From 65e185e8edc534d3773e9787f3f93078d46fd3e0 Mon Sep 17 00:00:00 2001
From: Laurent Pugin <lxpugin@gmail.com>
Date: Mon, 11 Nov 2024 10:25:33 +0100
Subject: [PATCH 1/4] Move HasLedgerLines from Note to PositionInterface

---
 include/vrv/calcledgerlinesfunctor.h |  4 ++++
 include/vrv/note.h                   |  8 --------
 include/vrv/positioninterface.h      |  8 ++++++++
 src/calcledgerlinesfunctor.cpp       | 22 ++++++++++++++--------
 src/note.cpp                         | 15 ---------------
 src/positioninterface.cpp            | 18 ++++++++++++++++++
 6 files changed, 44 insertions(+), 31 deletions(-)

diff --git a/include/vrv/calcledgerlinesfunctor.h b/include/vrv/calcledgerlinesfunctor.h
index d2d83ab4829..e6bd8797cd2 100644
--- a/include/vrv/calcledgerlinesfunctor.h
+++ b/include/vrv/calcledgerlinesfunctor.h
@@ -45,6 +45,10 @@ class CalcLedgerLinesFunctor : public DocFunctor {
 protected:
     //
 private:
+    /**
+     *
+     */
+    void CalcFor(LayerElement *layerElement);
     /**
      * Shorten ledger lines which overlap with neighbors
      */
diff --git a/include/vrv/note.h b/include/vrv/note.h
index 2ab4cc48bcf..d7872a8b3f3 100644
--- a/include/vrv/note.h
+++ b/include/vrv/note.h
@@ -132,14 +132,6 @@ class Note : public LayerElement,
     int GetDrawingLoc() const { return m_drawingLoc; }
     ///@}
 
-    /**
-     * Check if the note has ledger lines.
-     * If staff is passed, use it for getting the staff line number.
-     * Otherwise, it will look for the Staff ancestor.
-     * Set the value of ledger lines above or below.
-     */
-    bool HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff = NULL) const;
-
     /**
      * Overriding functions to return information from chord parent if any
      */
diff --git a/include/vrv/positioninterface.h b/include/vrv/positioninterface.h
index 4cc01c49909..9d65cb89768 100644
--- a/include/vrv/positioninterface.h
+++ b/include/vrv/positioninterface.h
@@ -57,6 +57,14 @@ class PositionInterface : public Interface, public AttStaffLoc, public AttStaffL
      */
     bool HasIdenticalPositionInterface(const PositionInterface *otherPositionInterface) const;
 
+    /**
+     * Check if the note has ledger lines.
+     * If staff is passed, use it for getting the staff line number.
+     * Otherwise, it will look for the Staff ancestor.
+     * Set the value of ledger lines above or below.
+     */
+    bool HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff = NULL) const;
+
     //-----------------//
     // Pseudo functors //
     //-----------------//
diff --git a/src/calcledgerlinesfunctor.cpp b/src/calcledgerlinesfunctor.cpp
index a1cf9b5b5b9..62bb40625dd 100644
--- a/src/calcledgerlinesfunctor.cpp
+++ b/src/calcledgerlinesfunctor.cpp
@@ -31,22 +31,29 @@ FunctorCode CalcLedgerLinesFunctor::VisitNote(Note *note)
         return FUNCTOR_SIBLINGS;
     }
 
