diff --git a/src/engraving/dom/spanner.cpp b/src/engraving/dom/spanner.cpp index e0d2fc11283c5..afe2176688aef 100644 --- a/src/engraving/dom/spanner.cpp +++ b/src/engraving/dom/spanner.cpp @@ -723,18 +723,7 @@ PropertyValue Spanner::propertyDefault(Pid propertyId) const void Spanner::computeStartElement() { - EngravingItem* oldStartElement = m_startElement; - doComputeStartElement(); - - if (oldStartElement && oldStartElement->isChord()) { - toChord(oldStartElement)->removeStartingSpanner(this); - } - - Chord* startChord = m_startElement && m_startElement->isChord() ? toChord(m_startElement) : nullptr; - if (startChord) { - startChord->addStartingSpanner(this); - } } void Spanner::doComputeStartElement() @@ -746,24 +735,24 @@ void Spanner::doComputeStartElement() return; } if (systemFlag()) { - m_startElement = startSegment(); + setStartElement(startSegment()); } else { EngravingItem* startEl = startSeg->element(track()); if (startEl) { - m_startElement = startEl; + setStartElement(startEl); } else { - m_startElement = startSeg->firstElement(track2staff(track())); + setStartElement(startSeg->firstElement(track2staff(track()))); } } } break; case Anchor::MEASURE: - m_startElement = score()->tick2measure(tick()); + setStartElement(score()->tick2measure(tick())); break; case Anchor::CHORD: - m_startElement = startCR(); + setStartElement(startCR()); break; case Anchor::NOTE: break; @@ -777,22 +766,11 @@ void Spanner::doComputeStartElement() void Spanner::computeEndElement() { if (score()->isPaletteScore()) { - m_endElement = nullptr; + setEndElement(nullptr); return; } - EngravingItem* oldEndElement = m_endElement; - doComputeEndElement(); - - if (oldEndElement && oldEndElement->isChord()) { - toChord(oldEndElement)->removeEndingSpanner(this); - } - - Chord* endChord = m_endElement && m_endElement->isChord() ? toChord(m_endElement) : nullptr; - if (endChord) { - endChord->addEndingSpanner(this); - } } void Spanner::doComputeEndElement() @@ -804,27 +782,27 @@ void Spanner::doComputeEndElement() return; } if (systemFlag()) { - m_endElement = endSeg; + setEndElement(endSeg); } else { track_idx_t trackIdx = effectiveTrack2(); EngravingItem* endEl = endSeg->element(trackIdx); if (endEl) { - m_endElement = endEl; + setEndElement(endEl); } else { - m_endElement = endSeg->firstElement(track2staff(trackIdx)); + setEndElement(endSeg->firstElement(track2staff(trackIdx))); } } } break; case Anchor::MEASURE: - m_endElement = score()->tick2measure(tick2() - Fraction(1, 1920)); + setEndElement(score()->tick2measure(tick2() - Fraction(1, 1920))); break; case Anchor::NOTE: break; case Anchor::CHORD: - m_endElement = endCR(); + setEndElement(endCR()); break; } } @@ -957,7 +935,7 @@ Chord* Spanner::startChord() return nullptr; } if (!m_startElement) { - m_startElement = findStartChord(); + setStartElement(findStartChord()); } if (m_startElement && m_startElement->isChord()) { @@ -977,7 +955,7 @@ Chord* Spanner::endChord() return nullptr; } if (!m_endElement && type() == ElementType::SLUR) { - m_endElement = findEndChord(); + setEndElement(findEndChord()); } if (m_endElement && m_endElement->isChord()) { @@ -996,7 +974,7 @@ ChordRest* Spanner::startCR() assert(m_anchor == Anchor::SEGMENT || m_anchor == Anchor::CHORD); if (!m_startElement || m_startElement->score() != score()) { // TODO: This is a bit weird and prevents this method from being const... - m_startElement = findStartCR(); + setStartElement(findStartCR()); } return (m_startElement && m_startElement->isChordRest()) ? toChordRest(m_startElement) : nullptr; } @@ -1010,7 +988,7 @@ ChordRest* Spanner::endCR() assert(m_anchor == Anchor::SEGMENT || m_anchor == Anchor::CHORD); if ((!m_endElement || m_endElement->score() != score())) { // TODO: This is a bit weird and prevents this method from being const... - m_endElement = findEndCR(); + setEndElement(findEndCR()); } return (m_endElement && m_endElement->isChordRest()) ? toChordRest(m_endElement) : nullptr; } @@ -1260,7 +1238,18 @@ void Spanner::setStartElement(EngravingItem* e) assert(!e || e->isNote()); } #endif + EngravingItem* oldStartElement = m_startElement; + m_startElement = e; + + if (oldStartElement && oldStartElement->isChord()) { + toChord(oldStartElement)->removeStartingSpanner(this); + } + + Chord* startChord = m_startElement && m_startElement->isChord() ? toChord(m_startElement) : nullptr; + if (startChord) { + startChord->addStartingSpanner(this); + } } //--------------------------------------------------------- @@ -1274,7 +1263,18 @@ void Spanner::setEndElement(EngravingItem* e) assert(!e || e->isNote()); } #endif + EngravingItem* oldEndElement = m_endElement; + m_endElement = e; + + if (oldEndElement && oldEndElement->isChord()) { + toChord(oldEndElement)->removeEndingSpanner(this); + } + + Chord* endChord = m_endElement && m_endElement->isChord() ? toChord(m_endElement) : nullptr; + if (endChord) { + endChord->addEndingSpanner(this); + } } //--------------------------------------------------------- diff --git a/src/engraving/rw/read206/read206.cpp b/src/engraving/rw/read206/read206.cpp index 7581e3ac9c431..a581857a00224 100644 --- a/src/engraving/rw/read206/read206.cpp +++ b/src/engraving/rw/read206/read206.cpp @@ -3653,6 +3653,18 @@ Ret Read206::readScoreFile(Score* score, XmlReader& e, ReadInOutData* out) } } + // Discard slurs that were started but never terminated + for (Spanner* sp : score->spannerList()) { + if (sp->isSlur() && sp->ticks() <= Fraction(0, 1) && sp->startElement() == sp->endElement()) { + LOGW() << "discarding slur (id " << ctx.spannerId(sp) << ") that has no end"; + assert(sp->startElement() && sp->startElement()->isChord()); + + ctx.removeSpanner(sp); + score->removeSpanner(sp); + delete sp; + } + } + for (Staff* s : score->staves()) { s->updateOttava(); } diff --git a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp index 6118e46636092..f020af3b2c772 100644 --- a/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp +++ b/src/importexport/musicxml/internal/import/importmusicxmlpass2.cpp @@ -8339,6 +8339,7 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N slurs[slurNo] = SlurDesc(); if (newSlur->endElement() == cr && note) { + newSlur->setEndElement(nullptr); delete newSlur; // Slur starts & ends on same chord - add lv instead @@ -8350,6 +8351,7 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N const Fraction tick2 = newSlur->endElement()->tick(); if (tick2 < tick) { logger->logError(String(u"slur end is before slur start"), xmlreader); + newSlur->setEndElement(nullptr); delete newSlur; return; } @@ -8400,6 +8402,7 @@ static void addSlur(const Notation& notation, SlurStack& slurs, ChordRest* cr, N slurs[slurNo] = SlurDesc(); if (newSlur->startElement() == cr && note) { + newSlur->setStartElement(nullptr); delete newSlur; // Slur starts & ends on same chord - add lv instead