diff --git a/include/vrv/arpeg.h b/include/vrv/arpeg.h index 4867378037..80f41500e9 100644 --- a/include/vrv/arpeg.h +++ b/include/vrv/arpeg.h @@ -28,7 +28,6 @@ class Arpeg : public ControlElement, public TimePointInterface, public AttArpegLog, public AttArpegVis, - public AttColor, public AttEnclosingChars { public: /** diff --git a/include/vrv/beamspan.h b/include/vrv/beamspan.h index b66631bb92..5533e5c840 100644 --- a/include/vrv/beamspan.h +++ b/include/vrv/beamspan.h @@ -33,8 +33,7 @@ class BeamSpan : public ControlElement, public PlistInterface, public TimeSpanningInterface, public AttBeamedWith, - public AttBeamRend, - public AttColor { + public AttBeamRend { public: /** * @name Constructors, destructors, and other standard methods diff --git a/include/vrv/bracketspan.h b/include/vrv/bracketspan.h index 22e8c1aa69..5937dd0c0f 100644 --- a/include/vrv/bracketspan.h +++ b/include/vrv/bracketspan.h @@ -24,7 +24,6 @@ namespace vrv { class BracketSpan : public ControlElement, public TimeSpanningInterface, public AttBracketSpanLog, - public AttColor, public AttLineRend, public AttLineRendBase { public: diff --git a/include/vrv/breath.h b/include/vrv/breath.h index 502b510e25..c11ec1213a 100644 --- a/include/vrv/breath.h +++ b/include/vrv/breath.h @@ -21,7 +21,7 @@ namespace vrv { /** * This class models the MEI element. */ -class Breath : public ControlElement, public TimePointInterface, public AttColor, public AttPlacementRelStaff { +class Breath : public ControlElement, public TimePointInterface, public AttPlacementRelStaff { public: /** * @name Constructors, destructors, and other standard methods diff --git a/include/vrv/caesura.h b/include/vrv/caesura.h index 5125f911de..49fe58336d 100644 --- a/include/vrv/caesura.h +++ b/include/vrv/caesura.h @@ -24,7 +24,6 @@ namespace vrv { */ class Caesura : public ControlElement, public TimePointInterface, - public AttColor, public AttExtSymAuth, public AttExtSymNames, public AttPlacementRelStaff { diff --git a/include/vrv/controlelement.h b/include/vrv/controlelement.h index 6d595ddfbc..3253a7213f 100644 --- a/include/vrv/controlelement.h +++ b/include/vrv/controlelement.h @@ -10,6 +10,7 @@ #include "altsyminterface.h" #include "atts_shared.h" +#include "atts_visual.h" #include "devicecontextbase.h" #include "floatingobject.h" #include "linkinginterface.h" @@ -27,6 +28,7 @@ namespace vrv { class ControlElement : public FloatingObject, public AltSymInterface, public LinkingInterface, + public AttColor, public AttLabelled, public AttTyped { public: diff --git a/include/vrv/editortoolkit_neume.h b/include/vrv/editortoolkit_neume.h index 1a925b0c8f..e0a7801e51 100644 --- a/include/vrv/editortoolkit_neume.h +++ b/include/vrv/editortoolkit_neume.h @@ -41,7 +41,7 @@ class EditorToolkitNeume : public EditorToolkit { ///@{ bool Chain(jsonxx::Array actions); bool DisplaceClefOctave(std::string elementId, std::string direction); - bool Drag(std::string elementId, int x, int y); + bool Drag(std::string elementId, int x, int y, bool topLevel = true); bool Insert(std::string elementType, std::string staffId, int ulx, int uly, int lrx, int lry, std::vector> attributes); bool InsertToSyllable(std::string elementId); @@ -102,7 +102,8 @@ class EditorToolkitNeume : public EditorToolkit { * Helper functions for editor actions. */ ///@{ - bool AdjustPitchFromPosition(Object *obj, Clef *clef = NULL); + bool AdjustPitchAfterDrag(Object *obj, int y = 0); + bool AdjustPitchFromPosition(Object *obj); bool AdjustClefLineFromPosition(Clef *clef, Staff *staff = NULL); ///@} }; diff --git a/include/vrv/fermata.h b/include/vrv/fermata.h index 128368fd85..b0429636ed 100644 --- a/include/vrv/fermata.h +++ b/include/vrv/fermata.h @@ -25,7 +25,6 @@ namespace vrv { */ class Fermata : public ControlElement, public TimePointInterface, - public AttColor, public AttEnclosingChars, public AttExtSymAuth, public AttExtSymNames, diff --git a/include/vrv/gliss.h b/include/vrv/gliss.h index 3eb6c55378..a464862fca 100644 --- a/include/vrv/gliss.h +++ b/include/vrv/gliss.h @@ -23,7 +23,6 @@ namespace vrv { */ class Gliss : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttLineRend, public AttLineRendBase, public AttNNumberLike { diff --git a/include/vrv/hairpin.h b/include/vrv/hairpin.h index 8a81dd1d3d..353b53adbc 100644 --- a/include/vrv/hairpin.h +++ b/include/vrv/hairpin.h @@ -24,7 +24,6 @@ namespace vrv { */ class Hairpin : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttHairpinLog, public AttHairpinVis, public AttLineRendBase, diff --git a/include/vrv/mnum.h b/include/vrv/mnum.h index a8d32b1de0..44d3e5329a 100644 --- a/include/vrv/mnum.h +++ b/include/vrv/mnum.h @@ -27,7 +27,6 @@ class MNum : public ControlElement, public TextListInterface, public TextDirInterface, public TimePointInterface, - public AttColor, public AttLang, public AttTypography { public: diff --git a/include/vrv/mordent.h b/include/vrv/mordent.h index 2eaf9ddeaf..c479d62bf8 100644 --- a/include/vrv/mordent.h +++ b/include/vrv/mordent.h @@ -25,7 +25,6 @@ namespace vrv { */ class Mordent : public ControlElement, public TimePointInterface, - public AttColor, public AttExtSymAuth, public AttExtSymNames, public AttOrnamentAccid, diff --git a/include/vrv/note.h b/include/vrv/note.h index aaf6a461b5..28bc00c41b 100644 --- a/include/vrv/note.h +++ b/include/vrv/note.h @@ -13,6 +13,7 @@ //---------------------------------------------------------------------------- #include "accid.h" +#include "altsyminterface.h" #include "atts_analytical.h" #include "atts_externalsymbols.h" #include "atts_frettab.h" @@ -45,6 +46,7 @@ class Verse; */ class Note : public LayerElement, public StemmedDrawingInterface, + public AltSymInterface, public DurationInterface, public PitchInterface, public PositionInterface, @@ -80,6 +82,8 @@ class Note : public LayerElement, * @name Getter to interfaces */ ///@{ + AltSymInterface *GetAltSymInterface() override { return vrv_cast(this); } + const AltSymInterface *GetAltSymInterface() const override { return vrv_cast(this); } DurationInterface *GetDurationInterface() override { return vrv_cast(this); } const DurationInterface *GetDurationInterface() const override { return vrv_cast(this); } PitchInterface *GetPitchInterface() override { return vrv_cast(this); } @@ -145,7 +149,7 @@ class Note : public LayerElement, * @name Return the smufl string to use for a note give the notation type */ ///@{ - std::u32string GetTabFretString(data_NOTATIONTYPE notationType) const; + std::u32string GetTabFretString(data_NOTATIONTYPE notationType, int &overline, int &strike, int &underline) const; ///@} /** diff --git a/include/vrv/octave.h b/include/vrv/octave.h index c9f59f7651..d8ebf6609c 100644 --- a/include/vrv/octave.h +++ b/include/vrv/octave.h @@ -24,7 +24,6 @@ namespace vrv { */ class Octave : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttExtender, public AttLineRend, public AttLineRendBase, diff --git a/include/vrv/ornam.h b/include/vrv/ornam.h index 25950ab63b..2f417fa446 100644 --- a/include/vrv/ornam.h +++ b/include/vrv/ornam.h @@ -28,7 +28,6 @@ class Ornam : public ControlElement, public TextListInterface, public TextDirInterface, public TimePointInterface, - public AttColor, public AttOrnamentAccid { public: /** diff --git a/include/vrv/pedal.h b/include/vrv/pedal.h index 36b521be3a..2bde8f287a 100644 --- a/include/vrv/pedal.h +++ b/include/vrv/pedal.h @@ -26,7 +26,6 @@ class System; */ class Pedal : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttExtSymAuth, public AttExtSymNames, public AttPedalLog, diff --git a/include/vrv/reh.h b/include/vrv/reh.h index 51f837a32f..a371468605 100644 --- a/include/vrv/reh.h +++ b/include/vrv/reh.h @@ -26,7 +26,6 @@ class TextElement; class Reh : public ControlElement, public TextDirInterface, public TimePointInterface, - public AttColor, public AttLang, public AttVerticalGroup { public: diff --git a/include/vrv/repeatmark.h b/include/vrv/repeatmark.h index 87e3cadd8d..ce228b37dc 100644 --- a/include/vrv/repeatmark.h +++ b/include/vrv/repeatmark.h @@ -27,7 +27,6 @@ class RepeatMark : public ControlElement, public TextListInterface, public TextDirInterface, public TimePointInterface, - public AttColor, public AttExtSymAuth, public AttExtSymNames, public AttRepeatMarkLog { diff --git a/include/vrv/rest.h b/include/vrv/rest.h index 506df84a89..9a833f49cd 100644 --- a/include/vrv/rest.h +++ b/include/vrv/rest.h @@ -8,6 +8,7 @@ #ifndef __VRV_REST_H__ #define __VRV_REST_H__ +#include "altsyminterface.h" #include "atts_externalsymbols.h" #include "atts_mensural.h" #include "durationinterface.h" @@ -34,6 +35,7 @@ enum RestNotePlace { RNP_UNSET = -1, RNP_noteInSpace, RNP_noteOnLine }; * This class models the MEI element. */ class Rest : public LayerElement, + public AltSymInterface, public DurationInterface, public PositionInterface, public AttColor, @@ -69,6 +71,7 @@ class Rest : public LayerElement, * @name Getter to interfaces */ ///@{ + AltSymInterface *GetAltSymInterface() override { return vrv_cast(this); } PositionInterface *GetPositionInterface() override { return vrv_cast(this); } const PositionInterface *GetPositionInterface() const override { return vrv_cast(this); } DurationInterface *GetDurationInterface() override { return vrv_cast(this); } diff --git a/include/vrv/slur.h b/include/vrv/slur.h index 6c6e6ac8d7..595a9235cb 100644 --- a/include/vrv/slur.h +++ b/include/vrv/slur.h @@ -52,7 +52,6 @@ enum class PortatoSlurType { None, StemSide, Centered }; class Slur : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttCurvature, public AttLayerIdent, public AttLineRendBase { diff --git a/include/vrv/staffdef.h b/include/vrv/staffdef.h index 7e779f3df0..b59d303483 100644 --- a/include/vrv/staffdef.h +++ b/include/vrv/staffdef.h @@ -32,7 +32,8 @@ class StaffDef : public ScoreDefElement, public AttStaffDefLog, public AttStaffDefVis, public AttTimeBase, - public AttTransposition { + public AttTransposition, + public AttVerticalAlign { public: /** * @name Constructors, destructors, and other standard methods diff --git a/include/vrv/tabdursym.h b/include/vrv/tabdursym.h index 87e39ab218..e83d6b7819 100644 --- a/include/vrv/tabdursym.h +++ b/include/vrv/tabdursym.h @@ -21,7 +21,7 @@ namespace vrv { /** * This class models the MEI element. */ -class TabDurSym : public LayerElement, public StemmedDrawingInterface, public AttNNumberLike { +class TabDurSym : public LayerElement, public StemmedDrawingInterface, public AttNNumberLike, public AttStaffLoc { public: /** * @name Constructors, destructors, and other standard methods @@ -30,6 +30,7 @@ class TabDurSym : public LayerElement, public StemmedDrawingInterface, public At ///@{ TabDurSym(); virtual ~TabDurSym(); + Object *Clone() const override { return new TabDurSym(*this); } void Reset() override; std::string GetClassName() const override { return "TabDurSym"; } ///@} diff --git a/include/vrv/tabgrp.h b/include/vrv/tabgrp.h index 14e9f8ba4d..cf9dd6713b 100644 --- a/include/vrv/tabgrp.h +++ b/include/vrv/tabgrp.h @@ -29,6 +29,7 @@ class TabGrp : public LayerElement, public ObjectListInterface, public DurationI ///@{ TabGrp(); virtual ~TabGrp(); + Object *Clone() const override { return new TabGrp(*this); } void Reset() override; std::string GetClassName() const override { return "TabGrp"; } ///@} diff --git a/include/vrv/tie.h b/include/vrv/tie.h index ccd92e5e5e..8b6686f2cd 100644 --- a/include/vrv/tie.h +++ b/include/vrv/tie.h @@ -24,11 +24,7 @@ class Note; /** * This class models the MEI element. */ -class Tie : public ControlElement, - public TimeSpanningInterface, - public AttColor, - public AttCurvature, - public AttLineRendBase { +class Tie : public ControlElement, public TimeSpanningInterface, public AttCurvature, public AttLineRendBase { public: /** * @name Constructors, destructors, and other standard methods diff --git a/include/vrv/trill.h b/include/vrv/trill.h index da61ec3d25..622965a76e 100644 --- a/include/vrv/trill.h +++ b/include/vrv/trill.h @@ -25,7 +25,6 @@ namespace vrv { */ class Trill : public ControlElement, public TimeSpanningInterface, - public AttColor, public AttExtender, public AttExtSymAuth, public AttExtSymNames, diff --git a/include/vrv/tuning.h b/include/vrv/tuning.h index bdb78867b9..d30b842856 100644 --- a/include/vrv/tuning.h +++ b/include/vrv/tuning.h @@ -40,9 +40,22 @@ class Tuning : public Object, public AttCourseLog { bool IsSupportedChild(Object *object) override; /** - * Return the line for a the tuning and a given course and a notation type + * Return the line for a note according to tablature type. + * Guitar, french and italian tablature: the line is based on the course. + * German tablature: the line is based on the note's index in the note list + * or by explicit @loc. + * + * @param[in] course + * @param[in] notationType + * @param[in] lines + * @param[in] listSize + * @param[in] index - 0 based from the bottom of the chord + * @param[in] loc - German tablature: note@loc if specified, 0 at the bottom + * @param[in] topAlign - German tablature: true => align at the top, false => align at the bottom + * @return position in staff half lines */ - int CalcPitchPos(int course, data_NOTATIONTYPE notationType, int lines) const; + int CalcPitchPos( + int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index, int loc, bool topAlign) const; /** * Calculate the MIDI note number for course/fret diff --git a/include/vrv/turn.h b/include/vrv/turn.h index f11f12e35a..6c7a535780 100644 --- a/include/vrv/turn.h +++ b/include/vrv/turn.h @@ -25,7 +25,6 @@ namespace vrv { */ class Turn : public ControlElement, public TimePointInterface, - public AttColor, public AttExtSymAuth, public AttExtSymNames, public AttOrnamentAccid, diff --git a/include/vrv/view.h b/include/vrv/view.h index 63f55a2769..56cdedebee 100644 --- a/include/vrv/view.h +++ b/include/vrv/view.h @@ -232,7 +232,7 @@ class View { void DrawMeterSigGrp(DeviceContext *dc, Layer *layer, Staff *staff); void DrawMNum(DeviceContext *dc, MNum *mnum, Measure *measure, System *system, int yOffset); void DrawStaff(DeviceContext *dc, Staff *staff, Measure *measure, System *system); - void DrawStaffLines(DeviceContext *dc, Staff *staff, Measure *measure, System *system); + void DrawStaffLines(DeviceContext *dc, Staff *staff, StaffDef *staffDef, Measure *measure, System *system); void DrawLayer(DeviceContext *dc, Layer *layer, Staff *staff, Measure *measure); void DrawLayerList(DeviceContext *dc, Layer *layer, Staff *staff, Measure *measure, const ClassId classId); void DrawLayerDefLabels( diff --git a/include/vrv/vrvdef.h b/include/vrv/vrvdef.h index b1fd69af2d..750326523f 100644 --- a/include/vrv/vrvdef.h +++ b/include/vrv/vrvdef.h @@ -695,6 +695,7 @@ enum MeasureType { MEASURED = 0, UNMEASURED, NEUMELINE }; //---------------------------------------------------------------------------- #define TABLATURE_STAFF_RATIO 1.75 +#define GERMAN_TAB_STAFF_RATIO 2.2 #define SUPER_SCRIPT_FACTOR 0.58 #define SUPER_SCRIPT_POSITION -0.20 // lowered down from the midline diff --git a/src/arpeg.cpp b/src/arpeg.cpp index 09863c30f0..aef7ee75ac 100644 --- a/src/arpeg.cpp +++ b/src/arpeg.cpp @@ -29,14 +29,12 @@ namespace vrv { static const ClassRegistrar s_factory("arpeg", ARPEG); -Arpeg::Arpeg() - : ControlElement(ARPEG, "arpeg-"), PlistInterface(), TimePointInterface(), AttArpegLog(), AttArpegVis(), AttColor() +Arpeg::Arpeg() : ControlElement(ARPEG, "arpeg-"), PlistInterface(), TimePointInterface(), AttArpegLog(), AttArpegVis() { this->RegisterInterface(PlistInterface::GetAttClasses(), PlistInterface::IsInterface()); this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); this->RegisterAttClass(ATT_ARPEGLOG); this->RegisterAttClass(ATT_ARPEGVIS); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_ENCLOSINGCHARS); this->Reset(); @@ -51,7 +49,6 @@ void Arpeg::Reset() TimePointInterface::Reset(); this->ResetArpegLog(); this->ResetArpegVis(); - this->ResetColor(); this->ResetEnclosingChars(); m_drawingXRel = 0; diff --git a/src/beam.cpp b/src/beam.cpp index 2cefcb2e3b..5a51746a94 100644 --- a/src/beam.cpp +++ b/src/beam.cpp @@ -602,8 +602,8 @@ void BeamSegment::CalcBeamInit( beamInterface->m_beamWidthBlack /= 2; beamInterface->m_beamWidthWhite /= 2; - // Adjust it further for tab.lute.french and tab.lute.italian - if (staff->IsTabLuteFrench() || staff->IsTabLuteItalian()) { + // Adjust it further for tab.lute.french, tab.lute.german and tab.lute.italian + if (staff->IsTabLuteFrench() || staff->IsTabLuteGerman() || staff->IsTabLuteItalian()) { beamInterface->m_beamWidthBlack = beamInterface->m_beamWidthBlack * 2 / 5; beamInterface->m_beamWidthWhite = beamInterface->m_beamWidthWhite * 3 / 5; } diff --git a/src/beamspan.cpp b/src/beamspan.cpp index 605016a01e..ea02767983 100644 --- a/src/beamspan.cpp +++ b/src/beamspan.cpp @@ -36,13 +36,11 @@ BeamSpan::BeamSpan() , TimeSpanningInterface() , AttBeamedWith() , AttBeamRend() - , AttColor() { RegisterInterface(PlistInterface::GetAttClasses(), PlistInterface::IsInterface()); RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); RegisterAttClass(ATT_BEAMEDWITH); RegisterAttClass(ATT_BEAMREND); - RegisterAttClass(ATT_COLOR); Reset(); InitBeamSegments(); @@ -61,7 +59,6 @@ void BeamSpan::Reset() TimeSpanningInterface::Reset(); ResetBeamedWith(); ResetBeamRend(); - ResetColor(); ClearBeamSegments(); } diff --git a/src/bracketspan.cpp b/src/bracketspan.cpp index a793311d60..ed49bcadd5 100644 --- a/src/bracketspan.cpp +++ b/src/bracketspan.cpp @@ -31,13 +31,11 @@ BracketSpan::BracketSpan() : ControlElement(BRACKETSPAN, "bspan-") , TimeSpanningInterface() , AttBracketSpanLog() - , AttColor() , AttLineRend() , AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); this->RegisterAttClass(ATT_BRACKETSPANLOG); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LINEREND); this->RegisterAttClass(ATT_LINERENDBASE); @@ -51,7 +49,6 @@ void BracketSpan::Reset() ControlElement::Reset(); TimeSpanningInterface::Reset(); this->ResetBracketSpanLog(); - this->ResetColor(); this->ResetLineRend(); this->ResetLineRendBase(); } diff --git a/src/breath.cpp b/src/breath.cpp index e0af690624..5237195401 100644 --- a/src/breath.cpp +++ b/src/breath.cpp @@ -24,10 +24,9 @@ namespace vrv { static const ClassRegistrar s_factory("breath", BREATH); -Breath::Breath() : ControlElement(BREATH, "breath-"), TimePointInterface(), AttColor(), AttPlacementRelStaff() +Breath::Breath() : ControlElement(BREATH, "breath-"), TimePointInterface(), AttPlacementRelStaff() { this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_PLACEMENTRELSTAFF); this->Reset(); @@ -39,7 +38,6 @@ void Breath::Reset() { ControlElement::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetPlacementRelStaff(); } diff --git a/src/caesura.cpp b/src/caesura.cpp index 494baca028..4aab629585 100644 --- a/src/caesura.cpp +++ b/src/caesura.cpp @@ -29,13 +29,11 @@ static const ClassRegistrar s_factory("caesura", CAESURA); Caesura::Caesura() : ControlElement(CAESURA, "caesura-") , TimePointInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttPlacementRelStaff() { this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); this->RegisterAttClass(ATT_PLACEMENTRELSTAFF); @@ -49,7 +47,6 @@ void Caesura::Reset() { ControlElement::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetPlacementRelStaff(); } diff --git a/src/calcalignmentpitchposfunctor.cpp b/src/calcalignmentpitchposfunctor.cpp index 982d8078d8..dabdc80d3e 100644 --- a/src/calcalignmentpitchposfunctor.cpp +++ b/src/calcalignmentpitchposfunctor.cpp @@ -17,6 +17,7 @@ #include "rest.h" #include "score.h" #include "staff.h" +#include "tabgrp.h" #include "tuning.h" //---------------------------------------------------------------------------- @@ -105,8 +106,10 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE TabGrp *tabGrp = note->IsTabGrpNote(); if (tabGrp) { assert(staffY->m_drawingTuning); - loc = staffY->m_drawingTuning->CalcPitchPos( - note->GetTabCourse(), staffY->m_drawingNotationType, staffY->m_drawingLines); + assert(staffY->m_drawingStaffDef); + loc = staffY->m_drawingTuning->CalcPitchPos(note->GetTabCourse(), staffY->m_drawingNotationType, + staffY->m_drawingLines, tabGrp->GetListSize(), tabGrp->GetListIndex(note), note->GetLoc(), + staffY->m_drawingStaffDef->GetValign() != VERTICALALIGNMENT_bottom); } else if ((note->HasPname() && (note->HasOct() || note->HasOctDefault())) || note->HasLoc()) { loc = PitchInterface::CalcLoc(note, layerY, layerElementY); @@ -307,7 +310,7 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE else if (layerElement->Is(TABDURSYM)) { int yRel = 0; if (staffY->IsTabWithStemsOutside()) { - double spacingRatio = (staffY->IsTabLuteFrench()) ? 2.0 : 1.0; + double spacingRatio = (staffY->IsTabLuteFrench() || staffY->IsTabLuteGerman()) ? 2.0 : 1.0; yRel += m_doc->GetDrawingUnit(staffY->m_drawingStaffSize) * spacingRatio; } layerElement->SetDrawingYRel(yRel); diff --git a/src/controlelement.cpp b/src/controlelement.cpp index 9891f5aaeb..7024457fdf 100644 --- a/src/controlelement.cpp +++ b/src/controlelement.cpp @@ -28,10 +28,16 @@ namespace vrv { //---------------------------------------------------------------------------- ControlElement::ControlElement() - : FloatingObject(CONTROL_ELEMENT, "ce"), AltSymInterface(), LinkingInterface(), AttLabelled(), AttTyped() + : FloatingObject(CONTROL_ELEMENT, "ce") + , AltSymInterface() + , LinkingInterface() + , AttColor() + , AttLabelled() + , AttTyped() { this->RegisterInterface(AltSymInterface::GetAttClasses(), AltSymInterface::IsInterface()); this->RegisterInterface(LinkingInterface::GetAttClasses(), LinkingInterface::IsInterface()); + this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LABELLED); this->RegisterAttClass(ATT_TYPED); @@ -43,6 +49,7 @@ ControlElement::ControlElement(ClassId classId) { this->RegisterInterface(AltSymInterface::GetAttClasses(), AltSymInterface::IsInterface()); this->RegisterInterface(LinkingInterface::GetAttClasses(), LinkingInterface::IsInterface()); + this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LABELLED); this->RegisterAttClass(ATT_TYPED); @@ -54,6 +61,7 @@ ControlElement::ControlElement(ClassId classId, const std::string &classIdStr) { this->RegisterInterface(AltSymInterface::GetAttClasses(), AltSymInterface::IsInterface()); this->RegisterInterface(LinkingInterface::GetAttClasses(), LinkingInterface::IsInterface()); + this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LABELLED); this->RegisterAttClass(ATT_TYPED); @@ -67,6 +75,7 @@ void ControlElement::Reset() FloatingObject::Reset(); AltSymInterface::Reset(); LinkingInterface::Reset(); + this->ResetColor(); this->ResetLabelled(); this->ResetTyped(); } diff --git a/src/editortoolkit_neume.cpp b/src/editortoolkit_neume.cpp index 576e4c3549..9c51155be2 100644 --- a/src/editortoolkit_neume.cpp +++ b/src/editortoolkit_neume.cpp @@ -489,7 +489,7 @@ bool EditorToolkitNeume::ClefMovementHandler(Clef *clef, int x, int y) return true; } -bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) +bool EditorToolkitNeume::Drag(std::string elementId, int x, int y, bool topLevel) { std::string status = "OK", message = ""; if (!m_doc->GetDrawingPage()) { @@ -520,87 +520,55 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) assert(zone); zone->ShiftByXY(x, -y); - AdjustPitchFromPosition(element); + AdjustPitchAfterDrag(element, y); } - else if (element->HasInterface(INTERFACE_PITCH) || element->Is(NEUME) || element->Is(SYLLABLE)) { - Layer *layer = dynamic_cast(element->GetFirstAncestor(LAYER)); - if (!layer) { - LogError("Element does not have Layer parent. This should not happen."); - m_editInfo.import("status", "FAILURE"); - m_editInfo.import("message", "Element does not have Layer parent."); - return false; - } - - // clef association is done at the syllable level because of MEI structure - // also note this will initialize syllable as null in the case of custos - // which is why all the references to syllable are ternary - - Object *syllable = ((element->Is(SYLLABLE) ? (element) : element->GetFirstAncestor(SYLLABLE))); - - ClassIdComparison ac(CLEF); - InterfaceComparison facsIC(INTERFACE_FACSIMILE); - InterfaceComparison pitchIC(INTERFACE_PITCH); - + else if (element->Is(SYLLABLE)) { // Check for clefs in syllable ListOfObjects clefs; - syllable->FindAllDescendantsByComparison(&clefs, &ac); + ClassIdComparison ac(CLEF); + element->FindAllDescendantsByComparison(&clefs, &ac); bool hasClef = (clefs.size() != 0); - - FacsimileInterface *fi = element->GetFacsimileInterface(); - if (fi && fi->HasFacs()) { - bool ignoreFacs = false; - // Dont adjust the same facsimile twice. NCs in a ligature share a single zone. - if (element->Is(NC)) { - Nc *nc = dynamic_cast(element); - if (nc->GetLigated() == BOOLEAN_true) { - Neume *neume = vrv_cast(nc->GetFirstAncestor(NEUME)); - Nc *nextNc = dynamic_cast(neume->GetChild(1 + neume->GetChildIndex(element))); - if (nextNc != NULL && nextNc->GetLigated() == BOOLEAN_true && nextNc->GetZone() == nc->GetZone()) { - ignoreFacs = true; - } - } - } - if (!ignoreFacs) { - FacsimileInterface *fi = element->GetFacsimileInterface(); - assert(fi); - Zone *zone = fi->GetZone(); - assert(zone); - zone->ShiftByXY(x, -y); - } - } - else { - ListOfObjects facsChildren; - element->FindAllDescendantsByComparison(&facsChildren, &facsIC); - for (auto it = facsChildren.begin(); it != facsChildren.end(); ++it) { - // Don't change the text bbox position and skip clefs until later - if ((*it)->Is(SYL) || !(*it)->GetFacsimileInterface()->HasFacs() || (*it)->Is(CLEF)) { - continue; - } - else { - (*it)->GetFacsimileInterface()->GetZone()->ShiftByXY(x, -y); - } - } - } - if (hasClef) { for (Object *obj : clefs) { Clef *clef = dynamic_cast(obj); - ClefMovementHandler(clef, x, 0); + Drag(clef->GetID(), x, y, false); } + } - // if syllable contains clef, adjust individual neumes - ListOfObjects neumes; - ClassIdComparison neumeCompare(NEUME); - element->FindAllDescendantsByComparison(&neumes, &neumeCompare); - for (auto neume = neumes.begin(); neume != neumes.end(); ++neume) { - AdjustPitchFromPosition(*neume); + ListOfObjects ncs; + ClassIdComparison ncComp(NC); + element->FindAllDescendantsByComparison(&ncs, &ncComp); + for (auto nc = ncs.begin(); nc != ncs.end(); ++nc) { + Drag((*nc)->GetID(), x, y, false); + } + } + else if (element->Is(NEUME)) { + ListOfObjects ncs; + ClassIdComparison ncComp(NC); + element->FindAllDescendantsByComparison(&ncs, &ncComp); + for (auto nc = ncs.begin(); nc != ncs.end(); ++nc) { + Drag((*nc)->GetID(), x, y, false); + } + } + else if (element->Is(NC)) { + // Don't adjust the same facsimile twice. NCs in a ligature share a single zone. + bool skipLigature = false; + Nc *nc = dynamic_cast(element); + if (nc->GetLigated() == BOOLEAN_true) { + Neume *neume = vrv_cast(nc->GetFirstAncestor(NEUME)); + Nc *nextNc = dynamic_cast(neume->GetChild(1 + neume->GetChildIndex(element))); + if (nextNc != NULL && nextNc->GetLigated() == BOOLEAN_true && nextNc->GetZone() == nc->GetZone()) { + skipLigature = true; } } - else { - AdjustPitchFromPosition(syllable); + if (!skipLigature) { + FacsimileInterface *fi = element->GetFacsimileInterface(); + assert(fi); + Zone *zone = fi->GetZone(); + assert(zone); + zone->ShiftByXY(x, -y); } - - layer->ReorderByXPos(); + AdjustPitchAfterDrag(nc, y); } else if (element->Is(CLEF)) { Clef *clef = dynamic_cast(element); @@ -653,6 +621,7 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) else { ClefMovementHandler(clef, x, y); } + m_doc->ScoreDefSetCurrentDoc(true); // this is needed for staves without clef } else if (element->Is(STAFF)) { Staff *staff = vrv_cast(element); @@ -679,9 +648,8 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) SortStaves(); - m_doc->GetDrawingPage()->LayOutTranscription(true); - if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); + m_doc->GetDrawingPage()->LayOutTranscription(true); return true; // Can't reorder by layer since staves contain layers } @@ -738,12 +706,17 @@ bool EditorToolkitNeume::Drag(std::string elementId, int x, int y) m_editInfo.import("message", "Unsupported element for dragging."); return false; } - Layer *layer = vrv_cast(element->GetFirstAncestor(LAYER)); - layer->ReorderByXPos(); // Reflect position order of elements internally (and in the resulting output file) - m_doc->GetDrawingPage()->LayOutPitchPos(); - if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); - m_editInfo.import("status", status); - m_editInfo.import("message", message); + + if (topLevel) { + Layer *layer = vrv_cast(element->GetFirstAncestor(LAYER)); + layer->ReorderByXPos(); // Reflect position order of elements internally (and in the resulting output file) + if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); + m_doc->GetDrawingPage()->LayOutTranscription(true); + + m_editInfo.import("status", status); + m_editInfo.import("message", message); + } + return true; } @@ -1075,7 +1048,7 @@ bool EditorToolkitNeume::Insert(std::string elementType, std::string staffId, in layer->ReorderByXPos(); // ensure pitched elements associated with this clef keep their x,y positions - + m_doc->ScoreDefSetCurrentDoc(true); // this is needed for staves without clef ClassIdComparison ac(CLEF); Clef *previousClef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, clef)); Clef *nextClef = dynamic_cast(m_doc->GetDrawingPage()->FindNextChild(&ac, clef)); @@ -1116,9 +1089,9 @@ bool EditorToolkitNeume::Insert(std::string elementType, std::string staffId, in uly -= noteHeight / 2; zone->SetUlx(ulx + offsetX); - zone->SetUly(uly); + zone->SetUly(uly + noteHeight); zone->SetLrx(ulx + noteWidth + offsetX); - zone->SetLry(uly + noteHeight); + zone->SetLry(uly + noteHeight * 2); layer->ReorderByXPos(); if (!AdjustPitchFromPosition(custos)) { LogError("Failed to set pitch."); @@ -1253,9 +1226,8 @@ bool EditorToolkitNeume::Insert(std::string elementType, std::string staffId, in } layer->ReorderByXPos(); - m_doc->GetDrawingPage()->LayOutTranscription(true); - if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); + m_doc->GetDrawingPage()->LayOutTranscription(true); m_editInfo.import("status", status); m_editInfo.import("message", message); @@ -2524,6 +2496,8 @@ bool EditorToolkitNeume::Resize(std::string elementId, int ulx, int uly, int lrx accidZone->SetLry(accidZone->GetLry() + int(rotationOffset)); } } + if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); + m_doc->GetDrawingPage()->LayOutTranscription(true); } else if (obj->Is(SYL)) { Syl *syl = vrv_cast(obj); @@ -2558,6 +2532,7 @@ bool EditorToolkitNeume::Resize(std::string elementId, int ulx, int uly, int lrx zone->SetRotate(rotate); } zone->Modify(); + if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); } else { LogError("Element of type '%s' is unsupported.", obj->GetClassName().c_str()); @@ -2566,8 +2541,6 @@ bool EditorToolkitNeume::Resize(std::string elementId, int ulx, int uly, int lrx return false; } - if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); - m_editInfo.import("status", "OK"); m_editInfo.import("message", ""); return true; @@ -3522,8 +3495,8 @@ bool EditorToolkitNeume::ToggleLigature(std::vector elementIds) return false; } - m_doc->GetDrawingPage()->LayOutTranscription(true); if (m_doc->IsTranscription() && m_doc->HasFacsimile()) m_doc->SyncFromFacsimileDoc(); + m_doc->GetDrawingPage()->LayOutTranscription(true); m_editInfo.import("status", "OK"); m_editInfo.import("message", ""); @@ -4200,75 +4173,80 @@ bool EditorToolkitNeume::ParseChangeStaffToAction(jsonxx::Object param, std::str return true; } -bool EditorToolkitNeume::AdjustPitchFromPosition(Object *obj, Clef *clef) +bool EditorToolkitNeume::AdjustPitchAfterDrag(Object *obj, int y) { - // remember to reorderbyxpos! (not called in function so that it can be used in loops) - // this should only be called in cases where finding the old clef is not required - // since doing it based only on clefs is much more efficient than based on position - // also if you are calling this function in a loop you should always be passing a clef argument - // since repeatedly finding the previous clef is very inefficient + if (!obj->Is(NC) && !obj->Is(CUSTOS)) { + LogError("AdjustPitchAfterDrag should only be called on custos or ncs." + "It has been called on %s, whose id is %s", + obj->GetClassName().c_str(), obj->GetID().c_str()); + return false; + } + PitchInterface *pi = obj->GetPitchInterface(); + assert(pi); + Staff *staff = dynamic_cast(obj->GetFirstAncestor(STAFF)); + const int staffSize = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + const int noteHeight = (int)(staffSize * 2 / NOTE_HEIGHT_TO_STAFF_SIZE_RATIO); + const int yOffset = y > 0 ? noteHeight / 2 : -noteHeight / 2; + const int pitchDifference = (y + yOffset) / staffSize; + pi->AdjustPitchByOffset(pitchDifference); + return true; +} - if (obj->Is(CUSTOS)) { - Custos *custos = dynamic_cast(obj); - Staff *staff = custos->GetAncestorStaff(); +bool EditorToolkitNeume::AdjustPitchFromPosition(Object *obj) +{ + if (!obj->Is(CUSTOS) && !obj->Is(SYLLABLE) && !obj->Is(NEUME)) { + LogError("AdjustPitchFromPosition should only be called on custos or syllables/neumes. Called on %s, ID: %s", + obj->GetClassName().c_str(), obj->GetID().c_str()); + return false; + } - // Check interfaces - if ((custos->GetPitchInterface() == NULL) || (custos->GetFacsimileInterface() == NULL)) { - LogError("Element is lacking an interface which is required for pitch adjusting"); - return false; - } - PitchInterface *pi = custos->GetPitchInterface(); - FacsimileInterface *fi = custos->GetFacsimileInterface(); + // Helper lambda to retrieve the clef and calculate its offset + auto getClefAndOffset = [this](Object *obj, Staff *staff, int staffSize, Clef *&clef, int &clefOffset) -> bool { + clefOffset = 0; + ClassIdComparison ac(CLEF); + clef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, obj)); - // Check for facsimile - if (!fi->HasFacs() || !staff->HasFacs()) { - LogError("Could not adjust pitch: the element or staff lacks facsimile data"); - return false; + if (!clef) { + Layer *layer = vrv_cast(staff->FindDescendantByType(LAYER)); + if (!layer) { + LogError("Unable to find layer for staff."); + return false; + } + clef = layer->GetCurrentClef(); } - - int clefOffset = 0; - if (clef == NULL) { - ClassIdComparison ac(CLEF); - clef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, obj)); - int clefOffset = 0; - if (clef == NULL) { - ClassIdComparison ac(CLEF); - clef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, obj)); - if (clef == NULL) { - Layer *layer = vrv_cast(staff->FindDescendantByType(LAYER)); - assert(layer); - clef = layer->GetCurrentClef(); - } - else { - Staff *clefStaff = dynamic_cast(clef->GetFirstAncestor(STAFF)); - assert(clefStaff); - clefOffset = round((double)(clefStaff->GetDrawingY() - - clefStaff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(clef->GetZone()->GetUlx())) - - m_view->ToLogicalY(clef->GetZone()->GetUly()))); - } + else { + Staff *clefStaff = dynamic_cast(clef->GetFirstAncestor(STAFF)); + if (!clefStaff) { + LogError("Clef is missing its parent staff."); + return false; } + clefOffset + = round((double)(clefStaff->GetDrawingY() + - clefStaff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(clef->GetZone()->GetUlx())) + - m_view->ToLogicalY(clef->GetZone()->GetUly())) + + staffSize); } + return true; + }; - data_PITCHNAME pname; - const int staffSize = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); - switch (clef->GetShape()) { - case CLEFSHAPE_C: pname = PITCHNAME_c; break; - case CLEFSHAPE_F: pname = PITCHNAME_f; break; - case CLEFSHAPE_G: pname = PITCHNAME_g; break; - default: - LogError("Clef %s does not have valid shape. Shape is %s", clef->GetID().c_str(), clef->GetShape()); - return false; + // Common logic for adjusting pitch + auto adjustPitch = [this](PitchInterface *pi, FacsimileInterface *fi, Clef *clef, int clefOffset, int staffSize, + int baseOctave, data_PITCHNAME pname, Staff *staff) { + if (!pi || !fi || !fi->HasFacs()) { + LogError("Pitch adjustment failed due to missing interfaces or facsimile data."); + return false; } + pi->SetPname(pname); - // The default octave = 4, but the actual octave is calculated by - // taking into account the displacement of the clef - int octave = 4; + // Calculate the octave based on clef displacement + int octave = baseOctave; if (clef->GetDis() && clef->GetDisPlace()) { octave += (clef->GetDisPlace() == STAFFREL_basic_above ? 1 : -1) * (clef->GetDis() / 7); } pi->SetOct(octave); + // Adjust pitch difference const int pitchDifference = round((double)((staff->GetDrawingY() - staff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(fi->GetZone()->GetUlx())) @@ -4276,90 +4254,68 @@ bool EditorToolkitNeume::AdjustPitchFromPosition(Object *obj, Clef *clef) / (double)(staffSize)); pi->AdjustPitchByOffset(-pitchDifference); return true; + }; + + Staff *staff = dynamic_cast(obj->GetFirstAncestor(STAFF)); + const int staffSize = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + if (!staff) { + LogError("Object does not have a valid parent staff."); + return false; } - else if (obj->Is(SYLLABLE) || obj->Is(NEUME)) { - Staff *staff = dynamic_cast(obj->GetFirstAncestor(STAFF)); - assert(staff); + Clef *clef = nullptr; + int clefOffset = 0; + if (!getClefAndOffset(obj, staff, staffSize, clef, clefOffset)) { + return false; + } + + data_PITCHNAME pname; + int baseOctave; + + // Determine pitch name and base octave based on clef shape + switch (clef->GetShape()) { + case CLEFSHAPE_C: + pname = PITCHNAME_c; + baseOctave = 4; + break; + case CLEFSHAPE_F: + pname = PITCHNAME_f; + baseOctave = 3; + break; + case CLEFSHAPE_G: + pname = PITCHNAME_g; + baseOctave = 4; + break; + default: + LogError("Clef %s does not have a valid shape: %s", clef->GetID().c_str(), clef->GetShape()); + return false; + } + if (obj->Is(CUSTOS)) { + return adjustPitch(obj->GetPitchInterface(), obj->GetFacsimileInterface(), clef, clefOffset, staffSize, + baseOctave, pname, staff); + } + // syllable/neume: call the adjustPitch on children + else { ListOfObjects pitchedChildren; InterfaceComparison ic(INTERFACE_PITCH); obj->FindAllDescendantsByComparison(&pitchedChildren, &ic); if (pitchedChildren.empty()) { - LogWarning("Syllable/neume had no pitched children to reorder for syllable/neume %s", obj->GetID().c_str()); + LogWarning("Syllable/neume has no pitched children: %s", obj->GetID().c_str()); return true; } - int clefOffset = 0; - if (clef == NULL) { - ClassIdComparison ac(CLEF); - clef = dynamic_cast(m_doc->GetDrawingPage()->FindPreviousChild(&ac, obj)); - if (clef == NULL) { - Layer *layer = vrv_cast(staff->FindDescendantByType(LAYER)); - assert(layer); - clef = layer->GetCurrentClef(); - } - else { - Staff *clefStaff = dynamic_cast(clef->GetFirstAncestor(STAFF)); - assert(clefStaff); - clefOffset = round((double)(clefStaff->GetDrawingY() - - clefStaff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(clef->GetZone()->GetUlx())) - - m_view->ToLogicalY(clef->GetZone()->GetUly()))); - } - } - - data_PITCHNAME pname = PITCHNAME_c; - const int staffSize = m_doc->GetDrawingUnit(staff->m_drawingStaffSize); - - switch (clef->GetShape()) { - case CLEFSHAPE_C: pname = PITCHNAME_c; break; - case CLEFSHAPE_F: pname = PITCHNAME_f; break; - case CLEFSHAPE_G: pname = PITCHNAME_g; break; - default: - LogError("Clef %s does not have valid shape. Shape is %s", clef->GetID().c_str(), clef->GetShape()); - return false; - } - - for (auto it = pitchedChildren.begin(); it != pitchedChildren.end(); ++it) { - if ((*it)->Is(LIQUESCENT)) continue; - - FacsimileInterface *fi = (*it)->GetFacsimileInterface(); - if (fi == NULL || !fi->HasFacs()) { - LogError("Could not adjust pitch: child %s does not have facsimile data", (*it)->GetID().c_str()); - return false; - } - - PitchInterface *pi = (*it)->GetPitchInterface(); - assert(pi); - pi->SetPname(pname); - - // The default octave = 4, but the actual octave is calculated by - // taking into account the displacement of the clef - int octave = 4; - if (clef->GetDis() && clef->GetDisPlace()) { - octave += (clef->GetDisPlace() == STAFFREL_basic_above ? 1 : -1) * (clef->GetDis() / 7); + for (auto *child : pitchedChildren) { + if (!child->Is(LIQUESCENT)) { + if (!adjustPitch(child->GetPitchInterface(), child->GetFacsimileInterface(), clef, clefOffset, + staffSize, baseOctave, pname, staff)) { + return false; + } } - pi->SetOct(octave); - - const int pitchDifference - = round((double)((staff->GetDrawingY() - - staff->GetDrawingRotationOffsetFor(m_view->ToLogicalX(fi->GetZone()->GetUlx())) - - m_view->ToLogicalY(fi->GetZone()->GetUly()) - clefOffset)) - / (double)(staffSize)); - - pi->AdjustPitchByOffset(-pitchDifference); } - - return true; - } - - else { - LogError("AdjustPitchFromPosition should only be called on custos or syllables." - "It has been called on %s, whose id is %s", - obj->GetClassName().c_str(), obj->GetID().c_str()); - return false; } + return true; } bool EditorToolkitNeume::AdjustClefLineFromPosition(Clef *clef, Staff *staff) diff --git a/src/fermata.cpp b/src/fermata.cpp index 830f9a4dca..34014f4004 100644 --- a/src/fermata.cpp +++ b/src/fermata.cpp @@ -29,14 +29,12 @@ static const ClassRegistrar s_factory("fermata", FERMATA); Fermata::Fermata() : ControlElement(FERMATA, "fermata-") , TimePointInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttFermataVis() , AttPlacementRelStaff() { this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_ENCLOSINGCHARS); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); @@ -53,7 +51,6 @@ void Fermata::Reset() ControlElement::Reset(); AltSymInterface::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetEnclosingChars(); this->ResetExtSymAuth(); this->ResetExtSymNames(); diff --git a/src/gliss.cpp b/src/gliss.cpp index 791030e350..e2d9c20ade 100644 --- a/src/gliss.cpp +++ b/src/gliss.cpp @@ -27,15 +27,9 @@ namespace vrv { static const ClassRegistrar s_factory("gliss", GLISS); Gliss::Gliss() - : ControlElement(GLISS, "gliss-") - , TimeSpanningInterface() - , AttColor() - , AttLineRend() - , AttLineRendBase() - , AttNNumberLike() + : ControlElement(GLISS, "gliss-"), TimeSpanningInterface(), AttLineRend(), AttLineRendBase(), AttNNumberLike() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LINEREND); this->RegisterAttClass(ATT_LINERENDBASE); this->RegisterAttClass(ATT_NNUMBERLIKE); @@ -49,7 +43,6 @@ void Gliss::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetLineRend(); this->ResetLineRendBase(); this->ResetNNumberLike(); diff --git a/src/hairpin.cpp b/src/hairpin.cpp index 56115adb49..b5f68b901e 100644 --- a/src/hairpin.cpp +++ b/src/hairpin.cpp @@ -34,14 +34,12 @@ static const ClassRegistrar s_factory("hairpin", HAIRPIN); Hairpin::Hairpin() : ControlElement(HAIRPIN, "hairpin-") , TimeSpanningInterface() - , AttColor() , AttHairpinLog() , AttHairpinVis() , AttPlacementRelStaff() , AttVerticalGroup() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_HAIRPINLOG); this->RegisterAttClass(ATT_HAIRPINVIS); this->RegisterAttClass(ATT_LINERENDBASE); @@ -57,7 +55,6 @@ void Hairpin::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetHairpinLog(); this->ResetHairpinVis(); this->ResetLineRendBase(); diff --git a/src/iohumdrum.cpp b/src/iohumdrum.cpp index 5e9e6b5b55..e4a02f50c3 100644 --- a/src/iohumdrum.cpp +++ b/src/iohumdrum.cpp @@ -8443,13 +8443,13 @@ void HumdrumInput::setInstrumentAbbreviation(ELEMENT *element, const std::string std::string name8 = name; // Substitute b and "-flat" for Unicode flat symbol: - std::regex exp1("\\b([ABDEFG])b\\b"); - std::regex exp2("\\b([A-Ga-g])-flat\\b"); + static const std::regex exp1("\\b([ABDEFG])b\\b"); + static const std::regex exp2("\\b([A-Ga-g])-flat\\b"); name8 = std::regex_replace(name8, exp1, "$1\xe2\x99\xad"); name8 = std::regex_replace(name8, exp2, "$1\xe2\x99\xad"); // Substitute # and "-sharp" for Unicode sharp symbol: - std::regex exp3("\\b([A-G])#\\b"); - std::regex exp4("\\b([A-Ga-g])-sharp\\b"); + static const std::regex exp3("\\b([A-G])#\\b"); + static const std::regex exp4("\\b([A-Ga-g])-sharp\\b"); name8 = std::regex_replace(name8, exp3, "$1\xe2\x99\xaf"); name8 = std::regex_replace(name8, exp4, "$1\xe2\x99\xaf"); diff --git a/src/iomei.cpp b/src/iomei.cpp index 5968378c37..a6a4fe2b25 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -1840,6 +1840,7 @@ void MEIOutput::WriteStaffDef(pugi::xml_node currentNode, StaffDef *staffDef) staffDef->WriteStaffDefVis(currentNode); staffDef->WriteTimeBase(currentNode); staffDef->WriteTransposition(currentNode); + staffDef->WriteVerticalAlign(currentNode); } void MEIOutput::WriteInstrDef(pugi::xml_node currentNode, InstrDef *instrDef) @@ -1950,6 +1951,7 @@ void MEIOutput::WriteControlElement(pugi::xml_node currentNode, ControlElement * this->WriteXmlId(currentNode, controlElement); this->WriteAltSymInterface(currentNode, controlElement); this->WriteLinkingInterface(currentNode, controlElement); + controlElement->WriteColor(currentNode); controlElement->WriteLabelled(currentNode); controlElement->WriteTyped(currentNode); } @@ -1971,7 +1973,6 @@ void MEIOutput::WriteArpeg(pugi::xml_node currentNode, Arpeg *arpeg) this->WriteTimePointInterface(currentNode, arpeg); arpeg->WriteArpegLog(currentNode); arpeg->WriteArpegVis(currentNode); - arpeg->WriteColor(currentNode); arpeg->WriteEnclosingChars(currentNode); } @@ -1984,7 +1985,6 @@ void MEIOutput::WriteBeamSpan(pugi::xml_node currentNode, BeamSpan *beamSpan) WriteTimeSpanningInterface(currentNode, beamSpan); beamSpan->WriteBeamedWith(currentNode); beamSpan->WriteBeamRend(currentNode); - beamSpan->WriteColor(currentNode); } void MEIOutput::WriteBracketSpan(pugi::xml_node currentNode, BracketSpan *bracketSpan) @@ -1994,7 +1994,6 @@ void MEIOutput::WriteBracketSpan(pugi::xml_node currentNode, BracketSpan *bracke this->WriteControlElement(currentNode, bracketSpan); this->WriteTimeSpanningInterface(currentNode, bracketSpan); bracketSpan->WriteBracketSpanLog(currentNode); - bracketSpan->WriteColor(currentNode); bracketSpan->WriteLineRend(currentNode); bracketSpan->WriteLineRendBase(currentNode); } @@ -2005,7 +2004,6 @@ void MEIOutput::WriteBreath(pugi::xml_node currentNode, Breath *breath) this->WriteControlElement(currentNode, breath); this->WriteTimePointInterface(currentNode, breath); - breath->WriteColor(currentNode); breath->WritePlacementRelStaff(currentNode); } @@ -2015,7 +2013,6 @@ void MEIOutput::WriteCaesura(pugi::xml_node currentNode, Caesura *caesura) this->WriteControlElement(currentNode, caesura); this->WriteTimePointInterface(currentNode, caesura); - caesura->WriteColor(currentNode); caesura->WriteExtSymAuth(currentNode); caesura->WriteExtSymNames(currentNode); caesura->WritePlacementRelStaff(currentNode); @@ -2055,7 +2052,6 @@ void MEIOutput::WriteFermata(pugi::xml_node currentNode, Fermata *fermata) this->WriteControlElement(currentNode, fermata); this->WriteTimePointInterface(currentNode, fermata); - fermata->WriteColor(currentNode); fermata->WriteEnclosingChars(currentNode); fermata->WriteExtSymAuth(currentNode); fermata->WriteExtSymNames(currentNode); @@ -2079,7 +2075,6 @@ void MEIOutput::WriteGliss(pugi::xml_node currentNode, Gliss *gliss) this->WriteControlElement(currentNode, gliss); this->WriteTimeSpanningInterface(currentNode, gliss); - gliss->WriteColor(currentNode); gliss->WriteLineRend(currentNode); gliss->WriteLineRendBase(currentNode); gliss->WriteNNumberLike(currentNode); @@ -2091,7 +2086,6 @@ void MEIOutput::WriteHairpin(pugi::xml_node currentNode, Hairpin *hairpin) this->WriteControlElement(currentNode, hairpin); this->WriteTimeSpanningInterface(currentNode, hairpin); - hairpin->WriteColor(currentNode); hairpin->WriteHairpinLog(currentNode); hairpin->WriteHairpinVis(currentNode); hairpin->WriteLineRendBase(currentNode); @@ -2116,7 +2110,6 @@ void MEIOutput::WriteLv(pugi::xml_node currentNode, Lv *lv) this->WriteControlElement(currentNode, lv); this->WriteTimeSpanningInterface(currentNode, lv); - lv->WriteColor(currentNode); lv->WriteCurvature(currentNode); lv->WriteLineRendBase(currentNode); } @@ -2128,7 +2121,6 @@ void MEIOutput::WriteMNum(pugi::xml_node currentNode, MNum *mNum) this->WriteControlElement(currentNode, mNum); this->WriteTextDirInterface(currentNode, mNum); this->WriteTimePointInterface(currentNode, mNum); - mNum->WriteColor(currentNode); mNum->WriteLang(currentNode); mNum->WriteTypography(currentNode); } @@ -2139,7 +2131,6 @@ void MEIOutput::WriteMordent(pugi::xml_node currentNode, Mordent *mordent) this->WriteControlElement(currentNode, mordent); this->WriteTimePointInterface(currentNode, mordent); - mordent->WriteColor(currentNode); mordent->WriteExtSymAuth(currentNode); mordent->WriteExtSymNames(currentNode); mordent->WriteOrnamentAccid(currentNode); @@ -2153,7 +2144,6 @@ void MEIOutput::WriteOctave(pugi::xml_node currentNode, Octave *octave) this->WriteControlElement(currentNode, octave); this->WriteTimeSpanningInterface(currentNode, octave); - octave->WriteColor(currentNode); octave->WriteExtender(currentNode); octave->WriteLineRend(currentNode); octave->WriteLineRendBase(currentNode); @@ -2168,7 +2158,6 @@ void MEIOutput::WriteOrnam(pugi::xml_node currentNode, Ornam *ornam) this->WriteControlElement(currentNode, ornam); this->WriteTextDirInterface(currentNode, ornam); this->WriteTimePointInterface(currentNode, ornam); - ornam->WriteColor(currentNode); ornam->WriteOrnamentAccid(currentNode); } @@ -2178,7 +2167,6 @@ void MEIOutput::WritePedal(pugi::xml_node currentNode, Pedal *pedal) this->WriteControlElement(currentNode, pedal); this->WriteTimeSpanningInterface(currentNode, pedal); - pedal->WriteColor(currentNode); pedal->WriteExtSymAuth(currentNode); pedal->WriteExtSymNames(currentNode); pedal->WritePedalLog(currentNode); @@ -2209,7 +2197,6 @@ void MEIOutput::WriteReh(pugi::xml_node currentNode, Reh *reh) this->WriteControlElement(currentNode, reh); this->WriteTextDirInterface(currentNode, reh); this->WriteTimePointInterface(currentNode, reh); - reh->WriteColor(currentNode); reh->WriteLang(currentNode); reh->WriteVerticalGroup(currentNode); } @@ -2221,7 +2208,6 @@ void MEIOutput::WriteRepeatMark(pugi::xml_node currentNode, RepeatMark *repeatMa this->WriteControlElement(currentNode, repeatMark); this->WriteTextDirInterface(currentNode, repeatMark); this->WriteTimePointInterface(currentNode, repeatMark); - repeatMark->WriteColor(currentNode); repeatMark->WriteExtSymAuth(currentNode); repeatMark->WriteExtSymNames(currentNode); repeatMark->WriteRepeatMarkLog(currentNode); @@ -2233,7 +2219,6 @@ void MEIOutput::WriteSlur(pugi::xml_node currentNode, Slur *slur) this->WriteControlElement(currentNode, slur); this->WriteTimeSpanningInterface(currentNode, slur); - slur->WriteColor(currentNode); slur->WriteCurvature(currentNode); slur->WriteLayerIdent(currentNode); slur->WriteLineRendBase(currentNode); @@ -2275,7 +2260,6 @@ void MEIOutput::WriteTie(pugi::xml_node currentNode, Tie *tie) this->WriteControlElement(currentNode, tie); this->WriteTimeSpanningInterface(currentNode, tie); - tie->WriteColor(currentNode); tie->WriteCurvature(currentNode); tie->WriteLineRendBase(currentNode); } @@ -2286,7 +2270,6 @@ void MEIOutput::WriteTrill(pugi::xml_node currentNode, Trill *trill) this->WriteControlElement(currentNode, trill); this->WriteTimeSpanningInterface(currentNode, trill); - trill->WriteColor(currentNode); trill->WriteExtender(currentNode); trill->WriteExtSymAuth(currentNode); trill->WriteExtSymNames(currentNode); @@ -2302,7 +2285,6 @@ void MEIOutput::WriteTurn(pugi::xml_node currentNode, Turn *turn) this->WriteControlElement(currentNode, turn); this->WriteTimePointInterface(currentNode, turn); - turn->WriteColor(currentNode); turn->WriteExtSymAuth(currentNode); turn->WriteExtSymNames(currentNode); turn->WriteOrnamentAccid(currentNode); @@ -2763,6 +2745,7 @@ void MEIOutput::WriteNote(pugi::xml_node currentNode, Note *note) assert(note); this->WriteLayerElement(currentNode, note); + this->WriteAltSymInterface(currentNode, note); this->WriteDurationInterface(currentNode, note); this->WritePitchInterface(currentNode, note); this->WritePositionInterface(currentNode, note); @@ -2823,6 +2806,7 @@ void MEIOutput::WriteRest(pugi::xml_node currentNode, Rest *rest) assert(rest); this->WriteLayerElement(currentNode, rest); + this->WriteAltSymInterface(currentNode, rest); this->WriteDurationInterface(currentNode, rest); this->WritePositionInterface(currentNode, rest); rest->WriteColor(currentNode); @@ -2856,6 +2840,7 @@ void MEIOutput::WriteTabDurSym(pugi::xml_node currentNode, TabDurSym *tabDurSym) this->WriteLayerElement(currentNode, tabDurSym); tabDurSym->WriteNNumberLike(currentNode); + tabDurSym->WriteStaffLoc(currentNode); } void MEIOutput::WriteTabGrp(pugi::xml_node currentNode, TabGrp *tabGrp) @@ -3842,6 +3827,9 @@ bool MEIInput::IsAllowed(std::string element, Object *filterParent) if (element == "note") { return true; } + if (element == "rest") { + return true; + } else { return false; } @@ -5207,6 +5195,7 @@ bool MEIInput::ReadStaffDef(Object *parent, pugi::xml_node staffDef) vrvStaffDef->ReadStaffDefVis(staffDef); vrvStaffDef->ReadTimeBase(staffDef); vrvStaffDef->ReadTransposition(staffDef); + vrvStaffDef->ReadVerticalAlign(staffDef); if (!vrvStaffDef->HasN()) { LogWarning("No @n on might yield unpredictable results"); @@ -5630,6 +5619,7 @@ bool MEIInput::ReadControlElement(pugi::xml_node element, ControlElement *object this->SetMeiID(element, object); this->ReadAltSymInterface(element, object); this->ReadLinkingInterface(element, object); + object->ReadColor(element); object->ReadLabelled(element); object->ReadTyped(element); @@ -5657,7 +5647,6 @@ bool MEIInput::ReadArpeg(Object *parent, pugi::xml_node arpeg) this->ReadTimePointInterface(arpeg, vrvArpeg); vrvArpeg->ReadArpegLog(arpeg); vrvArpeg->ReadArpegVis(arpeg); - vrvArpeg->ReadColor(arpeg); vrvArpeg->ReadEnclosingChars(arpeg); parent->AddChild(vrvArpeg); @@ -5674,7 +5663,6 @@ bool MEIInput::ReadBeamSpan(Object *parent, pugi::xml_node beamSpan) this->ReadTimeSpanningInterface(beamSpan, vrvBeamSpan); vrvBeamSpan->ReadBeamedWith(beamSpan); vrvBeamSpan->ReadBeamRend(beamSpan); - vrvBeamSpan->ReadColor(beamSpan); parent->AddChild(vrvBeamSpan); this->ReadUnsupportedAttr(beamSpan, vrvBeamSpan); @@ -5688,7 +5676,6 @@ bool MEIInput::ReadBracketSpan(Object *parent, pugi::xml_node bracketSpan) this->ReadTimeSpanningInterface(bracketSpan, vrvBracketSpan); vrvBracketSpan->ReadBracketSpanLog(bracketSpan); - vrvBracketSpan->ReadColor(bracketSpan); vrvBracketSpan->ReadLineRend(bracketSpan); vrvBracketSpan->ReadLineRendBase(bracketSpan); @@ -5703,7 +5690,6 @@ bool MEIInput::ReadBreath(Object *parent, pugi::xml_node breath) this->ReadControlElement(breath, vrvBreath); this->ReadTimePointInterface(breath, vrvBreath); - vrvBreath->ReadColor(breath); vrvBreath->ReadPlacementRelStaff(breath); parent->AddChild(vrvBreath); @@ -5717,7 +5703,6 @@ bool MEIInput::ReadCaesura(Object *parent, pugi::xml_node caesura) this->ReadControlElement(caesura, vrvCaesura); this->ReadTimePointInterface(caesura, vrvCaesura); - vrvCaesura->ReadColor(caesura); vrvCaesura->ReadExtSymAuth(caesura); vrvCaesura->ReadExtSymNames(caesura); vrvCaesura->ReadPlacementRelStaff(caesura); @@ -5769,7 +5754,6 @@ bool MEIInput::ReadFermata(Object *parent, pugi::xml_node fermata) this->ReadControlElement(fermata, vrvFermata); this->ReadTimePointInterface(fermata, vrvFermata); - vrvFermata->ReadColor(fermata); vrvFermata->ReadEnclosingChars(fermata); vrvFermata->ReadExtSymAuth(fermata); vrvFermata->ReadExtSymNames(fermata); @@ -5801,7 +5785,6 @@ bool MEIInput::ReadGliss(Object *parent, pugi::xml_node gliss) this->ReadControlElement(gliss, vrvGliss); this->ReadTimeSpanningInterface(gliss, vrvGliss); - vrvGliss->ReadColor(gliss); vrvGliss->ReadLineRend(gliss); vrvGliss->ReadLineRendBase(gliss); vrvGliss->ReadNNumberLike(gliss); @@ -5817,7 +5800,6 @@ bool MEIInput::ReadHairpin(Object *parent, pugi::xml_node hairpin) this->ReadControlElement(hairpin, vrvHairpin); this->ReadTimeSpanningInterface(hairpin, vrvHairpin); - vrvHairpin->ReadColor(hairpin); vrvHairpin->ReadHairpinLog(hairpin); vrvHairpin->ReadHairpinVis(hairpin); vrvHairpin->ReadLineRendBase(hairpin); @@ -5850,7 +5832,6 @@ bool MEIInput::ReadLv(Object *parent, pugi::xml_node lv) this->ReadControlElement(lv, vrvLv); this->ReadTimeSpanningInterface(lv, vrvLv); - vrvLv->ReadColor(lv); vrvLv->ReadCurvature(lv); vrvLv->ReadLineRendBase(lv); @@ -5866,7 +5847,6 @@ bool MEIInput::ReadMNum(Object *parent, pugi::xml_node mNum) this->ReadTextDirInterface(mNum, vrvMNum); this->ReadTimePointInterface(mNum, vrvMNum); - vrvMNum->ReadColor(mNum); vrvMNum->ReadLang(mNum); vrvMNum->ReadTypography(mNum); @@ -5884,7 +5864,6 @@ bool MEIInput::ReadMordent(Object *parent, pugi::xml_node mordent) } this->ReadTimePointInterface(mordent, vrvMordent); - vrvMordent->ReadColor(mordent); vrvMordent->ReadExtSymAuth(mordent); vrvMordent->ReadExtSymNames(mordent); vrvMordent->ReadOrnamentAccid(mordent); @@ -5902,7 +5881,6 @@ bool MEIInput::ReadOctave(Object *parent, pugi::xml_node octave) this->ReadControlElement(octave, vrvOctave); this->ReadTimeSpanningInterface(octave, vrvOctave); - vrvOctave->ReadColor(octave); vrvOctave->ReadExtender(octave); vrvOctave->ReadLineRend(octave); vrvOctave->ReadLineRendBase(octave); @@ -5921,7 +5899,6 @@ bool MEIInput::ReadOrnam(Object *parent, pugi::xml_node ornam) this->ReadTextDirInterface(ornam, vrvOrnam); this->ReadTimePointInterface(ornam, vrvOrnam); - vrvOrnam->ReadColor(ornam); vrvOrnam->ReadOrnamentAccid(ornam); parent->AddChild(vrvOrnam); @@ -5935,7 +5912,6 @@ bool MEIInput::ReadPedal(Object *parent, pugi::xml_node pedal) this->ReadControlElement(pedal, vrvPedal); this->ReadTimeSpanningInterface(pedal, vrvPedal); - vrvPedal->ReadColor(pedal); vrvPedal->ReadExtSymAuth(pedal); vrvPedal->ReadExtSymNames(pedal); vrvPedal->ReadPedalLog(pedal); @@ -5954,7 +5930,6 @@ bool MEIInput::ReadPhrase(Object *parent, pugi::xml_node phrase) this->ReadControlElement(phrase, vrvPhrase); this->ReadTimeSpanningInterface(phrase, vrvPhrase); - vrvPhrase->ReadColor(phrase); vrvPhrase->ReadCurvature(phrase); vrvPhrase->ReadLayerIdent(phrase); vrvPhrase->ReadLineRendBase(phrase); @@ -5983,7 +5958,6 @@ bool MEIInput::ReadReh(Object *parent, pugi::xml_node reh) this->ReadTextDirInterface(reh, vrvReh); this->ReadTimePointInterface(reh, vrvReh); - vrvReh->ReadColor(reh); vrvReh->ReadLang(reh); vrvReh->ReadVerticalGroup(reh); @@ -5999,7 +5973,6 @@ bool MEIInput::ReadRepeatMark(Object *parent, pugi::xml_node repeatMark) this->ReadTextDirInterface(repeatMark, vrvRepeatMark); this->ReadTimePointInterface(repeatMark, vrvRepeatMark); - vrvRepeatMark->ReadColor(repeatMark); vrvRepeatMark->ReadExtSymAuth(repeatMark); vrvRepeatMark->ReadExtSymNames(repeatMark); vrvRepeatMark->ReadRepeatMarkLog(repeatMark); @@ -6015,7 +5988,6 @@ bool MEIInput::ReadSlur(Object *parent, pugi::xml_node slur) this->ReadControlElement(slur, vrvSlur); this->ReadTimeSpanningInterface(slur, vrvSlur); - vrvSlur->ReadColor(slur); vrvSlur->ReadCurvature(slur); vrvSlur->ReadLayerIdent(slur); vrvSlur->ReadLineRendBase(slur); @@ -6048,7 +6020,6 @@ bool MEIInput::ReadTie(Object *parent, pugi::xml_node tie) this->ReadControlElement(tie, vrvTie); this->ReadTimeSpanningInterface(tie, vrvTie); - vrvTie->ReadColor(tie); vrvTie->ReadCurvature(tie); vrvTie->ReadLineRendBase(tie); @@ -6063,7 +6034,6 @@ bool MEIInput::ReadTrill(Object *parent, pugi::xml_node trill) this->ReadControlElement(trill, vrvTrill); this->ReadTimeSpanningInterface(trill, vrvTrill); - vrvTrill->ReadColor(trill); vrvTrill->ReadExtender(trill); vrvTrill->ReadExtSymAuth(trill); vrvTrill->ReadExtSymNames(trill); @@ -6087,7 +6057,6 @@ bool MEIInput::ReadTurn(Object *parent, pugi::xml_node turn) } this->ReadTimePointInterface(turn, vrvTurn); - vrvTurn->ReadColor(turn); vrvTurn->ReadExtSymAuth(turn); vrvTurn->ReadExtSymNames(turn); vrvTurn->ReadOrnamentAccid(turn); @@ -6967,6 +6936,7 @@ bool MEIInput::ReadNote(Object *parent, pugi::xml_node note) } } + this->ReadAltSymInterface(note, vrvNote); this->ReadDurationInterface(note, vrvNote); this->ReadPitchInterface(note, vrvNote); this->ReadPositionInterface(note, vrvNote); @@ -7021,6 +6991,7 @@ bool MEIInput::ReadRest(Object *parent, pugi::xml_node rest) } } + this->ReadAltSymInterface(rest, vrvRest); this->ReadDurationInterface(rest, vrvRest); this->ReadPositionInterface(rest, vrvRest); vrvRest->ReadColor(rest); @@ -7150,6 +7121,7 @@ bool MEIInput::ReadTabDurSym(Object *parent, pugi::xml_node tabRhyhtm) this->ReadLayerElement(tabRhyhtm, vrvTabDurSym); vrvTabDurSym->ReadNNumberLike(tabRhyhtm); + vrvTabDurSym->ReadStaffLoc(tabRhyhtm); parent->AddChild(vrvTabDurSym); this->ReadUnsupportedAttr(tabRhyhtm, vrvTabDurSym); @@ -7287,6 +7259,9 @@ bool MEIInput::ReadSymbolDefChildren(Object *parent, pugi::xml_node parentNode, else if (elementName == "svg") { success = this->ReadSvg(parent, xmlElement); } + else if (elementName == "symbol") { + success = this->ReadSymbol(parent, xmlElement); + } // xml comment else if (elementName == "") { success = this->ReadXMLComment(parent, xmlElement); diff --git a/src/iomusxml.cpp b/src/iomusxml.cpp index 86cb54613d..eb9d68fb6d 100644 --- a/src/iomusxml.cpp +++ b/src/iomusxml.cpp @@ -1796,8 +1796,7 @@ void MusicXmlInput::ReadMusicXmlAttributes( } // read clef changes as MEI clef and add them to the stack - pugi::xml_node clef = node.child("clef"); - if (clef) { + for (pugi::xml_node clef : node.children("clef")) { // check if we have a staff number short int staffNum = clef.attribute("number").as_int(); staffNum = (staffNum < 1) ? 1 : staffNum; @@ -3051,9 +3050,9 @@ void MusicXmlInput::ReadMusicXmlNote( std::string textStr = childNode.text().as_string(); // convert verse numbers to labels - std::regex labelSearch("^([^[:alpha:]]*\\d[^[:alpha:]]*)$"); + static const std::regex labelSearch("^([^[:alpha:]]*\\d[^[:alpha:]]*)$"); std::smatch labelSearchMatches; - std::regex labelPrefixSearch("^([^[:alpha:]]*\\d[^[:alpha:]]*)[\\s\\u00A0]+"); + static const std::regex labelPrefixSearch("^([^[:alpha:]]*\\d[^[:alpha:]]*)[\\s\\u00A0]+"); std::smatch labelPrefixSearchMatches; if (!textStr.empty() && std::regex_search(textStr, labelSearchMatches, labelSearch) && labelSearchMatches.ready() && childNode.next_sibling("elision")) { diff --git a/src/iopae.cpp b/src/iopae.cpp index 75431ad881..d5dcfc412d 100644 --- a/src/iopae.cpp +++ b/src/iopae.cpp @@ -1249,7 +1249,7 @@ int PAEInput::getTupletFermata(const char *incipit, pae::Note *note, int index) // std::regex_constants::ECMAScript is the default syntax, so optional. // Previously these were extended regex syntax, but this case // is the same in ECMAScript syntax. - std::regex exp("^([^)]*[ABCDEFG-][^)]*[ABCDEFG-][^)]*)", std::regex_constants::ECMAScript); + static const std::regex exp("^([^)]*[ABCDEFG-][^)]*[ABCDEFG-][^)]*)", std::regex_constants::ECMAScript); bool is_tuplet = regex_search(incipit + i, exp); if (is_tuplet) { diff --git a/src/mnum.cpp b/src/mnum.cpp index a98a5ec5d5..6c19384fa6 100644 --- a/src/mnum.cpp +++ b/src/mnum.cpp @@ -30,13 +30,11 @@ MNum::MNum() , TextListInterface() , TextDirInterface() , TimePointInterface() - , AttColor() , AttLang() , AttTypography() { this->RegisterInterface(TextDirInterface::GetAttClasses(), TextDirInterface::IsInterface()); this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LANG); this->RegisterAttClass(ATT_TYPOGRAPHY); @@ -50,7 +48,6 @@ void MNum::Reset() ControlElement::Reset(); TextDirInterface::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetLang(); this->ResetTypography(); diff --git a/src/mordent.cpp b/src/mordent.cpp index ac42882eef..f846216424 100644 --- a/src/mordent.cpp +++ b/src/mordent.cpp @@ -29,7 +29,6 @@ static const ClassRegistrar s_factory("mordent", MORDENT); Mordent::Mordent() : ControlElement(MORDENT, "mordent-") , TimePointInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttOrnamentAccid() @@ -37,7 +36,6 @@ Mordent::Mordent() , AttMordentLog() { this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); this->RegisterAttClass(ATT_ORNAMENTACCID); @@ -53,7 +51,6 @@ void Mordent::Reset() { ControlElement::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetExtSymAuth(); this->ResetExtSymNames(); this->ResetOrnamentAccid(); diff --git a/src/note.cpp b/src/note.cpp index f0bd536eca..3af77d8737 100644 --- a/src/note.cpp +++ b/src/note.cpp @@ -31,6 +31,7 @@ #include "staff.h" #include "stem.h" #include "syl.h" +#include "symboldef.h" #include "tabgrp.h" #include "tie.h" #include "tuning.h" @@ -52,6 +53,7 @@ static const ClassRegistrar s_factory("note", NOTE); Note::Note() : LayerElement(NOTE, "note-") , StemmedDrawingInterface() + , AltSymInterface() , DurationInterface() , PitchInterface() , PositionInterface() @@ -71,6 +73,7 @@ Note::Note() , AttTiePresent() , AttVisibility() { + this->RegisterInterface(AltSymInterface::GetAttClasses(), AltSymInterface::IsInterface()); this->RegisterInterface(DurationInterface::GetAttClasses(), DurationInterface::IsInterface()); this->RegisterInterface(PitchInterface::GetAttClasses(), PitchInterface::IsInterface()); this->RegisterInterface(PositionInterface::GetAttClasses(), PositionInterface::IsInterface()); @@ -99,6 +102,7 @@ void Note::Reset() { LayerElement::Reset(); StemmedDrawingInterface::Reset(); + AltSymInterface::Reset(); DurationInterface::Reset(); PitchInterface::Reset(); PositionInterface::Reset(); @@ -251,25 +255,78 @@ const TabGrp *Note::IsTabGrpNote() const return vrv_cast(this->GetFirstAncestor(TABGRP, MAX_TABGRP_DEPTH)); } -std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType) const +std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType, int &overline, int &strike, int &underline) const { + overline = 0; + strike = 0; + underline = 0; + + // @glyph.num, @glyph.name or @altsym + const Resources *resources = this->GetDocResources(); + if (resources != NULL) { + std::u32string fretStr; + // If there is @glyph.num, return glyph based on it (first priority) + if (this->HasGlyphNum()) { + const char32_t code = this->GetGlyphNum(); + if (NULL != resources->GetGlyph(code)) fretStr.push_back(code); + } + + // If there is @glyph.name (second priority) + else if (this->HasGlyphName()) { + const char32_t code = resources->GetGlyphCode(this->GetGlyphName()); + if (NULL != resources->GetGlyph(code)) fretStr.push_back(code); + } + + // If there is @altsym (third priority) + else if (this->HasAltsym() && this->HasAltSymbolDef()) { + const SymbolDef *symbolDef = this->GetAltSymbolDef(); + + // there may be more than one + for (const Object *child : symbolDef->GetChildren()) { + if (child->Is(SYMBOL)) { + const Symbol *symbol = vrv_cast(child); + + // If there is @glyph.num, return glyph based on it (fourth priority) + if (symbol->HasGlyphNum()) { + const char32_t code = symbol->GetGlyphNum(); + if (NULL != resources->GetGlyph(code)) fretStr.push_back(code); + } + + // If there is @glyph.name (fifth priority) + else if (symbol->HasGlyphName()) { + const char32_t code = resources->GetGlyphCode(symbol->GetGlyphName()); + if (NULL != resources->GetGlyph(code)) fretStr.push_back(code); + } + } + } + } + + if (!fretStr.empty()) return fretStr; + } + if (notationType == NOTATIONTYPE_tab_lute_italian) { std::u32string fretStr; - int fret = this->GetTabFret(); - // Maximum allowed would be 19 (always bindly addind 1 as first figure) - if (fret > 9) fretStr.push_back(SMUFL_EBE1_luteItalianFret1); - switch (fret % 10) { - case 0: fretStr.push_back(SMUFL_EBE0_luteItalianFret0); break; - case 1: fretStr.push_back(SMUFL_EBE1_luteItalianFret1); break; - case 2: fretStr.push_back(SMUFL_EBE2_luteItalianFret2); break; - case 3: fretStr.push_back(SMUFL_EBE3_luteItalianFret3); break; - case 4: fretStr.push_back(SMUFL_EBE4_luteItalianFret4); break; - case 5: fretStr.push_back(SMUFL_EBE5_luteItalianFret5); break; - case 6: fretStr.push_back(SMUFL_EBE6_luteItalianFret6); break; - case 7: fretStr.push_back(SMUFL_EBE7_luteItalianFret7); break; - case 8: fretStr.push_back(SMUFL_EBE8_luteItalianFret8); break; - case 9: fretStr.push_back(SMUFL_EBE9_luteItalianFret9); break; - default: break; + const int fret = this->GetTabFret(); + const int course = this->GetTabCourse(); + + // Italian tablature glyphs are contiguous + static_assert(SMUFL_EBE1_luteItalianFret1 == SMUFL_EBE0_luteItalianFret0 + 1); + static_assert(SMUFL_EBE2_luteItalianFret2 == SMUFL_EBE0_luteItalianFret0 + 2); + // ... + static_assert(SMUFL_EBE9_luteItalianFret9 == SMUFL_EBE0_luteItalianFret0 + 9); + + if (course <= 7 || fret != 0) { + const auto decimal = std::div(fret, 10); + if (decimal.quot > 0) fretStr.push_back(SMUFL_EBE0_luteItalianFret0 + decimal.quot); + if (decimal.rem <= 9) fretStr.push_back(SMUFL_EBE0_luteItalianFret0 + decimal.rem); + if (course >= 7) strike = 1; // course 7 and fretted courses >= 8 use a ledger line + underline = std::max(0, course - 7); // compressed ledger lines for fretted courses >= 8 + } + else { + // open courses >= 8 just use the number of the course on stave line 7 + const auto decimal = std::div(course, 10); + if (decimal.quot > 0) fretStr.push_back(SMUFL_EBE0_luteItalianFret0 + decimal.quot); + if (decimal.rem <= 9) fretStr.push_back(SMUFL_EBE0_luteItalianFret0 + decimal.rem); } return fretStr; } @@ -320,6 +377,75 @@ std::u32string Note::GetTabFretString(data_NOTATIONTYPE notationType) const } return fretStr; } + else if (notationType == NOTATIONTYPE_tab_lute_german) { + std::u32string fretStr; + const int fret = this->GetTabFret(); + const int course = this->GetTabCourse(); + + // SMuFL has glyphs for German lute tablature following Hans and Melchior Newsidler's notation + // for the >= 6th courses. + // "German Renaissance lute tablature (U+EC00–U+EC2F)" + // https://w3c.github.io/smufl/latest/tables/german-renaissance-lute-tablature.html + // + // However, some glyphs are missing: + // + // Digit 1 with a strike through for the open 6th course. + // Digit 1 with two strike throughs for the open 7th course. + // Digit 1 with three strike throughs for the open 8th course. + // "et" for 2nd course 5th fret. + // "con" for 1st course 5th fret. + // Gothic font digits 1-5 for the open courses <= 5. + // Second lowercase alphabet with an overline used for courses <= 5 frets 6 to 10. + // + // To overcome these omissions I've substituted missing glyphs from other + // parts of the SMuFL collection. Overlines and strike throughs are drawn separately. + + if (course >= 6 && fret >= 0 && fret <= 13) { + // + A B C D ... + if (fret == 0) { + fretStr = SMUFL_EA51_figbass1; // substitute for 1 with oblique stroke + strike = course - 5; // 6 course 1 strike, 7 course 2 strikes, ... + } + else { + // The German tablature uppercase letters A-N are contiguous, correctly omitting J + static_assert(SMUFL_EC23_luteGermanNUpper == SMUFL_EC17_luteGermanAUpper + 13 - 1); + fretStr = SMUFL_EC17_luteGermanAUpper + fret - 1; + overline = course - 6; // 6 course 0 overline, 7 course 1 overline, ... + } + } + else if (course >= 1 && course <= 5 && fret == 0) { + // Substitute for gothic digits + static const char32_t digit[] = { SMUFL_EA51_figbass1, SMUFL_EA52_figbass2, SMUFL_EA54_figbass3, + SMUFL_EA55_figbass4, SMUFL_EA57_figbass5 }; + fretStr = digit[5 - course]; + } + else if (course >= 1 && course <= 5 && fret >= 0 && fret <= 10) { + const int firstAlphabetFret = fret <= 5 ? fret : fret - 5; // map second alphabet to first + + if (course == 2 && firstAlphabetFret == 5) { + // TODO replace with U+EC24, luteGermanEt when available + // https://github.com/w3c/smufl/issues/274 + fretStr = SMUFL_EA5F_figbass7Raised2; // substitute for "et" + } + else if (course == 1 && firstAlphabetFret == 5) { + // TODO replace with U+EC25, luteGermanCon when available + // https://github.com/w3c/smufl/issues/274 + fretStr = SMUFL_EA61_figbass9; // substitute for "con" + } + else { + // The German tablature lowercase letters a-z are contiguous, correctly omitting j u w + static_assert(SMUFL_EC16_luteGermanZLower == SMUFL_EC00_luteGermanALower + 23 - 1); + + // lowercase letters run 5th to 1st course, frets 1 to 5 + // and frets 6 to 10 with an overline + fretStr = SMUFL_EC00_luteGermanALower + (5 - course) + (firstAlphabetFret - 1) * 5; + } + + // second alphabet needs an overline + overline = (fret >= 6) ? 1 : 0; + } + return fretStr; + } else { std::string str = StringFormat("%d", this->GetTabFret()); return UTF8to32(str); diff --git a/src/octave.cpp b/src/octave.cpp index db7af715bc..834750f8af 100644 --- a/src/octave.cpp +++ b/src/octave.cpp @@ -29,7 +29,6 @@ static const ClassRegistrar s_factory("octave", OCTAVE); Octave::Octave() : ControlElement(OCTAVE, "octave-") , TimeSpanningInterface() - , AttColor() , AttExtender() , AttLineRend() , AttLineRendBase() @@ -37,7 +36,6 @@ Octave::Octave() , AttOctaveDisplacement() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTENDER); this->RegisterAttClass(ATT_LINEREND); this->RegisterAttClass(ATT_LINERENDBASE); @@ -53,7 +51,6 @@ void Octave::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetExtender(); this->ResetLineRend(); this->ResetLineRendBase(); diff --git a/src/ornam.cpp b/src/ornam.cpp index 89ec050612..d53f114ce5 100644 --- a/src/ornam.cpp +++ b/src/ornam.cpp @@ -30,16 +30,10 @@ namespace vrv { static const ClassRegistrar s_factory("ornam", ORNAM); Ornam::Ornam() - : ControlElement(ORNAM, "ornam-") - , TextListInterface() - , TextDirInterface() - , TimePointInterface() - , AttColor() - , AttOrnamentAccid() + : ControlElement(ORNAM, "ornam-"), TextListInterface(), TextDirInterface(), TimePointInterface(), AttOrnamentAccid() { this->RegisterInterface(TextDirInterface::GetAttClasses(), TextDirInterface::IsInterface()); this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_ORNAMENTACCID); this->Reset(); @@ -52,7 +46,6 @@ void Ornam::Reset() ControlElement::Reset(); TextDirInterface::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetOrnamentAccid(); } diff --git a/src/pedal.cpp b/src/pedal.cpp index 79a162cc67..5438f314a5 100644 --- a/src/pedal.cpp +++ b/src/pedal.cpp @@ -37,7 +37,6 @@ static const ClassRegistrar s_factory("pedal", PEDAL); Pedal::Pedal() : ControlElement(PEDAL, "pedal-") , TimeSpanningInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttPedalLog() @@ -46,7 +45,6 @@ Pedal::Pedal() , AttVerticalGroup() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); this->RegisterAttClass(ATT_PEDALLOG); @@ -63,7 +61,6 @@ void Pedal::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetExtSymAuth(); this->ResetExtSymNames(); this->ResetPedalLog(); diff --git a/src/positioninterface.cpp b/src/positioninterface.cpp index d3bf0abed6..0a20079ba1 100644 --- a/src/positioninterface.cpp +++ b/src/positioninterface.cpp @@ -76,6 +76,17 @@ bool PositionInterface::HasLedgerLines(int &linesAbove, int &linesBelow, const S { if (!staff) return false; + if (staff->IsTabLuteFrench() || staff->IsTabLuteGerman() || staff->IsTabLuteItalian()) { + // French and German tablature do not use ledger lines. + // Italian tablature does use a single ledger line for 7th course, and compressed + // ledger lines for fretted 8th and above, but not for open 8th and above. So + // rather than use the CMN ledger line handling we draw our own. + // Guitar tablature has been left as originally implemented. + linesAbove = 0; + linesBelow = 0; + return false; + } + linesAbove = (this->GetDrawingLoc() - staff->m_drawingLines * 2 + 2) / 2; linesBelow = -(this->GetDrawingLoc()) / 2; diff --git a/src/reh.cpp b/src/reh.cpp index 90bf6643ad..6627775701 100644 --- a/src/reh.cpp +++ b/src/reh.cpp @@ -28,12 +28,10 @@ namespace vrv { static const ClassRegistrar s_factory("reh", REH); -Reh::Reh() - : ControlElement(REH, "reh-"), TextDirInterface(), TimePointInterface(), AttColor(), AttLang(), AttVerticalGroup() +Reh::Reh() : ControlElement(REH, "reh-"), TextDirInterface(), TimePointInterface(), AttLang(), AttVerticalGroup() { this->RegisterInterface(TextDirInterface::GetAttClasses(), TextDirInterface::IsInterface()); this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_LANG); this->RegisterAttClass(ATT_VERTICALGROUP); @@ -47,7 +45,6 @@ void Reh::Reset() ControlElement::Reset(); TextDirInterface::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetLang(); this->ResetVerticalGroup(); } diff --git a/src/repeatmark.cpp b/src/repeatmark.cpp index 02d4fa6df0..0f662d9476 100644 --- a/src/repeatmark.cpp +++ b/src/repeatmark.cpp @@ -34,14 +34,12 @@ RepeatMark::RepeatMark() , TextListInterface() , TextDirInterface() , TimePointInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttRepeatMarkLog() { this->RegisterInterface(TextDirInterface::GetAttClasses(), TextDirInterface::IsInterface()); this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); this->RegisterAttClass(ATT_REPEATMARKLOG); @@ -56,7 +54,6 @@ void RepeatMark::Reset() ControlElement::Reset(); TextDirInterface::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetExtSymAuth(); this->ResetExtSymNames(); this->ResetRepeatMarkLog(); diff --git a/src/rest.cpp b/src/rest.cpp index 7e622d604d..477f707d08 100644 --- a/src/rest.cpp +++ b/src/rest.cpp @@ -22,6 +22,7 @@ #include "layer.h" #include "smufl.h" #include "staff.h" +#include "symboldef.h" #include "system.h" #include "transposition.h" #include "vrv.h" @@ -171,6 +172,7 @@ static const ClassRegistrar s_factory("rest", REST); Rest::Rest() : LayerElement(REST, "rest-") + , AltSymInterface() , DurationInterface() , PositionInterface() , AttColor() @@ -179,6 +181,7 @@ Rest::Rest() , AttExtSymNames() , AttRestVisMensural() { + this->RegisterInterface(AltSymInterface::GetAttClasses(), AltSymInterface::IsInterface()); this->RegisterInterface(DurationInterface::GetAttClasses(), DurationInterface::IsInterface()); this->RegisterInterface(PositionInterface::GetAttClasses(), PositionInterface::IsInterface()); this->RegisterAttClass(ATT_COLOR); @@ -194,6 +197,7 @@ Rest::~Rest() {} void Rest::Reset() { LayerElement::Reset(); + AltSymInterface::Reset(); DurationInterface::Reset(); PositionInterface::Reset(); this->ResetColor(); @@ -259,6 +263,23 @@ char32_t Rest::GetRestGlyph(const data_DURATION duration) const char32_t code = resources->GetGlyphCode(this->GetGlyphName()); if (NULL != resources->GetGlyph(code)) return code; } + // If there is @altsym (third priority) + else if (this->HasAltsym() && this->HasAltSymbolDef()) { + const SymbolDef *symbolDef = this->GetAltSymbolDef(); + const Symbol *symbol = vrv_cast(symbolDef->GetFirst(SYMBOL)); + if (symbol != NULL) { + // If there is @glyph.num, return glyph based on it (fourth priority) + if (symbol->HasGlyphNum()) { + const char32_t code = symbol->GetGlyphNum(); + if (NULL != resources->GetGlyph(code)) return code; + } + // If there is @glyph.name (fifth priority) + else if (symbol->HasGlyphName()) { + const char32_t code = resources->GetGlyphCode(symbol->GetGlyphName()); + if (NULL != resources->GetGlyph(code)) return code; + } + } + } if (this->IsMensuralDur()) { switch (duration) { diff --git a/src/slur.cpp b/src/slur.cpp index 5250e5ef56..830e11835e 100644 --- a/src/slur.cpp +++ b/src/slur.cpp @@ -41,15 +41,9 @@ namespace vrv { static const ClassRegistrar s_factory("slur", SLUR); Slur::Slur() - : ControlElement(SLUR, "slur-") - , TimeSpanningInterface() - , AttColor() - , AttCurvature() - , AttLayerIdent() - , AttLineRendBase() + : ControlElement(SLUR, "slur-"), TimeSpanningInterface(), AttCurvature(), AttLayerIdent(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LAYERIDENT); this->RegisterAttClass(ATT_LINERENDBASE); @@ -58,15 +52,9 @@ Slur::Slur() } Slur::Slur(ClassId classId) - : ControlElement(classId, "slur-") - , TimeSpanningInterface() - , AttColor() - , AttCurvature() - , AttLayerIdent() - , AttLineRendBase() + : ControlElement(classId, "slur-"), TimeSpanningInterface(), AttCurvature(), AttLayerIdent(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LAYERIDENT); this->RegisterAttClass(ATT_LINERENDBASE); @@ -75,15 +63,9 @@ Slur::Slur(ClassId classId) } Slur::Slur(ClassId classId, const std::string &classIdStr) - : ControlElement(classId, classIdStr) - , TimeSpanningInterface() - , AttColor() - , AttCurvature() - , AttLayerIdent() - , AttLineRendBase() + : ControlElement(classId, classIdStr), TimeSpanningInterface(), AttCurvature(), AttLayerIdent(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LAYERIDENT); this->RegisterAttClass(ATT_LINERENDBASE); @@ -97,7 +79,6 @@ void Slur::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetCurvature(); this->ResetLayerIdent(); this->ResetLineRendBase(); diff --git a/src/staff.cpp b/src/staff.cpp index 26de629c67..4d1188afb3 100644 --- a/src/staff.cpp +++ b/src/staff.cpp @@ -186,6 +186,8 @@ void Staff::AdjustDrawingStaffSize() int Staff::GetDrawingStaffNotationSize() const { + if (this->IsTabLuteGerman()) return m_drawingStaffSize / GERMAN_TAB_STAFF_RATIO; + return (this->IsTablature()) ? m_drawingStaffSize / TABLATURE_STAFF_RATIO : m_drawingStaffSize; } diff --git a/src/staffdef.cpp b/src/staffdef.cpp index 5a86e2a6c4..5d55f3c8f8 100644 --- a/src/staffdef.cpp +++ b/src/staffdef.cpp @@ -42,6 +42,7 @@ StaffDef::StaffDef() , AttStaffDefVis() , AttTimeBase() , AttTransposition() + , AttVerticalAlign() { this->RegisterAttClass(ATT_DISTANCES); this->RegisterAttClass(ATT_LABELLED); @@ -52,6 +53,7 @@ StaffDef::StaffDef() this->RegisterAttClass(ATT_STAFFDEFVIS); this->RegisterAttClass(ATT_TIMEBASE); this->RegisterAttClass(ATT_TRANSPOSITION); + this->RegisterAttClass(ATT_VERTICALALIGN); this->Reset(); } @@ -71,6 +73,7 @@ void StaffDef::Reset() this->ResetStaffDefVis(); this->ResetTimeBase(); this->ResetTransposition(); + this->ResetVerticalAlign(); m_drawingVisibility = OPTIMIZATION_NONE; } diff --git a/src/symboldef.cpp b/src/symboldef.cpp index a0fe1d66c7..eb58a10fcd 100644 --- a/src/symboldef.cpp +++ b/src/symboldef.cpp @@ -16,6 +16,7 @@ #include "doc.h" #include "graphic.h" #include "svg.h" +#include "symbol.h" #include "vrv.h" namespace vrv { @@ -48,6 +49,9 @@ bool SymbolDef::IsSupportedChild(Object *child) else if (child->Is(SVG)) { assert(dynamic_cast(child)); } + else if (child->Is(SYMBOL)) { + assert(dynamic_cast(child)); + } else { return false; } diff --git a/src/tabdursym.cpp b/src/tabdursym.cpp index 21d03c05f6..2bb64949d1 100644 --- a/src/tabdursym.cpp +++ b/src/tabdursym.cpp @@ -31,9 +31,11 @@ namespace vrv { static const ClassRegistrar s_factory("tabDurSym", TABDURSYM); -TabDurSym::TabDurSym() : LayerElement(TABDURSYM, "tabdursym-"), StemmedDrawingInterface(), AttNNumberLike() +TabDurSym::TabDurSym() + : LayerElement(TABDURSYM, "tabdursym-"), StemmedDrawingInterface(), AttNNumberLike(), AttStaffLoc() { this->RegisterAttClass(ATT_NNUMBERLIKE); + this->RegisterAttClass(ATT_STAFFLOC); this->Reset(); } @@ -45,6 +47,7 @@ void TabDurSym::Reset() LayerElement::Reset(); StemmedDrawingInterface::Reset(); this->ResetNNumberLike(); + this->ResetStaffLoc(); } bool TabDurSym::IsSupportedChild(Object *child) @@ -89,7 +92,7 @@ void TabDurSym::AdjustDrawingYRel(const Staff *staff, const Doc *doc) // For stems outside add a margin to the tabDurSym - otherwise attached to the staff line if (staff->IsTabWithStemsOutside()) { - double spacingRatio = (staff->IsTabLuteFrench()) ? 2.0 : 1.0; + double spacingRatio = (staff->IsTabLuteFrench() || staff->IsTabLuteGerman()) ? 2.0 : 1.0; yRel += doc->GetDrawingUnit(staff->m_drawingStaffSize) * spacingRatio; } @@ -116,8 +119,11 @@ int TabDurSym::CalcStemLenInThirdUnits(const Staff *staff, data_STEMDIRECTION st int baseStem = STANDARD_STEMLENGTH_TAB * 3; + // Shorter for german lute tablature to match ryhthm glyphs + if (staff->IsTabLuteGerman()) baseStem -= 3; // One unit longer for guitar tablature - if (staff->IsTabGuitar()) baseStem += 3; + else if (staff->IsTabGuitar()) + baseStem += 3; // One unit longer for stems inside the staff if (!staff->IsTabWithStemsOutside()) baseStem += 3; diff --git a/src/tabgrp.cpp b/src/tabgrp.cpp index 72436718d3..d9b668b073 100644 --- a/src/tabgrp.cpp +++ b/src/tabgrp.cpp @@ -16,6 +16,7 @@ #include "editorial.h" #include "functor.h" #include "note.h" +#include "rest.h" #include "tabdursym.h" namespace vrv { @@ -46,6 +47,9 @@ bool TabGrp::IsSupportedChild(Object *child) if (child->Is(NOTE)) { assert(dynamic_cast(child)); } + else if (child->Is(REST)) { + assert(dynamic_cast(child)); + } else if (child->Is(TABDURSYM)) { assert(dynamic_cast(child)); } diff --git a/src/tie.cpp b/src/tie.cpp index d66e942061..3469b28506 100644 --- a/src/tie.cpp +++ b/src/tie.cpp @@ -34,21 +34,18 @@ namespace vrv { static const ClassRegistrar s_factory("tie", TIE); -Tie::Tie() : ControlElement(TIE, "tie-"), TimeSpanningInterface(), AttColor(), AttCurvature(), AttLineRendBase() +Tie::Tie() : ControlElement(TIE, "tie-"), TimeSpanningInterface(), AttCurvature(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LINERENDBASE); this->Reset(); } -Tie::Tie(ClassId classId) - : ControlElement(classId, "tie-"), TimeSpanningInterface(), AttColor(), AttCurvature(), AttLineRendBase() +Tie::Tie(ClassId classId) : ControlElement(classId, "tie-"), TimeSpanningInterface(), AttCurvature(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LINERENDBASE); @@ -56,10 +53,9 @@ Tie::Tie(ClassId classId) } Tie::Tie(ClassId classId, const std::string &classIdStr) - : ControlElement(classId, classIdStr), TimeSpanningInterface(), AttColor(), AttCurvature(), AttLineRendBase() + : ControlElement(classId, classIdStr), TimeSpanningInterface(), AttCurvature(), AttLineRendBase() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_CURVATURE); this->RegisterAttClass(ATT_LINERENDBASE); @@ -72,7 +68,6 @@ void Tie::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetCurvature(); this->ResetLineRendBase(); } diff --git a/src/trill.cpp b/src/trill.cpp index 8d6b762ff3..418bb1cde6 100644 --- a/src/trill.cpp +++ b/src/trill.cpp @@ -29,7 +29,6 @@ static const ClassRegistrar s_factory("trill", TRILL); Trill::Trill() : ControlElement(TRILL, "trill-") , TimeSpanningInterface() - , AttColor() , AttExtender() , AttExtSymAuth() , AttExtSymNames() @@ -39,7 +38,6 @@ Trill::Trill() , AttPlacementRelStaff() { this->RegisterInterface(TimeSpanningInterface::GetAttClasses(), TimeSpanningInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTENDER); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); @@ -57,7 +55,6 @@ void Trill::Reset() { ControlElement::Reset(); TimeSpanningInterface::Reset(); - this->ResetColor(); this->ResetExtender(); this->ResetExtSymAuth(); this->ResetExtSymNames(); diff --git a/src/tuning.cpp b/src/tuning.cpp index 7ebbdc1e4b..1dde76662f 100644 --- a/src/tuning.cpp +++ b/src/tuning.cpp @@ -56,13 +56,27 @@ bool Tuning::IsSupportedChild(Object *child) return true; } -int Tuning::CalcPitchPos(int course, data_NOTATIONTYPE notationType, int lines) const +int Tuning::CalcPitchPos( + int course, data_NOTATIONTYPE notationType, int lines, int listSize, int index, int loc, bool topAlign) const { switch (notationType) { case NOTATIONTYPE_tab_lute_french: // all courses >= 7 are positioned above line 0 return (lines - std::min(course, 7)) * 2 + 1; // above the line - case NOTATIONTYPE_tab_lute_italian: return (course - 1) * 2; + case NOTATIONTYPE_tab_lute_italian: + // all courses >= 7 are positioned on line 7 + return (std::min(course, 7) - 1) * 2; + case NOTATIONTYPE_tab_lute_german: + if (loc != MEI_UNSET) { + return loc; + } + else if (topAlign) { + return (lines - (listSize - index)) * 2; + } + else { + // bottom align + return index * 2; + } case NOTATIONTYPE_tab_guitar: [[fallthrough]]; default: return abs(course - lines) * 2; } diff --git a/src/turn.cpp b/src/turn.cpp index 15797caa73..8c6c1b3e2e 100644 --- a/src/turn.cpp +++ b/src/turn.cpp @@ -31,7 +31,6 @@ static const ClassRegistrar s_factory("turn", TURN); Turn::Turn() : ControlElement(TURN, "turn-") , TimePointInterface() - , AttColor() , AttExtSymAuth() , AttExtSymNames() , AttOrnamentAccid() @@ -39,7 +38,6 @@ Turn::Turn() , AttTurnLog() { this->RegisterInterface(TimePointInterface::GetAttClasses(), TimePointInterface::IsInterface()); - this->RegisterAttClass(ATT_COLOR); this->RegisterAttClass(ATT_EXTSYMAUTH); this->RegisterAttClass(ATT_EXTSYMNAMES); this->RegisterAttClass(ATT_ORNAMENTACCID); @@ -55,7 +53,6 @@ void Turn::Reset() { ControlElement::Reset(); TimePointInterface::Reset(); - this->ResetColor(); this->ResetExtSymAuth(); this->ResetExtSymNames(); this->ResetOrnamentAccid(); diff --git a/src/view_beam.cpp b/src/view_beam.cpp index 046e24e190..1673c5d82a 100644 --- a/src/view_beam.cpp +++ b/src/view_beam.cpp @@ -292,7 +292,7 @@ void View::DrawBeamSegment( data_DURATION durRef = DURATION_8; data_DURATION durRef2 = DURATION_16; - if (staff->IsTabLuteFrench() || staff->IsTabLuteItalian()) { + if (staff->IsTabLuteFrench() || staff->IsTabLuteGerman() || staff->IsTabLuteItalian()) { durRef = DURATION_4; durRef2 = DURATION_8; } diff --git a/src/view_element.cpp b/src/view_element.cpp index c4166e20b9..cad7563ea2 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -53,6 +53,7 @@ #include "stem.h" #include "syl.h" #include "system.h" +#include "tabgrp.h" #include "tie.h" #include "tuplet.h" #include "verse.h" @@ -1538,12 +1539,17 @@ void View::DrawRest(DeviceContext *dc, LayerElement *element, Layer *layer, Staf const bool drawingCueSize = rest->GetDrawingCueSize(); const int staffSize = staff->GetDrawingStaffNotationSize(); data_DURATION drawingDur = rest->GetActualDur(); - if (drawingDur == DURATION_NONE) { - if (!dc->Is(BBOX_DEVICE_CONTEXT)) { - LogWarning("Missing duration for rest '%s'", rest->GetID().c_str()); - } + // in tablature the @dur is in the parent TabGrp - try to get if from there + if ((drawingDur == DURATION_NONE) && staff->IsTablature()) { + TabGrp *tabGrp = vrv_cast(rest->GetFirstAncestor(TABGRP)); + if (tabGrp != NULL) drawingDur = tabGrp->GetActualDur(); + } + // Make sure we have something to draw + if ((drawingDur == DURATION_NONE) && !dc->Is(BBOX_DEVICE_CONTEXT)) { + LogWarning("Missing duration for rest '%s'", rest->GetID().c_str()); drawingDur = DURATION_4; } + const char32_t drawingGlyph = rest->GetRestGlyph(drawingDur); const int x = element->GetDrawingX(); diff --git a/src/view_page.cpp b/src/view_page.cpp index ccabdb3237..304095385a 100644 --- a/src/view_page.cpp +++ b/src/view_page.cpp @@ -1253,9 +1253,7 @@ void View::DrawStaff(DeviceContext *dc, Staff *staff, Measure *measure, System * staff->SetFromFacsimile(m_doc); } - if (staffDef && (staffDef->GetLinesVisible() != BOOLEAN_false)) { - this->DrawStaffLines(dc, staff, measure, system); - } + this->DrawStaffLines(dc, staff, staffDef, measure, system); if (staffDef && (m_doc->GetType() != Facs)) { this->DrawStaffDef(dc, staff, measure); @@ -1285,13 +1283,22 @@ void View::DrawStaff(DeviceContext *dc, Staff *staff, Measure *measure, System * dc->EndGraphic(staff, this); } -void View::DrawStaffLines(DeviceContext *dc, Staff *staff, Measure *measure, System *system) +void View::DrawStaffLines(DeviceContext *dc, Staff *staff, StaffDef *staffDef, Measure *measure, System *system) { assert(dc); assert(staff); assert(measure); assert(system); + // If German lute tablature the default is @lines.visible="false", but setting @lines.visible="true" + // will draw the staff lines. + bool gltLines = (staff->IsTabLuteGerman() && staffDef->GetLinesVisible() != BOOLEAN_true); + // For anything other than German lute tablature the default is @lines.visible="true" + bool visibleLines = (staffDef->GetLinesVisible() != BOOLEAN_false); + + // Nothing to do if both are false + if (!gltLines && !visibleLines) return; + int j, x1, x2, y1, y2; x1 = measure->GetDrawingX(); @@ -1308,35 +1315,51 @@ void View::DrawStaffLines(DeviceContext *dc, Staff *staff, Measure *measure, Sys dc->SetPen(m_currentColor, ToDeviceContextX(lineWidth), AxSOLID); dc->SetBrush(m_currentColor, AxSOLID); - for (j = 0; j < staff->m_drawingLines; ++j) { - // Skewed lines - with Facs (neumes) only for now - if (y1 != y2) { - dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y2)); - // For drawing rectangles instead of lines - y1 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); - y2 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); - } - else { - const bool isFrenchOrItalianTablature = (staff->IsTabLuteFrench() || staff->IsTabLuteItalian()); - SegmentedLine line(x1, x2); - // We do not need to do this during layout calculation - and only with tablature but not for French or - // Italian tablature - if (!dc->Is(BBOX_DEVICE_CONTEXT) && staff->IsTablature() && !isFrenchOrItalianTablature) { - Object fullLine; - fullLine.SetParent(system); - fullLine.UpdateContentBBoxY(y1 + (lineWidth / 2), y1 - (lineWidth / 2)); - fullLine.UpdateContentBBoxX(x1, x2); - int margin = m_doc->GetDrawingUnit(100) / 2; - ListOfObjects notes = staff->FindAllDescendantsByType(NOTE, false); - for (Object *note : notes) { - if (note->VerticalContentOverlap(&fullLine, margin / 2)) { - line.AddGap(note->GetContentLeft() - margin, note->GetContentRight() + margin); + // If German lute tablature the default is @lines.visible="false", but setting @lines.visible="true" + // will draw the staff lines. + // For anything other than German lute tablature the default is @lines.visible="true" + if (gltLines) { + // German tablature has no staff, just a single base line + // But internally we maintain the fiction of an invisible staff as a coordinate system + SegmentedLine line(x1, x2); + // Issue #3589 move base line slightly further down and reduce thickness + y1 -= (m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize) * staff->m_drawingLines) * 11 / 10; + this->DrawHorizontalSegmentedLine(dc, y1, line, lineWidth / 2); + } + // Normal staff lines + else { + // draw staff lines + for (j = 0; j < staff->m_drawingLines; ++j) { + // Skewed lines - with Facs (neumes) only for now + if (y1 != y2) { + dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y2)); + // For drawing rectangles instead of lines + y1 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); + y2 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); + } + else { + const bool isFrenchOrGermanOrItalianTablature + = (staff->IsTabLuteFrench() || staff->IsTabLuteGerman() || staff->IsTabLuteItalian()); + SegmentedLine line(x1, x2); + // We do not need to do this during layout calculation - and only with guitar tablature but not for + // French, German or Italian lute tablature + if (!dc->Is(BBOX_DEVICE_CONTEXT) && staff->IsTablature() && !isFrenchOrGermanOrItalianTablature) { + Object fullLine; + fullLine.SetParent(system); + fullLine.UpdateContentBBoxY(y1 + (lineWidth / 2), y1 - (lineWidth / 2)); + fullLine.UpdateContentBBoxX(x1, x2); + int margin = m_doc->GetDrawingUnit(100) / 2; + ListOfObjects notes = staff->FindAllDescendantsByType(NOTE, false); + for (Object *note : notes) { + if (note->VerticalContentOverlap(&fullLine, margin / 2)) { + line.AddGap(note->GetContentLeft() - margin, note->GetContentRight() + margin); + } } } + this->DrawHorizontalSegmentedLine(dc, y1, line, lineWidth); + y1 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); + y2 = y1; } - this->DrawHorizontalSegmentedLine(dc, y1, line, lineWidth); - y1 -= m_doc->GetDrawingDoubleUnit(staff->m_drawingStaffSize); - y2 = y1; } } diff --git a/src/view_tab.cpp b/src/view_tab.cpp index 6fa926578e..44a247351b 100644 --- a/src/view_tab.cpp +++ b/src/view_tab.cpp @@ -22,6 +22,7 @@ #include "rend.h" #include "smufl.h" #include "staff.h" +#include "staffdef.h" #include "stem.h" #include "system.h" #include "tabdursym.h" @@ -103,10 +104,13 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S int glyphSize = staff->GetDrawingStaffNotationSize(); bool drawingCueSize = false; + int overline = 0; + int strike = 0; + int underline = 0; if (staff->m_drawingNotationType == NOTATIONTYPE_tab_guitar) { - std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType); + std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType, overline, strike, underline); FontInfo fretTxt; if (!dc->UseGlobalStyling()) { @@ -132,7 +136,7 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S } else { - std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType); + std::u32string fret = note->GetTabFretString(staff->m_drawingNotationType, overline, strike, underline); // Center for italian tablature if (staff->IsTabLuteItalian()) { y -= (m_doc->GetGlyphHeight(SMUFL_EBE0_luteItalianFret0, glyphSize, drawingCueSize) / 2); @@ -142,9 +146,59 @@ void View::DrawTabNote(DeviceContext *dc, LayerElement *element, Layer *layer, S y -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) - m_doc->GetDrawingStaffLineWidth(staff->m_drawingStaffSize); } + // Center for German tablature + else if (staff->IsTabLuteGerman()) { + y -= m_doc->GetGlyphHeight(SMUFL_EC17_luteGermanAUpper, glyphSize, drawingCueSize) / 2; + } dc->SetFont(m_doc->GetDrawingSmuflFont(glyphSize, false)); this->DrawSmuflString(dc, x, y, fret, HORIZONTALALIGNMENT_center, glyphSize); + + // Add overlines, strikethoughs and underlines if required + if ((overline > 0 || strike > 0 || underline > 0) && !fret.empty()) { + const int lineThickness + = m_options->m_lyricLineThickness.GetValue() * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + const int widthFront = m_doc->GetGlyphWidth(fret.front(), glyphSize, drawingCueSize); + const int widthBack = m_doc->GetGlyphWidth(fret.back(), glyphSize, drawingCueSize); + TextExtend extend; + dc->GetSmuflTextExtent(fret, &extend); + + // TODO These fiddle factors seem necessary to get the lines balanced on either side + // of the fret string. Can we do better? + const int x1 + = x - (fret.size() == 1 ? widthFront * 7 / 10 : widthFront * 12 / 10); // extend on the left hand side + const int x2 = x + extend.m_width - widthBack * 1 / 10; // trim right hand overhang on last character + + dc->SetPen(m_currentColor, lineThickness, AxSOLID); + dc->SetBrush(m_currentColor, AxSOLID); + + // overlines + int y1 = y + extend.m_ascent + lineThickness; + + for (int i = 0; i < overline; ++i) { + dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y1)); + y1 += 2 * lineThickness; + } + + // strikethroughs + y1 = y + extend.m_ascent / 2 - (strike - 1) * lineThickness; + + for (int i = 0; i < strike; ++i) { + dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y1)); + y1 += 2 * lineThickness; + } + + // underlines + y1 = y - extend.m_descent - lineThickness; + + for (int i = 0; i < underline; ++i) { + dc->DrawLine(ToDeviceContextX(x1), ToDeviceContextY(y1), ToDeviceContextX(x2), ToDeviceContextY(y1)); + y1 -= 2 * lineThickness; + } + + dc->ResetPen(); + dc->ResetBrush(); + } dc->ResetFont(); } @@ -167,10 +221,23 @@ void View::DrawTabDurSym(DeviceContext *dc, LayerElement *element, Layer *layer, dc->StartGraphic(tabDurSym, "", tabDurSym->GetID()); + if (tabDurSym->HasLoc()) { + const int yRel = ((staff->m_drawingLines - 1) * 2 - tabDurSym->GetLoc()) + * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + tabDurSym->SetDrawingYRel(-yRel); + } + else if (staff->IsTabLuteItalian()) { + // make space for 7th course + const int yRel + = ((staff->m_drawingLines - 1) * 2 - 7 * 2 + 1) * m_doc->GetDrawingUnit(staff->m_drawingStaffSize); + tabDurSym->SetDrawingYRel(-yRel); + } + int x = element->GetDrawingX(); int y = element->GetDrawingY(); const int glyphSize = staff->GetDrawingStaffNotationSize(); + const int drawingDur = (tabGrp->GetDurGes() != DURATION_NONE) ? tabGrp->GetActualDurGes() : tabGrp->GetActualDur(); // For beam and guitar notation, stem are drawn through the child Stem diff --git a/src/vrv.cpp b/src/vrv.cpp index 2378a542dd..115fbf626f 100644 --- a/src/vrv.cpp +++ b/src/vrv.cpp @@ -235,20 +235,20 @@ bool AreEqual(double dFirstVal, double dSecondVal) bool IsValidInteger(const std::string &value) { // Accept "1" " 1 " "+1" "-1" "1." "1.0" - std::regex re(R"(^\s*[+-]?\d+\.?\d*\s*$)"); + static const std::regex re(R"(^\s*[+-]?\d+\.?\d*\s*$)"); return std::regex_match(value, re); } bool IsValidDouble(const std::string &value) { // Accept "1.0" " 1.0 " ".0" "1." "+1.0" "-1.0" - std::regex re(R"(^\s*[+-]?(?:\d+\.?\d*|\.\d+)\s*$)"); + static const std::regex re(R"(^\s*[+-]?(?:\d+\.?\d*|\.\d+)\s*$)"); return std::regex_match(value, re); } bool IsDigits(const std::string &value) { - std::regex re(R"(^\d+$)"); + static const std::regex re(R"(^\d+$)"); return std::regex_match(value, re); } @@ -432,8 +432,8 @@ std::string BaseEncodeInt(uint32_t value, uint8_t base) std::string FromCamelCase(const std::string &s) { - std::regex regExp1("(.)([A-Z][a-z]+)"); - std::regex regExp2("([a-z0-9])([A-Z])"); + static const std::regex regExp1("(.)([A-Z][a-z]+)"); + static const std::regex regExp2("([a-z0-9])([A-Z])"); std::string result = s; result = std::regex_replace(result, regExp1, "$1-$2");