Donner SVG 0.8.0
0.8.0 ยท ebf353960.8.0 main
SVG editor and embeddable C⁠+⁠+⁠20 engine.
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

class  HitTestSnapshot
 Immutable hit geometry for one rendered document state. No live layout access during queries. More...
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

std::shared_ptr< const HitTestSnapshot > captureHitTest ()
 Capture current hit geometry and targets for interaction with the corresponding rendered frame. Targets resolve as for findIntersecting, so they remain valid document elements after later render-tree rebuilds.
 DonnerController (SVGDocument document)
 Create a controller for the given document.
std::optional< SVGGraphicsElement > findIntersecting (const Vector2d &point, HitTestMode mode=HitTestMode::SvgPointerEvents)
 Finds the topmost rendered element (a shape, or a <text> element when text support is enabled) whose rendered area contains the given point.
std::vector< SVGGraphicsElement > findAllIntersecting (const Vector2d &point, HitTestMode mode=HitTestMode::SvgPointerEvents)
 Return every painted element intersecting point, front to back.
std::optional< Cursor > cursorAt (const Vector2d &point)
 Returns the inherited CSS cursor value for the topmost interactive element at a point.
std::optional< LinkHit > 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).

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:397

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>), or the <use> element whose content was hit. 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

◆ captureHitTest()

std::shared_ptr< const HitTestSnapshot > donner::svg::DonnerController::captureHitTest ( )

Capture current hit geometry and targets for interaction with the corresponding rendered frame. Targets resolve as for findIntersecting, so they remain valid document elements after later render-tree rebuilds.

Returns
A snapshot; check HitTestSnapshot::complete for budget exhaustion.

◆ cursorAt()

std::optional< Cursor > donner::svg::DonnerController::cursorAt ( const Vector2d & point)

Returns the inherited CSS cursor value for the topmost interactive element at a point.

Cursor image URLs are returned as authored, without resolving them against a base URL.

Parameters
pointPosition in document coordinates, as for findIntersecting.
Returns
Ordered image candidates and keyword fallback, or std::nullopt when no element is hit.

◆ findAllIntersecting()

std::vector< SVGGraphicsElement > donner::svg::DonnerController::findAllIntersecting ( const Vector2d & point,
HitTestMode mode = HitTestMode::SvgPointerEvents )

Return every painted element intersecting point, front to back.

This supports scoped editor hit testing without allowing an element outside the active scope to occlude an eligible descendant. Targets resolve as for findIntersecting, and each element is reported once, at its frontmost hit.

Parameters
pointPosition in document coordinates, as for findIntersecting.
modeHit eligibility policy, with the same semantics as findIntersecting.
Returns
Intersecting elements, topmost first, or an empty vector if no element is hit.

◆ findIntersecting()

std::optional< SVGGraphicsElement > donner::svg::DonnerController::findIntersecting ( const Vector2d & point,
HitTestMode mode = HitTestMode::SvgPointerEvents )

Finds the topmost rendered element (a shape, or a <text> element when text support is enabled) whose rendered area contains the given point.

The point is in document coordinates: the user space of the root <svg> element's viewBox. To hit-test a canvas pixel, map it through the inverse of SVGDocument::canvasFromDocumentTransform first. Returns the last-painted (topmost) matching element.

Content rendered by a <use> element resolves to that <use> element (the outermost one for nested <use> instances), matching SVG 2 event retargeting for <use> instances. Pattern, mask and marker content is painted as part of the element that references it and is never returned.

Parameters
pointPosition in document coordinates.
modeSVG event targeting by default; EditorSelection ignores pointer-events while retaining visible painted geometry. Neither mode changes the document's properties.
Returns
The topmost intersecting 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 document coordinates (the user space of 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 rendered through <use> resolves to the <use> element, so a link applies when it encloses that <use> element.

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 document 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: