From c5b4bfd4e1734c8054868c74413fbea9bb830d86 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 4 Dec 2023 15:21:32 -0800 Subject: [PATCH 1/4] Insets no longer apply to statically positioned nodes (#41369) Summary: X-link: https://github.com/facebook/yoga/pull/1454 One of the most basic aspects of statically positioned nodes is that [insets do not apply to them](https://developer.mozilla.org/en-US/docs/Web/CSS/position#static). So I put a guard inside `Node::relativePosition` where we take that into account when setting the position. Reviewed By: NickGerleman Differential Revision: D50507808 --- .../react-native/ReactCommon/yoga/yoga/node/Node.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp index faf812e8cf1949..63639aafd01bd2 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/node/Node.cpp @@ -488,11 +488,16 @@ void Node::setLayoutDimension(float LengthValue, Dimension dimension) { } // If both left and right are defined, then use left. Otherwise return +left or -// -right depending on which is defined. +// -right depending on which is defined. Ignore statically positioned nodes as +// insets do not apply to them. float Node::relativePosition( FlexDirection axis, Direction direction, float axisSize) const { + if (style_.positionType() == PositionType::Static && + !hasErrata(Errata::PositionStaticBehavesLikeRelative)) { + return 0; + } if (isInlineStartPositionDefined(axis, direction)) { return getInlineStartPosition(axis, direction, axisSize); } @@ -514,8 +519,7 @@ void Node::setPosition( const FlexDirection crossAxis = yoga::resolveCrossDirection(mainAxis, directionRespectingRoot); - // Here we should check for `PositionType::Static` and in this case zero inset - // properties (left, right, top, bottom, begin, end). + // In the case of position static these are just 0. See: // https://www.w3.org/TR/css-position-3/#valdef-position-static const float relativePositionMain = relativePosition(mainAxis, directionRespectingRoot, mainSize); From 5aaa52dc3d4ef500a6608ef6e26f2c4b2b58b9b4 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 4 Dec 2023 15:21:32 -0800 Subject: [PATCH 2/4] Let containing blocks layout their absolute descendants, not parents (#41488) Summary: X-link: https://github.com/facebook/yoga/pull/1470 The way we plan on implementing `position: static` is by changing how we lay out absolutely positioned nodes. Instead of letting their direct parent lay them out we are going to let their containing block handle it. This is useful because by the time the containing block gets to this step it will already know its size, which is needed to ensure that absolute nodes can get the right value with percentage units. Additionally, it means that we can "translate" the position of the absolute nodes to be relative to their parent fairly easily, instead of some second pass that would not be possible with a different design. This change just gets the core pieces of this process going. It makes it so that containing blocks will layout out absolute descendants that they contain. We also pass in the containing block size to the owner size args for `layoutAbsoluteChild`. This new path will only happen if we have the errata turned off. If there is no positioned ancestor for a given node we just assume the root is. This is not exactly how it works on the web - there is a notion of an initial containing block - but we are not implementing that as of right now. Reviewed By: NickGerleman Differential Revision: D51182593 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 98 +++++++++++++++---- 1 file changed, 77 insertions(+), 21 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index fe97b4e1166482..ce745e39430382 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -531,6 +531,45 @@ static void layoutAbsoluteChild( } } +static void layoutAbsoluteDescendants( + yoga::Node* currentNode, + SizingMode widthSizingMode, + Direction currentNodeDirection, + LayoutData& layoutMarkerData, + uint32_t currentDepth, + uint32_t generationCount, + float containingBlockWidth, + float containingBlockHeight) { + for (auto child : currentNode->getChildren()) { + if (child->getStyle().display() == Display::None) { + continue; + } else if (child->getStyle().positionType() == PositionType::Absolute) { + layoutAbsoluteChild( + currentNode, + child, + containingBlockWidth, + widthSizingMode, + containingBlockHeight, + currentNodeDirection, + layoutMarkerData, + currentDepth, + generationCount); + } else if (child->getStyle().positionType() == PositionType::Static) { + const Direction childDirection = + child->resolveDirection(currentNodeDirection); + layoutAbsoluteDescendants( + child, + widthSizingMode, + childDirection, + layoutMarkerData, + currentDepth + 1, + generationCount, + containingBlockWidth, + containingBlockHeight); + } + } +} + static void measureNodeWithMeasureFunc( yoga::Node* const node, float availableWidth, @@ -2304,29 +2343,46 @@ static void calculateLayoutImpl( if (performLayout) { // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN - for (auto child : node->getChildren()) { - if (child->getStyle().display() == Display::None || - child->getStyle().positionType() != PositionType::Absolute) { - continue; + if (!node->hasErrata(Errata::PositionStaticBehavesLikeRelative)) { + // Let the containing block layout its absolute descendants. By definition + // the containing block will not be static unless we are at the root. + if (node->getStyle().positionType() != PositionType::Static || + depth == 1) { + layoutAbsoluteDescendants( + node, + isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, + direction, + layoutMarkerData, + depth, + generationCount, + node->getLayout().measuredDimension(Dimension::Width), + node->getLayout().measuredDimension(Dimension::Height)); } - const bool absolutePercentageAgainstPaddingEdge = - node->getConfig()->isExperimentalFeatureEnabled( - ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge); + } else { + for (auto child : node->getChildren()) { + if (child->getStyle().display() == Display::None || + child->getStyle().positionType() != PositionType::Absolute) { + continue; + } + const bool absolutePercentageAgainstPaddingEdge = + node->getConfig()->isExperimentalFeatureEnabled( + ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge); - layoutAbsoluteChild( - node, - child, - absolutePercentageAgainstPaddingEdge - ? node->getLayout().measuredDimension(Dimension::Width) - : availableInnerWidth, - isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, - absolutePercentageAgainstPaddingEdge - ? node->getLayout().measuredDimension(Dimension::Height) - : availableInnerHeight, - direction, - layoutMarkerData, - depth, - generationCount); + layoutAbsoluteChild( + node, + child, + absolutePercentageAgainstPaddingEdge + ? node->getLayout().measuredDimension(Dimension::Width) + : availableInnerWidth, + isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, + absolutePercentageAgainstPaddingEdge + ? node->getLayout().measuredDimension(Dimension::Height) + : availableInnerHeight, + direction, + layoutMarkerData, + depth, + generationCount); + } } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN From 80c36e734b1810d1585a8a5224e93dbbcb46c4fa Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 4 Dec 2023 15:21:32 -0800 Subject: [PATCH 3/4] Allow the containing block to set trailing position of absolute descendants (#41489) Summary: X-link: https://github.com/facebook/yoga/pull/1471 If we are going to allow the containing block to layout its absolute descendants and NOT the direct parent then we need to change step 11 which is concerned with setting the trailing position in the case we are row or column reverse. This is the very last step in the function and is positioned that way because it operates on the assumption that all children have their position set by this time. That is no longer a valid assumption if CBs layout their absolute children. In that case the CB also needs to take care of setting the position here. Because of this problem I moved some things around. It now works like: * If errata is set, the direct parent will set trailing position for all non absolute children in step 11 * If errata is set the CB will set trailing position of absolute descendants after they are laid out inside of layoutAbsoluteDescendants Reviewed By: NickGerleman Differential Revision: D51217291 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 30 +++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index ce745e39430382..733603d043b230 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -93,6 +93,11 @@ static void setChildTrailingPosition( flexEndEdge(axis)); } +static bool needsTrailingPosition(const FlexDirection axis) { + return axis == FlexDirection::RowReverse || + axis == FlexDirection::ColumnReverse; +} + static void constrainMaxSizeForMode( const yoga::Node* const node, const enum FlexDirection axis, @@ -554,6 +559,17 @@ static void layoutAbsoluteDescendants( layoutMarkerData, currentDepth, generationCount); + + const FlexDirection mainAxis = resolveDirection( + currentNode->getStyle().flexDirection(), currentNodeDirection); + const FlexDirection crossAxis = + resolveCrossDirection(mainAxis, currentNodeDirection); + if (needsTrailingPosition(mainAxis)) { + setChildTrailingPosition(currentNode, child, mainAxis); + } + if (needsTrailingPosition(crossAxis)) { + setChildTrailingPosition(currentNode, child, crossAxis); + } } else if (child->getStyle().positionType() == PositionType::Static) { const Direction childDirection = child->resolveDirection(currentNodeDirection); @@ -2386,16 +2402,18 @@ static void calculateLayoutImpl( } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN - const bool needsMainTrailingPos = mainAxis == FlexDirection::RowReverse || - mainAxis == FlexDirection::ColumnReverse; - const bool needsCrossTrailingPos = crossAxis == FlexDirection::RowReverse || - crossAxis == FlexDirection::ColumnReverse; + const bool needsMainTrailingPos = needsTrailingPosition(mainAxis); + const bool needsCrossTrailingPos = needsTrailingPosition(crossAxis); - // Set trailing position if necessary. if (needsMainTrailingPos || needsCrossTrailingPos) { for (size_t i = 0; i < childCount; i++) { const auto child = node->getChild(i); - if (child->getStyle().display() == Display::None) { + // Absolute children will be handled by their containing block since we + // cannot guarantee that their positions are set when their parents are + // done with layout. + if (child->getStyle().display() == Display::None || + (!node->hasErrata(Errata::PositionStaticBehavesLikeRelative) && + child->getStyle().positionType() == PositionType::Absolute)) { continue; } if (needsMainTrailingPos) { From 047b96b9a68a48057e5b2a82f82c54d1e71fad7f Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Mon, 4 Dec 2023 15:21:32 -0800 Subject: [PATCH 4/4] Use containing block to adjust absolute child position (#41490) Summary: X-link: https://github.com/facebook/yoga/pull/1472 This change has most of the logic needed for supporting `position: static`. We do two things here that fix a lot of the broken static test: 1) We pass in the containing node to `layoutAbsoluteChild` and use it to properly position the child in the case that insets are defined. 2) We rewrite the absolute child's position to be relative to it's parent in the event that insets are defined for that child (and thus it is positioned relative to its CB). Yoga's layout position has always be relative to parent, so I feel it is easier to just adjust the coordinates of a node to adhere to that design rather than change the consumers of yoga. The "hard" part of this algorithm is determining how to iterate the offset from the containing block needed to do this translation described above. That is handled in `layoutAbsoluteDescendants`. Reviewed By: NickGerleman Differential Revision: D51224327 --- .../yoga/yoga/algorithm/CalculateLayout.cpp | 180 ++++++++++++------ .../ReactCommon/yoga/yoga/style/Style.h | 16 ++ 2 files changed, 136 insertions(+), 60 deletions(-) diff --git a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp index 733603d043b230..9b2fcde5a91087 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp +++ b/packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp @@ -319,11 +319,12 @@ static void computeFlexBasisForChild( } static void layoutAbsoluteChild( + const yoga::Node* const containingNode, const yoga::Node* const node, yoga::Node* const child, - const float width, + const float containingBlockWidth, + const float containingBlockHeight, const SizingMode widthMode, - const float height, const Direction direction, LayoutData& layoutMarkerData, const uint32_t depth, @@ -338,48 +339,65 @@ static void layoutAbsoluteChild( SizingMode childWidthSizingMode = SizingMode::MaxContent; SizingMode childHeightSizingMode = SizingMode::MaxContent; - auto marginRow = child->getMarginForAxis(FlexDirection::Row, width); - auto marginColumn = child->getMarginForAxis(FlexDirection::Column, width); + auto marginRow = + child->getMarginForAxis(FlexDirection::Row, containingBlockWidth); + auto marginColumn = + child->getMarginForAxis(FlexDirection::Column, containingBlockWidth); - if (styleDefinesDimension(child, FlexDirection::Row, width)) { + if (styleDefinesDimension(child, FlexDirection::Row, containingBlockWidth)) { childWidth = - yoga::resolveValue(child->getResolvedDimension(Dimension::Width), width) + yoga::resolveValue( + child->getResolvedDimension(Dimension::Width), containingBlockWidth) .unwrap() + marginRow; } else { // If the child doesn't have a specified width, compute the width based on // the left/right offsets if they're defined. - if (child->isInlineStartPositionDefined(FlexDirection::Row, direction) && - child->isInlineEndPositionDefined(FlexDirection::Row, direction)) { - childWidth = node->getLayout().measuredDimension(Dimension::Width) - - (node->getInlineStartBorder(FlexDirection::Row, direction) + - node->getInlineEndBorder(FlexDirection::Row, direction)) - - (child->getInlineStartPosition(FlexDirection::Row, direction, width) + - child->getInlineEndPosition(FlexDirection::Row, direction, width)); + if (child->isFlexStartPositionDefined(FlexDirection::Row) && + child->isFlexEndPositionDefined(FlexDirection::Row)) { childWidth = - boundAxis(child, FlexDirection::Row, childWidth, width, width); + containingNode->getLayout().measuredDimension(Dimension::Width) - + (containingNode->getFlexStartBorder(FlexDirection::Row, direction) + + containingNode->getFlexEndBorder(FlexDirection::Row, direction)) - + (child->getFlexStartPosition( + FlexDirection::Row, containingBlockWidth) + + child->getFlexEndPosition(FlexDirection::Row, containingBlockWidth)); + childWidth = boundAxis( + child, + FlexDirection::Row, + childWidth, + containingBlockWidth, + containingBlockWidth); } } - if (styleDefinesDimension(child, FlexDirection::Column, height)) { + if (styleDefinesDimension( + child, FlexDirection::Column, containingBlockHeight)) { childHeight = yoga::resolveValue( - child->getResolvedDimension(Dimension::Height), height) + child->getResolvedDimension(Dimension::Height), + containingBlockHeight) .unwrap() + marginColumn; } else { // If the child doesn't have a specified height, compute the height based on // the top/bottom offsets if they're defined. - if (child->isInlineStartPositionDefined(FlexDirection::Column, direction) && - child->isInlineEndPositionDefined(FlexDirection::Column, direction)) { - childHeight = node->getLayout().measuredDimension(Dimension::Height) - - (node->getInlineStartBorder(FlexDirection::Column, direction) + - node->getInlineEndBorder(FlexDirection::Column, direction)) - - (child->getInlineStartPosition( - FlexDirection::Column, direction, height) + - child->getInlineEndPosition( - FlexDirection::Column, direction, height)); + if (child->isFlexStartPositionDefined(FlexDirection::Column) && + child->isFlexEndPositionDefined(FlexDirection::Column)) { childHeight = - boundAxis(child, FlexDirection::Column, childHeight, height, width); + containingNode->getLayout().measuredDimension(Dimension::Height) - + (containingNode->getFlexStartBorder( + FlexDirection::Column, direction) + + containingNode->getFlexEndBorder(FlexDirection::Column, direction)) - + (child->getFlexStartPosition( + FlexDirection::Column, containingBlockHeight) + + child->getFlexEndPosition( + FlexDirection::Column, containingBlockHeight)); + childHeight = boundAxis( + child, + FlexDirection::Column, + childHeight, + containingBlockHeight, + containingBlockWidth); } } @@ -413,9 +431,9 @@ 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 != SizingMode::MaxContent && yoga::isDefined(width) && - width > 0) { - childWidth = width; + widthMode != SizingMode::MaxContent && + yoga::isDefined(containingBlockWidth) && containingBlockWidth > 0) { + childWidth = containingBlockWidth; childWidthSizingMode = SizingMode::FitContent; } @@ -434,9 +452,9 @@ static void layoutAbsoluteChild( depth, generationCount); childWidth = child->getLayout().measuredDimension(Dimension::Width) + - child->getMarginForAxis(FlexDirection::Row, width); + child->getMarginForAxis(FlexDirection::Row, containingBlockWidth); childHeight = child->getLayout().measuredDimension(Dimension::Height) + - child->getMarginForAxis(FlexDirection::Column, width); + child->getMarginForAxis(FlexDirection::Column, containingBlockWidth); } calculateLayoutInternal( @@ -457,11 +475,15 @@ static void layoutAbsoluteChild( if (child->isFlexEndPositionDefined(mainAxis) && !child->isFlexStartPositionDefined(mainAxis)) { child->setLayoutPosition( - node->getLayout().measuredDimension(dimension(mainAxis)) - + containingNode->getLayout().measuredDimension(dimension(mainAxis)) - child->getLayout().measuredDimension(dimension(mainAxis)) - - node->getFlexEndBorder(mainAxis, direction) - - child->getFlexEndMargin(mainAxis, isMainAxisRow ? width : height) - - child->getFlexEndPosition(mainAxis, isMainAxisRow ? width : height), + containingNode->getFlexEndBorder(mainAxis, direction) - + child->getFlexEndMargin( + mainAxis, + isMainAxisRow ? containingBlockWidth : containingBlockHeight) - + child->getFlexEndPosition( + mainAxis, + isMainAxisRow ? containingBlockWidth : containingBlockHeight), flexStartEdge(mainAxis)); } else if ( !child->isFlexStartPositionDefined(mainAxis) && @@ -485,25 +507,28 @@ static void layoutAbsoluteChild( child->setLayoutPosition( child->getFlexStartPosition( mainAxis, - node->getLayout().measuredDimension(dimension(mainAxis))) + - node->getFlexStartBorder(mainAxis, direction) + + containingNode->getLayout().measuredDimension( + dimension(mainAxis))) + + containingNode->getFlexStartBorder(mainAxis, direction) + child->getFlexStartMargin( mainAxis, - node->getLayout().measuredDimension(dimension(mainAxis))), + isMainAxisRow ? containingBlockWidth : containingBlockHeight), flexStartEdge(mainAxis)); } if (child->isFlexEndPositionDefined(crossAxis) && !child->isFlexStartPositionDefined(crossAxis)) { child->setLayoutPosition( - node->getLayout().measuredDimension(dimension(crossAxis)) - + containingNode->getLayout().measuredDimension(dimension(crossAxis)) - child->getLayout().measuredDimension(dimension(crossAxis)) - - node->getFlexEndBorder(crossAxis, direction) - - child->getFlexEndMargin(crossAxis, isMainAxisRow ? height : width) - + containingNode->getFlexEndBorder(crossAxis, direction) - + child->getFlexEndMargin( + crossAxis, + isMainAxisRow ? containingBlockHeight : containingBlockWidth) - child->getFlexEndPosition( - crossAxis, isMainAxisRow ? height : width), + crossAxis, + isMainAxisRow ? containingBlockHeight : containingBlockWidth), flexStartEdge(crossAxis)); - } else if ( !child->isFlexStartPositionDefined(crossAxis) && resolveChildAlignment(node, child) == Align::Center) { @@ -521,49 +546,74 @@ static void layoutAbsoluteChild( child->getLayout().measuredDimension(dimension(crossAxis))), flexStartEdge(crossAxis)); } else if ( - node->getConfig()->isExperimentalFeatureEnabled( + containingNode->getConfig()->isExperimentalFeatureEnabled( ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge) && child->isFlexStartPositionDefined(crossAxis)) { child->setLayoutPosition( child->getFlexStartPosition( crossAxis, - node->getLayout().measuredDimension(dimension(crossAxis))) + - node->getFlexStartBorder(crossAxis, direction) + + containingNode->getLayout().measuredDimension( + dimension(crossAxis))) + + containingNode->getFlexStartBorder(crossAxis, direction) + child->getFlexStartMargin( crossAxis, - node->getLayout().measuredDimension(dimension(crossAxis))), + isMainAxisRow ? containingBlockHeight : containingBlockWidth), flexStartEdge(crossAxis)); } } static void layoutAbsoluteDescendants( + yoga::Node* containingNode, yoga::Node* currentNode, SizingMode widthSizingMode, Direction currentNodeDirection, LayoutData& layoutMarkerData, uint32_t currentDepth, uint32_t generationCount, - float containingBlockWidth, - float containingBlockHeight) { + float currentNodeMainOffsetFromContainingBlock, + float currentNodeCrossOffsetFromContainingBlock) { + const FlexDirection mainAxis = resolveDirection( + currentNode->getStyle().flexDirection(), currentNodeDirection); + const FlexDirection crossAxis = + resolveCrossDirection(mainAxis, currentNodeDirection); for (auto child : currentNode->getChildren()) { if (child->getStyle().display() == Display::None) { continue; } else if (child->getStyle().positionType() == PositionType::Absolute) { layoutAbsoluteChild( + containingNode, currentNode, child, - containingBlockWidth, + containingNode->getLayout().measuredDimension(Dimension::Width), + containingNode->getLayout().measuredDimension(Dimension::Height), widthSizingMode, - containingBlockHeight, currentNodeDirection, layoutMarkerData, currentDepth, generationCount); - const FlexDirection mainAxis = resolveDirection( - currentNode->getStyle().flexDirection(), currentNodeDirection); - const FlexDirection crossAxis = - resolveCrossDirection(mainAxis, currentNodeDirection); + const bool isMainAxisRow = isRow(mainAxis); + const bool mainInsetsDefined = isMainAxisRow + ? child->getStyle().horizontalInsetsDefined() + : child->getStyle().verticalInsetsDefined(); + const bool crossInsetsDefined = isMainAxisRow + ? child->getStyle().verticalInsetsDefined() + : child->getStyle().horizontalInsetsDefined(); + + const float childMainOffsetFromParent = mainInsetsDefined + ? (child->getLayout().position(flexStartEdge(mainAxis)) - + currentNodeMainOffsetFromContainingBlock) + : child->getLayout().position(flexStartEdge(mainAxis)); + const float childCrossOffsetFromParent = crossInsetsDefined + ? (child->getLayout().position(flexStartEdge(crossAxis)) - + currentNodeCrossOffsetFromContainingBlock) + : child->getLayout().position(flexStartEdge(crossAxis)); + + child->setLayoutPosition( + childMainOffsetFromParent, flexStartEdge(mainAxis)); + child->setLayoutPosition( + childCrossOffsetFromParent, flexStartEdge(crossAxis)); + if (needsTrailingPosition(mainAxis)) { setChildTrailingPosition(currentNode, child, mainAxis); } @@ -573,15 +623,23 @@ static void layoutAbsoluteDescendants( } else if (child->getStyle().positionType() == PositionType::Static) { const Direction childDirection = child->resolveDirection(currentNodeDirection); + const float childMainOffsetFromContainingBlock = + currentNodeMainOffsetFromContainingBlock + + child->getLayout().position(flexStartEdge(mainAxis)); + const float childCrossOffsetFromContainingBlock = + currentNodeCrossOffsetFromContainingBlock + + child->getLayout().position(flexStartEdge(crossAxis)); + layoutAbsoluteDescendants( + containingNode, child, widthSizingMode, childDirection, layoutMarkerData, currentDepth + 1, generationCount, - containingBlockWidth, - containingBlockHeight); + childMainOffsetFromContainingBlock, + childCrossOffsetFromContainingBlock); } } } @@ -2365,14 +2423,15 @@ static void calculateLayoutImpl( if (node->getStyle().positionType() != PositionType::Static || depth == 1) { layoutAbsoluteDescendants( + node, node, isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, direction, layoutMarkerData, depth, generationCount, - node->getLayout().measuredDimension(Dimension::Width), - node->getLayout().measuredDimension(Dimension::Height)); + 0.0f, + 0.0f); } } else { for (auto child : node->getChildren()) { @@ -2385,15 +2444,16 @@ static void calculateLayoutImpl( ExperimentalFeature::AbsolutePercentageAgainstPaddingEdge); layoutAbsoluteChild( + node, node, child, absolutePercentageAgainstPaddingEdge ? node->getLayout().measuredDimension(Dimension::Width) : availableInnerWidth, - isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, absolutePercentageAgainstPaddingEdge ? node->getLayout().measuredDimension(Dimension::Height) : availableInnerHeight, + isMainAxisRow ? sizingModeMainDim : sizingModeCrossDim, direction, layoutMarkerData, depth, diff --git a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h index 530cbb75c309ed..ea3680aa441bc1 100644 --- a/packages/react-native/ReactCommon/yoga/yoga/style/Style.h +++ b/packages/react-native/ReactCommon/yoga/yoga/style/Style.h @@ -231,6 +231,22 @@ class YG_EXPORT Style { } } + bool horizontalInsetsDefined() const { + return position_[YGEdge::YGEdgeLeft].isDefined() || + position_[YGEdge::YGEdgeRight].isDefined() || + position_[YGEdge::YGEdgeAll].isDefined() || + position_[YGEdge::YGEdgeHorizontal].isDefined() || + position_[YGEdge::YGEdgeStart].isDefined() || + position_[YGEdge::YGEdgeEnd].isDefined(); + } + + bool verticalInsetsDefined() const { + return position_[YGEdge::YGEdgeTop].isDefined() || + position_[YGEdge::YGEdgeBottom].isDefined() || + position_[YGEdge::YGEdgeAll].isDefined() || + position_[YGEdge::YGEdgeVertical].isDefined(); + } + bool operator==(const Style& other) const { return direction_ == other.direction_ && flexDirection_ == other.flexDirection_ &&