Skip to content

Round node dimensions in double so far-off nodes keep their full size - #2037

Open
ybelakov wants to merge 2 commits into
react:mainfrom
ybelakov:fix/pixel-grid-double-difference
Open

ybelakov wants to merge 2 commits into
react:mainfrom
ybelakov:fix/pixel-grid-double-difference

Conversation

@ybelakov

@ybelakov ybelakov commented Oct 9, 2026 •

Copy link
Copy Markdown

Summary

roundLayoutResultsToPixelGrid computes a node's rounded width and height as the difference of its two rounded absolute edges. roundValueToPixelGrid returns float, so the subtraction happened in float. Far from the origin a float has fewer bits than a pixel (at y ≈ 2000 the step is 2⁻¹³ ≈ 0.00012pt; a 3x pixel is 0.333pt), and when the two edges fall on either side of a power of two they are quantized with different steps. The difference can then come out a float step short of the true size.

Concrete case (React Native 0.86, iOS, 3x screen): a measured text node with top at 2004⅓ and height 44 (two lines of lineHeight: 22) got height = 43.9998779296875. React Native hands that box to TextKit as the container, TextKit decides the second line doesn't fit, and the text is drawn as one unwrapped line clipped at the edge. User-facing report with a reproducer: react/react-native#58970.

This change rounds in double and subtracts before narrowing to float. roundValueToPixelGrid keeps its public signature and now wraps the double version.

Test plan

New test rounding_measured_height_is_exact_across_float_steps: a 3x config, a spacer, then a measured node returning 292×44, for spacers on both sides of 1024, 2048 and 4096. Heights on the previous code vs. this change (verified by compiling the Yoga sources with the test scenario directly; no CMake on this machine):

spacer before after
1012⅓ 44.0000610 44
1012⅔ 43.9999390 44
2004⅓ 43.9998779 44
2028⅔ 43.9998779 44
4052⅔ 43.9997559 44

Formatted by hand in the repo's style; clang-format wasn't available locally.

@meta-cla

meta-cla Bot commented Oct 9, 2026

Copy link
Copy Markdown

Hi @ybelakov!

Thank you for your pull request and welcome to our community.

Action Required

In order to merge any pull request (code, docs, etc.), we require contributors to sign our Contributor License Agreement, and we don't seem to have one on file for you.

Process

In order for us to review and merge your suggested changes, please sign at https://code.facebook.com/cla. If you are contributing on behalf of someone else (eg your employer), the individual CLA may not be sufficient and your employer may need to sign the corporate CLA.

Once the CLA is signed, our tooling will perform checks and validations. Afterwards, the pull request will be tagged with CLA signed. The tagging process may take up to 1 hour after signing. Please give it that time before contacting us about it.

If you have received this in error or have any questions, please contact us at cla@meta.com. Thanks!

A node's rounded width and height are the difference of its two rounded
absolute edges. roundValueToPixelGrid returns float, so that difference was
taken in float; far from the origin a float has fewer bits than a pixel, and
when the two edges fall on either side of a power of two they are quantized
differently. A measured text node spanning y = 2048 on a 3x screen came out
43.9998779 tall instead of 44, one float step short of the two lines it was
measured at, and the text renderer then dropped the last line.

Round in double and subtract before narrowing to float. The public
roundValueToPixelGrid keeps its signature.
@ybelakov
ybelakov force-pushed the fix/pixel-grid-double-difference branch from 9631935 to b7b0540 Compare October 9, 2026 14:26
@ybelakov

ybelakov commented Oct 9, 2026

Copy link
Copy Markdown
Author

React Native issue with a reproducer and screenshots: react/react-native#58970

…nding test

On the previous rounding each of these came out off by a float step
(44.00006, 43.99994, 43.99988, 43.99988 and 43.99976); all are exactly 44
now.

This branch has not been deployed

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

Labels

CLA Signed Shared with Meta Applied via automation to indicate that an Issue or Pull Request has been shared with the team.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant