Skip to content

Follow-up: Fix chord bracket layout across visual staves - #34434

Open
pyonpyoco wants to merge 5 commits into
musescore:mainfrom
pyonpyoco:fix/multi-staff-chord-bracket-layout
Open

Follow-up: Fix chord bracket layout across visual staves#34434
pyonpyoco wants to merge 5 commits into
musescore:mainfrom
pyonpyoco:fix/multi-staff-chord-bracket-layout

Conversation

@pyonpyoco

Copy link
Copy Markdown
Contributor

Follow-up to #33983 (comment)

This PR extends the previous chord bracket spacing fix to cases where the relevant chords are distributed across visual staves.

Problems addressed

Case 1

A chord bracket is visually contained within a single staff, but one of the chords spanned by the bracket is a cross-staff chord.
スクリーンショット 2026-07-29 184615

Case 2

A chord bracket spans chords that are visually placed on multiple staves within the same part.
スクリーンショット 2026-07-29 184230

In the Case 2 matrix, * marks a rendering where the accidental and chord bracket collide.
The matrix covers 16 combinations of the relative pitch ordering of the bracket anchors and voices 1 and 2 on the upper and lower staves. Each combination is repeated with the accidental placed on each of the four chords, producing 64 renderings in total.

In these cases, accidentals on the relevant chords were not consistently taken into account when positioning the chord bracket.

Root cause and design rationale

Chord bracket layout previously ran at Chord scope. In cross-staff cases, some of the geometry needed for placement belongs to another visual staff and may not yet be available, depending on staff and track iteration order.

The layout is therefore moved to Segment scope, where all chords at the same tick can be considered together. The process consists of initial horizontal placement after staff-local chord layout, horizontal spacing between Segments, and a final vertical update after staff distances are known.

The existing tablature layout path is left unchanged.

Implementation

A new ChordBracketLayout component handles pitched chord brackets at Segment scope. Its methods correspond to the three layout stages:

  • layoutSegment() performs the initial horizontal placement.
  • updateHorizontalSpacing() accounts for brackets when spacing adjacent Segments.
  • updateVerticalGeometry() performs the final update after staff spacing.

MeasureLayout runs the Segment-level pass before Segment Shapes are finalized, while page and horizontal view layout perform the final vertical update after staff spacing.

The chord-level layout and relayout passes for pitched chord brackets are removed.

TLayout also normalizes reversed top and bottom coordinates when the bracket endpoints are manually edited.

Tests

Manually verified the layout results for both cases shown above.

Test score: 33883_chordBracket4c.zip

スクリーンショット 2026-07-29 191122 スクリーンショット 2026-07-29 191116
  • I signed the CLA as username: 9zu8co
  • The title of the PR describes the problem it addresses.
  • Each commit's message describes its purpose and effects, and references the issue it resolves. If changes are extensive, there is a sequence of easily reviewable commits.
  • The code in the PR follows the coding rules.
  • I understand all aspects of the code I'm contributing and I'm able to explain it if requested.
  • The code compiles and runs on my machine, preferably after each commit individually. I have manually tested and verified that my changes fulfil their intended purpose.
  • No prior attempts to resolve this problem exist, or if they do, I listed them in my PR description and described how I avoided repeating past mistakes.
  • There are no unnecessary changes.
  • I created a unit test or vtest to verify the changes I made (if applicable).

@coderabbitai

coderabbitai Bot commented Aug 1, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 41294cd9-8985-4073-996c-7570ac06426b

📥 Commits

Reviewing files that changed from the base of the PR and between c538e5f and 3a93707.

📒 Files selected for processing (9)
  • src/engraving/rendering/score/chordbracketlayout.cpp
  • src/engraving/rendering/score/chordbracketlayout.h
  • src/engraving/rendering/score/chordlayout.cpp
  • src/engraving/rendering/score/horizontalspacing.cpp
  • src/engraving/rendering/score/measurelayout.cpp
  • src/engraving/rendering/score/pagelayout.cpp
  • src/engraving/rendering/score/rendering.cmake
  • src/engraving/rendering/score/scorehorizontalviewlayout.cpp
  • src/engraving/rendering/score/tlayout.cpp
💤 Files with no reviewable changes (1)
  • src/engraving/rendering/score/chordlayout.cpp
