Skip to content

jwmcglynn/donner

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Donner, a modern SVG rendering library in C++

Build Status License: ISC Code coverage % Product lines of code Test lines of code Comments %

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 renders with Skia, which provides the same high-quality rendering used by Chromium.

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

Open in GitHub Codespaces

How it works: svg_to_png.cc

API Demo

// This is the base SVG we are loading, a simple path containing a line
donner::svg::parser::XMLParser::InputBuffer 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>
)");

// Call ParseSVG to load the SVG file
donner::base::parser::ParseResult<donner::svg::SVGDocument> maybeResult =
    donner::svg::parser::XMLParser::ParseSVG(svgContents);

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
}

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.
donner::svg::SVGPathElement path = maybePath->cast<donner::svg::SVGPathElement>();

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

API Demo 2: Rendering a SVG to PNG

using namespace donner::base;
using namespace donner::base::parser;
using namespace donner::svg;
using namespace donner::svg::parser;

std::ifstream file("test.svg");
if (!file) {
  std::cerr << "Could not open file\n";
  std::abort();
}

XMLParser::InputBuffer fileData;
fileData.loadFromStream(file);

ParseResult<SVGDocument> maybeDocument = XMLParser::ParseSVG(fileData);
if (maybeDocument.hasError()) {
  std::cerr << "Parse Error: " << maybeDocument.error() << "\n";
  std::abort();
}

RendererSkia renderer;
renderer.draw(maybeDocument.result());

const bool success = renderer.save("output.png");

Detailed docs: svg_to_png.cc

API Demo 3: Interactive SVG Viewer using ImGui

bazel run --run_under="cd $PWD &&" //examples:svg_viewer -- <filename>

This example demonstrates how to create an interactive SVG viewer using ImGui. The viewer allows you to load and display SVG files, and interact with SVG elements using ImGui.

Detailed docs: svg_viewer.cc

Documentation

Status

Other Libraries

  • C++ | LunaSVG: A lightweight library with an embedded renderer, suitable for embedded applications
  • Rust | librsvg: Provides a simple way to render SVGs one-shot, does not provide a DOM or animation
  • Rust | resvg: Library that focuses on correctness, safety, and portability for static SVGs