From 1f5c4a4407c5ea3b4a6e6133b8955134b87b4454 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 6 Nov 2023 14:50:29 -0800 Subject: [PATCH] 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,