From 8afc5f5edd353def613fd90626d34bb593ea37cc Mon Sep 17 00:00:00 2001 From: Matt Diamant Date: Tue, 27 Oct 2026 10:43:32 -0700 Subject: [PATCH] fix(yoga): keep measured pixel size of text nodes when rounding to the pixel grid Backports facebook/yoga#2037 and facebook/yoga#2040. --- .../yoga/yoga/algorithm/PixelGrid.cpp | 58 +++++++++++++------ 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp index 61de2be2e8f6..afdc7da4d0fd 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp @@ -12,7 +12,9 @@ namespace facebook::yoga { -float roundValueToPixelGrid( +namespace { + +double roundValueToPixelGridDouble( const double value, const double pointScaleFactor, const bool forceCeil, @@ -59,7 +61,18 @@ float roundValueToPixelGrid( } return (std::isnan(scaledValue) || std::isnan(pointScaleFactor)) ? YGUndefined - : (float)(scaledValue / pointScaleFactor); + : scaledValue / pointScaleFactor; +} + +} // namespace + +float roundValueToPixelGrid( + const double value, + const double pointScaleFactor, + const bool forceCeil, + const bool forceFloor) { + return static_cast(roundValueToPixelGridDouble( + value, pointScaleFactor, forceCeil, forceFloor)); } void roundLayoutResultsToPixelGrid( @@ -98,9 +111,9 @@ void roundLayoutResultsToPixelGrid( // whole number, we don't have any fraction To verify if the result is close // to whole number we want to check both floor and ceil numbers - const double scaledNodeWith = nodeWidth * pointScaleFactor; + const double scaledNodeWidth = nodeWidth * pointScaleFactor; const bool hasFractionalWidth = - !yoga::inexactEquals(round(scaledNodeWith), scaledNodeWith); + !yoga::inexactEquals(round(scaledNodeWidth), scaledNodeWidth); const double scaledNodeHeight = nodeHeight * pointScaleFactor; const bool hasFractionalHeight = @@ -108,23 +121,32 @@ void roundLayoutResultsToPixelGrid( node->getLayout().setDimension( Dimension::Width, - roundValueToPixelGrid( - absoluteNodeRight, - pointScaleFactor, - (textRounding && hasFractionalWidth), - (textRounding && !hasFractionalWidth)) - - roundValueToPixelGrid( - absoluteNodeLeft, pointScaleFactor, false, textRounding)); + textRounding && !hasFractionalWidth + ? static_cast(round(scaledNodeWidth) / pointScaleFactor) + : static_cast( + roundValueToPixelGridDouble( + absoluteNodeRight, + pointScaleFactor, + textRounding, + false) - + roundValueToPixelGridDouble( + absoluteNodeLeft, + pointScaleFactor, + false, + textRounding))); node->getLayout().setDimension( Dimension::Height, - roundValueToPixelGrid( - absoluteNodeBottom, - pointScaleFactor, - (textRounding && hasFractionalHeight), - (textRounding && !hasFractionalHeight)) - - roundValueToPixelGrid( - absoluteNodeTop, pointScaleFactor, false, textRounding)); + textRounding && !hasFractionalHeight + ? static_cast(round(scaledNodeHeight) / pointScaleFactor) + : static_cast( + roundValueToPixelGridDouble( + absoluteNodeBottom, + pointScaleFactor, + textRounding, + false) - + roundValueToPixelGridDouble( + absoluteNodeTop, pointScaleFactor, false, textRounding))); } for (yoga::Node* child : node->getChildren()) {