From 135ccb5bbcf72f5ebaaeb3dd49614ec4b0470d10 Mon Sep 17 00:00:00 2001 From: jeetee Date: Wed, 4 Nov 2020 02:14:40 +0100 Subject: [PATCH] Fix #311986: handle duplicate voltas (repeat58) Fixed initial voltas having the same start crash Also handles overlapping voltas by splitting them into non-overlapping voltas with cross-section repeatlists --- libmscore/repeatlist.cpp | 231 +++++++---- mtest/libmscore/repeat/repeat58.mscx | 292 ++++++++++++++ mtest/libmscore/repeat/repeat59.mscx | 545 ++++++++++++++++++++++++++ mtest/libmscore/repeat/repeat60.mscx | 285 ++++++++++++++ mtest/libmscore/repeat/repeat61.mscx | 257 ++++++++++++ mtest/libmscore/repeat/repeat62.mscx | 262 +++++++++++++ mtest/libmscore/repeat/repeat63.mscx | 256 ++++++++++++ mtest/libmscore/repeat/repeat64.mscx | 256 ++++++++++++ mtest/libmscore/repeat/tst_repeat.cpp | 8 + 9 files changed, 2319 insertions(+), 73 deletions(-) create mode 100644 mtest/libmscore/repeat/repeat58.mscx create mode 100644 mtest/libmscore/repeat/repeat59.mscx create mode 100644 mtest/libmscore/repeat/repeat60.mscx create mode 100644 mtest/libmscore/repeat/repeat61.mscx create mode 100644 mtest/libmscore/repeat/repeat62.mscx create mode 100644 mtest/libmscore/repeat/repeat63.mscx create mode 100644 mtest/libmscore/repeat/repeat64.mscx diff --git a/libmscore/repeatlist.cpp b/libmscore/repeatlist.cpp index 4ff7dd5f18823..92d92fc528b03 100644 --- a/libmscore/repeatlist.cpp +++ b/libmscore/repeatlist.cpp @@ -21,7 +21,7 @@ #include "types.h" #include "volta.h" -#include +#include #include // std::pair namespace Ms { @@ -266,7 +266,7 @@ void RepeatList::flatten() do { s->addMeasure(m); m = m->nextMeasure(); - }while (m); + } while (m); push_back(s); _expanded = false; @@ -307,6 +307,14 @@ class RepeatListElement repeatCount = (type == RepeatListElementType::REPEAT_START) ? 1 : 0; } + ~RepeatListElement() + { + // Voltas are cloned elements, we need to cleanup ourselves + if (repeatListElementType == RepeatListElementType::VOLTA_START) { + delete element; + } + } + int getRepeatCount() const { return repeatCount; } void addToRepeatCount(int add) { repeatCount += add; } }; @@ -318,7 +326,6 @@ class RepeatListElement void RepeatList::collectRepeatListElements() { QList* sectionRLElements = new QList(); - auto spannerIt = _score->spanner().cbegin(); // Clear out previous listing for (QList* srle : _rlElements) { @@ -338,97 +345,165 @@ void RepeatList::collectRepeatListElements() sectionRLElements->push_back(startFromRepeatMeasure); // Also trace down the final actual measure of this section (in case a frame follows) MeasureBase* sectionEndMeasureBase = nullptr; - // Used to track the actual end of a volta - std::stack voltaStack; + // Used to track voltas; overlappings and real endings + Volta* volta; + std::list preProcessedVoltas; + + // Voltas might overlap (duplicate entries on multiple staves or "real" overlaps) + // so we will pre-process them into cloned versions that handle those overlaps. + // This assumes that spanners are ordered from first to last tick-wise + for (const auto& spannerEntry : _score->spanner()) { + if ((spannerEntry.second)->isVolta()) { + volta = toVolta(spannerEntry.second)->clone(); + if (preProcessedVoltas.empty()) { // First entry + preProcessedVoltas.push_back(volta); + } else { // Compare + std::list voltasToMerge; + // List all overlapping voltas + while ((!preProcessedVoltas.empty()) + && (volta->startMeasure()->tick() <= preProcessedVoltas.back()->endMeasure()->tick()) + ) { + voltasToMerge.push_back(preProcessedVoltas.back()); + preProcessedVoltas.pop_back(); + } + + while (!voltasToMerge.empty()) { + // We'll have to shorten the already stored volta and split its remainder for merging + Volta* remainder = voltasToMerge.back()->clone(); + if (volta->startMeasure() != remainder->startMeasure()) { + // First part is not empty + voltasToMerge.back()->setEndElement(volta->startMeasure()->prevMeasure()); + remainder->setStartElement(volta->startMeasure()); + // Store it + preProcessedVoltas.push_back(voltasToMerge.back()); + } //else { + // New volta and existing one start at the same moment, there is no first part, only a remainder + //} + voltasToMerge.pop_back(); + + // remainder and volta now have the same start point + // Compare the end points and make remainder end first + if (volta->endMeasure()->tick() < remainder->endMeasure()->tick()) { + Volta* swap = volta; + volta = remainder; + remainder = swap; + } + // Cross-section of the repeatList + std::list endings = remainder->endings().toStdList(); + endings.remove_if([&volta](const int& ending) { + return !(volta->hasEnding(ending)); + }); + remainder->setEndings(QList::fromStdList(endings)); + // Split and merge done + preProcessedVoltas.push_back(remainder); + if (volta->endMeasure() != remainder->endMeasure()) { + // volta extends past the end of remainder -> move its startpoint after remainder + volta->setStartElement(remainder->endMeasure()->nextMeasure()); + } else { + // volta matched remainder endpoint, nothing left to merge from + preProcessedVoltas.splice(preProcessedVoltas.cend(), voltasToMerge); + delete volta; + volta = nullptr; + } + } // !voltasToMerge.empty() - // We only care about Volta within the spanner types, so forward the iterator to the first one - while ((spannerIt != _score->spanner().cend()) && !(((*spannerIt).second)->isVolta())) { - ++spannerIt; + if (volta != nullptr) { + preProcessedVoltas.push_back(volta); + } + } + } // spanner->isVolta } + volta = nullptr; for (; mb; mb = mb->next()) { if (mb->isMeasure()) { - sectionEndMeasureBase = mb; // ending measure of section is the most recently encountered actual Measure + sectionEndMeasureBase = mb; // ending measure of section is the most recently encountered actual Measure // Volta ? - if ((spannerIt != _score->spanner().cend()) && (toVolta((*spannerIt).second)->startMeasure() == mb)) { - if (!voltaStack.empty()) { - //if (voltaStack.top()->endMeasure()->tick() < mb->tick()) { + if ((!preProcessedVoltas.empty()) && (preProcessedVoltas.front()->startMeasure() == mb)) { + if (volta != nullptr) { + //if (volta->endMeasure()->tick() < mb->tick()) { // The previous volta was supposed to end before us (open volta case) -> insert the end - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), - toMeasure(mb->prevMeasure()))); - voltaStack.pop(); - // } - //else { // Overlapping voltas } + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb->prevMeasure()))); + // volta = nullptr; // No need, replaced immediately further down + //} else { + // Overlapping voltas; this should not happen as preProcessedVoltas should've dealt with this already + //} } // Now insert the start of the current volta - voltaStack.push(toVolta((*spannerIt).second)); - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_START, (*spannerIt).second, toMeasure(mb))); - // Forward iterator to next volta - do { - ++spannerIt; - } while ((spannerIt != _score->spanner().cend()) && !(((*spannerIt).second)->isVolta())); + volta = preProcessedVoltas.front(); + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_START, + volta, toMeasure(mb))); + // Look for start of next volta + preProcessedVoltas.pop_front(); } // Start if (mb->repeatStart()) { - if (!voltaStack.empty()) { - if (voltaStack.top()->startMeasure() != toMeasure(mb)) { + if (volta != nullptr) { + if (volta->startMeasure() != toMeasure(mb)) { // Volta and Start repeat are not on the same measure // assume the previous volta was supposed to end before us (open volta case) -> insert the end // Warning: This might "break" a volta prematurely if its explicit notated end is later than this point // Consider splitting the volta or ignoring this repeat all together - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), - toMeasure(mb->prevMeasure()))); - voltaStack.pop(); + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb->prevMeasure()))); + volta = nullptr; } //else { // Volta and Start Repeat coincide on the same measure, see test::repeat56.mscx } } - startFromRepeatMeasure = new RepeatListElement(RepeatListElementType::REPEAT_START, mb, toMeasure(mb)); + startFromRepeatMeasure = new RepeatListElement(RepeatListElementType::REPEAT_START, + mb, toMeasure(mb)); sectionRLElements->push_back(startFromRepeatMeasure); } // Jumps and Markers for (Element* e : mb->el()) { if (e->isJump()) { - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::JUMP, e, toMeasure(mb))); - if (!voltaStack.empty()) { - if (voltaStack.top()->endMeasure()->tick() <= mb->tick()) { + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::JUMP, + e, toMeasure(mb))); + if (volta != nullptr) { + if (volta->endMeasure()->tick() <= mb->tick()) { // The previous volta was supposed to end before us (open volta case) -> insert the end - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), - toMeasure(mb))); - voltaStack.pop(); - } - //else { // Volta is spanning past this jump instruction } + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb))); + volta = nullptr; + } //else { // Volta is spanning past this jump instruction } } } else if (e->isMarker()) { - RepeatListElement* markerRLE = new RepeatListElement(RepeatListElementType::MARKER, e, toMeasure(mb)); + RepeatListElement* markerRLE = new RepeatListElement(RepeatListElementType::MARKER, + e, toMeasure(mb)); // There may be multiple markers in the same measure and there is no guarantee we're reading // them from left to right. The only way available to guess their order is to look at their // text alignment and order them left to right // At the same time, we should ensure Markers are evaluated before Jumps - Align markerRLEalignmentH - = static_cast(static_cast(toMarker(e)->align()) & static_cast(Align::HMASK)); + Align markerRLEalignmentH = static_cast( + static_cast(toMarker(e)->align()) & static_cast(Align::HMASK) + ); auto insertionIt = sectionRLElements->end() - 1; while ((*insertionIt)->measure == markerRLE->measure) { bool markerShouldGoBefore = false; if (((*insertionIt)->repeatListElementType == RepeatListElementType::MARKER) - && (markerRLEalignmentH != Align::RIGHT) // We can be the end when right aligned + && (markerRLEalignmentH != Align::RIGHT) // We can be the end when right aligned ) { - Align storedMarkerAlignmentH - = static_cast(static_cast(toMarker((*insertionIt)->element)->align()) - & static_cast(Align::HMASK)); + Align storedMarkerAlignmentH = static_cast( + static_cast(toMarker((*insertionIt)->element)->align()) + & static_cast(Align::HMASK) + ); if (markerRLEalignmentH == Align::HCENTER) { markerShouldGoBefore = (storedMarkerAlignmentH == Align::RIGHT); - } else { //(markerRLEalignmentH == Align::LEFT) + } else { //(markerRLEalignmentH == Align::LEFT) markerShouldGoBefore = (storedMarkerAlignmentH != Align::LEFT); } } if (markerShouldGoBefore || ((*insertionIt)->repeatListElementType == RepeatListElementType::JUMP) ) { - // Decrease position - this should always be possible as the list always starts with a REPEAT_START element + // Decrease position + // This should always be possible as the list always starts with a REPEAT_START element Q_ASSERT(insertionIt != sectionRLElements->begin()); --insertionIt; - } else { // Found location after which we should go + } else { + // Found location after which we should go break; } } @@ -438,42 +513,51 @@ void RepeatList::collectRepeatListElements() } // End if (mb->repeatEnd()) { - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::REPEAT_END, mb, toMeasure(mb))); + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::REPEAT_END, + mb, toMeasure(mb))); if (startFromRepeatMeasure != nullptr) { startFromRepeatMeasure->addToRepeatCount(toMeasure(mb)->repeatCount() - 1); } - if (!voltaStack.empty()) { - //if (voltaStack.top()->endMeasure()->tick() < mb->tick()) { + if (volta != nullptr) { + //if (volta->endMeasure()->tick() < mb->tick()) { // The previous volta was supposed to end before us (open volta case) -> insert the end - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), toMeasure(mb))); - voltaStack.pop(); - // } - //else { // Volta is spanning over this end repeat, consider splitting the volta or ignoring this repeat all together } + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb))); + volta = nullptr; + //} else { + // // Volta is spanning over this end repeat, consider splitting the volta + // // or ignoring this repeat all together + //} } } // Volta end - if (!voltaStack.empty() - && (voltaStack.top()->endMeasure()->tick() == mb->tick()) - && (voltaStack.top()->getProperty(Pid::END_HOOK_TYPE).value() != HookType::NONE)) { + if ((volta != nullptr) + && (volta->endMeasure()->tick() == mb->tick()) + && (volta->getProperty(Pid::END_HOOK_TYPE).value() != HookType::NONE) + ) { // end of closed volta - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), toMeasure(mb))); - voltaStack.pop(); + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb))); + volta = nullptr; } } // Section break (or end of score) if (mb->sectionBreak() || !mb->nextMeasure()) { if (sectionEndMeasureBase != nullptr) { - if (!voltaStack.empty()) { - //if (voltaStack.top()->endMeasure()->tick() < mb->tick()) { + if (volta != nullptr) { + //if (volta->endMeasure()->tick() < mb->tick()) { // The previous volta was supposed to end before us (open volta case) -> insert the end - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, voltaStack.top(), toMeasure(mb))); - voltaStack.pop(); - // } - //else { // Volta is spanning over this section break, consider splitting the volta and adding it again at the start of the next section } + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::VOLTA_END, + volta, toMeasure(mb))); + volta = nullptr; + //} else { + // // Volta is spanning over this section break, consider splitting the volta + // // and adding it again at the start of the next section + //} } - sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::SECTION_BREAK, mb, - toMeasure(sectionEndMeasureBase))); - sectionEndMeasureBase = nullptr; // reset to indicate not having found the end for the next section + sectionRLElements->push_back(new RepeatListElement(RepeatListElementType::SECTION_BREAK, + mb, toMeasure(sectionEndMeasureBase))); + sectionEndMeasureBase = nullptr; // reset to indicate not having found the end for the next section // store section _rlElements.push_back(sectionRLElements); } @@ -482,14 +566,15 @@ void RepeatList::collectRepeatListElements() sectionRLElements = new QList(); // First measure of a section/score is always used as a reference REPEAT_START point // even if it doesn't have a start repeat - startFromRepeatMeasure - = new RepeatListElement(RepeatListElementType::REPEAT_START, mb->nextMeasure(), toMeasure(mb->nextMeasure())); + startFromRepeatMeasure = new RepeatListElement(RepeatListElementType::REPEAT_START, + mb->nextMeasure(), toMeasure(mb->nextMeasure())); sectionRLElements->push_back(startFromRepeatMeasure); // Loop will forward one measureBase, so return one now // this logic aids in skipping multiple frames between sections mb = mb->nextMeasure()->prev(); } else { - break; // no more measures -> done + // no more measures -> done + break; } } } @@ -822,7 +907,7 @@ void RepeatList::unwind() QList::const_iterator findRepeatIt = repeatListElementIt; do { --findRepeatIt; - }while ((*findRepeatIt) != startRepeatReference); + } while ((*findRepeatIt) != startRepeatReference); ++findRepeatIt; // Start volta analysis past this start repeat Volta const* voltaReference = nullptr; int processedRepeatCount = 1; @@ -890,7 +975,7 @@ void RepeatList::unwind() rs->addMeasure((*repeatListElementIt)->measure); continueAt.first = _rlElements.cend(); // Clear this reference - processed - } else { // Nowhere to go to, break out of this section loop and onto the next section + } else { // Nowhere to go to, break out of this section loop and onto the next section repeatListElementIt = (*sectionIt)->cend(); continue; } diff --git a/mtest/libmscore/repeat/repeat58.mscx b/mtest/libmscore/repeat/repeat58.mscx new file mode 100644 index 0000000000000..f9b8ac98ebceb --- /dev/null +++ b/mtest/libmscore/repeat/repeat58.mscx @@ -0,0 +1,292 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat58 + + + + duplicate volta - single staff + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2, 1, 3, 4,5, 4, 6,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + 2 + + + + 1 + 1. + 1 + + + + 1 + + + + + whole + + 62 + 16 + + + + + + + + + + -1 + + + + + + 2. + 2 + + + + 1 + + + + + + 2. + + 0 + + + + 2 + + + + 1 + + + + + whole + + 64 + 18 + + + + + + + + + + + -1 + + + + + + + -1 + + + + + whole + + 65 + 13 + + + + + + 2 + + + + 1 + 1. + 1 + + + + 1 + + + + + whole + + 67 + 15 + + + + + + + + + + -1 + + + + + + 2. + 2 + + + + 1 + + + + + whole + + 71 + 19 + + + + + + + + + + -1 + + + + + whole + + 72 + 14 + + + + + + + diff --git a/mtest/libmscore/repeat/repeat59.mscx b/mtest/libmscore/repeat/repeat59.mscx new file mode 100644 index 0000000000000..feb3dac11379b --- /dev/null +++ b/mtest/libmscore/repeat/repeat59.mscx @@ -0,0 +1,545 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + + stdNormal + + + 1 + + + + stdNormal + + F + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 150 + 100 + + + 150 + 50 + + + 120 + 50 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat59 + + + + duplicate volta - multiple instruments + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2, 1, 3, 4,5, 4, 6,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + 2 + + + + 1 + 1. + 1 + + + + 1 + + + + + whole + + 62 + 16 + + + + + + + + + + -1 + + + + + + + 1 + -1 + + + + + + 2. + 2 + + + + 1 + + + + + whole + + 64 + 18 + + + + + + + + + + + -1 + + + + + + + 1 + -1 + + + + + whole + + 65 + 13 + + + + + + 2 + + + + 1 + 1. + 1 + + + + 1 + + + + + whole + + 67 + 15 + + + + + + + + + + -1 + + + + + + + 1 + -1 + + + + + + 2. + 2 + + + + 1 + + + + + whole + + 71 + 19 + + + + + + + + + + -1 + + + + + + + 1 + -1 + + + + + whole + + 72 + 14 + + + + + + + + + + 4 + 4 + + + measure + 4/4 + + + + + + + + 1 + 1. + 1 + + + + -1 + 1 + + + + + measure + 4/4 + + + + + + + + 2. + 2 + + + + -1 + 1 + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + + 1 + 1. + 1 + + + + -1 + 1 + + + + + measure + 4/4 + + + + + + + + 2. + 2 + + + + -1 + 1 + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + + + 4 + 4 + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + + measure + 4/4 + + + + + + diff --git a/mtest/libmscore/repeat/repeat60.mscx b/mtest/libmscore/repeat/repeat60.mscx new file mode 100644 index 0000000000000..8def06dfd7a7d --- /dev/null +++ b/mtest/libmscore/repeat/repeat60.mscx @@ -0,0 +1,285 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat60 + + + + overlapping voltas - go nuts ;-) + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2, 6,7, 1,2,3, 6,7, 1,2,3,4,5,6,7, 1,2,3, 6,7, 1,2, 6,7, 1,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + + + + 1 + 1-5 + + 0 + + + + 1, 2, 3, 4, 5 + + + + 5 + + + + + whole + + 62 + 16 + + + + + + + + + 2-4 + + 0 + + + + 2, 3, 4 + + + + 2 + + + + + whole + + 64 + 18 + + + + + + + + + 1 + 3. + + 0 + + + 0.430001 + + 3 + + + + 2 + + + + + whole + + 65 + 13 + + + + + + + + + + -2 + + + + + whole + + 67 + 15 + + + + + + + + + + -2 + + + + + whole + + 71 + 19 + + + + + + 6 + + + + + -5 + + + + + + 0 + 6x + center,center + 0.149991 + + + + 1/1 + + + + + whole + + 72 + 14 + + + + + + -1/1 + + + + + + + + diff --git a/mtest/libmscore/repeat/repeat61.mscx b/mtest/libmscore/repeat/repeat61.mscx new file mode 100644 index 0000000000000..a837759919dfe --- /dev/null +++ b/mtest/libmscore/repeat/repeat61.mscx @@ -0,0 +1,257 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat61 + + + + overlapping voltas - nested + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2,3, 6,7, 1,2,3,4,5,6,7, 1,2,3, 6,7, 1,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + + + + 1 + 1-3 + 1, 2, 3 + + + + 5 + + + + + whole + + 62 + 16 + + + + + + + + whole + + 64 + 18 + + + + + + + + + 1 + 2. + + 0 + + + 0.430001 + + 2 + + + + 2 + + + + + whole + + 65 + 13 + + + + + + + + whole + + 67 + 15 + + + + + + + + + + -2 + + + + + whole + + 71 + 19 + + + + + + 4 + + + + + -5 + + + + + + 0 + 4x + center,center + 0.149991 + + + + 1/1 + + + + + whole + + 72 + 14 + + + + + + -1/1 + + + + + + + + diff --git a/mtest/libmscore/repeat/repeat62.mscx b/mtest/libmscore/repeat/repeat62.mscx new file mode 100644 index 0000000000000..83d6387fc70e7 --- /dev/null +++ b/mtest/libmscore/repeat/repeat62.mscx @@ -0,0 +1,262 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat62 + + + + overlapping voltas - same start + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1, 5,6,7, 1,2,3,4,5,6,7, 1, 5,6,7, 1,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + + + + 1 + 1-3 + + 0 + + + + 1, 2, 3 + + + + 5 + + + + + + 1 + 2. + + 0 + + + 0.390001 + + 2 + + + + 3 + + + + + whole + + 62 + 16 + + + + + + + + whole + + 64 + 18 + + + + + + + + whole + + 65 + 13 + + + + + + + + + + -3 + + + + + whole + + 67 + 15 + + + + + + + + whole + + 71 + 19 + + + + + + 4 + + + + + -5 + + + + + + 0 + 4x + center,center + 0.149991 + + + + 1/1 + + + + + whole + + 72 + 14 + + + + + + -1/1 + + + + + + + + diff --git a/mtest/libmscore/repeat/repeat63.mscx b/mtest/libmscore/repeat/repeat63.mscx new file mode 100644 index 0000000000000..b4638d2bc0283 --- /dev/null +++ b/mtest/libmscore/repeat/repeat63.mscx @@ -0,0 +1,256 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat63 + + + + overlapping voltas - same end + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2,3, 7, 1,2,3,4,5,6,7, 1,2,3, 7, 1,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + + + + 1 + 1-3 + + 0 + + + + 1, 2, 3 + + + + 5 + + + + + whole + + 62 + 16 + + + + + + + + whole + + 64 + 18 + + + + + + + + + 1 + 2. + 2 + + + + 3 + + + + + whole + + 65 + 13 + + + + + + + + whole + + 67 + 15 + + + + + + + + whole + + 71 + 19 + + + + + + 4 + + + + + -5 + + + + + + + -3 + + + + + + 0 + 4x + center,center + 0.149991 + + + + 1/1 + + + + + whole + + 72 + 14 + + + + + + -1/1 + + + + + + + + diff --git a/mtest/libmscore/repeat/repeat64.mscx b/mtest/libmscore/repeat/repeat64.mscx new file mode 100644 index 0000000000000..33dac6a6e8d2e --- /dev/null +++ b/mtest/libmscore/repeat/repeat64.mscx @@ -0,0 +1,256 @@ + + + + + 0 + 480 + + 1 + 1 + 1 + 0 + + + + + + + + + + + Repeat Test + + + + stdNormal + + + Piano + + Piano + Pno. + Piano + 21 + 108 + 21 + 108 + keyboard.piano + F + + 100 + 95 + + + 100 + 33 + + + 100 + 50 + + + 100 + 67 + + + 100 + 100 + + + 120 + 67 + + + 120 + 100 + + + + + + + + + 10 + 1 + + + repeat64 + + + + overlapping voltas + + + + 1 + 0 + 1 + 1 + 1 + 1 + + + 1,2,3, 7, 1,2,3,4,5,6,7, 1,2,3, 7, 1,7 + + + + + + + 4 + 4 + + + 6.66667 + 1 + = 400 + + + whole + + 60 + 14 + + + + + + + + + 1 + 1-3 + + 0 + + + + 1, 2, 3 + + + + 3 + + + + + whole + + 62 + 16 + + + + + + + + whole + + 64 + 18 + + + + + + + + + 1 + 2. + 2 + + + + 3 + + + + + whole + + 65 + 13 + + + + + + + + + + -3 + + + + + whole + + 67 + 15 + + + + + + + + whole + + 71 + 19 + + + + + + 4 + + + + + -3 + + + + + + 0 + 4x + center,center + 0.149991 + + + + 1/1 + + + + + whole + + 72 + 14 + + + + + + -1/1 + + + + + + + + diff --git a/mtest/libmscore/repeat/tst_repeat.cpp b/mtest/libmscore/repeat/tst_repeat.cpp index 323bacb9b6b61..7ed83c9048bfd 100644 --- a/mtest/libmscore/repeat/tst_repeat.cpp +++ b/mtest/libmscore/repeat/tst_repeat.cpp @@ -114,6 +114,14 @@ private slots: void repeat56() { repeat("repeat56.mscx", "1;2;3;4; 2; 5;6;7; 5;6;7;8"); } // start of volta and start repeat on same measure void repeat57() { repeat("repeat57.mscx", "1;2;3"); } // no repeat, skip volta until section end, relates to #274690 + + void repeat58() { repeat("repeat58.mscx", "1;2; 1; 3;4;5; 4; 6;7"); } // duplicate voltas #311986 - single instrument + void repeat59() { repeat("repeat59.mscx", "1;2; 1; 3;4;5; 4; 6;7"); } // duplicate voltas #311986 - multiple instruments + void repeat60() { repeat("repeat60.mscx", "1;2;6;7; 1;2;3;6;7; 1;2;3;4;5;6;7; 1;2;3;6;7; 1;2;6;7; 1;7"); } // overlapping voltas + void repeat61() { repeat("repeat61.mscx", "1;2;3;6;7; 1;2;3;4;5;6;7; 1;2;3;6;7; 1;7"); } // overlapping voltas - nested + void repeat62() { repeat("repeat62.mscx", "1;5;6;7; 1;2;3;4;5;6;7; 1;5;6;7; 1;7"); } // overlapping voltas - same start + void repeat63() { repeat("repeat63.mscx", "1;2;3;7; 1;2;3;4;5;6;7; 1;2;3;7; 1;7"); } // overlapping voltas - same end + void repeat64() { repeat("repeat64.mscx", "1;2;3;7; 1;2;3;4;5;6;7; 1;2;3;7; 1;7"); } // overlapping voltas }; //---------------------------------------------------------