Skip to content

fix(measurement-tool): apply devicePixelRatio in legacy applyToolTran…#229

Open
sebcarley wants to merge 1 commit into
OpenAEC-Foundation:mainfrom
sebcarley:fix/retina-dpr-measurement-preview
Open

fix(measurement-tool): apply devicePixelRatio in legacy applyToolTran…#229
sebcarley wants to merge 1 commit into
OpenAEC-Foundation:mainfrom
sebcarley:fix/retina-dpr-measurement-preview

Conversation

@sebcarley

Copy link
Copy Markdown

Summary
On Retina (HiDPI) displays, the in-progress measurement preview is drawn at half size and anchored to the page origin instead of tracking the cursor. The final shape (after Enter) draws correctly. Affects area and perimeter measurement tools.
Root cause
In js/tools/tool-context.js, applyToolTransform has two branches. The vector-viewport branch correctly uses setTransform with the active viewport zoom. The legacy branch uses:
jsconst scale = doc?.scale || 1.5;
ctx.scale(scale, scale);
But the page itself is rendered at scale * devicePixelRatio (DPR=2 on Retina). The preview transform drops the DPR factor, so the preview lands at half size from origin (0,0).
The function's header comment notes "DPR handled elsewhere" for legacy mode, but in the preview-drawing call path it isn't.
I confirmed via dev-console logging that when applyToolTransform runs from _measureMultiClickMove, the canvas is at the identity transform — the function is correctly being called from a clean state, just applying the wrong total transform.
Fix
jsconst dpr = window.devicePixelRatio || 1;
ctx.setTransform(scale * dpr, 0, 0, scale * dpr, 0, 0);
Switched from ctx.scale() to ctx.setTransform() for symmetry with the vector-viewport branch above. At identity-canvas state the two are equivalent, so other tools that call applyToolTransform (angle, draw, spline, calibration-pick, arc, select) are unaffected — verified all still working.
Testing

macOS 26.4.1, Apple Silicon, devicePixelRatio = 2
Built from main (v1.46.0)
Confirmed area and perimeter previews now track the cursor at the correct scale and position, at all zoom levels
Confirmed other tools (angle, draw, calibration) still render correctly

Notes
I'm a non-developer who hit this bug while building from source for personal use. Happy to make any changes you'd like, or if you'd prefer to handle it differently, feel free to close this and I'll learn from whatever you ship.

…sform

On Retina (HiDPI) displays the in-progress measurement preview was drawn
at half size and anchored to the page origin instead of tracking the cursor.

The page is rendered at scale * devicePixelRatio, but the legacy branch of
applyToolTransform only applied scale, dropping the DPR factor. The header
comment notes 'DPR handled elsewhere' for legacy mode, but in this code path
it wasn't.

Use ctx.setTransform with scale * dpr so the legacy branch matches the page
render transform. Switched from ctx.scale to ctx.setTransform for symmetry
with the vector-viewport branch above; at identity-canvas state the two are
equivalent, so other tools that call applyToolTransform are unaffected.

Verified on macOS 26.4.1, Apple Silicon, devicePixelRatio=2.

Affects: area and perimeter measurement tools (any tool calling
applyToolTransform after ctx.redraw()).
@sebcarley sebcarley requested a review from mojtabakarimi as a code owner May 6, 2026 14:01
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.

1 participant