SVGC (SVG C Library) – библиотека языка C для программного построения векторных изображений в формате Scalable Vector Graphics (SVG). Она предназначена прежде всего для научных иллюстраций, инженерных схем, математических рисунков, графиков численных экспериментов и любых задач, в которых изображение должно быть результатом воспроизводимого алгоритма, а не только ручной работы в графическом редакторе.

Обзор

Основная идея SVGC проста: программа на C вычисляет координаты, формы, геометрические построения и стили, а библиотека превращает соответствующие объекты в структурированный SVG-документ. Полученный файл можно открыть в браузере, исследовать как XML, образованный из обычных элементов SVG, изменить средствами SVG-редактора или использовать как основу для векторной иллюстрации в научной публикации.

SVGC не требует от пользователя писать SVG/XML-разметку вручную. Вместо этого программа создаёт лист, сцену и объекты изображения, настраивает их атрибуты и вызывает функцию вывода. При этом итоговый SVG остаётся обычным текстовым документом с геометрическими элементами и допускает проверку независимо от самой библиотеки.

Публичный выпуск SVGC 1.1.0 содержит C API, сборочную инфраструктуру GNU Autotools/Libtool, метаданные pkg-config, утилиту svgc-config, Autoconf-макрос AC_CHECK_SVGC, тесты и самостоятельные примеры. Для изучения научного рисунка опубликована отдельная книга на русском и английском языках с исходными текстами 21 программы.

Программный научный рисунок

Научный рисунок часто связан с исходными данными, системой уравнений или вычислительным алгоритмом. Например, оси графика определяются интервалами данных, фазовая траектория – результатом интегрирования системы ОДУ, а стрелки на структурной схеме – взаимным расположением блоков. Сохранение этих зависимостей в программе позволяет повторить построение при изменении данных или параметров модели.

В SVGC графическая часть намеренно отделена от вычислительной. Библиотека создаёт графические примитивы SVG и сериализует сцену, но не подменяет численный интегратор, алгоритм интерполяции, численный решатель или систему построения графов. Приложение самостоятельно решает математическую задачу и передаёт в SVGC уже вычисленную геометрию.

Такое разделение полезно в научной публикации и технической документации. Вместе с рисунком можно хранить исходный текст на C, параметры расчёта и исходные данные. Повторная сборка программы создаёт новый SVG, а текстовый формат позволяет проверить, какие именно координаты и стили были выведены.

Лист, сцена и узлы

В основе интерфейса находятся три понятия: sheet (лист SVG), scene (упорядоченная сцена) и node (узел изображения). Лист задаёт размеры документа и его поля. Сцена содержит список графических узлов, а каждый узел хранит тип, геометрию и связанные с ним стилевые параметры. Отдельные definitions относятся к листу и выводятся в <defs>.

Обычная последовательность работы начинается с __svg_new_sheet() и __svg_new_scene(). Примитивы создаются функциями семейства __svg_new_* и добавляются через __svg_scene_add_node(). После вызова __svg_paint_scene() ресурсы сцены освобождаются функцией __svg_free_scene(). Лист находится в списке сцены, поэтому при успешном её создании отдельно освобождать лист не требуется.

Порядок добавления объектов имеет смысл. SVG обычно рисует элементы последовательно: позднее помещённый на сцену объект может перекрывать ранее нарисованный. Поэтому фон, сетку, данные, стрелки и подписи удобно добавлять слоями в требуемом порядке. Второй аргумент __svg_paint_scene() позволяет выбирать вывод объектов с группировкой или без неё.

Объект Роль C API
__svg_sheet Размеры документа, поля, определения __svg_new_sheet()
__svg_scene Упорядоченные графические узлы __svg_new_scene()
__svg_node Общий интерфейс для графических элементов __svg_scene_add_node()
SVG output Запись готового документа __svg_paint_scene()

Геометрические примитивы

Библиотека предоставляет привычные элементы геометрического рисунка: линии, прямоугольники, окружности, эллипсы, ломаные, многоугольники, составные пути, текст и изображения. Объекты создаются с координатами типа double, что позволяет передавать в графическую подсистему результаты вычислений без принудительного предварительного округления до целых пикселей.

