From c313b2649233586c071289b5c1877626cd017c9c Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 6 Nov 2023 17:41:26 -0800 Subject: [PATCH 1/3] Simplify getting padding + border for cross axis in algorithm (#41208) Summary: X-link: https://github.com/facebook/yoga/pull/1437 Reading through the sizing logic and this seemed a bit redundant/confusing. Lets use the same function we just used for the main axis for the cross axis as well so people do not think its special. Also we will need one less variable. The reason this was done it seems is because we need the leading padding + border elsewhere so this is technically a few less steps but this is cleaner Reviewed By: NickGerleman Differential Revision: D50704177 --- .../ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 123ade22a57d5c..3f4af2d3b8a75c 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -1612,12 +1612,10 @@ static void calculateLayoutImpl( const float paddingAndBorderAxisMain = paddingAndBorderForAxis(node, mainAxis, ownerWidth); + const float paddingAndBorderAxisCross = + paddingAndBorderForAxis(node, crossAxis, ownerWidth); const float leadingPaddingAndBorderCross = node->getInlineStartPaddingAndBorder(crossAxis, direction, ownerWidth); - const float trailingPaddingAndBorderCross = - node->getInlineEndPaddingAndBorder(crossAxis, direction, ownerWidth); - const float paddingAndBorderAxisCross = - leadingPaddingAndBorderCross + trailingPaddingAndBorderCross; MeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; From 12c7eaa4e181427b439edd0fd304d7568dbeedd3 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 6 Nov 2023 17:41:26 -0800 Subject: [PATCH 2/3] Introduce isDefined() and remove cases of !isUndefined() (#41209) Summary: X-link: https://github.com/facebook/yoga/pull/1439 There are so many instances in this code base where we use the double negative of `!yoga::isUndefined()`. This is not as easy to read since because of this double negative imo. Additionally, sometimes we have really long chains like `!longVariableName.longFunctionName(longArgumentName).isUndefined()` and it is hard to see that this undefined is inverted. This just replaces all instances of inverted `isUndefined()` with `isDefined()` so its easier to read. Reviewed By: NickGerleman Differential Revision: D50705523 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 92 +++++++++---------- .../yoga/yoga/debug/NodeToString.cpp | 4 +- .../ReactCommon/yoga/yoga/node/Node.cpp | 30 +++--- .../yoga/yoga/numeric/Comparison.h | 12 ++- .../yoga/yoga/numeric/FloatOptional.h | 4 + .../yoga/yoga/style/CompactValue.h | 4 + .../ReactCommon/yoga/yoga/style/Style.h | 4 +- 7 files changed, 80 insertions(+), 70 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 3f4af2d3b8a75c..22997719ae7b5c 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -61,16 +61,16 @@ static inline bool styleDefinesDimension( const yoga::Node* const node, const FlexDirection axis, const float ownerSize) { - bool isUndefined = - yoga::isUndefined(node->getResolvedDimension(dimension(axis)).value); + bool isDefined = + yoga::isDefined(node->getResolvedDimension(dimension(axis)).value); auto resolvedDimension = node->getResolvedDimension(dimension(axis)); return !( resolvedDimension.unit == YGUnitAuto || resolvedDimension.unit == YGUnitUndefined || - (resolvedDimension.unit == YGUnitPoint && !isUndefined && + (resolvedDimension.unit == YGUnitPoint && isDefined && resolvedDimension.value < 0.0f) || - (resolvedDimension.unit == YGUnitPercent && !isUndefined && + (resolvedDimension.unit == YGUnitPercent && isDefined && (resolvedDimension.value < 0.0f || yoga::isUndefined(ownerSize)))); } @@ -78,7 +78,7 @@ static inline bool isLayoutDimensionDefined( const yoga::Node* const node, const FlexDirection axis) { const float value = node->getLayout().measuredDimension(dimension(axis)); - return !yoga::isUndefined(value) && value >= 0.0f; + return yoga::isDefined(value) && value >= 0.0f; } static void setChildTrailingPosition( @@ -111,7 +111,7 @@ static void constrainMaxSizeForMode( : maxSize.unwrap(); break; case MeasureMode::Undefined: - if (!maxSize.isUndefined()) { + if (maxSize.isDefined()) { *mode = MeasureMode::AtMost; *size = maxSize.unwrap(); } @@ -150,7 +150,7 @@ static void computeFlexBasisForChild( const bool isColumnStyleDimDefined = styleDefinesDimension(child, FlexDirection::Column, ownerHeight); - if (!resolvedFlexBasis.isUndefined() && !yoga::isUndefined(mainAxisSize)) { + if (resolvedFlexBasis.isDefined() && yoga::isDefined(mainAxisSize)) { if (child->getLayout().computedFlexBasis.isUndefined() || (child->getConfig()->isExperimentalFeatureEnabled( ExperimentalFeature::WebFlexBasis) && @@ -210,7 +210,7 @@ static void computeFlexBasisForChild( // major browsers appear to implement the following logic. if ((!isMainAxisRow && node->getStyle().overflow() == Overflow::Scroll) || node->getStyle().overflow() != Overflow::Scroll) { - if (yoga::isUndefined(childWidth) && !yoga::isUndefined(width)) { + if (yoga::isUndefined(childWidth) && yoga::isDefined(width)) { childWidth = width; childWidthMeasureMode = MeasureMode::AtMost; } @@ -218,14 +218,14 @@ static void computeFlexBasisForChild( if ((isMainAxisRow && node->getStyle().overflow() == Overflow::Scroll) || node->getStyle().overflow() != Overflow::Scroll) { - if (yoga::isUndefined(childHeight) && !yoga::isUndefined(height)) { + if (yoga::isUndefined(childHeight) && yoga::isDefined(height)) { childHeight = height; childHeightMeasureMode = MeasureMode::AtMost; } } const auto& childStyle = child->getStyle(); - if (!childStyle.aspectRatio().isUndefined()) { + if (childStyle.aspectRatio().isDefined()) { if (!isMainAxisRow && childWidthMeasureMode == MeasureMode::Exactly) { childHeight = marginColumn + (childWidth - marginRow) / childStyle.aspectRatio().unwrap(); @@ -242,7 +242,7 @@ static void computeFlexBasisForChild( // the cross axis to be measured exactly with the available inner width const bool hasExactWidth = - !yoga::isUndefined(width) && widthMode == MeasureMode::Exactly; + yoga::isDefined(width) && widthMode == MeasureMode::Exactly; const bool childWidthStretch = resolveChildAlignment(node, child) == Align::Stretch && childWidthMeasureMode != MeasureMode::Exactly; @@ -250,7 +250,7 @@ static void computeFlexBasisForChild( childWidthStretch) { childWidth = width; childWidthMeasureMode = MeasureMode::Exactly; - if (!childStyle.aspectRatio().isUndefined()) { + if (childStyle.aspectRatio().isDefined()) { childHeight = (childWidth - marginRow) / childStyle.aspectRatio().unwrap(); childHeightMeasureMode = MeasureMode::Exactly; @@ -258,7 +258,7 @@ static void computeFlexBasisForChild( } const bool hasExactHeight = - !yoga::isUndefined(height) && heightMode == MeasureMode::Exactly; + yoga::isDefined(height) && heightMode == MeasureMode::Exactly; const bool childHeightStretch = resolveChildAlignment(node, child) == Align::Stretch && childHeightMeasureMode != MeasureMode::Exactly; @@ -267,7 +267,7 @@ static void computeFlexBasisForChild( childHeight = height; childHeightMeasureMode = MeasureMode::Exactly; - if (!childStyle.aspectRatio().isUndefined()) { + if (childStyle.aspectRatio().isDefined()) { childWidth = (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); childWidthMeasureMode = MeasureMode::Exactly; @@ -382,7 +382,7 @@ static void layoutAbsoluteChild( // flexible. const auto& childStyle = child->getStyle(); if (yoga::isUndefined(childWidth) ^ yoga::isUndefined(childHeight)) { - if (!childStyle.aspectRatio().isUndefined()) { + if (childStyle.aspectRatio().isDefined()) { if (yoga::isUndefined(childWidth)) { childWidth = marginRow + (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); @@ -407,7 +407,7 @@ static void layoutAbsoluteChild( // wrap to the size of its owner. This is the same behavior as many browsers // implement. if (!isMainAxisRow && yoga::isUndefined(childWidth) && - widthMode != MeasureMode::Undefined && !yoga::isUndefined(width) && + widthMode != MeasureMode::Undefined && yoga::isDefined(width) && width > 0) { childWidth = width; childWidthMeasureMode = MeasureMode::AtMost; @@ -678,9 +678,9 @@ static bool measureNodeWithFixedSize( const MeasureMode heightMeasureMode, const float ownerWidth, const float ownerHeight) { - if ((!yoga::isUndefined(availableWidth) && + if ((yoga::isDefined(availableWidth) && widthMeasureMode == MeasureMode::AtMost && availableWidth <= 0.0f) || - (!yoga::isUndefined(availableHeight) && + (yoga::isDefined(availableHeight) && heightMeasureMode == MeasureMode::AtMost && availableHeight <= 0.0f) || (widthMeasureMode == MeasureMode::Exactly && heightMeasureMode == MeasureMode::Exactly)) { @@ -736,7 +736,7 @@ static float calculateAvailableInnerDimension( float availableInnerDim = availableDim - paddingAndBorder; // Max dimension overrides predefined dimension value; Min dimension in turn // overrides both of the above - if (!yoga::isUndefined(availableInnerDim)) { + if (yoga::isDefined(availableInnerDim)) { // We want to make sure our available height does not violate min and max // constraints const FloatOptional minDimensionOptional = @@ -880,7 +880,7 @@ static float distributeFreeSpaceSecondPass( .unwrap(); float updatedMainSize = childFlexBasis; - if (!yoga::isUndefined(flexLine.layout.remainingFreeSpace) && + if (yoga::isDefined(flexLine.layout.remainingFreeSpace) && flexLine.layout.remainingFreeSpace < 0) { flexShrinkScaledFactor = -currentLineChild->resolveFlexShrink() * childFlexBasis; @@ -888,7 +888,7 @@ static float distributeFreeSpaceSecondPass( if (flexShrinkScaledFactor != 0) { float childSize; - if (!yoga::isUndefined(flexLine.layout.totalFlexShrinkScaledFactors) && + if (yoga::isDefined(flexLine.layout.totalFlexShrinkScaledFactors) && flexLine.layout.totalFlexShrinkScaledFactors == 0) { childSize = childFlexBasis + flexShrinkScaledFactor; } else { @@ -906,7 +906,7 @@ static float distributeFreeSpaceSecondPass( availableInnerWidth); } } else if ( - !yoga::isUndefined(flexLine.layout.remainingFreeSpace) && + yoga::isDefined(flexLine.layout.remainingFreeSpace) && flexLine.layout.remainingFreeSpace > 0) { flexGrowFactor = currentLineChild->resolveFlexGrow(); @@ -936,7 +936,7 @@ static float distributeFreeSpaceSecondPass( MeasureMode childMainMeasureMode = MeasureMode::Exactly; const auto& childStyle = currentLineChild->getStyle(); - if (!childStyle.aspectRatio().isUndefined()) { + if (childStyle.aspectRatio().isDefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / childStyle.aspectRatio().unwrap() : (childMainSize - marginMain) * childStyle.aspectRatio().unwrap(); @@ -1062,7 +1062,7 @@ static void distributeFreeSpaceFirstPass( -currentLineChild->resolveFlexShrink() * childFlexBasis; // Is this child able to shrink? - if (!yoga::isUndefined(flexShrinkScaledFactor) && + if (yoga::isDefined(flexShrinkScaledFactor) && flexShrinkScaledFactor != 0) { baseMainSize = childFlexBasis + flexLine.layout.remainingFreeSpace / @@ -1074,8 +1074,7 @@ static void distributeFreeSpaceFirstPass( baseMainSize, availableInnerMainDim, availableInnerWidth); - if (!yoga::isUndefined(baseMainSize) && - !yoga::isUndefined(boundMainSize) && + if (yoga::isDefined(baseMainSize) && yoga::isDefined(boundMainSize) && baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, this // item's min/max constraints should also trigger in the second pass @@ -1088,12 +1087,12 @@ static void distributeFreeSpaceFirstPass( } } } else if ( - !yoga::isUndefined(flexLine.layout.remainingFreeSpace) && + yoga::isDefined(flexLine.layout.remainingFreeSpace) && flexLine.layout.remainingFreeSpace > 0) { flexGrowFactor = currentLineChild->resolveFlexGrow(); // Is this child able to grow? - if (!yoga::isUndefined(flexGrowFactor) && flexGrowFactor != 0) { + if (yoga::isDefined(flexGrowFactor) && flexGrowFactor != 0) { baseMainSize = childFlexBasis + flexLine.layout.remainingFreeSpace / flexLine.layout.totalFlexGrowFactors * flexGrowFactor; @@ -1104,8 +1103,7 @@ static void distributeFreeSpaceFirstPass( availableInnerMainDim, availableInnerWidth); - if (!yoga::isUndefined(baseMainSize) && - !yoga::isUndefined(boundMainSize) && + if (yoga::isDefined(baseMainSize) && yoga::isDefined(boundMainSize) && baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, this // item's min/max constraints should also trigger in the second pass @@ -1219,10 +1217,10 @@ static void justifyMainAxis( // remainingFreeSpace is 0 when min main dimension is not given if (measureModeMainDim == MeasureMode::AtMost && flexLine.layout.remainingFreeSpace > 0) { - if (!style.minDimension(dimension(mainAxis)).isUndefined() && - !yoga::resolveValue( - style.minDimension(dimension(mainAxis)), mainAxisownerSize) - .isUndefined()) { + if (style.minDimension(dimension(mainAxis)).isDefined() && + yoga::resolveValue( + style.minDimension(dimension(mainAxis)), mainAxisownerSize) + .isDefined()) { // This condition makes sure that if the size of main dimension(after // considering child nodes main dim, leading and trailing padding etc) // falls below min dimension, then the remainingFreeSpace is reassigned @@ -1743,11 +1741,11 @@ static void calculateLayoutImpl( const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; - if (!yoga::isUndefined(minInnerMainDim) && + if (yoga::isDefined(minInnerMainDim) && flexLine.sizeConsumed < minInnerMainDim) { availableInnerMainDim = minInnerMainDim; } else if ( - !yoga::isUndefined(maxInnerMainDim) && + yoga::isDefined(maxInnerMainDim) && flexLine.sizeConsumed > maxInnerMainDim) { availableInnerMainDim = maxInnerMainDim; } else { @@ -1755,9 +1753,9 @@ static void calculateLayoutImpl( node->hasErrata(Errata::StretchFlexBasis); if (!useLegacyStretchBehaviour && - ((!yoga::isUndefined(flexLine.layout.totalFlexGrowFactors) && + ((yoga::isDefined(flexLine.layout.totalFlexGrowFactors) && flexLine.layout.totalFlexGrowFactors == 0) || - (!yoga::isUndefined(node->resolveFlexGrow()) && + (yoga::isDefined(node->resolveFlexGrow()) && node->resolveFlexGrow() == 0))) { // If we don't have any children to flex or we can't flex the node // itself, space we've used is all space we need. Root node also @@ -1769,7 +1767,7 @@ static void calculateLayoutImpl( } } - if (!sizeBasedOnContent && !yoga::isUndefined(availableInnerMainDim)) { + if (!sizeBasedOnContent && yoga::isDefined(availableInnerMainDim)) { flexLine.layout.remainingFreeSpace = availableInnerMainDim - flexLine.sizeConsumed; } else if (flexLine.sizeConsumed < 0) { @@ -1910,7 +1908,7 @@ static void calculateLayoutImpl( float childMainSize = child->getLayout().measuredDimension(dimension(mainAxis)); const auto& childStyle = child->getStyle(); - float childCrossSize = !childStyle.aspectRatio().isUndefined() + float childCrossSize = childStyle.aspectRatio().isDefined() ? child->getMarginForAxis(crossAxis, availableInnerWidth) + (isMainAxisRow ? childMainSize / childStyle.aspectRatio().unwrap() @@ -2013,7 +2011,7 @@ static void calculateLayoutImpl( if (performLayout && (isNodeFlexWrap || isBaselineLayout(node))) { float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; - if (!yoga::isUndefined(availableInnerCrossDim)) { + if (yoga::isDefined(availableInnerCrossDim)) { const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; switch (node->getStyle().alignContent()) { @@ -2691,9 +2689,9 @@ void calculateLayout( .unwrap() + node->getMarginForAxis(FlexDirection::Row, ownerWidth)); widthMeasureMode = MeasureMode::Exactly; - } else if (!yoga::resolveValue( - style.maxDimension(Dimension::Width), ownerWidth) - .isUndefined()) { + } else if (yoga::resolveValue( + style.maxDimension(Dimension::Width), ownerWidth) + .isDefined()) { width = yoga::resolveValue(style.maxDimension(Dimension::Width), ownerWidth) .unwrap(); widthMeasureMode = MeasureMode::AtMost; @@ -2713,9 +2711,9 @@ void calculateLayout( .unwrap() + node->getMarginForAxis(FlexDirection::Column, ownerWidth)); heightMeasureMode = MeasureMode::Exactly; - } else if (!yoga::resolveValue( - style.maxDimension(Dimension::Height), ownerHeight) - .isUndefined()) { + } else if (yoga::resolveValue( + style.maxDimension(Dimension::Height), ownerHeight) + .isDefined()) { height = yoga::resolveValue(style.maxDimension(Dimension::Height), ownerHeight) .unwrap(); diff --git a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp index d944b3a51d7765..a2bf467bede115 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/debug/NodeToString.cpp @@ -46,7 +46,7 @@ static void appendFloatOptionalIfDefined( std::string& base, const std::string key, const FloatOptional num) { - if (!num.isUndefined()) { + if (num.isDefined()) { appendFormattedString(base, "%s: %g; ", key.c_str(), num.unwrap()); } } @@ -177,7 +177,7 @@ void nodeToString( appendEdges(str, "padding", style.padding()); appendEdges(str, "border", style.border()); - if (!style.gap(Gutter::All).isUndefined()) { + if (style.gap(Gutter::All).isDefined()) { appendNumberIfNotUndefined(str, "gap", style.gap(Gutter::All)); } else { appendNumberIfNotUndefined(str, "column-gap", style.gap(Gutter::Column)); diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index 257aa3ce0df38f..3a458d1ccb1e96 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -60,11 +60,11 @@ CompactValue Node::computeEdgeValueForRow( const Style::Edges& edges, YGEdge rowEdge, YGEdge edge) { - if (!edges[rowEdge].isUndefined()) { + if (edges[rowEdge].isDefined()) { return edges[rowEdge]; - } else if (!edges[edge].isUndefined()) { + } else if (edges[edge].isDefined()) { return edges[edge]; - } else if (!edges[YGEdgeHorizontal].isUndefined()) { + } else if (edges[YGEdgeHorizontal].isDefined()) { return edges[YGEdgeHorizontal]; } else { return edges[YGEdgeAll]; @@ -74,9 +74,9 @@ CompactValue Node::computeEdgeValueForRow( CompactValue Node::computeEdgeValueForColumn( const Style::Edges& edges, YGEdge edge) { - if (!edges[edge].isUndefined()) { + if (edges[edge].isDefined()) { return edges[edge]; - } else if (!edges[YGEdgeVertical].isUndefined()) { + } else if (edges[YGEdgeVertical].isDefined()) { return edges[YGEdgeVertical]; } else { return edges[YGEdgeAll]; @@ -106,7 +106,7 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) : computeEdgeValueForColumn(style_.position(), startEdge); - return !leadingPosition.isUndefined(); + return leadingPosition.isDefined(); } bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) @@ -116,7 +116,7 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) : computeEdgeValueForColumn(style_.position(), endEdge); - return !trailingPosition.isUndefined(); + return trailingPosition.isDefined(); } float Node::getInlineStartPosition( @@ -511,7 +511,7 @@ void Node::setPosition( } YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { - if (isRow(axis) && !style_.margin()[YGEdgeStart].isUndefined()) { + if (isRow(axis) && style_.margin()[YGEdgeStart].isDefined()) { return style_.margin()[YGEdgeStart]; } else { return style_.margin()[flexStartEdge(axis)]; @@ -519,7 +519,7 @@ YGValue Node::getFlexStartMarginValue(FlexDirection axis) const { } YGValue Node::marginTrailingValue(FlexDirection axis) const { - if (isRow(axis) && !style_.margin()[YGEdgeEnd].isUndefined()) { + if (isRow(axis) && style_.margin()[YGEdgeEnd].isDefined()) { return style_.margin()[YGEdgeEnd]; } else { return style_.margin()[flexEndEdge(axis)]; @@ -531,7 +531,7 @@ YGValue Node::resolveFlexBasisPtr() const { if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { return flexBasis; } - if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { + if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) { return config_->useWebDefaults() ? YGValueAuto : YGValueZero; } return YGValueAuto; @@ -540,7 +540,7 @@ YGValue Node::resolveFlexBasisPtr() const { void Node::resolveDimension() { const Style& style = getStyle(); for (auto dim : {Dimension::Width, Dimension::Height}) { - if (!style.maxDimension(dim).isUndefined() && + if (style.maxDimension(dim).isDefined() && yoga::inexactEquals(style.maxDimension(dim), style.minDimension(dim))) { resolvedDimensions_[yoga::to_underlying(dim)] = style.maxDimension(dim); } else { @@ -598,10 +598,10 @@ float Node::resolveFlexGrow() const { if (owner_ == nullptr) { return 0.0; } - if (!style_.flexGrow().isUndefined()) { + if (style_.flexGrow().isDefined()) { return style_.flexGrow().unwrap(); } - if (!style_.flex().isUndefined() && style_.flex().unwrap() > 0.0f) { + if (style_.flex().isDefined() && style_.flex().unwrap() > 0.0f) { return style_.flex().unwrap(); } return Style::DefaultFlexGrow; @@ -611,10 +611,10 @@ float Node::resolveFlexShrink() const { if (owner_ == nullptr) { return 0.0; } - if (!style_.flexShrink().isUndefined()) { + if (style_.flexShrink().isDefined()) { return style_.flexShrink().unwrap(); } - if (!config_->useWebDefaults() && !style_.flex().isUndefined() && + if (!config_->useWebDefaults() && style_.flex().isDefined() && style_.flex().unwrap() < 0.0f) { return -style_.flex().unwrap(); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/numeric/Comparison.h b/packages/react-native/ReactCommon/yoga/yoga/numeric/Comparison.h index b881810b4100b5..3bf1037b9cc376 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/numeric/Comparison.h +++ b/packages/react-native/ReactCommon/yoga/yoga/numeric/Comparison.h @@ -19,15 +19,19 @@ constexpr bool isUndefined(auto value) { return value != value; } +constexpr bool isDefined(auto value) { + return !isUndefined(value); +} + constexpr auto maxOrDefined(auto a, auto b) { - if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { + if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::max(a, b); } return yoga::isUndefined(a) ? b : a; } constexpr auto minOrDefined(auto a, auto b) { - if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { + if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::min(a, b); } @@ -37,14 +41,14 @@ constexpr auto minOrDefined(auto a, auto b) { // Custom equality functions using a hardcoded epsilon of 0.0001f, or returning // true if both floats are NaN. inline bool inexactEquals(float a, float b) { - if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { + if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::abs(a - b) < 0.0001f; } return yoga::isUndefined(a) && yoga::isUndefined(b); } inline bool inexactEquals(double a, double b) { - if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { + if (yoga::isDefined(a) && yoga::isDefined(b)) { return std::abs(a - b) < 0.0001; } return yoga::isUndefined(a) && yoga::isUndefined(b); diff --git a/packages/react-native/ReactCommon/yoga/yoga/numeric/FloatOptional.h b/packages/react-native/ReactCommon/yoga/yoga/numeric/FloatOptional.h index 8fd9bbb2d187cc..4f2e5db92f84f6 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/numeric/FloatOptional.h +++ b/packages/react-native/ReactCommon/yoga/yoga/numeric/FloatOptional.h @@ -32,6 +32,10 @@ struct FloatOptional { constexpr bool isUndefined() const { return yoga::isUndefined(value_); } + + constexpr bool isDefined() const { + return yoga::isDefined(value_); + } }; // operators take FloatOptional by value, as it is a 32bit value diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h b/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h index 03722aee83ddb7..a6ca3f1283e175 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/CompactValue.h @@ -137,6 +137,10 @@ class YG_EXPORT CompactValue { repr_ != ZERO_BITS_PERCENT && std::isnan(yoga::bit_cast(repr_))); } + bool isDefined() const noexcept { + return !isUndefined(); + } + bool isAuto() const noexcept { return repr_ == AUTO_BITS; } diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index f02710d3e0aaac..3eb5cadd195e16 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -312,7 +312,7 @@ class YG_EXPORT Style { } CompactValue resolveColumnGap() const { - if (!gap_[yoga::to_underlying(Gutter::Column)].isUndefined()) { + if (gap_[yoga::to_underlying(Gutter::Column)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Column)]; } else { return gap_[yoga::to_underlying(Gutter::All)]; @@ -320,7 +320,7 @@ class YG_EXPORT Style { } CompactValue resolveRowGap() const { - if (!gap_[yoga::to_underlying(Gutter::Row)].isUndefined()) { + if (gap_[yoga::to_underlying(Gutter::Row)].isDefined()) { return gap_[yoga::to_underlying(Gutter::Row)]; } else { return gap_[yoga::to_underlying(Gutter::All)]; From 91b47c302b0b60f40bf0703339551ebd195ee455 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 6 Nov 2023 17:41:26 -0800 Subject: [PATCH 3/3] Fix issue where absolute children of row-reverse containers would inset on the wrong side (#41293) Summary: X-link: https://github.com/facebook/yoga/pull/1446 NickGerleman pointed out that my recent changes to fix the slew of row-reverse problems in Yoga actually ended up regressing some parts. Specifically, absolute children of row-reverse containers would have their insets set to the wrong side. So if you set left: 10 it would apply it to the right. Turns out, in `layoutAbsoluteChild` there were cases where we were applying inlineStart/End values to the flexStart/End edge, which can never be right. So I changed the values to also be flexStart/End as the fix here. Reviewed By: NickGerleman Differential Revision: D50945475 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 53 ++++++++---------- .../ReactCommon/yoga/yoga/node/Node.cpp | 54 +++++++++++++++++++ .../ReactCommon/yoga/yoga/node/Node.h | 6 +++ 3 files changed, 83 insertions(+), 30 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 22997719ae7b5c..c1026c9adcf823 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -448,19 +448,17 @@ static void layoutAbsoluteChild( depth, generationCount); - if (child->isInlineEndPositionDefined(mainAxis, direction) && - !child->isInlineStartPositionDefined(mainAxis, direction)) { + if (child->isFlexEndPositionDefined(mainAxis) && + !child->isFlexStartPositionDefined(mainAxis)) { child->setLayoutPosition( node->getLayout().measuredDimension(dimension(mainAxis)) - child->getLayout().measuredDimension(dimension(mainAxis)) - - node->getInlineEndBorder(mainAxis, direction) - - child->getInlineEndMargin( - mainAxis, direction, isMainAxisRow ? width : height) - - child->getInlineEndPosition( - mainAxis, direction, isMainAxisRow ? width : height), + node->getFlexEndBorder(mainAxis, direction) - + child->getFlexEndMargin(mainAxis, isMainAxisRow ? width : height) - + child->getFlexEndPosition(mainAxis, isMainAxisRow ? width : height), flexStartEdge(mainAxis)); } else if ( - !child->isInlineStartPositionDefined(mainAxis, direction) && + !child->isFlexStartPositionDefined(mainAxis) && node->getStyle().justifyContent() == Justify::Center) { child->setLayoutPosition( (node->getLayout().measuredDimension(dimension(mainAxis)) - @@ -468,7 +466,7 @@ static void layoutAbsoluteChild( 2.0f, flexStartEdge(mainAxis)); } else if ( - !child->isInlineStartPositionDefined(mainAxis, direction) && + !child->isFlexStartPositionDefined(mainAxis) && node->getStyle().justifyContent() == Justify::FlexEnd) { child->setLayoutPosition( (node->getLayout().measuredDimension(dimension(mainAxis)) - @@ -477,34 +475,31 @@ static void layoutAbsoluteChild( } else if ( node->getConfig()->isExperimentalFeatureEnabled( ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) && - child->isInlineStartPositionDefined(mainAxis, direction)) { + child->isFlexStartPositionDefined(mainAxis)) { child->setLayoutPosition( - child->getInlineStartPosition( + child->getFlexStartPosition( mainAxis, - direction, node->getLayout().measuredDimension(dimension(mainAxis))) + - node->getInlineStartBorder(mainAxis, direction) + - child->getInlineStartMargin( + node->getFlexStartBorder(mainAxis, direction) + + child->getFlexStartMargin( mainAxis, - direction, node->getLayout().measuredDimension(dimension(mainAxis))), flexStartEdge(mainAxis)); } - if (child->isInlineEndPositionDefined(crossAxis, direction) && - !child->isInlineStartPositionDefined(crossAxis, direction)) { + if (child->isFlexEndPositionDefined(crossAxis) && + !child->isFlexStartPositionDefined(crossAxis)) { child->setLayoutPosition( node->getLayout().measuredDimension(dimension(crossAxis)) - child->getLayout().measuredDimension(dimension(crossAxis)) - - node->getInlineEndBorder(crossAxis, direction) - - child->getInlineEndMargin( - crossAxis, direction, isMainAxisRow ? height : width) - - child->getInlineEndPosition( - crossAxis, direction, isMainAxisRow ? height : width), + node->getFlexEndBorder(crossAxis, direction) - + child->getFlexEndMargin(crossAxis, isMainAxisRow ? height : width) - + child->getFlexEndPosition( + crossAxis, isMainAxisRow ? height : width), flexStartEdge(crossAxis)); } else if ( - !child->isInlineStartPositionDefined(crossAxis, direction) && + !child->isFlexStartPositionDefined(crossAxis) && resolveChildAlignment(node, child) == Align::Center) { child->setLayoutPosition( (node->getLayout().measuredDimension(dimension(crossAxis)) - @@ -512,7 +507,7 @@ static void layoutAbsoluteChild( 2.0f, flexStartEdge(crossAxis)); } else if ( - !child->isInlineStartPositionDefined(crossAxis, direction) && + !child->isFlexStartPositionDefined(crossAxis) && ((resolveChildAlignment(node, child) == Align::FlexEnd) ^ (node->getStyle().flexWrap() == Wrap::WrapReverse))) { child->setLayoutPosition( @@ -522,16 +517,14 @@ static void layoutAbsoluteChild( } else if ( node->getConfig()->isExperimentalFeatureEnabled( ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) && - child->isInlineStartPositionDefined(crossAxis, direction)) { + child->isFlexStartPositionDefined(crossAxis)) { child->setLayoutPosition( - child->getInlineStartPosition( + child->getFlexStartPosition( crossAxis, - direction, node->getLayout().measuredDimension(dimension(crossAxis))) + - node->getInlineStartBorder(crossAxis, direction) + - child->getInlineStartMargin( + node->getFlexStartBorder(crossAxis, direction) + + child->getFlexStartMargin( crossAxis, - direction, node->getLayout().measuredDimension(dimension(crossAxis))), flexStartEdge(crossAxis)); } diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index 3a458d1ccb1e96..e13274cf9b7800 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -99,6 +99,15 @@ YGEdge Node::getInlineEndEdgeUsingErrata( : inlineEndEdge(flexDirection, direction); } +bool Node::isFlexStartPositionDefined(FlexDirection axis) const { + const YGEdge startEdge = flexStartEdge(axis); + auto leadingPosition = isRow(axis) + ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) + : computeEdgeValueForColumn(style_.position(), startEdge); + + return leadingPosition.isDefined(); +} + bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge startEdge = getInlineStartEdgeUsingErrata(axis, direction); @@ -109,6 +118,15 @@ bool Node::isInlineStartPositionDefined(FlexDirection axis, Direction direction) return leadingPosition.isDefined(); } +bool Node::isFlexEndPositionDefined(FlexDirection axis) const { + const YGEdge endEdge = flexEndEdge(axis); + auto trailingPosition = isRow(axis) + ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) + : computeEdgeValueForColumn(style_.position(), endEdge); + + return !trailingPosition.isUndefined(); +} + bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { const YGEdge endEdge = getInlineEndEdgeUsingErrata(axis, direction); @@ -119,6 +137,15 @@ bool Node::isInlineEndPositionDefined(FlexDirection axis, Direction direction) return trailingPosition.isDefined(); } +float Node::getFlexStartPosition(FlexDirection axis, float axisSize) const { + const YGEdge startEdge = flexStartEdge(axis); + auto leadingPosition = isRow(axis) + ? computeEdgeValueForRow(style_.position(), YGEdgeStart, startEdge) + : computeEdgeValueForColumn(style_.position(), startEdge); + + return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); +} + float Node::getInlineStartPosition( FlexDirection axis, Direction direction, @@ -131,6 +158,15 @@ float Node::getInlineStartPosition( return resolveValue(leadingPosition, axisSize).unwrapOrDefault(0.0f); } +float Node::getFlexEndPosition(FlexDirection axis, float axisSize) const { + const YGEdge endEdge = flexEndEdge(axis); + auto trailingPosition = isRow(axis) + ? computeEdgeValueForRow(style_.position(), YGEdgeEnd, endEdge) + : computeEdgeValueForColumn(style_.position(), endEdge); + + return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); +} + float Node::getInlineEndPosition( FlexDirection axis, Direction direction, @@ -143,6 +179,15 @@ float Node::getInlineEndPosition( return resolveValue(trailingPosition, axisSize).unwrapOrDefault(0.0f); } +float Node::getFlexStartMargin(FlexDirection axis, float widthSize) const { + const YGEdge startEdge = flexStartEdge(axis); + auto leadingMargin = isRow(axis) + ? computeEdgeValueForRow(style_.margin(), YGEdgeStart, startEdge) + : computeEdgeValueForColumn(style_.margin(), startEdge); + + return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); +} + float Node::getInlineStartMargin( FlexDirection axis, Direction direction, @@ -155,6 +200,15 @@ float Node::getInlineStartMargin( return resolveValue(leadingMargin, widthSize).unwrapOrDefault(0.0f); } +float Node::getFlexEndMargin(FlexDirection axis, float widthSize) const { + const YGEdge endEdge = flexEndEdge(axis); + auto trailingMargin = isRow(axis) + ? computeEdgeValueForRow(style_.margin(), YGEdgeEnd, endEdge) + : computeEdgeValueForColumn(style_.margin(), endEdge); + + return resolveValue(trailingMargin, widthSize).unwrapOrDefault(0.0f); +} + float Node::getInlineEndMargin( FlexDirection axis, Direction direction, diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h index 005459434d7465..0069f69bd2d2ec 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.h +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.h @@ -199,22 +199,28 @@ class YG_EXPORT Node : public ::YGNode { YGEdge edge); // Methods related to positions, margin, padding and border + bool isFlexStartPositionDefined(FlexDirection axis) const; bool isInlineStartPositionDefined(FlexDirection axis, Direction direction) const; + bool isFlexEndPositionDefined(FlexDirection axis) const; bool isInlineEndPositionDefined(FlexDirection axis, Direction direction) const; + float getFlexStartPosition(FlexDirection axis, float axisSize) const; float getInlineStartPosition( FlexDirection axis, Direction direction, float axisSize) const; + float getFlexEndPosition(FlexDirection axis, float axisSize) const; float getInlineEndPosition( FlexDirection axis, Direction direction, float axisSize) const; + float getFlexStartMargin(FlexDirection axis, float widthSize) const; float getInlineStartMargin( FlexDirection axis, Direction direction, float widthSize) const; + float getFlexEndMargin(FlexDirection axis, float widthSize) const; float getInlineEndMargin( FlexDirection axis, Direction direction,