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

Adding to your bazel project

Add the following to your MODULE.bazel (bazel 7.0.0 required):

bazel_dep(name = "donner", version = "0.0.0")
git_override(
module_name = "donner",
remote = "https://github.com/jwmcglynn/donner",
commit = "<latest commit>",
)

Adding a dependency

Donner with the default renderer is available through the @donner dependency, add to your rule like so:

cc_binary(
name = "my_library",
# ...
deps = [
"@donner",
],
)

Loading an SVG

First include the core SVG module with:

Use XMLParser to load an SVG from a string, which may be loaded from a file. Note that the string needs to be mutable as it is modified by the parser.

// This is the base SVG we are loading, a simple path containing a line
<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
ParseResult<donner::svg::SVGDocument> maybeResult =

ParseResult contains either the document or an error, which can be checked with hasError() and error():

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
}

Then get the SVGDocument and start using it. For example, to get the SVGElement for the <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.has_value(), "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.

The document tree can be traversed via the Donner API, and the SVG can be modified in-memory:

path.setStyle("fill: red");
path.setStyle("stroke: white");
// Get the parsed, cascaded style for this element and output it to the console.
std::cout << "Computed style: " << path.getComputedStyle() << "\n";

Outputs

Computed style: PropertyRegistry {
fill: PaintServer(solid Color(rgba(0, 0, 255, 255))) (set) @ Specificity(0, 0, 0)
stroke-width: 3px (set) @ Specificity(0, 0, 0)
}

Rendering an SVG

To render the SVG using the Skia renderer, include the renderer header and invoke it like so

renderer.draw(document);
Rendering backend using Skia, https://github.com/google/skia.
Definition RendererSkia.h:26
void draw(SVGDocument &document)
Draw the SVG document using the renderer.
Definition RendererSkia.cc:992

Outputs can be saved to a PNG file

const bool success = renderer.save("output.png");
bool save(const char *filename)
Save the rendered image to a PNG file.
Definition RendererSkia.cc:1087

Or pixel data can be accessed directly

std::span<const uint8_t> data = renderer.pixelData();
std::cout << "Size: " << renderer.width() << "x" << renderer.height() << "\n";
int height() const
Get the height of the rendered image in pixels.
Definition RendererSkia.h:119
int width() const
Get the width of the rendered image in pixels.
Definition RendererSkia.h:116
std::span< const uint8_t > pixelData() const
Get the pixel data of the rendered image.
Definition RendererSkia.cc:1093
Previous Next
Home Donner API