Inter-staff slice 1/2: a two-staff pressure fixture

Groundwork for inter-staff band-height renegotiation (the last vertical-spring
piece): a fixture whose two staves' content nearly collides at the engraver's
fixed staff pitch, so the pending solve has something meaningful to separate.

two_staff_close_content: a one-measure, two-staff (treble/treble) metric score.
The top staff descends into low ledger notes (down to C2); the bottom staff
climbs into high ledger notes (up to C6) under a slur that arcs further above
them. In the constrained frame the top staff's content occupies y ≈ [-8, +4]
and the bottom staff's ≈ [-12, -5], overlapping in [-8, -5] — the C2 ledgers
collide with the C6 + slur. Invariant-clean; 8 notes, 1 slur, 41 strokes
(the heavy ledgering), 1 curve.

Registered in the render-svg acceptance suite; its goldens (this commit) show
the CURRENT overlapping layout — slice 2 (the solve) will update the engrave
golden to show the staves separated. Invariant test added. 946 tests, clippy 0,
docs -D warnings, conformance 8/8.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
Levi Neuwirth 2026-07-08 22:48:39 -04:00
parent 177bcdb43b
commit f103641013
6 changed files with 324 additions and 0 deletions

View File

@ -45,6 +45,10 @@ fn fixtures() -> Vec<(&'static str, Score)> {
"ten_measure_with_slurs",
epiphany_testkit::fixtures::ten_measure_with_slurs(0x000A_11CE),
),
(
"two_staff_close_content",
epiphany_testkit::fixtures::two_staff_close_content(0x000A_11CE),
),
]
}

View File

