Both scan problems reported from testing came from the same place: the
content rectangle defaulted to the whole page, so the mechanism meant
to handle margin junk never engaged. Ketun joululaulu has a vertical
scan streak down the right margin and Engel a shadow, and because trim
is tight and per slice, either one sets that slice's width, which sets
the song's widest slice, which scales the whole song down.
Detection can propose it. Staff lines are long horizontal runs; scan
shadows, spine darkening and glass streaks are vertical, so a wide flat
opening keeps one and erases the other. Three corrections were needed
against the corpus:
- Search only rows inside detected systems. A horizontal artefact above
or below the music is itself a long horizontal run reaching the paper
edge, which put Engel's left bound at 0.
- Take a percentile of the staff-line extents, not the maximum. Where
an artefact touches a staff line the two merge into one component: on
Ketun p2 the merged line ends at 1575px against 1544px on the clean
page.
- Take the left bound from the brackets too. A bracket sits left of
every staff line, so a staff-line bound crops it off — visible
immediately when comparing exported slices.
Anchors are now a dataclass carrying their left edge rather than a
(top, bottom) tuple.
Engel now drops 12-14% of page width and its music fills 1920px instead
of leaving the shadow's dead space; Ketun drops 12%.
Existing projects keep their saved rectangle; the editor's new Auto-fit
and Auto-fit all buttons re-propose it without disturbing cuts.
Feliz Navidad exposed two assignment faults. Each bracket was expanding
independently, so a lyric line between two systems could be claimed by
both, producing overlapping extents. And nearest-bracket is the wrong
rule: engravers space lyrics generously, so a line sits 43px under its
own system's bracket but only 10px above the next one's.
Now one pass assigns every run exactly once: ink overlapping a bracket
belongs to it, and otherwise the system above wins over the system
below. Text under a staff belongs to that staff.
Known limit, documented in _assign: where a lyric is printed tight
enough that no blank row separates it from the next system's staves,
the two fuse into one ink run and no row profile can split them. The
lyric goes to the system below and the cut lands ~90px high. Dragging
it is the fix.
Feliz Navidad now reads 5 systems on every page, staff 70px, with no
overlapping extents; Ketun joululaulu, Engel and Elaman nalka are
unchanged.
Systems anchor on the vertical bracket and expand over nearby ink, per
ADR 0006. Two corrections the corpus forced:
- Expansion measures distance from the bracket, never from the growing
extent. A chaining expansion hops between the closely-stacked lines of
a title block and walks the whole way up the page — on Engel p1 it
swallowed the title into system 1 and the copyright footer into
system 3.
- Reach is 1.5 staff heights, which takes in the lyrics below the last
staff and the tempo mark and INTRO box above the first, while leaving
the title block and footer out.
Verified against the corpus. Ketun joululaulu: 2 systems per page except
p7 (3) and p12 (1), staff 48px throughout, skew -2.7 to +1.2 per page,
and p2 system 1 spans 179-1071 where its bracket is 177-994 — the
difference being the bottom voice's lyric line. Engel: 2-3 systems per
page, staff 70-72px. Elaman nalka: 3 systems per page, 0 skew, staff
118px at 600 DPI.
The overlay dump is what made both bugs visible, and stays as the tool
for diagnosing a page that comes out wrong.
Closes#4, #5, #6, #7, #8, #9