Expand description
Scanline intersection lists for path fill and clip.
XPathScanner converts an XPath edge table into per-scanline
intersection spans, which are then consumed by ScanIterator (a
private iterator type) to emit (x0, x1) spans for compositing.
§Design vs. C++ original
The C++ SplashXPathScanner stores std::vector<SplashIntersect> (or
boost::container::small_vector<SplashIntersect, 4>) per scanline — one
heap allocation per row. This replacement uses a flat SoA layout:
row_start[i]is the index intointersectsof the first intersection on scanliney_min + i.row_start[n_rows]is the total number of intersections (sentinel).- All intersections are stored in a single
Vec<Intersect>, sorted byx0within each row.
This eliminates per-row heap allocations and is friendlier to the CPU cache and future SIMD work.
§Two-pass construction (Tier 3)
XPathScanner::new uses a two-pass counting-sort to avoid n_rows
individual Vec allocations:
- Count pass: walk segments, increment a
counts[row]entry for each intersection generated (identical edge-walking logic as the fill pass). - Prefix-sum: convert counts into
row_startoffsets; allocate the flatintersectsbuffer in one shot. - Fill pass: walk segments again, writing into the pre-allocated slots.
- Sort: sort each row’s slice in-place by
x0.
This reduces construction from O(n_rows) heap allocs + flatten to a single
pair of allocations regardless of path height.
Modules§
- iter
- The coalescing span iterator for a scanner row. Coalescing span iterator over a scanner’s intersection row.
Structs§
- Intersect
- One intersection entry for a scanline.
- XPath
Scanner - Per-scanline intersection table built from an
XPath.