From 04f2da6a53cc8f42b31704aba9d98f707c651b92 Mon Sep 17 00:00:00 2001 From: Marc Sabatella Date: Tue, 21 May 2019 23:28:43 -0600 Subject: [PATCH 1/2] fix #289492: bad layout of slurs with cross-staff beams --- libmscore/slur.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/libmscore/slur.cpp b/libmscore/slur.cpp index 40826a5eb76a..a30f28d78113 100644 --- a/libmscore/slur.cpp +++ b/libmscore/slur.cpp @@ -701,7 +701,7 @@ void Slur::slurPos(SlurPos* sp) if (scr->up() == _up && stem1 && sc->hook()) { sa1 = SlurAnchor::STEM; // if end chord is in same direction, link end of slur to stem too - if (ecr->up() == scr->up() && stem2) + if (ecr->up() == scr->up() && stem2 && (!ecr->beam() || !ecr->beam()->cross())) sa2 = SlurAnchor::STEM; } @@ -773,7 +773,11 @@ void Slur::slurPos(SlurPos* sp) if (stem1) { //sc not null Beam* beam1 = sc->beam(); - if (beam1 && (beam1->elements().back() != sc) && (sc->up() == _up)) { + if (beam1 && beam1->cross()) { + // TODO: stem direction is not finalized, so we cannot use it here + yo = fixArticulations(yo, sc, __up, false); + } + else if (beam1 && (beam1->elements().back() != sc) && (sc->up() == _up)) { // start chord is beamed but not the last chord of beam group // and slur direction is same as start chord (stem side) @@ -873,7 +877,11 @@ void Slur::slurPos(SlurPos* sp) if (stem2) { //ec can't be null Beam* beam2 = ec->beam(); - if ((stemPos && (scr->up() == ec->up())) + if (beam2 && beam2->cross()) { + // TODO: stem direction is not finalized, so we cannot use it here + yo = fixArticulations(yo, ec, __up, false); + } + else if ((stemPos && (scr->up() == ec->up())) || (beam2 && (!beam2->elements().empty()) && (beam2->elements().front() != ec) @@ -1073,6 +1081,12 @@ SpannerSegment* Slur::layoutSystem(System* system) Chord* c1 = startCR()->isChord() ? toChord(startCR()) : 0; Chord* c2 = endCR()->isChord() ? toChord(endCR()) : 0; + if (c1 && c1->beam() && c1->beam()->cross()) { + // TODO: stem direction is not finalized, so we cannot use it here + _up = true; + break; + } + _up = !(startCR()->up()); Measure* m1 = startCR()->measure(); From f2073afc57bf94d2040e18709fd0d4cf370c766c Mon Sep 17 00:00:00 2001 From: Marc Sabatella Date: Tue, 21 May 2019 23:29:29 -0600 Subject: [PATCH 2/2] fix #289498: bad layout of beam with cross-staff beam in another voice --- libmscore/beam.cpp | 1 + libmscore/layout.cpp | 46 +++++++++++++++++++++++++++++++++++++++++++- 2 files changed, 46 insertions(+), 1 deletion(-) diff --git a/libmscore/beam.cpp b/libmscore/beam.cpp index 44df023936ff..81aa0591a19c 100644 --- a/libmscore/beam.cpp +++ b/libmscore/beam.cpp @@ -1624,6 +1624,7 @@ void Beam::layout2(std::vectorcrl, SpannerSegmentType, int frag) // we should relayout entire measure // this probably means starting over for beam as well // see https://musescore.org/en/node/71901 + // also see https://musescore.org/en/node/289492 } } diff --git a/libmscore/layout.cpp b/libmscore/layout.cpp index 3645988ec3e5..725f4dfb8a9e 100644 --- a/libmscore/layout.cpp +++ b/libmscore/layout.cpp @@ -96,6 +96,45 @@ static void layoutSegmentElements(Segment* segment, int startTrack, int endTrack } } +#if 0 +//--------------------------------------------------------- +// vUp +// reurns true if chord should be treated as up +// for purpose of setting horizontal position +// for most chords, this is just chord->up() +// but for notes on cross-staff beams, we take care to produce more consistent results +// since the initial guess for up() may change during layout +//--------------------------------------------------------- +static bool vUp(Chord* chord) + { + if (!chord) + return true; + else if (!chord->beam() || !chord->beam()->cross()) { + return chord->up(); + } + else { + // cross-staff beam: we cannot know the actual direction of this chord until the beam layout, + // but that's too late - it won't work to lay out as if the chord is up on pass one but then down on pass two + // so just assign a logical direction based on attributes that won't change + // so chords can be laid out consistently on both passes + bool up; + if (chord->stemDirection() != Direction::AUTO) + up = chord->stemDirection() == Direction::UP; + else if (chord->staffMove()) + up = chord->staffMove() > 0; + else if (chord->track() < chord->beam()->track()) + up = false; + else if (chord->track() > chord->beam()->track()) + up = true; + else if (chord->measure()->hasVoices(chord->staffIdx())) + up = !(chord->track() % 2); + else + up = !chord->staff()->isTop(); + return up; + } + } +#endif + //--------------------------------------------------------- // layoutChords1 // - layout upstem and downstem chords @@ -113,6 +152,7 @@ void Score::layoutChords1(Segment* segment, int staffIdx) return; } + bool crossBeamFound = false; std::vector upStemNotes; std::vector downStemNotes; int upVoices = 0; @@ -137,6 +177,8 @@ void Score::layoutChords1(Segment* segment, int staffIdx) Element* e = segment->element(track); if (e && e->isChord()) { Chord* chord = toChord(e); + if (chord->beam() && chord->beam()->cross()) + crossBeamFound = true; bool hasGraceBefore = false; for (Chord* c : chord->graceNotes()) { if (c->isGraceBefore()) @@ -268,7 +310,9 @@ void Score::layoutChords1(Segment* segment, int staffIdx) Note* bottomUpNote = upStemNotes.front(); Note* topDownNote = downStemNotes.back(); int separation; - if (bottomUpNote->chord()->staffMove() == topDownNote->chord()->staffMove()) + // TODO: handle conflicts for cross-staff notes and notes on cross-staff beams + // for now we simply treat these as though there is no conflict + if (bottomUpNote->chord()->staffMove() == topDownNote->chord()->staffMove() && !crossBeamFound) separation = topDownNote->line() - bottomUpNote->line(); else separation = 2; // no conflict