Skip to content

Commit

Permalink
Fix GH#8980, fix #45576: Improve horizontal placement of tie endpoints
Browse files Browse the repository at this point in the history
Backport of  musescore#9077, part 1 and 2, fixes musescore#8980
  • Loading branch information
asattely authored and Jojo-Schmitz committed Sep 13, 2021
1 parent a80ee11 commit dfb982e
Showing 1 changed file with 87 additions and 16 deletions.
103 changes: 87 additions & 16 deletions libmscore/tie.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
#include "system.h"
#include "undo.h"
#include "chord.h"
#include "hook.h"
#include "ledgerline.h"
#include "tie.h"

namespace Ms {
Expand Down Expand Up @@ -455,9 +457,10 @@ void Tie::slurPos(SlurPos* sp)
qDebug("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount());
}

qreal xo;
qreal yo;
qreal x1, y1;
qreal x2, y2;
bool shortStart = false;
qreal offsetMargin = 0.25 * _spatium;

// determine attachment points
// similar code is used in Chord::layoutPitched()
Expand All @@ -467,18 +470,61 @@ void Tie::slurPos(SlurPos* sp)
sp->p1 = sc->pos() + sc->segment()->pos() + sc->measure()->pos();

//------p1
if ((sc->notes().size() > 1) || (sc->stem() && (sc->up() == _up))) {
xo = startNote()->x() + hw * 1.12;
yo = startNote()->pos().y() + yOffInside;
if (sc->notes().size() > 1) {
y1 = startNote()->pos().y() + yOffInside;
x1 = 0;
qreal xo = startNote()->pos().x() + hw; // x offset for p1 will be at least note head width

// ADJUST FOR COLLISIONS ----------------

for (auto note : sc->notes()) {
// adjust for dots
if (startNote()->dots().size() > 0) {
qreal dotY = note->pos().y() + note->dots().last()->pos().y();
if (qAbs(y1 - dotY) < _spatium * 0.5)
xo = qMax(xo, startNote()->dots().last()->x() + startNote()->dots().last()->width());
}

// adjust for note collisions
if (note == startNote())
continue;
qreal noteTop = note->y();
qreal noteHeight = note->height();
if (y1 > noteTop && y1 < noteTop + noteHeight)
xo = qMax(xo, note->x() + note->width());
}

// adjust for flags (hooks)
if (sc->hook() && sc->up()) {
if (y1 < sc->hook()->pos().y() + sc->hook()->bbox().height() + (offsetMargin * 2))
xo = qMax(xo, sc->hook()->pos().x() + sc->hook()->bbox().width());
}

// adjust for ledger lines
auto currLedger = sc->ledgerLines(); // search through ledger lines and see if any are within .5sp of tie start
while (currLedger) {
if (qAbs(y1 - currLedger->y()) < _spatium * 0.5) {
xo = qMax(xo, currLedger->x() + currLedger->len());
break;
}
currLedger = currLedger->next();
}

x1 += xo + offsetMargin;
shortStart = true;
}
else if (sc->stem() && sc->up() == _up) {
x1 = startNote()->x() + hw * 1.12;
y1 = startNote()->pos().y() + yOffInside;
}
else {
xo = startNote()->x() + hw * 0.65;
yo = startNote()->pos().y() + yOffOutside;
x1 = startNote()->x() + hw * 0.65;
y1 = startNote()->pos().y() + yOffOutside;
}
sp->p1 += QPointF(xo, yo);
sp->p1 += QPointF(x1, y1);

//------p2
y2 = y1;
if (endNote() == 0) {
sp->p2 = sp->p1 + QPointF(_spatium * 3, 0.0);
sp->system2 = sp->system1;
Expand All @@ -492,22 +538,47 @@ void Tie::slurPos(SlurPos* sp)
bool horizontal = startNote()->line() == endNote()->line() && sc->vStaffIdx() == ec->vStaffIdx();

hw = endNote()->tabHeadWidth(stt);
if ((ec->notes().size() > 1) || (ec->stem() && !ec->up() && !_up)) {
xo = endNote()->x() - hw * 0.12;
if (ec->notes().size() > 1) {
x2 = endNote()->x();
qreal xo = 0.0;

// ADJUST FOR COLLISIONS ----------------

// adjust for ledger lines
auto currLedger = ec->ledgerLines(); // search through ledger lines and see if any are within .5sp of tie end
while (currLedger) {
if (qAbs(y1 - currLedger->y()) < _spatium * 0.5)
xo = qMax(xo, x2 - currLedger->x());
currLedger = currLedger->next();
}

// adjust for shifted notes (such as intervals of unison or second)
for (auto note : ec->notes()) {
if (note == endNote())
continue;
qreal noteTop = note->y();
if (y2 >= noteTop - offsetMargin && y2 <= noteTop + note->headHeight() + offsetMargin)
xo = qMax(xo, x2 - note->x());
}

x2 -= (xo + offsetMargin);
}
else if (ec->stem() && !ec->up() && !_up) {
x2 = endNote()->x() - hw * 0.12;
if (!horizontal)
yo = endNote()->pos().y() + yOffInside;
y2 = endNote()->pos().y() + yOffInside;
}
else if (shortStart) {
xo = endNote()->x() + hw * 0.15;
x2 = endNote()->x() + hw * 0.15;
if (!horizontal)
yo = endNote()->pos().y() + yOffOutside;
y2 = endNote()->pos().y() + yOffOutside;
}
else {
xo = endNote()->x() + hw * 0.35;
x2 = endNote()->x() + hw * 0.35;
if (!horizontal)
yo = endNote()->pos().y() + yOffOutside;
y2 = endNote()->pos().y() + yOffOutside;
}
sp->p2 += QPointF(xo, yo);
sp->p2 += QPointF(x2, y2);

// adjust for cross-staff
if (sc->vStaffIdx() != vStaffIdx() && sp->system1) {
Expand Down

0 comments on commit dfb982e

Please sign in to comment.