cleared up DynamicType enum

This commit is contained in:
Igor Korsukov 2021-12-10 14:15:19 +02:00
parent d100ab95a0
commit 0037fb35c6
12 changed files with 247 additions and 159 deletions

View file

@ -22,6 +22,7 @@
#include "dynamic.h"
#include "style/style.h"
#include "rw/xml.h"
#include "types/typesconv.h"
#include "dynamichairpingroup.h"
#include "score.h"
@ -45,65 +46,62 @@ namespace Ms {
//-----------------------------------------------------------------------------
struct Dyn {
DynamicType type;
int velocity; ///< associated midi velocity (0-127, -1 = none)
bool accent; ///< if true add velocity to current chord velocity
SymId symId;
const char* tag; // name of dynamics, eg. "fff"
const char* text; // utf8 text of dynamic
int changeInVelocity;
bool accent; ///< if true add velocity to current chord velocity
const char* text; // utf8 text of dynamic
};
// variant with ligatures, works for both emmentaler and bravura:
static Dyn dynList[] = {
// dynamic:
{ -1, true, SymId::noSym, "other-dynamics", "", 0 },
{ 1, false, SymId::dynamicPPPPPP, "pppppp",
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>",
0 },
{ 5, false, SymId::dynamicPPPPP, "ppppp",
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
{ 10, false, SymId::dynamicPPPP, "pppp",
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
{ 16, false, SymId::dynamicPPP, "ppp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
{ 33, false, SymId::dynamicPP, "pp", "<sym>dynamicPiano</sym><sym>dynamicPiano</sym>", 0 },
{ 49, false, SymId::dynamicPiano, "p", "<sym>dynamicPiano</sym>", 0 },
{ 64, false, SymId::dynamicMP, "mp", "<sym>dynamicMezzo</sym><sym>dynamicPiano</sym>", 0 },
{ 80, false, SymId::dynamicMF, "mf", "<sym>dynamicMezzo</sym><sym>dynamicForte</sym>", 0 },
{ 96, false, SymId::dynamicForte, "f", "<sym>dynamicForte</sym>", 0 },
{ 112, false, SymId::dynamicFF, "ff", "<sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
{ 126, false, SymId::dynamicFFF, "fff", "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
{ 127, false, SymId::dynamicFFFF, "ffff",
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
{ 127, false, SymId::dynamicFFFFF, "fffff",
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>", 0 },
{ 127, false, SymId::dynamicFFFFFF, "ffffff",
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>",
0 },
{ DynamicType::OTHER, -1, 0, true, "" },
{ DynamicType::PPPPPP, 1, 0, false,
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::PPPPP, 5, 0, false,
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::PPPP, 10, 0, false,
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::PPP, 16, 0, false,
"<sym>dynamicPiano</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::PP, 33, 0, false, "<sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::P, 49, 0, false, "<sym>dynamicPiano</sym>" },
// accents:
{ 96, true, SymId::dynamicFortePiano, "fp", "<sym>dynamicForte</sym><sym>dynamicPiano</sym>", -47 },
{ 49, true, SymId::noSym, "pf", "<sym>dynamicPiano</sym><sym>dynamicForte</sym>", 47 },
{ 112, true, SymId::dynamicSforzando1, "sf", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym>", -18 },
{ 112, true, SymId::dynamicSforzato, "sfz", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>",
-18 },
{ 126, true, SymId::noSym, "sff", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>",
-18 },
{ 126, true, SymId::dynamicSforzatoFF, "sffz",
"<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
{ 112, true, SymId::dynamicSforzandoPiano, "sfp", "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym>",
-47 },
{ 112, true, SymId::dynamicSforzandoPianissimo, "sfpp",
"<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>", -79 },
{ 112, true, SymId::dynamicRinforzando2, "rfz", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>",
-18 },
{ 112, true, SymId::dynamicRinforzando1, "rf", "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym>", -18 },
{ 112, true, SymId::dynamicForzando, "fz", "<sym>dynamicForte</sym><sym>dynamicZ</sym>", -18 },
{ 96, true, SymId::dynamicMezzo, "m", "<sym>dynamicMezzo</sym>", -16 },
{ 112, true, SymId::dynamicRinforzando, "r", "<sym>dynamicRinforzando</sym>", -18 },
{ 112, true, SymId::dynamicSforzando, "s", "<sym>dynamicSforzando</sym>", -18 },
{ 80, true, SymId::dynamicZ, "z", "<sym>dynamicZ</sym>", 0 },
{ 49, true, SymId::dynamicNiente, "n", "<sym>dynamicNiente</sym>", -48 }
{ DynamicType::MP, 64, 0, false, "<sym>dynamicMezzo</sym><sym>dynamicPiano</sym>" },
{ DynamicType::MF, 80, 0, false, "<sym>dynamicMezzo</sym><sym>dynamicForte</sym>" },
{ DynamicType::F, 96, 0, false, "<sym>dynamicForte</sym>" },
{ DynamicType::FF, 112, 0, false, "<sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::FFF, 126, 0, false, "<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::FFFF, 127, 0, false,
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::FFFFF, 127, 0, false,
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::FFFFFF, 127, 0, false,
"<sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::FP, 96, -47, true, "<sym>dynamicForte</sym><sym>dynamicPiano</sym>" },
{ DynamicType::PF, 49, 47, true, "<sym>dynamicPiano</sym><sym>dynamicForte</sym>" },
{ DynamicType::SF, 112, -18, true, "<sym>dynamicSforzando</sym><sym>dynamicForte</sym>" },
{ DynamicType::SFZ, 112, -18, true, "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>" },
{ DynamicType::SFF, 126, -18, true, "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym>" },
{ DynamicType::SFFZ, 126, -18, true,
"<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>" },
{ DynamicType::SFP, 112, -47, true, "<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym>" },
{ DynamicType::SFPP, 112, -79, true,
"<sym>dynamicSforzando</sym><sym>dynamicForte</sym><sym>dynamicPiano</sym><sym>dynamicPiano</sym>" },
{ DynamicType::RFZ, 112, -18, true, "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym><sym>dynamicZ</sym>" },
{ DynamicType::RF, 112, -18, true, "<sym>dynamicRinforzando</sym><sym>dynamicForte</sym>" },
{ DynamicType::FZ, 112, -18, true, "<sym>dynamicForte</sym><sym>dynamicZ</sym>" },
{ DynamicType::M, 96, -16, true, "<sym>dynamicMezzo</sym>" },
{ DynamicType::R, 112, -18, true, "<sym>dynamicRinforzando</sym>" },
{ DynamicType::S, 112, -18, true, "<sym>dynamicSforzando</sym>" },
{ DynamicType::Z, 80, 0, true, "<sym>dynamicZ</sym>" },
{ DynamicType::N, 49, -48, true, "<sym>dynamicNiente</sym>" }
};
//---------------------------------------------------------
@ -125,45 +123,6 @@ const std::vector<Dynamic::ChangeSpeedItem> Dynamic::changeSpeedTable {
{ Dynamic::Speed::FAST, "fast" },
};
//---------------------------------------------------------
// findInString
//---------------------------------------------------------
// find the longest first match of dynList's dynamic text in s
// used by the MusicXML export to correctly export dynamics embedded
// in spanner begin- or endtexts
// return match's position and length and the dynamic type
int Dynamic::findInString(const QString& s, int& length, QString& type)
{
length = 0;
type = "";
int matchIndex { -1 };
const int n = sizeof(dynList) / sizeof(*dynList);
// for all dynamics, find their text in s
for (int i = 0; i < n; ++i) {
const QString dynamicText = dynList[i].text;
const int dynamicLength = dynamicText.length();
// note: skip entries with empty text
if (dynamicLength > 0) {
const auto index = s.indexOf(dynamicText);
if (index >= 0) {
// found a match, accept it if
// - it is the first one
// - or it starts a the same index but is longer ("pp" versus "p")
if (matchIndex == -1 || (index == matchIndex && dynamicLength > length)) {
matchIndex = index;
length = dynamicLength;
type = dynList[i].tag;
}
}
}
}
return matchIndex;
}
//---------------------------------------------------------
// Dynamic
//---------------------------------------------------------
@ -335,7 +294,7 @@ void Dynamic::layout()
continue;
}
if (e->isChord() && (align() & Align::HCENTER)) {
SymId symId = dynList[int(dynamicType())].symId;
SymId symId = TConv::symId(dynamicType());
// this value is different than chord()->mag() or mag()
// as it reflects the actual scaling of the text
@ -411,7 +370,7 @@ void Dynamic::setDynamicType(const QString& tag)
{
int n = sizeof(dynList) / sizeof(*dynList);
for (int i = 0; i < n; ++i) {
if (dynList[i].tag == tag || dynList[i].text == tag) {
if (TConv::toXml(DynamicType(i)) == tag || dynList[i].text == tag) {
setDynamicType(DynamicType(i));
setXmlText(QString::fromUtf8(dynList[i].text));
return;
@ -422,13 +381,14 @@ void Dynamic::setDynamicType(const QString& tag)
setXmlText(tag);
}
//---------------------------------------------------------
// dynamicTypeName
//---------------------------------------------------------
QString Dynamic::dynamicTypeName(DynamicType type)
QString Dynamic::dynamicText(DynamicType t)
{
return dynList[int(type)].tag;
return dynList[int(t)].text;
}
QString Dynamic::subtypeName() const
{
return TConv::toXml(dynamicType());
}
//---------------------------------------------------------
@ -591,7 +551,7 @@ bool Dynamic::setProperty(Pid propertyId, const PropertyValue& v)
_velocity = v.toInt();
break;
case Pid::SUBTYPE:
_dynamicType = DynamicType(v.toInt());
_dynamicType = v.value<DynamicType>();
break;
case Pid::VELO_CHANGE:
if (isVelocityChangeAvailable()) {
@ -664,7 +624,7 @@ QString Dynamic::accessibleInfo() const
s += "";
}
} else {
s = dynamicTypeName();
s = TConv::toUserName(dynamicType());
}
return QString("%1: %2").arg(EngravingItem::accessibleInfo(), s);
}
@ -680,7 +640,7 @@ QString Dynamic::screenReaderInfo() const
if (dynamicType() == DynamicType::OTHER) {
s = plainText().simplified();
} else {
s = dynamicTypeName();
s = TConv::toUserName(dynamicType());
}
return QString("%1: %2").arg(EngravingItem::accessibleInfo(), s);
}

View file

@ -75,11 +75,10 @@ public:
void setDynamicType(DynamicType val) { _dynamicType = val; }
void setDynamicType(const QString&);
static QString dynamicTypeName(DynamicType type);
QString dynamicTypeName() const { return dynamicTypeName(_dynamicType); }
DynamicType dynamicType() const { return _dynamicType; }
int subtype() const override { return static_cast<int>(_dynamicType); }
QString subtypeName() const override { return dynamicTypeName(); }
QString subtypeName() const override;
void layout() override;
void write(XmlWriter& xml) const override;
@ -118,7 +117,8 @@ public:
void doAutoplace();
static const std::vector<ChangeSpeedItem> changeSpeedTable;
static int findInString(const QString& text, int& length, QString& type);
static QString dynamicText(DynamicType t);
};
} // namespace Ms

View file

@ -552,8 +552,10 @@ PropertyValue readProperty(Pid id, XmlReader& e)
return PropertyValue(TConv::fromXml(e.readElementText(), NoteHeadGroup::HEAD_NORMAL));
case P_TYPE::CLEF_TYPE:
return PropertyValue(TConv::fromXml(e.readElementText(), ClefType::G));
case P_TYPE::SYMID:
case P_TYPE::DYNAMIC_TYPE:
return PropertyValue(TConv::fromXml(e.readElementText(), DynamicType::OTHER));
case P_TYPE::SYMID:
case P_TYPE::SUB_STYLE:
case P_TYPE::ORIENTATION:
return propertyFromString(propertyType(id), e.readElementText());
@ -638,8 +640,6 @@ QString propertyToString(Pid id, const PropertyValue& value, bool mscx)
return Dynamic::speedToName(Dynamic::Speed(value.toInt()));
case P_TYPE::CHANGE_METHOD:
return ChangeMap::changeMethodToName(ChangeMethod(value.toInt()));
case P_TYPE::DYNAMIC_TYPE:
return Dynamic::dynamicTypeName(value.value<DynamicType>());
case P_TYPE::ORIENTATION: {
const Orientation o = Orientation(value.toInt());
if (o == Orientation::VERTICAL) {

View file

@ -594,38 +594,6 @@ enum class HookType : char {
NONE, HOOK_90, HOOK_45, HOOK_90T
};
enum class DynamicType : char {
OTHER,
PPPPPP,
PPPPP,
PPPP,
PPP,
PP,
P,
MP,
MF,
F,
FF,
FFF,
FFFF,
FFFFF,
FFFFFF,
FP,
SF,
SFZ,
SFF,
SFFZ,
SFP,
SFPP,
RFZ,
RF,
FZ,
M,
R,
S,
Z
};
//---------------------------------------------------------
// AccidentalRole
//---------------------------------------------------------
@ -644,7 +612,6 @@ Q_ENUM_NS(NoteType);
Q_ENUM_NS(PlayEventType);
Q_ENUM_NS(AccidentalType);
Q_ENUM_NS(HarmonyType);
Q_ENUM_NS(DynamicType);
#endif
//hack: to force the build system to run moc on this file
@ -661,6 +628,4 @@ Q_DECLARE_METATYPE(Ms::PlayEventType);
Q_DECLARE_METATYPE(Ms::AccidentalType);
Q_DECLARE_METATYPE(Ms::DynamicType)
#endif

View file

@ -165,11 +165,12 @@ QVariant PropertyValue::toQVariant() const
case P_TYPE::NOTEHEAD_SCHEME: return static_cast<int>(value<NoteHeadScheme>());
case P_TYPE::NOTEHEAD_GROUP: return static_cast<int>(value<NoteHeadGroup>());
case P_TYPE::CLEF_TYPE: return static_cast<int>(value<ClefType>());
case P_TYPE::DYNAMIC_TYPE: return static_cast<int>(value<DynamicType>());
// other
case P_TYPE::SYMID: return static_cast<int>(value<Ms::SymId>());
case P_TYPE::HOOK_TYPE: return static_cast<int>(value<Ms::HookType>());
case P_TYPE::DYNAMIC_TYPE: return static_cast<int>(value<Ms::DynamicType>());
case P_TYPE::ACCIDENTAL_ROLE: return static_cast<int>(value<Ms::AccidentalRole>());
default:
UNREACHABLE; //! TODO
@ -230,12 +231,12 @@ PropertyValue PropertyValue::fromQVariant(const QVariant& v, P_TYPE type)
case P_TYPE::NOTEHEAD_SCHEME: return PropertyValue(NoteHeadScheme(v.toInt()));
case P_TYPE::NOTEHEAD_GROUP: return PropertyValue(NoteHeadGroup(v.toInt()));
case P_TYPE::CLEF_TYPE: return PropertyValue(ClefType(v.toInt()));
case P_TYPE::DYNAMIC_TYPE: return PropertyValue(DynamicType(v.toInt()));
// other
case P_TYPE::SYMID: return PropertyValue(Ms::SymId(v.toInt()));
case P_TYPE::HOOK_TYPE: return PropertyValue(Ms::HookType(v.toInt()));
case P_TYPE::DYNAMIC_TYPE: return PropertyValue(Ms::DynamicType(v.toInt()));
case P_TYPE::ACCIDENTAL_ROLE: return PropertyValue(Ms::AccidentalRole(v.toInt()));
default:
break;

View file

@ -85,6 +85,7 @@ enum class P_TYPE {
NOTEHEAD_SCHEME,
NOTEHEAD_GROUP,
CLEF_TYPE,
DYNAMIC_TYPE,
TEMPO,
GROUPS,
@ -98,7 +99,6 @@ enum class P_TYPE {
CHANGE_METHOD, // enum class VeloChangeMethod (for single note dynamics)
CHANGE_SPEED, // enum class Dynamic::Speed
DYNAMIC_TYPE, // enum class DynamicType
KEYMODE, // enum class KeyMode
ORIENTATION, // enum class Orientation
@ -203,6 +203,9 @@ public:
PropertyValue(ClefType v)
: m_type(P_TYPE::CLEF_TYPE), m_data(make_data<ClefType>(v)) {}
PropertyValue(DynamicType v)
: m_type(P_TYPE::DYNAMIC_TYPE), m_data(make_data<DynamicType>(v)) {}
// not sorted
PropertyValue(Ms::SymId v)
: m_type(P_TYPE::SYMID), m_data(make_data<Ms::SymId>(v)) {}
@ -210,9 +213,6 @@ public:
PropertyValue(Ms::HookType v)
: m_type(P_TYPE::HOOK_TYPE), m_data(make_data<Ms::HookType>(v)) {}
PropertyValue(Ms::DynamicType v)
: m_type(P_TYPE::DYNAMIC_TYPE), m_data(make_data<Ms::DynamicType>(v)) {}
PropertyValue(const Ms::PitchValues& v)
: m_type(P_TYPE::PITCH_VALUES), m_data(make_data<Ms::PitchValues>(v)) {}

View file

@ -384,6 +384,12 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
*this << TConv::toXml(data.value<ClefType>());
*this << "</" << ename << ">\n";
} break;
case P_TYPE::DYNAMIC_TYPE: {
putLevel();
*this << "<" << name << ">";
*this << TConv::toXml(data.value<DynamicType>());
*this << "</" << ename << ">\n";
} break;
default: {
UNREACHABLE; //! TODO
}
@ -392,28 +398,21 @@ void XmlWriter::tagProperty(const char* name, P_TYPE type, const PropertyValue&
// case P_TYPE::TDURATION,
// case P_TYPE::BEAM_MODE,
// case P_TYPE::TEXT_PLACE,
// case P_TYPE::TEMPO,
// case P_TYPE::GROUPS,
// case P_TYPE::SYMID,
// case P_TYPE::INT_LIST,
// case P_TYPE::GLISS_STYLE,
// case P_TYPE::BARLINE_TYPE,
// case P_TYPE::HEAD_TYPE, // enum class Notehead::Type
// case P_TYPE::HEAD_GROUP, // enum class Notehead::Group
// case P_TYPE::ZERO_INT, // displayed with offset +1
// case P_TYPE::SUB_STYLE,
// case P_TYPE::CHANGE_METHOD, // enum class VeloChangeMethod (for single note dynamics)
// case P_TYPE::CHANGE_SPEED, // enum class Dynamic::Speed
// case P_TYPE::CLEF_TYPE, // enum class ClefType
// case P_TYPE::DYNAMIC_TYPE, // enum class DynamicType
// case P_TYPE::KEYMODE, // enum class KeyMode
// case P_TYPE::ORIENTATION, // enum class Orientation
// case P_TYPE::HEAD_SCHEME, // enum class NoteHead::Scheme
// case P_TYPE::PITCH_VALUES,
// case P_TYPE::HOOK_TYPE
}

View file

@ -311,6 +311,42 @@ enum class ClefType : signed char {
TAB4_SERIF,
MAX
};
// P_TYPE::DYNAMIC_TYPE
enum class DynamicType : char {
OTHER,
PPPPPP,
PPPPP,
PPPP,
PPP,
PP,
P,
MP,
MF,
F,
FF,
FFF,
FFFF,
FFFFF,
FFFFFF,
FP,
PF,
SF,
SFZ,
SFF,
SFFZ,
SFP,
SFPP,
RFZ,
RF,
FZ,
M,
R,
S,
Z,
N,
LAST
};
} // mu::engraving
//! NOTE compat
@ -331,6 +367,7 @@ using NoteHeadType = mu::engraving::NoteHeadType;
using NoteHeadScheme = mu::engraving::NoteHeadScheme;
using NoteHeadGroup = mu::engraving::NoteHeadGroup;
using ClefType = mu::engraving::ClefType;
using DynamicType = mu::engraving::DynamicType;
}
#endif // MU_ENGRAVING_TYPES_H

View file

@ -25,6 +25,7 @@
#include "log.h"
using namespace mu::engraving;
using namespace Ms;
template<typename T>
struct Item
@ -32,6 +33,7 @@ struct Item
T type;
QString xml;
const char* userName = nullptr;
SymId symId = SymId::noSym;
};
template<typename T>
@ -45,9 +47,27 @@ static QString findUserNameByType(const std::vector<Item<T> >& cont, const T& v)
static QString dummy;
return dummy;
}
if (!it->userName) {
return it->xml;
}
return mu::qtrc("engraving", it->userName);
}
template<typename T>
static SymId findSymIdByType(const std::vector<Item<T> >& cont, const T& v)
{
auto it = std::find_if(cont.cbegin(), cont.cend(), [v](const Item<T>& i) {
return i.type == v;
});
IF_ASSERT_FAILED(it != cont.cend()) {
return SymId::noSym;
}
return it->symId;
}
template<typename T>
static QString findXmlTagByType(const std::vector<Item<T> >& cont, const T& v)
{
@ -269,3 +289,62 @@ ClefType TConv::fromXml(const QString& tag, ClefType def)
{
return findTypeByXmlTag<ClefType>(CLEF_TYPES, tag, def);
}
static const std::vector<Item<DynamicType> > DYNAMIC_TYPES = {
{ DynamicType::OTHER, "other-dynamics", nullptr, SymId::noSym },
{ DynamicType::PPPPPP, "pppppp", nullptr, SymId::dynamicPPPPPP },
{ DynamicType::PPPPP, "ppppp", nullptr, SymId::dynamicPPPPP },
{ DynamicType::PPPP, "pppp", nullptr, SymId::dynamicPPPP },
{ DynamicType::PPP, "ppp", nullptr, SymId::dynamicPPP },
{ DynamicType::PP, "pp", nullptr, SymId::dynamicPP },
{ DynamicType::P, "p", nullptr, SymId::dynamicPiano },
{ DynamicType::MP, "mp", nullptr, SymId::dynamicMP },
{ DynamicType::MF, "mf", nullptr, SymId::dynamicMF },
{ DynamicType::F, "f", nullptr, SymId::dynamicForte },
{ DynamicType::FF, "ff", nullptr, SymId::dynamicFF },
{ DynamicType::FFF, "fff", nullptr, SymId::dynamicFFF },
{ DynamicType::FFFF, "ffff", nullptr, SymId::dynamicFFFF },
{ DynamicType::FFFFF, "fffff", nullptr, SymId::dynamicFFFFF },
{ DynamicType::FFFFFF, "ffffff", nullptr, SymId::dynamicFFFFFF },
{ DynamicType::FP, "fp", nullptr, SymId::dynamicFortePiano },
{ DynamicType::PF, "pf", nullptr, SymId::noSym },
{ DynamicType::SF, "sf", nullptr, SymId::dynamicSforzando1 },
{ DynamicType::SFZ, "sfz", nullptr, SymId::dynamicSforzato },
{ DynamicType::SFF, "sff", nullptr, SymId::noSym },
{ DynamicType::SFFZ, "sffz", nullptr, SymId::dynamicSforzatoFF },
{ DynamicType::SFP, "sfp", nullptr, SymId::dynamicSforzandoPiano },
{ DynamicType::SFPP, "sfpp", nullptr, SymId::dynamicSforzandoPianissimo },
{ DynamicType::RFZ, "rfz", nullptr, SymId::dynamicRinforzando2 },
{ DynamicType::RF, "rf", nullptr, SymId::dynamicRinforzando1 },
{ DynamicType::FZ, "fz", nullptr, SymId::dynamicForzando },
{ DynamicType::M, "m", nullptr, SymId::dynamicMezzo },
{ DynamicType::R, "r", nullptr, SymId::dynamicRinforzando },
{ DynamicType::S, "s", nullptr, SymId::dynamicSforzando },
{ DynamicType::Z, "z", nullptr, SymId::dynamicZ },
{ DynamicType::N, "n", nullptr, SymId::dynamicNiente },
};
QString TConv::toUserName(DynamicType v)
{
return findUserNameByType<DynamicType>(DYNAMIC_TYPES, v);
}
Ms::SymId TConv::symId(DynamicType v)
{
return findSymIdByType<DynamicType>(DYNAMIC_TYPES, v);
}
QString TConv::toXml(DynamicType v)
{
return findXmlTagByType<DynamicType>(DYNAMIC_TYPES, v);
}
DynamicType TConv::fromXml(const QString& tag, DynamicType def)
{
return findTypeByXmlTag<DynamicType>(DYNAMIC_TYPES, tag, def);
}

View file

@ -25,6 +25,7 @@
#include <QString>
#include "types.h"
#include "libmscore/symid.h"
namespace mu::engraving {
class TConv
@ -45,6 +46,11 @@ public:
static QString toUserName(ClefType v);
static QString toXml(ClefType v);
static ClefType fromXml(const QString& tag, ClefType def);
static QString toUserName(DynamicType v);
static Ms::SymId symId(DynamicType v);
static QString toXml(DynamicType v);
static DynamicType fromXml(const QString& tag, DynamicType def);
};
}

View file

@ -48,6 +48,7 @@
#include "engraving/style/style.h"
#include "engraving/rw/xml.h"
#include "engraving/types/typesconv.h"
#include "libmscore/factory.h"
#include "libmscore/masterscore.h"
@ -4496,6 +4497,46 @@ int ExportMusicXml::findHairpin(const Hairpin* hp) const
return -1;
}
//---------------------------------------------------------
// findInString
//---------------------------------------------------------
// find the longest first match of dynList's dynamic text in s
// used by the MusicXML export to correctly export dynamics embedded
// in spanner begin- or endtexts
// return match's position and length and the dynamic type
static int findDynamicInString(const QString& s, int& length, QString& type)
{
length = 0;
type = "";
int matchIndex { -1 };
const int n = static_cast<int>(DynamicType::LAST) - 1;
// for all dynamics, find their text in s
for (int i = 0; i < n; ++i) {
DynamicType t = static_cast<DynamicType>(i);
const QString dynamicText = Dynamic::dynamicText(t);
const int dynamicLength = dynamicText.length();
// note: skip entries with empty text
if (dynamicLength > 0) {
const auto index = s.indexOf(dynamicText);
if (index >= 0) {
// found a match, accept it if
// - it is the first one
// - or it starts a the same index but is longer ("pp" versus "p")
if (matchIndex == -1 || (index == matchIndex && dynamicLength > length)) {
matchIndex = index;
length = dynamicLength;
type = TConv::toXml(t);
}
}
}
}
return matchIndex;
}
//---------------------------------------------------------
// writeHairpinText
//---------------------------------------------------------
@ -4506,7 +4547,7 @@ static void writeHairpinText(XmlWriter& xml, const TextLineBase* const tlb, bool
while (text != "") {
int dynamicLength { 0 };
QString dynamicsType;
auto dynamicPosition = Dynamic::findInString(text, dynamicLength, dynamicsType);
auto dynamicPosition = findDynamicInString(text, dynamicLength, dynamicsType);
if (dynamicPosition == -1 || dynamicPosition > 0) {
// text remaining and either no dynamic of not at front of text
xml.startObject("direction-type");
@ -4888,7 +4929,7 @@ void ExportMusicXml::dynamic(Dynamic const* const dyn, int staff)
QString tagName = "dynamics";
tagName += positioningAttributes(dyn);
_xml.startObject(tagName);
const QString dynTypeName = dyn->dynamicTypeName();
const QString dynTypeName = TConv::toXml(dyn->dynamicType());
if (set.contains(dynTypeName)) {
_xml.tagE(dynTypeName);

View file

@ -220,7 +220,7 @@ PalettePtr PaletteCreator::newDynamicsPalette(bool defaultPalette)
for (const char* dynamicType : (defaultPalette ? defaultArray : fullArray)) {
auto dynamic = makeElement<Dynamic>(Ms::gpaletteScore);
dynamic->setDynamicType(dynamicType);
sp->appendElement(dynamic, dynamic->dynamicTypeName());
sp->appendElement(dynamic, TConv::toUserName(dynamic->dynamicType()));
}
return sp;
}