From e089df950b788f540836ae34022a038f2ca75f4b Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Mon, 9 Dec 2024 21:30:17 +0100 Subject: [PATCH 1/3] add forgotten color to trill ornaments --- src/importexport/mei/internal/meiconverter.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/importexport/mei/internal/meiconverter.cpp b/src/importexport/mei/internal/meiconverter.cpp index 8dc9957949f97..484ca90774b3e 100644 --- a/src/importexport/mei/internal/meiconverter.cpp +++ b/src/importexport/mei/internal/meiconverter.cpp @@ -3160,6 +3160,9 @@ Convert::OrnamStruct Convert::trillFromMEI(engraving::Ornament* ornament, const ornament->setSymId(symId); + // @color + Convert::colorFromMEI(ornament, meiTrill); + // Other attributes return Convert::ornamFromMEI(ornament, meiTrill, warning); } @@ -3177,6 +3180,9 @@ libmei::Trill Convert::trillToMEI(const engraving::Ornament* ornament) meiTrill.SetGlyphAuth(SMUFL_AUTH); } + // @color + Convert::colorToMEI(ornament, meiTrill); + return meiTrill; } From 42786cb78ec61791c076e28dcf66d3a3506c31ba Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Mon, 9 Dec 2024 21:34:12 +0100 Subject: [PATCH 2/3] add support for spanning trills --- src/importexport/mei/internal/meiexporter.cpp | 29 ++++++++++++++++++- src/importexport/mei/internal/meiexporter.h | 2 ++ src/importexport/mei/internal/meiimporter.cpp | 17 +++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/importexport/mei/internal/meiexporter.cpp b/src/importexport/mei/internal/meiexporter.cpp index 2cd73480e3ffa..6f83f991ff464 100644 --- a/src/importexport/mei/internal/meiexporter.cpp +++ b/src/importexport/mei/internal/meiexporter.cpp @@ -65,6 +65,7 @@ #include "engraving/dom/text.h" #include "engraving/dom/tie.h" #include "engraving/dom/timesig.h" +#include "engraving/dom/trill.h" #include "engraving/dom/tuplet.h" #include "engraving/dom/volta.h" @@ -837,6 +838,8 @@ bool MeiExporter::writeMeasure(const Measure* measure, int& measureN, bool& isFi success = success && this->writeTempo(dynamic_cast(controlEvent.first), controlEvent.second); } else if (controlEvent.first->isTie()) { success = success && this->writeTie(dynamic_cast(controlEvent.first), controlEvent.second); + } else if (controlEvent.first->isTrill()) { + success = success && this->writeTrill(dynamic_cast(controlEvent.first), controlEvent.second); } } m_startingControlEventList.clear(); @@ -2032,6 +2035,30 @@ bool MeiExporter::writeTie(const Tie* tie, const std::string& startid) return true; } +/** + * Write a trill. + */ + +bool MeiExporter::writeTrill(const Trill* trill, const std::string& startid) +{ + IF_ASSERT_FAILED(trill) { + return false; + } + + pugi::xml_node trillNode = m_currentNode.append_child(); + libmei::Trill meiTrill = Convert::trillToMEI(trill->ornament()); + Convert::colorlineToMEI(trill, meiTrill); + meiTrill.SetExtender(libmei::BOOLEAN_true); + meiTrill.SetStartid(startid); + + meiTrill.Write(trillNode, this->getXmlIdFor(trill, 't')); + + // Add the node to the map of open control events + this->addNodeToOpenControlEvents(trillNode, trill, startid); + + return true; +} + //--------------------------------------------------------- // write MEI attribute classes //--------------------------------------------------------- @@ -2157,7 +2184,7 @@ void MeiExporter::fillControlEventMap(const std::string& xmlId, const ChordRest* auto spanners = smap.findOverlapping(chordRest->tick().ticks(), chordRest->tick().ticks()); for (auto interval : spanners) { Spanner* spanner = interval.value; - if (spanner && (spanner->isHairpin() || spanner->isOttava() || spanner->isPedal() || spanner->isSlur())) { + if (spanner && (spanner->isHairpin() || spanner->isOttava() || spanner->isPedal() || spanner->isSlur() || spanner->isTrill())) { if (spanner->startCR() == chordRest) { m_startingControlEventList.push_back(std::make_pair(spanner, "#" + xmlId)); } else if (spanner->endCR() == chordRest) { diff --git a/src/importexport/mei/internal/meiexporter.h b/src/importexport/mei/internal/meiexporter.h index 218660aa8fc56..100464f32ea4a 100644 --- a/src/importexport/mei/internal/meiexporter.h +++ b/src/importexport/mei/internal/meiexporter.h @@ -51,6 +51,7 @@ class Rest; class Score; class Staff; class TremoloSingleChord; +class Trill; class Tuplet; class VBox; } @@ -143,6 +144,7 @@ class MeiExporter bool writeSlur(const engraving::Slur* slur, const std::string& startid); bool writeTempo(const engraving::TempoText* tempoText, const std::string& startid); bool writeTie(const engraving::Tie* tie, const std::string& startid); + bool writeTrill(const engraving::Trill* trill, const std::string& startid); /** * Methods for writing specific MEI attribute classes within elements diff --git a/src/importexport/mei/internal/meiimporter.cpp b/src/importexport/mei/internal/meiimporter.cpp index ae865ea176306..815c08705664c 100644 --- a/src/importexport/mei/internal/meiimporter.cpp +++ b/src/importexport/mei/internal/meiimporter.cpp @@ -497,6 +497,8 @@ Spanner* MeiImporter::addSpanner(const libmei::Element& meiElement, Measure* mea item = Factory::createPedal(chordRest->segment()); } else if (meiElement.m_name == "slur") { item = Factory::createSlur(chordRest->segment()); + } else if (meiElement.m_name == "trill") { + item = Factory::createTrill(chordRest->segment()); } else { return nullptr; } @@ -2885,6 +2887,17 @@ bool MeiImporter::readTrill(pugi::xml_node trillNode, Measure* measure) return true; } + if (meiTrill.HasEndid()) { + Trill* trill = static_cast(this->addSpanner(meiTrill, measure, trillNode)); + if (trill) { + // move ornament to spanner + ornament->parentItem()->remove(ornament); + trill->setOrnament(ornament); + // @color + Convert::colorlineFromMEI(trill, meiTrill); + } + } + Convert::OrnamStruct ornamSt = Convert::trillFromMEI(ornament, meiTrill, warning); this->setOrnamentAccid(ornament, ornamSt); @@ -3286,10 +3299,10 @@ void MeiImporter::addSpannerEnds() spannerMapEntry.first->setTick2(chordRest->tick()); spannerMapEntry.first->setEndElement(chordRest); spannerMapEntry.first->setTrack2(chordRest->track()); - if (spannerMapEntry.first->isOttava()) { + if (spannerMapEntry.first->isOttava() || spannerMapEntry.first->isTrill()) { // Set the tick2 to include the duration of the ChordRest spannerMapEntry.first->setTick2(chordRest->tick() + chordRest->ticks()); - // Special handling of ottava + // Special handling of ottavas if (spannerMapEntry.first->isOttava()) { Ottava* ottava = toOttava(spannerMapEntry.first); // Make the staff fill the pitch offsets accordingly since we use Note::ppitch in export From b2a2a2a9a3d0619cb3f2ccde54a0709867ebb28f Mon Sep 17 00:00:00 2001 From: rettinghaus Date: Mon, 9 Dec 2024 21:34:17 +0100 Subject: [PATCH 3/3] add test --- src/importexport/mei/tests/data/trill-01.mei | 170 ++++++ src/importexport/mei/tests/data/trill-01.mscx | 535 ++++++++++++++++++ src/importexport/mei/tests/mei_tests.cpp | 4 + 3 files changed, 709 insertions(+) create mode 100644 src/importexport/mei/tests/data/trill-01.mei create mode 100755 src/importexport/mei/tests/data/trill-01.mscx diff --git a/src/importexport/mei/tests/data/trill-01.mei b/src/importexport/mei/tests/data/trill-01.mei new file mode 100644 index 0000000000000..d70603189cda8 --- /dev/null +++ b/src/importexport/mei/tests/data/trill-01.mei @@ -0,0 +1,170 @@ + + + + + + + + The Art of Trill + + Klaus Rettinghaus + + + + + + + + + + + + + + + The Art of Trill + + + + + + Picc. + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+
+
+ +
+
diff --git a/src/importexport/mei/tests/data/trill-01.mscx b/src/importexport/mei/tests/data/trill-01.mscx new file mode 100755 index 0000000000000..5ea33e680566b --- /dev/null +++ b/src/importexport/mei/tests/data/trill-01.mscx @@ -0,0 +1,535 @@ + + + + 480 + + 1 + 1 + 1 + 0 + + Klaus Rettinghaus + + + <meiHead><fileDesc><titleStmt><title type="main">The Art of Trill</title><respStmt><persName role="composer">Klaus Rettinghaus</persName></respStmt></titleStmt><pubStmt><date isodate="2024-12-09T15:18:31"/></pubStmt></fileDesc></meiHead> + + + + + + The Art of Trill + + + + stdNormal + + + + + Piccolo + Picc. + + 7 + 12 + wind.flutes.flute.piccolo + + + + + + + 10 + + + The Art of Trill + + + + + + G + G + 1 + + + 2 + 4 + + + + trill + + ornamentTrill + + + + + 4 + + + + + half + + + + + + + 1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + -1 + + + + 83 + 19 + + + + + + + + + + -4 + + + + + + trill + + + accidentalSharp + + second,major + ornamentTrill + + + + + 4 + + + + + half + + + + + + + 1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + -1 + + + + 83 + 19 + + + + + + + + + + -4 + + + + + + trill + + + + + accidentalFlat + + second,minor + ornamentTrill + 1 + + + + + + 4 + + + + + half + + + + + + + 1 + + + + 84 + 14 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 84 + 14 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 84 + 14 + + + + + + + + half + + + + + -1 + + + + 84 + 14 + + + + + + + + + + -4 + + + + + + trill + + second,minor + ornamentTrill + 0 + + + + + 3 + 1/2 + + + + + half + + + + + + + 1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + + + 1 + + + + + + + -1 + + + + 83 + 19 + + + + + + + + half + + + + + -1 + + + + 83 + 19 + + + + + + -3 + -1/2 + + + + + + + -3 + -1/2 + + + + + end + + + + + + diff --git a/src/importexport/mei/tests/mei_tests.cpp b/src/importexport/mei/tests/mei_tests.cpp index c212a23aa316c..2c8f20d8942ad 100644 --- a/src/importexport/mei/tests/mei_tests.cpp +++ b/src/importexport/mei/tests/mei_tests.cpp @@ -307,6 +307,10 @@ TEST_F(Mei_Tests, mei_transpose_01) { meiReadTest("transpose-01"); } +TEST_F(Mei_Tests, mei_trill_01) { + meiReadTest("trill-01"); +} + TEST_F(Mei_Tests, mei_tuplet_01) { meiReadTest("tuplet-01"); }