Skip to content

Commit

Permalink
Merge pull request #8953 from asattely/continued-lines-placement
Browse files Browse the repository at this point in the history
fix #8935 - Slurs, ties, lines extend beyond final barline
  • Loading branch information
RomanPudashkin committed Sep 14, 2021
2 parents 2987c68 + 71ba56c commit 4f2c437
Show file tree
Hide file tree
Showing 6 changed files with 53 additions and 11 deletions.
10 changes: 5 additions & 5 deletions src/engraving/libmscore/line.cpp
Expand Up @@ -129,7 +129,7 @@ PointF LineSegment::leftAnchorPosition(const qreal& systemPositionY) const
PointF LineSegment::rightAnchorPosition(const qreal& systemPositionY) const
{
if (isMiddleType() || isBeginType()) {
return PointF(system()->lastMeasure()->abbox().right(), systemPositionY);
return PointF(system()->lastNoteRestSegmentX(true), systemPositionY);
}

PointF result;
Expand Down Expand Up @@ -1119,13 +1119,13 @@ SpannerSegment* SLine::layoutSystem(System* system)
System* s;
PointF p1 = linePos(Grip::START, &s);
lineSegm->setPos(p1);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
lineSegm->setPos2(PointF(x2 - p1.x(), 0.0));
}
break;
case SpannerSegmentType::MIDDLE: {
qreal x1 = system->firstNoteRestSegmentX(true);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
System* s;
PointF p1 = linePos(Grip::START, &s);
lineSegm->setPos(PointF(x1, p1.y()));
Expand Down Expand Up @@ -1235,13 +1235,13 @@ void SLine::layout()
// start segment
lineSegm->setSpannerSegmentType(SpannerSegmentType::BEGIN);
lineSegm->setPos(p1);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
lineSegm->setPos2(PointF(x2 - p1.x(), 0.0));
} else if (i > 0 && i != sysIdx2) {
// middle segment
lineSegm->setSpannerSegmentType(SpannerSegmentType::MIDDLE);
qreal x1 = system->firstNoteRestSegmentX(true);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
lineSegm->setPos(PointF(x1, p1.y()));
lineSegm->setPos2(PointF(x2 - x1, 0.0));
} else if (i == sysIdx2) {
Expand Down
8 changes: 5 additions & 3 deletions src/engraving/libmscore/lyricsline.cpp
Expand Up @@ -237,14 +237,14 @@ SpannerSegment* LyricsLine::layoutSystem(System* system)
System* s;
PointF p1 = linePos(Grip::START, &s);
lineSegm->setPos(p1);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
lineSegm->setPos2(PointF(x2 - p1.x(), 0.0));
}
break;
case SpannerSegmentType::MIDDLE: {
bool leading = (anchor() == Anchor::SEGMENT || anchor() == Anchor::MEASURE);
qreal x1 = system->firstNoteRestSegmentX(leading);
qreal x2 = system->bbox().right();
qreal x2 = system->lastNoteRestSegmentX(true);
System* s;
PointF p1 = linePos(Grip::START, &s);
lineSegm->setPos(PointF(x1, p1.y()));
Expand Down Expand Up @@ -419,10 +419,12 @@ void LyricsLineSegment::layout()
if (isEndMelisma) { // melisma
_numOfDashes = 1;
rypos() -= lyricsLine()->lineWidth() * .5; // let the line 'sit on' the base line
// if not final segment, shorten it
// if not final segment, shorten it (why? -AS)
/*
if (isBeginType() || isMiddleType()) {
rxpos2() -= score()->styleP(Sid::minNoteDistance) * mag();
}
*/
} else { // dash(es)
// set conventional dash Y pos
rypos() -= lyr->fontMetrics().xHeight() * score()->styleD(Sid::lyricsDashYposRatio);
Expand Down
4 changes: 2 additions & 2 deletions src/engraving/libmscore/slur.cpp
Expand Up @@ -1159,11 +1159,11 @@ SpannerSegment* Slur::layoutSystem(System* system)
slurSegment->layoutSegment(sPos.p1, sPos.p2);
break;
case SpannerSegmentType::BEGIN:
slurSegment->layoutSegment(sPos.p1, PointF(system->bbox().width(), sPos.p1.y()));
slurSegment->layoutSegment(sPos.p1, PointF(system->lastNoteRestSegmentX(true), sPos.p1.y()));
break;
case SpannerSegmentType::MIDDLE: {
qreal x1 = system->firstNoteRestSegmentX(true);
qreal x2 = system->bbox().width();
qreal x2 = system->lastNoteRestSegmentX(true);
qreal y = staffIdx() > system->staves()->size() ? system->y() : system->staff(staffIdx())->y();
slurSegment->layoutSegment(PointF(x1, y), PointF(x2, y));
}
Expand Down
39 changes: 39 additions & 0 deletions src/engraving/libmscore/system.cpp
Expand Up @@ -1662,6 +1662,45 @@ qreal System::firstNoteRestSegmentX(bool leading)
return margin;
}

//---------------------------------------------------------
// lastNoteRestSegmentX
// in System() coordinates
// returns the position of the last note or rest,
// or the position just before the first non-chordrest segment
//---------------------------------------------------------

qreal System::lastNoteRestSegmentX(bool trailing)
{
qreal margin = score()->spatium() / 4; // TODO: this can be parameterizable
//for (const MeasureBase* mb : measures()) {
for (auto measureBaseIter = measures().rbegin(); measureBaseIter != measures().rend(); measureBaseIter++) {
if ((*measureBaseIter)->isMeasure()) {
const Measure* measure = static_cast<const Measure*>(*measureBaseIter);
for (const Segment* seg = measure->last(); seg; seg = seg->prev()) {
if (seg->isChordRestType()) {
qreal noteRestPos = seg->measure()->pos().x() + seg->pos().x();
if (!trailing) {
return noteRestPos;
}

// last CR found; find next segment after this one
seg = seg->nextActive();
while (seg && seg->allElementsInvisible()) {
seg = seg->nextActive();
}
if (seg) {
return qMax(seg->measure()->pos().x() + seg->pos().x() - margin, noteRestPos);
} else {
return bbox().x() - margin;
}
}
}
}
}
qDebug("lastNoteRestSegmentX: did not find segment");
return margin;
}

//---------------------------------------------------------
// pageBreak
//---------------------------------------------------------
Expand Down
1 change: 1 addition & 0 deletions src/engraving/libmscore/system.h
Expand Up @@ -213,6 +213,7 @@ class System final : public EngravingItem
Spacer* downSpacer(int staffIdx) const;

qreal firstNoteRestSegmentX(bool leading = false);
qreal lastNoteRestSegmentX(bool trailing = false);

bool hasFixedDownDistance() const { return fixedDownDistance; }
int firstVisibleStaff() const;
Expand Down
2 changes: 1 addition & 1 deletion src/engraving/libmscore/tie.cpp
Expand Up @@ -745,7 +745,7 @@ TieSegment* Tie::layoutFor(System* system)
int n;
if (sPos.system1 != sPos.system2) {
n = 2;
sPos.p2 = PointF(system->width(), sPos.p1.y());
sPos.p2 = PointF(system->lastNoteRestSegmentX(true), sPos.p1.y());
} else {
n = 1;
}
Expand Down

0 comments on commit 4f2c437

Please sign in to comment.