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
+51
View File
@@ -21,6 +21,7 @@ import generator.engraving.types
import generator.guitar
import generator.model
import generator.musicxml
import generator.performance
import tests.score_events
import tests.arrangement_fixtures
import tests.test_accompaniment
@@ -139,6 +140,56 @@ class EngravingTests(unittest.TestCase):
actual = generator.engraving.raster.rasterize_page(layout.pages[0], self.fonts)
with PIL.Image.open('tests/fixtures/notation_python.png') as expected:
self.assertIsNone(PIL.ImageChops.difference(actual, expected.convert('RGB')).getbbox())
def test_playback_windows_reuse_complete_systems_and_finish_on_top(self):
for count in (1, 2, 3, 4):
with self.subTest(systems=count):
source = tests.test_musicxml.parse(tests.test_accompaniment.xml_bars([tests.test_musicxml.xml_note()] * count))
style = generator.engraving.types.Style()
index = generator.engraving.notation.ScoreIndex(source)
systems = [generator.engraving.layout.make_system(index, i * 4, (i + 1) * 4, self.fonts, style) for i in range(count)]
pages, playback = generator.engraving.layout.page_views(systems, source, self.fonts, style, index=index)
generator.engraving.audit.audit_layout(source, generator.engraving.types.LayoutDocument(pages, style, ''), self.fonts)
generator.engraving.audit.audit_playback(pages, playback, style, self.fonts)
self.assertEqual(len(pages), (count + 1) // 2)
self.assertEqual(len(playback), count)
self.assertEqual([[s.start for s in p.systems] for p in playback], [[i * 4, (i + 1) * 4] if i + 1 < count else [i * 4] for i in range(count)])
self.assertLess(playback[-1].systems[0].box.top, style.height / 2)
for sequence in (pages, playback):
for page in sequence:
self.assertEqual(len({s.scale for s in page.systems}), 1)
normal = [generator.performance.page_timing(source, p) for p in pages]
sliding = [generator.performance.page_timing(source, p) for p in playback]
generator.performance.validate_views(source, normal, sliding)
def test_transition_pair_of_tall_systems_fits_at_shared_scale(self):
short = tests.test_musicxml.xml_note()
tall = tests.test_musicxml.xml_note('C', 2, 'half', octave=2) + tests.test_musicxml.xml_note('C', 2, 'half', octave=7)
source = tests.test_musicxml.parse(tests.test_accompaniment.xml_bars([short, tall, tall, short]))
style = generator.engraving.types.Style()
index = generator.engraving.notation.ScoreIndex(source)
systems = [generator.engraving.layout.make_system(index, i * 4, (i + 1) * 4, self.fonts, style) for i in range(4)]
pages, playback = generator.engraving.layout.page_views(systems, source, self.fonts, style)
generator.engraving.audit.audit_playback(pages, playback, style, self.fonts)
self.assertEqual(playback[1].systems[0].scale, pages[0].systems[0].scale)
self.assertLess(playback[1].systems[1].box.bottom, style.height - style.margin_y)
def test_measure_numbers_clear_high_notes_and_follow_barlines(self):
source = tests.test_musicxml.parse(tests.test_accompaniment.xml_bars([tests.test_musicxml.xml_note('C', octave=7)] * 3))
for i, measure in enumerate(source['staves'][0]['measures']):
measure['number'] = str(169 + i)
layout = self.layout(source)
for page in layout.pages:
for system in page.systems:
labels = [p for p in system.primitives if p.role == 'measure_number']
self.assertEqual(len({round(p.points[0][1], 6) for p in labels}), 1)
bars = [p for p in system.primitives if p.role == 'barline']
for i, label in enumerate(labels):
center = (label.box.left + label.box.right) / 2
if i == 0:
self.assertAlmostEqual(center, layout.style.margin_x + 1, places=2)
else:
self.assertTrue(any(abs(center - p.points[0][0]) < system.scale for p in bars))
for other in system.primitives:
if other is not label:
self.assertFalse(label.box.overlaps(other.box, 3 * system.scale))
def test_aligned_bands_match_full_pages_with_spans_tab_and_sampling_phases(self):
tied = tests.test_musicxml.xml_note('E', 2, 'half', extra='<tie type="start"/>') + tests.test_musicxml.xml_note('E', 2, 'half', extra='<tie type="stop"/>')
content = ''.join(tests.test_musicxml.xml_note('G', 1, 'eighth') for _ in range(8))