Skip to content

Commit c4ab947

Browse files
rettinghausJojo-Schmitz
authored andcommitted
[MusicXML] invisible notations
Backport of musescore#27422
1 parent 919eccc commit c4ab947

File tree

5 files changed

+387
-105
lines changed

5 files changed

+387
-105
lines changed

importexport/musicxml/exportxml.cpp

+74-61
Original file line numberDiff line numberDiff line change
@@ -188,11 +188,12 @@ void Attributes::stop(XmlWriter& xml)
188188
//---------------------------------------------------------
189189

190190
class Notations {
191-
bool notationsPrinted;
191+
bool notationsPrinted = false;
192+
bool prevElementVisible = true;
192193

193194
public:
194195
Notations() { notationsPrinted = false; }
195-
void tag(XmlWriter& xml);
196+
void tag(XmlWriter& xml, const Element* e = nullptr);
196197
void etag(XmlWriter& xml);
197198
};
198199

@@ -525,11 +526,27 @@ static QString positioningAttributes(Element const* const el, bool isSpanStart =
525526
// tag
526527
//---------------------------------------------------------
527528

528-
void Notations::tag(XmlWriter& xml)
529+
void Notations::tag(XmlWriter& xml, const Element* e)
529530
{
530-
if (!notationsPrinted)
531-
xml.stag("notations");
531+
if (!e) {
532+
if (!notationsPrinted)
533+
xml.stag("notations");
534+
notationsPrinted = true;
535+
return;
536+
}
537+
538+
if (notationsPrinted && prevElementVisible != e->visible())
539+
etag(xml);
540+
541+
if (!notationsPrinted) {
542+
if (e->visible())
543+
xml.stag("notations");
544+
else
545+
xml.stag("notations print-object=\"no\"");
546+
}
547+
532548
notationsPrinted = true;
549+
prevElementVisible = e->visible();
533550
}
534551

535552
//---------------------------------------------------------
@@ -784,7 +801,7 @@ void SlurHandler::doSlurs(const ChordRest* chordRest, Notations& notations, XmlW
784801
// search for slur(s) starting or stopping at this chord
785802
for (const auto& it : chordRest->score()->spanner()) {
786803
auto sp = it.second;
787-
if (sp->generated() || sp->type() != ElementType::SLUR || !ExportMusicXml::canWrite(sp))
804+
if (sp->generated() || sp->type() != ElementType::SLUR)
788805
continue;
789806
if (chordRest == sp->startElement() || chordRest == sp->endElement()) {
790807
const Slur* s = static_cast<const Slur*>(sp);
@@ -824,7 +841,7 @@ void SlurHandler::doSlurStart(const Slur* s, Notations& notations, XmlWriter& xm
824841
// remove from list and print start
825842
slur[i] = 0;
826843
started[i] = false;
827-
notations.tag(xml);
844+
notations.tag(xml, s);
828845
tagName += QString(" number=\"%1\"").arg(i + 1);
829846
xml.tagE(tagName);
830847
}
@@ -834,7 +851,7 @@ void SlurHandler::doSlurStart(const Slur* s, Notations& notations, XmlWriter& xm
834851
if (i >= 0) {
835852
slur[i] = s;
836853
started[i] = true;
837-
notations.tag(xml);
854+
notations.tag(xml, s);
838855
tagName += QString(" number=\"%1\"").arg(i + 1);
839856
xml.tagE(tagName);
840857
}
@@ -863,7 +880,7 @@ void SlurHandler::doSlurStop(const Slur* s, Notations& notations, XmlWriter& xml
863880
if (i >= 0) {
864881
slur[i] = s;
865882
started[i] = false;
866-
notations.tag(xml);
883+
notations.tag(xml, s);
867884
QString tagName = QString("slur type=\"stop\" number=\"%1\"").arg(i + 1);
868885
tagName += positioningAttributes(s, false);
869886
xml.tagE(tagName);
@@ -875,7 +892,7 @@ void SlurHandler::doSlurStop(const Slur* s, Notations& notations, XmlWriter& xml
875892
// found (already started), stop it and remove from list
876893
slur[i] = 0;
877894
started[i] = false;
878-
notations.tag(xml);
895+
notations.tag(xml, s);
879896
QString tagName = QString("slur type=\"stop\" number=\"%1\"").arg(i + 1);
880897
tagName += positioningAttributes(s, false);
881898
xml.tagE(tagName);
@@ -922,7 +939,7 @@ static void glissando(const Glissando* gli, int number, bool start, Notations& n
922939
tagName += color2xml(gli);
923940
tagName += positioningAttributes(gli, start);
924941
}
925-
notations.tag(xml);
942+
notations.tag(xml, gli);
926943
if (start && gli->showText() && !gli->text().isEmpty())
927944
xml.tag(tagName, gli->text());
928945
else
@@ -1051,7 +1068,7 @@ static void findTrills(const Measure* const measure, int strack, int etrack, Tri
10511068
for (auto it = measure->score()->spanner().lower_bound(stick.ticks()); it != measure->score()->spanner().upper_bound(etick.ticks()); ++it) {
10521069
Element* e = it->second;
10531070
//qDebug("1 trill %p type %d track %d tick %s", e, e->type(), e->track(), qPrintable(e->tick().print()));
1054-
if (e->isTrill() && ExportMusicXml::canWrite(e) && strack <= e->track() && e->track() < etrack
1071+
if (e->isTrill() && strack <= e->track() && e->track() < etrack
10551072
&& e->tick() >= measure->tick() && e->tick() < (measure->tick() + measure->ticks()))
10561073
{
10571074
//qDebug("2 trill %p", e);
@@ -2550,7 +2567,7 @@ static void tupletActualAndNormal(const Tuplet* const t, XmlWriter& xml)
25502567

25512568
static void tupletStart(const Tuplet* const t, const int number, const bool needActualAndNormal, Notations& notations, XmlWriter& xml)
25522569
{
2553-
notations.tag(xml);
2570+
notations.tag(xml, t);
25542571
QString tupletTag = "tuplet type=\"start\"";
25552572
if (!isSimpleTuplet(t))
25562573
tupletTag += QString(" number=\"%1\"").arg(number);
@@ -2581,7 +2598,7 @@ static void tupletStart(const Tuplet* const t, const int number, const bool need
25812598

25822599
static void tupletStop(const Tuplet* const t, const int number, Notations& notations, XmlWriter& xml)
25832600
{
2584-
notations.tag(xml);
2601+
notations.tag(xml, t);
25852602
QString tupletTag = "tuplet type=\"stop\"";
25862603
if (!isSimpleTuplet(t))
25872604
tupletTag += QString(" number=\"%1\"").arg(number);
@@ -2695,7 +2712,7 @@ static void writeDisplayName(XmlWriter& xml, const QString& partName)
26952712

26962713
static void wavyLineStart(const Trill* tr, const int number, Notations& notations, Ornaments& ornaments, XmlWriter& xml)
26972714
{
2698-
notations.tag(xml);
2715+
notations.tag(xml, tr);
26992716
ornaments.tag(xml);
27002717
switch (tr->trillType()) {
27012718
case Trill::Type::TRILL_LINE:
@@ -2725,7 +2742,7 @@ static void wavyLineStart(const Trill* tr, const int number, Notations& notation
27252742

27262743
static void wavyLineStop(const Trill* tr, const int number, Notations& notations, Ornaments& ornaments, XmlWriter& xml)
27272744
{
2728-
notations.tag(xml);
2745+
notations.tag(xml, tr);
27292746
ornaments.tag(xml);
27302747
QString trillXml = QString("wavy-line type=\"stop\" number=\"%1\"").arg(number + 1);
27312748
trillXml += positioningAttributes(tr, false);
@@ -2798,7 +2815,7 @@ void ExportMusicXml::wavyLineStartStop(const ChordRest* const cr, Notations& not
27982815
static void tremoloSingleStartStop(Chord* chord, Notations& notations, Ornaments& ornaments, XmlWriter& xml)
27992816
{
28002817
Tremolo* tr = chord->tremolo();
2801-
if (tr && ExportMusicXml::canWrite(tr)) {
2818+
if (tr) {
28022819
int count = 0;
28032820
TremoloType st = tr->tremoloType();
28042821
QString type;
@@ -2843,7 +2860,7 @@ static void tremoloSingleStartStop(Chord* chord, Notations& notations, Ornaments
28432860

28442861

28452862
if (!type.isEmpty() && ((count > 0 && type != "unmeasured") || (count == 0 && type == "unmeasured"))) {
2846-
notations.tag(xml);
2863+
notations.tag(xml, tr);
28472864
ornaments.tag(xml);
28482865
QString tagName = "tremolo";
28492866
tagName += QString(" type=\"%1\"").arg(type);
@@ -2861,9 +2878,9 @@ static void tremoloSingleStartStop(Chord* chord, Notations& notations, Ornaments
28612878
static void fermatas(const QVector<Element*>& cra, XmlWriter& xml, Notations& notations)
28622879
{
28632880
for (const Element* e : cra) {
2864-
if (!e->isFermata() || !ExportMusicXml::canWrite(e))
2881+
if (!e->isFermata())
28652882
continue;
2866-
notations.tag(xml);
2883+
notations.tag(xml, e);
28672884
fermata(toFermata(e), xml);
28682885
}
28692886
}
@@ -3115,9 +3132,9 @@ static void writeChordLines(const Chord* const chord, XmlWriter& xml, Notations&
31153132
default:
31163133
qDebug("unknown ChordLine subtype %d", int(cl->chordLineType()));
31173134
}
3118-
subtype += color2xml(cl);
31193135
if (!subtype.isEmpty()) {
3120-
notations.tag(xml);
3136+
subtype += color2xml(cl);
3137+
notations.tag(xml, cl);
31213138
articulations.tag(xml);
31223139
xml.tagE(subtype);
31233140
}
@@ -3131,11 +3148,11 @@ static void writeChordLines(const Chord* const chord, XmlWriter& xml, Notations&
31313148

31323149
static void writeBreathMark(const Breath* const breath, XmlWriter& xml, Notations& notations, Articulations& articulations)
31333150
{
3134-
if (breath && ExportMusicXml::canWrite(breath)) {
3151+
if (breath) {
31353152
QString tagName;
31363153
QString type;
31373154

3138-
notations.tag(xml);
3155+
notations.tag(xml, breath);
31393156
articulations.tag(xml);
31403157
if (breath->isCaesura()) {
31413158
tagName = "caesura";
@@ -3214,9 +3231,6 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
32143231
// first the attributes whose elements are children of <articulations>
32153232
Articulations articulations;
32163233
for (const Articulation* a : na) {
3217-
if (!ExportMusicXml::canWrite(a))
3218-
continue;
3219-
32203234
SymId sid = a->symId();
32213235
std::vector<QString> mxmlArtics = symIdToArtics(sid);
32223236

@@ -3237,7 +3251,7 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
32373251
mxmlArtic += color2xml(a);
32383252
mxmlArtic += positioningAttributes(a);
32393253

3240-
notations.tag(_xml);
3254+
notations.tag(_xml, a);
32413255
articulations.tag(_xml);
32423256
_xml.tagE(mxmlArtic);
32433257
}
@@ -3251,8 +3265,6 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
32513265
// then the attributes whose elements are children of <ornaments>
32523266
Ornaments ornaments;
32533267
for (const Articulation* a : na) {
3254-
if (!ExportMusicXml::canWrite(a))
3255-
continue;
32563268
if (!a->isOrnament())
32573269
continue;
32583270

@@ -3266,7 +3278,7 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
32663278
mxmlOrnam += QString(" placement=\"%1\"").arg(placement);
32673279
mxmlOrnam += color2xml(a);
32683280

3269-
notations.tag(_xml);
3281+
notations.tag(_xml, a);
32703282
ornaments.tag(_xml);
32713283
_xml.tagE(mxmlOrnam);
32723284
// accidental-mark is missing
@@ -3279,9 +3291,6 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
32793291

32803292
// and finally the attributes whose elements are children of <technical>
32813293
for (const Articulation* a : na) {
3282-
if (!ExportMusicXml::canWrite(a))
3283-
continue;
3284-
32853294
SymId sid = a->symId();
32863295
QString placement;
32873296
QString direction;
@@ -3303,7 +3312,7 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
33033312

33043313
QString mxmlTechn = symIdToTechn(sid);
33053314
if (!mxmlTechn.isEmpty()) {
3306-
notations.tag(_xml);
3315+
notations.tag(_xml, a);
33073316
technical.tag(_xml);
33083317
mxmlTechn += color2xml(a);
33093318
mxmlTechn += positioningAttributes(a);
@@ -3369,9 +3378,6 @@ void ExportMusicXml::chordAttributes(Chord* chord, Notations& notations, Technic
33693378

33703379
// check if all articulations were handled
33713380
for (const Articulation* a : na) {
3372-
if (!ExportMusicXml::canWrite(a))
3373-
continue;
3374-
33753381
SymId sid = a->symId();
33763382
if (symIdToArtics(sid).empty()
33773383
&& symIdToTechn(sid).isEmpty()
@@ -3411,32 +3417,29 @@ static Arpeggio* findArpeggio(Note* note)
34113417

34123418
static void arpeggiate(Arpeggio* arp, bool front, bool back, XmlWriter& xml, Notations& notations)
34133419
{
3414-
if (!ExportMusicXml::canWrite(arp))
3415-
return;
3416-
34173420
QString tagName;
34183421
switch (arp->arpeggioType()) {
34193422
case ArpeggioType::NORMAL:
3420-
notations.tag(xml);
3423+
notations.tag(xml, arp);
34213424
tagName = "arpeggiate";
34223425
break;
34233426
case ArpeggioType::UP: // fall through
34243427
case ArpeggioType::UP_STRAIGHT: // not supported by MusicXML, export as normal arpeggio
3425-
notations.tag(xml);
3428+
notations.tag(xml, arp);
34263429
tagName = "arpeggiate direction=\"up\"";
34273430
break;
34283431
case ArpeggioType::DOWN: // fall through
34293432
case ArpeggioType::DOWN_STRAIGHT: // not supported by MusicXML, export as normal arpeggio
3430-
notations.tag(xml);
3433+
notations.tag(xml, arp);
34313434
tagName = "arpeggiate direction=\"down\"";
34323435
break;
34333436
case ArpeggioType::BRACKET:
34343437
if (front) {
3435-
notations.tag(xml);
3438+
notations.tag(xml, arp);
34363439
tagName = "non-arpeggiate type=\"bottom\"";
34373440
}
34383441
if (back) {
3439-
notations.tag(xml);
3442+
notations.tag(xml, arp);
34403443
tagName = "non-arpeggiate type=\"top\"";
34413444
}
34423445
break;
@@ -3666,12 +3669,9 @@ static void writeNotehead(XmlWriter& xml, const Note* const note)
36663669
static void writeFingering(XmlWriter& xml, Notations& notations, Technical& technical, const Note* const note)
36673670
{
36683671
for (const Element* e : note->el()) {
3669-
if (!ExportMusicXml::canWrite(e))
3670-
continue;
3671-
36723672
if (e->type() == ElementType::FINGERING) {
36733673
const TextBase* f = toTextBase(e);
3674-
notations.tag(xml);
3674+
notations.tag(xml, e);
36753675
technical.tag(xml);
36763676
QString t = MScoreTextToMXML::toPlainText(f->xmlText());
36773677
QString attr;
@@ -4021,20 +4021,30 @@ void ExportMusicXml::chord(Chord* chord, int staff, const std::vector<Lyrics*>*
40214021
Technical technical;
40224022

40234023
const Tie* tieBack = note->tieBack();
4024-
if (tieBack && ExportMusicXml::canWrite(tieBack)) {
4025-
notations.tag(_xml);
4024+
if (tieBack) {
4025+
notations.tag(_xml, tieBack);
40264026
_xml.tagE("tied type=\"stop\"");
40274027
}
4028+
#if 0 // TODO
4029+
const LaissezVib* laissezVib = note->laissezVib();
4030+
if (laissezVib) {
4031+
notations.tag(_xml, laissezVib);
4032+
_xml.tagE(QString("tied type=\"let-ring\"%1").arg(rest));
4033+
}
40284034
const Tie* tieFor = note->tieFor();
4029-
if (tieFor && ExportMusicXml::canWrite(tieFor)) {
4035+
if (tieFor/* && !laissezVib*/) {
4036+
#else
4037+
if (hasLaissezVibrer(chord)) {
40304038
notations.tag(_xml);
4039+
_xml.tagE("tied type=\"let-ring\"");
4040+
}
4041+
const Tie* tieFor = note->tieFor();
4042+
if (tieFor) {
4043+
#endif
4044+
notations.tag(_xml, tieFor);
40314045
QString rest = slurTieLineStyle(tieFor);
40324046
_xml.tagE(QString("tied type=\"start\"%1").arg(rest));
40334047
}
4034-
if (hasLaissezVibrer(chord)/* && ExportMusicXml::canWrite(laissezVibrer)*/) {
4035-
notations.tag(_xml);
4036-
_xml.tagE("tied type=\"let-ring\"");
4037-
}
40384048

40394049
if (note == nl.front()) {
40404050
if (!grace)
@@ -4050,7 +4060,7 @@ void ExportMusicXml::chord(Chord* chord, int staff, const std::vector<Lyrics*>*
40504060
// write tablature string / fret
40514061
if (chord->staff() && chord->staff()->isTabStaff(Fraction(0,1)))
40524062
if (note->fret() >= 0 && note->string() >= 0) {
4053-
notations.tag(_xml);
4063+
notations.tag(_xml, note);
40544064
technical.tag(_xml);
40554065
_xml.tag("string", note->string() + 1);
40564066
_xml.tag("fret", note->fret());
@@ -4061,11 +4071,11 @@ void ExportMusicXml::chord(Chord* chord, int staff, const std::vector<Lyrics*>*
40614071
arpeggiate(arp, note == nl.front(), note == nl.back(), _xml, notations);
40624072
}
40634073
for (Spanner* spanner : note->spannerFor())
4064-
if (spanner->type() == ElementType::GLISSANDO && ExportMusicXml::canWrite(spanner)) {
4074+
if (spanner->type() == ElementType::GLISSANDO) {
40654075
gh.doGlissandoStart(static_cast<Glissando*>(spanner), notations, _xml);
40664076
}
40674077
for (Spanner* spanner : note->spannerBack())
4068-
if (spanner->type() == ElementType::GLISSANDO && ExportMusicXml::canWrite(spanner)) {
4078+
if (spanner->type() == ElementType::GLISSANDO) {
40694079
gh.doGlissandoStop(static_cast<Glissando*>(spanner), notations, _xml);
40704080
}
40714081
// write glissando (only for last note)
@@ -5813,6 +5823,9 @@ static void measureStyle(XmlWriter& xml, Attributes& attr, const Measure* const
58135823

58145824
static bool commonAnnotations(ExportMusicXml* exp, const Element* e, int sstaff)
58155825
{
5826+
if (!exp->canWrite(e))
5827+
return false;
5828+
58165829
bool instrChangeHandled = false;
58175830

58185831
// note: the instrument change details are handled in ExportMusicXml::writeMeasureTracks,
@@ -7595,7 +7608,7 @@ void ExportMusicXml::writeMeasure(const Measure* const m,
75957608
writeInstrumentDetails(part->instrument(), _score->styleB(Sid::concertPitch));
75967609
}
75977610
else {
7598-
for (size_t staffIdx : _hiddenStaves) {
7611+
for (int& staffIdx : _hiddenStaves) {
75997612
_attr.doAttr(_xml, true);
76007613
QString attributes;
76017614
if (staves > 1)

0 commit comments

Comments
 (0)