|
|
Donner SVG 0.8.0-pre
SVG editor and embeddable C++20 engine.
|
Device-aware curve-flattening tolerance for stroke-outline generation. More...
Namespaces | |
| namespace | donner |
| Top-level Donner namespace, which is split into different sub-namespaces such as donner::svg and donner::css. | |
Functions | |
| double | donner::geode::MaxAbsScaleFactor (const Transform2d &transform) |
Largest factor by which transform can stretch a vector, i.e. | |
| double | donner::geode::StrokeFlattenScaleBucket (double scale) |
Round scale up to the next power of two, with a floor of 1. | |
| double | donner::geode::StrokeFlattenToleranceFor (const Transform2d &deviceFromLocal) |
Path-local curve-flattening tolerance for stroke geometry that will be drawn with deviceFromLocal. | |
Variables | |
| constexpr double | donner::geode::kStrokeFlattenDevicePixels = 0.25 |
| Target flattening chord error for stroke outlines, in device pixels. Matches the historical path-local default so unscaled rendering is unchanged. | |
| constexpr double | donner::geode::kMinStrokeFlattenTolerance = 1e-4 |
| Lower clamp for the derived path-local tolerance. Bounds tessellation work (and recursion depth) at absurd zoom levels. The device-pixel guarantee holds up to a scale of kStrokeFlattenDevicePixels / kMinStrokeFlattenTolerance. | |
| constexpr double | donner::geode::kMaxStrokeFlattenTolerance = kStrokeFlattenDevicePixels |
| Upper clamp for the derived path-local tolerance: the historical path-local default. The derivation only ever REFINES flattening, never coarsens it. | |
Device-aware curve-flattening tolerance for stroke-outline generation.
Path::strokeToFill flattens curves to line segments before offsetting them, and the tolerance it takes is expressed in the path's OWN coordinate space. A renderer that submits geometry in document space and lets the GPU apply the view transform therefore gets a polygon that was tessellated once at document scale and then magnified: at any meaningful zoom a circle (4 kappa cubics) degenerates into a visibly faceted segment chain.
The fix is to derive the path-local tolerance from the transform the geometry is actually rasterized with, so the chord error stays bounded in DEVICE pixels no matter what the view scale is. Curves rendering as visible line segments is a correctness violation, not a cosmetic one, so this derivation is mandatory for every renderer-side stroke call site.
The derived scale is quantized to power-of-two buckets so that a continuous zoom gesture does not invalidate the stroke cache on every frame: within a bucket the tolerance is bit-identical, and crossing a bucket boundary re-derives (and, via the cache key, re-flattens) exactly once.
|
inline |
Largest factor by which transform can stretch a vector, i.e.
the maximum singular value of its 2x2 linear part.
Using the maximum singular value (rather than, say, the average of the axis scales) is what makes the device-space bound a guarantee: for any local-space error vector e, |M e| <= sigmaMax * |e|, so bounding the local chord error by target / sigmaMax bounds the device chord error by target.
| transform | Transform whose linear part is measured. Translation is ignored. |
|
inline |
Round scale up to the next power of two, with a floor of 1.
Quantizing before deriving the tolerance keeps the tolerance stable across a continuous zoom, so the stroke cache is rebuilt on bucket crossings only. Rounding UP (never down) keeps the derived tolerance conservative: the flattening is at least as fine as the exact scale demands.
The floor of 1 is what makes the derivation refine-only - see kMaxStrokeFlattenTolerance. Minified geometry keeps the path-local default rather than being tessellated more coarsely.
| scale | Linear scale factor. Non-finite and non-positive inputs fall back to 1.0 (a degenerate transform paints nothing, so any bucket works). |
|
inline |
Path-local curve-flattening tolerance for stroke geometry that will be drawn with deviceFromLocal.
The result keeps the flattening chord error under kStrokeFlattenDevicePixels device pixels for every scale up to kStrokeFlattenDevicePixels / kMinStrokeFlattenTolerance, and is clamped to [kMinStrokeFlattenTolerance, kMaxStrokeFlattenTolerance].
| deviceFromLocal | Transform applied to the geometry at draw time. |
|
inlineconstexpr |
Upper clamp for the derived path-local tolerance: the historical path-local default. The derivation only ever REFINES flattening, never coarsens it.
Coarsening minified geometry would technically stay inside the device-pixel budget, but it trades output quality for CPU on content that is not the defect this derivation exists to fix, and it perturbs the rendering of every downscaled document (filter sub-renders, pattern tiles, thumbnails). Refining only keeps the change strictly additive.