diff --git a/.github/workflows/tests_build.yml b/.github/workflows/tests_build.yml index a76db42cad0..ceea5116bb9 100644 --- a/.github/workflows/tests_build.yml +++ b/.github/workflows/tests_build.yml @@ -32,7 +32,7 @@ jobs: ################################################### build_python: name: Build the test suite - runs-on: ubuntu-22.04 + runs-on: ubuntu-24.04 steps: - uses: FranzDiebold/github-env-vars-action@v2.8.0 @@ -62,7 +62,7 @@ jobs: mkdir -p ${{ env.OUTPUT_DIR }} ls -alh ls -alh ${{ env.OUTPUT_DIR }} - sudo apt-get install openresolv wireguard + sudo apt-get install wireguard sudo echo "${{ secrets.VPN_CONFIGURATION }}" > wg0.conf python3 -m pip install diffimg jsondiff lxml xmldiff cairosvg diff --git a/Verovio.podspec b/Verovio.podspec index 08b2c403f09..301777674e1 100644 --- a/Verovio.podspec +++ b/Verovio.podspec @@ -17,7 +17,7 @@ Pod::Spec.new do |s| s.ios.deployment_target = '14.0' s.osx.deployment_target = '10.15' s.pod_target_xcconfig = { - "CLANG_CXX_LANGUAGE_STANDARD" => "c++20", + "CLANG_CXX_LANGUAGE_STANDARD" => "c++23", "CLANG_CXX_LIBRARY" => "libc++", "GCC_C_LANGUAGE_STANDARD" => "gnu11", "GCC_DYNAMIC_NO_PIC" => "NO", diff --git a/appveyor.yml b/appveyor.yml index 8e2e90238b8..77d43fd1351 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -4,7 +4,7 @@ branches: only: - develop -image: Visual Studio 2019 +image: Visual Studio 2022 configuration: Release diff --git a/emscripten/buildToolkit b/emscripten/buildToolkit index 3a2f1304d96..6c179ae0581 100755 --- a/emscripten/buildToolkit +++ b/emscripten/buildToolkit @@ -56,7 +56,7 @@ my ($lightQ, $version, $chattyQ, $helpQ, $exclusion, $wasmQ, $makeQ, $modularize my ($nopae, $nohumdrum, $nomusicxml, $nodarms); my ($FLAGS_NAME, $VERSION, $CHATTY); -my $cpp = 20; # c++ version to compile (11, 14, 17) +my $cpp = 20; # c++ version to compile (11, 14, 17) my $VEROVIO_ROOT = ".."; Getopt::Long::Configure("bundling"); diff --git a/include/vrv/alignfunctor.h b/include/vrv/alignfunctor.h index a1728f2f31f..8b9678f5226 100644 --- a/include/vrv/alignfunctor.h +++ b/include/vrv/alignfunctor.h @@ -23,6 +23,7 @@ struct AlignMeterParams { const Mensur *mensur = NULL; // Not const since we are cumulating proportion Proport *proport = NULL; + data_DURATION equivalence = DURATION_brevis; }; //---------------------------------------------------------------------------- diff --git a/include/vrv/convertfunctor.h b/include/vrv/convertfunctor.h index b651ea6bb16..fa8d84b009b 100644 --- a/include/vrv/convertfunctor.h +++ b/include/vrv/convertfunctor.h @@ -10,6 +10,10 @@ #include "functor.h" +//---------------------------------------------------------------------------- + +#include "alignfunctor.h" + namespace vrv { //---------------------------------------------------------------------------- @@ -81,7 +85,7 @@ class ConvertToCastOffMensuralFunctor : public DocFunctor { * @name Constructors, destructors */ ///@{ - ConvertToCastOffMensuralFunctor(Doc *doc, System *targetSystem, const IntTree *layerTree); + ConvertToCastOffMensuralFunctor(Doc *doc, System *targetSystem); virtual ~ConvertToCastOffMensuralFunctor() = default; ///@} @@ -90,52 +94,44 @@ class ConvertToCastOffMensuralFunctor : public DocFunctor { */ bool ImplementsEndInterface() const override { return false; } - /* - * Setter for staff @n - */ - ///@{ - void AddStaffN(int staffN) { m_staffNs.push_back(staffN); } - void ClearStaffNs() { m_staffNs.clear(); } - ///@} - /* * Functor interface */ ///@{ - FunctorCode VisitBarLine(BarLine *barLine) override; FunctorCode VisitLayer(Layer *layer) override; FunctorCode VisitMeasure(Measure *measure) override; FunctorCode VisitObject(Object *object) override; FunctorCode VisitScoreDef(ScoreDef *scoreDef) override; FunctorCode VisitStaff(Staff *staff) override; - FunctorCode VisitSyllable(Syllable *syllable) override; FunctorCode VisitSystemElement(SystemElement *systemElement) override; ///@} protected: // private: - // + /** Check if the alignment is a valid breakpoint */ + bool IsValidBreakPoint(const Alignment *alignment, const int nbLayers); + /** Create the staff and layer when a new segment starts */ + void InitSegment(Object *object); + public: // private: - // The staff @n for finding splitting bar lines - std::vector m_staffNs; + /** The list of segments (i.e., measures) we are going to create */ + std::list m_segments; + /** The current segment, reset at for every staff/layer */ + std::list::iterator m_currentSegment; + /** The list of break points (one less than the segments) */ + std::list m_breakPoints; + /** The current breakpoint, reset for every staff/layer */ + std::list::const_iterator m_currentBreakPoint; // The content layer from which we are copying the elements + Staff *m_contentStaff; Layer *m_contentLayer; // The target system, measure, staff & layer System *m_targetSystem; - Measure *m_targetMeasure; Staff *m_targetStaff; Layer *m_targetLayer; - // A sub-system (e.g., section) to add measure segments - System *m_targetSubSystem; - // A counter for segments in the sub-system (section) - int m_segmentIdx; - // The total number of segments (previous sections) - int m_segmentTotal; - // An IntTree for processing by layer - const IntTree *m_layerTree; }; //---------------------------------------------------------------------------- @@ -194,6 +190,146 @@ class ConvertToUnCastOffMensuralFunctor : public Functor { ArrayOfObjects m_segmentsToDelete; }; +//---------------------------------------------------------------------------- +// ConvertToCmnFunctor +//---------------------------------------------------------------------------- + +/** + * This class converts mensural MEI into cast-off (measure) segments looking at the barLine objects. + * Segment positions occur where a barLine is set on all staves. + */ +class ConvertToCmnFunctor : public DocFunctor { +public: + /** + * @name Constructors, destructors + */ + ///@{ + ConvertToCmnFunctor(Doc *doc, System *targetSystem, Score *score); + virtual ~ConvertToCmnFunctor() = default; + ///@} + + /* + * Abstract base implementation + */ + bool ImplementsEndInterface() const override { return true; } + + /* + * Functor interface + */ + ///@{ + FunctorCode VisitChord(Chord *chord) override; + FunctorCode VisitLayer(Layer *layer) override; + FunctorCode VisitLayerElement(LayerElement *object) override; + FunctorCode VisitLigature(Ligature *ligature) override; + FunctorCode VisitLigatureEnd(Ligature *ligature) override; + FunctorCode VisitMeasure(Measure *measure) override; + FunctorCode VisitMeasureEnd(Measure *measure) override; + FunctorCode VisitNote(Note *note) override; + FunctorCode VisitRest(Rest *rest) override; + FunctorCode VisitScoreDef(ScoreDef *scoreDef) override; + FunctorCode VisitStaff(Staff *staff) override; + FunctorCode VisitStaffEnd(Staff *staff) override; + FunctorCode VisitSystemElement(SystemElement *systemElement) override; + FunctorCode VisitSystemEnd(System *system) override; + ///@} + +protected: + // +private: + /** Check if the alignment correspond to a global mensur change */ + bool IsGlobalMensur(const Alignment *alignment, const int nbLayers, Mensur &mensur); + /** */ + Fraction CalcMeasureDuration(const Mensur &mensur); + /** Convert the objects with a DurationInterface into corresponding CMN notes or rests */ + void ConvertDurationInterface(DurationInterface *interface, ClassId classId); + /** Split DurationInterface objects into CMN ones - including over several measures with a recursive call */ + void SplitDurationInterface(ClassId classId, data_DURATION elementDur, Fraction time, Fraction duration); + /** Convert accid (mensural) into cmn accids - when not the first note, added as `@accid.ges` */ + void ConvertAccid(Note *cmnNote, const Accid *accid, bool &isFirstNote); + /** Convert clef (mensural) into cmn clef */ + void ConvertClef(Clef *cmnClef, const Clef *clef); + /** Convert mensur to dir */ + void ConvertMensur(const Mensur *mensur); + + /** Internal class for holding information about the mensur considered for meter signature (changes) */ + class MensurInfo { + public: + Mensur m_mensur; + Fraction m_time; + }; + + /** Internal class for holding infromation about the measures (time, duration) */ + class MeasureInfo { + public: + MeasureInfo(const Fraction &time, const Fraction &duration) : m_time(time), m_duration(duration) + { + m_measure = NULL; + } + + public: + Measure *m_measure; + Fraction m_time; + Fraction m_duration; + }; + + /** Internal class for holding information about the CMN notes to be generated in the process */ + class CmnDuration { + public: + CmnDuration(data_DURATION duration, int dots, int num = 1, int numbase = 1) + : m_duration(duration), m_dots(dots), m_num(num), m_numbase(numbase) + { + } + + public: + data_DURATION m_duration; + int m_dots; + int m_num; + int m_numbase; + }; + + /** + * Split a mensural duration into corresponding CMN durations - which can be more than one. + */ + void SplitDurationIntoCmn( + data_DURATION elementDur, Fraction duration, const Mensur *mensur, std::list &cmnDurations); + +public: + // +private: + /** The score with the main scoreDef */ + Score *m_score; + /** The list of segments (i.e., measures) we are going to create */ + std::vector m_measures; + /** The current segment, reset at for every staff/layer */ + std::vector::iterator m_currentMeasure; + /** The list of break points (one less than the measures) */ + std::vector m_layers; + /** The current breakpoint, reset for every staff/layer */ + std::vector::iterator m_currentLayer; + /** A list with the clef for each staff */ + std::list m_clefs; + /** The first clef encountered in the layer */ + Clef *m_layerClef; + /** The target system, measure, staff & layer */ + System *m_targetSystem; + /** The current Mensur and Proport */ + AlignMeterParams m_currentParams; + /** List of duration element potentially splitted across measures */ + ListOfObjects m_durationElements; + /** Bracket span for ligature, which also acts as a flag */ + BracketSpan *m_ligature; + /** Bracket span for coloration, which also acts as a flag */ + BracketSpan *m_coloration; + /** Proportion tuplet */ + Tuplet *m_proportTuplet; + /** The current staffN */ + Staff *m_currentStaff; + /** The current startid (empty string means beginning of the measure and tstamp 0.0) */ + std::string m_startid; + /** The number of CMN measures generated */ + int m_n; +}; + //---------------------------------------------------------------------------- // ConvertMarkupAnalyticalFunctor //---------------------------------------------------------------------------- @@ -340,6 +476,55 @@ class ConvertMarkupScoreDefFunctor : public DocFunctor { ScoreDefElement *m_currentScoreDef; }; +//---------------------------------------------------------------------------- +// ConvertToMensuralViewFunctor +//---------------------------------------------------------------------------- + +/** + * This class moves scoreDef clef, keySig, meterSig and mensur to staffDef. + * When a staffDef already has one, it is not replaced. + */ +class ConvertToMensuralViewFunctor : public DocFunctor { +public: + /** + * @name Constructors, destructors + */ + ///@{ + ConvertToMensuralViewFunctor(Doc *doc); + virtual ~ConvertToMensuralViewFunctor() = default; + ///@} + + /* + * Abstract base implementation + */ + bool ImplementsEndInterface() const override { return true; } + + /* + * Functor interface + */ + ///@{ + FunctorCode VisitEditorialElement(EditorialElement *editorialElement) override; + FunctorCode VisitLayer(Layer *layer) override; + FunctorCode VisitLayerEnd(Layer *layer) override; + FunctorCode VisitLayerElement(LayerElement *layerElement) override; + FunctorCode VisitLayerElementEnd(LayerElement *layerElement) override; + FunctorCode VisitLigature(Ligature *ligature) override; + FunctorCode VisitLigatureEnd(Ligature *ligature) override; + ///@} + +protected: + // +private: + // +public: + // +private: + /** The layer view we are flattening the content to */ + Layer *m_viewLayer; + /** The stack of current objects */ + ListOfObjects m_stack; +}; + } // namespace vrv #endif // __VRV_CONVERTFUNCTOR_H__ diff --git a/include/vrv/doc.h b/include/vrv/doc.h index 5361e886203..857e3ec7832 100644 --- a/include/vrv/doc.h +++ b/include/vrv/doc.h @@ -103,9 +103,14 @@ class Doc : public Object { bool GenerateMeasureNumbers(); /** - * Generate an MEI header + * Generate a minimal MEI header */ - void GenerateMEIHeader(bool meiBasic); + void GenerateMEIHeader(); + + /** + * Convert the header to MEI basic by preserving only the fileDesc and its titleStmt + */ + void ConvertHeaderToMEIBasic(); /** * Getter and setter for the DocType. @@ -365,6 +370,11 @@ class Doc : public Object { */ void ConvertToCastOffMensuralDoc(bool castOff); + /** + * Convert mensural MEI into CMN measure-based MEI. + */ + void ConvertToCmnDoc(); + /** * Convert analytical encoding (@fermata, @tie) to correpsonding elements * By default, the element are used only for the rendering and not preserved in the MEI output @@ -372,6 +382,16 @@ class Doc : public Object { */ void ConvertMarkupDoc(bool permanent = true); + /** + * Convert the doc from mensural to a flattened version with no ligatures and the selected editorial markup. + */ + void ConvertToMensuralViewDoc(); + + /** + * Convert the doc from mensural to CMN. + */ + void ConvertMensuralToCmnDoc(); + /** * Sync the coordinate provided trought to m_drawingFacsX/Y. * Call the SyncToFacsimile functor. @@ -447,8 +467,8 @@ class Doc : public Object { * @name Setter for and getter for mensural only flag */ ///@{ - void SetMensuralMusicOnly(bool isMensuralMusicOnly) { m_isMensuralMusicOnly = isMensuralMusicOnly; } - bool IsMensuralMusicOnly() const { return m_isMensuralMusicOnly; } + void SetMensuralMusicOnly(data_BOOLEAN isMensuralMusicOnly); + bool IsMensuralMusicOnly() const { return (m_isMensuralMusicOnly == BOOLEAN_true); } ///@} /** @@ -666,7 +686,7 @@ class Doc : public Object { * A flag to indicate whereas to document contains only mensural music. * Mensural only music will be converted to cast-off segments by Doc::ConvertToCastOffMensuralDoc */ - bool m_isMensuralMusicOnly; + data_BOOLEAN m_isMensuralMusicOnly; /** * A flag to indicate that the document contains neume lines. diff --git a/include/vrv/durationinterface.h b/include/vrv/durationinterface.h index d8e8714c12c..fe83fac8768 100644 --- a/include/vrv/durationinterface.h +++ b/include/vrv/durationinterface.h @@ -67,10 +67,22 @@ class DurationInterface : public Interface, /** * Returns the duration (in Fraction) for the element for mensural notation - * Currently this assume brevis equality and would - * need to be modified for shorter equality in later repertoire. + * The level of equality is given in equivalence (brevis, semibrevis or minima) */ - Fraction GetInterfaceAlignmentMensuralDuration(int num, int numBase, const Mensur *currentMensur) const; + Fraction GetInterfaceAlignmentMensuralDuration( + int num, int numBase, const Mensur *currentMensur, data_DURATION equivalence) const; + + /** + * @name Return the duration (in Fraction) for the corresponding level of equivalence + */ + ///@{ + Fraction DurationWithBrevisEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const; + Fraction DurationWithSemibrevisEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const; + Fraction DurationWithMinimaEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const; + ///@} /** * Return true if the note or rest is the first of a beam. diff --git a/include/vrv/fraction.h b/include/vrv/fraction.h index c65f19fb5d4..d26430e92b7 100644 --- a/include/vrv/fraction.h +++ b/include/vrv/fraction.h @@ -37,6 +37,8 @@ class Fraction { Fraction operator*(const Fraction &other) const; /** Division operator */ Fraction operator/(const Fraction &other) const; + /** Modulo operator */ + Fraction operator%(const Fraction &other) const; /** Equality operator */ bool operator==(const Fraction &other) const; diff --git a/include/vrv/horizontalaligner.h b/include/vrv/horizontalaligner.h index 887fe49e739..48fbb88e613 100644 --- a/include/vrv/horizontalaligner.h +++ b/include/vrv/horizontalaligner.h @@ -193,7 +193,7 @@ class Alignment : public Object { */ std::string LogDebugTreeMsg() override { - return StringFormat("%d %s", this->GetXRel(), this->GetTime().ToString().c_str()); + return StringFormat("%d %f", this->GetXRel(), this->GetTime().ToDouble()); } //----------------// diff --git a/include/vrv/iocmme.h b/include/vrv/iocmme.h index f74831ca7d3..3f6e3a68132 100644 --- a/include/vrv/iocmme.h +++ b/include/vrv/iocmme.h @@ -54,6 +54,7 @@ class CmmeInput : public Input { bool Import(const std::string &cmme) override; private: + void CreateMetadata(pugi::xml_node metadataNode); void CreateSection(pugi::xml_node musicSectionNode); void CreateStaff(pugi::xml_node voiceNode); void CreateApp(pugi::xml_node appNode); @@ -63,6 +64,7 @@ class CmmeInput : public Input { void ReadEditorialCommentary(pugi::xml_node evenNode, Object *object); void CreateAccid(pugi::xml_node accidNode); + void CreateColorChange(pugi::xml_node colorChangeNode); void CreateBarline(pugi::xml_node barlineNode); void CreateBreak(pugi::xml_node breakNode); void CreateChord(pugi::xml_node chordNode); @@ -94,6 +96,11 @@ class CmmeInput : public Input { int ChildAsInt(const pugi::xml_node node, const std::string &child) const; ///@} + /** + * Post-process the data to adjust the type of tempo change proport. + */ + void PostProcessProport(); + public: // private: @@ -113,11 +120,15 @@ class CmmeInput : public Input { std::vector m_mensInfos; /** The mensural info for the current voice */ cmme::mensInfo *m_mensInfo; + /** The current color (if not black) */ + std::string m_currentColor; /** The number of voices as given in the general data */ int m_numVoices; /** The name of the voices - if any */ std::vector m_voices; + /** A flag indicating we had a tempo change */ + bool m_activeTempoChange; }; } // namespace vrv diff --git a/include/vrv/midifunctor.h b/include/vrv/midifunctor.h index 47e4b47d3bf..9e883a83d12 100644 --- a/include/vrv/midifunctor.h +++ b/include/vrv/midifunctor.h @@ -30,13 +30,13 @@ class Timemap; /** * This class prepares Note onsets. */ -class InitOnsetOffsetFunctor : public Functor { +class InitOnsetOffsetFunctor : public DocFunctor { public: /** * @name Constructors, destructors */ ///@{ - InitOnsetOffsetFunctor(); + InitOnsetOffsetFunctor(Doc *doc); virtual ~InitOnsetOffsetFunctor() = default; ///@} diff --git a/include/vrv/object.h b/include/vrv/object.h index 7da3e2c1309..f5c2590419d 100644 --- a/include/vrv/object.h +++ b/include/vrv/object.h @@ -292,6 +292,13 @@ class Object : public BoundingBox { */ ArrayOfObjects &GetChildrenForModification() { return m_children; } + /** + * Copy all the attributes of an obejct to target. + * The object must be of the same ClassId. + * Unsupported attrbutes are also copied. + */ + void CopyAttributesTo(Object *target) const; + /** * Fill an array of pairs with all attributes and their values. * Return the number of attributes found. @@ -994,6 +1001,11 @@ class ObjectFactory { */ Object *Create(std::string name); + /** + * Create the object from the ClassId by making a lookup in the register + */ + Object *Create(ClassId classId); + /** * Add the name / constructor map entry to the static register */ @@ -1010,7 +1022,7 @@ class ObjectFactory { void GetClassIds(const std::vector &classStrings, std::vector &classIds); public: - static thread_local MapOfStrConstructors s_ctorsRegistry; + static thread_local MapOfClassIdConstructors s_ctorsRegistry; static thread_local MapOfStrClassIds s_classIdsRegistry; }; diff --git a/include/vrv/options.h b/include/vrv/options.h index 5435e2d7721..c81516b128b 100644 --- a/include/vrv/options.h +++ b/include/vrv/options.h @@ -60,6 +60,8 @@ enum option_BREAKS { BREAKS_none = 0, BREAKS_auto, BREAKS_line, BREAKS_smart, BR enum option_CONDENSE { CONDENSE_none = 0, CONDENSE_auto, CONDENSE_all, CONDENSE_encoded }; +enum option_DURATION_EQ { DURATION_EQ_brevis = 0, DURATION_EQ_semibrevis, DURATION_EQ_minima }; + enum option_ELISION { ELISION_regular = SMUFL_E551_lyricsElision, ELISION_narrow = SMUFL_E550_lyricsElisionNarrow, @@ -141,6 +143,7 @@ class Option { */ static const std::map s_breaks; static const std::map s_condense; + static const std::map s_durationEq; static const std::map s_elision; static const std::map s_fontFallback; static const std::map s_footer; @@ -839,8 +842,10 @@ class Options { */ OptionGrp m_mensural; + OptionIntMap m_durationEquivalence; OptionBool m_ligatureAsBracket; - OptionBool m_mensuralToMeasure; + OptionBool m_mensuralResponsiveView; + OptionBool m_mensuralToCmn; /** * Additional options for passing method JSON options to the command-line diff --git a/include/vrv/proport.h b/include/vrv/proport.h index 8aa0c240ca4..521e6363d09 100644 --- a/include/vrv/proport.h +++ b/include/vrv/proport.h @@ -38,6 +38,7 @@ class Proport : public LayerElement, public AttDurationRatio { int GetCumulatedNumbase() const; void Cumulate(const Proport *proport); + void ResetCumulate(); /** Override the method since alignment is required */ bool HasToBeAligned() const override { return true; } diff --git a/include/vrv/resetfunctor.h b/include/vrv/resetfunctor.h index e67034ccfc7..635a34881c6 100644 --- a/include/vrv/resetfunctor.h +++ b/include/vrv/resetfunctor.h @@ -128,6 +128,7 @@ class ResetHorizontalAlignmentFunctor : public Functor { FunctorCode VisitMeasure(Measure *measure) override; FunctorCode VisitMRest(MRest *mRest) override; FunctorCode VisitNote(Note *note) override; + FunctorCode VisitProport(Proport *proport) override; FunctorCode VisitRest(Rest *rest) override; FunctorCode VisitScoreDef(ScoreDef *scoreDef) override; FunctorCode VisitSystem(System *system) override; diff --git a/include/vrv/system.h b/include/vrv/system.h index 7485e2abfbe..16d90be3cf7 100644 --- a/include/vrv/system.h +++ b/include/vrv/system.h @@ -154,12 +154,6 @@ class System : public Object, public DrawingListInterface, public AttTyped { */ double EstimateJustificationRatio(const Doc *doc) const; - /** - * Convert mensural MEI into cast-off (measure) segments looking at the barLine objects. - * Segment positions occur where a barLine is set on all staves. - */ - void ConvertToCastOffMensuralSystem(Doc *doc, System *targetSystem); - /** * Reverse of ConvertToCastOffMensural() */ diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index b596eac7762..d4e01342ef4 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -389,7 +389,7 @@ typedef std::map MapOfIntGraceAligners; typedef std::vector> ArrayOfStringDynamTypePairs; -typedef std::map> MapOfStrConstructors; +typedef std::map> MapOfClassIdConstructors; typedef std::map MapOfStrClassIds; diff --git a/libmei/dist/attmodule.cpp b/libmei/dist/attmodule.cpp index 05323880d55..e0c35c7635a 100644 --- a/libmei/dist/attmodule.cpp +++ b/libmei/dist/attmodule.cpp @@ -62,6 +62,18 @@ void AttModule::GetMei(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyMei(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_NOTATIONTYPE)) { + const AttNotationType *att = dynamic_cast(element); + assert(att); + AttNotationType *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNotationtype(att->GetNotationtype()); + attTarget->SetNotationsubtype(att->GetNotationsubtype()); + } +} + } // namespace vrv #include "atts_analytical.h" @@ -216,6 +228,68 @@ void AttModule::GetAnalytical(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyAnalytical(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_HARMANL)) { + const AttHarmAnl *att = dynamic_cast(element); + assert(att); + AttHarmAnl *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_HARMONICFUNCTION)) { + const AttHarmonicFunction *att = dynamic_cast(element); + assert(att); + AttHarmonicFunction *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDeg(att->GetDeg()); + } + if (element->HasAttClass(ATT_INTERVALHARMONIC)) { + const AttIntervalHarmonic *att = dynamic_cast(element); + assert(att); + AttIntervalHarmonic *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetInth(att->GetInth()); + } + if (element->HasAttClass(ATT_INTERVALMELODIC)) { + const AttIntervalMelodic *att = dynamic_cast(element); + assert(att); + AttIntervalMelodic *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetIntm(att->GetIntm()); + } + if (element->HasAttClass(ATT_KEYSIGDEFAULTANL)) { + const AttKeySigDefaultAnl *att = dynamic_cast(element); + assert(att); + AttKeySigDefaultAnl *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetKeyAccid(att->GetKeyAccid()); + attTarget->SetKeyMode(att->GetKeyMode()); + attTarget->SetKeyPname(att->GetKeyPname()); + } + if (element->HasAttClass(ATT_MELODICFUNCTION)) { + const AttMelodicFunction *att = dynamic_cast(element); + assert(att); + AttMelodicFunction *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMfunc(att->GetMfunc()); + } + if (element->HasAttClass(ATT_PITCHCLASS)) { + const AttPitchClass *att = dynamic_cast(element); + assert(att); + AttPitchClass *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPclass(att->GetPclass()); + } + if (element->HasAttClass(ATT_SOLFA)) { + const AttSolfa *att = dynamic_cast(element); + assert(att); + AttSolfa *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPsolfa(att->GetPsolfa()); + } +} + } // namespace vrv #include "atts_cmn.h" @@ -790,6 +864,230 @@ void AttModule::GetCmn(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyCmn(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_ARPEGLOG)) { + const AttArpegLog *att = dynamic_cast(element); + assert(att); + AttArpegLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOrder(att->GetOrder()); + } + if (element->HasAttClass(ATT_BEAMPRESENT)) { + const AttBeamPresent *att = dynamic_cast(element); + assert(att); + AttBeamPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeam(att->GetBeam()); + } + if (element->HasAttClass(ATT_BEAMREND)) { + const AttBeamRend *att = dynamic_cast(element); + assert(att); + AttBeamRend *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetPlace(att->GetPlace()); + attTarget->SetSlash(att->GetSlash()); + attTarget->SetSlope(att->GetSlope()); + } + if (element->HasAttClass(ATT_BEAMSECONDARY)) { + const AttBeamSecondary *att = dynamic_cast(element); + assert(att); + AttBeamSecondary *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBreaksec(att->GetBreaksec()); + } + if (element->HasAttClass(ATT_BEAMEDWITH)) { + const AttBeamedWith *att = dynamic_cast(element); + assert(att); + AttBeamedWith *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeamWith(att->GetBeamWith()); + } + if (element->HasAttClass(ATT_BEAMINGLOG)) { + const AttBeamingLog *att = dynamic_cast(element); + assert(att); + AttBeamingLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeamGroup(att->GetBeamGroup()); + attTarget->SetBeamRests(att->GetBeamRests()); + } + if (element->HasAttClass(ATT_BEATRPTLOG)) { + const AttBeatRptLog *att = dynamic_cast(element); + assert(att); + AttBeatRptLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeatdef(att->GetBeatdef()); + } + if (element->HasAttClass(ATT_BRACKETSPANLOG)) { + const AttBracketSpanLog *att = dynamic_cast(element); + assert(att); + AttBracketSpanLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_CUTOUT)) { + const AttCutout *att = dynamic_cast(element); + assert(att); + AttCutout *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCutout(att->GetCutout()); + } + if (element->HasAttClass(ATT_EXPANDABLE)) { + const AttExpandable *att = dynamic_cast(element); + assert(att); + AttExpandable *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetExpand(att->GetExpand()); + } + if (element->HasAttClass(ATT_GLISSPRESENT)) { + const AttGlissPresent *att = dynamic_cast(element); + assert(att); + AttGlissPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetGliss(att->GetGliss()); + } + if (element->HasAttClass(ATT_GRACEGRPLOG)) { + const AttGraceGrpLog *att = dynamic_cast(element); + assert(att); + AttGraceGrpLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAttach(att->GetAttach()); + } + if (element->HasAttClass(ATT_GRACED)) { + const AttGraced *att = dynamic_cast(element); + assert(att); + AttGraced *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetGrace(att->GetGrace()); + attTarget->SetGraceTime(att->GetGraceTime()); + } + if (element->HasAttClass(ATT_HAIRPINLOG)) { + const AttHairpinLog *att = dynamic_cast(element); + assert(att); + AttHairpinLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetNiente(att->GetNiente()); + } + if (element->HasAttClass(ATT_HARPPEDALLOG)) { + const AttHarpPedalLog *att = dynamic_cast(element); + assert(att); + AttHarpPedalLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetC(att->GetC()); + attTarget->SetD(att->GetD()); + attTarget->SetE(att->GetE()); + attTarget->SetF(att->GetF()); + attTarget->SetG(att->GetG()); + attTarget->SetA(att->GetA()); + attTarget->SetB(att->GetB()); + } + if (element->HasAttClass(ATT_LVPRESENT)) { + const AttLvPresent *att = dynamic_cast(element); + assert(att); + AttLvPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLv(att->GetLv()); + } + if (element->HasAttClass(ATT_MEASURELOG)) { + const AttMeasureLog *att = dynamic_cast(element); + assert(att); + AttMeasureLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLeft(att->GetLeft()); + attTarget->SetRight(att->GetRight()); + } + if (element->HasAttClass(ATT_METERSIGGRPLOG)) { + const AttMeterSigGrpLog *att = dynamic_cast(element); + assert(att); + AttMeterSigGrpLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_NUMBERPLACEMENT)) { + const AttNumberPlacement *att = dynamic_cast(element); + assert(att); + AttNumberPlacement *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNumPlace(att->GetNumPlace()); + attTarget->SetNumVisible(att->GetNumVisible()); + } + if (element->HasAttClass(ATT_NUMBERED)) { + const AttNumbered *att = dynamic_cast(element); + assert(att); + AttNumbered *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNum(att->GetNum()); + } + if (element->HasAttClass(ATT_OCTAVELOG)) { + const AttOctaveLog *att = dynamic_cast(element); + assert(att); + AttOctaveLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetColl(att->GetColl()); + } + if (element->HasAttClass(ATT_PEDALLOG)) { + const AttPedalLog *att = dynamic_cast(element); + assert(att); + AttPedalLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDir(att->GetDir()); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_PIANOPEDALS)) { + const AttPianoPedals *att = dynamic_cast(element); + assert(att); + AttPianoPedals *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPedalStyle(att->GetPedalStyle()); + } + if (element->HasAttClass(ATT_REHEARSAL)) { + const AttRehearsal *att = dynamic_cast(element); + assert(att); + AttRehearsal *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetRehEnclose(att->GetRehEnclose()); + } + if (element->HasAttClass(ATT_SLURREND)) { + const AttSlurRend *att = dynamic_cast(element); + assert(att); + AttSlurRend *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSlurLform(att->GetSlurLform()); + attTarget->SetSlurLwidth(att->GetSlurLwidth()); + } + if (element->HasAttClass(ATT_STEMSCMN)) { + const AttStemsCmn *att = dynamic_cast(element); + assert(att); + AttStemsCmn *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStemWith(att->GetStemWith()); + } + if (element->HasAttClass(ATT_TIEREND)) { + const AttTieRend *att = dynamic_cast(element); + assert(att); + AttTieRend *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTieLform(att->GetTieLform()); + attTarget->SetTieLwidth(att->GetTieLwidth()); + } + if (element->HasAttClass(ATT_TREMFORM)) { + const AttTremForm *att = dynamic_cast(element); + assert(att); + AttTremForm *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_TREMMEASURED)) { + const AttTremMeasured *att = dynamic_cast(element); + assert(att); + AttTremMeasured *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetUnitdur(att->GetUnitdur()); + } +} + } // namespace vrv #include "atts_cmnornaments.h" @@ -891,6 +1189,41 @@ void AttModule::GetCmnornaments(const Object *element, ArrayOfStrAttr *attribute } } +void AttModule::CopyCmnornaments(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_MORDENTLOG)) { + const AttMordentLog *att = dynamic_cast(element); + assert(att); + AttMordentLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetLong(att->GetLong()); + } + if (element->HasAttClass(ATT_ORNAMPRESENT)) { + const AttOrnamPresent *att = dynamic_cast(element); + assert(att); + AttOrnamPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOrnam(att->GetOrnam()); + } + if (element->HasAttClass(ATT_ORNAMENTACCID)) { + const AttOrnamentAccid *att = dynamic_cast(element); + assert(att); + AttOrnamentAccid *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAccidupper(att->GetAccidupper()); + attTarget->SetAccidlower(att->GetAccidlower()); + } + if (element->HasAttClass(ATT_TURNLOG)) { + const AttTurnLog *att = dynamic_cast(element); + assert(att); + AttTurnLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDelayed(att->GetDelayed()); + attTarget->SetForm(att->GetForm()); + } +} + } // namespace vrv #include "atts_critapp.h" @@ -926,6 +1259,17 @@ void AttModule::GetCritapp(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyCritapp(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_CRIT)) { + const AttCrit *att = dynamic_cast(element); + assert(att); + AttCrit *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCause(att->GetCause()); + } +} + } // namespace vrv #include "atts_edittrans.h" @@ -976,6 +1320,24 @@ void AttModule::GetEdittrans(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyEdittrans(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_AGENTIDENT)) { + const AttAgentIdent *att = dynamic_cast(element); + assert(att); + AttAgentIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAgent(att->GetAgent()); + } + if (element->HasAttClass(ATT_REASONIDENT)) { + const AttReasonIdent *att = dynamic_cast(element); + assert(att); + AttReasonIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetReason(att->GetReason()); + } +} + } // namespace vrv #include "atts_externalsymbols.h" @@ -1040,6 +1402,26 @@ void AttModule::GetExternalsymbols(const Object *element, ArrayOfStrAttr *attrib } } +void AttModule::CopyExternalsymbols(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_EXTSYMAUTH)) { + const AttExtSymAuth *att = dynamic_cast(element); + assert(att); + AttExtSymAuth *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetGlyphAuth(att->GetGlyphAuth()); + attTarget->SetGlyphUri(att->GetGlyphUri()); + } + if (element->HasAttClass(ATT_EXTSYMNAMES)) { + const AttExtSymNames *att = dynamic_cast(element); + assert(att); + AttExtSymNames *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetGlyphName(att->GetGlyphName()); + attTarget->SetGlyphNum(att->GetGlyphNum()); + } +} + } // namespace vrv #include "atts_facsimile.h" @@ -1075,6 +1457,17 @@ void AttModule::GetFacsimile(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyFacsimile(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_FACSIMILE)) { + const AttFacsimile *att = dynamic_cast(element); + assert(att); + AttFacsimile *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFacs(att->GetFacs()); + } +} + } // namespace vrv #include "atts_figtable.h" @@ -1117,6 +1510,18 @@ void AttModule::GetFigtable(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyFigtable(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_TABULAR)) { + const AttTabular *att = dynamic_cast(element); + assert(att); + AttTabular *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetColspan(att->GetColspan()); + attTarget->SetRowspan(att->GetRowspan()); + } +} + } // namespace vrv #include "atts_fingering.h" @@ -1152,6 +1557,17 @@ void AttModule::GetFingering(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyFingering(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_FINGGRPLOG)) { + const AttFingGrpLog *att = dynamic_cast(element); + assert(att); + AttFingGrpLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } +} + } // namespace vrv #include "atts_frettab.h" @@ -1209,6 +1625,25 @@ void AttModule::GetFrettab(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyFrettab(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_COURSELOG)) { + const AttCourseLog *att = dynamic_cast(element); + assert(att); + AttCourseLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTuningStandard(att->GetTuningStandard()); + } + if (element->HasAttClass(ATT_NOTEGESTAB)) { + const AttNoteGesTab *att = dynamic_cast(element); + assert(att); + AttNoteGesTab *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTabCourse(att->GetTabCourse()); + attTarget->SetTabFret(att->GetTabFret()); + } +} + } // namespace vrv #include "atts_gestural.h" @@ -1471,20 +1906,112 @@ void AttModule::GetGestural(const Object *element, ArrayOfStrAttr *attributes) } } -} // namespace vrv - -#include "atts_harmony.h" - -namespace vrv { - -//---------------------------------------------------------------------------- -// Harmony -//---------------------------------------------------------------------------- - -bool AttModule::SetHarmony(Object *element, const std::string &attrType, const std::string &attrValue) +void AttModule::CopyGestural(const Object *element, Object *target) { - if (element->HasAttClass(ATT_HARMLOG)) { - AttHarmLog *att = dynamic_cast(element); + if (element->HasAttClass(ATT_ACCIDENTALGES)) { + const AttAccidentalGes *att = dynamic_cast(element); + assert(att); + AttAccidentalGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAccidGes(att->GetAccidGes()); + } + if (element->HasAttClass(ATT_ARTICULATIONGES)) { + const AttArticulationGes *att = dynamic_cast(element); + assert(att); + AttArticulationGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetArticGes(att->GetArticGes()); + } + if (element->HasAttClass(ATT_ATTACKING)) { + const AttAttacking *att = dynamic_cast(element); + assert(att); + AttAttacking *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAttacca(att->GetAttacca()); + } + if (element->HasAttClass(ATT_BENDGES)) { + const AttBendGes *att = dynamic_cast(element); + assert(att); + AttBendGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAmount(att->GetAmount()); + } + if (element->HasAttClass(ATT_DURATIONGES)) { + const AttDurationGes *att = dynamic_cast(element); + assert(att); + AttDurationGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDurGes(att->GetDurGes()); + attTarget->SetDotsGes(att->GetDotsGes()); + attTarget->SetDurMetrical(att->GetDurMetrical()); + attTarget->SetDurPpq(att->GetDurPpq()); + attTarget->SetDurReal(att->GetDurReal()); + attTarget->SetDurRecip(att->GetDurRecip()); + } + if (element->HasAttClass(ATT_NOTEGES)) { + const AttNoteGes *att = dynamic_cast(element); + assert(att); + AttNoteGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetExtremis(att->GetExtremis()); + } + if (element->HasAttClass(ATT_ORNAMENTACCIDGES)) { + const AttOrnamentAccidGes *att = dynamic_cast(element); + assert(att); + AttOrnamentAccidGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAccidupperGes(att->GetAccidupperGes()); + attTarget->SetAccidlowerGes(att->GetAccidlowerGes()); + } + if (element->HasAttClass(ATT_PITCHGES)) { + const AttPitchGes *att = dynamic_cast(element); + assert(att); + AttPitchGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOctGes(att->GetOctGes()); + attTarget->SetPnameGes(att->GetPnameGes()); + attTarget->SetPnum(att->GetPnum()); + } + if (element->HasAttClass(ATT_SOUNDLOCATION)) { + const AttSoundLocation *att = dynamic_cast(element); + assert(att); + AttSoundLocation *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAzimuth(att->GetAzimuth()); + attTarget->SetElevation(att->GetElevation()); + } + if (element->HasAttClass(ATT_TIMESTAMPGES)) { + const AttTimestampGes *att = dynamic_cast(element); + assert(att); + AttTimestampGes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTstampGes(att->GetTstampGes()); + attTarget->SetTstampReal(att->GetTstampReal()); + } + if (element->HasAttClass(ATT_TIMESTAMP2GES)) { + const AttTimestamp2Ges *att = dynamic_cast(element); + assert(att); + AttTimestamp2Ges *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTstamp2Ges(att->GetTstamp2Ges()); + attTarget->SetTstamp2Real(att->GetTstamp2Real()); + } +} + +} // namespace vrv + +#include "atts_harmony.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// Harmony +//---------------------------------------------------------------------------- + +bool AttModule::SetHarmony(Object *element, const std::string &attrType, const std::string &attrValue) +{ + if (element->HasAttClass(ATT_HARMLOG)) { + AttHarmLog *att = dynamic_cast(element); assert(att); if (attrType == "chordref") { att->SetChordref(att->StrToStr(attrValue)); @@ -1506,6 +2033,17 @@ void AttModule::GetHarmony(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyHarmony(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_HARMLOG)) { + const AttHarmLog *att = dynamic_cast(element); + assert(att); + AttHarmLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetChordref(att->GetChordref()); + } +} + } // namespace vrv #include "atts_header.h" @@ -1659,6 +2197,63 @@ void AttModule::GetHeader(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyHeader(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_ADLIBITUM)) { + const AttAdlibitum *att = dynamic_cast(element); + assert(att); + AttAdlibitum *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAdlib(att->GetAdlib()); + } + if (element->HasAttClass(ATT_BIFOLIUMSURFACES)) { + const AttBifoliumSurfaces *att = dynamic_cast(element); + assert(att); + AttBifoliumSurfaces *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOuterRecto(att->GetOuterRecto()); + attTarget->SetInnerVerso(att->GetInnerVerso()); + attTarget->SetInnerRecto(att->GetInnerRecto()); + attTarget->SetOuterVerso(att->GetOuterVerso()); + } + if (element->HasAttClass(ATT_FOLIUMSURFACES)) { + const AttFoliumSurfaces *att = dynamic_cast(element); + assert(att); + AttFoliumSurfaces *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetRecto(att->GetRecto()); + attTarget->SetVerso(att->GetVerso()); + } + if (element->HasAttClass(ATT_PERFRES)) { + const AttPerfRes *att = dynamic_cast(element); + assert(att); + AttPerfRes *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSolo(att->GetSolo()); + } + if (element->HasAttClass(ATT_PERFRESBASIC)) { + const AttPerfResBasic *att = dynamic_cast(element); + assert(att); + AttPerfResBasic *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCount(att->GetCount()); + } + if (element->HasAttClass(ATT_RECORDTYPE)) { + const AttRecordType *att = dynamic_cast(element); + assert(att); + AttRecordType *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetRecordtype(att->GetRecordtype()); + } + if (element->HasAttClass(ATT_REGULARMETHOD)) { + const AttRegularMethod *att = dynamic_cast(element); + assert(att); + AttRegularMethod *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMethod(att->GetMethod()); + } +} + } // namespace vrv #include "atts_mensural.h" @@ -1804,6 +2399,57 @@ void AttModule::GetMensural(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyMensural(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_DURATIONQUALITY)) { + const AttDurationQuality *att = dynamic_cast(element); + assert(att); + AttDurationQuality *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDurQuality(att->GetDurQuality()); + } + if (element->HasAttClass(ATT_MENSURALLOG)) { + const AttMensuralLog *att = dynamic_cast(element); + assert(att); + AttMensuralLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetProportNum(att->GetProportNum()); + attTarget->SetProportNumbase(att->GetProportNumbase()); + } + if (element->HasAttClass(ATT_MENSURALSHARED)) { + const AttMensuralShared *att = dynamic_cast(element); + assert(att); + AttMensuralShared *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetModusmaior(att->GetModusmaior()); + attTarget->SetModusminor(att->GetModusminor()); + attTarget->SetProlatio(att->GetProlatio()); + attTarget->SetTempus(att->GetTempus()); + attTarget->SetDivisio(att->GetDivisio()); + } + if (element->HasAttClass(ATT_NOTEVISMENSURAL)) { + const AttNoteVisMensural *att = dynamic_cast(element); + assert(att); + AttNoteVisMensural *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLig(att->GetLig()); + } + if (element->HasAttClass(ATT_RESTVISMENSURAL)) { + const AttRestVisMensural *att = dynamic_cast(element); + assert(att); + AttRestVisMensural *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSpaces(att->GetSpaces()); + } + if (element->HasAttClass(ATT_STEMSMENSURAL)) { + const AttStemsMensural *att = dynamic_cast(element); + assert(att); + AttStemsMensural *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStemForm(att->GetStemForm()); + } +} + } // namespace vrv #include "atts_midi.h" @@ -2022,6 +2668,82 @@ void AttModule::GetMidi(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyMidi(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_CHANNELIZED)) { + const AttChannelized *att = dynamic_cast(element); + assert(att); + AttChannelized *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMidiChannel(att->GetMidiChannel()); + attTarget->SetMidiDuty(att->GetMidiDuty()); + attTarget->SetMidiPort(att->GetMidiPort()); + attTarget->SetMidiTrack(att->GetMidiTrack()); + } + if (element->HasAttClass(ATT_INSTRUMENTIDENT)) { + const AttInstrumentIdent *att = dynamic_cast(element); + assert(att); + AttInstrumentIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetInstr(att->GetInstr()); + } + if (element->HasAttClass(ATT_MIDIINSTRUMENT)) { + const AttMidiInstrument *att = dynamic_cast(element); + assert(att); + AttMidiInstrument *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMidiInstrnum(att->GetMidiInstrnum()); + attTarget->SetMidiInstrname(att->GetMidiInstrname()); + attTarget->SetMidiPan(att->GetMidiPan()); + attTarget->SetMidiPatchname(att->GetMidiPatchname()); + attTarget->SetMidiPatchnum(att->GetMidiPatchnum()); + attTarget->SetMidiVolume(att->GetMidiVolume()); + } + if (element->HasAttClass(ATT_MIDINUMBER)) { + const AttMidiNumber *att = dynamic_cast(element); + assert(att); + AttMidiNumber *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNum(att->GetNum()); + } + if (element->HasAttClass(ATT_MIDITEMPO)) { + const AttMidiTempo *att = dynamic_cast(element); + assert(att); + AttMidiTempo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMidiBpm(att->GetMidiBpm()); + attTarget->SetMidiMspb(att->GetMidiMspb()); + } + if (element->HasAttClass(ATT_MIDIVALUE)) { + const AttMidiValue *att = dynamic_cast(element); + assert(att); + AttMidiValue *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVal(att->GetVal()); + } + if (element->HasAttClass(ATT_MIDIVALUE2)) { + const AttMidiValue2 *att = dynamic_cast(element); + assert(att); + AttMidiValue2 *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVal2(att->GetVal2()); + } + if (element->HasAttClass(ATT_MIDIVELOCITY)) { + const AttMidiVelocity *att = dynamic_cast(element); + assert(att); + AttMidiVelocity *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVel(att->GetVel()); + } + if (element->HasAttClass(ATT_TIMEBASE)) { + const AttTimeBase *att = dynamic_cast(element); + assert(att); + AttTimeBase *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPpq(att->GetPpq()); + } +} + } // namespace vrv #include "atts_neumes.h" @@ -2151,6 +2873,45 @@ void AttModule::GetNeumes(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyNeumes(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_DIVLINELOG)) { + const AttDivLineLog *att = dynamic_cast(element); + assert(att); + AttDivLineLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_NCLOG)) { + const AttNcLog *att = dynamic_cast(element); + assert(att); + AttNcLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOct(att->GetOct()); + attTarget->SetPname(att->GetPname()); + } + if (element->HasAttClass(ATT_NCFORM)) { + const AttNcForm *att = dynamic_cast(element); + assert(att); + AttNcForm *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAngled(att->GetAngled()); + attTarget->SetCon(att->GetCon()); + attTarget->SetHooked(att->GetHooked()); + attTarget->SetLigated(att->GetLigated()); + attTarget->SetRellen(att->GetRellen()); + attTarget->SetSShape(att->GetSShape()); + attTarget->SetTilt(att->GetTilt()); + } + if (element->HasAttClass(ATT_NEUMETYPE)) { + const AttNeumeType *att = dynamic_cast(element); + assert(att); + AttNeumeType *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetType(att->GetType()); + } +} + } // namespace vrv #include "atts_pagebased.h" @@ -2207,6 +2968,20 @@ void AttModule::GetPagebased(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyPagebased(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_MARGINS)) { + const AttMargins *att = dynamic_cast(element); + assert(att); + AttMargins *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTopmar(att->GetTopmar()); + attTarget->SetBotmar(att->GetBotmar()); + attTarget->SetLeftmar(att->GetLeftmar()); + attTarget->SetRightmar(att->GetRightmar()); + } +} + } // namespace vrv #include "atts_performance.h" @@ -2242,6 +3017,17 @@ void AttModule::GetPerformance(const Object *element, ArrayOfStrAttr *attributes } } +void AttModule::CopyPerformance(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_ALIGNMENT)) { + const AttAlignment *att = dynamic_cast(element); + assert(att); + AttAlignment *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetWhen(att->GetWhen()); + } +} + } // namespace vrv #include "atts_shared.h" @@ -5257,67 +6043,1208 @@ void AttModule::GetShared(const Object *element, ArrayOfStrAttr *attributes) } } -} // namespace vrv - -#include "atts_usersymbols.h" - -namespace vrv { - -//---------------------------------------------------------------------------- -// Usersymbols -//---------------------------------------------------------------------------- - -bool AttModule::SetUsersymbols(Object *element, const std::string &attrType, const std::string &attrValue) +void AttModule::CopyShared(const Object *element, Object *target) { - if (element->HasAttClass(ATT_ALTSYM)) { - AttAltSym *att = dynamic_cast(element); + if (element->HasAttClass(ATT_ACCIDLOG)) { + const AttAccidLog *att = dynamic_cast(element); assert(att); - if (attrType == "altsym") { - att->SetAltsym(att->StrToStr(attrValue)); - return true; - } + AttAccidLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); } - if (element->HasAttClass(ATT_ANCHOREDTEXTLOG)) { - AttAnchoredTextLog *att = dynamic_cast(element); + if (element->HasAttClass(ATT_ACCIDENTAL)) { + const AttAccidental *att = dynamic_cast(element); assert(att); - if (attrType == "func") { - att->SetFunc(att->StrToStr(attrValue)); - return true; - } + AttAccidental *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAccid(att->GetAccid()); } - if (element->HasAttClass(ATT_CURVELOG)) { - AttCurveLog *att = dynamic_cast(element); + if (element->HasAttClass(ATT_ARTICULATION)) { + const AttArticulation *att = dynamic_cast(element); assert(att); - if (attrType == "func") { - att->SetFunc(att->StrToStr(attrValue)); - return true; - } + AttArticulation *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetArtic(att->GetArtic()); } - if (element->HasAttClass(ATT_LINELOG)) { - AttLineLog *att = dynamic_cast(element); + if (element->HasAttClass(ATT_ATTACCALOG)) { + const AttAttaccaLog *att = dynamic_cast(element); assert(att); - if (attrType == "func") { - att->SetFunc(att->StrToStr(attrValue)); - return true; - } + AttAttaccaLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTarget(att->GetTarget()); } - - return false; -} - -void AttModule::GetUsersymbols(const Object *element, ArrayOfStrAttr *attributes) -{ - if (element->HasAttClass(ATT_ALTSYM)) { - const AttAltSym *att = dynamic_cast(element); + if (element->HasAttClass(ATT_AUDIENCE)) { + const AttAudience *att = dynamic_cast(element); assert(att); - if (att->HasAltsym()) { - attributes->push_back({ "altsym", att->StrToStr(att->GetAltsym()) }); - } + AttAudience *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAudience(att->GetAudience()); } - if (element->HasAttClass(ATT_ANCHOREDTEXTLOG)) { - const AttAnchoredTextLog *att = dynamic_cast(element); + if (element->HasAttClass(ATT_AUGMENTDOTS)) { + const AttAugmentDots *att = dynamic_cast(element); assert(att); - if (att->HasFunc()) { + AttAugmentDots *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDots(att->GetDots()); + } + if (element->HasAttClass(ATT_AUTHORIZED)) { + const AttAuthorized *att = dynamic_cast(element); + assert(att); + AttAuthorized *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAuth(att->GetAuth()); + attTarget->SetAuthUri(att->GetAuthUri()); + } + if (element->HasAttClass(ATT_BARLINELOG)) { + const AttBarLineLog *att = dynamic_cast(element); + assert(att); + AttBarLineLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_BARRING)) { + const AttBarring *att = dynamic_cast(element); + assert(att); + AttBarring *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBarLen(att->GetBarLen()); + attTarget->SetBarMethod(att->GetBarMethod()); + attTarget->SetBarPlace(att->GetBarPlace()); + } + if (element->HasAttClass(ATT_BASIC)) { + const AttBasic *att = dynamic_cast(element); + assert(att); + AttBasic *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBase(att->GetBase()); + } + if (element->HasAttClass(ATT_BIBL)) { + const AttBibl *att = dynamic_cast(element); + assert(att); + AttBibl *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAnalog(att->GetAnalog()); + } + if (element->HasAttClass(ATT_CALENDARED)) { + const AttCalendared *att = dynamic_cast(element); + assert(att); + AttCalendared *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCalendar(att->GetCalendar()); + } + if (element->HasAttClass(ATT_CANONICAL)) { + const AttCanonical *att = dynamic_cast(element); + assert(att); + AttCanonical *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCodedval(att->GetCodedval()); + } + if (element->HasAttClass(ATT_CLASSED)) { + const AttClassed *att = dynamic_cast(element); + assert(att); + AttClassed *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetClass(att->GetClass()); + } + if (element->HasAttClass(ATT_CLEFLOG)) { + const AttClefLog *att = dynamic_cast(element); + assert(att); + AttClefLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCautionary(att->GetCautionary()); + } + if (element->HasAttClass(ATT_CLEFSHAPE)) { + const AttClefShape *att = dynamic_cast(element); + assert(att); + AttClefShape *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetShape(att->GetShape()); + } + if (element->HasAttClass(ATT_CLEFFINGLOG)) { + const AttCleffingLog *att = dynamic_cast(element); + assert(att); + AttCleffingLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetClefShape(att->GetClefShape()); + attTarget->SetClefLine(att->GetClefLine()); + attTarget->SetClefDis(att->GetClefDis()); + attTarget->SetClefDisPlace(att->GetClefDisPlace()); + } + if (element->HasAttClass(ATT_COLOR)) { + const AttColor *att = dynamic_cast(element); + assert(att); + AttColor *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetColor(att->GetColor()); + } + if (element->HasAttClass(ATT_COLORATION)) { + const AttColoration *att = dynamic_cast(element); + assert(att); + AttColoration *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetColored(att->GetColored()); + } + if (element->HasAttClass(ATT_COORDX1)) { + const AttCoordX1 *att = dynamic_cast(element); + assert(att); + AttCoordX1 *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCoordX1(att->GetCoordX1()); + } + if (element->HasAttClass(ATT_COORDX2)) { + const AttCoordX2 *att = dynamic_cast(element); + assert(att); + AttCoordX2 *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCoordX2(att->GetCoordX2()); + } + if (element->HasAttClass(ATT_COORDY1)) { + const AttCoordY1 *att = dynamic_cast(element); + assert(att); + AttCoordY1 *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCoordY1(att->GetCoordY1()); + } + if (element->HasAttClass(ATT_COORDINATED)) { + const AttCoordinated *att = dynamic_cast(element); + assert(att); + AttCoordinated *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLrx(att->GetLrx()); + attTarget->SetLry(att->GetLry()); + attTarget->SetRotate(att->GetRotate()); + } + if (element->HasAttClass(ATT_COORDINATEDUL)) { + const AttCoordinatedUl *att = dynamic_cast(element); + assert(att); + AttCoordinatedUl *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetUlx(att->GetUlx()); + attTarget->SetUly(att->GetUly()); + } + if (element->HasAttClass(ATT_CUE)) { + const AttCue *att = dynamic_cast(element); + assert(att); + AttCue *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCue(att->GetCue()); + } + if (element->HasAttClass(ATT_CURVATURE)) { + const AttCurvature *att = dynamic_cast(element); + assert(att); + AttCurvature *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBezier(att->GetBezier()); + attTarget->SetBulge(att->GetBulge()); + attTarget->SetCurvedir(att->GetCurvedir()); + } + if (element->HasAttClass(ATT_CUSTOSLOG)) { + const AttCustosLog *att = dynamic_cast(element); + assert(att); + AttCustosLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTarget(att->GetTarget()); + } + if (element->HasAttClass(ATT_DATAPOINTING)) { + const AttDataPointing *att = dynamic_cast(element); + assert(att); + AttDataPointing *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetData(att->GetData()); + } + if (element->HasAttClass(ATT_DATABLE)) { + const AttDatable *att = dynamic_cast(element); + assert(att); + AttDatable *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetEnddate(att->GetEnddate()); + attTarget->SetIsodate(att->GetIsodate()); + attTarget->SetNotafter(att->GetNotafter()); + attTarget->SetNotbefore(att->GetNotbefore()); + attTarget->SetStartdate(att->GetStartdate()); + } + if (element->HasAttClass(ATT_DISTANCES)) { + const AttDistances *att = dynamic_cast(element); + assert(att); + AttDistances *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDirDist(att->GetDirDist()); + attTarget->SetDynamDist(att->GetDynamDist()); + attTarget->SetHarmDist(att->GetHarmDist()); + attTarget->SetRehDist(att->GetRehDist()); + attTarget->SetTempoDist(att->GetTempoDist()); + } + if (element->HasAttClass(ATT_DOTLOG)) { + const AttDotLog *att = dynamic_cast(element); + assert(att); + AttDotLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_DURATIONADDITIVE)) { + const AttDurationAdditive *att = dynamic_cast(element); + assert(att); + AttDurationAdditive *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDur(att->GetDur()); + } + if (element->HasAttClass(ATT_DURATIONDEFAULT)) { + const AttDurationDefault *att = dynamic_cast(element); + assert(att); + AttDurationDefault *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDurDefault(att->GetDurDefault()); + attTarget->SetNumDefault(att->GetNumDefault()); + attTarget->SetNumbaseDefault(att->GetNumbaseDefault()); + } + if (element->HasAttClass(ATT_DURATIONLOG)) { + const AttDurationLog *att = dynamic_cast(element); + assert(att); + AttDurationLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDur(att->GetDur()); + } + if (element->HasAttClass(ATT_DURATIONRATIO)) { + const AttDurationRatio *att = dynamic_cast(element); + assert(att); + AttDurationRatio *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNum(att->GetNum()); + attTarget->SetNumbase(att->GetNumbase()); + } + if (element->HasAttClass(ATT_ENCLOSINGCHARS)) { + const AttEnclosingChars *att = dynamic_cast(element); + assert(att); + AttEnclosingChars *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetEnclose(att->GetEnclose()); + } + if (element->HasAttClass(ATT_ENDINGS)) { + const AttEndings *att = dynamic_cast(element); + assert(att); + AttEndings *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetEndingRend(att->GetEndingRend()); + } + if (element->HasAttClass(ATT_EVIDENCE)) { + const AttEvidence *att = dynamic_cast(element); + assert(att); + AttEvidence *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCert(att->GetCert()); + attTarget->SetEvidence(att->GetEvidence()); + } + if (element->HasAttClass(ATT_EXTENDER)) { + const AttExtender *att = dynamic_cast(element); + assert(att); + AttExtender *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetExtender(att->GetExtender()); + } + if (element->HasAttClass(ATT_EXTENT)) { + const AttExtent *att = dynamic_cast(element); + assert(att); + AttExtent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetExtent(att->GetExtent()); + } + if (element->HasAttClass(ATT_FERMATAPRESENT)) { + const AttFermataPresent *att = dynamic_cast(element); + assert(att); + AttFermataPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFermata(att->GetFermata()); + } + if (element->HasAttClass(ATT_FILING)) { + const AttFiling *att = dynamic_cast(element); + assert(att); + AttFiling *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNonfiling(att->GetNonfiling()); + } + if (element->HasAttClass(ATT_FORMEWORK)) { + const AttFormework *att = dynamic_cast(element); + assert(att); + AttFormework *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_GRPSYMLOG)) { + const AttGrpSymLog *att = dynamic_cast(element); + assert(att); + AttGrpSymLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLevel(att->GetLevel()); + } + if (element->HasAttClass(ATT_HANDIDENT)) { + const AttHandIdent *att = dynamic_cast(element); + assert(att); + AttHandIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetHand(att->GetHand()); + } + if (element->HasAttClass(ATT_HEIGHT)) { + const AttHeight *att = dynamic_cast(element); + assert(att); + AttHeight *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetHeight(att->GetHeight()); + } + if (element->HasAttClass(ATT_HORIZONTALALIGN)) { + const AttHorizontalAlign *att = dynamic_cast(element); + assert(att); + AttHorizontalAlign *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetHalign(att->GetHalign()); + } + if (element->HasAttClass(ATT_INTERNETMEDIA)) { + const AttInternetMedia *att = dynamic_cast(element); + assert(att); + AttInternetMedia *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMimetype(att->GetMimetype()); + } + if (element->HasAttClass(ATT_JOINED)) { + const AttJoined *att = dynamic_cast(element); + assert(att); + AttJoined *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetJoin(att->GetJoin()); + } + if (element->HasAttClass(ATT_KEYMODE)) { + const AttKeyMode *att = dynamic_cast(element); + assert(att); + AttKeyMode *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMode(att->GetMode()); + } + if (element->HasAttClass(ATT_KEYSIGLOG)) { + const AttKeySigLog *att = dynamic_cast(element); + assert(att); + AttKeySigLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSig(att->GetSig()); + } + if (element->HasAttClass(ATT_KEYSIGDEFAULTLOG)) { + const AttKeySigDefaultLog *att = dynamic_cast(element); + assert(att); + AttKeySigDefaultLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetKeysig(att->GetKeysig()); + } + if (element->HasAttClass(ATT_LABELLED)) { + const AttLabelled *att = dynamic_cast(element); + assert(att); + AttLabelled *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLabel(att->GetLabel()); + } + if (element->HasAttClass(ATT_LANG)) { + const AttLang *att = dynamic_cast(element); + assert(att); + AttLang *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLang(att->GetLang()); + attTarget->SetTranslit(att->GetTranslit()); + } + if (element->HasAttClass(ATT_LAYERLOG)) { + const AttLayerLog *att = dynamic_cast(element); + assert(att); + AttLayerLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDef(att->GetDef()); + } + if (element->HasAttClass(ATT_LAYERIDENT)) { + const AttLayerIdent *att = dynamic_cast(element); + assert(att); + AttLayerIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLayer(att->GetLayer()); + } + if (element->HasAttClass(ATT_LINELOC)) { + const AttLineLoc *att = dynamic_cast(element); + assert(att); + AttLineLoc *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLine(att->GetLine()); + } + if (element->HasAttClass(ATT_LINEREND)) { + const AttLineRend *att = dynamic_cast(element); + assert(att); + AttLineRend *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLendsym(att->GetLendsym()); + attTarget->SetLendsymSize(att->GetLendsymSize()); + attTarget->SetLstartsym(att->GetLstartsym()); + attTarget->SetLstartsymSize(att->GetLstartsymSize()); + } + if (element->HasAttClass(ATT_LINERENDBASE)) { + const AttLineRendBase *att = dynamic_cast(element); + assert(att); + AttLineRendBase *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLform(att->GetLform()); + attTarget->SetLwidth(att->GetLwidth()); + attTarget->SetLsegs(att->GetLsegs()); + } + if (element->HasAttClass(ATT_LINKING)) { + const AttLinking *att = dynamic_cast(element); + assert(att); + AttLinking *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCopyof(att->GetCopyof()); + attTarget->SetCorresp(att->GetCorresp()); + attTarget->SetFollows(att->GetFollows()); + attTarget->SetNext(att->GetNext()); + attTarget->SetPrecedes(att->GetPrecedes()); + attTarget->SetPrev(att->GetPrev()); + attTarget->SetSameas(att->GetSameas()); + attTarget->SetSynch(att->GetSynch()); + } + if (element->HasAttClass(ATT_LYRICSTYLE)) { + const AttLyricStyle *att = dynamic_cast(element); + assert(att); + AttLyricStyle *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLyricAlign(att->GetLyricAlign()); + attTarget->SetLyricFam(att->GetLyricFam()); + attTarget->SetLyricName(att->GetLyricName()); + attTarget->SetLyricSize(att->GetLyricSize()); + attTarget->SetLyricStyle(att->GetLyricStyle()); + attTarget->SetLyricWeight(att->GetLyricWeight()); + } + if (element->HasAttClass(ATT_MEASURENUMBERS)) { + const AttMeasureNumbers *att = dynamic_cast(element); + assert(att); + AttMeasureNumbers *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMnumVisible(att->GetMnumVisible()); + } + if (element->HasAttClass(ATT_MEASUREMENT)) { + const AttMeasurement *att = dynamic_cast(element); + assert(att); + AttMeasurement *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetUnit(att->GetUnit()); + } + if (element->HasAttClass(ATT_MEDIABOUNDS)) { + const AttMediaBounds *att = dynamic_cast(element); + assert(att); + AttMediaBounds *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBegin(att->GetBegin()); + attTarget->SetEnd(att->GetEnd()); + attTarget->SetBetype(att->GetBetype()); + } + if (element->HasAttClass(ATT_MEDIUM)) { + const AttMedium *att = dynamic_cast(element); + assert(att); + AttMedium *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMedium(att->GetMedium()); + } + if (element->HasAttClass(ATT_MEIVERSION)) { + const AttMeiVersion *att = dynamic_cast(element); + assert(att); + AttMeiVersion *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMeiversion(att->GetMeiversion()); + } + if (element->HasAttClass(ATT_MENSURLOG)) { + const AttMensurLog *att = dynamic_cast(element); + assert(att); + AttMensurLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLevel(att->GetLevel()); + } + if (element->HasAttClass(ATT_METADATAPOINTING)) { + const AttMetadataPointing *att = dynamic_cast(element); + assert(att); + AttMetadataPointing *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDecls(att->GetDecls()); + } + if (element->HasAttClass(ATT_METERCONFORMANCE)) { + const AttMeterConformance *att = dynamic_cast(element); + assert(att); + AttMeterConformance *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMetcon(att->GetMetcon()); + } + if (element->HasAttClass(ATT_METERCONFORMANCEBAR)) { + const AttMeterConformanceBar *att = dynamic_cast(element); + assert(att); + AttMeterConformanceBar *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMetcon(att->GetMetcon()); + attTarget->SetControl(att->GetControl()); + } + if (element->HasAttClass(ATT_METERSIGLOG)) { + const AttMeterSigLog *att = dynamic_cast(element); + assert(att); + AttMeterSigLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCount(att->GetCount()); + attTarget->SetSym(att->GetSym()); + attTarget->SetUnit(att->GetUnit()); + } + if (element->HasAttClass(ATT_METERSIGDEFAULTLOG)) { + const AttMeterSigDefaultLog *att = dynamic_cast(element); + assert(att); + AttMeterSigDefaultLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMeterCount(att->GetMeterCount()); + attTarget->SetMeterUnit(att->GetMeterUnit()); + attTarget->SetMeterSym(att->GetMeterSym()); + } + if (element->HasAttClass(ATT_MMTEMPO)) { + const AttMmTempo *att = dynamic_cast(element); + assert(att); + AttMmTempo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMm(att->GetMm()); + attTarget->SetMmUnit(att->GetMmUnit()); + attTarget->SetMmDots(att->GetMmDots()); + } + if (element->HasAttClass(ATT_MULTINUMMEASURES)) { + const AttMultinumMeasures *att = dynamic_cast(element); + assert(att); + AttMultinumMeasures *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMultiNumber(att->GetMultiNumber()); + } + if (element->HasAttClass(ATT_NINTEGER)) { + const AttNInteger *att = dynamic_cast(element); + assert(att); + AttNInteger *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetN(att->GetN()); + } + if (element->HasAttClass(ATT_NNUMBERLIKE)) { + const AttNNumberLike *att = dynamic_cast(element); + assert(att); + AttNNumberLike *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetN(att->GetN()); + } + if (element->HasAttClass(ATT_NAME)) { + const AttName *att = dynamic_cast(element); + assert(att); + AttName *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetNymref(att->GetNymref()); + attTarget->SetRole(att->GetRole()); + } + if (element->HasAttClass(ATT_NOTATIONSTYLE)) { + const AttNotationStyle *att = dynamic_cast(element); + assert(att); + AttNotationStyle *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMusicName(att->GetMusicName()); + attTarget->SetMusicSize(att->GetMusicSize()); + } + if (element->HasAttClass(ATT_NOTEHEADS)) { + const AttNoteHeads *att = dynamic_cast(element); + assert(att); + AttNoteHeads *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetHeadAltsym(att->GetHeadAltsym()); + attTarget->SetHeadAuth(att->GetHeadAuth()); + attTarget->SetHeadColor(att->GetHeadColor()); + attTarget->SetHeadFill(att->GetHeadFill()); + attTarget->SetHeadFillcolor(att->GetHeadFillcolor()); + attTarget->SetHeadMod(att->GetHeadMod()); + attTarget->SetHeadRotation(att->GetHeadRotation()); + attTarget->SetHeadShape(att->GetHeadShape()); + attTarget->SetHeadVisible(att->GetHeadVisible()); + } + if (element->HasAttClass(ATT_OCTAVE)) { + const AttOctave *att = dynamic_cast(element); + assert(att); + AttOctave *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOct(att->GetOct()); + } + if (element->HasAttClass(ATT_OCTAVEDEFAULT)) { + const AttOctaveDefault *att = dynamic_cast(element); + assert(att); + AttOctaveDefault *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOctDefault(att->GetOctDefault()); + } + if (element->HasAttClass(ATT_OCTAVEDISPLACEMENT)) { + const AttOctaveDisplacement *att = dynamic_cast(element); + assert(att); + AttOctaveDisplacement *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDis(att->GetDis()); + attTarget->SetDisPlace(att->GetDisPlace()); + } + if (element->HasAttClass(ATT_ONELINESTAFF)) { + const AttOneLineStaff *att = dynamic_cast(element); + assert(att); + AttOneLineStaff *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOntheline(att->GetOntheline()); + } + if (element->HasAttClass(ATT_OPTIMIZATION)) { + const AttOptimization *att = dynamic_cast(element); + assert(att); + AttOptimization *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOptimize(att->GetOptimize()); + } + if (element->HasAttClass(ATT_ORIGINLAYERIDENT)) { + const AttOriginLayerIdent *att = dynamic_cast(element); + assert(att); + AttOriginLayerIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOriginLayer(att->GetOriginLayer()); + } + if (element->HasAttClass(ATT_ORIGINSTAFFIDENT)) { + const AttOriginStaffIdent *att = dynamic_cast(element); + assert(att); + AttOriginStaffIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOriginStaff(att->GetOriginStaff()); + } + if (element->HasAttClass(ATT_ORIGINSTARTENDID)) { + const AttOriginStartEndId *att = dynamic_cast(element); + assert(att); + AttOriginStartEndId *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOriginStartid(att->GetOriginStartid()); + attTarget->SetOriginEndid(att->GetOriginEndid()); + } + if (element->HasAttClass(ATT_ORIGINTIMESTAMPLOG)) { + const AttOriginTimestampLog *att = dynamic_cast(element); + assert(att); + AttOriginTimestampLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOriginTstamp(att->GetOriginTstamp()); + attTarget->SetOriginTstamp2(att->GetOriginTstamp2()); + } + if (element->HasAttClass(ATT_PAGES)) { + const AttPages *att = dynamic_cast(element); + assert(att); + AttPages *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPageHeight(att->GetPageHeight()); + attTarget->SetPageWidth(att->GetPageWidth()); + attTarget->SetPageTopmar(att->GetPageTopmar()); + attTarget->SetPageBotmar(att->GetPageBotmar()); + attTarget->SetPageLeftmar(att->GetPageLeftmar()); + attTarget->SetPageRightmar(att->GetPageRightmar()); + attTarget->SetPagePanels(att->GetPagePanels()); + attTarget->SetPageScale(att->GetPageScale()); + } + if (element->HasAttClass(ATT_PARTIDENT)) { + const AttPartIdent *att = dynamic_cast(element); + assert(att); + AttPartIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPart(att->GetPart()); + attTarget->SetPartstaff(att->GetPartstaff()); + } + if (element->HasAttClass(ATT_PITCH)) { + const AttPitch *att = dynamic_cast(element); + assert(att); + AttPitch *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPname(att->GetPname()); + } + if (element->HasAttClass(ATT_PLACEMENTONSTAFF)) { + const AttPlacementOnStaff *att = dynamic_cast(element); + assert(att); + AttPlacementOnStaff *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOnstaff(att->GetOnstaff()); + } + if (element->HasAttClass(ATT_PLACEMENTRELEVENT)) { + const AttPlacementRelEvent *att = dynamic_cast(element); + assert(att); + AttPlacementRelEvent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_PLACEMENTRELSTAFF)) { + const AttPlacementRelStaff *att = dynamic_cast(element); + assert(att); + AttPlacementRelStaff *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_PLIST)) { + const AttPlist *att = dynamic_cast(element); + assert(att); + AttPlist *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlist(att->GetPlist()); + } + if (element->HasAttClass(ATT_POINTING)) { + const AttPointing *att = dynamic_cast(element); + assert(att); + AttPointing *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetActuate(att->GetActuate()); + attTarget->SetRole(att->GetRole()); + attTarget->SetShow(att->GetShow()); + attTarget->SetTarget(att->GetTarget()); + attTarget->SetTargettype(att->GetTargettype()); + } + if (element->HasAttClass(ATT_QUANTITY)) { + const AttQuantity *att = dynamic_cast(element); + assert(att); + AttQuantity *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetQuantity(att->GetQuantity()); + } + if (element->HasAttClass(ATT_RANGING)) { + const AttRanging *att = dynamic_cast(element); + assert(att); + AttRanging *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAtleast(att->GetAtleast()); + attTarget->SetAtmost(att->GetAtmost()); + attTarget->SetMin(att->GetMin()); + attTarget->SetMax(att->GetMax()); + attTarget->SetConfidence(att->GetConfidence()); + } + if (element->HasAttClass(ATT_REPEATMARKLOG)) { + const AttRepeatMarkLog *att = dynamic_cast(element); + assert(att); + AttRepeatMarkLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_RESPONSIBILITY)) { + const AttResponsibility *att = dynamic_cast(element); + assert(att); + AttResponsibility *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetResp(att->GetResp()); + } + if (element->HasAttClass(ATT_RESTDURATIONLOG)) { + const AttRestdurationLog *att = dynamic_cast(element); + assert(att); + AttRestdurationLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDur(att->GetDur()); + } + if (element->HasAttClass(ATT_SCALABLE)) { + const AttScalable *att = dynamic_cast(element); + assert(att); + AttScalable *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetScale(att->GetScale()); + } + if (element->HasAttClass(ATT_SEQUENCE)) { + const AttSequence *att = dynamic_cast(element); + assert(att); + AttSequence *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSeq(att->GetSeq()); + } + if (element->HasAttClass(ATT_SLASHCOUNT)) { + const AttSlashCount *att = dynamic_cast(element); + assert(att); + AttSlashCount *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSlash(att->GetSlash()); + } + if (element->HasAttClass(ATT_SLURPRESENT)) { + const AttSlurPresent *att = dynamic_cast(element); + assert(att); + AttSlurPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSlur(att->GetSlur()); + } + if (element->HasAttClass(ATT_SOURCE)) { + const AttSource *att = dynamic_cast(element); + assert(att); + AttSource *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSource(att->GetSource()); + } + if (element->HasAttClass(ATT_SPACING)) { + const AttSpacing *att = dynamic_cast(element); + assert(att); + AttSpacing *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSpacingPackexp(att->GetSpacingPackexp()); + attTarget->SetSpacingPackfact(att->GetSpacingPackfact()); + attTarget->SetSpacingStaff(att->GetSpacingStaff()); + attTarget->SetSpacingSystem(att->GetSpacingSystem()); + } + if (element->HasAttClass(ATT_STAFFLOG)) { + const AttStaffLog *att = dynamic_cast(element); + assert(att); + AttStaffLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDef(att->GetDef()); + } + if (element->HasAttClass(ATT_STAFFDEFLOG)) { + const AttStaffDefLog *att = dynamic_cast(element); + assert(att); + AttStaffDefLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLines(att->GetLines()); + } + if (element->HasAttClass(ATT_STAFFGROUPINGSYM)) { + const AttStaffGroupingSym *att = dynamic_cast(element); + assert(att); + AttStaffGroupingSym *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSymbol(att->GetSymbol()); + } + if (element->HasAttClass(ATT_STAFFIDENT)) { + const AttStaffIdent *att = dynamic_cast(element); + assert(att); + AttStaffIdent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStaff(att->GetStaff()); + } + if (element->HasAttClass(ATT_STAFFITEMS)) { + const AttStaffItems *att = dynamic_cast(element); + assert(att); + AttStaffItems *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAboveorder(att->GetAboveorder()); + attTarget->SetBeloworder(att->GetBeloworder()); + attTarget->SetBetweenorder(att->GetBetweenorder()); + } + if (element->HasAttClass(ATT_STAFFLOC)) { + const AttStaffLoc *att = dynamic_cast(element); + assert(att); + AttStaffLoc *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLoc(att->GetLoc()); + } + if (element->HasAttClass(ATT_STAFFLOCPITCHED)) { + const AttStaffLocPitched *att = dynamic_cast(element); + assert(att); + AttStaffLocPitched *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPloc(att->GetPloc()); + attTarget->SetOloc(att->GetOloc()); + } + if (element->HasAttClass(ATT_STARTENDID)) { + const AttStartEndId *att = dynamic_cast(element); + assert(att); + AttStartEndId *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetEndid(att->GetEndid()); + } + if (element->HasAttClass(ATT_STARTID)) { + const AttStartId *att = dynamic_cast(element); + assert(att); + AttStartId *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStartid(att->GetStartid()); + } + if (element->HasAttClass(ATT_STEMS)) { + const AttStems *att = dynamic_cast(element); + assert(att); + AttStems *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStemDir(att->GetStemDir()); + attTarget->SetStemLen(att->GetStemLen()); + attTarget->SetStemMod(att->GetStemMod()); + attTarget->SetStemPos(att->GetStemPos()); + attTarget->SetStemSameas(att->GetStemSameas()); + attTarget->SetStemVisible(att->GetStemVisible()); + attTarget->SetStemX(att->GetStemX()); + attTarget->SetStemY(att->GetStemY()); + } + if (element->HasAttClass(ATT_SYLLOG)) { + const AttSylLog *att = dynamic_cast(element); + assert(att); + AttSylLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCon(att->GetCon()); + attTarget->SetWordpos(att->GetWordpos()); + } + if (element->HasAttClass(ATT_SYLTEXT)) { + const AttSylText *att = dynamic_cast(element); + assert(att); + AttSylText *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSyl(att->GetSyl()); + } + if (element->HasAttClass(ATT_SYSTEMS)) { + const AttSystems *att = dynamic_cast(element); + assert(att); + AttSystems *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSystemLeftline(att->GetSystemLeftline()); + attTarget->SetSystemLeftmar(att->GetSystemLeftmar()); + attTarget->SetSystemRightmar(att->GetSystemRightmar()); + attTarget->SetSystemTopmar(att->GetSystemTopmar()); + } + if (element->HasAttClass(ATT_TARGETEVAL)) { + const AttTargetEval *att = dynamic_cast(element); + assert(att); + AttTargetEval *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetEvaluate(att->GetEvaluate()); + } + if (element->HasAttClass(ATT_TEMPOLOG)) { + const AttTempoLog *att = dynamic_cast(element); + assert(att); + AttTempoLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_TEXTRENDITION)) { + const AttTextRendition *att = dynamic_cast(element); + assert(att); + AttTextRendition *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAltrend(att->GetAltrend()); + attTarget->SetRend(att->GetRend()); + } + if (element->HasAttClass(ATT_TEXTSTYLE)) { + const AttTextStyle *att = dynamic_cast(element); + assert(att); + AttTextStyle *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTextFam(att->GetTextFam()); + attTarget->SetTextName(att->GetTextName()); + attTarget->SetTextSize(att->GetTextSize()); + attTarget->SetTextStyle(att->GetTextStyle()); + attTarget->SetTextWeight(att->GetTextWeight()); + } + if (element->HasAttClass(ATT_TIEPRESENT)) { + const AttTiePresent *att = dynamic_cast(element); + assert(att); + AttTiePresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTie(att->GetTie()); + } + if (element->HasAttClass(ATT_TIMESTAMPLOG)) { + const AttTimestampLog *att = dynamic_cast(element); + assert(att); + AttTimestampLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTstamp(att->GetTstamp()); + } + if (element->HasAttClass(ATT_TIMESTAMP2LOG)) { + const AttTimestamp2Log *att = dynamic_cast(element); + assert(att); + AttTimestamp2Log *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTstamp2(att->GetTstamp2()); + } + if (element->HasAttClass(ATT_TRANSPOSITION)) { + const AttTransposition *att = dynamic_cast(element); + assert(att); + AttTransposition *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTransDiat(att->GetTransDiat()); + attTarget->SetTransSemi(att->GetTransSemi()); + } + if (element->HasAttClass(ATT_TUNING)) { + const AttTuning *att = dynamic_cast(element); + assert(att); + AttTuning *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTuneHz(att->GetTuneHz()); + attTarget->SetTunePname(att->GetTunePname()); + attTarget->SetTuneTemper(att->GetTuneTemper()); + } + if (element->HasAttClass(ATT_TUPLETPRESENT)) { + const AttTupletPresent *att = dynamic_cast(element); + assert(att); + AttTupletPresent *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTuplet(att->GetTuplet()); + } + if (element->HasAttClass(ATT_TYPED)) { + const AttTyped *att = dynamic_cast(element); + assert(att); + AttTyped *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetType(att->GetType()); + } + if (element->HasAttClass(ATT_TYPOGRAPHY)) { + const AttTypography *att = dynamic_cast(element); + assert(att); + AttTypography *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFontfam(att->GetFontfam()); + attTarget->SetFontname(att->GetFontname()); + attTarget->SetFontsize(att->GetFontsize()); + attTarget->SetFontstyle(att->GetFontstyle()); + attTarget->SetFontweight(att->GetFontweight()); + attTarget->SetLetterspacing(att->GetLetterspacing()); + attTarget->SetLineheight(att->GetLineheight()); + } + if (element->HasAttClass(ATT_VERTICALALIGN)) { + const AttVerticalAlign *att = dynamic_cast(element); + assert(att); + AttVerticalAlign *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetValign(att->GetValign()); + } + if (element->HasAttClass(ATT_VERTICALGROUP)) { + const AttVerticalGroup *att = dynamic_cast(element); + assert(att); + AttVerticalGroup *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVgrp(att->GetVgrp()); + } + if (element->HasAttClass(ATT_VISIBILITY)) { + const AttVisibility *att = dynamic_cast(element); + assert(att); + AttVisibility *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVisible(att->GetVisible()); + } + if (element->HasAttClass(ATT_VISUALOFFSETHO)) { + const AttVisualOffsetHo *att = dynamic_cast(element); + assert(att); + AttVisualOffsetHo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetHo(att->GetHo()); + } + if (element->HasAttClass(ATT_VISUALOFFSETTO)) { + const AttVisualOffsetTo *att = dynamic_cast(element); + assert(att); + AttVisualOffsetTo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetTo(att->GetTo()); + } + if (element->HasAttClass(ATT_VISUALOFFSETVO)) { + const AttVisualOffsetVo *att = dynamic_cast(element); + assert(att); + AttVisualOffsetVo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVo(att->GetVo()); + } + if (element->HasAttClass(ATT_VISUALOFFSET2HO)) { + const AttVisualOffset2Ho *att = dynamic_cast(element); + assert(att); + AttVisualOffset2Ho *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStartho(att->GetStartho()); + attTarget->SetEndho(att->GetEndho()); + } + if (element->HasAttClass(ATT_VISUALOFFSET2TO)) { + const AttVisualOffset2To *att = dynamic_cast(element); + assert(att); + AttVisualOffset2To *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStartto(att->GetStartto()); + attTarget->SetEndto(att->GetEndto()); + } + if (element->HasAttClass(ATT_VISUALOFFSET2VO)) { + const AttVisualOffset2Vo *att = dynamic_cast(element); + assert(att); + AttVisualOffset2Vo *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetStartvo(att->GetStartvo()); + attTarget->SetEndvo(att->GetEndvo()); + } + if (element->HasAttClass(ATT_VOLTAGROUPINGSYM)) { + const AttVoltaGroupingSym *att = dynamic_cast(element); + assert(att); + AttVoltaGroupingSym *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVoltasym(att->GetVoltasym()); + } + if (element->HasAttClass(ATT_WHITESPACE)) { + const AttWhitespace *att = dynamic_cast(element); + assert(att); + AttWhitespace *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSpace(att->GetSpace()); + } + if (element->HasAttClass(ATT_WIDTH)) { + const AttWidth *att = dynamic_cast(element); + assert(att); + AttWidth *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetWidth(att->GetWidth()); + } + if (element->HasAttClass(ATT_XY)) { + const AttXy *att = dynamic_cast(element); + assert(att); + AttXy *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetX(att->GetX()); + attTarget->SetY(att->GetY()); + } + if (element->HasAttClass(ATT_XY2)) { + const AttXy2 *att = dynamic_cast(element); + assert(att); + AttXy2 *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetX2(att->GetX2()); + attTarget->SetY2(att->GetY2()); + } +} + +} // namespace vrv + +#include "atts_usersymbols.h" + +namespace vrv { + +//---------------------------------------------------------------------------- +// Usersymbols +//---------------------------------------------------------------------------- + +bool AttModule::SetUsersymbols(Object *element, const std::string &attrType, const std::string &attrValue) +{ + if (element->HasAttClass(ATT_ALTSYM)) { + AttAltSym *att = dynamic_cast(element); + assert(att); + if (attrType == "altsym") { + att->SetAltsym(att->StrToStr(attrValue)); + return true; + } + } + if (element->HasAttClass(ATT_ANCHOREDTEXTLOG)) { + AttAnchoredTextLog *att = dynamic_cast(element); + assert(att); + if (attrType == "func") { + att->SetFunc(att->StrToStr(attrValue)); + return true; + } + } + if (element->HasAttClass(ATT_CURVELOG)) { + AttCurveLog *att = dynamic_cast(element); + assert(att); + if (attrType == "func") { + att->SetFunc(att->StrToStr(attrValue)); + return true; + } + } + if (element->HasAttClass(ATT_LINELOG)) { + AttLineLog *att = dynamic_cast(element); + assert(att); + if (attrType == "func") { + att->SetFunc(att->StrToStr(attrValue)); + return true; + } + } + + return false; +} + +void AttModule::GetUsersymbols(const Object *element, ArrayOfStrAttr *attributes) +{ + if (element->HasAttClass(ATT_ALTSYM)) { + const AttAltSym *att = dynamic_cast(element); + assert(att); + if (att->HasAltsym()) { + attributes->push_back({ "altsym", att->StrToStr(att->GetAltsym()) }); + } + } + if (element->HasAttClass(ATT_ANCHOREDTEXTLOG)) { + const AttAnchoredTextLog *att = dynamic_cast(element); + assert(att); + if (att->HasFunc()) { attributes->push_back({ "func", att->StrToStr(att->GetFunc()) }); } } @@ -5337,6 +7264,38 @@ void AttModule::GetUsersymbols(const Object *element, ArrayOfStrAttr *attributes } } +void AttModule::CopyUsersymbols(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_ALTSYM)) { + const AttAltSym *att = dynamic_cast(element); + assert(att); + AttAltSym *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetAltsym(att->GetAltsym()); + } + if (element->HasAttClass(ATT_ANCHOREDTEXTLOG)) { + const AttAnchoredTextLog *att = dynamic_cast(element); + assert(att); + AttAnchoredTextLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_CURVELOG)) { + const AttCurveLog *att = dynamic_cast(element); + assert(att); + AttCurveLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } + if (element->HasAttClass(ATT_LINELOG)) { + const AttLineLog *att = dynamic_cast(element); + assert(att); + AttLineLog *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFunc(att->GetFunc()); + } +} + } // namespace vrv #include "atts_visual.h" @@ -6271,4 +8230,328 @@ void AttModule::GetVisual(const Object *element, ArrayOfStrAttr *attributes) } } +void AttModule::CopyVisual(const Object *element, Object *target) +{ + if (element->HasAttClass(ATT_ANNOTVIS)) { + const AttAnnotVis *att = dynamic_cast(element); + assert(att); + AttAnnotVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_ARPEGVIS)) { + const AttArpegVis *att = dynamic_cast(element); + assert(att); + AttArpegVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetArrow(att->GetArrow()); + attTarget->SetArrowShape(att->GetArrowShape()); + attTarget->SetArrowSize(att->GetArrowSize()); + attTarget->SetArrowColor(att->GetArrowColor()); + attTarget->SetArrowFillcolor(att->GetArrowFillcolor()); + } + if (element->HasAttClass(ATT_BARLINEVIS)) { + const AttBarLineVis *att = dynamic_cast(element); + assert(att); + AttBarLineVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLen(att->GetLen()); + attTarget->SetMethod(att->GetMethod()); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_BEAMINGVIS)) { + const AttBeamingVis *att = dynamic_cast(element); + assert(att); + AttBeamingVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeamColor(att->GetBeamColor()); + attTarget->SetBeamRend(att->GetBeamRend()); + attTarget->SetBeamSlope(att->GetBeamSlope()); + } + if (element->HasAttClass(ATT_BEATRPTVIS)) { + const AttBeatRptVis *att = dynamic_cast(element); + assert(att); + AttBeatRptVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetSlash(att->GetSlash()); + } + if (element->HasAttClass(ATT_CHORDVIS)) { + const AttChordVis *att = dynamic_cast(element); + assert(att); + AttChordVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCluster(att->GetCluster()); + } + if (element->HasAttClass(ATT_CLEFFINGVIS)) { + const AttCleffingVis *att = dynamic_cast(element); + assert(att); + AttCleffingVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetClefColor(att->GetClefColor()); + attTarget->SetClefVisible(att->GetClefVisible()); + } + if (element->HasAttClass(ATT_CURVATUREDIRECTION)) { + const AttCurvatureDirection *att = dynamic_cast(element); + assert(att); + AttCurvatureDirection *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCurve(att->GetCurve()); + } + if (element->HasAttClass(ATT_EPISEMAVIS)) { + const AttEpisemaVis *att = dynamic_cast(element); + assert(att); + AttEpisemaVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_FTREMVIS)) { + const AttFTremVis *att = dynamic_cast(element); + assert(att); + AttFTremVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBeams(att->GetBeams()); + attTarget->SetBeamsFloat(att->GetBeamsFloat()); + attTarget->SetFloatGap(att->GetFloatGap()); + } + if (element->HasAttClass(ATT_FERMATAVIS)) { + const AttFermataVis *att = dynamic_cast(element); + assert(att); + AttFermataVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetShape(att->GetShape()); + } + if (element->HasAttClass(ATT_FINGGRPVIS)) { + const AttFingGrpVis *att = dynamic_cast(element); + assert(att); + AttFingGrpVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOrient(att->GetOrient()); + } + if (element->HasAttClass(ATT_GUITARGRIDVIS)) { + const AttGuitarGridVis *att = dynamic_cast(element); + assert(att); + AttGuitarGridVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetGridShow(att->GetGridShow()); + } + if (element->HasAttClass(ATT_HAIRPINVIS)) { + const AttHairpinVis *att = dynamic_cast(element); + assert(att); + AttHairpinVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetOpening(att->GetOpening()); + attTarget->SetClosed(att->GetClosed()); + attTarget->SetOpeningVertical(att->GetOpeningVertical()); + attTarget->SetAngleOptimize(att->GetAngleOptimize()); + } + if (element->HasAttClass(ATT_HARMVIS)) { + const AttHarmVis *att = dynamic_cast(element); + assert(att); + AttHarmVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetRendgrid(att->GetRendgrid()); + } + if (element->HasAttClass(ATT_HISPANTICKVIS)) { + const AttHispanTickVis *att = dynamic_cast(element); + assert(att); + AttHispanTickVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlace(att->GetPlace()); + attTarget->SetTilt(att->GetTilt()); + } + if (element->HasAttClass(ATT_KEYSIGVIS)) { + const AttKeySigVis *att = dynamic_cast(element); + assert(att); + AttKeySigVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCancelaccid(att->GetCancelaccid()); + } + if (element->HasAttClass(ATT_KEYSIGDEFAULTVIS)) { + const AttKeySigDefaultVis *att = dynamic_cast(element); + assert(att); + AttKeySigDefaultVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetKeysigCancelaccid(att->GetKeysigCancelaccid()); + attTarget->SetKeysigVisible(att->GetKeysigVisible()); + } + if (element->HasAttClass(ATT_LIGATUREVIS)) { + const AttLigatureVis *att = dynamic_cast(element); + assert(att); + AttLigatureVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_LINEVIS)) { + const AttLineVis *att = dynamic_cast(element); + assert(att); + AttLineVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + attTarget->SetWidth(att->GetWidth()); + attTarget->SetEndsym(att->GetEndsym()); + attTarget->SetEndsymSize(att->GetEndsymSize()); + attTarget->SetStartsym(att->GetStartsym()); + attTarget->SetStartsymSize(att->GetStartsymSize()); + } + if (element->HasAttClass(ATT_LIQUESCENTVIS)) { + const AttLiquescentVis *att = dynamic_cast(element); + assert(att); + AttLiquescentVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLooped(att->GetLooped()); + } + if (element->HasAttClass(ATT_MENSURVIS)) { + const AttMensurVis *att = dynamic_cast(element); + assert(att); + AttMensurVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDot(att->GetDot()); + attTarget->SetForm(att->GetForm()); + attTarget->SetOrient(att->GetOrient()); + attTarget->SetSign(att->GetSign()); + } + if (element->HasAttClass(ATT_MENSURALVIS)) { + const AttMensuralVis *att = dynamic_cast(element); + assert(att); + AttMensuralVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMensurColor(att->GetMensurColor()); + attTarget->SetMensurDot(att->GetMensurDot()); + attTarget->SetMensurForm(att->GetMensurForm()); + attTarget->SetMensurLoc(att->GetMensurLoc()); + attTarget->SetMensurOrient(att->GetMensurOrient()); + attTarget->SetMensurSign(att->GetMensurSign()); + attTarget->SetMensurSize(att->GetMensurSize()); + attTarget->SetMensurSlash(att->GetMensurSlash()); + } + if (element->HasAttClass(ATT_METERSIGVIS)) { + const AttMeterSigVis *att = dynamic_cast(element); + assert(att); + AttMeterSigVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_METERSIGDEFAULTVIS)) { + const AttMeterSigDefaultVis *att = dynamic_cast(element); + assert(att); + AttMeterSigDefaultVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetMeterForm(att->GetMeterForm()); + attTarget->SetMeterShowchange(att->GetMeterShowchange()); + attTarget->SetMeterVisible(att->GetMeterVisible()); + } + if (element->HasAttClass(ATT_MULTIRESTVIS)) { + const AttMultiRestVis *att = dynamic_cast(element); + assert(att); + AttMultiRestVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBlock(att->GetBlock()); + } + if (element->HasAttClass(ATT_PBVIS)) { + const AttPbVis *att = dynamic_cast(element); + assert(att); + AttPbVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetFolium(att->GetFolium()); + } + if (element->HasAttClass(ATT_PEDALVIS)) { + const AttPedalVis *att = dynamic_cast(element); + assert(att); + AttPedalVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_PLICAVIS)) { + const AttPlicaVis *att = dynamic_cast(element); + assert(att); + AttPlicaVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetDir(att->GetDir()); + attTarget->SetLen(att->GetLen()); + } + if (element->HasAttClass(ATT_QUILISMAVIS)) { + const AttQuilismaVis *att = dynamic_cast(element); + assert(att); + AttQuilismaVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetWaves(att->GetWaves()); + } + if (element->HasAttClass(ATT_SBVIS)) { + const AttSbVis *att = dynamic_cast(element); + assert(att); + AttSbVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetForm(att->GetForm()); + } + if (element->HasAttClass(ATT_SCOREDEFVIS)) { + const AttScoreDefVis *att = dynamic_cast(element); + assert(att); + AttScoreDefVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetVuHeight(att->GetVuHeight()); + } + if (element->HasAttClass(ATT_SECTIONVIS)) { + const AttSectionVis *att = dynamic_cast(element); + assert(att); + AttSectionVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetRestart(att->GetRestart()); + } + if (element->HasAttClass(ATT_SIGNIFLETVIS)) { + const AttSignifLetVis *att = dynamic_cast(element); + assert(att); + AttSignifLetVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPlace(att->GetPlace()); + } + if (element->HasAttClass(ATT_SPACEVIS)) { + const AttSpaceVis *att = dynamic_cast(element); + assert(att); + AttSpaceVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetCompressable(att->GetCompressable()); + } + if (element->HasAttClass(ATT_STAFFDEFVIS)) { + const AttStaffDefVis *att = dynamic_cast(element); + assert(att); + AttStaffDefVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetLayerscheme(att->GetLayerscheme()); + attTarget->SetLinesColor(att->GetLinesColor()); + attTarget->SetLinesVisible(att->GetLinesVisible()); + attTarget->SetSpacing(att->GetSpacing()); + } + if (element->HasAttClass(ATT_STAFFGRPVIS)) { + const AttStaffGrpVis *att = dynamic_cast(element); + assert(att); + AttStaffGrpVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBarThru(att->GetBarThru()); + } + if (element->HasAttClass(ATT_STEMVIS)) { + const AttStemVis *att = dynamic_cast(element); + assert(att); + AttStemVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetPos(att->GetPos()); + attTarget->SetLen(att->GetLen()); + attTarget->SetForm(att->GetForm()); + attTarget->SetDir(att->GetDir()); + attTarget->SetFlagPos(att->GetFlagPos()); + attTarget->SetFlagForm(att->GetFlagForm()); + } + if (element->HasAttClass(ATT_TUPLETVIS)) { + const AttTupletVis *att = dynamic_cast(element); + assert(att); + AttTupletVis *attTarget = dynamic_cast(target); + assert(attTarget); + attTarget->SetBracketPlace(att->GetBracketPlace()); + attTarget->SetBracketVisible(att->GetBracketVisible()); + attTarget->SetDurVisible(att->GetDurVisible()); + attTarget->SetNumFormat(att->GetNumFormat()); + } +} + } // namespace vrv diff --git a/libmei/dist/attmodule.h b/libmei/dist/attmodule.h index be5498562f8..38f03134d80 100644 --- a/libmei/dist/attmodule.h +++ b/libmei/dist/attmodule.h @@ -48,69 +48,91 @@ class AttModule { ///@{ static bool SetMei(Object *element, const std::string &attrType, const std::string &attrValue); static void GetMei(const Object *element, ArrayOfStrAttr *attributes); + static void CopyMei(const Object *element, Object *target); static bool SetAnalytical(Object *element, const std::string &attrType, const std::string &attrValue); static void GetAnalytical(const Object *element, ArrayOfStrAttr *attributes); + static void CopyAnalytical(const Object *element, Object *target); static bool SetCmn(Object *element, const std::string &attrType, const std::string &attrValue); static void GetCmn(const Object *element, ArrayOfStrAttr *attributes); + static void CopyCmn(const Object *element, Object *target); static bool SetCmnornaments(Object *element, const std::string &attrType, const std::string &attrValue); static void GetCmnornaments(const Object *element, ArrayOfStrAttr *attributes); + static void CopyCmnornaments(const Object *element, Object *target); static bool SetCritapp(Object *element, const std::string &attrType, const std::string &attrValue); static void GetCritapp(const Object *element, ArrayOfStrAttr *attributes); + static void CopyCritapp(const Object *element, Object *target); static bool SetEdittrans(Object *element, const std::string &attrType, const std::string &attrValue); static void GetEdittrans(const Object *element, ArrayOfStrAttr *attributes); + static void CopyEdittrans(const Object *element, Object *target); static bool SetExternalsymbols(Object *element, const std::string &attrType, const std::string &attrValue); static void GetExternalsymbols(const Object *element, ArrayOfStrAttr *attributes); + static void CopyExternalsymbols(const Object *element, Object *target); static bool SetFacsimile(Object *element, const std::string &attrType, const std::string &attrValue); static void GetFacsimile(const Object *element, ArrayOfStrAttr *attributes); + static void CopyFacsimile(const Object *element, Object *target); static bool SetFigtable(Object *element, const std::string &attrType, const std::string &attrValue); static void GetFigtable(const Object *element, ArrayOfStrAttr *attributes); + static void CopyFigtable(const Object *element, Object *target); static bool SetFingering(Object *element, const std::string &attrType, const std::string &attrValue); static void GetFingering(const Object *element, ArrayOfStrAttr *attributes); + static void CopyFingering(const Object *element, Object *target); static bool SetFrettab(Object *element, const std::string &attrType, const std::string &attrValue); static void GetFrettab(const Object *element, ArrayOfStrAttr *attributes); + static void CopyFrettab(const Object *element, Object *target); static bool SetGestural(Object *element, const std::string &attrType, const std::string &attrValue); static void GetGestural(const Object *element, ArrayOfStrAttr *attributes); + static void CopyGestural(const Object *element, Object *target); static bool SetHarmony(Object *element, const std::string &attrType, const std::string &attrValue); static void GetHarmony(const Object *element, ArrayOfStrAttr *attributes); + static void CopyHarmony(const Object *element, Object *target); static bool SetHeader(Object *element, const std::string &attrType, const std::string &attrValue); static void GetHeader(const Object *element, ArrayOfStrAttr *attributes); + static void CopyHeader(const Object *element, Object *target); static bool SetMensural(Object *element, const std::string &attrType, const std::string &attrValue); static void GetMensural(const Object *element, ArrayOfStrAttr *attributes); + static void CopyMensural(const Object *element, Object *target); static bool SetMidi(Object *element, const std::string &attrType, const std::string &attrValue); static void GetMidi(const Object *element, ArrayOfStrAttr *attributes); + static void CopyMidi(const Object *element, Object *target); static bool SetNeumes(Object *element, const std::string &attrType, const std::string &attrValue); static void GetNeumes(const Object *element, ArrayOfStrAttr *attributes); + static void CopyNeumes(const Object *element, Object *target); static bool SetPagebased(Object *element, const std::string &attrType, const std::string &attrValue); static void GetPagebased(const Object *element, ArrayOfStrAttr *attributes); + static void CopyPagebased(const Object *element, Object *target); static bool SetPerformance(Object *element, const std::string &attrType, const std::string &attrValue); static void GetPerformance(const Object *element, ArrayOfStrAttr *attributes); + static void CopyPerformance(const Object *element, Object *target); static bool SetShared(Object *element, const std::string &attrType, const std::string &attrValue); static void GetShared(const Object *element, ArrayOfStrAttr *attributes); + static void CopyShared(const Object *element, Object *target); static bool SetUsersymbols(Object *element, const std::string &attrType, const std::string &attrValue); static void GetUsersymbols(const Object *element, ArrayOfStrAttr *attributes); + static void CopyUsersymbols(const Object *element, Object *target); static bool SetVisual(Object *element, const std::string &attrType, const std::string &attrValue); static void GetVisual(const Object *element, ArrayOfStrAttr *attributes); + static void CopyVisual(const Object *element, Object *target); ///@} }; diff --git a/libmei/tools/cpp.py b/libmei/tools/cpp.py index 9f051488959..b5e49c00711 100644 --- a/libmei/tools/cpp.py +++ b/libmei/tools/cpp.py @@ -473,6 +473,7 @@ class AttModule {{ SETTERS_GETTERS_H = """ static bool Set{moduleNameCap}(Object *element, const std::string &attrType, const std::string &attrValue); static void Get{moduleNameCap}(const Object *element, ArrayOfStrAttr *attributes); + static void Copy{moduleNameCap}(const Object *element, Object *target); """ @@ -553,6 +554,31 @@ class AttModule {{ GETTERS_END_CPP = """}} +""" + +# +# These templates generate a module level static method for copying attributes of an unspecified Object +# + +COPYERS_START_CPP = """void AttModule::Copy{moduleNameCap}(const Object *element, Object *target) +{{ +""" + +COPYERS_GRP_START_CPP = """ if (element->HasAttClass({attId})) {{ + const Att{attGroupNameUpper} *att = dynamic_cast(element); + assert(att); + Att{attGroupNameUpper} *attTarget = dynamic_cast(target); + assert(attTarget); +""" + +COPYERS_GRP_CPP = """ attTarget->Set{attNameUpper}(att->Get{attNameUpper}()); +""" + +COPYERS_GRP_END_CPP = """ }} +""" + +COPYERS_END_CPP = """}} + }} // namespace {ns} """ @@ -1110,6 +1136,7 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): setters: list = [] getters: list = [] + copyers: list = [] for gp, atts in sorted(atgroup.items()): if not atts: @@ -1121,6 +1148,7 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): } setters.append(SETTERS_GRP_START_CPP.format_map(set_get_fmt)) getters.append(GETTERS_GRP_START_CPP.format_map(set_get_fmt)) + copyers.append(COPYERS_GRP_START_CPP.format_map(set_get_fmt)) for att in atts: if "|" in att: @@ -1142,9 +1170,11 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): } setters.append(SETTERS_GRP_CPP.format_map(attsubstr)) getters.append(GETTERS_GRP_CPP.format_map(attsubstr)) + copyers.append(COPYERS_GRP_CPP.format_map(attsubstr)) setters.append(SETTERS_GRP_END_CPP.format_map(attsubstr)) getters.append(GETTERS_GRP_END_CPP.format_map(attsubstr)) + copyers.append(COPYERS_GRP_END_CPP.format_map(attsubstr)) tplvars = { "license": LICENSE.format(authors=AUTHORS), @@ -1160,6 +1190,9 @@ def create_att_module(cpp_ns: str, schema, outdir: Path): impl_modules.append(GETTERS_START_CPP.format_map(tplvars)) impl_modules.append("".join(getters)) impl_modules.append(GETTERS_END_CPP.format_map(tplvars)) + impl_modules.append(COPYERS_START_CPP.format_map(tplvars)) + impl_modules.append("".join(copyers)) + impl_modules.append(COPYERS_END_CPP.format_map(tplvars)) with Path(outdir, "attmodule.h").open("w") as f_att_module_h: lg.debug("\tCreating attmodule.h") diff --git a/src/alignfunctor.cpp b/src/alignfunctor.cpp index f838825000b..e6a9fb5fea1 100644 --- a/src/alignfunctor.cpp +++ b/src/alignfunctor.cpp @@ -40,12 +40,19 @@ namespace vrv { AlignHorizontallyFunctor::AlignHorizontallyFunctor(Doc *doc) : DocFunctor(doc) { + static const std::map durationEq{ + { DURATION_EQ_brevis, DURATION_brevis }, // + { DURATION_EQ_semibrevis, DURATION_semibrevis }, // + { DURATION_EQ_minima, DURATION_minima }, // + }; + m_measureAligner = NULL; m_time = 0; m_notationType = NOTATIONTYPE_cmn; m_scoreDefRole = SCOREDEF_NONE; m_isFirstMeasure = false; m_hasMultipleLayer = false; + m_currentParams.equivalence = durationEq.at(m_doc->GetOptions()->m_durationEquivalence.GetValue()); } FunctorCode AlignHorizontallyFunctor::VisitLayer(Layer *layer) @@ -174,8 +181,12 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme return FUNCTOR_CONTINUE; } } + // A ligature gets a default alignment in order to allow mensural cast-off + else if (layerElement->Is(LIGATURE)) { + // Nothing to do + } // We do not align these (container). Any other? - else if (layerElement->Is({ BEAM, LIGATURE, FTREM, TUPLET })) { + else if (layerElement->Is({ BEAM, FTREM, TUPLET })) { Fraction duration = layerElement->GetSameAsContentAlignmentDuration(m_currentParams, true, m_notationType); m_time = m_time + duration; return FUNCTOR_CONTINUE; @@ -235,6 +246,7 @@ FunctorCode AlignHorizontallyFunctor::VisitLayerElement(LayerElement *layerEleme } } else if (layerElement->Is(PROPORT)) { + if (layerElement->GetType() == "cmme_tempo_change") return FUNCTOR_SIBLINGS; // replace the current proport const Proport *previous = (m_currentParams.proport) ? (m_currentParams.proport) : NULL; m_currentParams.proport = vrv_cast(layerElement); diff --git a/src/calcstemfunctor.cpp b/src/calcstemfunctor.cpp index df7a50f18c1..d0e5e18b152 100644 --- a/src/calcstemfunctor.cpp +++ b/src/calcstemfunctor.cpp @@ -444,11 +444,12 @@ FunctorCode CalcStemFunctor::VisitStem(Stem *stem) if (m_dur > DURATION_16) { assert(flag); Point stemEnd; + // Commented since this is crashing - needs investigating if (stem->GetDrawingStemDir() == STEMDIRECTION_up) { - stemEnd = flag->GetStemUpSE(m_doc, staffSize, drawingCueSize); + // stemEnd = flag->GetStemUpSE(m_doc, staffSize, drawingCueSize); } else { - stemEnd = flag->GetStemDownNW(m_doc, staffSize, drawingCueSize); + // stemEnd = flag->GetStemDownNW(m_doc, staffSize, drawingCueSize); } // Trick for shortening the stem with DURATION_8 flagHeight = stemEnd.y; diff --git a/src/convertfunctor.cpp b/src/convertfunctor.cpp index d80c5db720f..25d43cbab9e 100644 --- a/src/convertfunctor.cpp +++ b/src/convertfunctor.cpp @@ -9,11 +9,18 @@ //---------------------------------------------------------------------------- +#include + +//---------------------------------------------------------------------------- + +#include "bracketspan.h" +#include "dir.h" #include "div.h" #include "doc.h" #include "ending.h" #include "fermata.h" #include "layer.h" +#include "ligature.h" #include "mdiv.h" #include "mrest.h" #include "page.h" @@ -23,7 +30,9 @@ #include "staff.h" #include "syllable.h" #include "system.h" +#include "text.h" #include "tie.h" +#include "tuplet.h" #include "vrv.h" //---------------------------------------------------------------------------- @@ -160,173 +169,54 @@ FunctorCode ConvertToPageBasedFunctor::VisitSystemElement(SystemElement *systemE // ConvertToCastOffMensuralFunctor //---------------------------------------------------------------------------- -ConvertToCastOffMensuralFunctor::ConvertToCastOffMensuralFunctor( - Doc *doc, System *targetSystem, const IntTree *layerTree) - : DocFunctor(doc) +ConvertToCastOffMensuralFunctor::ConvertToCastOffMensuralFunctor(Doc *doc, System *targetSystem) : DocFunctor(doc) { + m_contentStaff = NULL; m_contentLayer = NULL; m_targetSystem = targetSystem; - m_targetSubSystem = NULL; - m_targetMeasure = NULL; m_targetStaff = NULL; m_targetLayer = NULL; - m_segmentIdx = 0; - m_segmentTotal = 0; - m_layerTree = layerTree; -} - -FunctorCode ConvertToCastOffMensuralFunctor::VisitBarLine(BarLine *barLine) -{ - assert(barLine->GetAlignment()); - assert(m_targetSubSystem); - assert(m_targetLayer); - - // If this is the last barline of the layer, we will just move it and do not create a new segment - bool isLast = (m_contentLayer->GetLast() == barLine); - Object *next = m_contentLayer->GetNext(barLine); - bool nextIsBarline = (next && next->Is(BARLINE)); - - // See if we create proper measures and what to do with the barLine - MeasureType convertToMeasured = UNMEASURED; - if (m_doc->GetOptions()->m_mensuralToMeasure.GetValue()) { - convertToMeasured = MEASURED; - } - - if (convertToMeasured == MEASURED) { - // barLine object will be deleted - m_targetMeasure->SetRight(barLine->GetForm()); - } - else { - barLine->MoveItselfTo(m_targetLayer); - } - - // Now we can return if this is the end barLine - if (isLast || nextIsBarline) return FUNCTOR_SIBLINGS; - - for (int staffN : m_staffNs) { - // The barline is missing in at least one of the staves - do not break here - if (!barLine->GetAlignment()->HasAlignmentReference(staffN)) { - // LogDebug("BarLine not on all staves %d %s", m_targetStaff->GetN(), barLine->GetClassName().c_str()); - return FUNCTOR_SIBLINGS; - } - } - - // Make a segment break - // First case: add a new measure segment (e.g., first pass) - if (m_targetSubSystem->GetChildCount() <= m_segmentIdx) { - m_targetMeasure = new Measure(convertToMeasured); - if (convertToMeasured == MEASURED) { - m_targetMeasure->SetN(StringFormat("%d", m_segmentTotal + 1 + m_segmentIdx)); - } - m_targetSubSystem->AddChild(m_targetMeasure); - // Add a staff with same attributes as in the previous segment - m_targetStaff = new Staff(*m_targetStaff); - m_targetStaff->ClearChildren(); - m_targetStaff->CloneReset(); - m_targetMeasure->AddChild(m_targetStaff); - // Add a layer also with the same attributes as in the previous segment - m_targetLayer = new Layer(*m_targetLayer); - m_targetLayer->ClearChildren(); - m_targetLayer->CloneReset(); - m_targetStaff->AddChild(m_targetLayer); - } - // Second case: retrieve the appropriate segment - else { - m_targetMeasure = dynamic_cast(m_targetSubSystem->GetChild(m_segmentIdx)); - // It must be there - assert(m_targetMeasure); - - // Look if we already have the staff (e.g., with more than one layer) - AttNIntegerComparison comparisonStaffN(STAFF, m_targetStaff->GetN()); - Staff *staff = vrv_cast(m_targetMeasure->FindDescendantByComparison(&comparisonStaffN)); - if (!staff) { - staff = new Staff(*m_targetStaff); - staff->ClearChildren(); - staff->CloneReset(); - m_targetMeasure->AddChild(staff); - } - m_targetStaff = staff; - - // Add a new layer as the new target - m_targetLayer = new Layer(*m_targetLayer); - m_targetLayer->ClearChildren(); - m_targetLayer->CloneReset(); - m_targetStaff->AddChild(m_targetLayer); - } - ++m_segmentIdx; - - return FUNCTOR_SIBLINGS; } FunctorCode ConvertToCastOffMensuralFunctor::VisitLayer(Layer *layer) { m_contentLayer = layer; - - m_targetLayer = new Layer(*layer); - m_targetLayer->ClearChildren(); - m_targetLayer->CloneReset(); - // Keep the xml:id of the layer in the first segment - m_targetLayer->SwapID(layer); - assert(m_targetStaff); - m_targetStaff->AddChild(m_targetLayer); + m_targetLayer = NULL; return FUNCTOR_CONTINUE; } FunctorCode ConvertToCastOffMensuralFunctor::VisitMeasure(Measure *measure) { - // We are processing by staff/layer from the call below - we obviously do not want to loop... - if (m_targetMeasure) { - return FUNCTOR_CONTINUE; - } - - MeasureType convertToMeasured = UNMEASURED; - if (m_doc->GetOptions()->m_mensuralToMeasure.GetValue()) { - convertToMeasured = MEASURED; - } - - assert(m_targetSystem); - assert(m_layerTree); - - // Create a temporary subsystem for receiving the measure segments - System targetSubSystem; - m_targetSubSystem = &targetSubSystem; - - // Create the first measure segment - problem: we are dropping the section element - we should create a score-based - // MEI file instead - Measure *targetMeasure = new Measure(convertToMeasured); - if (convertToMeasured == MEASURED) { - targetMeasure->SetN(StringFormat("%d", m_segmentTotal + 1)); - } - m_targetSubSystem->AddChild(targetMeasure); - - Filters filters; - Filters *previousFilters = this->SetFilters(&filters); - - // Now we can process by layer and move their content to (measure) segments - for (const auto &staves : m_layerTree->child) { - for (const auto &layers : staves.second.child) { - // Create ad comparison object for each type / @n - AttNIntegerComparison matchStaff(STAFF, staves.first); - AttNIntegerComparison matchLayer(LAYER, layers.first); - filters = { &matchStaff, &matchLayer }; - - m_segmentIdx = 1; - m_targetMeasure = targetMeasure; - - measure->Process(*this); + m_segments.clear(); + m_breakPoints.clear(); + + const int nbLayers = measure->GetDescendantCount(LAYER); + bool isFirst = true; + + // Create at least one segment to copy stuff to + Measure *segment = new Measure(UNMEASURED); + m_targetSystem->AddChild(segment); + m_segments.push_back(segment); + + for (const Object *child : measure->m_measureAligner.GetChildren()) { + const Alignment *alignment = vrv_cast(child); + assert(alignment); + // We use the alignments with an element at all layer as a breakpoint + if (!this->IsValidBreakPoint(alignment, nbLayers)) continue; + // Do not break at the first one + if (isFirst) { + isFirst = false; + continue; } + Measure *segment = new Measure(UNMEASURED); + m_targetSystem->AddChild(segment); + m_segments.push_back(segment); + m_breakPoints.push_back(alignment); } - this->SetFilters(previousFilters); - - m_targetMeasure = NULL; - m_targetSubSystem = NULL; - m_segmentTotal = targetSubSystem.GetChildCount(); - // Copy the measure segments to the final target segment - m_targetSystem->MoveChildrenFrom(&targetSubSystem); - - return FUNCTOR_SIBLINGS; + // Now we are ready to process staves/layers and to move content to m_segments + return FUNCTOR_CONTINUE; } FunctorCode ConvertToCastOffMensuralFunctor::VisitObject(Object *object) @@ -334,6 +224,7 @@ FunctorCode ConvertToCastOffMensuralFunctor::VisitObject(Object *object) assert(object->GetParent()); // We want to move only the children of the layer of any type (notes, editorial elements, etc) if (object->GetParent()->Is(LAYER)) { + this->InitSegment(object); assert(m_targetLayer); object->MoveItselfTo(m_targetLayer); // Do not process children because we move the full sub-tree @@ -353,82 +244,84 @@ FunctorCode ConvertToCastOffMensuralFunctor::VisitScoreDef(ScoreDef *scoreDef) FunctorCode ConvertToCastOffMensuralFunctor::VisitStaff(Staff *staff) { - m_targetStaff = new Staff(*staff); - m_targetStaff->ClearChildren(); - m_targetStaff->CloneReset(); - // Keep the xml:id of the staff in the first staff segment - m_targetStaff->SwapID(staff); - assert(m_targetMeasure); - m_targetMeasure->AddChild(m_targetStaff); + m_currentSegment = m_segments.begin(); + m_currentBreakPoint = m_breakPoints.begin(); + + m_contentStaff = staff; + m_targetStaff = NULL; return FUNCTOR_CONTINUE; } -FunctorCode ConvertToCastOffMensuralFunctor::VisitSyllable(Syllable *syllable) +FunctorCode ConvertToCastOffMensuralFunctor::VisitSystemElement(SystemElement *systemElement) { - assert(m_targetSubSystem); - assert(m_targetLayer); - assert(syllable->GetParent()); + assert(m_targetSystem); + systemElement->MoveItselfTo(m_targetSystem); - // If this is the first syllable of the layer, we do not create a new segment - if (m_contentLayer->GetFirst() == syllable) { - syllable->MoveItselfTo(m_targetLayer); - return FUNCTOR_SIBLINGS; - } - // If the syllable is in editorial markup, do not create a new segment - if (!syllable->GetParent()->Is(LAYER)) return FUNCTOR_SIBLINGS; - - // Make a segment break - // First case: add a new measure segment (e.g., first pass) - if (m_targetSubSystem->GetChildCount() <= m_segmentIdx) { - m_targetMeasure = new Measure(UNMEASURED); - m_targetSubSystem->AddChild(m_targetMeasure); - // Add a staff with same attributes as in the previous segment - m_targetStaff = new Staff(*m_targetStaff); - m_targetStaff->ClearChildren(); - m_targetStaff->CloneReset(); - m_targetMeasure->AddChild(m_targetStaff); - // Add a layer also with the same attributes as in the previous segment - m_targetLayer = new Layer(*m_targetLayer); - m_targetLayer->ClearChildren(); - m_targetLayer->CloneReset(); - m_targetStaff->AddChild(m_targetLayer); - } - // Second case: retrieve the appropriate segment - else { - m_targetMeasure = dynamic_cast(m_targetSubSystem->GetChild(m_segmentIdx)); - // It must be there - assert(m_targetMeasure); - - // Look if we already have the staff (e.g., with more than one layer) - AttNIntegerComparison comparisonStaffN(STAFF, m_targetStaff->GetN()); - Staff *staff = vrv_cast(m_targetMeasure->FindDescendantByComparison(&comparisonStaffN)); - if (!staff) { - staff = new Staff(*m_targetStaff); - staff->ClearChildren(); - staff->CloneReset(); - m_targetMeasure->AddChild(staff); - } - m_targetStaff = staff; + return FUNCTOR_CONTINUE; +} - // Add a new layer as the new target - m_targetLayer = new Layer(*m_targetLayer); - m_targetLayer->ClearChildren(); - m_targetLayer->CloneReset(); - m_targetStaff->AddChild(m_targetLayer); +bool ConvertToCastOffMensuralFunctor::IsValidBreakPoint(const Alignment *alignment, const int nbLayers) +{ + if (alignment->GetType() != ALIGNMENT_DEFAULT) return false; + + // Not all layers have an alignment and we cannot break here + if (alignment->GetChildCount() != nbLayers) return false; + + const bool ligatureAsBracket = m_doc->GetOptions()->m_ligatureAsBracket.GetValue(); + + for (const Object *child : alignment->GetChildren()) { + for (const Object *refChild : child->GetChildren()) { + // Do not break within editorial markup + if (refChild->GetFirstAncestorInRange(EDITORIAL_ELEMENT, EDITORIAL_ELEMENT_max)) return false; + // Do not break within a ligature when rendered as bracket - (notes in it will have a different aligner + // execpt for the first one) + if (ligatureAsBracket && refChild->GetFirstAncestor(LIGATURE)) { + const Ligature *ligature = vrv_cast(refChild->GetFirstAncestor(LIGATURE)); + assert(ligature); + if (ligature->GetAlignment() != alignment) return false; + } + } + // When we have more than one neume in a syllable, every neume has its own alignment. + // Only the first one, which is shared with the syllable, is a valid break point + if (child->FindDescendantByType(NEUME) && !child->FindDescendantByType(SYLLABLE)) { + return false; + } } - syllable->MoveItselfTo(m_targetLayer); - ++m_segmentIdx; - return FUNCTOR_SIBLINGS; + return true; } -FunctorCode ConvertToCastOffMensuralFunctor::VisitSystemElement(SystemElement *systemElement) +void ConvertToCastOffMensuralFunctor::InitSegment(Object *object) { - assert(m_targetSystem); - systemElement->MoveItselfTo(m_targetSystem); + assert(m_contentStaff); + assert(m_contentLayer); - return FUNCTOR_CONTINUE; + LayerElement *element = NULL; + if (object->IsLayerElement()) element = vrv_cast(object); + + if (element && element->GetAlignment() && (element->GetAlignment() == *m_currentBreakPoint)) { + m_targetStaff = NULL; + m_targetLayer = NULL; + std::advance(m_currentBreakPoint, 1); + std::advance(m_currentSegment, 1); + } + + if (m_targetStaff && m_targetLayer) return; + + m_targetStaff = new Staff(); + m_contentStaff->CopyAttributesTo(m_targetStaff); + // Keep the xml:id of the staff in the first staff segment + m_targetStaff->SwapID(m_contentStaff); + assert(*m_currentSegment); + (*m_currentSegment)->AddChild(m_targetStaff); + + m_targetLayer = new Layer(); + m_contentLayer->CopyAttributesTo(m_targetLayer); + // Keep the xml:id of the layer in the first segment + m_targetLayer->SwapID(m_contentLayer); + assert(m_targetStaff); + m_targetStaff->AddChild(m_targetLayer); } //---------------------------------------------------------------------------- @@ -438,6 +331,7 @@ FunctorCode ConvertToCastOffMensuralFunctor::VisitSystemElement(SystemElement *s ConvertToUnCastOffMensuralFunctor::ConvertToUnCastOffMensuralFunctor() : Functor() { this->ResetContent(); + // We process layer by layer, keep a list of segments to be deleted the first time we go through m_trackSegmentsToDelete = true; } @@ -461,9 +355,11 @@ FunctorCode ConvertToUnCastOffMensuralFunctor::VisitLayer(Layer *layer) FunctorCode ConvertToUnCastOffMensuralFunctor::VisitMeasure(Measure *measure) { + // First measure of the section, move all content to it and keep it if (!m_contentMeasure) { m_contentMeasure = measure; } + // First pass, mark the measure to be deleted once finished else if (m_trackSegmentsToDelete) { m_segmentsToDelete.push_back(measure); } @@ -478,6 +374,740 @@ FunctorCode ConvertToUnCastOffMensuralFunctor::VisitSection(Section *section) return FUNCTOR_CONTINUE; } +//---------------------------------------------------------------------------- +// ConvertToCmnFunctor +//---------------------------------------------------------------------------- + +ConvertToCmnFunctor::ConvertToCmnFunctor(Doc *doc, System *targetSystem, Score *score) : DocFunctor(doc) +{ + m_targetSystem = targetSystem; + m_score = score; + m_currentStaff = NULL; + m_n = 0; +} + +FunctorCode ConvertToCmnFunctor::VisitChord(Chord *chord) +{ + // Mensural chords are aligned looking at the longest duration in the notes + Note *longestNote = NULL; + ListOfObjects notes = chord->FindAllDescendantsByType(NOTE); + for (Object *object : notes) { + Note *note = vrv_cast(object); + if (!longestNote || (note->GetScoreTimeDuration() > longestNote->GetScoreTimeDuration())) { + longestNote = note; + } + } + + // Use the longest note duration but create Chords + // That way the (longest) duration it move up from the note elements to the chord + // As it stands we ignore notes with shorter duration in the chords + // We also ignore coloration + this->ConvertDurationInterface(longestNote, CHORD); + + // This should not happen, just check it once for all + if (m_durationElements.empty()) return FUNCTOR_SIBLINGS; + + // Copy the `@pname` and `@oct` from the mensural note + for (Object *noteObject : notes) { + Object *tieStart = NULL; + const Accid *accid = vrv_cast(noteObject->FindDescendantByType(ACCID)); + bool isFirstNote = true; + for (Object *object : m_durationElements) { + Note *note = vrv_cast(noteObject); + Note *cmnNote = new Note(); + cmnNote->SetPname(note->GetPname()); + cmnNote->SetOct(note->GetOct()); + this->ConvertAccid(cmnNote, accid, isFirstNote); + object->AddChild(cmnNote); + + // Also create the ties for notes in the chord + if (tieStart) { + Object *measure = tieStart->GetFirstAncestor(MEASURE); + assert(measure); + Tie *tie = new Tie(); + tie->SetStartid("#" + tieStart->GetID()); + tie->SetEndid("#" + cmnNote->GetID()); + measure->AddChild(tie); + } + tieStart = cmnNote; + } + } + + // Move the verse + Object *verse = chord->FindDescendantByType(VERSE); + if (verse) { + verse->MoveItselfTo(m_durationElements.front()); + } + + return FUNCTOR_SIBLINGS; +} + +FunctorCode ConvertToCmnFunctor::VisitLayer(Layer *layer) +{ + m_currentParams.mensur = layer->GetCurrentMensur(); + m_currentParams.meterSig = layer->GetCurrentMeterSig(); + m_currentParams.proport = layer->GetCurrentProport(); + + m_ligature = NULL; + m_coloration = NULL; + m_proportTuplet = NULL; + + m_startid = ""; + + m_currentLayer = m_layers.begin(); + m_currentMeasure = m_measures.begin(); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitLayerElement(LayerElement *layerElement) +{ + if (layerElement->IsSystemElement()) return FUNCTOR_CONTINUE; + + if (layerElement->Is(CLEF)) { + if (!m_layerClef) m_layerClef = vrv_cast(layerElement); + } + else if (layerElement->Is(MENSUR)) { + // replace the current mensur + m_currentParams.mensur = vrv_cast(layerElement); + assert(m_currentParams.mensur); + this->ConvertMensur(m_currentParams.mensur); + } + else if (layerElement->Is(PROPORT)) { + if (layerElement->GetType() == "cmme_tempo_change") return FUNCTOR_SIBLINGS; + // replace the current proport + const Proport *previous = (m_currentParams.proport) ? (m_currentParams.proport) : NULL; + m_currentParams.proport = vrv_cast(layerElement); + assert(m_currentParams.proport); + if (previous) { + m_currentParams.proport->Cumulate(previous); + } + // Reset the tuplet since we expect the num / numbase to be different + m_proportTuplet = NULL; + } + else if (layerElement->Is({ ACCID, BARLINE, DOT })) { + // can be ignored + } + else { + LogDebug(layerElement->GetClassName().c_str()); + } + + return FUNCTOR_SIBLINGS; +} + +FunctorCode ConvertToCmnFunctor::VisitLigature(Ligature *ligature) +{ + assert(!m_ligature); + + m_ligature = new BracketSpan(); + m_ligature->SetFunc(bracketSpanLog_FUNC_ligature); + m_ligature->SetLform(LINEFORM_solid); + (*m_currentMeasure).m_measure->AddChild(m_ligature); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitLigatureEnd(Ligature *ligature) +{ + m_ligature = NULL; + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitMeasure(Measure *measure) +{ + m_measures.clear(); + + // measure->m_measureAligner.LogDebugTree(); + + const int nbLayers = measure->GetDescendantCount(LAYER); + + // First build an array of all mensuration signs that correspond to a time signature change + // Mensur sign should appear at all voices to be considered global + std::vector mensurs; + MensurInfo mensur; // Will be copied when added to the array, so we can re-use it. + + for (const Object *child : measure->m_measureAligner.GetChildren()) { + const Alignment *alignment = vrv_cast(child); + assert(alignment); + // We use the alignments with an element at all layer as a breakpoint + if (!this->IsGlobalMensur(alignment, nbLayers, mensur.m_mensur)) continue; + // + mensur.m_time = alignment->GetTime(); + mensurs.push_back(mensur); + } + // We need to have at least one and at least one at beginning (time 0) + if (mensurs.empty()) { + mensur.m_time = 0; + mensurs.push_back(mensur); + LogWarning("No mensur detected"); + } + else if (mensurs.front().m_time != 0) { + mensur.m_time = 0; + mensur.m_mensur.Reset(); + mensurs.insert(mensurs.begin(), mensur); + LogWarning("No mensur detected at the beginning"); + } + + // Now we can create measure object based on the mensur and the time of each MensurInfo section + // The total time of the piece + Fraction totalTime = measure->m_measureAligner.GetMaxTime(); + Fraction time(0); + // We know that we have at least one MensurInfo + std::vector::iterator mensurIter = mensurs.begin(); + Fraction measureDuration = this->CalcMeasureDuration(mensurs.front().m_mensur); + Mensur currentMensur = mensurs.front().m_mensur; + std::advance(mensurIter, 1); + // The next is either the next MensurInfo or the end of the piece + Fraction next = (mensurIter == mensurs.end()) ? totalTime : (*mensurIter).m_time; + + while (time < next) { + MeasureInfo measureInfo(time, measureDuration); + Measure *cmnMeasure = new Measure(); + cmnMeasure->SetN(std::to_string(++m_n)); + measureInfo.m_measure = cmnMeasure; + if ((time + measureInfo.m_duration) > next) { + measureInfo.m_duration = next - time; + cmnMeasure->SetMetcon(BOOLEAN_false); + } + m_targetSystem->AddChild(cmnMeasure); + m_measures.push_back(measureInfo); + + time = time + measureDuration; + if ((time >= next) && (mensurIter != mensurs.end())) { + time = next; + currentMensur = (*mensurIter).m_mensur; + Fraction duration = this->CalcMeasureDuration(currentMensur); + // The new measure does not have the same duration - add a scoreDef with a meterSig change + if (duration != measureDuration) { + ScoreDef *scoreDef = new ScoreDef(); + MeterSig *meterSig = new MeterSig(); + meterSig->IsAttribute(true); + meterSig->SetUnit(2); + Fraction count = duration / Fraction(DURATION_2); + meterSig->SetCount({ { count.GetNumerator() }, MeterCountSign::None }); + scoreDef->AddChild(meterSig); + m_targetSystem->AddChild(scoreDef); + } + measureDuration = duration; + std::advance(mensurIter, 1); + next = (mensurIter == mensurs.end()) ? totalTime : (*mensurIter).m_time; + } + } + // This will happen with empty CMME files + if (m_measures.empty()) { + LogWarning("The content of the measure seems empty, creating one for the process not to fail."); + MeasureInfo measureInfo(time, measureDuration); + Measure *cmnMeasure = new Measure(); + measureInfo.m_measure = cmnMeasure; + // Arbitrary duration + measureInfo.m_duration = 2; + cmnMeasure->SetMetcon(BOOLEAN_false); + m_targetSystem->AddChild(cmnMeasure); + m_measures.push_back(measureInfo); + } + + m_measures.back().m_measure->SetRight(BARRENDITION_dbl); + + // Now we are ready to process layers and to move content to m_measures + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitMeasureEnd(Measure *measure) +{ + // This is the first measure in the system - we need to update the scoreDef + if (m_score) { + for (Object *child : m_score->GetScoreDef()->GetList()) { + StaffDef *staffDef = vrv_cast(child); + assert(staffDef); + // Remove the notation type (CMN is normally the default) + staffDef->SetNotationtype(NOTATIONTYPE_NONE); + // Remove the mensur + Object *mensur = staffDef->GetFirst(MENSUR); + if (mensur) staffDef->DeleteChild(mensur); + // Add the meterSig + MeterSig *meterSig = new MeterSig(); + meterSig->SetUnit(2); + Fraction count = m_measures.front().m_duration / Fraction(DURATION_2); + meterSig->SetCount({ { count.GetNumerator() }, MeterCountSign::None }); + staffDef->AddChild(meterSig); + // Add or replace the clef + Object *clef = staffDef->GetFirst(CLEF); + // We must have m_clefs filled with clefs converted when processing layers + // However, if we have a clef in the staffDef, convert and use that one + if (clef) { + ConvertClef(m_clefs.back(), vrv_cast(clef)); + staffDef->DeleteChild(clef); + } + staffDef->AddChild(m_clefs.back()); + // Pop it from the list + m_clefs.pop_back(); + } + // Adjust the scoreDef only for the first measure, set it to NULL; + m_score = NULL; + } + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitNote(Note *note) +{ + this->ConvertDurationInterface(note, NOTE); + + // This should not happen, just check it once for all + if (m_durationElements.empty()) return FUNCTOR_SIBLINGS; + + const Accid *accid = vrv_cast(note->FindDescendantByType(ACCID)); + bool isFirstNote = true; + + // Copy the `@pname` and `@oct` from the mensural note + for (Object *object : m_durationElements) { + Note *cmnNote = vrv_cast(object); + assert(cmnNote); + cmnNote->SetPname(note->GetPname()); + cmnNote->SetOct(note->GetOct()); + if (note->HasColor()) cmnNote->SetColor(note->GetColor()); + this->ConvertAccid(cmnNote, accid, isFirstNote); + } + + // Check if we are in a ligature and set `@startid` and `@endid` as needed + if (m_ligature) { + // The ligature has just been created, add the first note as `@startid` + if (!m_ligature->HasStartid()) m_ligature->SetStartid("#" + m_durationElements.front()->GetID()); + // Set the last as `@endid` - will be updated until the ligature is closed + m_ligature->SetEndid("#" + m_durationElements.back()->GetID()); + } + + // Check if the note has coloration - create or add it to the coloration bracket as appropriate + if (note->HasColored()) { + if (!m_coloration) { + m_coloration = new BracketSpan(); + m_coloration->SetFunc(bracketSpanLog_FUNC_coloration); + Object *measure = m_durationElements.front()->GetFirstAncestor(MEASURE); + assert(measure); + measure->AddChild(m_coloration); + m_coloration->SetStartid("#" + m_durationElements.front()->GetID()); + } + // Set the last as `@endid` - will be updated if next note is also colored + m_coloration->SetEndid("#" + m_durationElements.back()->GetID()); + } + // End the coloration bracket if any + else if (m_coloration) { + m_coloration = NULL; + } + + // Move the verse + Object *verse = note->FindDescendantByType(VERSE); + if (verse) { + verse->MoveItselfTo(m_durationElements.front()); + } + + // Add the tie + Object *tieStart = m_durationElements.front(); + for (Object *tieEnd : m_durationElements | std::views::drop(1)) { + Object *measure = tieStart->GetFirstAncestor(MEASURE); + assert(measure); + Tie *tie = new Tie(); + tie->SetStartid("#" + tieStart->GetID()); + tie->SetEndid("#" + tieEnd->GetID()); + measure->AddChild(tie); + if (note->HasColor()) tie->SetColor(note->GetColor()); + tieStart = tieEnd; + } + + return FUNCTOR_SIBLINGS; +} + +FunctorCode ConvertToCmnFunctor::VisitRest(Rest *rest) +{ + this->ConvertDurationInterface(rest, REST); + + // Copy the `@color` from the mensural rest + for (Object *object : m_durationElements) { + Rest *cmnRest = vrv_cast(object); + assert(cmnRest); + if (rest->HasColor()) cmnRest->SetColor(rest->GetColor()); + } + + return FUNCTOR_SIBLINGS; +} + +FunctorCode ConvertToCmnFunctor::VisitScoreDef(ScoreDef *scoreDef) +{ + assert(m_targetSystem); + scoreDef->MoveItselfTo(m_targetSystem); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitStaff(Staff *staff) +{ + m_currentStaff = staff; + m_layerClef = NULL; + m_currentMeasure = m_measures.begin(); + + m_layers.clear(); + m_layers.reserve(m_measures.size()); + for (int i = 0; i < (int)m_measures.size(); ++i) { + Layer *layer = new Layer(); + m_layers.push_back(layer); + } + m_currentLayer = m_layers.begin(); + + for (int i = 0; i < (int)m_measures.size(); ++i) { + Staff *cmnStaff = new Staff(); + cmnStaff->SetN(staff->GetN()); + cmnStaff->AddChild(m_layers.at(i)); + m_measures.at(i).m_measure->AddChildBack(cmnStaff); + } + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitStaffEnd(Staff *staff) +{ + // Add mRest to empty layers + for (auto *layer : m_layers) { + if (layer->GetChildCount() == 0) { + layer->AddChild(new MRest()); + } + } + + Clef *clef = new Clef(); + ConvertClef(clef, m_layerClef); + // Add to the list of clef (one per staff) + m_clefs.push_front(clef); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitSystemElement(SystemElement *systemElement) +{ + assert(m_targetSystem); + systemElement->MoveItselfTo(m_targetSystem); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToCmnFunctor::VisitSystemEnd(System *system) +{ + assert(m_targetSystem); + Measure *last = vrv_cast(m_targetSystem->GetLast(MEASURE)); + assert(last); + last->SetRight(BARRENDITION_end); + + return FUNCTOR_CONTINUE; +} + +bool ConvertToCmnFunctor::IsGlobalMensur(const Alignment *alignment, const int nbLayers, Mensur &mensur) +{ + if (alignment->GetType() != ALIGNMENT_MENSUR) return false; + + // Not all layers have an alignment and we cannot break here + if (alignment->GetChildCount() != nbLayers) return false; + + for (const Object *child : alignment->GetChildren()) { + // Just pick the one of the first layer - quite arbitrary and we should check if they are all the same + // and decide what to do if they are not + const Mensur *mensurRef = vrv_cast(child->FindDescendantByType(MENSUR)); + if (mensurRef) { + mensur = *mensurRef; + return true; + } + } + + return true; +} + +Fraction ConvertToCmnFunctor::CalcMeasureDuration(const Mensur &mensur) +{ + Fraction duration(DURATION_2); + duration = duration * abs(mensur.GetProlatio()); + if (abs(mensur.GetProlatio()) == 2) duration = duration * abs(mensur.GetTempus()); + return duration; +} + +void ConvertToCmnFunctor::ConvertDurationInterface(DurationInterface *interface, ClassId classId) +{ + m_durationElements.clear(); + + data_DURATION noteDur = interface->GetActualDur(); + // Longa and maxima are converted into repeated breves since breve is the longest duration we can fit in a measure + if (noteDur < DURATION_breve) noteDur = DURATION_breve; + + this->SplitDurationInterface(classId, noteDur, interface->GetScoreTimeOnset() / SCORE_TIME_UNIT, + interface->GetScoreTimeDuration() / SCORE_TIME_UNIT); +} + +void ConvertToCmnFunctor::SplitDurationInterface( + ClassId classId, data_DURATION noteDur, Fraction time, Fraction duration) +{ + if (m_currentLayer == m_layers.end()) { + LogDebug("Extraneous content not processed"); + return; + } + + const Fraction measureEnd = (*m_currentMeasure).m_time + (*m_currentMeasure).m_duration; + const Fraction noteEnd = time + duration; + + std::list cmnDurations; + + Fraction processed = duration; + // If we go beyond the end of the measure, first process only what fits + if (noteEnd > measureEnd) { + processed = measureEnd - time; + } + + // The alignement duration features in the proportion - we can revert it back and make tuplets + Fraction durationWithoutProport = processed; + // Invert apply num and numbase + if (m_currentParams.proport->HasNum()) + durationWithoutProport = durationWithoutProport * m_currentParams.proport->GetCumulatedNum(); + if (m_currentParams.proport->HasNumbase()) + durationWithoutProport = durationWithoutProport / m_currentParams.proport->GetCumulatedNumbase(); + // We have a proportion applied, so the duration is different + bool hasProportion = (durationWithoutProport != processed); + // A flag indicating if the tuplet is a temporary one not corresponding to the proportion when notes are split + // across measures + bool nonProportTuplet = false; + + // Check if the value can be represented by value up to 16th (arbitrary) + // This is not always the case when notes are split across measures + // It is most likely to happen with proportions, but not only and it can also happen with coloration and notes + // having `@num` and `@numbase` One possible improvement would be to regroup sequences of notes with the same `@num` + // and `@numbase` under the same tuplet + if ((durationWithoutProport % Fraction(DURATION_16)) != 0) { + // If not, do not use the proportion tuplet an revert the duration back - however, that happens only when we + // have a proportion + m_proportTuplet = NULL; + durationWithoutProport = processed; + // If the remaining duration cannot be represented as well, last resort option with a specific tuplet + if ((durationWithoutProport % Fraction(DURATION_16)) != 0) { + m_proportTuplet = new Tuplet(); + // Use a note with half of the noteDur expected when in a proportion since the note is being split across + // measures - create a tuplet with according ratio + Fraction tupletRatio = (hasProportion) ? durationWithoutProport / Fraction(noteDur) * 2 + : durationWithoutProport / Fraction(noteDur); + LogWarning("The tuplet corresponding to proportion is not appropriate and must be changed to %s", + tupletRatio.ToString().c_str()); + m_proportTuplet->SetNum(tupletRatio.GetDenominator()); + m_proportTuplet->SetNumbase(tupletRatio.GetNumerator()); + m_proportTuplet->SetNumFormat(tupletVis_NUMFORMAT_ratio); + m_proportTuplet->SetBracketVisible(BOOLEAN_false); + // Same here : use a note with half of the noteDur expected when in a proportion since the note is being + // split across measures + durationWithoutProport = (hasProportion) ? Fraction(noteDur) / 2 : Fraction(noteDur); + (*m_currentLayer)->AddChild(m_proportTuplet); + // Mark the tuplet as temporary + nonProportTuplet = true; + } + } + // Create a new tuplet but only if we have not already created one for the previous note + else if (hasProportion && !m_proportTuplet) { + m_proportTuplet = new Tuplet(); + m_proportTuplet->SetNum(m_currentParams.proport->GetCumulatedNum()); + m_proportTuplet->SetNumbase(m_currentParams.proport->GetCumulatedNumbase()); + m_proportTuplet->SetNumFormat(tupletVis_NUMFORMAT_ratio); + m_proportTuplet->SetBracketVisible(BOOLEAN_false); + (*m_currentLayer)->AddChild(m_proportTuplet); + } + + // Split what we can fit within a measure into cmn duration (e.g., B => B. Sb. in tempus perfectum and prolatio + // major) Fill a list of CMN duration with dots (and num / numbase, unused for now) + this->SplitDurationIntoCmn(noteDur, durationWithoutProport, m_currentParams.mensur, cmnDurations); + + // Add them to the layer using the ObjectFactory (create notes or rests) + for (const CmnDuration &cmnDuration : cmnDurations) { + ObjectFactory *instance = ObjectFactory::GetInstance(); + Object *layerElement = instance->Create(classId); + assert(layerElement); + // Add it to the durationElement for post processing (e.g., setting note attributes or adding ties) + m_durationElements.push_back(layerElement); + DurationInterface *interface = layerElement->GetDurationInterface(); + assert(interface); + if (m_proportTuplet) { + // We already have note in the tuplet so we should show the bracket + if (m_proportTuplet->GetChildCount() > 0) m_proportTuplet->SetBracketVisible(BOOLEAN_true); + m_proportTuplet->AddChild(layerElement); + } + else { + (*m_currentLayer)->AddChild(layerElement); + } + interface->SetDur(cmnDuration.m_duration); + // Add a `@dots` only if not 0 + if (cmnDuration.m_dots != 0) interface->SetDots(cmnDuration.m_dots); + } + + // The tuplet is specific to the partial duration, reset it (e.g., at the beginning of a measure with a note split + // from the previous measure) + if (nonProportTuplet) m_proportTuplet = NULL; + + // Increase the tstamp by the value processed + m_startid = m_durationElements.front()->GetID(); + + // If we have reach the end of the measure, go to the next one + if (time + processed == measureEnd) { + ++m_currentMeasure; + ++m_currentLayer; + // End of the measure, close the tuplet + m_proportTuplet = NULL; + // Reset the tstamp + m_startid = ""; + } + // Also check if we have more to process for that note or rest - if yes, call it recursively + if (duration - processed != 0) { + this->SplitDurationInterface(classId, noteDur, time = (*m_currentMeasure).m_time, duration - processed); + } +} + +void ConvertToCmnFunctor::SplitDurationIntoCmn( + data_DURATION elementDur, Fraction duration, const Mensur *mensur, std::list &cmnDurations) +{ + const bool prolatioMajor = (abs(mensur->GetProlatio()) == 3); + const bool tempusPerfectum = (abs(mensur->GetTempus()) == 3); + const int semiBrevisDots = (prolatioMajor) ? 1 : 0; + const int brevisDots = (tempusPerfectum) ? 1 : 0; + + const Fraction semiBrevis = Fraction(1, 1) * abs(mensur->GetProlatio()) / 2; + const Fraction brevis = Fraction(1, 1) * abs(mensur->GetTempus()); + + // First see if we are expecting a breve and if the duration is long enough + if (elementDur == DURATION_breve) { + // First check if this in an imperfecta breve, which can be converted as a non dotted breve + if (tempusPerfectum && (duration == brevis * 2 / 3)) { + cmnDurations.push_back(CmnDuration(DURATION_breve, 0)); + duration = 0; + } + while (duration >= brevis) { + cmnDurations.push_back(CmnDuration(DURATION_breve, brevisDots)); + duration = duration - brevis; + // Check if we can use a dotted breve + if ((duration == brevis / 2) && (brevisDots == 0)) { + cmnDurations.back().m_dots = 1; + duration = 0; + } + if ((duration == brevis / 2) && (brevisDots == 0)) { + cmnDurations.back().m_dots = 1; + duration = 0; + } + } + // If we have not processed everything, go down to the level of semibrevis + if (duration != 0) elementDur = DURATION_1; + } + // See now if the duration is long enough for a semibrevis + if (elementDur == DURATION_1) { + // First check if this in an imperfecta semibreve, which can be converted as a non dotted semibreve + if (prolatioMajor && (duration == semiBrevis * 2 / 3)) { + cmnDurations.push_back(CmnDuration(DURATION_1, 0)); + duration = 0; + } + while (duration >= semiBrevis) { + cmnDurations.push_back(CmnDuration(DURATION_1, semiBrevisDots)); + duration = duration - semiBrevis; + // Check if we can use a dotted whole note + if ((duration == semiBrevis / 2) && (semiBrevisDots == 0)) { + cmnDurations.back().m_dots = 1; + duration = 0; + } + } + } + // Then process the rest until everything is processed + while (duration != 0) { + auto [durPart, remainder] = duration.ToDur(); + Fraction durPartDuration = duration - remainder; + cmnDurations.push_back(CmnDuration(durPart, 0)); + duration = remainder; + // Check if we can use a dotted value + if (duration == durPartDuration / 2) { + cmnDurations.back().m_dots = 1; + duration = 0; + } + } +} + +void ConvertToCmnFunctor::ConvertAccid(Note *cmnNote, const Accid *accid, bool &isFirstNote) +{ + if (!accid) return; + + Accid *cmnAccid = new Accid(); + if (isFirstNote) { + accid->CopyAttributesTo(cmnAccid); + isFirstNote = false; + } + else { + cmnAccid->SetAccidGes(Att::AccidentalWrittenToGestural(accid->GetAccid())); + } + cmnNote->AddChild(cmnAccid); +} + +void ConvertToCmnFunctor::ConvertClef(Clef *cmnClef, const Clef *clef) +{ + assert(cmnClef); + + if (!clef) { + // Default to C3 clef since this is the most neutral one ambitus-wise + cmnClef->SetLine(3); + cmnClef->SetShape(CLEFSHAPE_C); + } + else if (clef->GetShape() == CLEFSHAPE_F) { + cmnClef->SetShape(CLEFSHAPE_F); + cmnClef->SetLine(4); + } + else if (clef->GetShape() == CLEFSHAPE_G) { + cmnClef->SetShape(CLEFSHAPE_G); + cmnClef->SetLine(2); + } + // Assuming to be C + else { + if (clef->GetLine() > 4) { + cmnClef->SetShape(CLEFSHAPE_F); + cmnClef->SetLine(4); + } + else if (clef->GetLine() > 2) { + cmnClef->SetShape(CLEFSHAPE_G); + cmnClef->SetLine(2); + cmnClef->SetDis(OCTAVE_DIS_8); + cmnClef->SetDisPlace(STAFFREL_basic_below); + } + else { + cmnClef->SetShape(CLEFSHAPE_G); + cmnClef->SetLine(2); + } + } +} + +void ConvertToCmnFunctor::ConvertMensur(const Mensur *mensur) +{ + // We need as least a sign or a num + if (!mensur->HasSign() && !mensur->HasNum()) return; + + Dir *dir = new Dir(); + dir->SetStaff(m_currentStaff->AttNInteger::StrToXsdPositiveIntegerList(std::to_string(m_currentStaff->GetN()))); + if (m_startid.empty()) { + dir->SetTstamp(0.0); + } + else { + dir->SetStartid("#" + m_startid); + } + dir->SetType("mscore-staff-text"); + dir->SetPlace(STAFFREL_above); + Text *text = new Text(); + std::string str; + if (mensur->HasSign()) { + str += (mensur->GetSign() == MENSURATIONSIGN_C) ? "C" : "O"; + if (mensur->GetOrient() == ORIENTATION_reversed) str += "r"; + if (mensur->HasSlash()) str += "|"; + if (mensur->HasDot()) str += "."; + } + if (mensur->HasNum()) { + str += std::to_string(mensur->GetNum()); + if (mensur->HasNumbase()) str += "/" + std::to_string(mensur->GetNumbase()); + } + text->SetText(UTF8to32(str)); + dir->AddChild(text); + (*m_currentMeasure).m_measure->AddChild(dir); +} + //---------------------------------------------------------------------------- // ConvertMarkupAnalyticalFunctor //---------------------------------------------------------------------------- @@ -760,4 +1390,77 @@ FunctorCode ConvertMarkupScoreDefFunctor::VisitScoreDefElementEnd(ScoreDefElemen return FUNCTOR_CONTINUE; } +//---------------------------------------------------------------------------- +// ConvertToMensuralViewFunctor +//---------------------------------------------------------------------------- + +ConvertToMensuralViewFunctor::ConvertToMensuralViewFunctor(Doc *doc) : DocFunctor(doc) +{ + m_viewLayer = NULL; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitEditorialElement(EditorialElement *editorialElement) +{ + // We are not in a layer yet + if (!m_viewLayer) return FUNCTOR_CONTINUE; + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLayer(Layer *layer) +{ + assert(!m_viewLayer); + assert(m_stack.empty()); + + m_viewLayer = new Layer(); + layer->CopyAttributesTo(m_viewLayer); + m_stack.push_back(m_viewLayer); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLayerEnd(Layer *layer) +{ + layer->GetParent()->ReplaceChild(layer, m_viewLayer); + // This will delete all editorial markup and ligatures in the old layer + delete layer; + + // We should have only the m_layerView left + assert(m_stack.size() == 1); + m_viewLayer = NULL; + m_stack.clear(); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLayerElement(LayerElement *layerElement) +{ + // The stack top it either the new layer or the parent element within editorial markup + if (m_stack.back() != layerElement->GetParent()) { + layerElement->MoveItselfTo(m_stack.back()); + } + + m_stack.push_back(layerElement); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLayerElementEnd(LayerElement *layerElement) +{ + m_stack.pop_back(); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLigature(Ligature *ligature) +{ + // For now simply skip them - eventually we might want to add brackets + return FUNCTOR_CONTINUE; +} + +FunctorCode ConvertToMensuralViewFunctor::VisitLigatureEnd(Ligature *ligature) +{ + return FUNCTOR_CONTINUE; +} + } // namespace vrv diff --git a/src/doc.cpp b/src/doc.cpp index ba9fd5d10e5..5242122ad04 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -11,6 +11,7 @@ #include #include +#include //---------------------------------------------------------------------------- @@ -131,7 +132,7 @@ void Doc::Reset() m_dataPreparationDone = false; m_timemapTempo = 0.0; m_markup = MARKUP_DEFAULT; - m_isMensuralMusicOnly = false; + m_isMensuralMusicOnly = BOOLEAN_NONE; m_isNeumeLines = false; m_isCastOff = false; m_visibleScores.clear(); @@ -290,33 +291,14 @@ bool Doc::GenerateMeasureNumbers() return true; } -void Doc::GenerateMEIHeader(bool meiBasic) +void Doc::GenerateMEIHeader() { - // Try to preserve titles if we have an existing header - std::list titles; - pugi::xpath_node_set titlesNodeSet = m_header.select_nodes("//meiHead/fileDesc/titleStmt/title/text()"); - for (pugi::xpath_node titleXpathNode : titlesNodeSet) { - pugi::xml_node titleNode = titleXpathNode.node(); - if (!titleNode) continue; - titles.push_back(titleNode.text().as_string()); - } - m_header.remove_children(); pugi::xml_node meiHead = m_header.append_child("meiHead"); pugi::xml_node fileDesc = meiHead.append_child("fileDesc"); pugi::xml_node titleStmt = fileDesc.append_child("titleStmt"); - // Re-add preserved titles - if (titles.size() > 0) { - for (auto &title : titles) { - pugi::xml_node titleNode = titleStmt.append_child("title"); - pugi::xml_node textNode = titleNode.append_child(pugi::node_pcdata); - textNode.text() = title.c_str(); - } - } - // Add an empty title for validity - else { - titleStmt.append_child("title"); - } + titleStmt.append_child("title"); + pugi::xml_node pubStmt = fileDesc.append_child("pubStmt"); pugi::xml_node date = pubStmt.append_child("date"); @@ -327,20 +309,40 @@ void Doc::GenerateMEIHeader(bool meiBasic) now->tm_mday, now->tm_hour, now->tm_min, now->tm_sec); date.append_attribute("isodate") = dateStr.c_str(); - if (!meiBasic) { - // encodingDesc - pugi::xml_node encodingDesc = meiHead.append_child("encodingDesc"); - // appInfo/application/name - pugi::xml_node appInfo = encodingDesc.append_child("appInfo"); - pugi::xml_node application = appInfo.append_child("application"); - application.append_attribute("xml:id") = "verovio"; - application.append_attribute("version") = GetVersion().c_str(); - pugi::xml_node name = application.append_child("name"); - name.text().set(StringFormat("Verovio (%s)", GetVersion().c_str()).c_str()); - // projectDesc - pugi::xml_node projectDesc = encodingDesc.append_child("projectDesc"); - pugi::xml_node p1 = projectDesc.append_child("p"); - p1.text().set(StringFormat("MEI encoded with Verovio").c_str()); + // encodingDesc + pugi::xml_node encodingDesc = meiHead.append_child("encodingDesc"); + // appInfo/application/name + pugi::xml_node appInfo = encodingDesc.append_child("appInfo"); + pugi::xml_node application = appInfo.append_child("application"); + application.append_attribute("xml:id") = "verovio"; + application.append_attribute("version") = GetVersion().c_str(); + pugi::xml_node name = application.append_child("name"); + name.text().set(StringFormat("Verovio (%s)", GetVersion().c_str()).c_str()); + // projectDesc + pugi::xml_node projectDesc = encodingDesc.append_child("projectDesc"); + pugi::xml_node p1 = projectDesc.append_child("p"); + p1.text().set(StringFormat("MEI encoded with Verovio").c_str()); +} + +void Doc::ConvertHeaderToMEIBasic() +{ + pugi::xpath_node_set toRemove; + + // Keep only fileDesc + toRemove = m_header.select_nodes("//meiHead/*[not(self::fileDesc)]"); + // Remove each of the selected nodes + for (pugi::xpath_node node : toRemove) { + node.node().parent().remove_child(node.node()); + } + + // Keep only titleStmt, respStmt, composer, arranger and lyricist in fileDesc + pugi::xml_node titleStmt = m_header.select_node("//meiHead/fileDesc/titleStmt").node(); + // Remove each of the selected nodes + toRemove = titleStmt.select_nodes( + "./*[not(self::title or self::respStmt or self::composer or self::arranger or self::lyricist)]"); + // Remove each of the selected nodes + for (pugi::xpath_node node : toRemove) { + node.node().parent().remove_child(node.node()); } } @@ -384,7 +386,7 @@ void Doc::CalculateTimemap() this->Process(initMaxMeasureDuration); // Then calculate the onset and offset times (w.r.t. the measure) for every note - InitOnsetOffsetFunctor initOnsetOffset; + InitOnsetOffsetFunctor initOnsetOffset(this); this->Process(initOnsetOffset); // Adjust the duration of tied notes @@ -1282,7 +1284,7 @@ void Doc::ConvertToPageBasedDoc() void Doc::ConvertToCastOffMensuralDoc(bool castOff) { - if (!m_isMensuralMusicOnly) return; + if (!this->IsMensuralMusicOnly()) return; // Do not convert transcription files if (this->IsTranscription()) return; @@ -1290,13 +1292,8 @@ void Doc::ConvertToCastOffMensuralDoc(bool castOff) // Do not convert facs files if (this->IsFacs()) return; - // We are converting to measure music in a definite way - if (this->GetOptions()->m_mensuralToMeasure.GetValue()) { - m_isMensuralMusicOnly = false; - } - // Make sure the document is not cast-off - this->UnCastOffDoc(); + if (this->IsCastOff()) this->UnCastOffDoc(); this->ScoreDefSetCurrentDoc(); @@ -1311,7 +1308,9 @@ void Doc::ConvertToCastOffMensuralDoc(bool castOff) assert(system); if (castOff) { System *convertedSystem = new System(); - system->ConvertToCastOffMensuralSystem(this, convertedSystem); + ConvertToCastOffMensuralFunctor convertToCastOffMensural(this, convertedSystem); + // Convert the system and replace it + system->Process(convertToCastOffMensural); contentPage->ReplaceChild(system, convertedSystem); delete system; } @@ -1328,6 +1327,66 @@ void Doc::ConvertToCastOffMensuralDoc(bool castOff) this->ScoreDefSetCurrentDoc(true); } +void Doc::ConvertToCmnDoc() +{ + if (!this->IsMensuralMusicOnly()) return; + + // Do not convert transcription files + if (this->IsTranscription()) return; + + // Do not convert facs files + if (this->IsFacs()) return; + + m_isMensuralMusicOnly = BOOLEAN_false; + + // Temporarily change the equivalence option to minima + int previousEquivalence = m_options->m_durationEquivalence.GetValue(); + m_options->m_durationEquivalence.SetValue(DURATION_EQ_minima); + + // Make sure the document is not cast-off + if (this->IsCastOff()) this->UnCastOffDoc(); + + this->ScoreDefSetCurrentDoc(); + + this->CalculateTimemap(); + + Page *contentPage = this->SetDrawingPage(0); + assert(contentPage); + + contentPage->LayOutHorizontally(); + + ListOfObjects systems = contentPage->FindAllDescendantsByType(SYSTEM, false, 1); + ListOfObjects scores = contentPage->FindAllDescendantsByType(SCORE, false, 1); + assert(systems.size() == scores.size()); + + ListOfObjects::iterator systemsIt = systems.begin(); + ListOfObjects::iterator scoresIt = scores.begin(); + for (; systemsIt != systems.end(); ++systemsIt, ++scoresIt) { + System *system = vrv_cast(*systemsIt); + assert(system); + Score *score = vrv_cast(*scoresIt); + assert(score); + System *convertedSystem = new System(); + ConvertToCmnFunctor convertToCmn(this, convertedSystem, score); + // Convert the system and replace it + system->Process(convertToCmn); + contentPage->ReplaceChild(system, convertedSystem); + delete system; + } + + this->GenerateMeasureNumbers(); + + this->PrepareData(); + + // We need to reset the drawing page to NULL + // because idx will still be 0 but contentPage is dead! + this->ResetDataPage(); + this->ScoreDefSetCurrentDoc(true); + + // Reset the option + m_options->m_durationEquivalence.SetValue(previousEquivalence); +} + void Doc::ConvertMarkupDoc(bool permanent) { if (m_markup == MARKUP_DEFAULT) return; @@ -1389,6 +1448,25 @@ void Doc::ConvertMarkupDoc(bool permanent) } } +void Doc::ConvertToMensuralViewDoc() +{ + if (this->IsCastOff()) { + LogDebug("Document is cast off"); + return; + } + + ConvertToMensuralViewFunctor convertToMensuralView(this); + this->Process(convertToMensuralView); +} + +void Doc::ConvertMensuralToCmnDoc() +{ + if (this->IsCastOff()) { + LogDebug("Document is cast off"); + return; + } +} + void Doc::SyncFromFacsimileDoc() { PrepareFacsimileFunctor prepareFacsimile(this->GetFacsimile()); @@ -2153,6 +2231,14 @@ int Doc::GetAdjustedDrawingPageWidth() const return (contentWidth + m_drawingPageMarginLeft + m_drawingPageMarginRight) / DEFINITION_FACTOR; } +void Doc::SetMensuralMusicOnly(data_BOOLEAN isMensuralMusicOnly) +{ + // Already marked as non mensural only cannoy be set back + if (m_isMensuralMusicOnly != BOOLEAN_false) { + m_isMensuralMusicOnly = isMensuralMusicOnly; + } +} + //---------------------------------------------------------------------------- // Doc functors methods //---------------------------------------------------------------------------- diff --git a/src/durationinterface.cpp b/src/durationinterface.cpp index 00fa8867574..734ac5adf86 100644 --- a/src/durationinterface.cpp +++ b/src/durationinterface.cpp @@ -93,7 +93,7 @@ Fraction DurationInterface::GetInterfaceAlignmentDuration(int num, int numBase) } Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( - int num, int numBase, const Mensur *currentMensur) const + int num, int numBase, const Mensur *currentMensur, data_DURATION equivalence) const { data_DURATION noteDur = this->GetDurGes() != DURATION_NONE ? this->GetActualDurGes() : this->GetActualDur(); if (noteDur == DURATION_NONE) noteDur = DURATION_4; @@ -136,6 +136,24 @@ Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( } // Any other case (minor, perfecta in tempus perfectum, and imperfecta in tempus imperfectum) follows the // mensuration and has no @num and @numbase attributes + Fraction duration; + if (equivalence == DURATION_minima) { + duration = this->DurationWithMinimaEquivalence(num, numBase, currentMensur, noteDur); + } + else if (equivalence == DURATION_semibrevis) { + duration = this->DurationWithSemibrevisEquivalence(num, numBase, currentMensur, noteDur); + } + else { + duration = this->DurationWithBrevisEquivalence(num, numBase, currentMensur, noteDur); + } + duration = duration * numBase / num; + + return duration; +} + +Fraction DurationInterface::DurationWithBrevisEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const +{ int ratio = 0; Fraction duration(DURATION_breve); switch (noteDur) { @@ -146,13 +164,52 @@ Fraction DurationInterface::GetInterfaceAlignmentMensuralDuration( case DURATION_breve: break; case DURATION_1: duration = duration / abs(currentMensur->GetTempus()); break; default: + // ratio will be 1 for DURATION_2 (minima) where we apply the tempus and the prolatio ratio = pow(2.0, (double)(noteDur - DURATION_2)); assert(ratio); duration = duration / abs(currentMensur->GetTempus()) / abs(currentMensur->GetProlatio()) / ratio; break; } - duration = duration * numBase / num; + return duration; +} +Fraction DurationInterface::DurationWithSemibrevisEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const +{ + int ratio = 0; + Fraction duration(DURATION_1); + switch (noteDur) { + case DURATION_maxima: duration = duration * abs(currentMensur->GetModusmaior()); + case DURATION_long: duration = duration * abs(currentMensur->GetModusminor()); + case DURATION_breve: duration = duration * abs(currentMensur->GetTempus()); + case DURATION_1: break; + default: + // ratio will be 1 for DURATION_2 (minima) where we apply the prolatio + ratio = pow(2.0, (double)(noteDur - DURATION_2)); + assert(ratio); + duration = duration / abs(currentMensur->GetProlatio()) / ratio; + break; + } + return duration; +} + +Fraction DurationInterface::DurationWithMinimaEquivalence( + int num, int numBase, const Mensur *currentMensur, data_DURATION noteDur) const +{ + int ratio = 0; + Fraction duration(DURATION_2); + switch (noteDur) { + case DURATION_maxima: duration = duration * abs(currentMensur->GetModusmaior()); + case DURATION_long: duration = duration * abs(currentMensur->GetModusminor()); + case DURATION_breve: duration = duration * abs(currentMensur->GetTempus()); + case DURATION_1: duration = duration * abs(currentMensur->GetProlatio()); break; + default: + // ratio will be 1 for DURATION_2 (minima) + ratio = pow(2.0, (double)(noteDur - DURATION_2)); + assert(ratio); + duration = duration / ratio; + break; + } return duration; } diff --git a/src/fraction.cpp b/src/fraction.cpp index 63c0e8de678..9d3621edf49 100644 --- a/src/fraction.cpp +++ b/src/fraction.cpp @@ -74,6 +74,28 @@ Fraction Fraction::operator/(const Fraction &other) const return Fraction(num, denom); } +Fraction Fraction::operator%(const Fraction &other) const +{ + if (other.m_numerator == 0) { + LogDebug("Cannot divide by zero."); + return *this; + } + + // Convert both fractions to common denominator + int commonDenominator = m_denominator * other.m_denominator; + int leftNumerator = m_numerator * other.m_denominator; + int rightNumerator = other.m_numerator * m_denominator; + + // Integer quotient + int quotient = leftNumerator / rightNumerator; + + // Remainder as a fraction + Fraction remainder(leftNumerator - quotient * rightNumerator, commonDenominator); + remainder.Reduce(); + + return remainder; +} + bool Fraction::operator==(const Fraction &other) const { return m_numerator * other.m_denominator == other.m_numerator * m_denominator; @@ -117,7 +139,7 @@ std::pair Fraction::ToDur() const dur = vrv::DurationMin(DURATION_2048, dur); Fraction remainder = *this - Fraction(dur); - // Making sure we would not be trigger an inifite loop when looping over the remainder + // Making sure we would not be triggering an inifite loop when looping over the remainder if ((remainder >= *this) || (remainder < 0)) remainder = 0; return { dur, remainder }; } diff --git a/src/iocmme.cpp b/src/iocmme.cpp index 5b285264b07..97de53d063a 100644 --- a/src/iocmme.cpp +++ b/src/iocmme.cpp @@ -37,6 +37,7 @@ #include "measure.h" #include "mensur.h" #include "note.h" +#include "page.h" #include "proport.h" #include "rdg.h" #include "rest.h" @@ -48,6 +49,7 @@ #include "staffgrp.h" #include "supplied.h" #include "syl.h" +#include "system.h" #include "text.h" #include "verse.h" #include "vrv.h" @@ -83,7 +85,7 @@ bool CmmeInput::Import(const std::string &cmme) m_doc->SetMensuralMusicOnly(BOOLEAN_true); // Genereate the header and add a comment to the project description - m_doc->GenerateMEIHeader(false); + m_doc->GenerateMEIHeader(); pugi::xml_node projectDesc = m_doc->m_header.first_child().select_node("//projectDesc").node(); if (projectDesc) { pugi::xml_node p1 = projectDesc.append_child("p"); @@ -94,6 +96,10 @@ bool CmmeInput::Import(const std::string &cmme) doc.load_string(cmme.c_str(), (pugi::parse_comments | pugi::parse_default) & ~pugi::parse_eol); pugi::xml_node root = doc.first_child(); + if (root.child("GeneralData")) { + this->CreateMetadata(root.child("GeneralData")); + } + // The mDiv Mdiv *mdiv = new Mdiv(); mdiv->m_visibility = Visible; @@ -150,6 +156,8 @@ bool CmmeInput::Import(const std::string &cmme) m_score->GetScoreDef()->AddChild(staffGrp); m_doc->ConvertToPageBasedDoc(); + + this->PostProcessProport(); } catch (char *str) { LogError("%s", str); @@ -159,6 +167,105 @@ bool CmmeInput::Import(const std::string &cmme) return true; } +void CmmeInput::PostProcessProport() +{ + m_doc->PrepareData(); + m_doc->ScoreDefSetCurrentDoc(); + + Page *contentPage = m_doc->SetDrawingPage(0); + assert(contentPage); + + // Layout the content with tempo changes as original + contentPage->LayOutHorizontally(); + + // Go through all proportion marked as potentential tempo change, which is their + // status at this stage of import + // See if they are occurring at all voices with the same values + // If yes, this is a tempo change and mark them as such + // Otherwise mark them as "reset" since CMME does not cummulate values for tempo change + ListOfObjects proports = contentPage->FindAllDescendantsByType(PROPORT); + for (Object *object : proports) { + Proport *proport = vrv_cast(object); + assert(proport); + // Not a potential tempo change, or already processed + if (proport->GetType() != "cmme_tempo_change?") continue; + // Default type for tempo changes + std::string propType = "cmme_tempo_change"; + proport->SetType(propType); + + // Look at proportion aligned with it + Alignment *alignment = proport->GetAlignment(); + Object *measure = proport->GetFirstAncestor(MEASURE); + // Just in case + if (!measure || !alignment) continue; + // Check for the number of layer within the measure (e.g., section in CMME) + const int nbLayers = measure->GetDescendantCount(LAYER); + + bool isTempoChange = true; + bool allVoices = true; + // Not at all voices + if (nbLayers != alignment->GetChildCount()) { + isTempoChange = false; + allVoices = false; + } + // Check if the value of other proportions are the same + ListOfObjects alignProports = alignment->FindAllDescendantsByType(PROPORT); + for (Object *alignObject : alignProports) { + Proport *alignProport = vrv_cast(alignObject); + assert(proport); + isTempoChange = isTempoChange && (proport->GetNum() == alignProport->GetNum()); + isTempoChange = isTempoChange && (proport->GetNumbase() == alignProport->GetNumbase()); + } + if (!isTempoChange) { + propType = "reset"; + if (allVoices) { + LogWarning("A tempo change at all voices with different values detected"); + } + else { + LogWarning("A tempo change not occurring at all voices detected"); + } + } + + for (Object *alignObject : alignProports) { + Proport *alignProport = vrv_cast(alignObject); + assert(proport); + alignProport->SetType(propType); + } + } + + m_doc->ResetDataPage(); +} + +void CmmeInput::CreateMetadata(pugi::xml_node metadataNode) +{ + pugi::xml_node titleStmt = m_doc->m_header.first_child().select_node("//titleStmt").node(); + // Should have been created by Doc::GenerateHeader + if (!titleStmt) return; + + std::string titleStr = this->ChildAsString(metadataNode, "Title"); + if (!titleStr.empty()) { + pugi::xml_node title = titleStmt.child("title"); + title.text().set(titleStr.c_str()); + } + + std::string sectionStr = this->ChildAsString(metadataNode, "Section"); + if (!sectionStr.empty()) { + pugi::xml_node title = titleStmt.append_child("title"); + title.append_attribute("type") = "subordinate"; + title.text().set(sectionStr.c_str()); + } + + std::string composerStr = this->ChildAsString(metadataNode, "Composer"); + if (!composerStr.empty()) { + // pugi::xml_node respStmt = titleStmt.append_child("respStmt"); + // pugi::xml_node persName = respStmt.append_child("persName"); + // persName.append_attribute("role") = "composer"; + // persName.text().set(composerStr.c_str()); + pugi::xml_node composer = titleStmt.append_child("composer"); + composer.text().set(composerStr.c_str()); + } +} + void CmmeInput::CreateSection(pugi::xml_node musicSectionNode) { assert(m_score); @@ -206,6 +313,7 @@ void CmmeInput::CreateStaff(pugi::xml_node voiceNode) // Reset the syllable position m_isInSyllable = false; m_currentSignature = NULL; + m_activeTempoChange = false; staff->AddChild(m_currentContainer); m_currentSection->AddChild(staff); @@ -300,6 +408,9 @@ void CmmeInput::ReadEvents(pugi::xml_node eventsNode) CreateAccid(eventNode); } } + else if (name == "ColorChange") { + CreateColorChange(eventNode); + } else if (name == "Custos") { CreateCustos(eventNode); } @@ -488,21 +599,27 @@ void CmmeInput::CreateChord(pugi::xml_node chordNode) { assert(m_currentContainer); - Chord *chord = new Chord(); - m_currentContainer->AddChild(chord); - m_currentContainer = chord; + // CMME can have 'chords' in ligatures - we keep only the first note + bool inLigature = (m_currentContainer->Is(LIGATURE)); + + if (!inLigature) { + Chord *chord = new Chord(); + m_currentContainer->AddChild(chord); + m_currentContainer = chord; + } pugi::xpath_node_set events = chordNode.select_nodes("./*"); for (pugi::xpath_node event : events) { pugi::xml_node eventNode = event.node(); std::string name = eventNode.name(); if (name == "Note") { CreateNote(eventNode); + if (inLigature) break; } else { LogWarning("Unsupported chord component: '%s'", name.c_str()); } } - m_currentContainer = m_currentContainer->GetParent(); + if (!inLigature) m_currentContainer = m_currentContainer->GetParent(); } void CmmeInput::CreateClef(pugi::xml_node clefNode) @@ -534,6 +651,27 @@ void CmmeInput::CreateClef(pugi::xml_node clefNode) return; } +void CmmeInput::CreateColorChange(pugi::xml_node colorChangeNode) +{ + static const std::map colorMap{ + { "Black", "" }, // + { "Red", "red" }, // + { "Blue", "blue" }, // + { "Green", "green" }, // + { "Yellow", "yellow" }, // + }; + + assert(m_currentContainer); + + std::string color; + if (colorChangeNode.child("PrimaryColor")) { + color = this->ChildAsString(colorChangeNode.child("PrimaryColor"), "Color"); + } + m_currentColor = colorMap.contains(color) ? colorMap.at(color) : ""; + + return; +} + void CmmeInput::CreateCustos(pugi::xml_node custosNode) { static const std::map pitchMap{ @@ -553,6 +691,7 @@ void CmmeInput::CreateCustos(pugi::xml_node custosNode) // Default pitch to C data_PITCHNAME pname = pitchMap.contains(step) ? pitchMap.at(step) : PITCHNAME_c; custos->SetPname(pname); + if (!m_currentColor.empty()) custos->SetColor(m_currentColor); int oct = this->ChildAsInt(custosNode, "OctaveNum"); if ((pname != PITCHNAME_a) && (pname != PITCHNAME_b)) oct += 1; @@ -784,8 +923,21 @@ void CmmeInput::CreateMensuration(pugi::xml_node mensurationNode) if (denVal != VRV_UNSET) { proport->SetNumbase(denVal); } - proport->SetType("cmme_tempo_change"); + // Mark them as potential tempo changes + proport->SetType("cmme_tempo_change?"); m_currentContainer->AddChild(proport); + m_activeTempoChange = true; + } + // CMME resets the tempo change with a Mensuration with no tempo change + // We need to add one in the MEI + else if (m_activeTempoChange) { + Proport *proport = new Proport(); + proport->SetNum(1); + proport->SetNumbase(1); + // Mark them as potential tempo changes + proport->SetType("cmme_tempo_change?"); + m_currentContainer->AddChild(proport); + m_activeTempoChange = false; } return; @@ -827,6 +979,7 @@ void CmmeInput::CreateNote(pugi::xml_node noteNode) // Default pitch to C data_PITCHNAME pname = pitchMap.contains(step) ? pitchMap.at(step) : PITCHNAME_c; note->SetPname(pname); + if (!m_currentColor.empty()) note->SetColor(m_currentColor); int num; int numbase; @@ -970,6 +1123,8 @@ void CmmeInput::CreateRest(pugi::xml_node restNode) int numbase; data_DURATION duration = this->ReadDuration(restNode, num, numbase); rest->SetDur(duration); + if (!m_currentColor.empty()) rest->SetColor(m_currentColor); + if (num != VRV_UNSET && numbase != VRV_UNSET) { rest->SetNum(num); rest->SetNumbase(numbase); diff --git a/src/iohumdrum.cpp b/src/iohumdrum.cpp index cc281827ce5..5c2e7c01a55 100644 --- a/src/iohumdrum.cpp +++ b/src/iohumdrum.cpp @@ -32285,7 +32285,7 @@ void HumdrumInput::finalizeDocument(Doc *doc) if (m_mens) { doc->PrepareData(); - doc->SetMensuralMusicOnly(true); + doc->SetMensuralMusicOnly(BOOLEAN_true); doc->m_notationType = NOTATIONTYPE_mensural; doc->ConvertToCastOffMensuralDoc(true); } diff --git a/src/iomei.cpp b/src/iomei.cpp index dbdfe48d2ab..5968378c372 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -1469,7 +1469,9 @@ bool MEIOutput::WriteDoc(Doc *doc) // ---- header ---- if (!m_ignoreHeader) { - if (this->GetBasic() || !m_doc->m_header.first_child()) m_doc->GenerateMEIHeader(this->GetBasic()); + if (!m_doc->m_header.first_child()) m_doc->GenerateMEIHeader(); + if (this->GetBasic()) m_doc->ConvertHeaderToMEIBasic(); + // Now copy it to the m_mei node; m_mei.append_copy(m_doc->m_header.first_child()); // Add transposition in the revision list but not in mei-basic if (!this->GetBasic() && !m_doc->GetOptions()->m_transpose.GetValue().empty()) { @@ -4532,7 +4534,7 @@ bool MEIInput::ReadSectionChildren(Object *parent, pugi::xml_node parentNode) } else { unmeasured = new Measure(UNMEASURED); - m_doc->SetMensuralMusicOnly(true); + m_doc->SetMensuralMusicOnly(BOOLEAN_true); } parent->AddChild(unmeasured); } @@ -4568,7 +4570,7 @@ bool MEIInput::ReadSectionChildren(Object *parent, pugi::xml_node parentNode) } else { unmeasured = new Measure(UNMEASURED); - m_doc->SetMensuralMusicOnly(true); + m_doc->SetMensuralMusicOnly(BOOLEAN_true); } parent->AddChild(unmeasured); } @@ -4713,7 +4715,7 @@ bool MEIInput::ReadSystemChildren(Object *parent, pugi::xml_node parentNode) System *system = vrv_cast(parent); assert(system); unmeasured = new Measure(UNMEASURED); - m_doc->SetMensuralMusicOnly(true); + m_doc->SetMensuralMusicOnly(BOOLEAN_true); if (m_doc->IsTranscription() && (m_meiversion == meiVersion_MEIVERSION_2013)) { UpgradeMeasureTo_3_0_0(unmeasured, system); } @@ -5439,7 +5441,7 @@ bool MEIInput::ReadMeasure(Object *parent, pugi::xml_node measure) Measure *vrvMeasure = new Measure(); if (m_doc->IsMensuralMusicOnly()) { LogWarning("Mixing mensural and non mensural music is not supported. Trying to go ahead..."); - m_doc->SetMensuralMusicOnly(false); + m_doc->SetMensuralMusicOnly(BOOLEAN_false); } this->SetMeiID(measure, vrvMeasure); this->ReadFacsimileInterface(measure, vrvMeasure); @@ -6208,6 +6210,12 @@ bool MEIInput::ReadLayer(Object *parent, pugi::xml_node layer) LogWarning("Value @n='0' on might yield unpredictable results"); } + // Check that we have only one single layer in mensural music staves + if (m_doc->IsMensuralMusicOnly() && (parent->GetChildCount(LAYER) > 0)) { + LogWarning("Mensural music with more than one layer is not supported. Trying to go ahead..."); + m_doc->SetMensuralMusicOnly(BOOLEAN_false); + } + parent->AddChild(vrvLayer); this->ReadUnsupportedAttr(layer, vrvLayer); return this->ReadLayerChildren(vrvLayer, layer); diff --git a/src/iopae.cpp b/src/iopae.cpp index 0110464722d..75431ad8817 100644 --- a/src/iopae.cpp +++ b/src/iopae.cpp @@ -2826,7 +2826,7 @@ bool PAEInput::Import(const std::string &input) m_doc->SetType(Raw); // Genereate the header and add a comment to the project description - m_doc->GenerateMEIHeader(false); + m_doc->GenerateMEIHeader(); pugi::xml_node projectDesc = m_doc->m_header.first_child().select_node("//projectDesc").node(); if (projectDesc) { pugi::xml_node p1 = projectDesc.append_child("p"); diff --git a/src/layerelement.cpp b/src/layerelement.cpp index 8585bd8be38..f157d225313 100644 --- a/src/layerelement.cpp +++ b/src/layerelement.cpp @@ -722,7 +722,7 @@ Fraction LayerElement::GetAlignmentDuration( const DurationInterface *duration = this->GetDurationInterface(); assert(duration); if (duration->IsMensuralDur() && (notationType != NOTATIONTYPE_cmn)) { - return duration->GetInterfaceAlignmentMensuralDuration(num, numbase, params.mensur); + return duration->GetInterfaceAlignmentMensuralDuration(num, numbase, params.mensur, params.equivalence); } if (this->Is(NC)) { // This is called only with --neume-as-note diff --git a/src/midifunctor.cpp b/src/midifunctor.cpp index 7f2f42555b2..1ba9f2df13a 100644 --- a/src/midifunctor.cpp +++ b/src/midifunctor.cpp @@ -12,6 +12,7 @@ #include "arpeg.h" #include "beatrpt.h" #include "btrem.h" +#include "doc.h" #include "featureextractor.h" #include "ftrem.h" #include "gracegrp.h" @@ -40,12 +41,19 @@ namespace vrv { // InitOnsetOffsetFunctor //---------------------------------------------------------------------------- -InitOnsetOffsetFunctor::InitOnsetOffsetFunctor() : Functor() +InitOnsetOffsetFunctor::InitOnsetOffsetFunctor(Doc *doc) : DocFunctor(doc) { + static const std::map durationEq{ + { DURATION_EQ_brevis, DURATION_brevis }, // + { DURATION_EQ_semibrevis, DURATION_semibrevis }, // + { DURATION_EQ_minima, DURATION_minima }, // + }; + m_currentScoreTime = 0; m_currentRealTimeSeconds = 0.0; m_notationType = NOTATIONTYPE_cmn; m_currentTempo = MIDI_TEMPO; + m_meterParams.equivalence = durationEq.at(m_doc->GetOptions()->m_durationEquivalence.GetValue()); } FunctorCode InitOnsetOffsetFunctor::VisitChordEnd(Chord *chord) @@ -68,6 +76,7 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayer(Layer *layer) m_meterParams.mensur = layer->GetCurrentMensur(); m_meterParams.meterSig = layer->GetCurrentMeterSig(); + m_meterParams.proport = layer->GetCurrentProport(); return FUNCTOR_CONTINUE; } @@ -157,6 +166,16 @@ FunctorCode InitOnsetOffsetFunctor::VisitLayerElement(LayerElement *layerElement else if (layerElement->Is(METERSIG)) { this->m_meterParams.meterSig = vrv_cast(layerElement); } + else if (layerElement->Is(PROPORT)) { + if (layerElement->GetType() == "cmme_tempo_change") return FUNCTOR_SIBLINGS; + // replace the current proport + const Proport *previous = (m_meterParams.proport) ? (m_meterParams.proport) : NULL; + m_meterParams.proport = vrv_cast(layerElement); + assert(m_meterParams.proport); + if (previous) { + m_meterParams.proport->Cumulate(previous); + } + } return FUNCTOR_CONTINUE; } diff --git a/src/object.cpp b/src/object.cpp index d2cabed1835..cc9bfeb9aa7 100644 --- a/src/object.cpp +++ b/src/object.cpp @@ -393,6 +393,36 @@ int Object::GetDescendantCount(const ClassId classId) const return (int)objects.size(); } +void Object::CopyAttributesTo(Object *target) const +{ + assert(this->GetClassId() == target->GetClassId()); + + AttModule::CopyAnalytical(this, target); + AttModule::CopyCmn(this, target); + AttModule::CopyCmnornaments(this, target); + AttModule::CopyCritapp(this, target); + // AttModule::CopyEdittrans(this, target); + AttModule::CopyExternalsymbols(this, target); + AttModule::CopyFrettab(this, target); + AttModule::CopyFacsimile(this, target); + // AttModule::CopyFigtable(this, target); + // AttModule::CopyFingering(this, target); + AttModule::CopyGestural(this, target); + // AttModule::CopyHarmony(this, target); + // AttModule::CopyHeader(this, target); + AttModule::CopyMei(this, target); + AttModule::CopyMensural(this, target); + AttModule::CopyMidi(this, target); + AttModule::CopyNeumes(this, target); + AttModule::CopyPagebased(this, target); + // AttModule::CopyPerformance(this, target); + AttModule::CopyShared(this, target); + // AttModule::CopyUsersymbols(this, target); + AttModule::CopyVisual(this, target); + + target->m_unsupported = this->m_unsupported; +} + int Object::GetAttributes(ArrayOfStrAttr *attributes) const { assert(attributes); @@ -1568,7 +1598,7 @@ void TextListInterface::FilterList(ListOfConstObjects &childList) const // ObjectFactory methods //---------------------------------------------------------------------------- -thread_local MapOfStrConstructors ObjectFactory::s_ctorsRegistry; +thread_local MapOfClassIdConstructors ObjectFactory::s_ctorsRegistry; thread_local MapOfStrClassIds ObjectFactory::s_classIdsRegistry; ObjectFactory *ObjectFactory::GetInstance() @@ -1578,17 +1608,25 @@ ObjectFactory *ObjectFactory::GetInstance() } Object *ObjectFactory::Create(std::string name) +{ + ClassId classId = this->GetClassId(name); + if (classId == OBJECT) return NULL; + + return this->Create(classId); +} + +Object *ObjectFactory::Create(ClassId classId) { Object *object = NULL; - MapOfStrConstructors::iterator it = s_ctorsRegistry.find(name); + MapOfClassIdConstructors::iterator it = s_ctorsRegistry.find(classId); if (it != s_ctorsRegistry.end()) object = it->second(); if (object) { return object; } else { - LogError("Factory for '%s' not found", name.c_str()); + LogError("Factory for '%d' not found", classId); return NULL; } } @@ -1622,7 +1660,7 @@ void ObjectFactory::GetClassIds(const std::vector &classStrings, st void ObjectFactory::Register(std::string name, ClassId classId, std::function function) { - s_ctorsRegistry[name] = function; + s_ctorsRegistry[classId] = function; s_classIdsRegistry[name] = classId; } diff --git a/src/options.cpp b/src/options.cpp index 5f03508288c..1fcbb2c101c 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -29,6 +29,9 @@ const std::map Option::s_breaks = { { BREAKS_none, "none" }, { const std::map Option::s_condense = { { CONDENSE_none, "none" }, { CONDENSE_auto, "auto" }, { CONDENSE_encoded, "encoded" } }; +const std::map Option::s_durationEq + = { { DURATION_EQ_brevis, "brevis" }, { DURATION_EQ_semibrevis, "semibrevis" }, { DURATION_EQ_minima, "minima" } }; + const std::map Option::s_elision = { { ELISION_regular, "regular" }, { ELISION_narrow, "narrow" }, { ELISION_wide, "wide" }, { ELISION_unicode, "unicode" } }; @@ -1817,13 +1820,22 @@ Options::Options() m_mensural.SetCategory(OptionsCategory::Mensural); m_grps.push_back(&m_mensural); + m_durationEquivalence.SetInfo("Duration equivalence", "The mensural duration equivalence"); + m_durationEquivalence.Init(DURATION_EQ_brevis, &Option::s_durationEq); + this->Register(&m_durationEquivalence, "durationEquivalence", &m_mensural); + m_ligatureAsBracket.SetInfo("Ligature as bracket", "Render ligatures as bracket instead of original notation"); m_ligatureAsBracket.Init(false); this->Register(&m_ligatureAsBracket, "ligatureAsBracket", &m_mensural); - m_mensuralToMeasure.SetInfo("Mensural to measure", "Convert mensural sections to measure-based MEI"); - m_mensuralToMeasure.Init(false); - this->Register(&m_mensuralToMeasure, "mensuralToMeasure", &m_mensural); + m_mensuralResponsiveView.SetInfo( + "Mensural reduced view", "Convert mensural content to a more responsive view reduced to the seleceted markup"); + m_mensuralResponsiveView.Init(false); + this->Register(&m_mensuralResponsiveView, "mensuralResponsiveView", &m_mensural); + + m_mensuralToCmn.SetInfo("Mensural to CMN", "Convert mensural sections to CMN measure-based MEI"); + m_mensuralToCmn.Init(false); + this->Register(&m_mensuralToCmn, "mensuralToCmn", &m_mensural); /********* Method JSON options to the command-line *********/ diff --git a/src/pghead.cpp b/src/pghead.cpp index fcd7b1a05ea..4ce77ad4c38 100644 --- a/src/pghead.cpp +++ b/src/pghead.cpp @@ -85,13 +85,15 @@ bool PgHead::GenerateFromMEIHeader(const pugi::xml_document &header) this->AddChild(titleRend); } - nodeSet = header.select_nodes( - "//fileDesc/titleStmt/respStmt/persName[contains('lyricist translator composer harmonizer arranger', @role)]"); - for (pugi::xpath_node_set::const_iterator it = nodeSet.begin(); it != nodeSet.end(); ++it) { - node = *it; + nodeSet + = header.select_nodes("//fileDesc/titleStmt/composer|arranger|lyricist|respStmt/persName[contains('lyricist " + "translator composer harmonizer arranger', @role)]"); + + for (auto node : nodeSet) { Rend *personRend = new Rend(); std::string role = node.node().attribute("role").as_string(); - if (role == "lyricist" || role == "translator") { + std::string name = node.node().name(); + if (name == "lyricist" || role == "lyricist" || role == "translator") { personRend->SetHalign(HORIZONTALALIGNMENT_left); } else { diff --git a/src/proport.cpp b/src/proport.cpp index 44466ca8a59..1929eb0257c 100644 --- a/src/proport.cpp +++ b/src/proport.cpp @@ -50,6 +50,8 @@ int Proport::GetCumulatedNumbase() const void Proport::Cumulate(const Proport *proport) { // Unset values are not cumulated + if (this->GetType() == "reset") return; + if (proport->HasNum() && this->HasNum()) { m_cumulatedNum = this->GetNum() * proport->GetCumulatedNum(); } @@ -61,6 +63,12 @@ void Proport::Cumulate(const Proport *proport) } } +void Proport::ResetCumulate() +{ + m_cumulatedNum = VRV_UNSET; + m_cumulatedNumbase = VRV_UNSET; +} + FunctorCode Proport::Accept(Functor &functor) { return functor.VisitProport(this); diff --git a/src/resetfunctor.cpp b/src/resetfunctor.cpp index e09d3ee72a7..b8ff9f574a4 100644 --- a/src/resetfunctor.cpp +++ b/src/resetfunctor.cpp @@ -658,6 +658,14 @@ FunctorCode ResetHorizontalAlignmentFunctor::VisitNote(Note *note) return FUNCTOR_CONTINUE; } +FunctorCode ResetHorizontalAlignmentFunctor::VisitProport(Proport *proport) +{ + this->VisitLayerElement(proport); + proport->ResetCumulate(); + + return FUNCTOR_CONTINUE; +} + FunctorCode ResetHorizontalAlignmentFunctor::VisitRest(Rest *rest) { this->VisitLayerElement(rest); diff --git a/src/setscoredeffunctor.cpp b/src/setscoredeffunctor.cpp index bfb13ce8e2b..d1223ed0b1b 100644 --- a/src/setscoredeffunctor.cpp +++ b/src/setscoredeffunctor.cpp @@ -232,6 +232,7 @@ FunctorCode ScoreDefSetCurrentFunctor::VisitPage(Page *page) FunctorCode ScoreDefSetCurrentFunctor::VisitProport(Proport *proport) { + if (proport->GetType() == "cmme_tempo_change") return FUNCTOR_SIBLINGS; assert(m_currentStaffDef); StaffDef *upcomingStaffDef = m_upcomingScoreDef.GetStaffDef(m_currentStaffDef->GetN()); assert(upcomingStaffDef); diff --git a/src/system.cpp b/src/system.cpp index cbf3e6748f3..05585b9d7eb 100644 --- a/src/system.cpp +++ b/src/system.cpp @@ -429,27 +429,6 @@ double System::EstimateJustificationRatio(const Doc *doc) const return estimatedRatio; } -void System::ConvertToCastOffMensuralSystem(Doc *doc, System *targetSystem) -{ - assert(doc); - assert(targetSystem); - - // We need to populate processing lists for processing the document by Layer - InitProcessingListsFunctor initProcessingLists; - this->Process(initProcessingLists); - const IntTree &layerTree = initProcessingLists.GetLayerTree(); - - // Checking just in case - if (layerTree.child.empty()) return; - - ConvertToCastOffMensuralFunctor convertToCastOffMensural(doc, targetSystem, &layerTree); - // Store the list of staff N for detecting barLines that are on all systems - for (const auto &staves : layerTree.child) { - convertToCastOffMensural.AddStaffN(staves.first); - } - this->Process(convertToCastOffMensural); -} - void System::ConvertToUnCastOffMensuralSystem() { // We need to populate processing lists for processing the document by Layer diff --git a/src/toolkit.cpp b/src/toolkit.cpp index 8911ade8f58..3ed1bd7bbcb 100644 --- a/src/toolkit.cpp +++ b/src/toolkit.cpp @@ -571,6 +571,10 @@ bool Toolkit::LoadData(const std::string &data, bool resetLogBuffer) input = new VolpianoInput(&m_doc); } else if (inputFormat == CMME) { + if (m_options->m_durationEquivalence.GetValue() != DURATION_EQ_minima) { + LogWarning("CMME input uses 'minima' duration equivalence, changing the option accordingly."); + m_options->m_durationEquivalence.SetValue(DURATION_EQ_minima); + } input = new CmmeInput(&m_doc); } #ifndef NO_HUMDRUM_SUPPORT @@ -816,7 +820,15 @@ bool Toolkit::LoadData(const std::string &data, bool resetLogBuffer) // Convert pseudo-measures into distinct segments based on barLine elements if (m_doc.IsMensuralMusicOnly()) { - m_doc.ConvertToCastOffMensuralDoc(true); + if (m_options->m_mensuralResponsiveView.GetValue()) { + m_doc.ConvertToMensuralViewDoc(); + } + else if (m_options->m_mensuralToCmn.GetValue()) { + m_doc.ConvertToCmnDoc(); + } + else { + m_doc.ConvertToCastOffMensuralDoc(true); + } } // Do the layout? this depends on the options and the file. PAE and