Donner
C++20 SVG rendering library
Loading...
Searching...
No Matches
Introduction

Donner is an under-development modern C++20 SVG rendering library which provides full access to the SVG DOM, enabling browser-level functionality without the browser.

Donner splash image

Currently, Donner includes:

  • SVG2 core functionality, such as shapes, fills, strokes, and gradients.
  • CSS3 parsing and cascading support, with a hand-rolled library.
  • A game-engine-inspired EnTT ECS-backed document tree.
  • A SVG DOM-style API to traverse, inspect, and modify documents in memory.
  • A two-phase renderer, which builds and caches a rendering tree for efficient frame-based rendering.

Donner supports two rendering backends, selected at build time:

  • TinySkia (default): A lightweight software rasterizer for fast builds with no system dependencies.
  • Skia: Full-featured rendering via Google Skia, used as a reference renderer.

See the Building Donner instructions for backend selection.

Donner focuses on security and performance, which is validated with code coverage and fuzz testing.

Try it out: Render an SVG to PNG

bazel run --run_under="cd $PWD &&" //examples:svg_to_png -- donner_splash.svg

How it works: svg_to_png.cc

API Demo

//! [svg_string]
// This is the base SVG we are loading, a simple path containing a line
const std::string_view svgContents(R"(
<svg xmlns="http://www.w3.org/2000/svg" width="200" height="200" viewBox="0 0 10 10">
<path d="M 1 1 L 4 5" stroke="blue" />
</svg>
)");
//! [svg_string]
//! [svg_parse]
// Call ParseSVG to load the SVG file
//! [svg_parse]
//! [error_handling]
if (maybeResult.hasError()) {
std::cerr << "Parse Error " << maybeResult.error() << "\n"; // Includes line:column and reason
std::abort();
// - or - handle the error per your project's conventions
}
//! [error_handling]
//! [get_path]
donner::svg::SVGDocument document = std::move(maybeResult.result());
// querySelector supports standard CSS selectors, anything that's valid when defining a CSS rule
// works here too, for example querySelector("svg > path[fill='blue']") is also valid and will
// match the same element.
std::optional<donner::svg::SVGElement> maybePath = document.querySelector("path");
UTILS_RELEASE_ASSERT_MSG(maybePath, "Failed to find path element");
// The result of querySelector is a generic SVGElement, but we know it's a path, so we can cast
// it. If the cast fails, an assertion will be triggered.
//! [get_path]
if (std::optional<donner::svg::PathSpline> spline = path.computedSpline()) {
std::cout << "Path: " << *spline << "\n";
std::cout << "Length: " << spline->pathLength() << " userspace units\n";
} else {
std::cout << "Path is empty\n";
}

Detailed docs: svg_tree_interaction.cc

Documentation

Project Goals

  • Have minimal dependencies, so it can be integrated into existing applications, assuming a modern compiler.
  • Expose the SVG DOM, so that applications can manipulate SVGs dynamically.
  • Implement the SVG 2 Specification.

Status

Building

Donner is built using Bazel, and builds are tested on Linux and macOS.

See more details in the Building Donner instructions.

Previous Next
Getting Started