@@ -201,6 +201,17 @@ static Fraction lastChordTicks(const Segment* s, const Fraction& tick, const tra
201201 return Fraction (0 , 1 );
202202}
203203
204+ static bool spannerExists (const std::vector<MusicXmlSpannerDesc>& spanners, int number, engraving::ElementType elementType)
205+ {
206+ for (const MusicXmlSpannerDesc& desc : spanners) {
207+ if (desc.nr == number && desc.tp == elementType) {
208+ return true ;
209+ }
210+ }
211+
212+ return false ;
213+ }
214+
204215// ---------------------------------------------------------
205216// setExtend
206217// ---------------------------------------------------------
@@ -5075,6 +5086,12 @@ void MusicXmlParserDirection::bracket(const String& type, const int number,
50755086 const ElementType elementType = isWavy ? ElementType::TRILL : ElementType::TEXTLINE;
50765087 const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner ({ elementType, number });
50775088 if (type == " start" ) {
5089+ if (spannerExists (starts, number, elementType)) {
5090+ m_logger->logError (String (u" %1 with number %2 already started" ).arg (TConv::userName (elementType).translated ()).arg (number),
5091+ &m_e);
5092+ m_e.skipCurrentElement ();
5093+ return ;
5094+ }
50785095 SLine* sline = spdesc.isStopped ? spdesc.sp : 0 ;
50795096 if ((sline && sline->isTrill ()) || (!sline && isWavy)) {
50805097 if (!sline) {
@@ -5135,6 +5152,12 @@ void MusicXmlParserDirection::bracket(const String& type, const int number,
51355152
51365153 starts.push_back (MusicXmlSpannerDesc (sline, elementType, number));
51375154 } else if (type == " stop" ) {
5155+ if (spannerExists (stops, number, elementType)) {
5156+ m_logger->logError (String (u" %1 with number %2 already stopped" ).arg (TConv::userName (elementType).translated ()).arg (number),
5157+ &m_e);
5158+ m_e.skipCurrentElement ();
5159+ return ;
5160+ }
51385161 SLine* sline = spdesc.isStarted ? spdesc.sp : 0 ;
51395162 if ((sline && sline->isTrill ()) || (!sline && isWavy)) {
51405163 if (!sline) {
@@ -5186,6 +5209,11 @@ void MusicXmlParserDirection::dashes(const String& type, const int number,
51865209{
51875210 const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner ({ ElementType::HAIRPIN, number });
51885211 if (type == u" start" ) {
5212+ if (spannerExists (starts, number, ElementType::HAIRPIN)) {
5213+ m_logger->logError (String (u" hairpin with number %1 already started" ).arg (number), &m_e);
5214+ m_e.skipCurrentElement ();
5215+ return ;
5216+ }
51895217 TextLineBase* b = spdesc.isStopped ? toTextLineBase (spdesc.sp ) : Factory::createTextLine (m_score->dummy ());
51905218 // if (placement.empty()) placement = "above"; // TODO ? set default
51915219
@@ -5210,6 +5238,11 @@ void MusicXmlParserDirection::dashes(const String& type, const int number,
52105238 // use MusicXML specific type instead
52115239 starts.push_back (MusicXmlSpannerDesc (b, ElementType::TEXTLINE, number));
52125240 } else if (type == u" stop" ) {
5241+ if (spannerExists (stops, number, ElementType::HAIRPIN)) {
5242+ m_logger->logError (String (u" hairpin with number %1 already stopped" ).arg (number), &m_e);
5243+ m_e.skipCurrentElement ();
5244+ return ;
5245+ }
52135246 TextLineBase* b = spdesc.isStarted ? toTextLineBase (spdesc.sp ) : Factory::createTextLine (m_score->dummy ());
52145247 stops.push_back (MusicXmlSpannerDesc (b, ElementType::TEXTLINE, number));
52155248 }
@@ -5230,6 +5263,11 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number,
52305263{
52315264 const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner ({ ElementType::OTTAVA, number });
52325265 if (type == u" up" || type == u" down" ) {
5266+ if (spannerExists (starts, number, ElementType::OTTAVA)) {
5267+ m_logger->logError (String (u" ottava with number %1 already started" ).arg (number), &m_e);
5268+ m_e.skipCurrentElement ();
5269+ return ;
5270+ }
52335271 int ottavasize = m_e.intAttribute (" size" );
52345272 if (!(ottavasize == 8 || ottavasize == 15 )) {
52355273 m_logger->logError (String (u" unknown octave-shift size %1" ).arg (ottavasize), &m_e);
@@ -5257,6 +5295,11 @@ void MusicXmlParserDirection::octaveShift(const String& type, const int number,
52575295 starts.push_back (MusicXmlSpannerDesc (o, ElementType::OTTAVA, number));
52585296 }
52595297 } else if (type == u" stop" ) {
5298+ if (spannerExists (stops, number, ElementType::OTTAVA)) {
5299+ m_logger->logError (String (u" ottava with number %1 already stopped" ).arg (number), &m_e);
5300+ m_e.skipCurrentElement ();
5301+ return ;
5302+ }
52605303 Ottava* o = spdesc.isStarted ? toOttava (spdesc.sp ) : Factory::createOttava (m_score->dummy ());
52615304 stops.push_back (MusicXmlSpannerDesc (o, ElementType::OTTAVA, number));
52625305 }
@@ -5408,6 +5451,11 @@ void MusicXmlParserDirection::wedge(const String& type, const int number,
54085451 AsciiStringView niente = m_e.asciiAttribute (" niente" );
54095452 const MusicXmlExtendedSpannerDesc& spdesc = m_pass2.getSpanner ({ ElementType::HAIRPIN, number });
54105453 if (type == " crescendo" || type == " diminuendo" ) {
5454+ if (spannerExists (starts, number, ElementType::HAIRPIN)) {
5455+ m_logger->logError (String (u" hairpin with number %1 already started" ).arg (number), &m_e);
5456+ m_e.skipCurrentElement ();
5457+ return ;
5458+ }
54115459 Hairpin* h = spdesc.isStopped ? toHairpin (spdesc.sp ) : Factory::createHairpin (m_score->dummy ()->segment ());
54125460 h->setHairpinType (type == " crescendo"
54135461 ? HairpinType::CRESC_HAIRPIN : HairpinType::DIM_HAIRPIN);
@@ -5428,6 +5476,11 @@ void MusicXmlParserDirection::wedge(const String& type, const int number,
54285476 }
54295477 starts.push_back (MusicXmlSpannerDesc (h, ElementType::HAIRPIN, number));
54305478 } else if (type == " stop" ) {
5479+ if (spannerExists (stops, number, ElementType::HAIRPIN)) {
5480+ m_logger->logError (String (u" hairpin with number %1 already stopped" ).arg (number), &m_e);
5481+ m_e.skipCurrentElement ();
5482+ return ;
5483+ }
54315484 Hairpin* h = spdesc.isStarted ? toHairpin (spdesc.sp ) : Factory::createHairpin (m_score->dummy ()->segment ());
54325485 if (niente == " yes" ) {
54335486 h->setHairpinCircledTip (true );
0 commit comments