diff --git a/src/include/mx/api/MarkData.h b/src/include/mx/api/MarkData.h index 4fb831b0..a5489d07 100644 --- a/src/include/mx/api/MarkData.h +++ b/src/include/mx/api/MarkData.h @@ -34,7 +34,12 @@ enum class MarkType doit, falloff, breathMark, - caesura, + caesura, // an empty , the common form; renders the same as caesuraNormal + caesuraNormal, + caesuraThick, + caesuraShort, + caesuraCurved, + caesuraSingle, stress, unstress, softAccent, diff --git a/src/private/mx/api/MarkData.cpp b/src/private/mx/api/MarkData.cpp index f5e6bf8d..ca546eb7 100644 --- a/src/private/mx/api/MarkData.cpp +++ b/src/private/mx/api/MarkData.cpp @@ -105,8 +105,11 @@ bool isMarkArticulation(MarkType markType) (markType == MarkType::detachedLegato) || (markType == MarkType::staccatissimo) || (markType == MarkType::spiccato) || (markType == MarkType::scoop) || (markType == MarkType::plop) || (markType == MarkType::doit) || (markType == MarkType::falloff) || (markType == MarkType::breathMark) || - (markType == MarkType::caesura) || (markType == MarkType::stress) || (markType == MarkType::unstress) || - (markType == MarkType::softAccent) || (markType == MarkType::otherArticulation); + (markType == MarkType::caesura) || (markType == MarkType::caesuraNormal) || + (markType == MarkType::caesuraThick) || (markType == MarkType::caesuraShort) || + (markType == MarkType::caesuraCurved) || (markType == MarkType::caesuraSingle) || + (markType == MarkType::stress) || (markType == MarkType::unstress) || (markType == MarkType::softAccent) || + (markType == MarkType::otherArticulation); } bool isMarkOrnament(MarkType markType) diff --git a/src/private/mx/impl/ArticulationsFunctions.cpp b/src/private/mx/impl/ArticulationsFunctions.cpp index 4bcdbe16..2e5cdc1c 100644 --- a/src/private/mx/impl/ArticulationsFunctions.cpp +++ b/src/private/mx/impl/ArticulationsFunctions.cpp @@ -4,6 +4,7 @@ #include "mx/impl/ArticulationsFunctions.h" #include "mx/core/generated/ArticulationsChoice.h" +#include "mx/core/generated/CaesuraValue.h" #include "mx/impl/Converter.h" #include "mx/impl/MarkDataFunctions.h" #include "mx/impl/PositionFunctions.h" @@ -108,6 +109,27 @@ void ArticulationsFunctions::parseArticulation(const core::ArticulationsChoice & case core::ArticulationsChoice::Kind::caesura: { parseMarkDataAttributes(inArticulation.asCaesura(), outMark); outMark.name = "caesura"; + switch (inArticulation.asCaesura().value().tag()) + { + case core::CaesuraValue::Tag::empty: + outMark.markType = api::MarkType::caesura; + break; + case core::CaesuraValue::Tag::normal: + outMark.markType = api::MarkType::caesuraNormal; + break; + case core::CaesuraValue::Tag::thick: + outMark.markType = api::MarkType::caesuraThick; + break; + case core::CaesuraValue::Tag::short_: + outMark.markType = api::MarkType::caesuraShort; + break; + case core::CaesuraValue::Tag::curved: + outMark.markType = api::MarkType::caesuraCurved; + break; + case core::CaesuraValue::Tag::single: + outMark.markType = api::MarkType::caesuraSingle; + break; + } break; } case core::ArticulationsChoice::Kind::stress: { diff --git a/src/private/mx/impl/Converter.cpp b/src/private/mx/impl/Converter.cpp index 386be73e..299c1422 100644 --- a/src/private/mx/impl/Converter.cpp +++ b/src/private/mx/impl/Converter.cpp @@ -174,6 +174,11 @@ const Converter::EnumMap Convert {core::ArticulationsChoice::Kind::falloff, api::MarkType::falloff}, {core::ArticulationsChoice::Kind::breathMark, api::MarkType::breathMark}, {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesura}, + {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesuraNormal}, + {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesuraThick}, + {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesuraShort}, + {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesuraCurved}, + {core::ArticulationsChoice::Kind::caesura, api::MarkType::caesuraSingle}, {core::ArticulationsChoice::Kind::stress, api::MarkType::stress}, {core::ArticulationsChoice::Kind::unstress, api::MarkType::unstress}, {core::ArticulationsChoice::Kind::softAccent, api::MarkType::softAccent}, diff --git a/src/private/mx/impl/NotationsWriter.cpp b/src/private/mx/impl/NotationsWriter.cpp index cf7312ec..49f1613c 100644 --- a/src/private/mx/impl/NotationsWriter.cpp +++ b/src/private/mx/impl/NotationsWriter.cpp @@ -11,6 +11,7 @@ #include "mx/core/generated/ArticulationsChoice.h" #include "mx/core/generated/BreathMark.h" #include "mx/core/generated/Caesura.h" +#include "mx/core/generated/CaesuraValue.h" #include "mx/core/generated/EmptyLine.h" #include "mx/core/generated/EmptyPlacement.h" #include "mx/core/generated/EmptyPlacementSmufl.h" @@ -542,6 +543,30 @@ void NotationsWriter::addArticulation(const api::MarkData &mark, core::Articulat case core::ArticulationsChoice::Kind::caesura: { core::Caesura c; setAttributesFromPositionData(mark.positionData, c); + // MarkType::caesura is the common empty form ; the variants carry an + // explicit text value. + auto caesuraValue = core::CaesuraValue::empty(); + if (mark.markType == api::MarkType::caesuraNormal) + { + caesuraValue = core::CaesuraValue::normal(); + } + else if (mark.markType == api::MarkType::caesuraThick) + { + caesuraValue = core::CaesuraValue::thick(); + } + else if (mark.markType == api::MarkType::caesuraShort) + { + caesuraValue = core::CaesuraValue::short_(); + } + else if (mark.markType == api::MarkType::caesuraCurved) + { + caesuraValue = core::CaesuraValue::curved(); + } + else if (mark.markType == api::MarkType::caesuraSingle) + { + caesuraValue = core::CaesuraValue::single(); + } + c.setValue(caesuraValue); outArticulations.addChoice(core::ArticulationsChoice::caesura(c)); break; } diff --git a/src/private/mxtest/api/MarkRoundTripTest.cpp b/src/private/mxtest/api/MarkRoundTripTest.cpp index de76fcc1..191a90e7 100644 --- a/src/private/mxtest/api/MarkRoundTripTest.cpp +++ b/src/private/mxtest/api/MarkRoundTripTest.cpp @@ -268,4 +268,24 @@ TEST(NonArpeggiateAttributes, MarkRoundTrip) T_END; +TEST(CaesuraEmpty, MarkRoundTrip) +{ + // The common empty form must not acquire a "normal" text value on write. + const auto marks = roundTripMark(MarkType::caesura); + CHECK(hasMark(marks, MarkType::caesura)); +} + +T_END; + +TEST(CaesuraVariants, MarkRoundTrip) +{ + CHECK(hasMark(roundTripMark(MarkType::caesuraNormal), MarkType::caesuraNormal)); + CHECK(hasMark(roundTripMark(MarkType::caesuraThick), MarkType::caesuraThick)); + CHECK(hasMark(roundTripMark(MarkType::caesuraShort), MarkType::caesuraShort)); + CHECK(hasMark(roundTripMark(MarkType::caesuraCurved), MarkType::caesuraCurved)); + CHECK(hasMark(roundTripMark(MarkType::caesuraSingle), MarkType::caesuraSingle)); +} + +T_END; + #endif diff --git a/src/private/mxtest/api/roundtrip-baseline.txt b/src/private/mxtest/api/roundtrip-baseline.txt index c21fbe8c..70314f43 100644 --- a/src/private/mxtest/api/roundtrip-baseline.txt +++ b/src/private/mxtest/api/roundtrip-baseline.txt @@ -407,3 +407,10 @@ synthetic/arpeggiate.3.1.xml synthetic/arpeggiate.4.0.xml synthetic/non-arpeggiate.3.0.xml synthetic/non-arpeggiate.3.1.xml + +# Unblocked by the caesura value fix: MarkType::caesura now round-trips the +# common empty element form, and the caesuraNormal/Thick/Short/Curved/Single +# variants carry an explicit text value. +ksuite/k001a_Articulations.xml +musuite/testNoteAttributes2.xml +musuite/testNoteAttributes2_ref.xml