From bc5b52ab8a4c726a4d1c839ce410985189be5e8d Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 3 Jan 2024 14:06:38 +0100 Subject: [PATCH 01/12] Revert "Fix crash when converting mensural notation from Humdrum" This reverts commit 3ded68c67693dc7a80639aef3548751c1b2da016. --- src/doc.cpp | 3 --- src/iohumdrum.cpp | 1 - 2 files changed, 4 deletions(-) diff --git a/src/doc.cpp b/src/doc.cpp index 8d1710d09e3..01c2024601d 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -1291,9 +1291,6 @@ void Doc::ConvertToCastOffMensuralDoc(bool castOff) m_isMensuralMusicOnly = false; } - // Calling Doc::PrepareData is expected to collect visible scores - assert(m_dataPreparationDone); - // Make sure the document is not cast-off this->UnCastOffDoc(); diff --git a/src/iohumdrum.cpp b/src/iohumdrum.cpp index be58d5bb7ca..4353e83816a 100644 --- a/src/iohumdrum.cpp +++ b/src/iohumdrum.cpp @@ -31612,7 +31612,6 @@ void HumdrumInput::finalizeDocument(Doc *doc) if (m_mens) { doc->SetMensuralMusicOnly(true); doc->m_notationType = NOTATIONTYPE_mensural; - doc->PrepareData(); doc->ConvertToCastOffMensuralDoc(true); } } From 3ae599edf9ed1171cf3fe9d17a5d4daf82ff6abe Mon Sep 17 00:00:00 2001 From: David Bauer Date: Wed, 3 Jan 2024 14:51:52 +0100 Subject: [PATCH 02/12] Generic version of Doc::GetCorrespondingScore --- include/vrv/doc.h | 2 ++ src/doc.cpp | 11 ++++++++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/include/vrv/doc.h b/include/vrv/doc.h index 3952633bb49..a5f5c17f2e9 100644 --- a/include/vrv/doc.h +++ b/include/vrv/doc.h @@ -163,6 +163,8 @@ class Doc : public Object { ///@{ Score *GetCorrespondingScore(const Object *object); const Score *GetCorrespondingScore(const Object *object) const; + // Generic version that does not necessarily rely on precalculated visible scores + const Score *GetCorrespondingScore(const Object *object, const std::list &scores) const; ///@} /** diff --git a/src/doc.cpp b/src/doc.cpp index 01c2024601d..62c596e4684 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -1523,10 +1523,15 @@ Score *Doc::GetCorrespondingScore(const Object *object) const Score *Doc::GetCorrespondingScore(const Object *object) const { - assert(!m_visibleScores.empty()); + return this->GetCorrespondingScore(object, m_visibleScores); +} - const Score *correspondingScore = m_visibleScores.front(); - for (Score *score : m_visibleScores) { +const Score *Doc::GetCorrespondingScore(const Object *object, const std::list &scores) const +{ + assert(!scores.empty()); + + const Score *correspondingScore = scores.front(); + for (Score *score : scores) { if ((score == object) || Object::IsPreOrdered(score, object)) { correspondingScore = score; } From 34d358e7266e928ef24a1717e05148e4bc05ff50 Mon Sep 17 00:00:00 2001 From: Klaus Rettinghaus Date: Thu, 4 Jan 2024 18:18:45 +0100 Subject: [PATCH 03/12] check fTrem attributes --- src/view_beam.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/view_beam.cpp b/src/view_beam.cpp index 1be6bdbe31c..24bd8006935 100644 --- a/src/view_beam.cpp +++ b/src/view_beam.cpp @@ -150,8 +150,8 @@ void View::DrawFTremSegment(DeviceContext *dc, Staff *staff, FTrem *fTrem) secondElement->m_x += (m_doc->GetDrawingStemWidth(staff->m_drawingStaffSize)) / 2; } - // Number of bars to draw - const int allBars = fTrem->GetBeams(); + // Number of beams to draw + const int allBars = fTrem->HasBeams() ? fTrem->GetBeams() : fTrem->GetUnitdur() - DURATION_4; int floatingBars = fTrem->HasBeamsFloat() ? fTrem->GetBeamsFloat() : 0; int fullBars = allBars - floatingBars; From b9f27b988bf735c14b6882107c86eeecb7a5da06 Mon Sep 17 00:00:00 2001 From: Klaus Rettinghaus Date: Thu, 4 Jan 2024 18:25:46 +0100 Subject: [PATCH 04/12] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6b095c12dbf..2a415ca506a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,7 @@ # Changelog ## [unreleased] +* Support for `fTrem@unitdur` (@eNote-GmbH) ## [4.1.0] - 2023-12-15 * Support for staves ordered by `scoreDef` From 32a863df94414019da4a3f6d63045c4ec61074bf Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 4 Jan 2024 21:20:25 +0100 Subject: [PATCH 05/12] Track scores in ScoreDefSetCurrentPageFunctor --- include/vrv/doc.h | 1 + include/vrv/setscoredeffunctor.h | 4 +++- src/doc.cpp | 5 +++++ src/setscoredeffunctor.cpp | 11 +++++++++-- 4 files changed, 18 insertions(+), 3 deletions(-) diff --git a/include/vrv/doc.h b/include/vrv/doc.h index a5f5c17f2e9..be4b8d27d87 100644 --- a/include/vrv/doc.h +++ b/include/vrv/doc.h @@ -164,6 +164,7 @@ class Doc : public Object { Score *GetCorrespondingScore(const Object *object); const Score *GetCorrespondingScore(const Object *object) const; // Generic version that does not necessarily rely on precalculated visible scores + Score *GetCorrespondingScore(const Object *object, const std::list &scores); const Score *GetCorrespondingScore(const Object *object, const std::list &scores) const; ///@} diff --git a/include/vrv/setscoredeffunctor.h b/include/vrv/setscoredeffunctor.h index 5d4d417c455..60e3d9af41d 100644 --- a/include/vrv/setscoredeffunctor.h +++ b/include/vrv/setscoredeffunctor.h @@ -88,6 +88,7 @@ class ScoreDefSetCurrentPageFunctor : public DocFunctor { */ ///@{ FunctorCode VisitPageEnd(Page *page) override; + FunctorCode VisitScore(Score *score) override; ///@} protected: @@ -97,7 +98,8 @@ class ScoreDefSetCurrentPageFunctor : public DocFunctor { public: // private: - // + // The list of all scores + std::list m_scores; }; //---------------------------------------------------------------------------- diff --git a/src/doc.cpp b/src/doc.cpp index 62c596e4684..74fff4f5adf 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -1526,6 +1526,11 @@ const Score *Doc::GetCorrespondingScore(const Object *object) const return this->GetCorrespondingScore(object, m_visibleScores); } +Score *Doc::GetCorrespondingScore(const Object *object, const std::list &scores) +{ + return const_cast(std::as_const(*this).GetCorrespondingScore(object, scores)); +} + const Score *Doc::GetCorrespondingScore(const Object *object, const std::list &scores) const { assert(!scores.empty()); diff --git a/src/setscoredeffunctor.cpp b/src/setscoredeffunctor.cpp index 144bc4d3248..29f6548c8ce 100644 --- a/src/setscoredeffunctor.cpp +++ b/src/setscoredeffunctor.cpp @@ -68,11 +68,18 @@ FunctorCode ScoreDefSetCurrentPageFunctor::VisitPageEnd(Page *page) { const Object *firstSystem = page->GetFirst(SYSTEM); const Object *reference = firstSystem ? firstSystem : page; - page->m_score = m_doc->GetCorrespondingScore(reference); + page->m_score = m_doc->GetCorrespondingScore(reference, m_scores); const Object *lastSystem = page->GetLast(SYSTEM); reference = lastSystem ? lastSystem : page; - page->m_scoreEnd = m_doc->GetCorrespondingScore(reference); + page->m_scoreEnd = m_doc->GetCorrespondingScore(reference, m_scores); + + return FUNCTOR_CONTINUE; +} + +FunctorCode ScoreDefSetCurrentPageFunctor::VisitScore(Score *score) +{ + m_scores.push_back(score); return FUNCTOR_CONTINUE; } From e77dfdd2b2b18ce2b13f654043fc15fe217ec720 Mon Sep 17 00:00:00 2001 From: David Bauer Date: Thu, 4 Jan 2024 21:24:02 +0100 Subject: [PATCH 06/12] Remove unused --- src/verticalaligner.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/verticalaligner.cpp b/src/verticalaligner.cpp index 0bf5b3ed82e..60cbad6b3b7 100644 --- a/src/verticalaligner.cpp +++ b/src/verticalaligner.cpp @@ -48,7 +48,6 @@ void SystemAligner::Reset() m_spacingTypes.clear(); m_system = NULL; - ArrayOfObjects &children = this->GetChildrenForModification(); m_bottomAlignment = new StaffAlignment(); m_bottomAlignment->SetStaff(NULL, NULL, this->GetAboveSpacingType(NULL)); m_bottomAlignment->SetParentSystem(this->GetSystem()); From cc9410c3f2223c459bd9c12827f89540e7816bd1 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 7 Jan 2024 21:22:59 +0100 Subject: [PATCH 07/12] Adjust the facsimile functor to take into account the PPU --- include/vrv/devicecontext.h | 7 +++++ include/vrv/facsimilefunctor.h | 6 +++- src/devicecontext.cpp | 5 ++++ src/doc.cpp | 8 ++++-- src/facsimilefunctor.cpp | 51 ++++++++++++++++++++++++++++++---- src/measure.cpp | 4 +++ src/svgdevicecontext.cpp | 4 +-- src/toolkit.cpp | 3 +- 8 files changed, 77 insertions(+), 11 deletions(-) diff --git a/include/vrv/devicecontext.h b/include/vrv/devicecontext.h index e493d38b611..fde5c18875d 100644 --- a/include/vrv/devicecontext.h +++ b/include/vrv/devicecontext.h @@ -74,6 +74,7 @@ class DeviceContext { m_baseWidth = 0; m_baseHeight = 0; m_pushBack = false; + m_viewBoxFactor = (double)DEFINITION_FACTOR; } DeviceContext(ClassId classId) { @@ -89,6 +90,7 @@ class DeviceContext { m_baseWidth = 0; m_baseHeight = 0; m_pushBack = false; + m_viewBoxFactor = (double)DEFINITION_FACTOR; } virtual ~DeviceContext(){}; ClassId GetClassId() const { return m_classId; } @@ -124,12 +126,14 @@ class DeviceContext { m_baseWidth = width; m_baseHeight = height; } + void SetViewBoxFactor(double ppuFactor); int GetWidth() const { return m_width; } int GetHeight() const { return m_height; } int GetContentHeight() const { return m_contentHeight; } double GetUserScaleX() { return m_userScaleX; } double GetUserScaleY() { return m_userScaleY; } std::pair GetBaseSize() const { return std::make_pair(m_baseWidth, m_baseHeight); } + double GetViewBoxFactor() const { return m_viewBoxFactor; } ///@} /** @@ -365,6 +369,9 @@ class DeviceContext { /** stores the scale as requested by the used */ double m_userScaleX; double m_userScaleY; + + /** stores the viewbox factor taking into account the DEFINTION_FACTOR and the PPU */ + double m_viewBoxFactor; }; } // namespace vrv diff --git a/include/vrv/facsimilefunctor.h b/include/vrv/facsimilefunctor.h index 1273343626c..7ccf8f3e772 100644 --- a/include/vrv/facsimilefunctor.h +++ b/include/vrv/facsimilefunctor.h @@ -42,7 +42,7 @@ class SyncFromFacsimileFunctor : public Functor { /* * Abstract base implementation */ - bool ImplementsEndInterface() const override { return false; } + bool ImplementsEndInterface() const override { return true; } /* * Functor interface @@ -51,6 +51,7 @@ class SyncFromFacsimileFunctor : public Functor { FunctorCode VisitLayerElement(LayerElement *layerElement) override; FunctorCode VisitMeasure(Measure *measure) override; FunctorCode VisitPage(Page *page) override; + FunctorCode VisitPageEnd(Page *page) override; FunctorCode VisitPb(Pb *pb) override; FunctorCode VisitSb(Sb *sb) override; FunctorCode VisitStaff(Staff *staff) override; @@ -71,6 +72,9 @@ class SyncFromFacsimileFunctor : public Functor { // Page *m_currentPage; System *m_currentSystem; + Measure *m_currentNeumeLine; + /** map to store the zone corresponding to a staff */ + std::map m_staffZones; }; //---------------------------------------------------------------------------- diff --git a/src/devicecontext.cpp b/src/devicecontext.cpp index 09a868e56ab..e734a35919d 100644 --- a/src/devicecontext.cpp +++ b/src/devicecontext.cpp @@ -129,6 +129,11 @@ const Resources *DeviceContext::GetResources(bool showWarning) const return m_resources; } +void DeviceContext::SetViewBoxFactor(double ppuFactor) +{ + m_viewBoxFactor = double(DEFINITION_FACTOR) / ppuFactor; +} + void DeviceContext::SetPen(int color, int width, int style, int dashLength, int gapLength, int lineCap, int lineJoin) { float opacityValue; diff --git a/src/doc.cpp b/src/doc.cpp index ccce0a8f52c..0d962d9f3cb 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -2124,8 +2124,10 @@ int Doc::GetAdjustedDrawingPageHeight() const { assert(m_drawingPage); + // Take into account the PPU when getting the page height in facsimile if (this->IsTranscription() || this->IsFacs()) { - return m_drawingPage->m_pageHeight / DEFINITION_FACTOR; + const int factor = DEFINITION_FACTOR / m_drawingPage->GetPPUFactor(); + return m_drawingPage->m_pageHeight / factor; } int contentHeight = m_drawingPage->GetContentHeight(); @@ -2136,8 +2138,10 @@ int Doc::GetAdjustedDrawingPageWidth() const { assert(m_drawingPage); + // Take into account the PPU when getting the page width in facsimile if (this->IsTranscription() || this->IsFacs()) { - return m_drawingPage->m_pageWidth / DEFINITION_FACTOR; + const int factor = DEFINITION_FACTOR / m_drawingPage->GetPPUFactor(); + return m_drawingPage->m_pageWidth / factor; } int contentWidth = m_drawingPage->GetContentWidth(); diff --git a/src/facsimilefunctor.cpp b/src/facsimilefunctor.cpp index 73ec1ef23ca..6c01cbc5217 100644 --- a/src/facsimilefunctor.cpp +++ b/src/facsimilefunctor.cpp @@ -12,6 +12,7 @@ #include "doc.h" #include "layerelement.h" #include "measure.h" +#include "miscfunctor.h" #include "page.h" #include "pb.h" #include "sb.h" @@ -39,7 +40,7 @@ SyncFromFacsimileFunctor::SyncFromFacsimileFunctor(Doc *doc) : Functor() FunctorCode SyncFromFacsimileFunctor::VisitLayerElement(LayerElement *layerElement) { - if (!layerElement->Is({ NOTE, REST })) return FUNCTOR_CONTINUE; + if (!layerElement->Is({ CLEF, CUSTOS, NC, NOTE, REST, SYL })) return FUNCTOR_CONTINUE; Zone *zone = layerElement->GetZone(); assert(zone); @@ -50,22 +51,54 @@ FunctorCode SyncFromFacsimileFunctor::VisitLayerElement(LayerElement *layerEleme FunctorCode SyncFromFacsimileFunctor::VisitMeasure(Measure *measure) { - Zone *zone = measure->GetZone(); - assert(zone); - measure->m_drawingFacsX1 = m_view.ToLogicalX(zone->GetUlx() * DEFINITION_FACTOR); - measure->m_drawingFacsX2 = m_view.ToLogicalX(zone->GetLrx() * DEFINITION_FACTOR); + // neon specific code - measure have no zone, we will use the staff one in VisitStaff + if (measure->IsNeumeLine()) { + m_currentNeumeLine = measure; + } + else { + Zone *zone = measure->GetZone(); + assert(zone); + measure->m_drawingFacsX1 = m_view.ToLogicalX(zone->GetUlx() * DEFINITION_FACTOR); + measure->m_drawingFacsX2 = m_view.ToLogicalX(zone->GetLrx() * DEFINITION_FACTOR); + } return FUNCTOR_CONTINUE; } FunctorCode SyncFromFacsimileFunctor::VisitPage(Page *page) { + m_staffZones.clear(); m_currentPage = page; m_doc->SetDrawingPage(m_currentPage->GetIdx()); return FUNCTOR_CONTINUE; } +FunctorCode SyncFromFacsimileFunctor::VisitPageEnd(Page *page) +{ + // Used for adjusting staff size in neon - filled in VisitStaff + if (m_staffZones.empty()) return FUNCTOR_CONTINUE; + + // The staff size is calculated based on the zone height and takes into acocunt the rotation + for (auto &[staff, zone] : m_staffZones) { + double rotate = (zone->HasRotate()) ? zone->GetRotate() : 0.0; + int yDiff + = zone->GetLry() - zone->GetUly() - (zone->GetLrx() - zone->GetUlx()) * tan(abs(rotate) * M_PI / 180.0); + staff->m_drawingStaffSize + = 100 * yDiff / (m_doc->GetOptions()->m_unit.GetValue() * 2 * (staff->m_drawingLines - 1)); + } + + // Since we multiply all values by the DEFINITION_FACTOR, set it as PPU + m_currentPage->SetPPUFactor(DEFINITION_FACTOR); + if (m_currentPage->GetPPUFactor() != 1.0) { + ApplyPPUFactorFunctor applyPPUFactor; + m_currentPage->Process(applyPPUFactor); + m_doc->UpdatePageDrawingSizes(); + } + + return FUNCTOR_CONTINUE; +} + FunctorCode SyncFromFacsimileFunctor::VisitPb(Pb *pb) { // This would happen if we run the functor on data not converted to page-based @@ -109,12 +142,20 @@ FunctorCode SyncFromFacsimileFunctor::VisitStaff(Staff *staff) assert(zone); staff->m_drawingFacsY = m_view.ToLogicalY(zone->GetUly() * DEFINITION_FACTOR); + // neon specific code - set the position of the pseudo measure (neume line) + if (m_currentNeumeLine) { + m_currentNeumeLine->m_drawingFacsX1 = m_view.ToLogicalX(zone->GetUlx() * DEFINITION_FACTOR); + m_currentNeumeLine->m_drawingFacsX2 = m_view.ToLogicalX(zone->GetLrx() * DEFINITION_FACTOR); + m_staffZones[staff] = zone; + } + return FUNCTOR_CONTINUE; } FunctorCode SyncFromFacsimileFunctor::VisitSystem(System *system) { m_currentSystem = system; + m_currentNeumeLine = NULL; return FUNCTOR_CONTINUE; } diff --git a/src/measure.cpp b/src/measure.cpp index ada13c6296f..2b72137062e 100644 --- a/src/measure.cpp +++ b/src/measure.cpp @@ -213,6 +213,7 @@ void Measure::AddChildBack(Object *child) int Measure::GetDrawingX() const { + /* if (!this->IsMeasuredMusic()) { const System *system = vrv_cast(this->GetFirstAncestor(SYSTEM)); assert(system); @@ -220,6 +221,7 @@ int Measure::GetDrawingX() const return (system->m_systemLeftMar); } } + */ if (m_drawingFacsX1 != VRV_UNSET) return m_drawingFacsX1; @@ -353,6 +355,7 @@ int Measure::GetRightBarLineRight() const int Measure::GetWidth() const { + /* if (!this->IsMeasuredMusic()) { const System *system = vrv_cast(this->GetFirstAncestor(SYSTEM)); assert(system); @@ -363,6 +366,7 @@ int Measure::GetWidth() const return page->m_pageWidth - system->m_systemLeftMar - system->m_systemRightMar; } } + */ if (m_drawingFacsX2 != VRV_UNSET) return (m_drawingFacsX2 - m_drawingFacsX1); diff --git a/src/svgdevicecontext.cpp b/src/svgdevicecontext.cpp index 4451b067d8c..9e97ad92b2c 100644 --- a/src/svgdevicecontext.cpp +++ b/src/svgdevicecontext.cpp @@ -471,8 +471,8 @@ void SvgDeviceContext::StartPage() = StringFormat("0 0 %d %d", this->GetWidth(), this->GetHeight()).c_str(); } else { - m_currentNode.append_attribute("viewBox") = StringFormat( - "0 0 %d %d", this->GetWidth() * DEFINITION_FACTOR, this->GetContentHeight() * DEFINITION_FACTOR) + m_currentNode.append_attribute("viewBox") = StringFormat("0 0 %d %d", + int(this->GetWidth() * this->GetViewBoxFactor()), int(this->GetContentHeight() * this->GetViewBoxFactor())) .c_str(); } diff --git a/src/toolkit.cpp b/src/toolkit.cpp index 4821605cf8b..5566158b982 100644 --- a/src/toolkit.cpp +++ b/src/toolkit.cpp @@ -1499,7 +1499,7 @@ bool Toolkit::RenderToDeviceContext(int pageNo, DeviceContext *deviceContext) std::swap(height, width); } - double userScale = m_view.GetPPUFactor() * m_options->m_scale.GetValue() / 100; + double userScale = m_options->m_scale.GetValue() / 100.0; assert(userScale != 0.0); if (m_options->m_scaleToPageSize.GetValue()) { @@ -1511,6 +1511,7 @@ bool Toolkit::RenderToDeviceContext(int pageNo, DeviceContext *deviceContext) deviceContext->SetUserScale(userScale, userScale); deviceContext->SetWidth(width); deviceContext->SetHeight(height); + deviceContext->SetViewBoxFactor(m_view.GetPPUFactor()); if (m_doc.IsFacs()) { deviceContext->SetWidth(m_doc.GetFacsimile()->GetMaxX()); From 9302ad43914d6dd4f8670c2b0d8d58ece8b9e90f Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 7 Jan 2024 22:06:09 +0100 Subject: [PATCH 08/12] Store staff rotation in Staff and adjust facsimile functor --- include/vrv/staff.h | 16 ++++++++++++++++ src/facsimilefunctor.cpp | 8 ++++++++ src/staff.cpp | 2 ++ src/view_page.cpp | 7 ++++++- 4 files changed, 32 insertions(+), 1 deletion(-) diff --git a/include/vrv/staff.h b/include/vrv/staff.h index 51cbdbd9346..7e78484308c 100644 --- a/include/vrv/staff.h +++ b/include/vrv/staff.h @@ -69,6 +69,16 @@ class Staff : public Object, } ///@} + /** + * @name Getters and setters for the rotation. + * Used only with facsimile rendering. + */ + ///@{ + void SetDrawingRotation(double drawingRotation) { m_drawingRotation = drawingRotation; } + double GetDrawingRotation() const { return m_drawingRotation; } + bool HasDrawingRotation() const { return (m_drawingRotation != 0.0); } + ///@} + /** * Delete all the legder line arrays. */ @@ -247,6 +257,12 @@ class Staff : public Object, ArrayOfLedgerLines m_ledgerLinesAboveCue; ArrayOfLedgerLines m_ledgerLinesBelowCue; ///@} + + /** + * The drawing rotation. + * Used only with facsimile rendering + */ + double m_drawingRotation; }; //---------------------------------------------------------------------------- diff --git a/src/facsimilefunctor.cpp b/src/facsimilefunctor.cpp index 6c01cbc5217..0287275a7fc 100644 --- a/src/facsimilefunctor.cpp +++ b/src/facsimilefunctor.cpp @@ -86,6 +86,7 @@ FunctorCode SyncFromFacsimileFunctor::VisitPageEnd(Page *page) = zone->GetLry() - zone->GetUly() - (zone->GetLrx() - zone->GetUlx()) * tan(abs(rotate) * M_PI / 180.0); staff->m_drawingStaffSize = 100 * yDiff / (m_doc->GetOptions()->m_unit.GetValue() * 2 * (staff->m_drawingLines - 1)); + staff->SetDrawingRotation(rotate); } // Since we multiply all values by the DEFINITION_FACTOR, set it as PPU @@ -147,6 +148,13 @@ FunctorCode SyncFromFacsimileFunctor::VisitStaff(Staff *staff) m_currentNeumeLine->m_drawingFacsX1 = m_view.ToLogicalX(zone->GetUlx() * DEFINITION_FACTOR); m_currentNeumeLine->m_drawingFacsX2 = m_view.ToLogicalX(zone->GetLrx() * DEFINITION_FACTOR); m_staffZones[staff] = zone; + + // The staff slope is going up. The y left postion needs to be adjusted accordingly + if (zone->GetRotate() < 0) { + staff->m_drawingFacsY = staff->m_drawingFacsY + + (m_currentNeumeLine->m_drawingFacsX2 - m_currentNeumeLine->m_drawingFacsX1) + * tan(zone->GetRotate() * M_PI / 180.0); + } } return FUNCTOR_CONTINUE; diff --git a/src/staff.cpp b/src/staff.cpp index 28b69219213..1a37ab7ead0 100644 --- a/src/staff.cpp +++ b/src/staff.cpp @@ -75,6 +75,7 @@ void Staff::Reset() m_timeSpanningElements.clear(); m_drawingStaffDef = NULL; m_drawingTuning = NULL; + m_drawingRotation = 0.0; ClearLedgerLines(); } @@ -90,6 +91,7 @@ void Staff::CloneReset() m_timeSpanningElements.clear(); m_drawingStaffDef = NULL; m_drawingTuning = NULL; + m_drawingRotation = 0.0; } void Staff::ClearLedgerLines() diff --git a/src/view_page.cpp b/src/view_page.cpp index 51d8b78be5c..a8f41dfb829 100644 --- a/src/view_page.cpp +++ b/src/view_page.cpp @@ -1295,7 +1295,12 @@ void View::DrawStaffLines(DeviceContext *dc, Staff *staff, Measure *measure, Sys x1 = measure->GetDrawingX(); x2 = x1 + measure->GetWidth(); y1 = staff->GetDrawingY(); - y2 = y1; + if (!staff->HasDrawingRotation()) { + y2 = y1; + } + else { + y2 = y1 - staff->GetWidth() * tan(staff->GetDrawingRotation() * M_PI / 180.0); + } } const int lineWidth = m_doc->GetDrawingStaffLineWidth(staff->m_drawingStaffSize); From 0b9ca33b0e4144dff2eb68438f3cbe3169d10515 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Sun, 7 Jan 2024 22:28:25 +0100 Subject: [PATCH 09/12] Handle rotation offset when rendering layer elements --- include/vrv/staff.h | 1 + src/facsimilefunctor.cpp | 2 +- src/staff.cpp | 6 ++++++ src/view_element.cpp | 15 ++++++++++++--- src/view_neume.cpp | 20 ++++++++++---------- 5 files changed, 30 insertions(+), 14 deletions(-) diff --git a/include/vrv/staff.h b/include/vrv/staff.h index 7e78484308c..3bda856b577 100644 --- a/include/vrv/staff.h +++ b/include/vrv/staff.h @@ -77,6 +77,7 @@ class Staff : public Object, void SetDrawingRotation(double drawingRotation) { m_drawingRotation = drawingRotation; } double GetDrawingRotation() const { return m_drawingRotation; } bool HasDrawingRotation() const { return (m_drawingRotation != 0.0); } + int GetDrawingRotationOffsetFor(int x); ///@} /** diff --git a/src/facsimilefunctor.cpp b/src/facsimilefunctor.cpp index 0287275a7fc..436939cf0cf 100644 --- a/src/facsimilefunctor.cpp +++ b/src/facsimilefunctor.cpp @@ -149,7 +149,7 @@ FunctorCode SyncFromFacsimileFunctor::VisitStaff(Staff *staff) m_currentNeumeLine->m_drawingFacsX2 = m_view.ToLogicalX(zone->GetLrx() * DEFINITION_FACTOR); m_staffZones[staff] = zone; - // The staff slope is going up. The y left postion needs to be adjusted accordingly + // The staff slope is going up. The y left position needs to be adjusted accordingly if (zone->GetRotate() < 0) { staff->m_drawingFacsY = staff->m_drawingFacsY + (m_currentNeumeLine->m_drawingFacsX2 - m_currentNeumeLine->m_drawingFacsX1) diff --git a/src/staff.cpp b/src/staff.cpp index 1a37ab7ead0..1e3c1f00a52 100644 --- a/src/staff.cpp +++ b/src/staff.cpp @@ -94,6 +94,12 @@ void Staff::CloneReset() m_drawingRotation = 0.0; } +int Staff::GetDrawingRotationOffsetFor(int x) +{ + int xDiff = x - this->GetDrawingX(); + return int(xDiff * tan(this->GetDrawingRotation() * M_PI / 180.0)); +} + void Staff::ClearLedgerLines() { m_ledgerLinesAbove.clear(); diff --git a/src/view_element.cpp b/src/view_element.cpp index 82ba0443207..63e20bb66c2 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -300,16 +300,19 @@ void View::DrawAccid(DeviceContext *dc, LayerElement *element, Layer *layer, Sta } if (notationType == NOTATIONTYPE_neume) { - int rotateOffset = 0; + int rotationOffset = 0; if (m_doc->IsFacs() && (staff->GetDrawingRotate() != 0)) { double deg = staff->GetDrawingRotate(); int xDiff = x - staff->GetDrawingX(); - rotateOffset = int(xDiff * tan(deg * M_PI / 180.0)); + rotationOffset = int(xDiff * tan(deg * M_PI / 180.0)); + } + else if (staff->HasDrawingRotation()) { + rotationOffset = staff->GetDrawingRotationOffsetFor(x); } if (accid->HasFacs() && m_doc->IsFacs()) { y = ToLogicalY(y); } - y -= rotateOffset; + y -= rotationOffset; } this->DrawSmuflString( @@ -676,6 +679,9 @@ void View::DrawClef(DeviceContext *dc, LayerElement *element, Layer *layer, Staf int xDiff = x - staff->GetDrawingX(); y -= int(xDiff * tan(deg * M_PI / 180.0)); } + else if (staff->HasDrawingRotation()) { + y -= staff->GetDrawingRotationOffsetFor(x); + } } else if (clef->GetShape() == CLEFSHAPE_perc) { y -= m_doc->GetDrawingUnit(staff->m_drawingStaffSize) * (staff->m_drawingLines - 1); @@ -782,6 +788,9 @@ void View::DrawCustos(DeviceContext *dc, LayerElement *element, Layer *layer, St int xDiff = x - staff->GetDrawingX(); y -= int(xDiff * tan(deg * M_PI / 180.0)); } + else if (staff->HasDrawingRotation()) { + y -= staff->GetDrawingRotationOffsetFor(x); + } this->DrawSmuflCode(dc, x, y, sym, staff->m_drawingStaffSize, false, true); diff --git a/src/view_neume.cpp b/src/view_neume.cpp index eeeaed614b1..0d6e312ad75 100644 --- a/src/view_neume.cpp +++ b/src/view_neume.cpp @@ -228,14 +228,14 @@ void View::DrawNc(DeviceContext *dc, LayerElement *element, Layer *layer, Staff clefOctave += (clef->GetDisPlace() == STAFFREL_basic_above ? 1 : -1) * (clef->GetDis() / 7); } int octaveOffset = (nc->GetOct() - clefOctave) * ((staffSize / 2) * 7); - int rotateOffset; + int rotationOffset = 0; if (m_doc->IsFacs() && (staff->GetDrawingRotate() != 0)) { double deg = staff->GetDrawingRotate(); int xDiff = noteX - staff->GetDrawingX(); - rotateOffset = int(xDiff * tan(deg * M_PI / 180.0)); + rotationOffset = int(xDiff * tan(deg * M_PI / 180.0)); } - else { - rotateOffset = 0; + else if (staff->HasDrawingRotation()) { + rotationOffset = staff->GetDrawingRotationOffsetFor(noteX); } if (nc->HasLoc()) { @@ -248,7 +248,7 @@ void View::DrawNc(DeviceContext *dc, LayerElement *element, Layer *layer, Staff else if (clef->GetShape() == CLEFSHAPE_F) { pitchOffset = (nc->GetPname() - 4) * (staffSize / 2); } - yValue = clefYPosition + pitchOffset + octaveOffset - rotateOffset; + yValue = clefYPosition + pitchOffset + octaveOffset - rotationOffset; } for (auto it = params.begin(); it != params.end(); it++) { @@ -392,17 +392,17 @@ void View::DrawDivLine(DeviceContext *dc, LayerElement *element, Layer *layer, S y -= (m_doc->GetDrawingUnit(staff->m_drawingStaffSize)) * 3; - int rotateOffset; + int rotationOffset = 0; if (m_doc->IsFacs() && (staff->GetDrawingRotate() != 0)) { double deg = staff->GetDrawingRotate(); int xDiff = x - staff->GetDrawingX(); - rotateOffset = int(xDiff * tan(deg * M_PI / 180.0)); + rotationOffset = int(xDiff * tan(deg * M_PI / 180.0)); } - else { - rotateOffset = 0; + else if (staff->HasDrawingRotation()) { + rotationOffset = staff->GetDrawingRotationOffsetFor(x); } - y -= rotateOffset; + y -= rotationOffset; DrawSmuflCode(dc, x, y, sym, staff->m_drawingStaffSize, false, true); From 162d6df5f3624105bc29c2be38b4921a6c03e0e3 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Tue, 9 Jan 2024 07:54:34 +0100 Subject: [PATCH 10/12] Fix custos positioning without facs --- src/view_element.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/view_element.cpp b/src/view_element.cpp index 63e20bb66c2..5b2525d205a 100644 --- a/src/view_element.cpp +++ b/src/view_element.cpp @@ -754,17 +754,18 @@ void View::DrawCustos(DeviceContext *dc, LayerElement *element, Layer *layer, St const int sym = custos->GetCustosGlyph(staff->m_drawingNotationType); int x, y; - if (custos->HasFacs() && m_doc->IsFacs()) { + // For neume notation we ignore the value set in CalcAlignmentPitchPosFunctor + if (staff->m_drawingNotationType == NOTATIONTYPE_neume) { x = custos->GetDrawingX(); // Recalculate y from pitch to prevent visual/meaning mismatch Clef *clef = layer->GetClef(element); - y = ToLogicalY(staff->GetDrawingY()); + y = staff->GetDrawingY(); PitchInterface pi; // Neume notation uses C3 for C clef rather than C4. // Take this into account when determining location. // However this doesn't affect the value for F clef. pi.SetPname(PITCHNAME_c); - if ((staff->m_drawingNotationType == NOTATIONTYPE_neume) && (clef->GetShape() == CLEFSHAPE_C)) { + if (clef->GetShape() == CLEFSHAPE_C) { pi.SetOct(3); } else { From 2f2e5389f6f29c544fae74f9f0cefcfe0f7086b8 Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Tue, 9 Jan 2024 11:23:05 +0100 Subject: [PATCH 11/12] Resolve `@facs` pointing to `` --- include/vrv/facsimileinterface.h | 7 +++++++ src/facsimilefunctor.cpp | 8 +++++--- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/include/vrv/facsimileinterface.h b/include/vrv/facsimileinterface.h index 7afafef144b..84f46ddb9b8 100644 --- a/include/vrv/facsimileinterface.h +++ b/include/vrv/facsimileinterface.h @@ -58,6 +58,13 @@ class FacsimileInterface : public Interface, public AttFacsimile { Zone *GetZone() { return m_zone; } const Zone *GetZone() const { return m_zone; } ///@} + /// + + /** Get the surface */ + ///@{ + Surface *GetSurface() { return m_surface; } + const Surface *GetSurface() const { return m_surface; } + ///@} //-----------------// // Pseudo functors // diff --git a/src/facsimilefunctor.cpp b/src/facsimilefunctor.cpp index 436939cf0cf..83f53d6b275 100644 --- a/src/facsimilefunctor.cpp +++ b/src/facsimilefunctor.cpp @@ -106,9 +106,11 @@ FunctorCode SyncFromFacsimileFunctor::VisitPb(Pb *pb) assert(m_currentPage); Zone *zone = pb->GetZone(); - assert(zone && zone->GetParent()); - Surface *surface = (zone->GetParent()->Is(SURFACE)) ? vrv_cast(zone->GetParent()) : NULL; - // Use the parent surface attributes if given + Surface *surface = pb->GetSurface(); + if (!surface && zone && zone->GetParent()) + surface = (zone->GetParent()->Is(SURFACE)) ? vrv_cast(zone->GetParent()) : NULL; + assert(zone || surface); + // Use the (parent) surface attributes if given if (surface && surface->HasLrx() && surface->HasLry()) { m_currentPage->m_pageHeight = surface->GetLry() * DEFINITION_FACTOR; m_currentPage->m_pageWidth = surface->GetLrx() * DEFINITION_FACTOR; From 3d18b647145ce45643eff5d44c8893a8bbe6a08c Mon Sep 17 00:00:00 2001 From: Laurent Pugin Date: Tue, 9 Jan 2024 14:29:46 +0100 Subject: [PATCH 12/12] Fix milestone end for added mdiv and score --- src/doc.cpp | 2 ++ src/iomei.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/src/doc.cpp b/src/doc.cpp index 26f3e5494bc..dd980546768 100644 --- a/src/doc.cpp +++ b/src/doc.cpp @@ -1410,6 +1410,8 @@ void Doc::SyncToFacsimileDoc() if (!m_facsimile->FindDescendantByType(SURFACE)) { m_facsimile->AddChild(new Surface()); } + this->ScoreDefSetCurrentDoc(); + m_facsimile->SetType("transcription"); m_facsimile->ClearChildren(); diff --git a/src/iomei.cpp b/src/iomei.cpp index ca28fd5fe15..213b54a191a 100644 --- a/src/iomei.cpp +++ b/src/iomei.cpp @@ -8198,12 +8198,14 @@ void MEIInput::UpgradePageTo_5_0(Page *page) PageMilestoneEnd *scoreEnd = new PageMilestoneEnd(score); page->AddChild(scoreEnd); + score->SetEnd(scoreEnd); Mdiv *mdiv = new Mdiv(); page->InsertChild(mdiv, 0); PageMilestoneEnd *mdivEnd = new PageMilestoneEnd(mdiv); page->AddChild(mdivEnd); + mdiv->SetEnd(mdivEnd); } void MEIInput::UpgradePgHeadFootTo_5_0(pugi::xml_node element)