@ -0,0 +1,15 @@
fixture=two_staff_close_content solver=engrave
glyph_count=12
path_count=12
fallback_rect_count=0
stroke_count=41
curve_count=1
provenance_count=54
layer_count=1
hard_constraint_count=18
xml_well_formed=true
view_box=[5.5 -28.524578 17.379084 23.024]
class_counts:
barline=2
clef=2
notehead=8

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="173.7908" height="230.24" viewBox="0 0 17.3791 23.024">
<!-- epiphany-render-svg: glyphs are genuine Bravura SMuFL outlines inlined as paths; geometry is the resolved layout verbatim, no engraving performed here; every glyph, stroke, and curve carries a data-prov trace to its score-graph source -->
<g transform="translate(-5.5 -5.5006) scale(1 -1)">
<g data-layer="0">
<line x1="8.6599" y1="-12.8926" x2="8.6599" y2="-12.8926" stroke="#000000" stroke-width="0" data-prov="5ff1785b2e5e554c42cff8d78dd57953" data-source-kind="6" data-kind="stroke"/>
<line x1="7.565" y1="-12.8926" x2="20.2543" y2="-12.8926" stroke="#000000" stroke-width="0.13" data-prov="28cbe5009fab9990097b67e48c426c2b" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-11.8926" x2="20.2543" y2="-11.8926" stroke="#000000" stroke-width="0.13" data-prov="2dcbda48c9ae66371e9b618b4e0ff496" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-10.8926" x2="20.2543" y2="-10.8926" stroke="#000000" stroke-width="0.13" data-prov="5f47dfd6d0910fe3fa68504e3dc8b4cb" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-9.8926" x2="20.2543" y2="-9.8926" stroke="#000000" stroke-width="0.13" data-prov="2f1bc986dc62f2e24256b98e76338b40" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-8.8926" x2="20.2543" y2="-8.8926" stroke="#000000" stroke-width="0.13" data-prov="967277083788b3e3f9928206e546eb2d" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-24.8926" x2="20.2543" y2="-24.8926" stroke="#000000" stroke-width="0.13" data-prov="c6afc2060e4ee437d03c460c5e51edb0" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-23.8926" x2="20.2543" y2="-23.8926" stroke="#000000" stroke-width="0.13" data-prov="fc03fb2cca3c3f5d6276b60b1ff83b72" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-22.8926" x2="20.2543" y2="-22.8926" stroke="#000000" stroke-width="0.13" data-prov="4ac3502112246f2950bf9ba00346e839" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-21.8926" x2="20.2543" y2="-21.8926" stroke="#000000" stroke-width="0.13" data-prov="dbcbf5fb791e00972d5a014eb0897966" data-source-kind="3" data-kind="stroke"/>
<line x1="7.565" y1="-20.8926" x2="20.2543" y2="-20.8926" stroke="#000000" stroke-width="0.13" data-prov="0c940e546e084c0e0c76dc5b5d4cc29f" data-source-kind="3" data-kind="stroke"/>
<line x1="8.6599" y1="-12.8926" x2="8.6599" y2="-12.8926" stroke="#000000" stroke-width="0" data-prov="dec48b26ccf8d32aaef3b0d78c728ac1" data-source-kind="2" data-kind="stroke"/>
<line x1="13.0944" y1="-13.8926" x2="13.0944" y2="-10.3926" stroke="#000000" stroke-width="0.12" data-prov="2605e711923a6304409ca2b5627aed7e" data-source-kind="0" data-kind="stroke"/>
<line x1="11.6444" y1="-13.8926" x2="13.4251" y2="-13.8926" stroke="#000000" stroke-width="0.13" data-prov="9f71ea414173b35b44c2a526ba3572b7" data-source-kind="1" data-kind="stroke"/>
<line x1="15.1751" y1="-17.3926" x2="15.1751" y2="-13.8926" stroke="#000000" stroke-width="0.12" data-prov="b2df28c1e46d5eb33759d335032e7d07" data-source-kind="0" data-kind="stroke"/>
<line x1="13.7251" y1="-13.8926" x2="15.5058" y2="-13.8926" stroke="#000000" stroke-width="0.13" data-prov="609bda392c2721347d787ed7b85bab5a" data-source-kind="1" data-kind="stroke"/>
<line x1="13.7251" y1="-14.8926" x2="15.5058" y2="-14.8926" stroke="#000000" stroke-width="0.13" data-prov="6112bc164d0d03853f4fc44f55dcb57a" data-source-kind="1" data-kind="stroke"/>
<line x1="13.7251" y1="-15.8926" x2="15.5058" y2="-15.8926" stroke="#000000" stroke-width="0.13" data-prov="bef6e57fb87c56c2916a05fdb334f49c" data-source-kind="1" data-kind="stroke"/>
<line x1="13.7251" y1="-16.8926" x2="15.5058" y2="-16.8926" stroke="#000000" stroke-width="0.13" data-prov="15e0d12c71c4e3aa49c9145482409090" data-source-kind="1" data-kind="stroke"/>
<line x1="17.2558" y1="-20.8926" x2="17.2558" y2="-17.3926" stroke="#000000" stroke-width="0.12" data-prov="b625587ff114949abad6d0b181fbfd20" data-source-kind="0" data-kind="stroke"/>
<line x1="15.8058" y1="-13.8926" x2="17.5864" y2="-13.8926" stroke="#000000" stroke-width="0.13" data-prov="99a975983299cf3260278173c3867b94" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-14.8926" x2="17.5864" y2="-14.8926" stroke="#000000" stroke-width="0.13" data-prov="a53017a9a527ee7597897591ec0e0974" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-15.8926" x2="17.5864" y2="-15.8926" stroke="#000000" stroke-width="0.13" data-prov="250e0863d6d90879e1d890ec74b581c6" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-16.8926" x2="17.5864" y2="-16.8926" stroke="#000000" stroke-width="0.13" data-prov="c2fd369455e14f712c47c33eeb44c7e7" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-17.8926" x2="17.5864" y2="-17.8926" stroke="#000000" stroke-width="0.13" data-prov="6ec09f4ee7926af63e28300166ea6646" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-18.8926" x2="17.5864" y2="-18.8926" stroke="#000000" stroke-width="0.13" data-prov="74ef3fb044547118b3a45fa7ab21f91f" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-19.8926" x2="17.5864" y2="-19.8926" stroke="#000000" stroke-width="0.13" data-prov="a3f1031ad8b73109c6c7fdebb5a82f88" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-20.8926" x2="17.5864" y2="-20.8926" stroke="#000000" stroke-width="0.13" data-prov="14bc5e293e7e48821e34201207cedf7a" data-source-kind="1" data-kind="stroke"/>
<line x1="19.3364" y1="-17.3926" x2="19.3364" y2="-13.8926" stroke="#000000" stroke-width="0.12" data-prov="7cc4fe5d82ef7386da10c5cef6508856" data-source-kind="0" data-kind="stroke"/>
<line x1="17.8864" y1="-13.8926" x2="19.6671" y2="-13.8926" stroke="#000000" stroke-width="0.13" data-prov="516a866745c72968322bf22e817109f3" data-source-kind="1" data-kind="stroke"/>
<line x1="17.8864" y1="-14.8926" x2="19.6671" y2="-14.8926" stroke="#000000" stroke-width="0.13" data-prov="faa92f6a10e55a97e9b2f7e359f09038" data-source-kind="1" data-kind="stroke"/>
<line x1="17.8864" y1="-15.8926" x2="19.6671" y2="-15.8926" stroke="#000000" stroke-width="0.13" data-prov="c7f132db91c48ecc8015b7e748f00819" data-source-kind="1" data-kind="stroke"/>
<line x1="17.8864" y1="-16.8926" x2="19.6671" y2="-16.8926" stroke="#000000" stroke-width="0.13" data-prov="867f712bbd9c4c178425fd0f53e01fa2" data-source-kind="1" data-kind="stroke"/>
<line x1="8.6599" y1="-24.8926" x2="8.6599" y2="-24.8926" stroke="#000000" stroke-width="0" data-prov="781ef3842ebea010cbefab514c733440" data-source-kind="2" data-kind="stroke"/>
<line x1="13.0944" y1="-25.8926" x2="13.0944" y2="-22.3926" stroke="#000000" stroke-width="0.12" data-prov="8fedf07e00164403db044570899f2550" data-source-kind="0" data-kind="stroke"/>
<line x1="11.6444" y1="-25.8926" x2="13.4251" y2="-25.8926" stroke="#000000" stroke-width="0.13" data-prov="32b5060f271a3aa21b504bfc3160af6d" data-source-kind="1" data-kind="stroke"/>
<line x1="15.1751" y1="-22.3926" x2="15.1751" y2="-18.8926" stroke="#000000" stroke-width="0.12" data-prov="19a0fc032dbfc94ac8b2801dfdeaa658" data-source-kind="0" data-kind="stroke"/>
<line x1="17.2558" y1="-18.8926" x2="17.2558" y2="-15.3926" stroke="#000000" stroke-width="0.12" data-prov="e4e5f1717e87111231d31ba493aaac57" data-source-kind="0" data-kind="stroke"/>
<line x1="15.8058" y1="-19.8926" x2="17.5864" y2="-19.8926" stroke="#000000" stroke-width="0.13" data-prov="1caed515110c4415278d31cc474bf065" data-source-kind="1" data-kind="stroke"/>
<line x1="15.8058" y1="-18.8926" x2="17.5864" y2="-18.8926" stroke="#000000" stroke-width="0.13" data-prov="1189a8cf5e7e1526a44f3cf89e0b160e" data-source-kind="1" data-kind="stroke"/>
<line x1="19.3364" y1="-22.3926" x2="19.3364" y2="-18.8926" stroke="#000000" stroke-width="0.12" data-prov="f230acdf26cd79ad3ba5cd02002fa1f9" data-source-kind="0" data-kind="stroke"/>
<path d="M 14.8053 -20.1926 C 15.6723 -19.1259 16.5392 -19.1259 17.4062 -20.1926" fill="none" stroke="#000000" stroke-width="0.12" data-prov="0165993515166bea8f7cada46e27c86f" data-source-kind="11" data-kind="curve"/>
<path d="M1.504 1.66C1.496 1.708 1.504 1.712 1.528 1.736C1.96 2.14 2.288 2.648 2.288 3.26C2.288 3.608 2.192 3.952 2.028 4.192C1.968 4.28 1.864 4.392 1.82 4.392C1.764 4.392 1.64 4.288 1.56 4.2C1.264 3.872 1.168 3.372 1.168 2.956C1.168 2.724 1.196 2.464 1.224 2.3C1.232 2.252 1.236 2.244 1.188 2.204C0.612 1.728 0 1.156 0 0.348C0 -0.348 0.476 -1.008 1.456 -1.008C1.548 -1.008 1.652 -1 1.732 -0.984C1.776 -0.976 1.784 -0.972 1.792 -1.02C1.84 -1.288 1.9 -1.636 1.9 -1.824C1.9 -2.416 1.5 -2.488 1.264 -2.488C1.048 -2.488 0.944 -2.424 0.944 -2.372C0.944 -2.344 0.98 -2.332 1.072 -2.304C1.196 -2.268 1.34 -2.16 1.34 -1.928C1.34 -1.708 1.2 -1.52 0.956 -1.52C0.688 -1.52 0.528 -1.732 0.528 -1.98C0.528 -2.24 0.684 -2.632 1.288 -2.632C1.556 -2.632 2.076 -2.512 2.076 -1.832C2.076 -1.604 2.004 -1.224 1.96 -0.976C1.952 -0.928 1.956 -0.932 2.012 -0.908C2.416 -0.748 2.684 -0.408 2.684 0.044C2.684 0.556 2.308 1.008 1.72 1.008C1.616 1.008 1.616 1.008 1.604 1.08ZM1.88 3.772C2.012 3.772 2.12 3.664 2.12 3.444C2.12 3 1.74 2.64 1.424 2.364C1.396 2.34 1.38 2.344 1.372 2.396C1.356 2.5 1.348 2.636 1.348 2.764C1.348 3.388 1.636 3.772 1.88 3.772ZM1.444 1.048C1.456 0.972 1.456 0.976 1.384 0.952C1.032 0.832 0.804 0.516 0.804 0.176C0.804 -0.184 0.992 -0.44 1.264 -0.532C1.296 -0.544 1.344 -0.556 1.372 -0.556C1.404 -0.556 1.42 -0.536 1.42 -0.512C1.42 -0.484 1.388 -0.472 1.36 -0.46C1.192 -0.388 1.072 -0.216 1.072 -0.032C1.072 0.196 1.228 0.368 1.472 0.436C1.536 0.452 1.544 0.448 1.552 0.404L1.752 -0.788C1.76 -0.832 1.756 -0.832 1.696 -0.844C1.632 -0.856 1.552 -0.864 1.472 -0.864C0.772 -0.864 0.32 -0.476 0.32 0.08C0.32 0.316 0.36 0.632 0.692 1.008C0.932 1.276 1.116 1.424 1.304 1.576C1.344 1.608 1.352 1.604 1.36 1.56ZM1.72 0.412C1.712 0.46 1.716 0.472 1.764 0.468C2.088 0.44 2.356 0.168 2.356 -0.184C2.356 -0.436 2.204 -0.64 1.98 -0.752C1.932 -0.776 1.924 -0.776 1.916 -0.728Z" transform="translate(8.6599 -11.8926)" fill="#000000" data-prov="e81b0f9cc6ccb1d0209d51b1d9797db5" data-source-kind="4" data-glyph="gClef" data-class="clef"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(11.9444 -13.8926)" fill="#000000" data-prov="9b3ac956eb2deb3e538d9b1942c6ae97" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(14.0251 -17.3926)" fill="#000000" data-prov="751a5a693a87d6c1a15a8dfc3eda8102" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(16.1058 -20.8926)" fill="#000000" data-prov="130e9eddac04d8c2fb7373aae2c3b458" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(18.1864 -17.3926)" fill="#000000" data-prov="e6f9d102cb9512c808d4bff5a3560b34" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M1.504 1.66C1.496 1.708 1.504 1.712 1.528 1.736C1.96 2.14 2.288 2.648 2.288 3.26C2.288 3.608 2.192 3.952 2.028 4.192C1.968 4.28 1.864 4.392 1.82 4.392C1.764 4.392 1.64 4.288 1.56 4.2C1.264 3.872 1.168 3.372 1.168 2.956C1.168 2.724 1.196 2.464 1.224 2.3C1.232 2.252 1.236 2.244 1.188 2.204C0.612 1.728 0 1.156 0 0.348C0 -0.348 0.476 -1.008 1.456 -1.008C1.548 -1.008 1.652 -1 1.732 -0.984C1.776 -0.976 1.784 -0.972 1.792 -1.02C1.84 -1.288 1.9 -1.636 1.9 -1.824C1.9 -2.416 1.5 -2.488 1.264 -2.488C1.048 -2.488 0.944 -2.424 0.944 -2.372C0.944 -2.344 0.98 -2.332 1.072 -2.304C1.196 -2.268 1.34 -2.16 1.34 -1.928C1.34 -1.708 1.2 -1.52 0.956 -1.52C0.688 -1.52 0.528 -1.732 0.528 -1.98C0.528 -2.24 0.684 -2.632 1.288 -2.632C1.556 -2.632 2.076 -2.512 2.076 -1.832C2.076 -1.604 2.004 -1.224 1.96 -0.976C1.952 -0.928 1.956 -0.932 2.012 -0.908C2.416 -0.748 2.684 -0.408 2.684 0.044C2.684 0.556 2.308 1.008 1.72 1.008C1.616 1.008 1.616 1.008 1.604 1.08ZM1.88 3.772C2.012 3.772 2.12 3.664 2.12 3.444C2.12 3 1.74 2.64 1.424 2.364C1.396 2.34 1.38 2.344 1.372 2.396C1.356 2.5 1.348 2.636 1.348 2.764C1.348 3.388 1.636 3.772 1.88 3.772ZM1.444 1.048C1.456 0.972 1.456 0.976 1.384 0.952C1.032 0.832 0.804 0.516 0.804 0.176C0.804 -0.184 0.992 -0.44 1.264 -0.532C1.296 -0.544 1.344 -0.556 1.372 -0.556C1.404 -0.556 1.42 -0.536 1.42 -0.512C1.42 -0.484 1.388 -0.472 1.36 -0.46C1.192 -0.388 1.072 -0.216 1.072 -0.032C1.072 0.196 1.228 0.368 1.472 0.436C1.536 0.452 1.544 0.448 1.552 0.404L1.752 -0.788C1.76 -0.832 1.756 -0.832 1.696 -0.844C1.632 -0.856 1.552 -0.864 1.472 -0.864C0.772 -0.864 0.32 -0.476 0.32 0.08C0.32 0.316 0.36 0.632 0.692 1.008C0.932 1.276 1.116 1.424 1.304 1.576C1.344 1.608 1.352 1.604 1.36 1.56ZM1.72 0.412C1.712 0.46 1.716 0.472 1.764 0.468C2.088 0.44 2.356 0.168 2.356 -0.184C2.356 -0.436 2.204 -0.64 1.98 -0.752C1.932 -0.776 1.924 -0.776 1.916 -0.728Z" transform="translate(8.6599 -23.8926)" fill="#000000" data-prov="380c7e6f256e62d482135a6342d18380" data-source-kind="4" data-glyph="gClef" data-class="clef"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(11.9444 -25.8926)" fill="#000000" data-prov="38b6271edbb50b409f119eff31d0faa9" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(14.0251 -22.3926)" fill="#000000" data-prov="b2c29b264d8593df8589608aee4d8465" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(16.1058 -18.8926)" fill="#000000" data-prov="a6892ec5562df412ce4bdf3bc118e5e9" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(18.1864 -22.3926)" fill="#000000" data-prov="d8123de74f57fff5bdc35478e8ec8e9e" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.144 0V4H0V0ZM0.912 4H0.412V0H0.912Z" transform="translate(19.9671 -12.8926)" fill="#000000" data-prov="ed49137c7e716c68d78a85b89b50500a" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
<path d="M0.144 0V4H0V0ZM0.912 4H0.412V0H0.912Z" transform="translate(19.9671 -24.8926)" fill="#000000" data-prov="7171ecca2c439b3c03c959bdad56cf08" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 15 KiB