🚧 Files skipped from review as they are similar to previous changes (8)
  • src/engraving/rendering/score/rendering.cmake
  • src/engraving/rendering/score/scorehorizontalviewlayout.cpp
  • src/engraving/rendering/score/pagelayout.cpp
  • src/engraving/rendering/score/tlayout.cpp
  • src/engraving/rendering/score/chordbracketlayout.h
  • src/engraving/rendering/score/horizontalspacing.cpp
  • src/engraving/rendering/score/chordbracketlayout.cpp
  • src/engraving/rendering/score/measurelayout.cpp

📝 Walkthrough

Walkthrough

This change adds a dedicated ChordBracketLayout utility. It computes bracket spans, collision shapes, horizontal positions, spacing distances, and vertical geometry. Measure and horizontal-spacing stages now invoke bracket layout. Page and horizontal-view rendering use vertical geometry for non-tablature brackets and arpeggio layout for tablature brackets. Bracket shape bounds are normalized before storage.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: fixing chord bracket layout across visual staves.
Description check ✅ Passed The description explains the problem, design, implementation, testing, and checklist status, with only the issue-resolution template line omitted.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Warning

Review ran into problems

🔥 Problems

Linked repositories: Public OSS repositories can only analyze public repositories installed in this organization. No linked repositories were analyzed; skipped musescore/muse_framework.git.


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@src/engraving/rendering/score/chordbracketlayout.cpp`:
- Around line 84-129: Update bracketVisualSpan to apply the same 2 * spatium
minimum-length adjustment used by TLayout::layoutChordBracket() after computing
topY and bottomY, shifting both bounds equally to preserve the bracket hook
position. Ensure the adjusted span is used before the offset is applied and
returned, so bracketCollisionShape, layoutHorizontal, and
updateHorizontalSpacing match the rendered bracket.
- Around line 241-246: Update the updateForBrackets lambda in layoutSegment to
skip any bracket whose chord() is null before calling chord-dependent methods
such as onTabStaff(), bracketVisualSpan(), or pos().x(), matching the existing
guard used for segment entries.
- Around line 278-288: The updateVerticalGeometry method must regenerate the
chord bracket’s owner segment shape after relayout. After
TLayout::layoutItem(bracket, ctx), invoke TLayout::layoutChordBracket with the
bracket, its mutable layout data, and ctx.conf(), preserving the existing
horizontal-position restoration and avoiding ChordLayout::fillShape.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: b79776d6-1a47-47b8-a7ad-4c15ac0aba2d

📥 Commits

Reviewing files that changed from the base of the PR and between c1ad658 and d9084c9.

📒 Files selected for processing (9)
  • src/engraving/rendering/score/chordbracketlayout.cpp
  • src/engraving/rendering/score/chordbracketlayout.h
  • src/engraving/rendering/score/chordlayout.cpp
  • src/engraving/rendering/score/horizontalspacing.cpp
  • src/engraving/rendering/score/measurelayout.cpp
  • src/engraving/rendering/score/pagelayout.cpp
  • src/engraving/rendering/score/rendering.cmake
  • src/engraving/rendering/score/scorehorizontalviewlayout.cpp
  • src/engraving/rendering/score/tlayout.cpp
💤 Files with no reviewable changes (1)
  • src/engraving/rendering/score/chordlayout.cpp

Comment thread src/engraving/rendering/score/chordbracketlayout.cpp
Comment thread src/engraving/rendering/score/chordbracketlayout.cpp
Comment thread src/engraving/rendering/score/chordbracketlayout.cpp
@mathesoncalum
mathesoncalum requested a review from miiizen August 3, 2026 08:08
@pyonpyoco

Copy link
Copy Markdown
Contributor Author

Visual-test differences are present in chordBrackets-1 and chordBrackets-2.

In the attached example, the required horizontal spacing is A (upper staff, without ledger lines) < B (lower staff, with ledger lines). Previously, the two-staff case C followed A because spacing was based on the owner staff. This PR changes it to use max(A, B), so C now follows B.

Could you confirm whether the reference images should be updated for this change?

chordBrackets-1 - コピー

@pyonpyoco
pyonpyoco force-pushed the fix/multi-staff-chord-bracket-layout branch from 4d5329d to 3a93707 Compare August 5, 2026 09:39
@coderabbitai

coderabbitai Bot commented Aug 5, 2026

Copy link
Copy Markdown
Contributor

Note

GitHub couldn't provide a complete incremental comparison for this pull request, so CodeRabbit is performing a full review instead. This review may take a little longer.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants