fix #294085: all elements set to normal position if all rests in voices other than voice 1 are deleted
This factors out the inner workings of Measure::checkMultiVoices() into a variant of Measure::hasVoices() that takes a start tick and a length in addition to a staff index. Co-authored-by: Howard-C <howardc@pku.edu.cn>
This commit is contained in:
parent
4708ea20fb
commit
472cb6bfb5
10 changed files with 56 additions and 51 deletions
|
@ -396,7 +396,7 @@ void Beam::layout1()
|
||||||
Measure* m = c1->measure();
|
Measure* m = c1->measure();
|
||||||
if (c1->stemDirection() != Direction::AUTO)
|
if (c1->stemDirection() != Direction::AUTO)
|
||||||
_up = c1->stemDirection() == Direction::UP;
|
_up = c1->stemDirection() == Direction::UP;
|
||||||
else if (m->hasVoices(c1->staffIdx()))
|
else if (m->hasVoices(c1->staffIdx(), tick(), ticks()))
|
||||||
_up = !(c1->voice() % 2);
|
_up = !(c1->voice() % 2);
|
||||||
else if (!twoBeamedNotes()) {
|
else if (!twoBeamedNotes()) {
|
||||||
// highest or lowest note determines stem direction
|
// highest or lowest note determines stem direction
|
||||||
|
@ -483,7 +483,7 @@ void Beam::layoutGraceNotes()
|
||||||
ChordRest* cr = _elements[0];
|
ChordRest* cr = _elements[0];
|
||||||
|
|
||||||
Measure* m = cr->measure();
|
Measure* m = cr->measure();
|
||||||
if (m->hasVoices(cr->staffIdx()))
|
if (m->hasVoices(cr->staffIdx(), tick(), ticks()))
|
||||||
_up = !(cr->voice() % 2);
|
_up = !(cr->voice() % 2);
|
||||||
else
|
else
|
||||||
_up = true;
|
_up = true;
|
||||||
|
@ -2493,6 +2493,19 @@ Fraction Beam::rtick() const
|
||||||
return _elements.empty() ? Fraction(0, 1) : _elements.front()->segment()->rtick();
|
return _elements.empty() ? Fraction(0, 1) : _elements.front()->segment()->rtick();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// ticks
|
||||||
|
// calculate the ticks of all chords and rests connected by the beam
|
||||||
|
//---------------------------------------------------------
|
||||||
|
|
||||||
|
Fraction Beam::ticks() const
|
||||||
|
{
|
||||||
|
Fraction ticks = Fraction(0, 1);
|
||||||
|
for (ChordRest* cr : _elements)
|
||||||
|
ticks += cr->actualTicks();
|
||||||
|
return ticks;
|
||||||
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
// iconType
|
// iconType
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
|
|
@ -92,6 +92,7 @@ class Beam final : public Element {
|
||||||
|
|
||||||
Fraction tick() const override;
|
Fraction tick() const override;
|
||||||
Fraction rtick() const override;
|
Fraction rtick() const override;
|
||||||
|
Fraction ticks() const;
|
||||||
|
|
||||||
void write(XmlWriter& xml) const override;
|
void write(XmlWriter& xml) const override;
|
||||||
void read(XmlReader&) override;
|
void read(XmlReader&) override;
|
||||||
|
|
|
@ -868,7 +868,7 @@ void Chord::computeUp()
|
||||||
// if no stems or stem beside staves
|
// if no stems or stem beside staves
|
||||||
if (tab->stemless() || !tab->stemThrough()) {
|
if (tab->stemless() || !tab->stemThrough()) {
|
||||||
// if measure has voices, set stem direction according to voice
|
// if measure has voices, set stem direction according to voice
|
||||||
if (measure()->hasVoices(staffIdx()))
|
if (measure()->hasVoices(staffIdx(), tick(), actualTicks()))
|
||||||
_up = !(track() % 2);
|
_up = !(track() % 2);
|
||||||
else // if only voice 1,
|
else // if only voice 1,
|
||||||
// unconditionally set to down if not stems or according to TAB stem direction otherwise
|
// unconditionally set to down if not stems or according to TAB stem direction otherwise
|
||||||
|
@ -889,14 +889,14 @@ void Chord::computeUp()
|
||||||
//
|
//
|
||||||
// stem direction for grace notes
|
// stem direction for grace notes
|
||||||
//
|
//
|
||||||
if (measure()->hasVoices(staffIdx()))
|
if (measure()->hasVoices(staffIdx(), tick(), actualTicks()))
|
||||||
_up = !(track() % 2);
|
_up = !(track() % 2);
|
||||||
else
|
else
|
||||||
_up = true;
|
_up = true;
|
||||||
}
|
}
|
||||||
else if (staffMove())
|
else if (staffMove())
|
||||||
_up = staffMove() > 0;
|
_up = staffMove() > 0;
|
||||||
else if (measure()->hasVoices(staffIdx()))
|
else if (measure()->hasVoices(staffIdx(), tick(), actualTicks()))
|
||||||
_up = !(track() % 2);
|
_up = !(track() % 2);
|
||||||
else {
|
else {
|
||||||
int dnMaxLine = staff()->middleLine(tick());
|
int dnMaxLine = staff()->middleLine(tick());
|
||||||
|
@ -3401,7 +3401,7 @@ void Chord::layoutArticulations()
|
||||||
Articulation* prevArticulation = nullptr;
|
Articulation* prevArticulation = nullptr;
|
||||||
for (Articulation* a : _articulations) {
|
for (Articulation* a : _articulations) {
|
||||||
if (a->anchor() == ArticulationAnchor::CHORD) {
|
if (a->anchor() == ArticulationAnchor::CHORD) {
|
||||||
if (measure()->hasVoices(a->staffIdx()))
|
if (measure()->hasVoices(a->staffIdx(), tick(), actualTicks()))
|
||||||
a->setUp(up()); // if there are voices place articulation at stem
|
a->setUp(up()); // if there are voices place articulation at stem
|
||||||
else if (a->symId() >= SymId::articMarcatoAbove && a->symId() <= SymId::articMarcatoTenutoBelow)
|
else if (a->symId() >= SymId::articMarcatoAbove && a->symId() <= SymId::articMarcatoTenutoBelow)
|
||||||
a->setUp(true); // Gould, p. 117: strong accents above staff
|
a->setUp(true); // Gould, p. 117: strong accents above staff
|
||||||
|
|
|
@ -79,7 +79,7 @@ Placement Fingering::calculatePlacement() const
|
||||||
Staff* staff = chord->staff();
|
Staff* staff = chord->staff();
|
||||||
Part* part = staff->part();
|
Part* part = staff->part();
|
||||||
int nstaves = part->nstaves();
|
int nstaves = part->nstaves();
|
||||||
bool voices = chord->measure()->hasVoices(staff->idx());
|
bool voices = chord->measure()->hasVoices(staff->idx(), chord->tick(), chord->actualTicks());
|
||||||
bool below = voices ? !chord->up() : (nstaves > 1) && (staff->rstaff() == nstaves - 1);
|
bool below = voices ? !chord->up() : (nstaves > 1) && (staff->rstaff() == nstaves - 1);
|
||||||
return below ? Placement::BELOW : Placement::ABOVE;
|
return below ? Placement::BELOW : Placement::ABOVE;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +105,7 @@ void Fingering::layout()
|
||||||
if (autoplace() && note()) {
|
if (autoplace() && note()) {
|
||||||
Note* n = note();
|
Note* n = note();
|
||||||
Chord* chord = n->chord();
|
Chord* chord = n->chord();
|
||||||
bool voices = chord->measure()->hasVoices(chord->staffIdx());
|
bool voices = chord->measure()->hasVoices(chord->staffIdx(), chord->tick(), chord->actualTicks());
|
||||||
bool tight = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER;
|
bool tight = voices && chord->notes().size() == 1 && !chord->beam() && tid() != Tid::STRING_NUMBER;
|
||||||
|
|
||||||
qreal headWidth = n->bboxRightPos();
|
qreal headWidth = n->bboxRightPos();
|
||||||
|
|
|
@ -128,7 +128,7 @@ static bool vUp(Chord* chord)
|
||||||
up = false;
|
up = false;
|
||||||
else if (chord->track() > chord->beam()->track())
|
else if (chord->track() > chord->beam()->track())
|
||||||
up = true;
|
up = true;
|
||||||
else if (chord->measure()->hasVoices(chord->staffIdx()))
|
else if (chord->measure()->hasVoices(chord->staffIdx(), chord->tick(), chord->actualTicks()))
|
||||||
up = !(chord->track() % 2);
|
up = !(chord->track() % 2);
|
||||||
else
|
else
|
||||||
up = !chord->staff()->isTop();
|
up = !chord->staff()->isTop();
|
||||||
|
|
|
@ -2681,20 +2681,35 @@ void Measure::exchangeVoice(int strack, int dtrack, int staffIdx)
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
|
||||||
void Measure::checkMultiVoices(int staffIdx)
|
void Measure::checkMultiVoices(int staffIdx)
|
||||||
|
{
|
||||||
|
if (hasVoices(staffIdx, tick(), ticks()))
|
||||||
|
_mstaves[staffIdx]->setHasVoices(true);
|
||||||
|
else
|
||||||
|
_mstaves[staffIdx]->setHasVoices(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
//---------------------------------------------------------
|
||||||
|
// hasVoices
|
||||||
|
//---------------------------------------------------------
|
||||||
|
|
||||||
|
bool Measure::hasVoices(int staffIdx, Fraction stick, Fraction len) const
|
||||||
{
|
{
|
||||||
int strack = staffIdx * VOICES + 1;
|
int strack = staffIdx * VOICES + 1;
|
||||||
int etrack = staffIdx * VOICES + VOICES;
|
int etrack = staffIdx * VOICES + VOICES;
|
||||||
_mstaves[staffIdx]->setHasVoices(false);
|
Fraction etick = stick + len;
|
||||||
|
|
||||||
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
for (Segment* s = first(SegmentType::ChordRest); s; s = s->next(SegmentType::ChordRest)) {
|
||||||
|
if (s->tick() >= etick)
|
||||||
|
break;
|
||||||
for (int track = strack; track < etrack; ++track) {
|
for (int track = strack; track < etrack; ++track) {
|
||||||
Element* e = s->element(track);
|
ChordRest* cr = toChordRest(s->element(track));
|
||||||
if (e) {
|
if (cr) {
|
||||||
bool v;
|
if (cr->tick() + cr->actualTicks() <= stick)
|
||||||
if (e->isChord()) {
|
continue;
|
||||||
v = false;
|
bool v = false;
|
||||||
|
if (cr->isChord()) {
|
||||||
// consider chord visible if any note is visible
|
// consider chord visible if any note is visible
|
||||||
Chord* c = toChord(e);
|
Chord* c = toChord(cr);
|
||||||
for (Note* n : c->notes()) {
|
for (Note* n : c->notes()) {
|
||||||
if (n->visible()) {
|
if (n->visible()) {
|
||||||
v = true;
|
v = true;
|
||||||
|
@ -2702,15 +2717,14 @@ void Measure::checkMultiVoices(int staffIdx)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (cr->isRest())
|
||||||
v = e->visible();
|
v = cr->visible() && !toRest(cr)->isGap();
|
||||||
if (v) {
|
if (v)
|
||||||
_mstaves[staffIdx]->setHasVoices(true);
|
return true;
|
||||||
return;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
@ -2878,27 +2892,6 @@ bool Measure::isOnlyDeletedRests(int track) const
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
//---------------------------------------------------------
|
|
||||||
// isOnlyDeletedRests
|
|
||||||
//---------------------------------------------------------
|
|
||||||
|
|
||||||
bool Measure::isOnlyDeletedRests(int track, const Fraction& stick, const Fraction& etick) const
|
|
||||||
{
|
|
||||||
static const SegmentType st { SegmentType::ChordRest };
|
|
||||||
for (const Segment* s = first(st); s; s = s->next(st)) {
|
|
||||||
if (s->segmentType() != st || !s->element(track))
|
|
||||||
continue;
|
|
||||||
ChordRest* cr = toChordRest(s->element(track));
|
|
||||||
if (cr->tick() + cr->globalTicks() <= stick)
|
|
||||||
continue;
|
|
||||||
if (cr->tick() >= etick)
|
|
||||||
return true;
|
|
||||||
if (!cr->isRest() || !toRest(cr)->isGap())
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
// stretchedLen
|
// stretchedLen
|
||||||
//---------------------------------------------------------
|
//---------------------------------------------------------
|
||||||
|
|
|
@ -117,6 +117,7 @@ class Measure final : public MeasureBase {
|
||||||
void spatiumChanged(qreal oldValue, qreal newValue) override;
|
void spatiumChanged(qreal oldValue, qreal newValue) override;
|
||||||
|
|
||||||
System* system() const { return (System*)parent(); }
|
System* system() const { return (System*)parent(); }
|
||||||
|
bool hasVoices(int staffIdx, Fraction stick, Fraction len) const;
|
||||||
bool hasVoices(int staffIdx) const;
|
bool hasVoices(int staffIdx) const;
|
||||||
void setHasVoices(int staffIdx, bool v);
|
void setHasVoices(int staffIdx, bool v);
|
||||||
|
|
||||||
|
@ -227,7 +228,6 @@ class Measure final : public MeasureBase {
|
||||||
bool empty() const;
|
bool empty() const;
|
||||||
bool isOnlyRests(int track) const;
|
bool isOnlyRests(int track) const;
|
||||||
bool isOnlyDeletedRests(int track) const;
|
bool isOnlyDeletedRests(int track) const;
|
||||||
bool isOnlyDeletedRests(int track, const Fraction& stick, const Fraction& etick) const;
|
|
||||||
|
|
||||||
int playbackCount() const { return _playbackCount; }
|
int playbackCount() const { return _playbackCount; }
|
||||||
void setPlaybackCount(int val) { _playbackCount = val; }
|
void setPlaybackCount(int val) { _playbackCount = val; }
|
||||||
|
|
|
@ -480,7 +480,7 @@ int Rest::getDotline(TDuration::DurationType durationType)
|
||||||
int Rest::computeLineOffset(int lines)
|
int Rest::computeLineOffset(int lines)
|
||||||
{
|
{
|
||||||
Segment* s = segment();
|
Segment* s = segment();
|
||||||
bool offsetVoices = s && measure() && measure()->hasVoices(staffIdx());
|
bool offsetVoices = s && measure() && measure()->hasVoices(staffIdx(), tick(), actualTicks());
|
||||||
if (offsetVoices && voice() == 0) {
|
if (offsetVoices && voice() == 0) {
|
||||||
// do not offset voice 1 rest if there exists a matching invisible rest in voice 2;
|
// do not offset voice 1 rest if there exists a matching invisible rest in voice 2;
|
||||||
Element* e = s->element(track() + 1);
|
Element* e = s->element(track() + 1);
|
||||||
|
@ -490,8 +490,6 @@ int Rest::computeLineOffset(int lines)
|
||||||
offsetVoices = false;
|
offsetVoices = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (measure()->isOnlyDeletedRests(track() + 1, tick(), tick() + globalTicks()))
|
|
||||||
offsetVoices = false;
|
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
if (offsetVoices && staff()->mergeMatchingRests()) {
|
if (offsetVoices && staff()->mergeMatchingRests()) {
|
||||||
|
|
|
@ -1050,7 +1050,7 @@ SpannerSegment* Slur::layoutSystem(System* system)
|
||||||
// but grace notes are exceptions
|
// but grace notes are exceptions
|
||||||
_up = true;
|
_up = true;
|
||||||
}
|
}
|
||||||
else if (m1->hasVoices(startCR()->staffIdx()) && c1 && !c1->isGrace()) {
|
else if (m1->hasVoices(startCR()->staffIdx(), tick(), ticks()) && c1 && !c1->isGrace()) {
|
||||||
// in polyphonic passage, slurs go on the stem side
|
// in polyphonic passage, slurs go on the stem side
|
||||||
_up = startCR()->up();
|
_up = startCR()->up();
|
||||||
}
|
}
|
||||||
|
@ -1172,7 +1172,7 @@ void Slur::layout()
|
||||||
// but grace notes are exceptions
|
// but grace notes are exceptions
|
||||||
_up = true;
|
_up = true;
|
||||||
}
|
}
|
||||||
else if (m1->hasVoices(startCR()->staffIdx()) && c1 && c1->noteType() == NoteType::NORMAL) {
|
else if (m1->hasVoices(startCR()->staffIdx(), tick(), ticks()) && c1 && c1->noteType() == NoteType::NORMAL) {
|
||||||
// in polyphonic passage, slurs go on the stem side
|
// in polyphonic passage, slurs go on the stem side
|
||||||
_up = startCR()->up();
|
_up = startCR()->up();
|
||||||
}
|
}
|
||||||
|
|
|
@ -544,7 +544,7 @@ void Tie::calculateDirection()
|
||||||
if (_slurDirection == Direction::AUTO) {
|
if (_slurDirection == Direction::AUTO) {
|
||||||
std::vector<Note*> notes = c1->notes();
|
std::vector<Note*> notes = c1->notes();
|
||||||
size_t n = notes.size();
|
size_t n = notes.size();
|
||||||
if (m1->hasVoices(c1->staffIdx()) || m2->hasVoices(c2->staffIdx())) {
|
if (m1->hasVoices(c1->staffIdx(), c1->tick(), c1->actualTicks()) || m2->hasVoices(c2->staffIdx(), c2->tick(), c2->actualTicks())) {
|
||||||
// in polyphonic passage, ties go on the stem side
|
// in polyphonic passage, ties go on the stem side
|
||||||
_up = c1->up();
|
_up = c1->up();
|
||||||
}
|
}
|
||||||
|
@ -619,7 +619,7 @@ TieSegment* Tie::layoutFor(System* system)
|
||||||
}
|
}
|
||||||
Chord* c1 = startNote()->chord();
|
Chord* c1 = startNote()->chord();
|
||||||
if (_slurDirection == Direction::AUTO) {
|
if (_slurDirection == Direction::AUTO) {
|
||||||
if (c1->measure()->hasVoices(c1->staffIdx())) {
|
if (c1->measure()->hasVoices(c1->staffIdx(), c1->tick(), c1->actualTicks())) {
|
||||||
// in polyphonic passage, ties go on the stem side
|
// in polyphonic passage, ties go on the stem side
|
||||||
_up = c1->up();
|
_up = c1->up();
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue