Releases: jwmcglynn/donner
Donner SVG v0.5.0
Major release adding a software rendering backend, complete text rendering, all 17 SVG filter primitives, and a CLI tool — while maintaining the existing Skia backend.
Highlights
<text>support — Full<text>,<tspan>, and<textPath>support with per-character
positioning, text-anchor, text-decoration, and all baseline properties. Fonts are loaded from
@font-facerules (TTF, OTF, WOFF, WOFF2). An optional HarfBuzz tier (--config=text-full)
adds complex script shaping.<filter>support — all 17 SVG filter primitives — feGaussianBlur, feColorMatrix,
feComposite, feBlend, feTurbulence, feConvolveMatrix, feDiffuseLighting, feSpecularLighting,
feDisplacementMap, feComponentTransfer, feMorphology, feFlood, feOffset, feMerge, feTile,
feImage, feDropShadow. Float-precision pipeline with SIMD (NEON) optimizations. CSS shorthand
filter functions (blur(),brightness(),drop-shadow(), etc.) also supported.- tiny-skia software renderer — A new default rendering backend written in C++ that requires no
external GPU libraries. Achieves performance within 1.5x of Skia across all rendering operations.
The Skia backend remains available as a build option. A vectorized WASM SIMD128 backend ships
alongside the existing ARM NEON / x86 AVX2 / scalar paths and is selected automatically when
Donner is compiled with Emscripten's-msimd128. donner-svgCLI tool — Render SVGs to PNG, preview in the terminal, or interactively
inspect elements with mouse selection.- WebAssembly build — Donner's renderer and parser now build through the Emscripten toolchain
viabazel build --config=wasm //..., with anexamples/svg_viewerdemo that parses and
renders SVGs entirely in the browser using ImGui + emscripten-glfw. - Donner Editor — A new in-tree SVG editor lives under
donner/editor/, shipping both as a
native desktop application and as a WebAssembly edition that runs entirely in the browser. .svgzsupport —SVGParserauto-detects the gzip magic bytes and decompresses.svgz
input transparently, so gzipped SVG files load without any extra ceremony at the call site.
What's Changed
- Renderer architecture — Abstract
RendererInterfacewithRendererDrivertraversal,
enabling backend-agnostic rendering. Both Skia and tiny-skia implement the same interface. - Incremental invalidation — Dirty flags on DOM mutations with O(1) fast path for unchanged
documents.StyleSystemperforms selective per-entity recomputation. - External SVG references —
<image>and<use>elements can reference external.svgfiles
with sandboxed resource loading. <clipPath><use>support —<use>children inside<clipPath>now resolve correctly.transform-originpresentation attribute — Accepted as both a presentation attribute
and a CSS property, with the single-keyword grammar (top/bottom/left/right/center)
parsed per the spec.- XML entity support — Custom
<!ENTITY>declarations in doctypes are now parsed by default. - XML parser conformance —
Nametoken validation per XML 1.0 spec. - CSS Color 4 — Full CSS Color 4 parsing plus
color-profilealiases and modern color
function grammar. Hex colors,rgb()/rgba(),hsl()/hsla(),hwb(),lab(),lch(),
oklab(),oklch(), andcolor()all round-trip through the parser. - Unified parser diagnostics —
ParseDiagnosticreplacesParseError, carries a
DiagnosticSeverityand half-openSourceRange, and routes non-fatal warnings through
a lazy-evaluatedParseWarningSink. Clang/rustc-style source-context rendering via
DiagnosticRenderer. - CMake support — Full CMake build for both Skia and tiny-skia backends with feature toggles
for text, WOFF2, and filters. - Fuzzing — Continuous fuzzing harness with Docker support; all parser surfaces fuzz-tested.
- 81.7% line coverage across production code (84.0% function coverage, 73.4% branch
coverage).
Fixes and Internals
CompileTimeMap32-bit correctness fix — The compile-time perfect-hash map used for CSS
named colors, presentation attributes, and shape property tables was silently broken on
32-bit targets: the splitmix64 finalizer performed a>> 33shift onstd::size_t, which is
undefined behavior whensize_tis 32 bits. The hash has been reworked to use explicit
uint64_tarithmetic. Native builds (wheresize_tis already 64-bit) are unaffected, but
WebAssembly builds now produce correct lookups for every property map.- Modular EnTT headers — Switched from the monolithic
entt.hppamalgamation to the
modular EnTT headers, improving clean-build compile time and making incremental rebuilds
after ECS-adjacent edits measurably cheaper. - resvg test suite upgraded — Upgraded the vendored
resvg-test-suitesnapshot and
reworked the skip mechanism to carry a reason string per skipped test, which made it
straightforward to enable another wave of previously-skipped cases. - Filter-function CSS shorthand — 30 additional
filter: blur()/brightness()/
drop-shadow()/ ... resvg tests now pass.
Breaking API Changes
v0.5 includes a substantial API refactor to prepare for future GPU rendering and to unify parser
error reporting. Callers upgrading from v0.1 will need to update the following:
Transform→Transform2,Box→Box2— 2D math types are renamed to make room for
future 3D variants. No compatibility aliases are provided; callers must update to the new
names (and theTransform2f/Transform2d/Box2dshorthand typedefs).PathSplinereplaced by immutablePath+PathBuilder— The mutablePathSplineclass
is removed. Paths are now constructed viaPathBuilderand consumed as immutablePath
values.Pathexposes geometric queries (bounds,transformedBounds,pathLength,
pointAt,tangentAt,normalAt,strokeMiterBounds,isInside,isOnPath,vertices)
and conversions (cubicToQuadratic,toMonotonic,flatten,strokeToFill).PathBuilder
supports nativeQuadToand full SVG Appendix F.6 arc decomposition.BezierUtils— New public utility withEvalQuadratic/Cubic,SplitQuadratic/Cubic,
ApproximateCubicWithQuadratics,QuadraticYExtrema/CubicYExtrema, and
QuadraticBounds/CubicBounds.FillRulemoved fromdonner::svgtodonner— Now lives in the base namespace since
it is shared across the path and rendering layers.PathParseremits nativeQuadTo— Previously quadratic segments were degree-elevated to
cubics. Consumers that assumed only cubic segments will need to handleQuadToas well.- Unified parser diagnostics (
ParseError→ParseDiagnostic) — All parser APIs now return
ParseDiagnosticinstead ofParseError. Diagnostics carry aDiagnosticSeverity
(Error/Warning), a reason string, and a half-openSourceRange(replacing the previous
singleFileOffset). UseParseDiagnostic::Error()/ParseDiagnostic::Warning()factories
to construct them. ParseWarningSink— Parser entry points now accept aParseWarningSink&for collecting
non-fatal warnings, replacingstd::vector<ParseError>*out-parameters. The sink uses lazy
factory-callable evaluation, so warning construction is zero-cost when no sink is attached.
A newDiagnosticRendererproduces clang/rustc-style output with source context and
caret/tilde indicators.
Full Changelog: v0.1.2...v0.5.0
What's Included
donner-svg, a CLI tool for rendering and previewing SVG files.- An embeddable C++ API for parsing, inspecting, modifying, and rendering SVGs.
ParseResult<SVGDocument> maybeDocument = SVGParser::ParseSVG(fileData);
if (maybeDocument.hasError()) {
std::cerr << "Parse Error: " << maybeDocument.error() << "\n";
std::abort();
}
Renderer renderer;
renderer.draw(maybeDocument.result());
const bool success = renderer.save("output.png");To use the CLI tool:
# Render to PNG
donner-svg input.svg --output output.png
# Show a terminal preview
donner-svg input.svg --preview
# Interactive terminal mode with mouse selection
donner-svg input.svg --interactiveOr when building from source:
bazel run //donner/svg/tool -- input.svg --output output.pngDonner SVG v0.1.2
This release provides an embeddable SVG2 library, which includes CSS3 with a Skia-based renderer.
Large portions of the SVG2 static spec are implemented, including all shapes, markers, gradients, <use>, etc. Text is not yet implemented but is planned for v0.2.0.
What's Changed
- Add support for the
<symbol>element. - Experimentally support XML
<!ENTITY ...>references in the doctype (behind the off-by-defaultenableExperimentalOption). - Various dependency updates.
Full Changelog: v0.1.1...v0.1.2
What's Included
svg_to_png, which is a standalone tool to render an SVG using Donner.- An embeddable C++ API that allows rendering and manulating SVGs.
ParseResult<SVGDocument> maybeDocument = SVGParser::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");To use svg_to_png:
./svg_to_png donner_splash.svgOr when building from source:
bazel run --run_under="cd $PWD &&" //examples:svg_to_png -- donner_splash.svgDonner SVG v0.1.1
This release provides an embeddable SVG2 library, which includes CSS3 with a Skia-based renderer.
Large portions of the SVG2 static spec are implemented, including all shapes, markers, gradients, <use>, etc. Text is not yet implemented but is planned for v0.2.0.
What's Changed
- Improve error handling in
svg_to_pngapp. - Fixed
SVGElement::tryCastandSVGElement::isawith intermediate classes likeSVGGraphicsElement - Always build Skia optimized, even in debug builds.
- Fixed source offsets for namespace mismatch errors in XML.
- Remove dependency on absl, replace
absl::from_charswith a hand-rolled float parser. - Various dependency updates.
Full Changelog: v0.1.0...v0.1.1
What's Included
svg_to_png, which is a standalone tool to render an SVG using Donner.- An embeddable C++ API that allows rendering and manulating SVGs.
ParseResult<SVGDocument> maybeDocument = SVGParser::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");To use svg_to_png:
./svg_to_png donner_splash.svgOr when building from source:
bazel run --run_under="cd $PWD &&" //examples:svg_to_png -- donner_splash.svgDonner SVG v0.1.0
Donner SVG's first release!
This release provides an embeddable SVG2 library, which includes CSS3 with a Skia-based renderer.
Large portions of the SVG2 static spec are implemented, including all shapes, markers, gradients, <use>, etc. Text is not yet implemented but is planned for v0.2.0.
Included in the release are:
svg_to_png, which is a standalone tool to render an SVG using Donner.- An embeddable C++ API that allows rendering and manulating SVGs.
ParseResult<SVGDocument> maybeDocument = SVGParser::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");To use svg_to_png:
./svg_to_png donner_splash.svgOr when building from source:
bazel run --run_under="cd $PWD &&" //examples:svg_to_png -- donner_splash.svg