Playback Mode Pages
ci / checks (push) Successful in 50m29s

This commit is contained in:
khodowany
2026-10-06 23:11:25 -05:00
parent 125aaa1637
commit d2f493c17b
33 changed files with 620 additions and 130 deletions
+29
View File
@@ -79,6 +79,9 @@ def audit_layout(document: dict, layout: generator.engraving.types.LayoutDocumen
# Staff, ledger, stem, beam and tie contacts are intentional. Distinct
# noteheads, accidentals and text in the same lane must remain separate.
checked = [p for p in system.primitives if p.role in ('head', 'tab', 'accidental', 'harmony', 'lyric', 'scale', 'section')]
for label in (p for p in system.primitives if p.role == 'measure_number'):
if any(label.box.overlaps(p.box, 3 * system.scale) for p in system.primitives if p is not label):
raise generator.engraving.types.EngravingError(f'{label.sources}: measure number overlaps notation')
for i, item in enumerate(checked):
for other in checked[i + 1:]:
if set(item.sources) & set(other.sources) and (item.role != 'tab' or other.role != 'tab'):
@@ -141,3 +144,29 @@ def audit_layout(document: dict, layout: generator.engraving.types.LayoutDocumen
for span in index.staff.get('octave_shifts', []):
if not any(p.role == 'octave-shift' for p in primitives.get(span['id'], [])):
raise generator.engraving.types.EngravingError(f'{span["id"]}: octave shift was omitted')
def audit_playback(pages, playback, style, fonts):
canonical = [system for page in pages for system in page.systems]
if len(playback) != len(canonical):
raise generator.engraving.types.EngravingError('playback must have one view per system')
for i, page in enumerate(playback):
audit_primitives(page.primitives, page.width, page.height, fonts)
expected = canonical[i:i + 2]
if len(page.systems) != len(expected):
raise generator.engraving.types.EngravingError('invalid playback system pairing')
header = generator.engraving.types.bounds([p for p in page.primitives if p.role in ('title', 'subtitle')])
footer = generator.engraving.types.bounds([p for p in page.primitives if p.role == 'page_number'])
if page.systems[0].box.top < header.bottom + style.page_clearance - 0.01 or page.systems[-1].box.bottom > footer.top - style.page_clearance + 0.01:
raise generator.engraving.types.EngravingError('playback overlaps header or footer')
for a, b in zip(page.systems, page.systems[1:]):
if a.box.bottom + style.system_gap > b.box.top + 0.01:
raise generator.engraving.types.EngravingError('playback systems overlap')
for source, actual in zip(expected, page.systems):
if (source.start, source.end, source.scale, source.fragments) != (actual.start, actual.end, actual.scale, actual.fragments):
raise generator.engraving.types.EngravingError('playback changes system content')
dy = actual.box.top - source.box.top
if len(source.primitives) != len(actual.primitives):
raise generator.engraving.types.EngravingError('playback changes primitives')
for a, b in zip(source.primitives, actual.primitives):
if (a.kind, a.role, a.sources, a.value, a.size) != (b.kind, b.role, b.sources, b.value, b.size) or len(a.points) != len(b.points) or any(abs(x - u) > .001 or abs(y + dy - v) > .001 for (x, y), (u, v) in zip(a.points, b.points)):
raise generator.engraving.types.EngravingError('playback changes notation geometry')