|
|
Donner
C++20 SVG rendering library
|
At its core, Donner is an SVG "engine". Instead of treating SVGs as static images, they are dynamic scenes which can be modified, animated, or transformed.
Many SVG libraries load an SVG, and render and image as an output, but browsers are different: SVG in browsers is a graphical version of HTML, and HTML isn't static: It can be queried, modified, and styled.
Donner intends to provide browser-level functionality as a standalone C++ library:
Donner currently renders with Skia, which is the core rendering library used by Chrome and Firefox. Skia is a high-performance, hardware-accelerated 2D graphics library that provides a common API for drawing text, shapes, and images.
Donner consists of a core library and a renderer, which are built with separation of concerns to enable future integration with other rendering libraries.
Each component of Donner is designed to be used in isolation, with minimal dependencies on other components. This allows for easy testing and integration with other systems.
The parser suite consists of parsers in three layers:
| Namespace | Description |
|---|---|
| donner::parser | Parsers for shared data types such as NumberParser and LengthParser |
| donner::css::parser | Parsers for various CSS data types, such as the top-level StylesheetParser and SelectorParser, as well as internal details such as ColorParser. These are wrapped in the donner::css::CSS convenience API. Using these lower-level APIs allows for finer-grained control and error propagation. |
| donner::svg::parser | Parsers for the SVG XML format, SVGParser, as well as individual parsers for SVG components, such as PathParser and TransformParser. |
| donner::xml | XMLParser and an XML document tree represented by XMLDocument and XMLNode. |
Provides a fully-featured CSS3 toolkit, which can be used to parse CSS stylesheets, style strings, or selectors, and match those selectors against a document tree.
See Using the CSS API for more details.
The CSS layer parses stylesheets into lists of SelectorRule objects, which contains:
At this layer, the style information has no semantics, it contains raw parsed data and the ability to cascade it to the document tree. This raw data is consumed by the Styling component to parse these values into meaningful styling information.
Consumes information from the CSS parser and implements the SVG style model. This includes:
StyleSystem is the top-level component that manages the styling of the document tree.
Style information is held on each entity inside donner::svg::components::StyleComponent. During the rendering process, CSS cascading and inheritance is performed and cached on donner::svg::components::ComputedStyleComponent.
Donner provides a high-level API for interacting with the SVG document model. This API is designed to be easy to use and understand, while still providing access to the full power of the underlying document model.
The API takes a principled approach, focusing on:
See Donner API for more details.
The Document Model is built on top of the EnTT Entity-Component-System (ECS), which is used to build a tree of entities, components, and systems that represent the SVG document. It is designed to be efficient and flexible, allowing for easy modification and rendering of SVG documents.
The rendering backend traverses the internal ECS document model and instantiates rendering components such as RenderingInstanceComponent, which are then rendered by the Skia renderer.
Rendering components are attached to the same entities as the document model components, allowing for easy synchronization between the document model and the rendering backend. When the document model is modified, the associated rendering components are invalidated.
The //donner/base library contains common utility code used by the other libraries. This includes:
This library also contains common parsers such as NumberParser, which can parse a string into a number.
The base library has minimal dependencies and the types within it may be suitable for other libraries, however the base library is not publicly exported.
Donner has a multi-level testing strategy and aims to make the library production-grade and suitable for parsing untrusted inputs (eventually).
All components should be unit-tested, and test coverage is measured using Codecov.
As SVG is a visual format, image comparison tests are used to validate the rendered output.
These come in three flavors:
Low-level "unittest" image comparison using ASCII art.
High-level "integration" image comparison using the pixelmatch-cpp17 library.
bazel run //donner/svg/renderer/tests:renderer_tests
Using the external Resvg Test Suite to validate against a large corpus of SVG files and comparing against the reference output with pixelmatch.
bazel run //donner/svg/renderer/tests:resvg_test_suite
Since SVG and CSS require a large collection of parsers, fuzz tests are individually written for each parser.