View File

@ -0,0 +1,15 @@
fixture=two_staff_close_content solver=stub
glyph_count=12
path_count=12
fallback_rect_count=0
stroke_count=41
curve_count=1
provenance_count=54
layer_count=1
hard_constraint_count=18
xml_well_formed=true
view_box=[-3.065 -15.632 16.876999 23.024]
class_counts:
barline=2
clef=2
notehead=8

View File

@ -0,0 +1,62 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" width="168.77" height="230.24" viewBox="0 0 16.877 23.024">
<!-- epiphany-render-svg: glyphs are genuine Bravura SMuFL outlines inlined as paths; geometry is the resolved layout verbatim, no engraving performed here; every glyph, stroke, and curve carries a data-prov trace to its score-graph source -->
<g transform="translate(3.065 7.392) scale(1 -1)">
<g data-layer="0">
<line x1="0" y1="0" x2="0" y2="0" stroke="#000000" stroke-width="0" data-prov="5ff1785b2e5e554c42cff8d78dd57953" data-source-kind="6" data-kind="stroke"/>
<line x1="-1" y1="0" x2="11.4" y2="0" stroke="#000000" stroke-width="0.13" data-prov="28cbe5009fab9990097b67e48c426c2b" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="1" x2="11.4" y2="1" stroke="#000000" stroke-width="0.13" data-prov="2dcbda48c9ae66371e9b618b4e0ff496" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="2" x2="11.4" y2="2" stroke="#000000" stroke-width="0.13" data-prov="5f47dfd6d0910fe3fa68504e3dc8b4cb" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="3" x2="11.4" y2="3" stroke="#000000" stroke-width="0.13" data-prov="2f1bc986dc62f2e24256b98e76338b40" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="4" x2="11.4" y2="4" stroke="#000000" stroke-width="0.13" data-prov="967277083788b3e3f9928206e546eb2d" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="-12" x2="11.4" y2="-12" stroke="#000000" stroke-width="0.13" data-prov="c6afc2060e4ee437d03c460c5e51edb0" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="-11" x2="11.4" y2="-11" stroke="#000000" stroke-width="0.13" data-prov="fc03fb2cca3c3f5d6276b60b1ff83b72" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="-10" x2="11.4" y2="-10" stroke="#000000" stroke-width="0.13" data-prov="4ac3502112246f2950bf9ba00346e839" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="-9" x2="11.4" y2="-9" stroke="#000000" stroke-width="0.13" data-prov="dbcbf5fb791e00972d5a014eb0897966" data-source-kind="3" data-kind="stroke"/>
<line x1="-1" y1="-8" x2="11.4" y2="-8" stroke="#000000" stroke-width="0.13" data-prov="0c940e546e084c0e0c76dc5b5d4cc29f" data-source-kind="3" data-kind="stroke"/>
<line x1="0" y1="0" x2="0" y2="0" stroke="#000000" stroke-width="0" data-prov="dec48b26ccf8d32aaef3b0d78c728ac1" data-source-kind="2" data-kind="stroke"/>
<line x1="4.15" y1="-1" x2="4.15" y2="2.5" stroke="#000000" stroke-width="0.12" data-prov="2605e711923a6304409ca2b5627aed7e" data-source-kind="0" data-kind="stroke"/>
<line x1="2.7" y1="-1" x2="4.4807" y2="-1" stroke="#000000" stroke-width="0.13" data-prov="9f71ea414173b35b44c2a526ba3572b7" data-source-kind="1" data-kind="stroke"/>
<line x1="5.75" y1="-4.5" x2="5.75" y2="-1" stroke="#000000" stroke-width="0.12" data-prov="b2df28c1e46d5eb33759d335032e7d07" data-source-kind="0" data-kind="stroke"/>
<line x1="4.3" y1="-1" x2="6.0807" y2="-1" stroke="#000000" stroke-width="0.13" data-prov="609bda392c2721347d787ed7b85bab5a" data-source-kind="1" data-kind="stroke"/>
<line x1="4.3" y1="-2" x2="6.0807" y2="-2" stroke="#000000" stroke-width="0.13" data-prov="6112bc164d0d03853f4fc44f55dcb57a" data-source-kind="1" data-kind="stroke"/>
<line x1="4.3" y1="-3" x2="6.0807" y2="-3" stroke="#000000" stroke-width="0.13" data-prov="bef6e57fb87c56c2916a05fdb334f49c" data-source-kind="1" data-kind="stroke"/>
<line x1="4.3" y1="-4" x2="6.0807" y2="-4" stroke="#000000" stroke-width="0.13" data-prov="15e0d12c71c4e3aa49c9145482409090" data-source-kind="1" data-kind="stroke"/>
<line x1="7.35" y1="-8" x2="7.35" y2="-4.5" stroke="#000000" stroke-width="0.12" data-prov="b625587ff114949abad6d0b181fbfd20" data-source-kind="0" data-kind="stroke"/>
<line x1="5.9" y1="-1" x2="7.6807" y2="-1" stroke="#000000" stroke-width="0.13" data-prov="99a975983299cf3260278173c3867b94" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-2" x2="7.6807" y2="-2" stroke="#000000" stroke-width="0.13" data-prov="a53017a9a527ee7597897591ec0e0974" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-3" x2="7.6807" y2="-3" stroke="#000000" stroke-width="0.13" data-prov="250e0863d6d90879e1d890ec74b581c6" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-4" x2="7.6807" y2="-4" stroke="#000000" stroke-width="0.13" data-prov="c2fd369455e14f712c47c33eeb44c7e7" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-5" x2="7.6807" y2="-5" stroke="#000000" stroke-width="0.13" data-prov="6ec09f4ee7926af63e28300166ea6646" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-6" x2="7.6807" y2="-6" stroke="#000000" stroke-width="0.13" data-prov="74ef3fb044547118b3a45fa7ab21f91f" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-7" x2="7.6807" y2="-7" stroke="#000000" stroke-width="0.13" data-prov="a3f1031ad8b73109c6c7fdebb5a82f88" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-8" x2="7.6807" y2="-8" stroke="#000000" stroke-width="0.13" data-prov="14bc5e293e7e48821e34201207cedf7a" data-source-kind="1" data-kind="stroke"/>
<line x1="8.95" y1="-4.5" x2="8.95" y2="-1" stroke="#000000" stroke-width="0.12" data-prov="7cc4fe5d82ef7386da10c5cef6508856" data-source-kind="0" data-kind="stroke"/>
<line x1="7.5" y1="-1" x2="9.2807" y2="-1" stroke="#000000" stroke-width="0.13" data-prov="516a866745c72968322bf22e817109f3" data-source-kind="1" data-kind="stroke"/>
<line x1="7.5" y1="-2" x2="9.2807" y2="-2" stroke="#000000" stroke-width="0.13" data-prov="faa92f6a10e55a97e9b2f7e359f09038" data-source-kind="1" data-kind="stroke"/>
<line x1="7.5" y1="-3" x2="9.2807" y2="-3" stroke="#000000" stroke-width="0.13" data-prov="c7f132db91c48ecc8015b7e748f00819" data-source-kind="1" data-kind="stroke"/>
<line x1="7.5" y1="-4" x2="9.2807" y2="-4" stroke="#000000" stroke-width="0.13" data-prov="867f712bbd9c4c178425fd0f53e01fa2" data-source-kind="1" data-kind="stroke"/>
<line x1="0" y1="-12" x2="0" y2="-12" stroke="#000000" stroke-width="0" data-prov="781ef3842ebea010cbefab514c733440" data-source-kind="2" data-kind="stroke"/>
<line x1="4.15" y1="-13" x2="4.15" y2="-9.5" stroke="#000000" stroke-width="0.12" data-prov="8fedf07e00164403db044570899f2550" data-source-kind="0" data-kind="stroke"/>
<line x1="2.7" y1="-13" x2="4.4807" y2="-13" stroke="#000000" stroke-width="0.13" data-prov="32b5060f271a3aa21b504bfc3160af6d" data-source-kind="1" data-kind="stroke"/>
<line x1="5.75" y1="-9.5" x2="5.75" y2="-6" stroke="#000000" stroke-width="0.12" data-prov="19a0fc032dbfc94ac8b2801dfdeaa658" data-source-kind="0" data-kind="stroke"/>
<line x1="7.35" y1="-6" x2="7.35" y2="-2.5" stroke="#000000" stroke-width="0.12" data-prov="e4e5f1717e87111231d31ba493aaac57" data-source-kind="0" data-kind="stroke"/>
<line x1="5.9" y1="-7" x2="7.6807" y2="-7" stroke="#000000" stroke-width="0.13" data-prov="1caed515110c4415278d31cc474bf065" data-source-kind="1" data-kind="stroke"/>
<line x1="5.9" y1="-6" x2="7.6807" y2="-6" stroke="#000000" stroke-width="0.13" data-prov="1189a8cf5e7e1526a44f3cf89e0b160e" data-source-kind="1" data-kind="stroke"/>
<line x1="8.95" y1="-9.5" x2="8.95" y2="-6" stroke="#000000" stroke-width="0.12" data-prov="f230acdf26cd79ad3ba5cd02002fa1f9" data-source-kind="0" data-kind="stroke"/>
<path d="M 5.2 -7.3 C 5.8667 -6.2333 6.5333 -6.2333 7.2 -7.3" fill="none" stroke="#000000" stroke-width="0.12" data-prov="0165993515166bea8f7cada46e27c86f" data-source-kind="11" data-kind="curve"/>
<path d="M1.504 1.66C1.496 1.708 1.504 1.712 1.528 1.736C1.96 2.14 2.288 2.648 2.288 3.26C2.288 3.608 2.192 3.952 2.028 4.192C1.968 4.28 1.864 4.392 1.82 4.392C1.764 4.392 1.64 4.288 1.56 4.2C1.264 3.872 1.168 3.372 1.168 2.956C1.168 2.724 1.196 2.464 1.224 2.3C1.232 2.252 1.236 2.244 1.188 2.204C0.612 1.728 0 1.156 0 0.348C0 -0.348 0.476 -1.008 1.456 -1.008C1.548 -1.008 1.652 -1 1.732 -0.984C1.776 -0.976 1.784 -0.972 1.792 -1.02C1.84 -1.288 1.9 -1.636 1.9 -1.824C1.9 -2.416 1.5 -2.488 1.264 -2.488C1.048 -2.488 0.944 -2.424 0.944 -2.372C0.944 -2.344 0.98 -2.332 1.072 -2.304C1.196 -2.268 1.34 -2.16 1.34 -1.928C1.34 -1.708 1.2 -1.52 0.956 -1.52C0.688 -1.52 0.528 -1.732 0.528 -1.98C0.528 -2.24 0.684 -2.632 1.288 -2.632C1.556 -2.632 2.076 -2.512 2.076 -1.832C2.076 -1.604 2.004 -1.224 1.96 -0.976C1.952 -0.928 1.956 -0.932 2.012 -0.908C2.416 -0.748 2.684 -0.408 2.684 0.044C2.684 0.556 2.308 1.008 1.72 1.008C1.616 1.008 1.616 1.008 1.604 1.08ZM1.88 3.772C2.012 3.772 2.12 3.664 2.12 3.444C2.12 3 1.74 2.64 1.424 2.364C1.396 2.34 1.38 2.344 1.372 2.396C1.356 2.5 1.348 2.636 1.348 2.764C1.348 3.388 1.636 3.772 1.88 3.772ZM1.444 1.048C1.456 0.972 1.456 0.976 1.384 0.952C1.032 0.832 0.804 0.516 0.804 0.176C0.804 -0.184 0.992 -0.44 1.264 -0.532C1.296 -0.544 1.344 -0.556 1.372 -0.556C1.404 -0.556 1.42 -0.536 1.42 -0.512C1.42 -0.484 1.388 -0.472 1.36 -0.46C1.192 -0.388 1.072 -0.216 1.072 -0.032C1.072 0.196 1.228 0.368 1.472 0.436C1.536 0.452 1.544 0.448 1.552 0.404L1.752 -0.788C1.76 -0.832 1.756 -0.832 1.696 -0.844C1.632 -0.856 1.552 -0.864 1.472 -0.864C0.772 -0.864 0.32 -0.476 0.32 0.08C0.32 0.316 0.36 0.632 0.692 1.008C0.932 1.276 1.116 1.424 1.304 1.576C1.344 1.608 1.352 1.604 1.36 1.56ZM1.72 0.412C1.712 0.46 1.716 0.472 1.764 0.468C2.088 0.44 2.356 0.168 2.356 -0.184C2.356 -0.436 2.204 -0.64 1.98 -0.752C1.932 -0.776 1.924 -0.776 1.916 -0.728Z" transform="translate(0 1)" fill="#000000" data-prov="e81b0f9cc6ccb1d0209d51b1d9797db5" data-source-kind="4" data-glyph="gClef" data-class="clef"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(3 -1)" fill="#000000" data-prov="9b3ac956eb2deb3e538d9b1942c6ae97" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(4.6 -4.5)" fill="#000000" data-prov="751a5a693a87d6c1a15a8dfc3eda8102" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(6.2 -8)" fill="#000000" data-prov="130e9eddac04d8c2fb7373aae2c3b458" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(7.8 -4.5)" fill="#000000" data-prov="e6f9d102cb9512c808d4bff5a3560b34" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M1.504 1.66C1.496 1.708 1.504 1.712 1.528 1.736C1.96 2.14 2.288 2.648 2.288 3.26C2.288 3.608 2.192 3.952 2.028 4.192C1.968 4.28 1.864 4.392 1.82 4.392C1.764 4.392 1.64 4.288 1.56 4.2C1.264 3.872 1.168 3.372 1.168 2.956C1.168 2.724 1.196 2.464 1.224 2.3C1.232 2.252 1.236 2.244 1.188 2.204C0.612 1.728 0 1.156 0 0.348C0 -0.348 0.476 -1.008 1.456 -1.008C1.548 -1.008 1.652 -1 1.732 -0.984C1.776 -0.976 1.784 -0.972 1.792 -1.02C1.84 -1.288 1.9 -1.636 1.9 -1.824C1.9 -2.416 1.5 -2.488 1.264 -2.488C1.048 -2.488 0.944 -2.424 0.944 -2.372C0.944 -2.344 0.98 -2.332 1.072 -2.304C1.196 -2.268 1.34 -2.16 1.34 -1.928C1.34 -1.708 1.2 -1.52 0.956 -1.52C0.688 -1.52 0.528 -1.732 0.528 -1.98C0.528 -2.24 0.684 -2.632 1.288 -2.632C1.556 -2.632 2.076 -2.512 2.076 -1.832C2.076 -1.604 2.004 -1.224 1.96 -0.976C1.952 -0.928 1.956 -0.932 2.012 -0.908C2.416 -0.748 2.684 -0.408 2.684 0.044C2.684 0.556 2.308 1.008 1.72 1.008C1.616 1.008 1.616 1.008 1.604 1.08ZM1.88 3.772C2.012 3.772 2.12 3.664 2.12 3.444C2.12 3 1.74 2.64 1.424 2.364C1.396 2.34 1.38 2.344 1.372 2.396C1.356 2.5 1.348 2.636 1.348 2.764C1.348 3.388 1.636 3.772 1.88 3.772ZM1.444 1.048C1.456 0.972 1.456 0.976 1.384 0.952C1.032 0.832 0.804 0.516 0.804 0.176C0.804 -0.184 0.992 -0.44 1.264 -0.532C1.296 -0.544 1.344 -0.556 1.372 -0.556C1.404 -0.556 1.42 -0.536 1.42 -0.512C1.42 -0.484 1.388 -0.472 1.36 -0.46C1.192 -0.388 1.072 -0.216 1.072 -0.032C1.072 0.196 1.228 0.368 1.472 0.436C1.536 0.452 1.544 0.448 1.552 0.404L1.752 -0.788C1.76 -0.832 1.756 -0.832 1.696 -0.844C1.632 -0.856 1.552 -0.864 1.472 -0.864C0.772 -0.864 0.32 -0.476 0.32 0.08C0.32 0.316 0.36 0.632 0.692 1.008C0.932 1.276 1.116 1.424 1.304 1.576C1.344 1.608 1.352 1.604 1.36 1.56ZM1.72 0.412C1.712 0.46 1.716 0.472 1.764 0.468C2.088 0.44 2.356 0.168 2.356 -0.184C2.356 -0.436 2.204 -0.64 1.98 -0.752C1.932 -0.776 1.924 -0.776 1.916 -0.728Z" transform="translate(0 -11)" fill="#000000" data-prov="380c7e6f256e62d482135a6342d18380" data-source-kind="4" data-glyph="gClef" data-class="clef"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(3 -13)" fill="#000000" data-prov="38b6271edbb50b409f119eff31d0faa9" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(4.6 -9.5)" fill="#000000" data-prov="b2c29b264d8593df8589608aee4d8465" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(6.2 -6)" fill="#000000" data-prov="a6892ec5562df412ce4bdf3bc118e5e9" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.388 -0.5C0.744 -0.5 1.18 -0.172 1.18 0.168C1.18 0.372 1.02 0.5 0.792 0.5C0.352 0.5 0 0.176 0 -0.168C0 -0.376 0.172 -0.5 0.388 -0.5Z" transform="translate(7.8 -9.5)" fill="#000000" data-prov="d8123de74f57fff5bdc35478e8ec8e9e" data-source-kind="1" data-glyph="noteheadBlack" data-class="notehead"/>
<path d="M0.144 0V4H0V0ZM0.912 4H0.412V0H0.912Z" transform="translate(10.9 0)" fill="#000000" data-prov="ed49137c7e716c68d78a85b89b50500a" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
<path d="M0.144 0V4H0V0ZM0.912 4H0.412V0H0.912Z" transform="translate(10.9 -12)" fill="#000000" data-prov="7171ecca2c439b3c03c959bdad56cf08" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
</g>
</g>
</svg>

