[engraving] moved layout Tie
This commit is contained in:
parent
e49dca5c5d
commit
07629d88de
9 changed files with 280 additions and 272 deletions
|
@ -55,6 +55,8 @@
|
|||
#include "libmscore/undo.h"
|
||||
#include "libmscore/utils.h"
|
||||
|
||||
#include "slurtielayout.h"
|
||||
|
||||
using namespace mu::engraving;
|
||||
|
||||
void ChordLayout::layout(Chord* item, LayoutContext& ctx)
|
||||
|
@ -1975,7 +1977,7 @@ void ChordLayout::updateLineAttachPoints(Chord* chord, bool isFirstInMeasure)
|
|||
for (Note* note : chord->notes()) {
|
||||
Tie* tieBack = note->tieBack();
|
||||
if (tieBack && tieBack->startNote()->findMeasure() != note->findMeasure()) {
|
||||
tieBack->layoutBack(note->findMeasure()->system());
|
||||
SlurTieLayout::tieLayoutBack(tieBack, note->findMeasure()->system());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1984,7 +1986,7 @@ void ChordLayout::updateLineAttachPoints(Chord* chord, bool isFirstInMeasure)
|
|||
if (tie) {
|
||||
Note* endNote = tie->endNote();
|
||||
if (endNote && endNote->findMeasure() == note->findMeasure()) {
|
||||
tie->layoutFor(note->findMeasure()->system()); // line attach points are updated here
|
||||
SlurTieLayout::tieLayoutFor(tie, note->findMeasure()->system()); // line attach points are updated here
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -53,6 +53,7 @@
|
|||
#include "lyricslayout.h"
|
||||
#include "layoutmeasure.h"
|
||||
#include "layouttuplets.h"
|
||||
#include "slurtielayout.h"
|
||||
|
||||
#include "log.h"
|
||||
|
||||
|
@ -1409,7 +1410,7 @@ void LayoutSystem::layoutTies(Chord* ch, System* system, const Fraction& stick)
|
|||
for (Note* note : ch->notes()) {
|
||||
Tie* t = note->tieFor();
|
||||
if (t) {
|
||||
TieSegment* ts = t->layoutFor(system);
|
||||
TieSegment* ts = SlurTieLayout::tieLayoutFor(t, system);
|
||||
if (ts && ts->addToSkyline()) {
|
||||
staff->skyline().add(ts->shape().translate(ts->pos()));
|
||||
}
|
||||
|
@ -1417,7 +1418,7 @@ void LayoutSystem::layoutTies(Chord* ch, System* system, const Fraction& stick)
|
|||
t = note->tieBack();
|
||||
if (t) {
|
||||
if (t->startNote()->tick() < stick) {
|
||||
TieSegment* ts = t->layoutBack(system);
|
||||
TieSegment* ts = SlurTieLayout::tieLayoutBack(t, system);
|
||||
if (ts && ts->addToSkyline()) {
|
||||
staff->skyline().add(ts->shape().translate(ts->pos()));
|
||||
}
|
||||
|
|
|
@ -981,3 +981,259 @@ void SlurTieLayout::fixArticulations(Slur* item, PointF& pt, Chord* c, double up
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// layoutFor
|
||||
// layout the first SpannerSegment of a slur
|
||||
//---------------------------------------------------------
|
||||
|
||||
TieSegment* SlurTieLayout::tieLayoutFor(Tie* item, System* system)
|
||||
{
|
||||
// do not layout ties in tablature if not showing back-tied fret marks
|
||||
StaffType* st = item->staff()->staffType(item->startNote() ? item->startNote()->tick() : Fraction(0, 1));
|
||||
if (st && st->isTabStaff() && !st->showBackTied()) {
|
||||
if (!item->segmentsEmpty()) {
|
||||
item->eraseSpannerSegments();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
//
|
||||
// show short bow
|
||||
//
|
||||
if (item->startNote() == 0 || item->endNote() == 0) {
|
||||
if (item->startNote() == 0) {
|
||||
LOGD("no start note");
|
||||
return 0;
|
||||
}
|
||||
Chord* c1 = item->startNote()->chord();
|
||||
item->setTick(c1->tick());
|
||||
if (item->_slurDirection == DirectionV::AUTO) {
|
||||
bool simpleException = st && st->isSimpleTabStaff();
|
||||
if (st && st->isSimpleTabStaff()) {
|
||||
item->_up = isUpVoice(c1->voice());
|
||||
} else {
|
||||
if (c1->measure()->hasVoices(c1->staffIdx(), c1->tick(), c1->actualTicks())) {
|
||||
// in polyphonic passage, ties go on the stem side
|
||||
item->_up = simpleException ? isUpVoice(c1->voice()) : c1->up();
|
||||
} else {
|
||||
item->_up = !c1->up();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
item->_up = item->_slurDirection == DirectionV::UP ? true : false;
|
||||
}
|
||||
item->fixupSegments(1);
|
||||
TieSegment* segment = item->segmentAt(0);
|
||||
segment->setSpannerSegmentType(SpannerSegmentType::SINGLE);
|
||||
segment->setSystem(item->startNote()->chord()->segment()->measure()->system());
|
||||
SlurPos sPos;
|
||||
tiePos(item, &sPos);
|
||||
segment->adjustY(sPos.p1, sPos.p2);
|
||||
segment->finalizeSegment();
|
||||
return segment;
|
||||
}
|
||||
item->calculateDirection();
|
||||
|
||||
SlurPos sPos;
|
||||
tiePos(item, &sPos); // get unadjusted x values and determine inside or outside
|
||||
|
||||
item->setPos(0, 0);
|
||||
|
||||
int n;
|
||||
if (sPos.system1 != sPos.system2) {
|
||||
n = 2;
|
||||
sPos.p2 = PointF(system->lastNoteRestSegmentX(true), sPos.p1.y());
|
||||
} else {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
item->fixupSegments(n);
|
||||
TieSegment* segment = item->segmentAt(0);
|
||||
segment->setSystem(system); // Needed to populate System.spannerSegments
|
||||
Chord* c1 = item->startNote()->chord();
|
||||
item->setTick(c1->tick());
|
||||
segment->adjustY(sPos.p1, sPos.p2); // adjust vertically
|
||||
segment->setSpannerSegmentType(sPos.system1 != sPos.system2 ? SpannerSegmentType::BEGIN : SpannerSegmentType::SINGLE);
|
||||
segment->adjustX(); // adjust horizontally for inside-style ties
|
||||
segment->finalizeSegment(); // compute bezier and set bbox
|
||||
segment->addLineAttachPoints(); // add attach points to start and end note
|
||||
return segment;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// layoutBack
|
||||
// layout the second SpannerSegment of a split slur
|
||||
//---------------------------------------------------------
|
||||
|
||||
TieSegment* SlurTieLayout::tieLayoutBack(Tie* item, System* system)
|
||||
{
|
||||
// do not layout ties in tablature if not showing back-tied fret marks
|
||||
StaffType* st = item->staff()->staffType(item->startNote() ? item->startNote()->tick() : Fraction(0, 1));
|
||||
if (st->isTabStaff() && !st->showBackTied()) {
|
||||
if (!item->segmentsEmpty()) {
|
||||
item->eraseSpannerSegments();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SlurPos sPos;
|
||||
tiePos(item, &sPos);
|
||||
|
||||
item->fixupSegments(2);
|
||||
TieSegment* segment = item->segmentAt(1);
|
||||
segment->setSystem(system);
|
||||
|
||||
double x = system ? system->firstNoteRestSegmentX(true) : 0;
|
||||
|
||||
segment->adjustY(PointF(x, sPos.p2.y()), sPos.p2);
|
||||
segment->setSpannerSegmentType(SpannerSegmentType::END);
|
||||
segment->adjustX();
|
||||
segment->finalizeSegment();
|
||||
segment->addLineAttachPoints();
|
||||
return segment;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// slurPos
|
||||
// Calculate position of start- and endpoint of slur
|
||||
// relative to System() position.
|
||||
//---------------------------------------------------------
|
||||
|
||||
void SlurTieLayout::tiePos(Tie* item, SlurPos* sp)
|
||||
{
|
||||
const StaffType* staffType = item->staffType();
|
||||
bool useTablature = staffType->isTabStaff();
|
||||
double _spatium = item->spatium();
|
||||
double hw = item->startNote()->tabHeadWidth(staffType); // if staffType == 0, defaults to headWidth()
|
||||
/* Inside-style and Outside-style ties
|
||||
Outside ties connect above the notehead, in the middle. Ideally, we'd use opticalcenter for this, but
|
||||
that Smufl anchor is not available for noteheads yet. For this reason, we rely on Note::outsideTieAttachX()
|
||||
which makes its best guess as to where ties should connect.
|
||||
|
||||
As for y connection point, inside-style ties are decided by the space or line the note occupies in TieSegment::adjustY()
|
||||
so we don't need to worry about that. Outside-style ties will be 0.125 spatium from the top or bottom of the notehead.
|
||||
We can parameterize that later, but this describes only a minimum distance from the notehead, it can be changed, again,
|
||||
in TieSegment::adjustY().
|
||||
*/
|
||||
|
||||
Chord* sc = item->startNote()->chord();
|
||||
Chord* ec = item->endNote() ? item->endNote()->chord() : nullptr;
|
||||
sp->system1 = sc->measure()->system();
|
||||
if (!sp->system1) {
|
||||
Measure* m = sc->measure();
|
||||
LOGD("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount());
|
||||
}
|
||||
|
||||
double x1, y1;
|
||||
double x2, y2;
|
||||
|
||||
// determine attachment points
|
||||
// similar code is used in Chord::layoutPitched()
|
||||
// to allocate extra space to enforce minTieLength
|
||||
// so keep these in sync
|
||||
if (sc->notes().size() > 1 || (ec && ec->notes().size() > 1)) {
|
||||
item->_isInside = true;
|
||||
} else {
|
||||
item->_isInside = false;
|
||||
}
|
||||
sp->p1 = sc->pos() + sc->segment()->pos() + sc->measure()->pos();
|
||||
|
||||
//------p1
|
||||
y1 = item->startNote()->pos().y();
|
||||
y2 = item->endNote() ? item->endNote()->pos().y() : y1;
|
||||
|
||||
// force tie to be horizontal except for cross-staff or if there is a difference of line (tpc, clef)
|
||||
int line1 = useTablature ? item->startNote()->string() : item->startNote()->line();
|
||||
int line2 = line1;
|
||||
if (item->endNote()) {
|
||||
line2 = useTablature ? item->endNote()->string() : item->endNote()->line();
|
||||
}
|
||||
bool isHorizontal = ec ? line1 == line2 && sc->vStaffIdx() == ec->vStaffIdx() : true;
|
||||
y1 += item->startNote()->bbox().y();
|
||||
if (item->endNote()) {
|
||||
y2 += item->endNote()->bbox().y();
|
||||
}
|
||||
if (!item->up()) {
|
||||
y1 += item->startNote()->bbox().height();
|
||||
if (item->endNote()) {
|
||||
y2 += item->endNote()->bbox().height();
|
||||
}
|
||||
}
|
||||
if (!item->endNote()) {
|
||||
y2 = y1;
|
||||
}
|
||||
|
||||
// ensure that horizontal ties remain horizontal
|
||||
if (isHorizontal) {
|
||||
y1 = item->_up ? std::min(y1, y2) : std::max(y1, y2);
|
||||
y2 = item->_up ? std::min(y1, y2) : std::max(y1, y2);
|
||||
}
|
||||
|
||||
if (item->_isInside) {
|
||||
x1 = item->startNote()->pos().x() + hw; // the offset for these will be decided in TieSegment::adjustX()
|
||||
} else {
|
||||
if (sc->stem() && sc->stem()->visible() && sc->up() && item->_up) {
|
||||
// usually, outside ties start in the middle of the notehead, but
|
||||
// for up-ties on up-stems, we'll start at the end of the notehead
|
||||
// to avoid the stem
|
||||
x1 = item->startNote()->pos().x() + hw;
|
||||
} else {
|
||||
x1 = item->startNote()->outsideTieAttachX(item->_up);
|
||||
}
|
||||
}
|
||||
|
||||
sp->p1 += PointF(x1, y1);
|
||||
|
||||
//------p2
|
||||
if (!ec) {
|
||||
sp->p2 = sp->p1 + PointF(_spatium * 3, 0.0);
|
||||
sp->system2 = sp->system1;
|
||||
return;
|
||||
}
|
||||
sp->p2 = ec->pos() + ec->segment()->pos() + ec->measure()->pos();
|
||||
sp->system2 = ec->measure()->system();
|
||||
|
||||
if (item->isInside()) {
|
||||
x2 = item->endNote()->x();
|
||||
} else {
|
||||
if (ec->stem() && ec->stem()->visible() && !ec->up() && !item->_up) {
|
||||
// as before, xo should account for stems that could get in the way
|
||||
x2 = item->endNote()->x();
|
||||
} else {
|
||||
x2 = item->endNote()->outsideTieAttachX(item->_up);
|
||||
}
|
||||
}
|
||||
sp->p2 += PointF(x2, y2);
|
||||
// adjust for cross-staff
|
||||
if (sc->vStaffIdx() != item->staffIdx() && sp->system1) {
|
||||
double diff = sp->system1->staff(sc->vStaffIdx())->y() - sp->system1->staff(item->staffIdx())->y();
|
||||
sp->p1.ry() += diff;
|
||||
}
|
||||
if (ec->vStaffIdx() != item->staffIdx() && sp->system2) {
|
||||
double diff = sp->system2->staff(ec->vStaffIdx())->y() - sp->system2->staff(item->staffIdx())->y();
|
||||
sp->p2.ry() += diff;
|
||||
}
|
||||
|
||||
/// adjusting ties for notes in circles
|
||||
if (Tie::engravingConfiguration()->enableExperimentalFretCircle() && item->staff()->staffType()->isCommonTabStaff()) {
|
||||
auto adjustTie = [item](Chord* ch, PointF& coord, bool tieStart) {
|
||||
const Fraction halfFraction = Fraction(1, 2);
|
||||
if (ch && ch->ticks() >= halfFraction) {
|
||||
for (EngravingItem* e : ch->el()) {
|
||||
if (e && e->isFretCircle()) {
|
||||
FretCircle* fretCircle = toFretCircle(e);
|
||||
coord += PointF(0, fretCircle->offsetFromUpNote() * (item->up() ? -1 : 1));
|
||||
if (item->isInside()) {
|
||||
coord += PointF(fretCircle->sideOffset() * (tieStart ? 1 : -1), 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
adjustTie(sc, sp->p1, true);
|
||||
adjustTie(ec, sp->p2, false);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30,6 +30,8 @@ struct SlurPos;
|
|||
class SpannerSegment;
|
||||
class System;
|
||||
class Chord;
|
||||
class TieSegment;
|
||||
class Tie;
|
||||
|
||||
class SlurTieLayout
|
||||
{
|
||||
|
@ -37,9 +39,14 @@ public:
|
|||
static void layout(Slur* item, LayoutContext& ctx);
|
||||
static SpannerSegment* layoutSystem(Slur* item, System* system);
|
||||
|
||||
static TieSegment* tieLayoutFor(Tie* item, System* system);
|
||||
static TieSegment* tieLayoutBack(Tie* item, System* system);
|
||||
|
||||
private:
|
||||
static void slurPos(Slur* item, SlurPos* sp);
|
||||
static void fixArticulations(Slur* item, PointF& pt, Chord* c, double up, bool stemSide);
|
||||
|
||||
static void tiePos(Tie* item, SlurPos* sp);
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@
|
|||
|
||||
#include "style/style.h"
|
||||
#include "layout/tlayout.h"
|
||||
#include "layout/slurtielayout.h"
|
||||
|
||||
#include "accidental.h"
|
||||
#include "arpeggio.h"
|
||||
|
@ -2043,12 +2044,12 @@ void Chord::layoutSpanners(System* system, const Fraction& stick)
|
|||
for (const Note* note : notes()) {
|
||||
Tie* t = note->tieFor();
|
||||
if (t) {
|
||||
t->layoutFor(system);
|
||||
SlurTieLayout::tieLayoutFor(t, system);
|
||||
}
|
||||
t = note->tieBack();
|
||||
if (t) {
|
||||
if (t->startNote()->tick() < stick) {
|
||||
t->layoutBack(system);
|
||||
SlurTieLayout::tieLayoutBack(t, system);
|
||||
}
|
||||
}
|
||||
for (Spanner* sp : note->spannerBack()) {
|
||||
|
|
|
@ -95,7 +95,7 @@ public:
|
|||
void layout() override;
|
||||
SpannerSegment* layoutSystem(System*) override;
|
||||
void setTrack(track_idx_t val) override;
|
||||
void slurPos(SlurPos*) override {}
|
||||
|
||||
void computeUp();
|
||||
|
||||
void setSourceStemArrangement(int v) { _sourceStemArrangement = v; }
|
||||
|
|
|
@ -174,7 +174,6 @@ public:
|
|||
SlurStyleType styleType() const { return _styleType; }
|
||||
void setStyleType(SlurStyleType type) { _styleType = type; }
|
||||
|
||||
virtual void slurPos(SlurPos*) = 0;
|
||||
virtual SlurTieSegment* newSlurTieSegment(System* parent) = 0;
|
||||
|
||||
PropertyValue getProperty(Pid propertyId) const override;
|
||||
|
|
|
@ -851,151 +851,6 @@ void TieSegment::addLineAttachPoints()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// slurPos
|
||||
// Calculate position of start- and endpoint of slur
|
||||
// relative to System() position.
|
||||
//---------------------------------------------------------
|
||||
|
||||
void Tie::slurPos(SlurPos* sp)
|
||||
{
|
||||
const StaffType* staffType = this->staffType();
|
||||
bool useTablature = staffType->isTabStaff();
|
||||
double _spatium = spatium();
|
||||
double hw = startNote()->tabHeadWidth(staffType); // if staffType == 0, defaults to headWidth()
|
||||
/* Inside-style and Outside-style ties
|
||||
Outside ties connect above the notehead, in the middle. Ideally, we'd use opticalcenter for this, but
|
||||
that Smufl anchor is not available for noteheads yet. For this reason, we rely on Note::outsideTieAttachX()
|
||||
which makes its best guess as to where ties should connect.
|
||||
|
||||
As for y connection point, inside-style ties are decided by the space or line the note occupies in TieSegment::adjustY()
|
||||
so we don't need to worry about that. Outside-style ties will be 0.125 spatium from the top or bottom of the notehead.
|
||||
We can parameterize that later, but this describes only a minimum distance from the notehead, it can be changed, again,
|
||||
in TieSegment::adjustY().
|
||||
*/
|
||||
|
||||
Chord* sc = startNote()->chord();
|
||||
Chord* ec = endNote() ? endNote()->chord() : nullptr;
|
||||
sp->system1 = sc->measure()->system();
|
||||
if (!sp->system1) {
|
||||
Measure* m = sc->measure();
|
||||
LOGD("No system: measure is %d has %d count %d", m->isMMRest(), m->hasMMRest(), m->mmRestCount());
|
||||
}
|
||||
|
||||
double x1, y1;
|
||||
double x2, y2;
|
||||
|
||||
// determine attachment points
|
||||
// similar code is used in Chord::layoutPitched()
|
||||
// to allocate extra space to enforce minTieLength
|
||||
// so keep these in sync
|
||||
if (sc->notes().size() > 1 || (ec && ec->notes().size() > 1)) {
|
||||
_isInside = true;
|
||||
} else {
|
||||
_isInside = false;
|
||||
}
|
||||
sp->p1 = sc->pos() + sc->segment()->pos() + sc->measure()->pos();
|
||||
|
||||
//------p1
|
||||
y1 = startNote()->pos().y();
|
||||
y2 = endNote() ? endNote()->pos().y() : y1;
|
||||
|
||||
// force tie to be horizontal except for cross-staff or if there is a difference of line (tpc, clef)
|
||||
int line1 = useTablature ? startNote()->string() : startNote()->line();
|
||||
int line2 = line1;
|
||||
if (endNote()) {
|
||||
line2 = useTablature ? endNote()->string() : endNote()->line();
|
||||
}
|
||||
bool isHorizontal = ec ? line1 == line2 && sc->vStaffIdx() == ec->vStaffIdx() : true;
|
||||
y1 += startNote()->bbox().y();
|
||||
if (endNote()) {
|
||||
y2 += endNote()->bbox().y();
|
||||
}
|
||||
if (!up()) {
|
||||
y1 += startNote()->bbox().height();
|
||||
if (endNote()) {
|
||||
y2 += endNote()->bbox().height();
|
||||
}
|
||||
}
|
||||
if (!endNote()) {
|
||||
y2 = y1;
|
||||
}
|
||||
|
||||
// ensure that horizontal ties remain horizontal
|
||||
if (isHorizontal) {
|
||||
y1 = _up ? std::min(y1, y2) : std::max(y1, y2);
|
||||
y2 = _up ? std::min(y1, y2) : std::max(y1, y2);
|
||||
}
|
||||
|
||||
if (_isInside) {
|
||||
x1 = startNote()->pos().x() + hw; // the offset for these will be decided in TieSegment::adjustX()
|
||||
} else {
|
||||
if (sc->stem() && sc->stem()->visible() && sc->up() && _up) {
|
||||
// usually, outside ties start in the middle of the notehead, but
|
||||
// for up-ties on up-stems, we'll start at the end of the notehead
|
||||
// to avoid the stem
|
||||
x1 = startNote()->pos().x() + hw;
|
||||
} else {
|
||||
x1 = startNote()->outsideTieAttachX(_up);
|
||||
}
|
||||
}
|
||||
|
||||
sp->p1 += PointF(x1, y1);
|
||||
|
||||
//------p2
|
||||
if (!ec) {
|
||||
sp->p2 = sp->p1 + PointF(_spatium * 3, 0.0);
|
||||
sp->system2 = sp->system1;
|
||||
return;
|
||||
}
|
||||
sp->p2 = ec->pos() + ec->segment()->pos() + ec->measure()->pos();
|
||||
sp->system2 = ec->measure()->system();
|
||||
|
||||
if (isInside()) {
|
||||
x2 = endNote()->x();
|
||||
} else {
|
||||
if (ec->stem() && ec->stem()->visible() && !ec->up() && !_up) {
|
||||
// as before, xo should account for stems that could get in the way
|
||||
x2 = endNote()->x();
|
||||
} else {
|
||||
x2 = endNote()->outsideTieAttachX(_up);
|
||||
}
|
||||
}
|
||||
sp->p2 += PointF(x2, y2);
|
||||
// adjust for cross-staff
|
||||
if (sc->vStaffIdx() != staffIdx() && sp->system1) {
|
||||
double diff = sp->system1->staff(sc->vStaffIdx())->y() - sp->system1->staff(staffIdx())->y();
|
||||
sp->p1.ry() += diff;
|
||||
}
|
||||
if (ec->vStaffIdx() != staffIdx() && sp->system2) {
|
||||
double diff = sp->system2->staff(ec->vStaffIdx())->y() - sp->system2->staff(staffIdx())->y();
|
||||
sp->p2.ry() += diff;
|
||||
}
|
||||
|
||||
/// adjusting ties for notes in circles
|
||||
if (engravingConfiguration()->enableExperimentalFretCircle() && staff()->staffType()->isCommonTabStaff()) {
|
||||
auto adjustTie = [this](Chord* ch, PointF& coord, bool tieStart) {
|
||||
const Fraction halfFraction = Fraction(1, 2);
|
||||
if (ch && ch->ticks() >= halfFraction) {
|
||||
for (EngravingItem* item : ch->el()) {
|
||||
if (item && item->isFretCircle()) {
|
||||
FretCircle* fretCircle = toFretCircle(item);
|
||||
coord += PointF(0, fretCircle->offsetFromUpNote() * (up() ? -1 : 1));
|
||||
if (isInside()) {
|
||||
coord += PointF(fretCircle->sideOffset() * (tieStart ? 1 : -1), 0);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
adjustTie(sc, sp->p1, true);
|
||||
adjustTie(ec, sp->p2, false);
|
||||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// Tie
|
||||
//---------------------------------------------------------
|
||||
|
@ -1133,117 +988,6 @@ void Tie::calculateDirection()
|
|||
}
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// layoutFor
|
||||
// layout the first SpannerSegment of a slur
|
||||
//---------------------------------------------------------
|
||||
|
||||
TieSegment* Tie::layoutFor(System* system)
|
||||
{
|
||||
// do not layout ties in tablature if not showing back-tied fret marks
|
||||
StaffType* st = staff()->staffType(startNote() ? startNote()->tick() : Fraction(0, 1));
|
||||
if (st && st->isTabStaff() && !st->showBackTied()) {
|
||||
if (!segmentsEmpty()) {
|
||||
eraseSpannerSegments();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
//
|
||||
// show short bow
|
||||
//
|
||||
if (startNote() == 0 || endNote() == 0) {
|
||||
if (startNote() == 0) {
|
||||
LOGD("no start note");
|
||||
return 0;
|
||||
}
|
||||
Chord* c1 = startNote()->chord();
|
||||
setTick(c1->tick());
|
||||
if (_slurDirection == DirectionV::AUTO) {
|
||||
bool simpleException = st && st->isSimpleTabStaff();
|
||||
if (st && st->isSimpleTabStaff()) {
|
||||
_up = isUpVoice(c1->voice());
|
||||
} else {
|
||||
if (c1->measure()->hasVoices(c1->staffIdx(), c1->tick(), c1->actualTicks())) {
|
||||
// in polyphonic passage, ties go on the stem side
|
||||
_up = simpleException ? isUpVoice(c1->voice()) : c1->up();
|
||||
} else {
|
||||
_up = !c1->up();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
_up = _slurDirection == DirectionV::UP ? true : false;
|
||||
}
|
||||
fixupSegments(1);
|
||||
TieSegment* segment = segmentAt(0);
|
||||
segment->setSpannerSegmentType(SpannerSegmentType::SINGLE);
|
||||
segment->setSystem(startNote()->chord()->segment()->measure()->system());
|
||||
SlurPos sPos;
|
||||
slurPos(&sPos);
|
||||
segment->adjustY(sPos.p1, sPos.p2);
|
||||
segment->finalizeSegment();
|
||||
return segment;
|
||||
}
|
||||
calculateDirection();
|
||||
|
||||
SlurPos sPos;
|
||||
slurPos(&sPos); // get unadjusted x values and determine inside or outside
|
||||
|
||||
setPos(0, 0);
|
||||
|
||||
int n;
|
||||
if (sPos.system1 != sPos.system2) {
|
||||
n = 2;
|
||||
sPos.p2 = PointF(system->lastNoteRestSegmentX(true), sPos.p1.y());
|
||||
} else {
|
||||
n = 1;
|
||||
}
|
||||
|
||||
fixupSegments(n);
|
||||
TieSegment* segment = segmentAt(0);
|
||||
segment->setSystem(system); // Needed to populate System.spannerSegments
|
||||
Chord* c1 = startNote()->chord();
|
||||
setTick(c1->tick());
|
||||
segment->adjustY(sPos.p1, sPos.p2); // adjust vertically
|
||||
segment->setSpannerSegmentType(sPos.system1 != sPos.system2 ? SpannerSegmentType::BEGIN : SpannerSegmentType::SINGLE);
|
||||
segment->adjustX(); // adjust horizontally for inside-style ties
|
||||
segment->finalizeSegment(); // compute bezier and set bbox
|
||||
segment->addLineAttachPoints(); // add attach points to start and end note
|
||||
return segment;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// layoutBack
|
||||
// layout the second SpannerSegment of a split slur
|
||||
//---------------------------------------------------------
|
||||
|
||||
TieSegment* Tie::layoutBack(System* system)
|
||||
{
|
||||
// do not layout ties in tablature if not showing back-tied fret marks
|
||||
StaffType* st = staff()->staffType(startNote() ? startNote()->tick() : Fraction(0, 1));
|
||||
if (st->isTabStaff() && !st->showBackTied()) {
|
||||
if (!segmentsEmpty()) {
|
||||
eraseSpannerSegments();
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
SlurPos sPos;
|
||||
slurPos(&sPos);
|
||||
|
||||
fixupSegments(2);
|
||||
TieSegment* segment = segmentAt(1);
|
||||
segment->setSystem(system);
|
||||
|
||||
double x = system ? system->firstNoteRestSegmentX(true) : 0;
|
||||
|
||||
segment->adjustY(PointF(x, sPos.p2.y()), sPos.p2);
|
||||
segment->setSpannerSegmentType(SpannerSegmentType::END);
|
||||
segment->adjustX();
|
||||
segment->finalizeSegment();
|
||||
segment->addLineAttachPoints();
|
||||
return segment;
|
||||
}
|
||||
|
||||
//---------------------------------------------------------
|
||||
// setStartNote
|
||||
//---------------------------------------------------------
|
||||
|
|
|
@ -83,9 +83,6 @@ class Tie final : public SlurTie
|
|||
static Note* editStartNote;
|
||||
static Note* editEndNote;
|
||||
|
||||
private:
|
||||
bool _isInside{ false };
|
||||
|
||||
public:
|
||||
Tie(EngravingItem* parent = 0);
|
||||
|
||||
|
@ -102,11 +99,6 @@ public:
|
|||
|
||||
void calculateDirection();
|
||||
|
||||
void slurPos(SlurPos*) override;
|
||||
|
||||
TieSegment* layoutFor(System*);
|
||||
TieSegment* layoutBack(System*);
|
||||
|
||||
TieSegment* frontSegment() { return toTieSegment(Spanner::frontSegment()); }
|
||||
const TieSegment* frontSegment() const { return toTieSegment(Spanner::frontSegment()); }
|
||||
TieSegment* backSegment() { return toTieSegment(Spanner::backSegment()); }
|
||||
|
@ -115,6 +107,12 @@ public:
|
|||
const TieSegment* segmentAt(int n) const { return toTieSegment(Spanner::segmentAt(n)); }
|
||||
|
||||
SlurTieSegment* newSlurTieSegment(System* parent) override { return new TieSegment(parent); }
|
||||
|
||||
private:
|
||||
|
||||
friend class SlurTieLayout;
|
||||
|
||||
bool _isInside = false;
|
||||
};
|
||||
} // namespace mu::engraving
|
||||
#endif
|
||||
|
|
Loading…
Reference in a new issue