From 29293796b4abfaabd13846546769e0a42bf80f31 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Tue, 31 Oct 2023 10:40:35 +0100 Subject: [PATCH] Implement support for `@oct.default`. Closes #3513 --- include/vrv/pitchinterface.h | 14 +++++++++++++- src/calcalignmentpitchposfunctor.cpp | 17 ++++++++++++++--- src/pitchinterface.cpp | 7 +++++-- 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/include/vrv/pitchinterface.h b/include/vrv/pitchinterface.h index 15226365474..72b0d42a029 100644 --- a/include/vrv/pitchinterface.h +++ b/include/vrv/pitchinterface.h @@ -38,6 +38,15 @@ class PitchInterface : public Interface, public AttNoteGes, public AttOctave, pu InterfaceId IsInterface() const override { return INTERFACE_PITCH; } ///@} + /** + * @name Set and get the default octave + */ + ///@{ + void SetOctDefault(data_OCTAVE oct) { m_octDefault = oct; } + data_OCTAVE GetOctDefault() const { return m_octDefault; } + bool HasOctDefault() const { return (m_octDefault != MEI_UNSET_OCT); } + ///@} + /** * Interface comparison operator. * Checks if the LayerElement has a PitchInterface and compares attributes @@ -90,7 +99,10 @@ class PitchInterface : public Interface, public AttNoteGes, public AttOctave, pu public: // private: - // + /** + * The default octave: extracted from scoreDef/staffDef and used when no octave attribute is given + */ + data_OCTAVE m_octDefault; }; } // namespace vrv diff --git a/src/calcalignmentpitchposfunctor.cpp b/src/calcalignmentpitchposfunctor.cpp index 121ec4b643f..697ea7bf548 100644 --- a/src/calcalignmentpitchposfunctor.cpp +++ b/src/calcalignmentpitchposfunctor.cpp @@ -27,7 +27,10 @@ namespace vrv { // CalcAlignmentPitchPosFunctor //---------------------------------------------------------------------------- -CalcAlignmentPitchPosFunctor::CalcAlignmentPitchPosFunctor(Doc *doc) : DocFunctor(doc) {} +CalcAlignmentPitchPosFunctor::CalcAlignmentPitchPosFunctor(Doc *doc) : DocFunctor(doc) +{ + m_octDefault = MEI_UNSET_OCT; +} FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerElement) { @@ -38,6 +41,15 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE Layer *layerY = vrv_cast(layerElement->GetFirstAncestor(LAYER)); assert(layerY); + PitchInterface *pitchInterface = layerElement->GetPitchInterface(); + if (pitchInterface) { + pitchInterface->SetOctDefault(m_octDefault); + // Check if there is a octave default for the staff - ignore cross-staff for this and use staffY + if (m_octDefaultForStaffN.count(staffY->GetN()) > 0) { + pitchInterface->SetOctDefault(m_octDefaultForStaffN.at(staffY->GetN())); + } + } + if (layerElement->m_crossStaff && layerElement->m_crossLayer) { layerElementY = layerElement->m_crossLayer->GetAtPos(layerElement->GetDrawingX()); staffY = layerElement->m_crossStaff; @@ -95,7 +107,7 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE loc = staffY->m_drawingTuning->CalcPitchPos( note->GetTabCourse(), staffY->m_drawingNotationType, staffY->m_drawingLines); } - else if ((note->HasPname() && note->HasOct()) || note->HasLoc()) { + else if ((note->HasPname() && (note->HasOct() || note->HasOctDefault())) || note->HasLoc()) { loc = PitchInterface::CalcLoc(note, layerY, layerElementY); } int yRel = staffY->CalcPitchPosYRel(m_doc, loc); @@ -314,7 +326,6 @@ FunctorCode CalcAlignmentPitchPosFunctor::VisitLayerElement(LayerElement *layerE return FUNCTOR_CONTINUE; } - FunctorCode CalcAlignmentPitchPosFunctor::VisitScore(Score *score) { ScoreDef *scoreDef = score->GetScoreDef(); diff --git a/src/pitchinterface.cpp b/src/pitchinterface.cpp index 04fa9596152..893e928d57d 100644 --- a/src/pitchinterface.cpp +++ b/src/pitchinterface.cpp @@ -45,6 +45,8 @@ void PitchInterface::Reset() this->ResetOctave(); this->ResetPitch(); this->ResetPitchGes(); + + m_octDefault = MEI_UNSET_OCT; } bool PitchInterface::HasIdenticalPitchInterface(const PitchInterface *otherPitchInterface) const @@ -155,13 +157,14 @@ int PitchInterface::CalcLoc( if (note->HasLoc()) { return note->GetLoc(); } - else if (note->HasPname() && note->HasOct()) { + else if (note->HasPname() && (note->HasOct() || note->HasOctDefault())) { int offset = layer->GetClefLocOffset(crossStaffElement); const Layer *parentLayer = vrv_cast(layerElement->GetFirstAncestor(LAYER)); if (parentLayer != layer) { offset = parentLayer->GetCrossStaffClefLocOffset(layerElement, offset); } - return PitchInterface::CalcLoc(note->GetPname(), note->GetOct(), offset); + const data_OCTAVE oct = (note->HasOct()) ? note->GetOct() : note->GetOctDefault(); + return PitchInterface::CalcLoc(note->GetPname(), oct, offset); } else { return 0;