Skip to main content

Module iter

Module iter 

Source
Expand description

The coalescing span iterator for a scanner row. Coalescing span iterator over a scanner’s intersection row.

crate::ScanIterator mirrors SplashXPathScanIterator::getNextSpan from splash/SplashXPathScanner.cc. It merges adjacent and overlapping intersections into contiguous (x0, x1) spans (inclusive) and handles both even-odd and non-zero winding fill rules via the eo_mask.

§Winding-rule semantics

The iterator maintains a running count — the sum of all Intersect::count values consumed so far. Whether the current pixel position is inside the path depends on the fill rule:

  • Non-zero winding (eo = false): inside when count != 0. eo_mask = !0 so count & eo_mask is non-zero iff count != 0.
  • Even-odd (eo = true): inside when the crossing count is odd. eo_mask = 1 so count & eo_mask isolates the low bit (parity).

§Algorithm (next)

§Phase 1 — find the span start

Before consuming each entry, check count & eo_mask:

  • Already non-zero → we are inside from a previous span’s count residue; the current entry (row[idx]) is the span start. Record its x0 and go to phase 2 without consuming it yet (phase 2 will consume it).
  • Zero → consume the entry (add its count, advance idx). If now non-zero → this entry is the span start; record its x0 (from row[idx - 1]) and go to phase 2 (the entry is already consumed).
  • Still zero → continue to the next entry.

§Phase 2 — collect the span

Starting from row[phase2_start_idx] (inclusive), consume entries, tracking the maximum x1 seen, until count & eo_mask == 0. Emit (x0, x1).

Each Intersect entry’s count is accumulated exactly once across the two phases. After next returns, count equals the winding number immediately after the rightmost covered pixel x1.

Structs§

ScanIterator
An iterator that yields (x0, x1) inclusive pixel spans for one scanline.