Inter-staff review fix: make staff attribution y-aware (stems tore off)
Self-review of the inter-staff solve found a real bug: stroke->staff attribution reused component_glyph, whose fallback picks the nearest glyph by X ALONE. That is correct for a SLOT — both staves of a system share their x columns, hence their spring slots, so the horizontal delta is the same either way — but wrong for a STAFF: it handed a lower-staff stem to the UPPER staff's notehead. The stem then kept the wrong vertical shift and tore off its own head (measured worst stem->notehead distance 5.837 on the two-staff fixture vs 1.150, the stem x-inset, on the single-staff one), and it polluted the upper staff's content extent, inflating the computed gap. Fix: the staff attribution uses a 2-D nearest for that fallback (a ledger still resolves via owning_glyph's shared Pitch source; a staff line via its Staff source). component_glyph is unchanged and still serves the horizontal path. Also corrected: staff-attributed primitives now contribute their y ONLY through the shifted path (Extent::add_x for x, add_y for the shifted staff extent), so a lower staff's UNSHIFTED content can no longer inflate a system's max_y. Dead Extent::add removed. The corrected attribution yields a smaller, more accurate separation (two-staff view_box height 36.1 -> 31.1). Regression multi_staff_stems_stay_on_their_own_ staff (verified to fail at 5.837 without the fix). Only the two-staff engrave golden churned; single-staff goldens byte-stable. 948 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:
parent
3978225e06
commit
4132a7ac05
|
|
@ -709,13 +709,29 @@ single-staff score, with no inter-staff pair, is byte-identical).
|
|||
|
||||
**Attribution (`vertical_band` + owning-glyph).** Every resolved primitive is
|
||||
attributed to its owning staff: a glyph via its `vertical_band`
|
||||
(`VerticalBandKind::Staff` → `StaffId`); a stem or ledger via its notehead
|
||||
(`component_glyph` → that glyph's band); a staff line via its `Staff`
|
||||
provenance source; a slur via the notehead nearest its start endpoint. Spacing
|
||||
is horizontal-only, so a primitive's y is unchanged from the source frame the
|
||||
attribution reads, and the resolved and source indices line up. (The geometric
|
||||
`round(-y / pitch)` alternative was rejected: an extreme ledgered note on the
|
||||
top or bottom staff rounds to a non-existent neighbour.)
|
||||
(`VerticalBandKind::Staff` → `StaffId`); a ledger via its notehead
|
||||
(`owning_glyph`, a shared `Pitch` source); a **stem** — which has no same-source
|
||||
glyph — via the glyph nearest its BASE point *in two dimensions*; a staff line
|
||||
via its `Staff` provenance source; a slur via the notehead nearest its start
|
||||
endpoint. Spacing is horizontal-only, so a primitive's y is unchanged from the
|
||||
source frame the attribution reads, and the resolved and source indices line up.
|
||||
(The geometric `round(-y / pitch)` alternative was rejected: an extreme ledgered
|
||||
note on the top or bottom staff rounds to a non-existent neighbour.)
|
||||
|
||||
**Why staff attribution must be y-aware (review fix).** The first cut reused
|
||||
`component_glyph`, whose fallback picks the nearest glyph **by x alone**. That is
|
||||
right for a *slot* — both staves of a system share their x columns, hence their
|
||||
spring slots, so the horizontal delta is the same either way — but it is wrong
|
||||
for a *staff*: it handed a lower-staff stem to the UPPER staff's notehead, so the
|
||||
stem kept the wrong vertical shift and tore off its own head by several staff
|
||||
spaces (and polluted the upper staff's content extent, inflating the computed
|
||||
gap). The staff attribution now uses a 2-D nearest for that fallback.
|
||||
`component_glyph` is unchanged and still serves the horizontal path. Locked by
|
||||
`multi_staff_stems_stay_on_their_own_staff` (a stem's base sits at its notehead
|
||||
on both the single- and multi-staff fixtures). A related correction: staff-
|
||||
attributed primitives contribute their y ONLY through the shifted path
|
||||
(`Extent::add_x` for x, `add_y` for the shifted staff extent), so a lower staff's
|
||||
unshifted content can no longer inflate a system's `max_y`.
|
||||
|
||||
**The solve.** Per system, per staff, the real content y-extent is collected
|
||||
(glyphs, strokes, curves — ledgers and slurs included, not just noteheads). The
|
||||
|
|
|
|||
|
|
@ -81,7 +81,7 @@ use epiphany_layout_ir::{
|
|||
SynthesisKind, SynthesisRegistryId, VerticalBand, VerticalBandId, VerticalBandKind,
|
||||
};
|
||||
|
||||
use crate::{component_glyph, owning_glyph};
|
||||
use crate::owning_glyph;
|
||||
|
||||
/// The registry id for the engraver's **system-continuation synthesis**: the
|
||||
/// segment of a region-spanning stroke (a staff line) that casting-off places
|
||||
|
|
@ -353,22 +353,23 @@ impl Extent {
|
|||
}
|
||||
}
|
||||
|
||||
fn add(&mut self, x0: f32, y0: f32, x1: f32, y1: f32) {
|
||||
if [x0, y0, x1, y1].iter().all(|v| v.is_finite()) {
|
||||
self.min_x = self.min_x.min(x0.min(x1));
|
||||
self.max_x = self.max_x.max(x0.max(x1));
|
||||
self.min_y = self.min_y.min(y0.min(y1));
|
||||
self.max_y = self.max_y.max(y0.max(y1));
|
||||
self.any = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend only the vertical extent (the inter-staff solve grows a system's
|
||||
/// height by shifting staves apart, without touching its x-span).
|
||||
fn add_y(&mut self, y0: f32, y1: f32) {
|
||||
if y0.is_finite() && y1.is_finite() {
|
||||
self.min_y = self.min_y.min(y0.min(y1));
|
||||
self.max_y = self.max_y.max(y0.max(y1));
|
||||
self.any = true;
|
||||
}
|
||||
}
|
||||
|
||||
/// Extend only the horizontal extent. Staff-attributed content contributes
|
||||
/// its y through the inter-staff solve (SHIFTED), never here.
|
||||
fn add_x(&mut self, x0: f32, x1: f32) {
|
||||
if x0.is_finite() && x1.is_finite() {
|
||||
self.min_x = self.min_x.min(x0.min(x1));
|
||||
self.max_x = self.max_x.max(x0.max(x1));
|
||||
self.any = true;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -651,12 +652,28 @@ pub(crate) fn cast_off(
|
|||
.collect();
|
||||
let glyph_band_staff = |g: &GlyphObject| band_to_staff.get(&g.vertical_band).copied();
|
||||
let glyph_staff_of: Vec<Option<StaffId>> = input.glyphs.iter().map(glyph_band_staff).collect();
|
||||
// The glyph nearest a point in TWO dimensions. Attribution to a *staff* must
|
||||
// be y-aware: `component_glyph`'s horizontal fallback picks the nearest glyph
|
||||
// by x alone, which is right for a slot (both staves of a system share their
|
||||
// x columns, hence their slots) but would hand a stem to the ADJACENT staff.
|
||||
let nearest_glyph = |x: f32, y: f32| -> Option<&GlyphObject> {
|
||||
input.glyphs.iter().min_by(|a, b| {
|
||||
let d = |g: &GlyphObject| (g.baseline.x.0 - x).powi(2) + (g.baseline.y.0 - y).powi(2);
|
||||
d(a).total_cmp(&d(b))
|
||||
})
|
||||
};
|
||||
let stroke_staff_of: Vec<Option<StaffId>> = input
|
||||
.strokes
|
||||
.iter()
|
||||
.map(|s| match s.provenance.source {
|
||||
// A staff line names its staff outright.
|
||||
TypedObjectId::Staff(st) => Some(st),
|
||||
_ => component_glyph(s, &input.glyphs).and_then(glyph_band_staff),
|
||||
// A ledger shares its notehead's `Pitch` source (`owning_glyph`);
|
||||
// a stem has no same-source glyph, so it takes the staff of the
|
||||
// glyph nearest its BASE (`from`, which sits at the notehead).
|
||||
_ => owning_glyph(s, &input.glyphs)
|
||||
.or_else(|| nearest_glyph(s.from.x.0, s.from.y.0))
|
||||
.and_then(glyph_band_staff),
|
||||
})
|
||||
.collect();
|
||||
let curve_staff_of: Vec<Option<StaffId>> = input
|
||||
|
|
@ -706,13 +723,14 @@ pub(crate) fn cast_off(
|
|||
y + glyph.bounding_box.bottom.0,
|
||||
y + glyph.bounding_box.top.0,
|
||||
);
|
||||
extents[s].add(
|
||||
extents[s].add_x(
|
||||
x + glyph.bounding_box.left.0,
|
||||
lo_y,
|
||||
x + glyph.bounding_box.right.0,
|
||||
hi_y,
|
||||
);
|
||||
into_staff(&mut staff_ext, s, glyph_staff_of[g], lo_y, hi_y);
|
||||
match glyph_staff_of[g] {
|
||||
Some(_) => into_staff(&mut staff_ext, s, glyph_staff_of[g], lo_y, hi_y),
|
||||
None => extents[s].add_y(lo_y, hi_y),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -727,8 +745,11 @@ pub(crate) fn cast_off(
|
|||
};
|
||||
for (s, from, to) in segs {
|
||||
let (lo_y, hi_y) = (from.y.0.min(to.y.0) - half, from.y.0.max(to.y.0) + half);
|
||||
extents[s].add(from.x.0 - half, lo_y, to.x.0 + half, hi_y);
|
||||
into_staff(&mut staff_ext, s, staff, lo_y, hi_y);
|
||||
extents[s].add_x(from.x.0 - half, to.x.0 + half);
|
||||
match staff {
|
||||
Some(_) => into_staff(&mut staff_ext, s, staff, lo_y, hi_y),
|
||||
None => extents[s].add_y(lo_y, hi_y),
|
||||
}
|
||||
if is_staff_line {
|
||||
if let Some(st) = staff {
|
||||
staff_ref
|
||||
|
|
@ -749,8 +770,11 @@ pub(crate) fn cast_off(
|
|||
};
|
||||
for (s, cp) in segs {
|
||||
for p in cp {
|
||||
extents[s].add(p.x.0 - half, p.y.0 - half, p.x.0 + half, p.y.0 + half);
|
||||
into_staff(&mut staff_ext, s, staff, p.y.0 - half, p.y.0 + half);
|
||||
extents[s].add_x(p.x.0 - half, p.x.0 + half);
|
||||
match staff {
|
||||
Some(_) => into_staff(&mut staff_ext, s, staff, p.y.0 - half, p.y.0 + half),
|
||||
None => extents[s].add_y(p.y.0 - half, p.y.0 + half),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2233,6 +2233,56 @@ mod tests {
|
|||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_staff_stems_stay_on_their_own_staff() {
|
||||
use epiphany_layout_ir::{to_constrained, to_logical};
|
||||
// Review-found bug: the inter-staff attribution reused `component_glyph`,
|
||||
// whose fallback picks the nearest glyph by X ALONE — correct for a slot
|
||||
// (both staves of a system share their x columns, hence their slots) but
|
||||
// it handed a stem to the ADJACENT staff, so the stem kept that staff's
|
||||
// vertical shift and tore off its own notehead. Attribution is now
|
||||
// y-aware. Every stem's base must still sit at its notehead, offset only
|
||||
// by the stem's x inset — on the single- AND multi-staff fixtures.
|
||||
let worst = |score: epiphany_core::Score| -> f32 {
|
||||
let r = Engraver::default().solve(
|
||||
&to_constrained(&to_logical(&score)),
|
||||
&SolverConfig::default(),
|
||||
);
|
||||
let heads: Vec<(f32, f32)> = r
|
||||
.layout
|
||||
.glyphs
|
||||
.iter()
|
||||
.filter(|g| g.glyph.as_str().starts_with("notehead"))
|
||||
.map(|g| (g.position.x.0, g.position.y.0))
|
||||
.collect();
|
||||
r.layout
|
||||
.strokes
|
||||
.iter()
|
||||
.filter(|st| {
|
||||
(st.from.x.0 - st.to.x.0).abs() < 1e-4 && (st.from.y.0 - st.to.y.0).abs() > 1e-3
|
||||
})
|
||||
.map(|st| {
|
||||
heads
|
||||
.iter()
|
||||
.map(|(hx, hy)| {
|
||||
((hx - st.from.x.0).powi(2) + (hy - st.from.y.0).powi(2)).sqrt()
|
||||
})
|
||||
.fold(f32::INFINITY, f32::min)
|
||||
})
|
||||
.fold(0.0_f32, f32::max)
|
||||
};
|
||||
let single = worst(epiphany_testkit::fixtures::ten_measure_single_staff(1));
|
||||
let multi = worst(epiphany_testkit::fixtures::two_staff_close_content(1));
|
||||
assert!(
|
||||
single < 1.5,
|
||||
"single-staff stems stay on their heads: {single}"
|
||||
);
|
||||
assert!(
|
||||
multi < 1.5,
|
||||
"multi-staff stems stay on their OWN staff's heads: {multi}"
|
||||
);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn inter_staff_solve_separates_colliding_staves() {
|
||||
use epiphany_layout_ir::{to_constrained, to_logical};
|
||||
|
|
|
|||
|
|
@ -8,7 +8,7 @@ provenance_count=54
|
|||
layer_count=1
|
||||
hard_constraint_count=18
|
||||
xml_well_formed=true
|
||||
view_box=[5.5 -41.584576 17.379084 36.084]
|
||||
view_box=[5.5 -36.58458 17.379084 31.084002]
|
||||
class_counts:
|
||||
barline=2
|
||||
clef=2
|
||||
|
|
|
|||
|
|
@ -1,28 +1,28 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="173.7908" height="360.84" viewBox="0 0 17.3791 36.084">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="173.7908" height="310.84" viewBox="0 0 17.3791 31.084">
|
||||
<!-- 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="-25.9526" x2="8.6599" y2="-25.9526" stroke="#000000" stroke-width="0" data-prov="5ff1785b2e5e554c42cff8d78dd57953" data-source-kind="6" data-kind="stroke"/>
|
||||
<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="-37.9526" x2="20.2543" y2="-37.9526" stroke="#000000" stroke-width="0.13" data-prov="c6afc2060e4ee437d03c460c5e51edb0" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-36.9526" x2="20.2543" y2="-36.9526" stroke="#000000" stroke-width="0.13" data-prov="fc03fb2cca3c3f5d6276b60b1ff83b72" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-35.9526" x2="20.2543" y2="-35.9526" stroke="#000000" stroke-width="0.13" data-prov="4ac3502112246f2950bf9ba00346e839" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-34.9526" x2="20.2543" y2="-34.9526" stroke="#000000" stroke-width="0.13" data-prov="dbcbf5fb791e00972d5a014eb0897966" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-33.9526" x2="20.2543" y2="-33.9526" stroke="#000000" stroke-width="0.13" data-prov="0c940e546e084c0e0c76dc5b5d4cc29f" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="8.6599" y1="-25.9526" x2="8.6599" y2="-25.9526" stroke="#000000" stroke-width="0" data-prov="dec48b26ccf8d32aaef3b0d78c728ac1" data-source-kind="2" data-kind="stroke"/>
|
||||
<line x1="13.0944" y1="-26.9526" x2="13.0944" y2="-23.4526" stroke="#000000" stroke-width="0.12" data-prov="2605e711923a6304409ca2b5627aed7e" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-32.9526" x2="20.2543" y2="-32.9526" stroke="#000000" stroke-width="0.13" data-prov="c6afc2060e4ee437d03c460c5e51edb0" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-31.9526" x2="20.2543" y2="-31.9526" stroke="#000000" stroke-width="0.13" data-prov="fc03fb2cca3c3f5d6276b60b1ff83b72" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-30.9526" x2="20.2543" y2="-30.9526" stroke="#000000" stroke-width="0.13" data-prov="4ac3502112246f2950bf9ba00346e839" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-29.9526" x2="20.2543" y2="-29.9526" stroke="#000000" stroke-width="0.13" data-prov="dbcbf5fb791e00972d5a014eb0897966" data-source-kind="3" data-kind="stroke"/>
|
||||
<line x1="7.565" y1="-28.9526" x2="20.2543" y2="-28.9526" 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="-30.4526" x2="15.1751" y2="-26.9526" stroke="#000000" stroke-width="0.12" data-prov="b2df28c1e46d5eb33759d335032e7d07" data-source-kind="0" 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="-33.9526" x2="17.2558" y2="-30.4526" stroke="#000000" stroke-width="0.12" data-prov="b625587ff114949abad6d0b181fbfd20" data-source-kind="0" 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"/>
|
||||
|
|
@ -31,32 +31,32 @@
|
|||
<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="-30.4526" x2="19.3364" y2="-26.9526" stroke="#000000" stroke-width="0.12" data-prov="7cc4fe5d82ef7386da10c5cef6508856" data-source-kind="0" 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="-37.9526" x2="8.6599" y2="-37.9526" stroke="#000000" stroke-width="0" data-prov="781ef3842ebea010cbefab514c733440" data-source-kind="2" data-kind="stroke"/>
|
||||
<line x1="13.0944" y1="-38.9526" x2="13.0944" y2="-35.4526" stroke="#000000" stroke-width="0.12" data-prov="8fedf07e00164403db044570899f2550" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="11.6444" y1="-38.9526" x2="13.4251" y2="-38.9526" stroke="#000000" stroke-width="0.13" data-prov="32b5060f271a3aa21b504bfc3160af6d" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="15.1751" y1="-35.4526" x2="15.1751" y2="-31.9526" stroke="#000000" stroke-width="0.12" data-prov="19a0fc032dbfc94ac8b2801dfdeaa658" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="17.2558" y1="-31.9526" x2="17.2558" y2="-28.4526" stroke="#000000" stroke-width="0.12" data-prov="e4e5f1717e87111231d31ba493aaac57" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="15.8058" y1="-32.9526" x2="17.5864" y2="-32.9526" stroke="#000000" stroke-width="0.13" data-prov="1caed515110c4415278d31cc474bf065" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="15.8058" y1="-31.9526" x2="17.5864" y2="-31.9526" stroke="#000000" stroke-width="0.13" data-prov="1189a8cf5e7e1526a44f3cf89e0b160e" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="19.3364" y1="-35.4526" x2="19.3364" y2="-31.9526" stroke="#000000" stroke-width="0.12" data-prov="f230acdf26cd79ad3ba5cd02002fa1f9" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="8.6599" y1="-32.9526" x2="8.6599" y2="-32.9526" stroke="#000000" stroke-width="0" data-prov="781ef3842ebea010cbefab514c733440" data-source-kind="2" data-kind="stroke"/>
|
||||
<line x1="13.0944" y1="-33.9526" x2="13.0944" y2="-30.4526" stroke="#000000" stroke-width="0.12" data-prov="8fedf07e00164403db044570899f2550" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="11.6444" y1="-33.9526" x2="13.4251" y2="-33.9526" stroke="#000000" stroke-width="0.13" data-prov="32b5060f271a3aa21b504bfc3160af6d" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="15.1751" y1="-30.4526" x2="15.1751" y2="-26.9526" stroke="#000000" stroke-width="0.12" data-prov="19a0fc032dbfc94ac8b2801dfdeaa658" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="17.2558" y1="-26.9526" x2="17.2558" y2="-23.4526" stroke="#000000" stroke-width="0.12" data-prov="e4e5f1717e87111231d31ba493aaac57" data-source-kind="0" data-kind="stroke"/>
|
||||
<line x1="15.8058" y1="-27.9526" x2="17.5864" y2="-27.9526" stroke="#000000" stroke-width="0.13" data-prov="1caed515110c4415278d31cc474bf065" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="15.8058" y1="-26.9526" x2="17.5864" y2="-26.9526" stroke="#000000" stroke-width="0.13" data-prov="1189a8cf5e7e1526a44f3cf89e0b160e" data-source-kind="1" data-kind="stroke"/>
|
||||
<line x1="19.3364" y1="-30.4526" x2="19.3364" y2="-26.9526" 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 -36.9526)" 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 -38.9526)" 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 -35.4526)" 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 -31.9526)" 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 -35.4526)" fill="#000000" data-prov="d8123de74f57fff5bdc35478e8ec8e9e" 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 -31.9526)" 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 -33.9526)" 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 -30.4526)" 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 -26.9526)" 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 -30.4526)" 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 -37.9526)" fill="#000000" data-prov="7171ecca2c439b3c03c959bdad56cf08" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
|
||||
<path d="M0.144 0V4H0V0ZM0.912 4H0.412V0H0.912Z" transform="translate(19.9671 -32.9526)" fill="#000000" data-prov="7171ecca2c439b3c03c959bdad56cf08" data-source-kind="9" data-glyph="barlineFinal" data-class="barline"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 15 KiB |
Loading…
Reference in New Issue