Skip to content

Commit

Permalink
Breaking: per-node pointScaleFactor (#39403)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/yoga#1379

Pull Request resolved: #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
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Sep 13, 2023
1 parent fe4dab9 commit dce7242
Show file tree
Hide file tree
Showing 3 changed files with 50 additions and 55 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2487,7 +2487,7 @@ bool calculateLayoutInternal(
layout->cachedLayout.computedHeight,
marginAxisRow,
marginAxisColumn,
config)) {
node->getConfig())) {
cachedResults = &layout->cachedLayout;
} else {
// Try to use the measurement cache.
Expand All @@ -2505,7 +2505,7 @@ bool calculateLayoutInternal(
layout->cachedMeasurements[i].computedHeight,
marginAxisRow,
marginAxisColumn,
config)) {
node->getConfig())) {
cachedResults = &layout->cachedMeasurements[i];
break;
}
Expand Down Expand Up @@ -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()) {
Expand Down
97 changes: 47 additions & 50 deletions packages/react-native/ReactCommon/yoga/yoga/algorithm/PixelGrid.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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);

Expand Down

0 comments on commit dce7242

Please sign in to comment.