From dce7242ab6855e7a546e6d25482311d995a4a63b Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Wed, 13 Sep 2023 14:11:25 -0700 Subject: [PATCH] Breaking: per-node pointScaleFactor (#39403) Summary: X-link: https://github.com/facebook/yoga/pull/1379 Pull Request resolved: https://github.com/facebook/react-native/pull/39403 Right now we have a `pointScaleFactor` per-node, but only ever read the one off the root node. In most cases where config is global, these will be the same, but it is possible for these to differ. This... doesn't make much sense from an API perspective, and there are edge cases where we may want to allow laying out a subtree with a different DPI then the rest of the tree (though I think there might be other solutions to that). We should rethink some of what is currently on config being allowed per-node (do we really need each node to be able to have a separate logger?), but this makes the model consistent in the meantime. This change is breaking to any users relying on setting `pointScaleFactor` on the config of the root node, but not other nodes. Reviewed By: yungsters Differential Revision: D49181131 fbshipit-source-id: f1363ca242094f04b995fd50c1e56834d5003425 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 7 +- .../yoga/yoga/algorithm/PixelGrid.cpp | 97 +++++++++---------- .../yoga/yoga/algorithm/PixelGrid.h | 1 - 3 files changed, 50 insertions(+), 55 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index c91b30391badf2..e12a46bf151c7a 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -2487,7 +2487,7 @@ bool calculateLayoutInternal( layout->cachedLayout.computedHeight, marginAxisRow, marginAxisColumn, - config)) { + node->getConfig())) { cachedResults = &layout->cachedLayout; } else { // Try to use the measurement cache. @@ -2505,7 +2505,7 @@ bool calculateLayoutInternal( layout->cachedMeasurements[i].computedHeight, marginAxisRow, marginAxisColumn, - config)) { + node->getConfig())) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -2756,8 +2756,7 @@ void calculateLayout( gCurrentGenerationCount.load(std::memory_order_relaxed))) { node->setPosition( node->getLayout().direction(), ownerWidth, ownerHeight, ownerWidth); - roundLayoutResultsToPixelGrid( - node, node->getConfig()->getPointScaleFactor(), 0.0f, 0.0f); + roundLayoutResultsToPixelGrid(node, 0.0f, 0.0f); #ifdef DEBUG if (node->getConfig()->shouldPrintTree()) { diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp index 0a4bda22132885..b2749e9fbb872b 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp @@ -64,12 +64,9 @@ float roundValueToPixelGrid( void roundLayoutResultsToPixelGrid( yoga::Node* const node, - const double pointScaleFactor, const double absoluteLeft, const double absoluteTop) { - if (pointScaleFactor == 0.0f) { - return; - } + const auto pointScaleFactor = node->getConfig()->getPointScaleFactor(); const double nodeLeft = node->getLayout().position[YGEdgeLeft]; const double nodeTop = node->getLayout().position[YGEdgeTop]; @@ -83,52 +80,52 @@ void roundLayoutResultsToPixelGrid( const double absoluteNodeRight = absoluteNodeLeft + nodeWidth; const double absoluteNodeBottom = absoluteNodeTop + nodeHeight; - // If a node has a custom measure function we never want to round down its - // size as this could lead to unwanted text truncation. - const bool textRounding = node->getNodeType() == YGNodeTypeText; - - node->setLayoutPosition( - roundValueToPixelGrid(nodeLeft, pointScaleFactor, false, textRounding), - YGEdgeLeft); - - node->setLayoutPosition( - roundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding), - YGEdgeTop); - - // We multiply dimension by scale factor and if the result is close to the - // 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 bool hasFractionalWidth = - !yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 0) && - !yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 1.0); - const bool hasFractionalHeight = - !yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 0) && - !yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 1.0); - - node->setLayoutDimension( - roundValueToPixelGrid( - absoluteNodeRight, - pointScaleFactor, - (textRounding && hasFractionalWidth), - (textRounding && !hasFractionalWidth)) - - roundValueToPixelGrid( - absoluteNodeLeft, pointScaleFactor, false, textRounding), - YGDimensionWidth); - - node->setLayoutDimension( - roundValueToPixelGrid( - absoluteNodeBottom, - pointScaleFactor, - (textRounding && hasFractionalHeight), - (textRounding && !hasFractionalHeight)) - - roundValueToPixelGrid( - absoluteNodeTop, pointScaleFactor, false, textRounding), - YGDimensionHeight); - - const size_t childCount = node->getChildCount(); - for (size_t i = 0; i < childCount; i++) { - roundLayoutResultsToPixelGrid( - node->getChild(i), pointScaleFactor, absoluteNodeLeft, absoluteNodeTop); + if (pointScaleFactor != 0.0f) { + // If a node has a custom measure function we never want to round down its + // size as this could lead to unwanted text truncation. + const bool textRounding = node->getNodeType() == YGNodeTypeText; + + node->setLayoutPosition( + roundValueToPixelGrid(nodeLeft, pointScaleFactor, false, textRounding), + YGEdgeLeft); + + node->setLayoutPosition( + roundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding), + YGEdgeTop); + + // We multiply dimension by scale factor and if the result is close to the + // 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 bool hasFractionalWidth = + !yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 0) && + !yoga::inexactEquals(fmod(nodeWidth * pointScaleFactor, 1.0), 1.0); + const bool hasFractionalHeight = + !yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 0) && + !yoga::inexactEquals(fmod(nodeHeight * pointScaleFactor, 1.0), 1.0); + + node->setLayoutDimension( + roundValueToPixelGrid( + absoluteNodeRight, + pointScaleFactor, + (textRounding && hasFractionalWidth), + (textRounding && !hasFractionalWidth)) - + roundValueToPixelGrid( + absoluteNodeLeft, pointScaleFactor, false, textRounding), + YGDimensionWidth); + + node->setLayoutDimension( + roundValueToPixelGrid( + absoluteNodeBottom, + pointScaleFactor, + (textRounding && hasFractionalHeight), + (textRounding && !hasFractionalHeight)) - + roundValueToPixelGrid( + absoluteNodeTop, pointScaleFactor, false, textRounding), + YGDimensionHeight); + } + + for (yoga::Node* child : node->getChildren()) { + roundLayoutResultsToPixelGrid(child, absoluteNodeLeft, absoluteNodeTop); } } diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.h b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.h index 24cb10d0166790..6bedd3ac0ecc1b 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.h +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.h @@ -23,7 +23,6 @@ float roundValueToPixelGrid( // Round the layout results of a node and its subtree to the pixel grid. void roundLayoutResultsToPixelGrid( yoga::Node* const node, - const double pointScaleFactor, const double absoluteLeft, const double absoluteTop);