fix: preserve integer text advances and inside stroke geometry - #40
Merged
Conversation
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.
The narrowest width of a screen diverged from Figma's own PNG six times worse than the widest one. Two separate defects were compounding; both are fixed here. Measured on
landingagainst Figma's reference PNG:landing-833-3640landing-833-3322landing-832-2975The rendered height now equals the design height at all three widths. Thresholds moved down only.
1. The line advance was a ratio
Figma advances each line by
round(fontSize x ratio); the browser accumulates the fraction. A ratio structurally cannot express an integer advance across several font sizes, which is why the sign of the error flipped with font size (38/18/28 too tall, 52/36 too short) and every uniform correction traded one width for another. The advance is now emitted as a whole-pixel length, and all seven measured text blocks match their design height exactly.A pixel advance is only valid for the size it was computed from, so the resolved font size travels with it. A percentage line height whose font size is missing or bound to a mode-dependent variable is refused with a typed error naming the node or text style, rather than emitted as a number that would be wrong at another size.
2. An inside stroke was taking layout space
Figma's inside stroke consumes no layout space. With
box-sizing: border-boxa CSS border eats into the content box, and the existing padding compensation cannot absorb it when the design's own padding is narrower than the stroke - padding cannot go negative. Every bordered auto-layout container therefore grew by twice its stroke weight and pushed everything below it down by exactly 2px, at every width.That case now paints inward with
outlineat a negative offset, which takes no layout space, and the padding compensation stands down for it. The decision keys on stroke alignment, layout mode, and stroke weight against padding - never on a viewport width - so it survives a design redrawn at another size.Corpus and provenance
Twenty-four plugin goldens change, each enumerated with its reason in
docs/line-box-displacement.md. Forty-seven of the forty-eight line-height changes are the ratio-to-integer conversion (1.6to26px); the remaining one is a node whose typography token previously suppressed its own resolved metrics. The corpus consistency test and manifest checksums are unchanged in force.Source map and provenance follow the emission:
outline/outlineOffsetcarry their stroke provenance, and a rich-text wrapper's own advance is attributed to the segment whose text follows it.Verification
Re-measured independently from this branch with a binary built here (
a9b96f24df75, SHA-2561859B639...), not from the worker's report:python scripts/acquire.py landingthennode scripts/render.mjsexits 0 against the tightened thresholds.Gates:
fmt0,clippy --locked --workspace --all-targets --all-features -D warnings0,cargo test --workspace1056 passed / 0 failed / 2 ignored,insta --checkno drift,stdio_smoke2 passed.