Для полилиний и многоугольников предусмотрена структура точек __svg_points. Набор создаётся вызовом __svg_new_points(), после чего вершины добавляются функцией __svg_add_point(). Ломаная оставляет последовательность открытой, тогда как многоугольник предназначен для замкнутого контура и допускает заливку области.

Геометрия Функция
Отрезок __svg_new_line()
Прямоугольник со скруглением __svg_new_rect()
Окружность __svg_new_circle()
Эллипс __svg_new_ellipse()
Ломаная __svg_new_polyline()
Многоугольник __svg_new_polygon()
Составной путь __svg_new_path()
Надпись __svg_new_text()
Изображение по ссылке __svg_new_image()

Научные иллюстрации часто строятся из небольшого набора таких primitives. Например, вектор силы состоит из отрезка и наконечника, структурная схема – из прямоугольников, линий, окружностей и подписей, а график функции – из ломаной, осей, делений и текстовых меток. Сложность находится в алгоритме размещения объектов, а не в количестве специальных примитивов.

Пути, кривые и дуги

Составной путь SVG используется там, где простого отрезка или ломаной недостаточно. Программа формирует список команд __svg_cmds, а затем создаёт на его основе __svg_new_path(). В SVGC доступны перемещения и линии, горизонтальные и вертикальные отрезки, квадратичные и кубические кривые Безье, эллиптические дуги и замыкание контура.

Каждая path-команда может задаваться в абсолютных либо относительных координатах через константы ABSOLUTE и RELATIVE. Для кривой Безье программа передаёт управляющие точки, а для эллиптической дуги – радиусы, угол поворота осей и два управляющих флага выбора дуги. Это позволяет сохранять кривую как векторный объект, не аппроксимируя её заранее множеством отрезков.

struct __svg_cmds *cmds = __svg_new_cmds();

__svg_add_moveto_cmd( cmds, ABSOLUTE, 40.0, 100.0 );
__svg_add_curveto_cmd( cmds, ABSOLUTE,
                       80.0, 20.0, 140.0, 180.0,
                       180.0, 100.0 );

struct __svg_node *curve = __svg_new_path( cmds );
  

В книге подробно рассматриваются команды M/L/H/V/Z, Q/T, C/S и A, включая геометрию управляющих точек, форму дуг и построение замкнутых фигур. Пример выше показывает только создание команд; для окончательного SVG созданный узел нужно включить в сцену.

Контуры, заливки и оформление

Геометрия не определяет весь внешний вид элемента. SVG различает контур (stroke) и заливку (fill), позволяет задавать ширину линии, формы её концов, способ соединения сегментов и штриховой рисунок. Эти свойства необходимы, например, для различения экспериментальных кривых, линий вспомогательной сетки и основных осей на одном рисунке.

SVGC поддерживает как непосредственное изменение свойств узла через __svg_set_stroke(), __svg_set_stroke_width() и __svg_set_fill(), так и установку текущих значений для новых элементов сцены через __svg_set_scene_stroke() и другие функции семейства __svg_set_scene_*. Следует различать свойства уже созданного объекта и defaults для последующих объектов.