-    Staff *staff = note->GetAncestorStaff(RESOLVE_CROSS_STAFF);
+    this->CalcFor(note);
+
+    return FUNCTOR_SIBLINGS;
+}
+
+void CalcLedgerLinesFunctor::CalcFor(LayerElement *layerElement)
+{
+    /*
+    Staff *staff = layerElement->GetAncestorStaff(RESOLVE_CROSS_STAFF);
     const int staffSize = staff->m_drawingStaffSize;
     const int staffX = staff->GetDrawingX();
     const bool drawingCueSize = note->GetDrawingCueSize();
-    const int radius = note->GetDrawingRadius(m_doc);
+    const int radius = layerElement->GetDrawingRadius(m_doc);
 
-    /************** Ledger lines: **************/
 
     int linesAbove = 0;
     int linesBelow = 0;
 
-    if (!note->HasLedgerLines(linesAbove, linesBelow, staff)) return FUNCTOR_SIBLINGS;
+    if (!layerElement->HasLedgerLines(linesAbove, linesBelow, staff)) return FUNCTOR_SIBLINGS;
 
     const int extension = m_doc->GetDrawingLedgerLineExtension(staffSize, drawingCueSize);
-    const int left = note->GetDrawingX() - extension - staffX;
-    int right = note->GetDrawingX() + 2 * radius + extension - staffX;
+    const int left = layerElement->GetDrawingX() - extension - staffX;
+    int right = layerElement->GetDrawingX() + 2 * radius + extension - staffX;
 
     if (linesAbove > 0) {
         staff->AddLedgerLineAbove(linesAbove, left, right, extension, drawingCueSize);
@@ -54,8 +61,7 @@ FunctorCode CalcLedgerLinesFunctor::VisitNote(Note *note)
     else {
         staff->AddLedgerLineBelow(linesBelow, left, right, extension, drawingCueSize);
     }
-
-    return FUNCTOR_SIBLINGS;
+    */
 }
 
 FunctorCode CalcLedgerLinesFunctor::VisitStaffEnd(Staff *staff)
diff --git a/src/note.cpp b/src/note.cpp
index 54af2ee5695..3421cfb3cc7 100644
--- a/src/note.cpp
+++ b/src/note.cpp
@@ -214,21 +214,6 @@ const Accid *Note::GetDrawingAccid() const
     return vrv_cast<const Accid *>(this->FindDescendantByType(ACCID));
 }
 
-bool Note::HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff) const
-{
-    if (!staff) {
-        staff = this->GetAncestorStaff();
-    }
-
-    linesAbove = (this->GetDrawingLoc() - staff->m_drawingLines * 2 + 2) / 2;
-    linesBelow = -(this->GetDrawingLoc()) / 2;
-
-    linesAbove = std::max(linesAbove, 0);
-    linesBelow = std::max(linesBelow, 0);
-
-    return ((linesAbove > 0) || (linesBelow > 0));
-}
-
 Chord *Note::IsChordTone()
 {
     return vrv_cast<Chord *>(this->GetFirstAncestor(CHORD, MAX_CHORD_DEPTH));
diff --git a/src/positioninterface.cpp b/src/positioninterface.cpp
index 05c0ce496bb..f2c7505a6bf 100644
--- a/src/positioninterface.cpp
+++ b/src/positioninterface.cpp
@@ -71,6 +71,24 @@ int PositionInterface::CalcDrawingLoc(const Layer *layer, const LayerElement *el
     return m_drawingLoc;
 }
 
+bool PositionInterface::HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff) const
+{
+    /*
+    if (!staff) {
+        staff = this->GetAncestorStaff();
+    }
+
+    linesAbove = (this->GetDrawingLoc() - staff->m_drawingLines * 2 + 2) / 2;
+    linesBelow = -(this->GetDrawingLoc()) / 2;
+
+    linesAbove = std::max(linesAbove, 0);
+    linesBelow = std::max(linesBelow, 0);
+
+    return ((linesAbove > 0) || (linesBelow > 0));
+     */
+    return false;
+}
+
 //----------------------------------------------------------------------------
 // Interface pseudo functor (redirected)
 //----------------------------------------------------------------------------

From 790545c9a7a10c020ee7ed5541d7a90ec9c24dca Mon Sep 17 00:00:00 2001
From: Laurent Pugin <lxpugin@gmail.com>
Date: Mon, 11 Nov 2024 12:20:44 +0100
Subject: [PATCH 2/4] Remove duplicating Note::m_drawingLoc

---
 include/vrv/note.h | 14 --------------
 src/note.cpp       |  1 -
 2 files changed, 15 deletions(-)

