|
|
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.
|
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< SVGGraphicsElement > | findIntersecting (const Vector2d &point) |
| Finds the topmost geometry element whose rendered area contains the given point. | |
| std::vector< SVGGraphicsElement > | findAllIntersecting (const Vector2d &point) |
| Return every painted element intersecting p point, front to back. | |
| 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). | |
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.
| 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. |
|
explicit |
Create a controller for the given document.
| document | The SVG document to query. |
| 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.
| 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).
| point | Position in canvas coordinates. |
std::nullopt if no element is hit. 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.
| point | Position in canvas coordinates. |
std::nullopt if no link is at the point.