Skip to main content

Module scanner

Module scanner 

Source
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 into intersects of the first intersection on scanline y_min + i.
  • row_start[n_rows] is the total number of intersections (sentinel).
  • All intersections are stored in a single Vec<Intersect>, sorted by x0 within 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:

  1. Count pass: walk segments, increment a counts[row] entry for each intersection generated (identical edge-walking logic as the fill pass).
  2. Prefix-sum: convert counts into row_start offsets; allocate the flat intersects buffer in one shot.
  3. Fill pass: walk segments again, writing into the pre-allocated slots.
  4. 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.
XPathScanner
Per-scanline intersection table built from an XPath.