diff --git a/Verovio.xcodeproj/project.pbxproj b/Verovio.xcodeproj/project.pbxproj index 8952559be6..9242b6fd1b 100644 --- a/Verovio.xcodeproj/project.pbxproj +++ b/Verovio.xcodeproj/project.pbxproj @@ -655,6 +655,12 @@ 4DACCA162990F2E600B55913 /* att.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DACCA0D2990F2E600B55913 /* att.cpp */; }; 4DACCA172990F2E600B55913 /* attdef.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DACCA0E2990F2E600B55913 /* attdef.h */; }; 4DACCA182990F2E600B55913 /* attdef.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DACCA0E2990F2E600B55913 /* attdef.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4DAD09052D1EA207006095DC /* cpmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD09042D1EA207006095DC /* cpmark.cpp */; }; + 4DAD09062D1EA207006095DC /* cpmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD09042D1EA207006095DC /* cpmark.cpp */; }; + 4DAD09072D1EA207006095DC /* cpmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD09042D1EA207006095DC /* cpmark.cpp */; }; + 4DAD09082D1EA207006095DC /* cpmark.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DAD09042D1EA207006095DC /* cpmark.cpp */; }; + 4DAD090A2D1EA236006095DC /* cpmark.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DAD09092D1EA236006095DC /* cpmark.h */; settings = {ATTRIBUTES = (Public, ); }; }; + 4DAD090B2D1EA236006095DC /* cpmark.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DAD09092D1EA236006095DC /* cpmark.h */; }; 4DB0B0161C44129300DBDCC3 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DB0B0151C44129300DBDCC3 /* timestamp.cpp */; }; 4DB0B0171C44129300DBDCC3 /* timestamp.cpp in Sources */ = {isa = PBXBuildFile; fileRef = 4DB0B0151C44129300DBDCC3 /* timestamp.cpp */; }; 4DB0B0191C4412A400DBDCC3 /* timestamp.h in Headers */ = {isa = PBXBuildFile; fileRef = 4DB0B0181C4412A400DBDCC3 /* timestamp.h */; }; @@ -1435,7 +1441,7 @@ BDEF9EC926725234008A3A47 /* caesura.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDEF9EC626725234008A3A47 /* caesura.cpp */; }; BDEF9ECA26725234008A3A47 /* caesura.cpp in Sources */ = {isa = PBXBuildFile; fileRef = BDEF9EC626725234008A3A47 /* caesura.cpp */; }; BDEF9ECC26725248008A3A47 /* caesura.h in Headers */ = {isa = PBXBuildFile; fileRef = BDEF9ECB26725248008A3A47 /* caesura.h */; }; - BDEF9ECD26725248008A3A47 /* caesura.h in Headers */ = {isa = PBXBuildFile; fileRef = BDEF9ECB26725248008A3A47 /* caesura.h */; }; + BDEF9ECD26725248008A3A47 /* caesura.h in Headers */ = {isa = PBXBuildFile; fileRef = BDEF9ECB26725248008A3A47 /* caesura.h */; settings = {ATTRIBUTES = (Public, ); }; }; E708AA6229D2B96A001F937A /* adjustfloatingpositionerfunctor.h in Headers */ = {isa = PBXBuildFile; fileRef = E708AA6129D2B965001F937A /* adjustfloatingpositionerfunctor.h */; }; E708AA6329D2B96B001F937A /* adjustfloatingpositionerfunctor.h in Headers */ = {isa = PBXBuildFile; fileRef = E708AA6129D2B965001F937A /* adjustfloatingpositionerfunctor.h */; settings = {ATTRIBUTES = (Public, ); }; }; E708AA6529D2B985001F937A /* adjustfloatingpositionerfunctor.cpp in Sources */ = {isa = PBXBuildFile; fileRef = E708AA6429D2B985001F937A /* adjustfloatingpositionerfunctor.cpp */; }; @@ -2026,6 +2032,8 @@ 4DACCA0C2990F2E600B55913 /* attalternates.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = attalternates.h; path = libmei/addons/attalternates.h; sourceTree = ""; }; 4DACCA0D2990F2E600B55913 /* att.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = att.cpp; path = libmei/addons/att.cpp; sourceTree = ""; }; 4DACCA0E2990F2E600B55913 /* attdef.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = attdef.h; path = libmei/addons/attdef.h; sourceTree = ""; }; + 4DAD09042D1EA207006095DC /* cpmark.cpp */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.cpp; name = cpmark.cpp; path = src/cpmark.cpp; sourceTree = ""; }; + 4DAD09092D1EA236006095DC /* cpmark.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; name = cpmark.h; path = include/vrv/cpmark.h; sourceTree = ""; }; 4DB0B0151C44129300DBDCC3 /* timestamp.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = timestamp.cpp; path = src/timestamp.cpp; sourceTree = ""; }; 4DB0B0181C4412A400DBDCC3 /* timestamp.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = timestamp.h; path = include/vrv/timestamp.h; sourceTree = ""; }; 4DB3072D1AC9ED1800EE0982 /* space.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = space.h; path = include/vrv/space.h; sourceTree = ""; }; @@ -2742,6 +2750,8 @@ 4DE644F31EDBE9F8002FBE6C /* breath.h */, BDEF9EC626725234008A3A47 /* caesura.cpp */, BDEF9ECB26725248008A3A47 /* caesura.h */, + 4DAD09042D1EA207006095DC /* cpmark.cpp */, + 4DAD09092D1EA236006095DC /* cpmark.h */, 4DB351111C8040B1002DD057 /* dir.cpp */, 4DB3510E1C80409E002DD057 /* dir.h */, 4DDBBB591C7AE45900054AFF /* dynam.cpp */, @@ -3480,6 +3490,7 @@ 4D1BE7821C69434C0086DC0E /* MidiFile.h in Headers */, 4DACC9B62990F29A00B55913 /* atts_edittrans.h in Headers */, 4DEC4DD221C8295700D1D273 /* supplied.h in Headers */, + 4DAD090B2D1EA236006095DC /* cpmark.h in Headers */, 4D3C3F11294B89C9009993E6 /* ornam.h in Headers */, 4DD7C0FF27A55CFD00B9C017 /* timemap.h in Headers */, E79320642991452100D80975 /* calcstemfunctor.h in Headers */, @@ -3707,6 +3718,7 @@ BB4C4B8622A932DF001F6AF0 /* lb.h in Headers */, E77C197E28CD317B00F5BADA /* calcdotsfunctor.h in Headers */, BD0562302518CD12004057EB /* beamspan.h in Headers */, + 4DAD090A2D1EA236006095DC /* cpmark.h in Headers */, E7E9C11B29B0EF9700CFCE2F /* adjusttempofunctor.h in Headers */, BB4C4AFE22A932BC001F6AF0 /* subst.h in Headers */, BB4C4AFC22A932BC001F6AF0 /* sic.h in Headers */, @@ -4080,6 +4092,7 @@ E78F204B29D98D2B00CD5910 /* adjustxrelfortranscriptionfunctor.cpp in Sources */, BD0562372518CD20004057EB /* beamspan.cpp in Sources */, 4D1694181E3A44F300569BF4 /* text.cpp in Sources */, + 4DAD09052D1EA207006095DC /* cpmark.cpp in Sources */, E7265E7329DC701000D11F41 /* castofffunctor.cpp in Sources */, E7D48C7529D21F2B0031D89D /* adjustyposfunctor.cpp in Sources */, E77C198228CD31AC00F5BADA /* calcdotsfunctor.cpp in Sources */, @@ -4392,6 +4405,7 @@ E7770F8629D0DA1800A9BECF /* adjustslursfunctor.cpp in Sources */, E7F39C6129A62B3E0055DBE0 /* adjustclefchangesfunctor.cpp in Sources */, 8F086EF8188539540037FD8E /* note.cpp in Sources */, + 4DAD09082D1EA207006095DC /* cpmark.cpp in Sources */, 409B3DD91F2D1C2A0098A265 /* ftrem.cpp in Sources */, 4D5FA9111E16A93F00F3B919 /* boundingbox.cpp in Sources */, 8F086EF9188539540037FD8E /* object.cpp in Sources */, @@ -4663,6 +4677,7 @@ E78F204C29D98D2C00CD5910 /* adjustxrelfortranscriptionfunctor.cpp in Sources */, 4DDBBCC61C2EBAE7001AB50A /* view_text.cpp in Sources */, 8F3DD34618854B2E0051330C /* layerelement.cpp in Sources */, + 4DAD09072D1EA207006095DC /* cpmark.cpp in Sources */, BD6E5C3E290007CA0039B0F1 /* graphic.cpp in Sources */, E7265E7129DC700800D11F41 /* castofffunctor.cpp in Sources */, E7D48C7629D21F2C0031D89D /* adjustyposfunctor.cpp in Sources */, @@ -4955,6 +4970,7 @@ E78F204D29D98D2D00CD5910 /* adjustxrelfortranscriptionfunctor.cpp in Sources */, E77C198128CD318B00F5BADA /* calcdotsfunctor.cpp in Sources */, BD87768627CE8A1A005B97EA /* layerdef.cpp in Sources */, + 4DAD09062D1EA207006095DC /* cpmark.cpp in Sources */, BB4C4AF722A932BC001F6AF0 /* reg.cpp in Sources */, E7265E7229DC700800D11F41 /* castofffunctor.cpp in Sources */, E7D48C7729D21F2D0031D89D /* adjustyposfunctor.cpp in Sources */, diff --git a/bindings/iOS/all.h b/bindings/iOS/all.h index 97385c2d31..7484c090d0 100644 --- a/bindings/iOS/all.h +++ b/bindings/iOS/all.h @@ -69,6 +69,7 @@ #import #import #import +#import #import #import #import diff --git a/include/vrv/cpmark.h b/include/vrv/cpmark.h new file mode 100644 index 0000000000..d05724f0f9 --- /dev/null +++ b/include/vrv/cpmark.h @@ -0,0 +1,90 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: cpmark.h +// Author: Laurent Pugin +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#ifndef __VRV_CPMARK_H__ +#define __VRV_CPMARK_H__ + +#include "controlelement.h" +#include "textdirinterface.h" +#include "timeinterface.h" + +namespace vrv { + +class TextElement; + +//---------------------------------------------------------------------------- +// CpMark (copy/colla parte mark) +//---------------------------------------------------------------------------- + +/** + * This class models the MEI element. + */ +class CpMark : public ControlElement, public TextListInterface, public TextDirInterface, public TimeSpanningInterface { +public: + /** + * @name Constructors, destructors, and other standard methods + * Reset method reset all attribute classes + */ + ///@{ + CpMark(); + virtual ~CpMark(); + Object *Clone() const override { return new CpMark(*this); } + void Reset() override; + std::string GetClassName() const override { return "CpMark"; } + ///@} + + /** + * @name Getter to interfaces + */ + ///@{ + TextDirInterface *GetTextDirInterface() override { return vrv_cast(this); } + const TextDirInterface *GetTextDirInterface() const override { return vrv_cast(this); } + TimePointInterface *GetTimePointInterface() override { return vrv_cast(this); } + const TimePointInterface *GetTimePointInterface() const override + { + return vrv_cast(this); + } + TimeSpanningInterface *GetTimeSpanningInterface() override { return vrv_cast(this); } + const TimeSpanningInterface *GetTimeSpanningInterface() const override + { + return vrv_cast(this); + } + ///@} + + /** + * Add an element (text, rend. etc.) to a cpMark. + * Only supported elements will be actually added to the child list. + */ + bool IsSupportedChild(Object *object) override; + + //----------// + // Functors // + //----------// + + /** + * Interface for class functor visitation + */ + ///@{ + FunctorCode Accept(Functor &functor) override; + FunctorCode Accept(ConstFunctor &functor) const override; + FunctorCode AcceptEnd(Functor &functor) override; + FunctorCode AcceptEnd(ConstFunctor &functor) const override; + ///@} + +protected: + // +private: + // +public: + // +private: + // +}; + +} // namespace vrv + +#endif diff --git a/include/vrv/functorinterface.h b/include/vrv/functorinterface.h index f24743f583..cc6399048d 100644 --- a/include/vrv/functorinterface.h +++ b/include/vrv/functorinterface.h @@ -30,6 +30,7 @@ class Chord; class Clef; class ControlElement; class Course; +class CpMark; class Custos; class Dir; class Div; @@ -292,6 +293,8 @@ class FunctorInterface { virtual FunctorCode VisitCaesuraEnd(Caesura *caesura); virtual FunctorCode VisitControlElement(ControlElement *controlElement); virtual FunctorCode VisitControlElementEnd(ControlElement *controlElement); + virtual FunctorCode VisitCpMark(CpMark *cpMark); + virtual FunctorCode VisitCpMarkEnd(CpMark *cpMark); virtual FunctorCode VisitDir(Dir *dir); virtual FunctorCode VisitDirEnd(Dir *dir); virtual FunctorCode VisitDynam(Dynam *dynam); @@ -665,6 +668,8 @@ class ConstFunctorInterface { virtual FunctorCode VisitCaesuraEnd(const Caesura *caesura); virtual FunctorCode VisitControlElement(const ControlElement *controlElement); virtual FunctorCode VisitControlElementEnd(const ControlElement *controlElement); + virtual FunctorCode VisitCpMark(const CpMark *cpMark); + virtual FunctorCode VisitCpMarkEnd(const CpMark *cpMark); virtual FunctorCode VisitDir(const Dir *dir); virtual FunctorCode VisitDirEnd(const Dir *dir); virtual FunctorCode VisitDynam(const Dynam *dynam); diff --git a/include/vrv/iomei.h b/include/vrv/iomei.h index e58c74f20c..89c93f33f9 100644 --- a/include/vrv/iomei.h +++ b/include/vrv/iomei.h @@ -46,6 +46,7 @@ class Clef; class ControlElement; class Corr; class Course; +class CpMark; class Custos; class Damage; class Del; @@ -437,6 +438,7 @@ class MEIOutput : public Output { void WriteBracketSpan(pugi::xml_node currentNode, BracketSpan *bracketSpan); void WriteBreath(pugi::xml_node currentNode, Breath *breath); void WriteCaesura(pugi::xml_node currentNode, Caesura *caesura); + void WriteCpMark(pugi::xml_node currentNode, CpMark *cpMark); void WriteDir(pugi::xml_node currentNode, Dir *dir); void WriteDynam(pugi::xml_node currentNode, Dynam *dynam); void WriteFermata(pugi::xml_node currentNode, Fermata *fermata); @@ -753,6 +755,7 @@ class MEIInput : public Input { bool ReadBracketSpan(Object *parent, pugi::xml_node bracketSpan); bool ReadBreath(Object *parent, pugi::xml_node breath); bool ReadCaesura(Object *parent, pugi::xml_node caesura); + bool ReadCpMark(Object *parent, pugi::xml_node cpMark); bool ReadDir(Object *parent, pugi::xml_node dir); bool ReadDynam(Object *parent, pugi::xml_node dynam); bool ReadFermata(Object *parent, pugi::xml_node fermata); diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index 668561223b..6a18965d8c 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -181,6 +181,7 @@ enum ClassId : uint16_t { BRACKETSPAN, BREATH, CAESURA, + CPMARK, DIR, DYNAM, FERMATA, diff --git a/src/adjustfloatingpositionerfunctor.cpp b/src/adjustfloatingpositionerfunctor.cpp index 969ee0fc86..7f8e21c42a 100644 --- a/src/adjustfloatingpositionerfunctor.cpp +++ b/src/adjustfloatingpositionerfunctor.cpp @@ -115,6 +115,7 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitStaffAlignment(StaffAlignment // Handle within placement (ignore collisions for certain classes) if (place == STAFFREL_within) { + if (m_classId == CPMARK) continue; if (m_classId == DIR) continue; if (m_classId == HAIRPIN) continue; } @@ -214,6 +215,9 @@ FunctorCode AdjustFloatingPositionersFunctor::VisitSystem(System *system) adjustFloatingPositionerGrps.SetPlace(STAFFREL_below); system->m_systemAligner.Process(adjustFloatingPositionerGrps); + m_classId = CPMARK; + system->m_systemAligner.Process(*this); + m_classId = REPEATMARK; system->m_systemAligner.Process(*this); @@ -430,7 +434,7 @@ FunctorCode AdjustFloatingPositionersBetweenFunctor::VisitStaffAlignment(StaffAl for (FloatingPositioner *positioner : m_previousStaffAlignment->GetFloatingPositioners()) { assert(positioner->GetObject()); - if (!positioner->GetObject()->Is({ DIR, DYNAM, HAIRPIN, TEMPO })) continue; + if (!positioner->GetObject()->Is({ CPMARK, DIR, DYNAM, HAIRPIN, TEMPO })) continue; if (positioner->GetDrawingPlace() != STAFFREL_between) continue; diff --git a/src/adjustxoverflowfunctor.cpp b/src/adjustxoverflowfunctor.cpp index f095f61a52..7070914b45 100644 --- a/src/adjustxoverflowfunctor.cpp +++ b/src/adjustxoverflowfunctor.cpp @@ -32,7 +32,7 @@ AdjustXOverflowFunctor::AdjustXOverflowFunctor(int margin) : Functor() FunctorCode AdjustXOverflowFunctor::VisitControlElement(ControlElement *controlElement) { - if (!controlElement->Is({ DIR, DYNAM, ORNAM, REPEATMARK, TEMPO })) { + if (!controlElement->Is({ CPMARK, DIR, DYNAM, ORNAM, REPEATMARK, TEMPO })) { return FUNCTOR_SIBLINGS; } diff --git a/src/cpmark.cpp b/src/cpmark.cpp new file mode 100644 index 0000000000..39fc6d519a --- /dev/null +++ b/src/cpmark.cpp @@ -0,0 +1,87 @@ +///////////////////////////////////////////////////////////////////////////// +// Name: cpmark.cpp +// Author: Laurent Pugin +// Created: 2024 +// Copyright (c) Authors and others. All rights reserved. +///////////////////////////////////////////////////////////////////////////// + +#include "cpmark.h" + +//---------------------------------------------------------------------------- + +#include + +//---------------------------------------------------------------------------- + +#include "comparison.h" +#include "editorial.h" +#include "functor.h" +#include "symbol.h" +#include "text.h" +#include "verticalaligner.h" +#include "vrv.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// CpMark +//---------------------------------------------------------------------------- + +static const ClassRegistrar s_factory("cpMark", CPMARK); + +CpMark::CpMark() : ControlElement(CPMARK, "cpmark-"), TextListInterface(), TextDirInterface(), TimeSpanningInterface() +{ + this->RegisterInterface(TextDirInterface::GetAttClasses(), TextDirInterface::IsInterface()); + this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); + + this->Reset(); +} + +CpMark::~CpMark() {} + +void CpMark::Reset() +{ + ControlElement::Reset(); + TextDirInterface::Reset(); + TimeSpanningInterface::Reset(); +} + +bool CpMark::IsSupportedChild(Object *child) +{ + if (child->Is({ LB, REND, SYMBOL, TEXT })) { + assert(dynamic_cast(child)); + } + else if (child->IsEditorialElement()) { + assert(dynamic_cast(child)); + } + else { + return false; + } + return true; +} + +//---------------------------------------------------------------------------- +// CpMark functor methods +//---------------------------------------------------------------------------- + +FunctorCode CpMark::Accept(Functor &functor) +{ + return functor.VisitCpMark(this); +} + +FunctorCode CpMark::Accept(ConstFunctor &functor) const +{ + return functor.VisitCpMark(this); +} + +FunctorCode CpMark::AcceptEnd(Functor &functor) +{ + return functor.VisitCpMarkEnd(this); +} + +FunctorCode CpMark::AcceptEnd(ConstFunctor &functor) const +{ + return functor.VisitCpMarkEnd(this); +} + +} // namespace vrv diff --git a/src/floatingobject.cpp b/src/floatingobject.cpp index dd25a15a72..a6056260fa 100644 --- a/src/floatingobject.cpp +++ b/src/floatingobject.cpp @@ -19,6 +19,7 @@ #include "bracketspan.h" #include "breath.h" #include "caesura.h" +#include "cpmark.h" #include "dir.h" #include "doc.h" #include "dynam.h" @@ -233,6 +234,12 @@ FloatingPositioner::FloatingPositioner(FloatingObject *object, StaffAlignment *a // caesura within by default m_place = (caesura->GetPlace() != STAFFREL_NONE) ? caesura->GetPlace() : STAFFREL_within; } + else if (object->Is(CPMARK)) { + CpMark *cpMark = vrv_cast(object); + assert(cpMark); + // cpMark above by default + m_place = (cpMark->GetPlace() != STAFFREL_NONE) ? cpMark->GetPlace() : STAFFREL_above; + } else if (object->Is(DIR)) { Dir *dir = vrv_cast(object); assert(dir); @@ -490,7 +497,7 @@ void FloatingPositioner::CalcDrawingYRel( assert(turn); yRel += turn->GetTurnHeight(doc, staffSize) / 2; } - else if (!m_object->Is({ DIR, HAIRPIN })) { + else if (!m_object->Is({ CPMARK, DIR, HAIRPIN })) { yRel += (this->GetContentY2() - this->GetContentY1()) / 2; } this->SetDrawingYRel(yRel); diff --git a/src/functorinterface.cpp b/src/functorinterface.cpp index 202645cbbb..f54b6a5258 100644 --- a/src/functorinterface.cpp +++ b/src/functorinterface.cpp @@ -24,6 +24,7 @@ #include "chord.h" #include "clef.h" #include "course.h" +#include "cpmark.h" #include "custos.h" #include "dir.h" #include "div.h" @@ -550,6 +551,16 @@ FunctorCode FunctorInterface::VisitControlElementEnd(ControlElement *controlElem return this->VisitFloatingObjectEnd(controlElement); } +FunctorCode FunctorInterface::VisitCpMark(CpMark *cpMark) +{ + return this->VisitControlElement(cpMark); +} + +FunctorCode FunctorInterface::VisitCpMarkEnd(CpMark *cpMark) +{ + return this->VisitControlElementEnd(cpMark); +} + FunctorCode FunctorInterface::VisitDir(Dir *dir) { return this->VisitControlElement(dir); @@ -1884,6 +1895,16 @@ FunctorCode ConstFunctorInterface::VisitControlElementEnd(const ControlElement * return this->VisitFloatingObjectEnd(controlElement); } +FunctorCode ConstFunctorInterface::VisitCpMark(const CpMark *cpMark) +{ + return this->VisitControlElement(cpMark); +} + +FunctorCode ConstFunctorInterface::VisitCpMarkEnd(const CpMark *cpMark) +{ + return this->VisitControlElementEnd(cpMark); +} + FunctorCode ConstFunctorInterface::VisitDir(const Dir *dir) { return this->VisitControlElement(dir); diff --git a/src/iomei.cpp b/src/iomei.cpp index a6a4fe2b25..6d0b896172 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -36,6 +36,7 @@ #include "comparison.h" #include "corr.h" #include "course.h" +#include "cpmark.h" #include "custos.h" #include "damage.h" #include "del.h" @@ -492,6 +493,10 @@ bool MEIOutput::WriteObjectInternal(Object *object, bool useCustomScoreDef) m_currentNode = m_currentNode.append_child("caesura"); this->WriteCaesura(m_currentNode, vrv_cast(object)); } + else if (object->Is(CPMARK)) { + m_currentNode = m_currentNode.append_child("cpMark"); + this->WriteCpMark(m_currentNode, vrv_cast(object)); + } else if (object->Is(DIR)) { m_currentNode = m_currentNode.append_child("dir"); this->WriteDir(m_currentNode, vrv_cast(object)); @@ -2018,6 +2023,15 @@ void MEIOutput::WriteCaesura(pugi::xml_node currentNode, Caesura *caesura) caesura->WritePlacementRelStaff(currentNode); } +void MEIOutput::WriteCpMark(pugi::xml_node currentNode, CpMark *cpMark) +{ + assert(cpMark); + + this->WriteControlElement(currentNode, cpMark); + this->WriteTextDirInterface(currentNode, cpMark); + this->WriteTimeSpanningInterface(currentNode, cpMark); +} + void MEIOutput::WriteDir(pugi::xml_node currentNode, Dir *dir) { assert(dir); @@ -5491,6 +5505,9 @@ bool MEIInput::ReadMeasureChildren(Object *parent, pugi::xml_node parentNode) else if (currentName == "caesura") { success = this->ReadCaesura(parent, current); } + else if (currentName == "cpMark") { + success = this->ReadCpMark(parent, current); + } else if (currentName == "dir") { success = this->ReadDir(parent, current); } @@ -5712,6 +5729,19 @@ bool MEIInput::ReadCaesura(Object *parent, pugi::xml_node caesura) return true; } +bool MEIInput::ReadCpMark(Object *parent, pugi::xml_node cpMark) +{ + CpMark *vrvCpMark = new CpMark(); + this->ReadControlElement(cpMark, vrvCpMark); + + this->ReadTextDirInterface(cpMark, vrvCpMark); + this->ReadTimeSpanningInterface(cpMark, vrvCpMark); + + parent->AddChild(vrvCpMark); + this->ReadUnsupportedAttr(cpMark, vrvCpMark); + return this->ReadTextChildren(vrvCpMark, cpMark, vrvCpMark); +} + bool MEIInput::ReadDir(Object *parent, pugi::xml_node dir) { Dir *vrvDir = new Dir(); diff --git a/src/view_control.cpp b/src/view_control.cpp index 538acc581c..579e26f163 100644 --- a/src/view_control.cpp +++ b/src/view_control.cpp @@ -22,6 +22,7 @@ #include "caesura.h" #include "clef.h" #include "comparison.h" +#include "cpmark.h" #include "devicecontext.h" #include "dir.h" #include "doc.h" @@ -97,6 +98,11 @@ void View::DrawControlElement(DeviceContext *dc, ControlElement *element, Measur assert(caesura); this->DrawCaesura(dc, caesura, measure, system); } + else if (element->Is(CPMARK)) { + CpMark *cpMark = vrv_cast(element); + assert(cpMark); + this->DrawControlElementText(dc, cpMark, measure, system); + } else if (element->Is(DIR)) { Dir *dir = vrv_cast(element); assert(dir); diff --git a/src/view_page.cpp b/src/view_page.cpp index 304095385a..68d96dc1cc 100644 --- a/src/view_page.cpp +++ b/src/view_page.cpp @@ -924,7 +924,7 @@ void View::DrawBarLine(DeviceContext *dc, int yTop, int yBottom, BarLine *barLin lines.UpdateContentBBoxX(minX, maxX); lines.UpdateContentBBoxY(yTop, yBottom); const int margin = unit / 2; - system->m_systemAligner.FindAllIntersectionPoints(line, lines, { DIR, DYNAM, TEMPO }, margin); + system->m_systemAligner.FindAllIntersectionPoints(line, lines, { CPMARK, DIR, DYNAM, TEMPO }, margin); } } diff --git a/src/view_text.cpp b/src/view_text.cpp index f1f30653f9..990a51c3a6 100644 --- a/src/view_text.cpp +++ b/src/view_text.cpp @@ -500,7 +500,8 @@ void View::DrawText(DeviceContext *dc, Text *text, TextDrawingParams ¶ms) } // special case where we want to replace some unicode music points to SMuFL - if (text->GetFirstAncestor(DIR) || text->GetFirstAncestor(ORNAM) || text->GetFirstAncestor(REPEATMARK)) { + if (text->GetFirstAncestor(CPMARK) || text->GetFirstAncestor(DIR) || text->GetFirstAncestor(ORNAM) + || text->GetFirstAncestor(REPEATMARK)) { this->DrawDirString(dc, text->GetText(), params); } else if (text->GetFirstAncestor(DYNAM)) {