Donner 0.5.0
Embeddable browser-grade SVG2 engine
Loading...
Searching...
No Matches
svg_filter_interaction.cc

SVG Filter DOM Manipulation.

SVG Filter DOM Manipulation Demonstrates how to inspect and modify SVG filters through the Donner DOM. Parses an SVG containing an <feGaussianBlur> filter, finds the blur primitive, changes its stdDeviation, swaps the filter on a shape, then renders to PNG.

bazel run //examples:svg_filter_interaction -- output.png
/**
* @example svg_filter_interaction.cc SVG Filter DOM Manipulation
*
* Demonstrates how to inspect and modify SVG filters through the Donner DOM. Parses an SVG
* containing an `<feGaussianBlur>` filter, finds the blur primitive, changes its
* `stdDeviation`, swaps the filter on a shape, then renders to PNG.
*
* ```sh
* bazel run //examples:svg_filter_interaction -- output.png
* ```
*/
#include <iostream>
#include "donner/svg/SVG.h"
int main(int argc, char* argv[]) {
//! [filter_svg_source]
// A minimal document with a drop-shadow-style Gaussian blur applied to a rectangle.
const std::string_view kSvgSource(R"svg(
<svg xmlns="http://www.w3.org/2000/svg" width="320" height="160" viewBox="0 0 320 160">
<defs>
<filter id="Blur" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceGraphic" stdDeviation="2" />
</filter>
<filter id="Heavy" x="-20%" y="-20%" width="140%" height="140%">
<feGaussianBlur in="SourceGraphic" stdDeviation="8" />
</filter>
</defs>
<rect x="40" y="30" width="100" height="100" rx="12"
fill="#5aa9ff" stroke="#1f5a8a" stroke-width="3"
filter="url(#Blur)" />
<rect x="180" y="30" width="100" height="100" rx="12"
fill="#e0a63a" stroke="#7a5a1a" stroke-width="3"
filter="url(#Blur)" />
</svg>
)svg");
//! [filter_svg_source]
auto maybeDocument =
if (maybeDocument.hasError()) {
std::cerr << "Parse error: " << maybeDocument.error() << "\n";
return 1;
}
SVGDocument document = std::move(maybeDocument.result());
//! [filter_query_primitive]
// Find the first <feGaussianBlur> in the document. Filter primitives are ordinary SVG
// elements in the DOM and can be queried via CSS selectors just like shapes.
std::optional<SVGElement> maybeBlur = document.querySelector("feGaussianBlur");
UTILS_RELEASE_ASSERT_MSG(maybeBlur, "Expected an <feGaussianBlur> in the document");
std::cout << "Initial stdDeviation: (" << blur.stdDeviationX() << ", " << blur.stdDeviationY()
<< ")\n";
//! [filter_query_primitive]
//! [filter_mutate_primitive]
// Crank the blur up. The renderer picks up the new values on the next draw — filters are
// part of the live document, not baked at parse time.
blur.setStdDeviation(6.0, 6.0);
std::cout << "After mutation, stdDeviation: (" << blur.stdDeviationX() << ", "
<< blur.stdDeviationY() << ")\n";
//! [filter_mutate_primitive]
//! [filter_swap]
// Swap the filter reference on the second rect. CSS presentation attributes (including
// `filter`) can be set via setStyle(), which accepts any normal CSS declaration.
std::optional<SVGElement> maybeSecondRect =
document.querySelector("rect:nth-of-type(2)");
UTILS_RELEASE_ASSERT_MSG(maybeSecondRect, "Expected a second <rect>");
maybeSecondRect->setStyle("filter: url(#Heavy)");
//! [filter_swap]
//! [filter_render]
const std::string output = argc >= 2 ? argv[1] : "filter_interaction.png";
renderer.draw(document);
if (!renderer.save(output.c_str())) {
std::cerr << "Failed to save " << output << "\n";
return 1;
}
std::cout << "Rendered to " << output << " (" << renderer.width() << "x" << renderer.height()
<< ")\n";
//! [filter_render]
return 0;
}
#define UTILS_RELEASE_ASSERT_MSG(x, msg)
An assert that evaluates on both release and debug builds and errors with the provided msg.
Definition Utils.h:102
Represents a parsed SVG document containing a tree of SVGElement nodes.
Definition SVGDocument.h:39
std::optional< SVGElement > querySelector(std::string_view selector)
Find the first element in the tree that matches the given CSS selector.
Definition SVGDocument.cc:75
DOM object for a "<feGaussianBlur>" element.
Definition SVGFEGaussianBlurElement.h:69
void setStdDeviation(double valueX, double valueY)
Set the standard deviation, which is used to control the blur level.
Definition SVGFEGaussianBlurElement.cc:22
double stdDeviationX() const
Get the X-axis of the standard deviation, which is used to control the blur level.
Definition SVGFEGaussianBlurElement.cc:14
double stdDeviationY() const
Get the Y-axis of the standard deviation, which is used to control the blur level.
Definition SVGFEGaussianBlurElement.cc:18
Collects parse warnings during parsing.
Definition ParseWarningSink.h:28
Backend-agnostic renderer that resolves to the active build backend (Skia or tiny-skia).
Definition Renderer.h:27
int height() const override
Returns the rendered height in pixels.
Definition Renderer.cc:131
bool save(const char *filename)
Saves the last rendered frame to a PNG file.
Definition Renderer.cc:116
void draw(SVGDocument &document) override
Draws the SVG document using the active backend.
Definition Renderer.cc:18
int width() const override
Returns the rendered width in pixels.
Definition Renderer.cc:127
Represents a parsed SVG document containing a tree of SVGElement nodes.
Definition SVGDocument.h:39
Represents a single SVG element (e.g., <rect>, <circle>, <g>, <text>, etc.) within an SVGDocument.
Definition SVGElement.h:52
Derived cast()
Cast this element to its derived type.
Definition SVGElement.h:330
DOM object for a "<feGaussianBlur>" element.
Definition SVGFEGaussianBlurElement.h:69
static ParseResult< SVGDocument > ParseSVG(std::string_view source, ParseWarningSink &warningSink, Options options={}, SVGDocument::Settings settings={}) noexcept
Parses an SVG XML document from a string (typically the contents of a .svg file).
Definition SVGParser.cc:377