Donner SVG main
0.8.0 ยท 382bd0190.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
Loading...
Searching...
No Matches
svg_text_interaction.cc

SVG Text DOM Manipulation.

SVG Text DOM Manipulation Demonstrates how to create, inspect, and modify <text> content through the Donner DOM. Builds a new SVG document from scratch containing a <text> element with multiple <tspan> runs, then queries, re-styles, and appends more content, and finally renders the result to a PNG.

bazel run //examples:svg_text_interaction -- output.png
/**
* @example svg_text_interaction.cc SVG Text DOM Manipulation
*
* Demonstrates how to create, inspect, and modify `<text>` content through the Donner DOM.
* Builds a new SVG document from scratch containing a `<text>` element with multiple
* `<tspan>` runs, then queries, re-styles, and appends more content, and finally renders the
* result to a PNG.
*
* ```sh
* bazel run //examples:svg_text_interaction -- output.png
* ```
*/
#include <iostream>
#ifdef DONNER_EXAMPLE_NATIVE_TEXT
#endif
#include "donner/svg/SVG.h"
int main(int argc, char* argv[]) {
#ifdef DONNER_EXAMPLE_NATIVE_TEXT
std::string resourceError;
if (!donner::PreparePackagedResources(&resourceError)) {
std::cerr << "Packaged resources unavailable: " << resourceError << "\n";
return 1;
}
#endif
// Parse an initial document with one <text> element and two <tspan> runs. In a real
// application you would typically load this from a file, but the embedded snippet here
// keeps the example self-contained.
//! [text_svg_source]
const std::string_view kSvgSource(R"(
<svg xmlns="http://www.w3.org/2000/svg" width="400" height="120" viewBox="0 0 400 120">
<text x="20" y="70" font-family="sans-serif" font-size="32" fill="#1f5a8a">
Hello, <tspan fill="#c33" font-weight="bold">Donner</tspan>!
</text>
</svg>
)");
//! [text_svg_source]
auto maybeDocument = donner::svg::parser::SVGParser::ParseSVG(kSvgSource, warnings);
if (maybeDocument.hasError()) {
std::cerr << "Parse error: " << maybeDocument.error() << "\n";
return 1;
}
SVGDocument document = std::move(maybeDocument.result());
//! [text_query]
// Find the <text> element via a CSS selector and read its current content.
std::optional<SVGElement> maybeText = document.querySelector("text");
UTILS_RELEASE_ASSERT_MSG(maybeText, "Expected a <text> element in the document");
SVGTextElement text = maybeText->cast<SVGTextElement>();
std::cout << "Current text content: \"" << text.textContent() << "\"\n";
//! [text_query]
//! [text_restyle]
// Restyle the <text> element. setStyle replaces only this element's style attribute, so its
// fill presentation attribute and the nested <tspan> runs keep their own values.
text.setStyle("font-size: 40px; font-weight: 500");
text.setX(Lengthd(20));
text.setY(Lengthd(80));
//! [text_restyle]
//! [text_append_tspan]
// Append a new <tspan> run to the end of the text. New elements are attached via the same
// DOM API used for shapes: create them, configure their properties, then insert them into
// the tree.
newRun.appendText(" v0.5");
newRun.setStyle("fill: #2a9; font-style: italic");
text.appendChild(newRun);
//! [text_append_tspan]
std::cout << "After append, text content: \"" << text.textContent() << "\"\n";
#ifdef DONNER_EXAMPLE_NATIVE_TEXT
const double textLength = text.getComputedTextLength();
if (!(textLength > 0)) {
std::cerr << "Text layout did not produce a positive advance\n";
return 1;
}
std::cout << "Computed text length: " << textLength << "\n";
#endif
//! [text_render]
// Render the modified document to PNG.
const std::string output = argc >= 2 ? argv[1] : "text_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";
//! [text_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:121
Represents a parsed SVG document containing a tree of SVGElement nodes.
Definition SVGDocument.h:106
std::optional< SVGElement > querySelector(std::string_view selector)
Find the first descendant of the root <svg> element, in document order, that matches the given CSS se...
DOM object for a <tspan> element.
Definition SVGTSpanElement.h:103
static SVGTSpanElement Create(SVGDocument &document)
Create a new <tspan> element within the specified document.
Definition SVGTSpanElement.h:132
DOM object for a <text> element.
Definition SVGTextElement.h:80
Collects parse warnings during parsing.
Definition ParseWarningSink.h:29
Backend-agnostic renderer that resolves to the active build backend (tiny-skia by default,...
Definition Renderer.h:82
int height() const override
Returns the rendered height in pixels.
bool save(const char *filename)
Saves the last rendered frame to a PNG file.
void draw(SVGDocument &document) override
Draws the SVG document using the active backend.
int width() const override
Returns the rendered width in pixels.
Represents a parsed SVG document containing a tree of SVGElement nodes.
Definition SVGDocument.h:106
Represents a single SVG element (e.g., <rect>, <circle>, <g>, <text>, etc.) within an SVGDocument.
Definition SVGElement.h:265
Derived cast()
Cast this element to its derived type.
Definition SVGElement.h:649
void setStyle(std::string_view style)
Set the element style, the value of the "style" attribute.
void appendChild(const SVGElement &child)
Append child as a child of the current node.
DOM object for a <tspan> element.
Definition SVGTSpanElement.h:103
double getComputedTextLength() const
Computes the total advance distance for all glyphs.
void appendText(std::string_view text)
Append text content from text or CDATA nodes.
RcString textContent() const
Get the raw text content concatenated from all direct child text nodes.
DOM object for a <text> element.
Definition SVGTextElement.h:80
void setY(std::optional< Lengthd > value)
Sets the y attribute list to a single value (absolute y-position).
void setX(std::optional< Lengthd > value)
Sets the x attribute list to a single value (absolute x-position).
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).
bool PreparePackagedResources(std::string *error)
Native preflight validates the entire linked set; only essential resources are retained.
Length< double > Lengthd
Shorthand for Length<double>.
Definition Length.h:279
int main()
Run the rendering example and report its result.
Definition render_test.cc:34