Для stroke и fill предусмотрены как строковые значения (например, black, none или ссылка url(#id)), так и функции установки цвета через RGB-компоненты. Тип линии может задаваться через stroke-dasharray; окончания и соединения используют стандартные значения SVG, включая butt, round, square, miter и bevel.

Градиенты и определения SVG

Линейные и радиальные градиенты описываются специальными nodes, создаваемыми функциями __svg_new_l_gradient() и __svg_new_r_gradient(). Для них задаются положения и параметры stop через __svg_new_stop() и __svg_gradient_add_stop(). Градиент регистрируется в списке определений листа и затем используется в заливке графических элементов.

Для градиента важны система координат (objectBoundingBox либо userSpaceOnUse), распределение за пределами интервала (pad, reflect, repeat) и порядок цветовых остановок. В печатных научных схемах градиент может обозначать объём или выделять объект, однако его следует применять осмысленно, не подменяя цветом количественные данные.

Текст, шрифты и подписи

Научная иллюстрация почти всегда содержит подписи переменных, числовые деления, обозначения углов, индексы и пояснения. SVGC создаёт текстовый элемент функцией __svg_new_text(), принимающей положение, строку, family и размер шрифта. Отдельные функции позволяют изменить текст, цвет, family и размер. Положение текста следует рассчитывать с учётом baseline и выбранного шрифта.

Одинаковое числовое положение элемента не гарантирует одинаковой видимой типографики на разных системах. Важны доступность шрифтов, метрики глифов, поведение программе просмотра SVG и способ последующей конвертации в PDF. Поэтому для ответственных рисунков полезно проверять результат не только в браузере, но и в той цепочке печати, которая будет применяться при подготовке публикации.

Книга разбирает работу с baseline, XML-экранированием, font-family, математическими индексами и отдельными SVG-возможностями, например tspan. Не следует при этом предполагать, что каждый механизм SVG имеет отдельную функцию SVGC: библиотека предоставляет свой конкретный C API, а книга также объясняет окружающий стандарт SVG и практические приёмы построения рисунков.

Встраивание CSS и JavaScript

В SVGC имеются специальные функции __svg_sheet_add_css_file() и __svg_sheet_add_script_file(). Первая читает внешний файл CSS в кодировке UTF‑8 и помещает его содержимое в SVG <defs>. Вторая аналогично добавляет исходный текст JavaScript/ECMAScript. Эти функции предназначены для файлов, содержащих только текст соответствующего языка, без обёрток XML или заранее подготовленных CDATA-секций.

Библиотека проверяет encoding, сохраняет содержимое и безопасно оформляет CDATA в результирующем XML, в том числе при наличии последовательностей, требующих разделения CDATA-блока. CSS-правила могут содержать url(...), однако соответствующие внешние ресурсы (например, файлы шрифтов) не становятся автоматически частью SVG. Относительные ссылки разрешаются viewer относительно созданного SVG, а не расположения исходного файл CSS.

Исполнение встроенного скрипта зависит от режима просмотра. Например, интерактивный SVG, открытый как отдельный документ в браузере, и тот же SVG, подключённый как <img>, могут иметь принципиально разное поведение: в последнем случае scripts не исполняются. Для научной публикации интерактивность не должна быть единственным способом прочитать рисунок.

/* The input files contain CSS or ECMAScript source only. */
__svg_sheet_add_css_file( sheet, "fonts.css" );
__svg_sheet_add_script_file( sheet, "change-color.js" );
  

Координаты и масштабы

В обычной экранной системе SVG начало координат находится в верхнем левом углу: ось X направлена вправо, ось Y – вниз. Математические графики часто используют другую систему: X растёт вправо, а Y – вверх. Поэтому прикладной код должен явно преобразовывать математические данные в координаты листа, а не трактовать произвольные входные значения как готовые пиксельные позиции.

Пусть математические данные лежат в прямоугольнике [xmin,xmax] × [ymin,ymax], а область рисунка ограничена координатами left, top и размерами width, height. Простое аффинное преобразование имеет вид:

X = left + (x - xmin) * width  / (xmax - xmin);
Y = top  + (ymax - y) * height / (ymax - ymin);
  

Здесь инверсия в формуле Y обусловлена направлением экранной вертикальной оси. Значения xmax - xmin и ymax - ymin должны быть ненулевыми; поля листа и соотношение масштабов выбираются в зависимости от задачи. Для окружностей и геометрических конструкций может потребоваться единый масштаб по обеим осям, а для графиков данных часто допустимы разные.

SVGC намеренно не навязывает единственного алгоритма построения сетки, выбора делений, форматирования числовых меток или определения диапазона данных. В учебных примерах эти задачи решаются отдельными C-функциями. Читатель видит связь между исходными числами, экранным преобразованием и действительно записанной SVG-геометрией.

Первая программа на C

Следующий короткий пример показывает основные этапы работы с SVGC. Программа создаёт лист, сцену и два графических объекта, затем записывает SVG и освобождает память сцены. В полном учебном примере из книги те же действия дополнены фоном, рабочей областью, координатными осями и текстовыми подписями.

#include <stdio.h>
#include <svgc.h>

int main( void )
{
  struct __svg_sheet *sheet;
  struct __svg_scene *scene;
  struct __svg_node  *node;

  sheet = (struct __svg_sheet *)__svg_new_sheet( 640.0, 400.0,
                                                 20.0, 20.0,
                                                 20.0, 20.0 );
  if( !sheet ) return( 1 );

  scene = __svg_new_scene( sheet );
  if( !scene )
  {
    __svg_free_node( (struct __svg_node *)sheet );
    return( 1 );
  }

  node = __svg_new_line( 80.0, 100.0, 560.0, 100.0 );
  if( !node ) goto failed;
  (void)__svg_set_stroke( node, "black" );
  (void)__svg_set_stroke_width( node, 2.0 );
  if( __svg_scene_add_node( scene, node ) != 1 )
  {
    __svg_free_node( node );
    goto failed;
  }

  node = __svg_new_circle( 320.0, 220.0, 60.0 );
  if( !node ) goto failed;
  (void)__svg_set_stroke( node, "black" );
  (void)__svg_set_fill( node, "none" );
  if( __svg_scene_add_node( scene, node ) != 1 )
  {
    __svg_free_node( node );
    goto failed;
  }

  __svg_paint_scene( scene, 0, "drawing.svg" );
  __svg_free_scene( scene );
  return( 0 );

failed:
  fprintf( stderr, "Unable to build SVG scene\n" );
  __svg_free_scene( scene );
  return( 1 );
}
  

Обе фигуры остаются векторными объектами: при увеличении масштаба они не превращаются в растровые пиксели. Запись SVG происходит только после создания требуемой геометрии. При возникновении ошибки до сериализации сцена освобождается; если добавление нового node не удалось, непереданный объект освобождается отдельно.

Для компиляции установленной библиотеки достаточно воспользоваться pkg-config. После запуска программы результат drawing.svg можно открыть в браузере или программе просмотра SVG. Пример намеренно не включает ручное написание XML-тегов.

cc -Wall -Wextra -o drawing main.c \
  $(pkg-config --cflags --libs svgc)
./drawing
  

Научные и инженерные задачи

Визуализация данных становится интересной, когда форма рисунка определяется вычислениями. Для экспериментальных измерений программа может наносить отдельные markers, модельную кривую и оценку среднеквадратичной ошибки. Для интерполяции – вычислять коэффициенты натурального кубического сплайна и строить гладкую линию между узлами. SVGC в этих случаях отвечает за представление результата, а не за вычисление коэффициентов.

Для динамических систем программа может интегрировать уравнения движения, строить временные ряды, фазовые траектории и геометрию механической схемы. В книге такие построения рассматриваются на примерах осциллятора, классического RK4 и динамических характеристик численных методов. Таким образом, иллюстрация воспроизводит не условную картинку, а конкретный вычислительный эксперимент.

Контурные линии функций двух переменных дают ещё один полезный пример разделения ответственности. Алгоритм Marching Squares находит пересечения уровней с ячейками расчетной сетки; затем интерполированные сегменты становятся линиями или составными путями SVG. Библиотеке не требуется знать внутреннее устройство Marching Squares: она получает готовые геометрические объекты.

21 программируемая иллюстрация

Книга «Создание научной графики на языке C» содержит 21 самостоятельную C-программу, каждая из которых воспроизводит свою иллюстрацию. Примеры располагаются в отдельных каталогах src/svgc-examples/NNN-name/, имеют исходный текст main.c, обычный Makefile и страницу view.html для просмотра результата.

Учебный материал развивается от первого SVG-листа и базовых примитивов к кривым Безье, градиентам, структурным схемам и численным графикам. Затем рассматриваются осциллятор, координатные сетки, дискретные наблюдения, сплайны, фазовые портреты, контурные линии и динамическая характеристика метода Гаусса–Лежандра. Численные методы и геометрические построения представлены исходными программами, а не только готовыми картинками.

Раздел книги Примеры построений
Основы SVG Лист, примитивы, преобразование координат
Геометрия и оформление Ломаные, стрелки, схемы, paths, Bézier, дуги, текст, градиенты
Инженерные схемы Структурная схема системы управления, RK4, осциллятор
Численная графика Сетки, наблюдения, сплайны, фазовые траектории, изолинии
Исследование численных методов Динамические характеристики метода Гаусса–Лежандра

Все 21 рисунок имеют единую воспроизводимую схему получения: исходная C-программа создаёт SVG; SVG проверяется как векторный геометрический результат, после чего CairoSVG создаёт PDF для печатного издания. PNG-копии используются только для удобного просмотра в Markdown. Векторные PDF в самой книге не заменяются растровыми изображениями.

От SVG к печатному PDF

SVG удобно хранить как первичный результат программы: элементы остаются геометрическими, а координаты и стили доступны в текстовом виде. Для включения в научную книгу документ можно перевести в векторный PDF и поместить в TeX с помощью graphicx и \includegraphics. Это позволяет отдельно контролировать геометрию рисунка и макет печатной страницы.

В исходниках книги процесс автоматизирован: make-figures.sh пересобирает C-примеры, создаёт SVG и соответствующие PDF, build.sh собирает книгу с помощью XeLaTeX, а make-markdown.sh формирует отдельное Markdown-издание. Векторное представление сохраняется на этапе печати, а проверка шрифтов и размещения надписей остаётся частью редакционной работы.

C program  ->  SVG  ->  CairoSVG  ->  vector PDF
                                            |
                                            v
                                    XeLaTeX / book
  

Сборка и установка

SVGC использует стандартную инфраструктуру GNU Autotools и Libtool. Для сборки из исходного дистрибутива обычно достаточно вызвать configure, make, make check и затем выполнить установку. Префикс, каталог библиотек и параметры компилятора задаются обычными параметрами configure.

tar -xJf svgc-1.1.0.tar.xz
mkdir svgc-build
cd svgc-build

../svgc-1.1.0/configure --prefix=/usr --libdir=/usr/lib64
make
make check
make install
  

При сборке пакета для дистрибутива вместо непосредственной установки в системный корень удобно использовать DESTDIR. Например, команда make DESTDIR=/tmp/package-svgc install устанавливает файлы в промежуточный каталог установки, сохраняя целевое значение --prefix. Это важно для Slackware и других систем, в которых пакет формируется отдельно от текущей файловой системы хоста.

Для разработки из Git-дерева предусмотрен bootstrap, создающий необходимые файлы, генерируемые средствами Autotools. В опубликованном исходном архиве такие файлы уже присутствуют, поэтому запускать bootstrap перед обычной сборкой исходного архива выпуска не требуется. Для проверки полноты дистрибутива upstream может использовать make distcheck.

Подключение к программам и Autotools

После установки основной публичный заголовочный файл доступен как <svgc.h>. Самый простой способ получить параметры компиляции и линковки – использовать pkg-config. Пакет устанавливает svgc.pc, поэтому внешний проект может получать флаги без предположений о конкретных системных каталогах include и lib.

pkg-config --modversion svgc
pkg-config --cflags svgc
pkg-config --libs svgc

svgc-config --version
svgc-config --cflags
svgc-config --libs
  

Для проектов, применяющих Autoconf, библиотека предоставляет макрос AC_CHECK_SVGC, позволяющий проверить наличие SVGC и минимально требуемую версию. Сам макрос поставляется в файле svgc.m4. Таким образом, SVGC можно включать в состав более крупного C-проекта штатными средствами инфраструктуры сборки GNU.

dnl Example from an external configure.ac:
AC_CHECK_SVGC([1.1.0])
  

SVGC предоставляет C interface и может использоваться из других языков через соответствующие bindings, но в составе самой библиотеки не заявлен готовый универсальный слой bindings. Публичные структуры и имена функций следует брать из установленного svgc.h; примеры книги соответствуют этому реальному интерфейсу, а не воображаемой объектной надстройке.

Примеры в исходном выпуске

Помимо учебных программ отдельной книги, исходный дистрибутив SVGC содержит три небольших демонстрационных каталога в examples/. Они показывают обычное создание рисунка, подключение CSS с описанием шрифтов и встраивание ECMAScript для интерактивного поведения. Эти примеры поддерживаются собственными Makefile.am в составе исходного дерева.

Каталог Назначение
examples/oscilator/ Механический осциллятор, геометрические построения
examples/css-file/ Встраивание CSS и работа с подключаемыми шрифтами
examples/script-file/ Встраивание JavaScript и интерактивное SVG

Внешние файлы шрифтов не поставляются внутри SVG автоматически: CSS может лишь ссылаться на них. А скриптовый пример необходимо проверять в таком viewer и таком режиме загрузки, которые разрешают исполнение встроенного JavaScript. Эти особенности связаны с браузерами и форматом SVG, а не с ошибкой компоновки C-программы.

Проверка и воспроизводимость

Выпуск содержит автоматические тесты для механизмов встраивания CSS и ECMAScript; они запускаются через обычную цель make check. Такие проверки дополняют, но не заменяют просмотр реальных научных иллюстраций. Геометрию, подписи, шрифты и воспроизводимость полного рисунка необходимо проверять на уровне программы, которая его строит.

В книге для каждого рисунка предусмотрен самостоятельный источник на C. Такая организация позволяет исправить вычислительный алгоритм, изменить оформление или перенести построение на новую систему без потери происхождения графического результата. SVG служит промежуточным контролируемым артефактом, а PDF и Markdown формируются отдельными этапами.

Границы ответственности библиотеки

SVGC – средство создания векторной геометрии, а не готовая система построения графиков, пакет численных вычислений или универсальный WYSIWYG-редактор. Библиотека не решает автоматически, где разместить подписи осей, каким должен быть шаг сетки, как выбрать интервал интегрирования и когда численный метод потерял устойчивость. Эти решения принадлежат приложению и подробно обсуждаются в книге на конкретных примерах.

Ещё одно важное различие – документ SVG и будущая печатная страница. Сам по себе корректный SVG не гарантирует идентичного воспроизведения шрифтов всеми viewers и converters. Для печати необходимо контролировать внешние ресурсы шрифтов и другие зависимости, а затем проверять результат в выбранной цепочке инструментов PDF/TeX.

Книги и учебные материалы

Вместе с SVGC опубликована книга «Создание научной графики на языке C» (Creating Scientific Graphics in C). Это не краткий справочник функций библиотеки, а систематическое учебное изложение программного научного рисунка: от первых геометрических объектов до инженерных схем и визуализации численных методов. Отдельная глава посвящена справочному обзору C API.

Оба языковых издания доступны в PDF и Markdown. PDF ориентирован на последовательное чтение и печать, Markdown – на просмотр исходного учебного текста, формул и рисунков в цифровой среде. Опубликованные примеры помогают читателю не только изучить готовую иллюстрацию, но и воспроизвести её, изменить параметры и использовать метод построения в собственном проекте.

Главы охватывают устройство SVG, primitives, координатные отображения, arrows, составные paths, кривые Безье, градиенты, типографику, структурные схемы, RK4, сплайны, фазовые портреты, isolines и печатную графику. Исходники примеров и обе редакции книги собраны в отдельном разделе FTP: SVGC documentation and examples.

Краткий справочник

Задача Интерфейс
Создать лист __svg_new_sheet()
Создать сцену __svg_new_scene()
Добавить объект __svg_scene_add_node()
Создать точки __svg_new_points(), __svg_add_point()
Создать путь __svg_new_cmds(), __svg_new_path()
Настроить контур и заливку __svg_set_stroke(), __svg_set_fill()
Определить градиент __svg_new_l_gradient(), __svg_gradient_add_stop()
Подключить CSS __svg_sheet_add_css_file()
Подключить ECMAScript __svg_sheet_add_script_file()
Записать SVG __svg_paint_scene()
Освободить сцену __svg_free_scene()
Получить флаги компилятора pkg-config --cflags --libs svgc

Полный перечень публичных структур, аргументов и функций содержится в svgc.h и подробно систематизирован в заключительной справочной главе книги. При программировании следует сверять сигнатуры непосредственно с установленной версией заголовочного файла.

Исходные тексты и выпуски

Публичный выпуск SVGC 1.1.0 доступен как исходный архив на FTP Radix Linux. Git-репозиторий содержит исходное дерево и историю проекта. Книга, обе языковые редакции и самостоятельные C-примеры для научных рисунков опубликованы в каталоге документации. Эти ресурсы можно использовать независимо: разработчик может установить одну только библиотеку, а читатель – изучать алгоритмы построения рисунков по книге.

SVGC развивается как самостоятельная библиотека, применимая в разных C-программах. Её назначение не ограничивается одной книгой или одним вычислительным проектом: любой автор, которому нужны проверяемые, программно определяемые векторные иллюстрации, может использовать тот же набор графических primitives.