Чтение SVG в C++

в 15:27, , рубрики: c++, mpl, open source, svg, templates, векторная графика

При выборе формата хранения или обмена векторными 2D изображениями, SVG один из главных претендентов, благодаря открытости и распространенности. При всех его достоинствах, авторы, на мой взгляд, чрезмерно увлеклись удобством и гибкостью при создании документов, что привело к большой вариативности и избыточности, а, следовательно, и сложностью чтения. Кроме того, ради компактности были изобретены разные грамматики, встроенные внутрь XML, что тоже добавило головной боли программистам.

Сейчас есть несколько C/C++ библиотек, которые могут загрузить SVG и отрисовать его в растр, но это только малая часть возможных применений SVG в приложениях.

Я разработал C++ библиотеку, которая должна взять на себя реализацию большинства нюансов спецификации, предоставляя данные SVG в удобном виде. При этом ставилась задача не навязывать программисту каких-то упрощений исходной информации из SVG. Например, разработчику часто не интересно, в каких единицах измерения была задана длина, ему удобнее работать со значениями, приведенными к одной размерности. Но в некоторых случаях (например, создание SVG DOM) информацию о единицах надо передавать в программу. Или прямоугольники, окружности и т. д. — в ряде случаев их удобно представлять путями (path) для однообразия, но иногда мы хотим знать, какая это была фигура.

Итак, встречайте, SVG++ 1.0!

  • Бесплатна для коммерческого и некоммерческого использования, лицензия — Boost.
  • Header-only, кроссплатформенная, достаточно C++03.
  • Из сторонних библиотек требует только Boost. Ах да, еще XML парсер на ваш вкус. Из коробки есть адаптеры для RapidXML NS, libxml2 и MSXML, но поддержка других добавляется несложно.

Как принято, мотивирующий пример:

#include <rapidxml_ns/rapidxml_ns.hpp>
#include <svgpp/policy/xml/rapidxml_ns.hpp>
#include <svgpp/svgpp.hpp>

using namespace svgpp;

class Context
{
public:
  void on_enter_element(tag::element::any);
  void on_exit_element();
  void transform_matrix(const boost::array<double, 6> & matrix);
  void path_move_to(double x, double y, tag::coordinate::absolute);
  void path_line_to(double x, double y, tag::coordinate::absolute);
  void path_cubic_bezier_to(
    double x1, double y1,
    double x2, double y2,
    double x, double y,
    tag::coordinate::absolute);
  void path_quadratic_bezier_to(
    double x1, double y1,
    double x, double y,
    tag::coordinate::absolute);
  void path_elliptical_arc_to(
    double rx, double ry, double x_axis_rotation,
    bool large_arc_flag, bool sweep_flag,
    double x, double y,
    tag::coordinate::absolute);
  void path_close_subpath();
  void path_exit();
};

typedef 
  boost::mpl::set<
    tag::element::circle,
    tag::element::ellipse,
    tag::element::line,
    tag::element::path,
    tag::element::polygon,
    tag::element::polyline,
    tag::element::rect,
    tag::element::svg,
    tag::element::g
  >::type processed_elements_t;

typedef
  boost::mpl::insert<
    traits::shapes_attributes_by_element,
    tag::attribute::transform
  >::type processed_attributes_t;

void loadSvg(rapidxml_ns::xml_node<> const * xml_root_element)
{
  Context context;
  document_traversal<
    processed_elements<processed_elements_t>,
    processed_attributes<processed_attributes_t>
  >::load_document(xml_root_element, context);
}

Этот небольшой код позволяет объектам класса Context получать информацию о геометрии объектов SVG. Для этого «под капотом» SVG++ реализуется поддержка фич SVG path, basic shapes, units и transformations. И это лишь малая часть возможностей SVG++.
На самом деле, для полной поддержки геометрии (даже без стилей рисования, клипинга, масок и т. д.) требуется сделать еще несколько шагов (учитывать размер viewport'ов, разрешение устройства, ссылки и др.), но об этом в примерах, tutorial'е и справке.

Библиотека не рисует и не будет рисовать ничего сама, однако включает демонстрационное приложение svgpp/src/demo/render, реализующее растеризацию SVG (некоторое подмножество спецификации), используя для отрисовки AGG или GDI+.

Для полноценного использования библиотеки очень желательно знакомство со спецификацией SVG.

  • Главная страница библиотеки с документацией — svgpp.org (документация готовится к переводу на английский, поэтому временный mishmash русского and english языков)
  • Репозиторий на GitHub github.com/svgpp/svgpp
  • Форум на Google Groups

Автор: OlegMax

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js