diff --git a/include/vrv/note.h b/include/vrv/note.h
index d7872a8b3f3..aaf6a461b56 100644
--- a/include/vrv/note.h
+++ b/include/vrv/note.h
@@ -123,15 +123,6 @@ class Note : public LayerElement,
     const Accid *GetDrawingAccid() const;
     ///@}
 
-    /**
-     * @name Setter and getter for the drawing staff loc.
-     * This is set by the CalcAlignmentPitchPosFunctor.
-     */
-    ///@{
-    void SetDrawingLoc(int drawingLoc) { m_drawingLoc = drawingLoc; }
-    int GetDrawingLoc() const { return m_drawingLoc; }
-    ///@}
-
     /**
      * Overriding functions to return information from chord parent if any
      */
@@ -318,11 +309,6 @@ class Note : public LayerElement,
 public:
     //
 private:
-    /**
-     * The drawing location of the note
-     */
-    int m_drawingLoc;
-
     /**
      * A fling indicating if the note head is flipped
      */
diff --git a/src/note.cpp b/src/note.cpp
index 3421cfb3cc7..f0bd536ecad 100644
--- a/src/note.cpp
+++ b/src/note.cpp
@@ -121,7 +121,6 @@ void Note::Reset()
     m_noteGroupPosition = 0;
     m_noteGroup = NULL;
 
-    m_drawingLoc = 0;
     m_flippedNotehead = false;
 
     m_stemSameas = NULL;

From 27555e76cd79815edf58a40803999c9b7a4d9062 Mon Sep 17 00:00:00 2001
From: Laurent Pugin <lxpugin@gmail.com>
Date: Mon, 11 Nov 2024 13:35:11 +0100
Subject: [PATCH 3/4] Add ledger lines to accid direct children of layer

---
 include/vrv/calcledgerlinesfunctor.h |  3 +-
 include/vrv/positioninterface.h      |  2 +-
 src/accid.cpp                        |  3 +-
 src/calcledgerlinesfunctor.cpp       | 45 +++++++++++++++++++++-------
 src/calcstemfunctor.cpp              |  4 ++-
 src/positioninterface.cpp            |  8 ++---
 6 files changed, 46 insertions(+), 19 deletions(-)

diff --git a/include/vrv/calcledgerlinesfunctor.h b/include/vrv/calcledgerlinesfunctor.h
index e6bd8797cd2..826d66a2206 100644
--- a/include/vrv/calcledgerlinesfunctor.h
+++ b/include/vrv/calcledgerlinesfunctor.h
@@ -38,6 +38,7 @@ class CalcLedgerLinesFunctor : public DocFunctor {
      * Functor interface
      */
     ///@{
+    FunctorCode VisitAccid(Accid *accid) override;
     FunctorCode VisitNote(Note *note) override;
     FunctorCode VisitStaffEnd(Staff *staff) override;
     ///@}
@@ -48,7 +49,7 @@ class CalcLedgerLinesFunctor : public DocFunctor {
     /**
      *
      */
-    void CalcFor(LayerElement *layerElement);
+    void CalcForLayerElement(LayerElement *layerElement, int width, data_HORIZONTALALIGNMENT alignment);
     /**
      * Shorten ledger lines which overlap with neighbors
      */
diff --git a/include/vrv/positioninterface.h b/include/vrv/positioninterface.h
index 9d65cb89768..554b200037f 100644
--- a/include/vrv/positioninterface.h
+++ b/include/vrv/positioninterface.h
@@ -63,7 +63,7 @@ class PositionInterface : public Interface, public AttStaffLoc, public AttStaffL
      * Otherwise, it will look for the Staff ancestor.
      * Set the value of ledger lines above or below.
      */
-    bool HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff = NULL) const;
+    bool HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff) const;
 
     //-----------------//
     // Pseudo functors //
diff --git a/src/accid.cpp b/src/accid.cpp
index 73a12003ff8..e97ed1e5f85 100644
--- a/src/accid.cpp
+++ b/src/accid.cpp
@@ -130,7 +130,8 @@ void Accid::AdjustX(LayerElement *element, const Doc *doc, int staffSize, std::v
         Note *note = vrv_cast<Note *>(element);
         int ledgerAbove = 0;
         int ledgerBelow = 0;
-        if (note->HasLedgerLines(ledgerAbove, ledgerBelow)) {
+        Staff *staff = note->GetAncestorStaff(RESOLVE_CROSS_STAFF);
+        if (note->HasLedgerLines(ledgerAbove, ledgerBelow, staff)) {
             const int value = doc->GetOptions()->m_ledgerLineExtension.GetValue() * unit + 0.5 * horizontalMargin;
             horizontalMargin = std::max(horizontalMargin, value);
         }
diff --git a/src/calcledgerlinesfunctor.cpp b/src/calcledgerlinesfunctor.cpp
index 62bb40625dd..bef0616bf2b 100644
--- a/src/calcledgerlinesfunctor.cpp
+++ b/src/calcledgerlinesfunctor.cpp
@@ -10,6 +10,7 @@
 //----------------------------------------------------------------------------
 
 #include "doc.h"
+#include "dot.h"
 #include "note.h"
 #include "staff.h"
 
@@ -21,6 +22,21 @@ namespace vrv {
 
 CalcLedgerLinesFunctor::CalcLedgerLinesFunctor(Doc *doc) : DocFunctor(doc) {}
 
+FunctorCode CalcLedgerLinesFunctor::VisitAccid(Accid *accid)
+{
+    if (accid->GetFirstAncestor(NOTE)) {
+        return FUNCTOR_SIBLINGS;
+    }
+
+    Staff *staff = accid->GetAncestorStaff();
+
+    const int width = m_doc->GetGlyphWidth(Accid::GetAccidGlyph(accid->GetAccid()), staff->m_drawingStaffSize, false);
+
+    this->CalcForLayerElement(accid, width, HORIZONTALALIGNMENT_center);
+
+    return FUNCTOR_SIBLINGS;
+}
+
 FunctorCode CalcLedgerLinesFunctor::VisitNote(Note *note)
 {
     if (note->GetVisible() == BOOLEAN_false) {
@@ -31,29 +47,39 @@ FunctorCode CalcLedgerLinesFunctor::VisitNote(Note *note)
         return FUNCTOR_SIBLINGS;
     }
 
-    this->CalcFor(note);
+    const int radius = note->GetDrawingRadius(m_doc);
+
+    this->CalcForLayerElement(note, 2 * radius, HORIZONTALALIGNMENT_left);
 
     return FUNCTOR_SIBLINGS;
 }
 
-void CalcLedgerLinesFunctor::CalcFor(LayerElement *layerElement)
+void CalcLedgerLinesFunctor::CalcForLayerElement(
+    LayerElement *layerElement, int width, data_HORIZONTALALIGNMENT alignment)
 {
-    /*
     Staff *staff = layerElement->GetAncestorStaff(RESOLVE_CROSS_STAFF);
+    assert(staff);
+
     const int staffSize = staff->m_drawingStaffSize;
     const int staffX = staff->GetDrawingX();
-    const bool drawingCueSize = note->GetDrawingCueSize();
-    const int radius = layerElement->GetDrawingRadius(m_doc);
-
+    const bool drawingCueSize = layerElement->GetDrawingCueSize();
 
     int linesAbove = 0;
     int linesBelow = 0;
 
-    if (!layerElement->HasLedgerLines(linesAbove, linesBelow, staff)) return FUNCTOR_SIBLINGS;
+    PositionInterface *interface = layerElement->GetPositionInterface();
+    assert(interface);
+
+    if (!interface->HasLedgerLines(linesAbove, linesBelow, staff)) return;
 
     const int extension = m_doc->GetDrawingLedgerLineExtension(staffSize, drawingCueSize);
-    const int left = layerElement->GetDrawingX() - extension - staffX;
-    int right = layerElement->GetDrawingX() + 2 * radius + extension - staffX;
+    int left = layerElement->GetDrawingX() - extension - staffX;
+    int right = layerElement->GetDrawingX() + width + extension - staffX;
+
+    if (alignment == HORIZONTALALIGNMENT_center) {
+        right -= width / 2;
+        left -= width / 2;
+    }
 
     if (linesAbove > 0) {
         staff->AddLedgerLineAbove(linesAbove, left, right, extension, drawingCueSize);
@@ -61,7 +87,6 @@ void CalcLedgerLinesFunctor::CalcFor(LayerElement *layerElement)
     else {
         staff->AddLedgerLineBelow(linesBelow, left, right, extension, drawingCueSize);
     }
-    */
 }
 
 FunctorCode CalcLedgerLinesFunctor::VisitStaffEnd(Staff *staff)
diff --git a/src/calcstemfunctor.cpp b/src/calcstemfunctor.cpp
index 17a65040e5a..df7a50f18c1 100644
--- a/src/calcstemfunctor.cpp
+++ b/src/calcstemfunctor.cpp
@@ -660,7 +660,9 @@ void CalcStemFunctor::AdjustFlagPlacement(
     }
     int ledgerAbove = 0;
     int ledgerBelow = 0;
-    if (!note || !note->HasLedgerLines(ledgerAbove, ledgerBelow)) return;
+
+    Staff *staff = note->GetAncestorStaff(RESOLVE_CROSS_STAFF);
+    if (!note || !note->HasLedgerLines(ledgerAbove, ledgerBelow, staff)) return;
     if (((stemDirection == STEMDIRECTION_up) && !ledgerBelow)
         || ((stemDirection == STEMDIRECTION_down) && !ledgerAbove))
         return;
diff --git a/src/positioninterface.cpp b/src/positioninterface.cpp
index f2c7505a6bf..d3bf0abed6d 100644
--- a/src/positioninterface.cpp
+++ b/src/positioninterface.cpp
@@ -15,6 +15,7 @@
 
 #include "layer.h"
 #include "pitchinterface.h"
+#include "staff.h"
 
 namespace vrv {
 
@@ -73,10 +74,7 @@ int PositionInterface::CalcDrawingLoc(const Layer *layer, const LayerElement *el
 
 bool PositionInterface::HasLedgerLines(int &linesAbove, int &linesBelow, const Staff *staff) const
 {
-    /*
-    if (!staff) {
-        staff = this->GetAncestorStaff();
-    }
+    if (!staff) return false;
 
     linesAbove = (this->GetDrawingLoc() - staff->m_drawingLines * 2 + 2) / 2;
     linesBelow = -(this->GetDrawingLoc()) / 2;
@@ -85,7 +83,7 @@ bool PositionInterface::HasLedgerLines(int &linesAbove, int &linesBelow, const S
     linesBelow = std::max(linesBelow, 0);
 
     return ((linesAbove > 0) || (linesBelow > 0));
-     */
+
     return false;
 }
 

From f96a142be9c27e047f06f95c9ae76e7ddfc7fc0e Mon Sep 17 00:00:00 2001
From: Laurent Pugin <lxpugin@gmail.com>
Date: Mon, 11 Nov 2024 14:33:33 +0100
Subject: [PATCH 4/4] Prevent accids with the same aligner to crash

---
 src/adjustaccidxfunctor.cpp | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/adjustaccidxfunctor.cpp b/src/adjustaccidxfunctor.cpp
index f4baadfb231..d02ca426361 100644
--- a/src/adjustaccidxfunctor.cpp
+++ b/src/adjustaccidxfunctor.cpp
@@ -133,7 +133,7 @@ std::vector<Accid *> AdjustAccidXFunctor::GetAccidentalsForAdjustment(AlignmentR
     for (Object *child : alignmentReference->GetChildren()) {
         if (child->Is(ACCID)) {
             Accid *accid = vrv_cast<Accid *>(child);
-            if (accid->HasAccid()) accidentals.push_back(accid);
+            if (accid->HasAccid() && accid->GetFirstAncestor(NOTE)) accidentals.push_back(accid);
         }
     }
     return accidentals;