fix #2839: scale horizontal layout width with display.scale - #2894
Open
leocaseiro wants to merge 1 commit into
Open
leocaseiro wants to merge 1 commit into
leocaseiro wants to merge 1 commit into
Conversation
HorizontalScreenLayout scaled this.height by display.scale but left this.width in unscaled layout units. ScoreRenderer publishes that value as renderFinished.totalWidth, which on web sizes the overflow:hidden surface element, so with a scale above 1 everything past 1/scale of the score was clipped and unreachable by scrolling. Keep this.width in scaled units for the whole layout pass like the vertical layouts do, and use scaledWidth for the per-partial totalWidth. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Note
AI-authored disclosure (
alphatab-ai-authored-v1)Portions of this content were authored by an AI agent. The agent has read
AGENTS.md and the human submitter accepts responsibility for
compliance with the rules in that document.
Issues
Fixes #2839
Note on acceptance: #2839 is assigned to @Danielku15 but is not labelled
state-accepted. I read the assignment as triage, since no open issue currently carries that label — if that is the wrong read, happy to park this until the issue is formally accepted.Proposed changes
HorizontalScreenLayout.doLayoutAndRenderscalesthis.heightbydisplay.scaleat the end of the pass, but leavesthis.widthin unscaled layout units.ScoreRendererpublishes that value asrenderFinished.totalWidth, andAlphaTabApiBaseuses it to size the canvas element — on web that is theoverflow: hidden.at-surface. Withdisplay.scale > 1the surface ends up at1/scaleof the rendered content, so the tail of the score is clipped and unreachable by scrolling, and the playhead runs past the visible area.This keeps
this.widthin scaled units for the whole layout pass, the way the vertical layouts do, soScoreLayout.scaledWidthhands back the unscaled layout width where it is needed — including for the per-partialtotalWidth, whichVerticalLayoutBasealready reports that way.Measured in Chrome, both sides built from source with
npm run build, 30 bars,layoutMode: Horizontal,scale: 2:develop@ 212f2ec.at-surfacewidthscrollWidthScrolled all the way right,
developstops at bar 15 of 30; with the change the final barline is reached.Smaller alternative
A single
this.width *= this.renderer.settings.display.scale;next to the existingthis.height *= ...line fixes the reported symptom identically — I measured both and the surface width and scroll range come out the same. I went with the version in this PR because it also keepse.totalWidthcorrect on the per-partialpartialLayoutFinishedevents: with the one-liner those stay a factor ofscaletoo small, becausethis.widthis still unscaled whilelayoutAndRenderBottomScoreInfoand_layoutAndRenderAnnotationrun. Happy to switch to the one-liner if you would rather keep the diff minimal.Root-cause analysis
Which layer is the cause? The layout layer, not the renderer or the web bindings. The partials are already positioned, sized and painted correctly at every scale — only the total reported for the whole layout is wrong.
ScoreLayout.widthis device-space for every other layout (PageViewLayoutassignsthis.renderer.widthto it, andscaledWidthis defined asthis.width / scaleto convert back), andHorizontalScreenLayoutis the one place that leaves it in layout units.General defect or input-specific? Neither — it is a regression, and it affects every score in horizontal layout at
scale != 1. It came in with abc38b9 (first released in v1.7.0), which moved the* scaleonheightto the end ofdoLayoutAndRenderand dropped the one onwidth:The height half of that commit is correct and untouched here; this restores the width half in the same shape.
Does the fix apply consistently across TS, .NET and Kotlin? Yes — the change is in the shared layout source, so it transpiles into the .NET and Kotlin outputs unchanged. I verified the behaviour on web only, since the
overflow: hiddensurface element is what makes it visible there; thetotalWidthcontract it fixes is the same on all three.Do existing tests still hold, and what should be added? The full
packages/alphatabsuite is green locally — 79 files, 1760 tests, including the visual reference tests. The visual tests are unaffected because they run atdisplay.scale1, where* scaleis a no-op. They also could not have caught this: they compare painted partials, and the partials were always correct. The gap was that nothing asserted the reported total, which is what embedders size their scroll surface with — so that is what the new test covers.Checklist
test/rendering/HorizontalScreenLayoutScale.test.tsrenders the horizontal layout atscale1 and 2 and asserts that the reported total width scales like the total height, and that every partial reports the same total width as the final result. Both assertions fail ondevelop(the width comes back at exactly half) and pass with this change.AI authorship disclosure
alphatab-ai-authored-v1) is present at the top of this body, and I have personally reviewed every change and can explain each oneFurther details
🤖 Generated with Claude Code