Donner SVG Editor & Engine
SVG-native editor and embeddable SVG2 + CSS3 engine in C++20, with GPU (WebGPU) and compact CPU renderers, built for correctness, security, and performance.
Loading...
Searching...
No Matches
Introduction

Donner SVG Editor & Engine is an SVG-native editor and the C++20 engine underneath it, designed to be embedded. The engine renders SVG2 with CSS3 styling through either Geode (a GPU renderer built on WebGPU) or a compact CPU backend, tracks conformance against the resvg test suite, and treats all input as untrusted: fuzzing runs continuously across the parser, style, and text subsystems.

These pages document the engine API. Start with the core document model below; the editor is documented separately in the repository.

Donner splash image

Donner supports:

  • SVG2 core functionality, such as shapes, fills, strokes, and gradients.
  • Text rendering with <text>, <tspan>, and <textPath>, including WOFF2 web fonts and optional HarfBuzz shaping.
  • All 17 SVG filter primitives (feGaussianBlur, feColorMatrix, feComposite, etc.).
  • CSS3 parsing and cascading support, with a hand-rolled library.
  • Detailed validation and diagnostics, errors point to the exact location.
  • A performance-oriented document tree optimized for dynamic inspection, mutation, and rendering.
  • 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.
  • Two renderer backends: tiny_skia (a compact CPU software renderer) and Geode (a GPU renderer built on WebGPU).

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 //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
ParseResult<donner::svg::SVGDocument> maybeResult =
//! [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::Path> 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