Donner SVG Editor & Engine
SVG-native editor and embeddable SVG2 + CSS3 engine in C++20, with GPU (WebGPU) and compact CPU renderers, built for correctness, security, and performance.
Loading...
Searching...
No Matches
donner::svg::DonnerController Class Reference

Provides hit-testing and spatial queries for an SVG document. More...

#include "donner/svg/DonnerController.h"

Classes

struct  LinkHit
 Result of a successful hitTestLink query: the enclosing <a> element that was hit, its retained link target, and the concrete element under the point. More...

Public Member Functions

 DonnerController (SVGDocument document)
 Create a controller for the given document.
std::optional< SVGGraphicsElementfindIntersecting (const Vector2d &point)
 Finds the topmost geometry element whose rendered area contains the given point.
std::vector< SVGGraphicsElementfindAllIntersecting (const Vector2d &point)
 Return every painted element intersecting p point, front to back.
std::optional< LinkHithitTestLink (const Vector2d &point)
 Finds the hyperlink (<a>) at the given point, if any, resolving the enclosing-<a> semantics from the SVG linking model (https://www.w3.org/TR/SVG2/linking.html#Links).

Detailed Description

Provides hit-testing and spatial queries for an SVG document.

Use DonnerController when you need to determine which element is at a given point (e.g., for mouse interaction in a viewer). This supplements the DOM traversal API on SVGElement with geometry-aware queries.

DonnerController controller(document);
if (auto element = controller.findIntersecting(Vector2d(100, 50))) {
std::cout << "Hit: " << element->tagName() << "\n";
}
DonnerController(SVGDocument document)
Create a controller for the given document.
Vector2< double > Vector2d
Shorthand for Vector2<double>.
Definition Vector2.h:394

Class Documentation

◆ donner::svg::DonnerController::LinkHit

struct donner::svg::DonnerController::LinkHit

Result of a successful hitTestLink query: the enclosing <a> element that was hit, its retained link target, and the concrete element under the point.

Class Members
SVGGraphicsElement hitElement The concrete painted descendant actually under the point (e.g. the nested <rect> inside the <a>). An <a> paints nothing of its own, so this is always a descendant of linkElement, never the <a> element itself.
RcString href The raw, unresolved link target as authored on the <a> element (href / xlink:href), for example "#section", "../other.svg", or "https://example.com/". The embedding application is responsible for resolving this reference against the document base URL and performing any navigation; Donner returns the target verbatim and never navigates itself.
SVGAElement linkElement The enclosing <a> element whose content was hit.

Constructor & Destructor Documentation

◆ DonnerController()

donner::svg::DonnerController::DonnerController ( SVGDocument document)
explicit

Create a controller for the given document.

Parameters
documentThe SVG document to query.

Member Function Documentation

◆ findAllIntersecting()

std::vector< SVGGraphicsElement > donner::svg::DonnerController::findAllIntersecting ( const Vector2d & point)

Return every painted element intersecting p point, front to back.

This supports scoped editor hit testing without allowing an element outside the active scope to occlude an eligible descendant.

◆ findIntersecting()

std::optional< SVGGraphicsElement > donner::svg::DonnerController::findIntersecting ( const Vector2d & point)

Finds the topmost geometry element whose rendered area contains the given point.

The point is in SVG canvas coordinates (the same coordinate space as the root <svg> element's viewBox). Returns the deepest matching element in paint order (last painted = topmost).

Parameters
pointPosition in canvas coordinates.
Returns
The topmost intersecting geometry element, or std::nullopt if no element is hit.

◆ hitTestLink()

std::optional< LinkHit > donner::svg::DonnerController::hitTestLink ( const Vector2d & point)

Finds the hyperlink (<a>) at the given point, if any, resolving the enclosing-<a> semantics from the SVG linking model (https://www.w3.org/TR/SVG2/linking.html#Links).

The embedding application drives this query directly from its own pointer events, so the same call serves both link activation (on click / tap) and link affordances (on hover, e.g. a pointer-cursor change, hover highlight, or tooltip). Donner intentionally exposes a stateless query rather than registering navigation callbacks: it has no event loop and never navigates, so the application keeps full control over what a hover versus a click does with the returned target.

Hit resolution reuses findIntersecting, so it honors pointer-events, visibility, display, paint-order, transforms, and per-shape fill/stroke geometry, and it is independent of the active renderer (TinySkia or Geode). A point that lands on any descendant of an <a> resolves to that <a> (the nearest ancestor <a> with a link target), matching the SVG requirement that the whole subtree of a link is clickable. If the topmost painted element at the point is not inside any <a>, no link is returned even when a lower, occluded element would have been linked.

The point is in SVG canvas coordinates (the same coordinate space as the root <svg> element's viewBox), identical to findIntersecting.

Resolution follows the document-tree ancestor chain, which has two consequences worth noting: a <a> wrapping graphics (or a whole <text>) resolves normally, but an inline <a> span nested inside a <text> resolves to that enclosing <text> rather than to the inline span, because text is hit-tested at text-element granularity. Content injected through <use> is resolved by the referenced subtree's own ancestry.

DonnerController controller(document);
if (auto link = controller.hitTestLink(cursorPosition)) {
// On hover: show a pointer cursor / highlight link->linkElement.
// On click: navigate to link->href (the app resolves and follows it).
app.openUrl(link->href);
}
Parameters
pointPosition in canvas coordinates.
Returns
The enclosing link, its raw target, and the hit element, or std::nullopt if no link is at the point.

The documentation for this class was generated from the following file: