From 5c74adde39bf0f4e472408a5cf9dad85d4757a0d Mon Sep 17 00:00:00 2001 From: pyonpyoco <60975353+pyonpyoco@users.noreply.github.com> Date: Sun, 28 Jun 2026 16:23:07 +0900 Subject: [PATCH 1/3] Fix chord bracket spacing with accidentals in other voices --- src/engraving/rendering/score/tlayout.cpp | 36 +++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-) diff --git a/src/engraving/rendering/score/tlayout.cpp b/src/engraving/rendering/score/tlayout.cpp index ff48e59d73a88..4d28dc80f17ef 100644 --- a/src/engraving/rendering/score/tlayout.cpp +++ b/src/engraving/rendering/score/tlayout.cpp @@ -870,6 +870,39 @@ void TLayout::layoutArpeggio(const Arpeggio* item, Arpeggio::LayoutData* ldata, } } +static Shape chordBracketObstacleShape(const ChordBracket* item) +{ + Chord* owner = item->chord(); + Shape ownerShape = owner->shape(); + ownerShape.removeTypes({ ElementType::CHORD_BRACKET, ElementType::ARPEGGIO }); + if (!owner->segment() || !owner->staff()) { + return ownerShape; + } + + Shape result; + const track_idx_t startTrack = staff2track(owner->staffIdx()); + const track_idx_t endTrack = startTrack + VOICES; + + for (track_idx_t track = startTrack; track < endTrack; ++track) { + EngravingItem* e = owner->segment()->element(track); + if (!e || !e->isChord()) { + continue; + } + + Chord* chord = toChord(e); + if (chord->vStaffIdx() != owner->vStaffIdx()) { + continue; + } + + Shape chordShape = chord->shape(); + chordShape.removeTypes({ ElementType::CHORD_BRACKET, ElementType::ARPEGGIO }); + chordShape.translate(chord->pos() - owner->pos()); + result.add(chordShape); + } + + return result.empty() ? ownerShape : result; +} + void TLayout::layoutChordBracket(const ChordBracket* item, Arpeggio::LayoutData* ldata, const LayoutConfiguration& conf) { double spatium = item->spatium(); @@ -896,8 +929,7 @@ void TLayout::layoutChordBracket(const ChordBracket* item, Arpeggio::LayoutData* const Note* upnote = item->chord()->upNote(); ldata->setPosY(upnote->y() + upnote->ldata()->bbox().top()); - Shape chordShape = item->chord()->shape(); - chordShape.removeTypes({ ElementType::CHORD_BRACKET, ElementType::ARPEGGIO }); + Shape chordShape = chordBracketObstacleShape(item); Shape itemShape = item->shape().translated(PointF(0.0, item->ldata()->pos().y())); if (item->rightSide()) { double x = HorizontalSpacing::minHorizontalDistance(chordShape, itemShape, spatium); From e74d4b6ec1f08b0a40f161ba7365e33ecdbea721 Mon Sep 17 00:00:00 2001 From: pyonpyoco <60975353+pyonpyoco@users.noreply.github.com> Date: Thu, 2 Jul 2026 01:25:26 +0900 Subject: [PATCH 2/3] Refine chord bracket shape collection --- src/engraving/rendering/score/tlayout.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/engraving/rendering/score/tlayout.cpp b/src/engraving/rendering/score/tlayout.cpp index 4d28dc80f17ef..f354242828a8a 100644 --- a/src/engraving/rendering/score/tlayout.cpp +++ b/src/engraving/rendering/score/tlayout.cpp @@ -870,21 +870,24 @@ void TLayout::layoutArpeggio(const Arpeggio* item, Arpeggio::LayoutData* ldata, } } -static Shape chordBracketObstacleShape(const ChordBracket* item) +static Shape getChordsShape(const ChordBracket* item) { Chord* owner = item->chord(); - Shape ownerShape = owner->shape(); - ownerShape.removeTypes({ ElementType::CHORD_BRACKET, ElementType::ARPEGGIO }); + Shape result = owner->shape(); + result.removeTypes({ ElementType::CHORD_BRACKET, ElementType::ARPEGGIO }); if (!owner->segment() || !owner->staff()) { - return ownerShape; + return result; } - Shape result; const track_idx_t startTrack = staff2track(owner->staffIdx()); const track_idx_t endTrack = startTrack + VOICES; for (track_idx_t track = startTrack; track < endTrack; ++track) { EngravingItem* e = owner->segment()->element(track); + if (track == owner->track()) { + continue; + } + if (!e || !e->isChord()) { continue; } @@ -900,7 +903,7 @@ static Shape chordBracketObstacleShape(const ChordBracket* item) result.add(chordShape); } - return result.empty() ? ownerShape : result; + return result; } void TLayout::layoutChordBracket(const ChordBracket* item, Arpeggio::LayoutData* ldata, const LayoutConfiguration& conf) @@ -929,7 +932,7 @@ void TLayout::layoutChordBracket(const ChordBracket* item, Arpeggio::LayoutData* const Note* upnote = item->chord()->upNote(); ldata->setPosY(upnote->y() + upnote->ldata()->bbox().top()); - Shape chordShape = chordBracketObstacleShape(item); + Shape chordShape = getChordsShape(item); Shape itemShape = item->shape().translated(PointF(0.0, item->ldata()->pos().y())); if (item->rightSide()) { double x = HorizontalSpacing::minHorizontalDistance(chordShape, itemShape, spatium); From 7e1b02cddbd683b5920d4f766d3ff1983304786b Mon Sep 17 00:00:00 2001 From: pyonpyoco <60975353+pyonpyoco@users.noreply.github.com> Date: Sat, 4 Jul 2026 15:00:39 +0900 Subject: [PATCH 3/3] Relayout chord brackets after segment layout --- src/engraving/rendering/score/chordlayout.cpp | 24 +++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/src/engraving/rendering/score/chordlayout.cpp b/src/engraving/rendering/score/chordlayout.cpp index 6eeed77f0b030..7c900f94d579b 100644 --- a/src/engraving/rendering/score/chordlayout.cpp +++ b/src/engraving/rendering/score/chordlayout.cpp @@ -1656,6 +1656,26 @@ static void layoutSegmentElements(Segment* segment, track_idx_t startTrack, trac } } +static void relayoutChordBracketsAfterSegmentLayout(const std::vector& chords, LayoutContext& ctx) +{ + for (Chord* chord : chords) { + bool hasChordBracket = false; + + for (EngravingItem* e : chord->el()) { + if (!e->isChordBracket()) { + continue; + } + + hasChordBracket = true; + TLayout::layoutItem(e, ctx); + } + + if (hasChordBracket) { + ChordLayout::fillShape(chord, chord->mutldata(), ctx.conf()); + } + } +} + void ChordLayout::skipAccidentals(Segment* segment, track_idx_t startTrack, track_idx_t endTrack) { for (track_idx_t track = startTrack; track < endTrack; ++track) { @@ -2301,6 +2321,10 @@ void ChordLayout::layoutChords1(LayoutContext& ctx, Segment* segment, staff_idx_ TLayout::layoutOrnamentCueNote(ornament, ctx); } } + + // Chord brackets depend on the final layouts of all voices in the same segment and visual staff. + // Re-layout them after the segment elements have been laid out. + relayoutChordBracketsAfterSegmentLayout(posInfo.chords, ctx); } //---------------------------------------------------------