After

Width:  |  Height:  |  Size: 14 KiB

View File

@ -60,6 +60,157 @@ fn quarter(eid: EventId, voice: VoiceId, pid: PitchId, index: i64) -> Event {
})
}
/// A C pitched quarter-note at `octave`, at musical position `index/4`.
fn c_at(eid: EventId, voice: VoiceId, pid: PitchId, index: i64, octave: i8) -> Event {
Event::Pitched(epiphany_core::PitchedEvent {
id: eid,
voice,
position: EventPosition::Musical(MusicalPosition(RationalTime::new(index, 4).unwrap())),
duration: EventDuration::Musical(MusicalDuration(RationalTime::new(1, 4).unwrap())),
pitches: vec![IdentifiedPitch {
id: pid,
pitch: Pitch {
scale_position: ScalePosition {
space: PitchSpaceId::new("cmn-12"),
position: PitchSpacePosition::Cmn {
nominal: CmnNominal::C,
alteration: 0,
octave,
},
},
acoustic: AcousticPitch {
tuning: TuningReference::Inherit,
realization: AcousticRealization::Implicit,
},
},
}],
articulations: vec![],
dynamic: None,
ornaments: vec![],
stem: StemConfiguration,
grace: None,
})
}
/// A one-measure, TWO-staff (treble/treble) metric score whose staves carry
/// vertically extreme content: the top staff dips to low ledger notes (down to
/// C2) while the bottom staff climbs to high ledger notes (up to C6) under a
/// slur that arcs further above them. At the engraver's default *fixed* staff
/// pitch the two staves' content nearly collides — the inter-staff pressure case
/// the vertical spring solve must separate. Invariant-clean.
pub fn two_staff_close_content(seed: u64) -> Score {
let mut rng = SplitMix64::new(seed ^ 0x0002_57AF_F123);
let replica =
ReplicaId::from_entropy(rng.next_u64().to_le_bytes()).unwrap_or(ReplicaId(0x2ADF));
let mut idc = IdentityContext::new(replica);
let top_staff: StaffId = idc.mint();
let bottom_staff: StaffId = idc.mint();
let instrument: InstrumentId = idc.mint();
let region_id: RegionId = idc.mint();
let top_instance: StaffInstanceId = idc.mint();
let bottom_instance: StaffInstanceId = idc.mint();
let top_voice: VoiceId = idc.mint();
let bottom_voice: VoiceId = idc.mint();
let mut arena = EventArena::new();
// Top staff descends into low ledgers; bottom staff climbs into high ones.
let mut top_v = Voice::user(top_voice);
let mut bot_v = Voice::user(bottom_voice);
let mut bot_events: Vec<EventId> = Vec::new();
for (i, oct) in [4i8, 3, 2, 3].into_iter().enumerate() {
let (eid, pid): (EventId, PitchId) = (idc.mint(), idc.mint());
arena
.insert(c_at(eid, top_voice, pid, i as i64, oct))
.unwrap();
top_v.events.push(eid);
}
for (i, oct) in [4i8, 5, 6, 5].into_iter().enumerate() {
let (eid, pid): (EventId, PitchId) = (idc.mint(), idc.mint());
arena
.insert(c_at(eid, bottom_voice, pid, i as i64, oct))
.unwrap();
bot_v.events.push(eid);
bot_events.push(eid);
}
let measure = |id: MeasureId| Measure {
id,
start: TimeAnchor::Region {
id: region_id,
edge: RegionEdge::Start,
offset: AnchorOffset::Zero,
},
time_signature: None,
explicit_number: Some(1),
number_visibility: Default::default(),
};
let mut top_inst = StaffInstance::new(top_instance, top_staff);
top_inst.voices.push(top_v);
top_inst.measures.push(measure(idc.mint()));
let mut bot_inst = StaffInstance::new(bottom_instance, bottom_staff);
bot_inst.voices.push(bot_v);
bot_inst.measures.push(measure(idc.mint()));
// A slur over the bottom staff's high notes, arcing further up — extra
// upward extent that sharpens the collision with the top staff.
let mut cross_cutting = CrossCuttingRegistry::default();
cross_cutting.slurs.push(Slur {
id: idc.mint::<SlurId>(),
start_event: bot_events[1],
end_event: bot_events[3],
kind: SlurKind::Legato,
curvature_override: None,
style: SpanStyle::default(),
});
let region = epiphany_core::Region {
id: region_id,
time_model: RegionTimeModel::Metric(MetricTimeModel::default()),
content: RegionContent::StaffBased(StaffBasedContent {
staff_instances: vec![top_inst, bot_inst],
..Default::default()
}),
time_extent: TimeExtent {
start: TimeAnchor::WallClock {
time: WallClockTime(0),
},
end: TimeAnchor::WallClock {
time: WallClockTime(10_000_000),
},
},
staff_extent: StaffExtent {
staves: vec![top_staff, bottom_staff],
},
local_tempo_map: None,
permits_spanning_slurs: false,
};
let staff = |id: StaffId, name: &str| Staff {
id,
name: String::from(name),
abbreviation: None,
instrument,
default_staff_lines: StaffLineConfiguration::default(),
group: None,
default_clef: epiphany_core::Clef::treble(),
};
let mut score = Score::empty(idc.clone());
score.identity = idc;
score.instruments = vec![epiphany_core::Instrument::new(
instrument,
String::from("Keyboard"),
)];
score.staves = vec![staff(top_staff, "Right"), staff(bottom_staff, "Left")];
score.events = arena;
score.cross_cutting = cross_cutting;
score.canvas = Canvas {
regions: vec![region],
..Default::default()
};
score
}
/// A 10-measure, single-staff, single-voice metric score with 40 quarter notes
/// (four per measure), plus a tie, a spanner, a marker, and a chord symbol. The
/// QUICKSTART layout hand-off case. Invariant-clean (the returned graph passes
@ -325,6 +476,21 @@ mod tests {
assert_eq!(s.cross_cutting.chord_symbols.len(), 1);
}
#[test]
fn two_staff_close_content_is_invariant_clean_and_two_staves() {
let s = two_staff_close_content(1);
let v = check_invariants(&s);
assert!(v.is_empty(), "two-staff fixture has violations: {v:?}");
assert_eq!(s.staves.len(), 2, "two staves");
assert_eq!(
s.canvas.regions[0].staff_instances().len(),
2,
"two staff instances in the region"
);
assert_eq!(s.events.len(), 8, "four notes per staff");
assert_eq!(s.cross_cutting.slurs.len(), 1, "a slur over the high notes");
}
#[test]
fn repeat_fixture_is_invariant_clean_and_carries_three_repeats() {
let s = ten_measure_with_repeats(1);