diff --git a/enums.py b/enums.py index fa212249c0..543ad99152 100755 --- a/enums.py +++ b/enums.py @@ -61,9 +61,10 @@ # Allows main-axis flex basis to be stretched without flexGrow being # set (previously referred to as "UseLegacyStretchBehaviour") ("StretchFlexBasis", 1 << 0), - # Positioning of absolute nodes will have various bugs related to - # justification, alignment, and insets - ("AbsolutePositioningIncorrect", 1 << 1), + # Absolute position in a given axis will be relative to the padding + # edge of the parent container instead of the content edge when a + # specific inset (top/bottom/left/right) is not set. + ("AbsolutePositionWithoutInsetsExcludesPadding", 1 << 1), # Absolute nodes will resolve percentages against the inner size of # their containing node, not the padding box ("AbsolutePercentAgainstInnerSize", 1 << 2), diff --git a/java/com/facebook/yoga/YogaErrata.java b/java/com/facebook/yoga/YogaErrata.java index a0f26bf2a9..e0521b3fbb 100644 --- a/java/com/facebook/yoga/YogaErrata.java +++ b/java/com/facebook/yoga/YogaErrata.java @@ -12,7 +12,7 @@ public enum YogaErrata { NONE(0), STRETCH_FLEX_BASIS(1), - ABSOLUTE_POSITIONING_INCORRECT(2), + ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING(2), ABSOLUTE_PERCENT_AGAINST_INNER_SIZE(4), ALL(2147483647), CLASSIC(2147483646); @@ -31,7 +31,7 @@ public static YogaErrata fromInt(int value) { switch (value) { case 0: return NONE; case 1: return STRETCH_FLEX_BASIS; - case 2: return ABSOLUTE_POSITIONING_INCORRECT; + case 2: return ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING; case 4: return ABSOLUTE_PERCENT_AGAINST_INNER_SIZE; case 2147483647: return ALL; case 2147483646: return CLASSIC; diff --git a/javascript/src/generated/YGEnums.ts b/javascript/src/generated/YGEnums.ts index 48f27bf9af..ef3f141ef5 100644 --- a/javascript/src/generated/YGEnums.ts +++ b/javascript/src/generated/YGEnums.ts @@ -55,7 +55,7 @@ export enum Edge { export enum Errata { None = 0, StretchFlexBasis = 1, - AbsolutePositioningIncorrect = 2, + AbsolutePositionWithoutInsetsExcludesPadding = 2, AbsolutePercentAgainstInnerSize = 4, All = 2147483647, Classic = 2147483646, @@ -162,7 +162,7 @@ const constants = { EDGE_ALL: Edge.All, ERRATA_NONE: Errata.None, ERRATA_STRETCH_FLEX_BASIS: Errata.StretchFlexBasis, - ERRATA_ABSOLUTE_POSITIONING_INCORRECT: Errata.AbsolutePositioningIncorrect, + ERRATA_ABSOLUTE_POSITION_WITHOUT_INSETS_EXCLUDES_PADDING: Errata.AbsolutePositionWithoutInsetsExcludesPadding, ERRATA_ABSOLUTE_PERCENT_AGAINST_INNER_SIZE: Errata.AbsolutePercentAgainstInnerSize, ERRATA_ALL: Errata.All, ERRATA_CLASSIC: Errata.Classic, diff --git a/yoga/YGEnums.cpp b/yoga/YGEnums.cpp index c0a72918d8..bea2cefa93 100644 --- a/yoga/YGEnums.cpp +++ b/yoga/YGEnums.cpp @@ -105,8 +105,8 @@ const char* YGErrataToString(const YGErrata value) { return "none"; case YGErrataStretchFlexBasis: return "stretch-flex-basis"; - case YGErrataAbsolutePositioningIncorrect: - return "absolute-positioning-incorrect"; + case YGErrataAbsolutePositionWithoutInsetsExcludesPadding: + return "absolute-position-without-insets-excludes-padding"; case YGErrataAbsolutePercentAgainstInnerSize: return "absolute-percent-against-inner-size"; case YGErrataAll: diff --git a/yoga/YGEnums.h b/yoga/YGEnums.h index 83c368a601..a41f723220 100644 --- a/yoga/YGEnums.h +++ b/yoga/YGEnums.h @@ -61,7 +61,7 @@ YG_ENUM_DECL( YGErrata, YGErrataNone = 0, YGErrataStretchFlexBasis = 1, - YGErrataAbsolutePositioningIncorrect = 2, + YGErrataAbsolutePositionWithoutInsetsExcludesPadding = 2, YGErrataAbsolutePercentAgainstInnerSize = 4, YGErrataAll = 2147483647, YGErrataClassic = 2147483646) diff --git a/yoga/algorithm/AbsoluteLayout.cpp b/yoga/algorithm/AbsoluteLayout.cpp index de4eef9df9..852c8fc4f0 100644 --- a/yoga/algorithm/AbsoluteLayout.cpp +++ b/yoga/algorithm/AbsoluteLayout.cpp @@ -19,12 +19,15 @@ static inline void setFlexStartLayoutPosition( const Direction direction, const FlexDirection axis, const float containingBlockWidth) { - child->setLayoutPosition( - child->style().computeFlexStartMargin( - axis, direction, containingBlockWidth) + - parent->getLayout().border(flexStartEdge(axis)) + - parent->getLayout().padding(flexStartEdge(axis)), - flexStartEdge(axis)); + float position = child->style().computeFlexStartMargin( + axis, direction, containingBlockWidth) + + parent->getLayout().border(flexStartEdge(axis)); + + if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) { + position += parent->getLayout().padding(flexStartEdge(axis)); + } + + child->setLayoutPosition(position, flexStartEdge(axis)); } static inline void setFlexEndLayoutPosition( @@ -33,15 +36,16 @@ static inline void setFlexEndLayoutPosition( const Direction direction, const FlexDirection axis, const float containingBlockWidth) { + float flexEndPosition = parent->getLayout().border(flexEndEdge(axis)) + + child->style().computeFlexEndMargin( + axis, direction, containingBlockWidth); + + if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) { + flexEndPosition += parent->getLayout().padding(flexEndEdge(axis)); + } + child->setLayoutPosition( - getPositionOfOppositeEdge( - parent->getLayout().border(flexEndEdge(axis)) + - parent->getLayout().padding(flexEndEdge(axis)) + - child->style().computeFlexEndMargin( - axis, direction, containingBlockWidth), - axis, - parent, - child), + getPositionOfOppositeEdge(flexEndPosition, axis, parent, child), flexStartEdge(axis)); } @@ -51,22 +55,30 @@ static inline void setCenterLayoutPosition( const Direction direction, const FlexDirection axis, const float containingBlockWidth) { - const float parentContentBoxSize = + float parentContentBoxSize = parent->getLayout().measuredDimension(dimension(axis)) - parent->getLayout().border(flexStartEdge(axis)) - - parent->getLayout().border(flexEndEdge(axis)) - - parent->getLayout().padding(flexStartEdge(axis)) - - parent->getLayout().padding(flexEndEdge(axis)); + parent->getLayout().border(flexEndEdge(axis)); + + if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) { + parentContentBoxSize -= parent->getLayout().padding(flexStartEdge(axis)); + parentContentBoxSize -= parent->getLayout().padding(flexEndEdge(axis)); + } + const float childOuterSize = child->getLayout().measuredDimension(dimension(axis)) + child->style().computeMarginForAxis(axis, containingBlockWidth); - child->setLayoutPosition( - (parentContentBoxSize - childOuterSize) / 2.0f + - parent->getLayout().border(flexStartEdge(axis)) + - parent->getLayout().padding(flexStartEdge(axis)) + - child->style().computeFlexStartMargin( - axis, direction, containingBlockWidth), - flexStartEdge(axis)); + + float position = (parentContentBoxSize - childOuterSize) / 2.0f + + parent->getLayout().border(flexStartEdge(axis)) + + child->style().computeFlexStartMargin( + axis, direction, containingBlockWidth); + + if (!child->hasErrata(Errata::AbsolutePositionWithoutInsetsExcludesPadding)) { + position += parent->getLayout().padding(flexStartEdge(axis)); + } + + child->setLayoutPosition(position, flexStartEdge(axis)); } static void justifyAbsoluteChild( @@ -133,62 +145,6 @@ static void alignAbsoluteChild( } } -// To ensure no breaking changes, we preserve the legacy way of positioning -// absolute children and determine if we should use it using an errata. -static void positionAbsoluteChildLegacy( - const yoga::Node* const containingNode, - const yoga::Node* const parent, - yoga::Node* child, - const Direction direction, - const FlexDirection axis, - const bool isMainAxis, - const float containingBlockWidth, - const float containingBlockHeight) { - const bool isAxisRow = isRow(axis); - const bool shouldCenter = isMainAxis - ? parent->style().justifyContent() == Justify::Center - : resolveChildAlignment(parent, child) == Align::Center; - const bool shouldFlexEnd = isMainAxis - ? parent->style().justifyContent() == Justify::FlexEnd - : ((resolveChildAlignment(parent, child) == Align::FlexEnd) ^ - (parent->style().flexWrap() == Wrap::WrapReverse)); - - if (child->style().isFlexEndPositionDefined(axis, direction) && - (!child->style().isFlexStartPositionDefined(axis, direction) || - child->style().isFlexStartPositionAuto(axis, direction))) { - child->setLayoutPosition( - containingNode->getLayout().measuredDimension(dimension(axis)) - - child->getLayout().measuredDimension(dimension(axis)) - - containingNode->style().computeFlexEndBorder(axis, direction) - - child->style().computeFlexEndMargin( - axis, - direction, - isAxisRow ? containingBlockWidth : containingBlockHeight) - - child->style().computeFlexEndPosition( - axis, - direction, - isAxisRow ? containingBlockWidth : containingBlockHeight), - flexStartEdge(axis)); - } else if ( - (!child->style().isFlexStartPositionDefined(axis, direction) || - child->style().isFlexStartPositionAuto(axis, direction)) && - shouldCenter) { - child->setLayoutPosition( - (parent->getLayout().measuredDimension(dimension(axis)) - - child->getLayout().measuredDimension(dimension(axis))) / - 2.0f, - flexStartEdge(axis)); - } else if ( - (!child->style().isFlexStartPositionDefined(axis, direction) || - child->style().isFlexStartPositionAuto(axis, direction)) && - shouldFlexEnd) { - child->setLayoutPosition( - (parent->getLayout().measuredDimension(dimension(axis)) - - child->getLayout().measuredDimension(dimension(axis))), - flexStartEdge(axis)); - } -} - /* * Absolutely positioned nodes do not participate in flex layout and thus their * positions can be determined independently from the rest of their siblings. @@ -205,7 +161,7 @@ static void positionAbsoluteChildLegacy( * This function does that positioning for the given axis. The spec has more * information on this topic: https://www.w3.org/TR/css-flexbox-1/#abspos-items */ -static void positionAbsoluteChildImpl( +static void positionAbsoluteChild( const yoga::Node* const containingNode, const yoga::Node* const parent, yoga::Node* child, @@ -267,36 +223,6 @@ static void positionAbsoluteChildImpl( } } -static void positionAbsoluteChild( - const yoga::Node* const containingNode, - const yoga::Node* const parent, - yoga::Node* child, - const Direction direction, - const FlexDirection axis, - const bool isMainAxis, - const float containingBlockWidth, - const float containingBlockHeight) { - child->hasErrata(Errata::AbsolutePositioningIncorrect) - ? positionAbsoluteChildLegacy( - containingNode, - parent, - child, - direction, - axis, - isMainAxis, - containingBlockWidth, - containingBlockHeight) - : positionAbsoluteChildImpl( - containingNode, - parent, - child, - direction, - axis, - isMainAxis, - containingBlockWidth, - containingBlockHeight); -} - void layoutAbsoluteChild( const yoga::Node* const containingNode, const yoga::Node* const node, diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 3a98c9232c..d3c9bd7863 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -981,7 +981,6 @@ static void resolveFlexibleLength( static void justifyMainAxis( yoga::Node* const node, FlexLine& flexLine, - const size_t startOfLineIndex, const FlexDirection mainAxis, const FlexDirection crossAxis, const Direction direction, @@ -1081,102 +1080,69 @@ static void justifyMainAxis( float maxAscentForCurrentLine = 0; float maxDescentForCurrentLine = 0; bool isNodeBaselineLayout = isBaselineLayout(node); - for (size_t i = startOfLineIndex; i < flexLine.endOfLineIndex; i++) { - const auto child = node->getChild(i); - const Style& childStyle = child->style(); + for (auto child : flexLine.itemsInFlow) { const LayoutResults& childLayout = child->getLayout(); - if (childStyle.display() == Display::None) { - continue; + if (child->style().flexStartMarginIsAuto(mainAxis, direction) && + flexLine.layout.remainingFreeSpace > 0.0f) { + flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / + static_cast(flexLine.numberOfAutoMargins); } - if (childStyle.positionType() == PositionType::Absolute && - child->style().isFlexStartPositionDefined(mainAxis, direction) && - !child->style().isFlexStartPositionAuto(mainAxis, direction)) { - if (performLayout) { - // In case the child is position absolute and has left/top being - // defined, we override the position to whatever the user said (and - // margin/border). - child->setLayoutPosition( - child->style().computeFlexStartPosition( - mainAxis, direction, availableInnerMainDim) + - node->style().computeFlexStartBorder(mainAxis, direction) + - child->style().computeFlexStartMargin( - mainAxis, direction, availableInnerWidth), - flexStartEdge(mainAxis)); - } - } else { - // Now that we placed the element, we need to update the variables. - // We need to do that only for relative elements. Absolute elements do not - // take part in that phase. - if (childStyle.positionType() != PositionType::Absolute) { - if (child->style().flexStartMarginIsAuto(mainAxis, direction) && - flexLine.layout.remainingFreeSpace > 0.0f) { - flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / - static_cast(flexLine.numberOfAutoMargins); - } - if (performLayout) { - child->setLayoutPosition( - childLayout.position(flexStartEdge(mainAxis)) + - flexLine.layout.mainDim, - flexStartEdge(mainAxis)); - } - - if (child != flexLine.itemsInFlow.back()) { - flexLine.layout.mainDim += betweenMainDim; - } + if (performLayout) { + child->setLayoutPosition( + childLayout.position(flexStartEdge(mainAxis)) + + flexLine.layout.mainDim, + flexStartEdge(mainAxis)); + } - if (child->style().flexEndMarginIsAuto(mainAxis, direction) && - flexLine.layout.remainingFreeSpace > 0.0f) { - flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / - static_cast(flexLine.numberOfAutoMargins); - } - bool canSkipFlex = - !performLayout && sizingModeCrossDim == SizingMode::StretchFit; - if (canSkipFlex) { - // If we skipped the flex step, then we can't rely on the measuredDims - // because they weren't computed. This means we can't call - // dimensionWithMargin. - flexLine.layout.mainDim += child->style().computeMarginForAxis( - mainAxis, availableInnerWidth) + - childLayout.computedFlexBasis.unwrap(); - flexLine.layout.crossDim = availableInnerCrossDim; - } else { - // The main dimension is the sum of all the elements dimension plus - // the spacing. - flexLine.layout.mainDim += - child->dimensionWithMargin(mainAxis, availableInnerWidth); - - if (isNodeBaselineLayout) { - // If the child is baseline aligned then the cross dimension is - // calculated by adding maxAscent and maxDescent from the baseline. - const float ascent = calculateBaseline(child) + - child->style().computeFlexStartMargin( - FlexDirection::Column, direction, availableInnerWidth); - const float descent = - child->getLayout().measuredDimension(Dimension::Height) + - child->style().computeMarginForAxis( - FlexDirection::Column, availableInnerWidth) - - ascent; + if (child != flexLine.itemsInFlow.back()) { + flexLine.layout.mainDim += betweenMainDim; + } - maxAscentForCurrentLine = - yoga::maxOrDefined(maxAscentForCurrentLine, ascent); - maxDescentForCurrentLine = - yoga::maxOrDefined(maxDescentForCurrentLine, descent); - } else { - // The cross dimension is the max of the elements dimension since - // there can only be one element in that cross dimension in the case - // when the items are not baseline aligned - flexLine.layout.crossDim = yoga::maxOrDefined( - flexLine.layout.crossDim, - child->dimensionWithMargin(crossAxis, availableInnerWidth)); - } - } - } else if (performLayout) { - child->setLayoutPosition( - childLayout.position(flexStartEdge(mainAxis)) + - node->style().computeFlexStartBorder(mainAxis, direction) + - leadingMainDim, - flexStartEdge(mainAxis)); + if (child->style().flexEndMarginIsAuto(mainAxis, direction) && + flexLine.layout.remainingFreeSpace > 0.0f) { + flexLine.layout.mainDim += flexLine.layout.remainingFreeSpace / + static_cast(flexLine.numberOfAutoMargins); + } + bool canSkipFlex = + !performLayout && sizingModeCrossDim == SizingMode::StretchFit; + if (canSkipFlex) { + // If we skipped the flex step, then we can't rely on the measuredDims + // because they weren't computed. This means we can't call + // dimensionWithMargin. + flexLine.layout.mainDim += + child->style().computeMarginForAxis(mainAxis, availableInnerWidth) + + childLayout.computedFlexBasis.unwrap(); + flexLine.layout.crossDim = availableInnerCrossDim; + } else { + // The main dimension is the sum of all the elements dimension plus + // the spacing. + flexLine.layout.mainDim += + child->dimensionWithMargin(mainAxis, availableInnerWidth); + + if (isNodeBaselineLayout) { + // If the child is baseline aligned then the cross dimension is + // calculated by adding maxAscent and maxDescent from the baseline. + const float ascent = calculateBaseline(child) + + child->style().computeFlexStartMargin( + FlexDirection::Column, direction, availableInnerWidth); + const float descent = + child->getLayout().measuredDimension(Dimension::Height) + + child->style().computeMarginForAxis( + FlexDirection::Column, availableInnerWidth) - + ascent; + + maxAscentForCurrentLine = + yoga::maxOrDefined(maxAscentForCurrentLine, ascent); + maxDescentForCurrentLine = + yoga::maxOrDefined(maxDescentForCurrentLine, descent); + } else { + // The cross dimension is the max of the elements dimension since + // there can only be one element in that cross dimension in the case + // when the items are not baseline aligned + flexLine.layout.crossDim = yoga::maxOrDefined( + flexLine.layout.crossDim, + child->dimensionWithMargin(crossAxis, availableInnerWidth)); } } } @@ -1616,7 +1582,6 @@ static void calculateLayoutImpl( justifyMainAxis( node, flexLine, - startOfLineIndex, mainAxis, crossAxis, direction, @@ -1668,151 +1633,116 @@ static void calculateLayoutImpl( // STEP 7: CROSS-AXIS ALIGNMENT // We can skip child alignment if we're just measuring the container. if (performLayout) { - for (size_t i = startOfLineIndex; i < endOfLineIndex; i++) { - const auto child = node->getChild(i); - if (child->style().display() == Display::None) { - continue; - } - if (child->style().positionType() == PositionType::Absolute) { - // If the child is absolutely positioned and has a - // top/left/bottom/right set, override all the previously computed - // positions to set it correctly. - const bool isChildLeadingPosDefined = - child->style().isFlexStartPositionDefined(crossAxis, direction) && - !child->style().isFlexStartPositionAuto(crossAxis, direction); - if (isChildLeadingPosDefined) { - child->setLayoutPosition( - child->style().computeFlexStartPosition( - crossAxis, direction, availableInnerCrossDim) + - node->style().computeFlexStartBorder(crossAxis, direction) + - child->style().computeFlexStartMargin( - crossAxis, direction, availableInnerWidth), - flexStartEdge(crossAxis)); - } - // If leading position is not defined or calculations result in Nan, - // default to border + margin - if (!isChildLeadingPosDefined || - yoga::isUndefined( - child->getLayout().position(flexStartEdge(crossAxis)))) { - child->setLayoutPosition( - node->style().computeFlexStartBorder(crossAxis, direction) + - child->style().computeFlexStartMargin( - crossAxis, direction, availableInnerWidth), - flexStartEdge(crossAxis)); + for (auto child : flexLine.itemsInFlow) { + float leadingCrossDim = leadingPaddingAndBorderCross; + + // For a relative children, we're either using alignItems (owner) or + // alignSelf (child) in order to determine the position in the cross + // axis + const Align alignItem = resolveChildAlignment(node, child); + + // If the child uses align stretch, we need to lay it out one more + // time, this time forcing the cross-axis size to be the computed + // cross size for the current line. + if (alignItem == Align::Stretch && + !child->style().flexStartMarginIsAuto(crossAxis, direction) && + !child->style().flexEndMarginIsAuto(crossAxis, direction)) { + // If the child defines a definite size for its cross axis, there's + // no need to stretch. + if (!child->hasDefiniteLength( + dimension(crossAxis), availableInnerCrossDim)) { + float childMainSize = + child->getLayout().measuredDimension(dimension(mainAxis)); + const auto& childStyle = child->style(); + float childCrossSize = childStyle.aspectRatio().isDefined() + ? child->style().computeMarginForAxis( + crossAxis, availableInnerWidth) + + (isMainAxisRow + ? childMainSize / childStyle.aspectRatio().unwrap() + : childMainSize * childStyle.aspectRatio().unwrap()) + : flexLine.layout.crossDim; + + childMainSize += child->style().computeMarginForAxis( + mainAxis, availableInnerWidth); + + SizingMode childMainSizingMode = SizingMode::StretchFit; + SizingMode childCrossSizingMode = SizingMode::StretchFit; + constrainMaxSizeForMode( + child, + direction, + mainAxis, + availableInnerMainDim, + availableInnerWidth, + &childMainSizingMode, + &childMainSize); + constrainMaxSizeForMode( + child, + direction, + crossAxis, + availableInnerCrossDim, + availableInnerWidth, + &childCrossSizingMode, + &childCrossSize); + + const float childWidth = + isMainAxisRow ? childMainSize : childCrossSize; + const float childHeight = + !isMainAxisRow ? childMainSize : childCrossSize; + + auto alignContent = node->style().alignContent(); + auto crossAxisDoesNotGrow = + alignContent != Align::Stretch && isNodeFlexWrap; + const SizingMode childWidthSizingMode = + yoga::isUndefined(childWidth) || + (!isMainAxisRow && crossAxisDoesNotGrow) + ? SizingMode::MaxContent + : SizingMode::StretchFit; + const SizingMode childHeightSizingMode = + yoga::isUndefined(childHeight) || + (isMainAxisRow && crossAxisDoesNotGrow) + ? SizingMode::MaxContent + : SizingMode::StretchFit; + + calculateLayoutInternal( + child, + childWidth, + childHeight, + direction, + childWidthSizingMode, + childHeightSizingMode, + availableInnerWidth, + availableInnerHeight, + true, + LayoutPassReason::kStretch, + layoutMarkerData, + depth, + generationCount); } } else { - float leadingCrossDim = leadingPaddingAndBorderCross; - - // For a relative children, we're either using alignItems (owner) or - // alignSelf (child) in order to determine the position in the cross - // axis - const Align alignItem = resolveChildAlignment(node, child); - - // If the child uses align stretch, we need to lay it out one more - // time, this time forcing the cross-axis size to be the computed - // cross size for the current line. - if (alignItem == Align::Stretch && - !child->style().flexStartMarginIsAuto(crossAxis, direction) && - !child->style().flexEndMarginIsAuto(crossAxis, direction)) { - // If the child defines a definite size for its cross axis, there's - // no need to stretch. - if (!child->hasDefiniteLength( - dimension(crossAxis), availableInnerCrossDim)) { - float childMainSize = - child->getLayout().measuredDimension(dimension(mainAxis)); - const auto& childStyle = child->style(); - float childCrossSize = childStyle.aspectRatio().isDefined() - ? child->style().computeMarginForAxis( - crossAxis, availableInnerWidth) + - (isMainAxisRow - ? childMainSize / childStyle.aspectRatio().unwrap() - : childMainSize * childStyle.aspectRatio().unwrap()) - : flexLine.layout.crossDim; - - childMainSize += child->style().computeMarginForAxis( - mainAxis, availableInnerWidth); - - SizingMode childMainSizingMode = SizingMode::StretchFit; - SizingMode childCrossSizingMode = SizingMode::StretchFit; - constrainMaxSizeForMode( - child, - direction, - mainAxis, - availableInnerMainDim, - availableInnerWidth, - &childMainSizingMode, - &childMainSize); - constrainMaxSizeForMode( - child, - direction, - crossAxis, - availableInnerCrossDim, - availableInnerWidth, - &childCrossSizingMode, - &childCrossSize); - - const float childWidth = - isMainAxisRow ? childMainSize : childCrossSize; - const float childHeight = - !isMainAxisRow ? childMainSize : childCrossSize; - - auto alignContent = node->style().alignContent(); - auto crossAxisDoesNotGrow = - alignContent != Align::Stretch && isNodeFlexWrap; - const SizingMode childWidthSizingMode = - yoga::isUndefined(childWidth) || - (!isMainAxisRow && crossAxisDoesNotGrow) - ? SizingMode::MaxContent - : SizingMode::StretchFit; - const SizingMode childHeightSizingMode = - yoga::isUndefined(childHeight) || - (isMainAxisRow && crossAxisDoesNotGrow) - ? SizingMode::MaxContent - : SizingMode::StretchFit; - - calculateLayoutInternal( - child, - childWidth, - childHeight, - direction, - childWidthSizingMode, - childHeightSizingMode, - availableInnerWidth, - availableInnerHeight, - true, - LayoutPassReason::kStretch, - layoutMarkerData, - depth, - generationCount); - } + const float remainingCrossDim = containerCrossAxis - + child->dimensionWithMargin(crossAxis, availableInnerWidth); + + if (child->style().flexStartMarginIsAuto(crossAxis, direction) && + child->style().flexEndMarginIsAuto(crossAxis, direction)) { + leadingCrossDim += yoga::maxOrDefined(0.0f, remainingCrossDim / 2); + } else if (child->style().flexEndMarginIsAuto(crossAxis, direction)) { + // No-Op + } else if (child->style().flexStartMarginIsAuto( + crossAxis, direction)) { + leadingCrossDim += yoga::maxOrDefined(0.0f, remainingCrossDim); + } else if (alignItem == Align::FlexStart) { + // No-Op + } else if (alignItem == Align::Center) { + leadingCrossDim += remainingCrossDim / 2; } else { - const float remainingCrossDim = containerCrossAxis - - child->dimensionWithMargin(crossAxis, availableInnerWidth); - - if (child->style().flexStartMarginIsAuto(crossAxis, direction) && - child->style().flexEndMarginIsAuto(crossAxis, direction)) { - leadingCrossDim += - yoga::maxOrDefined(0.0f, remainingCrossDim / 2); - } else if (child->style().flexEndMarginIsAuto( - crossAxis, direction)) { - // No-Op - } else if (child->style().flexStartMarginIsAuto( - crossAxis, direction)) { - leadingCrossDim += yoga::maxOrDefined(0.0f, remainingCrossDim); - } else if (alignItem == Align::FlexStart) { - // No-Op - } else if (alignItem == Align::Center) { - leadingCrossDim += remainingCrossDim / 2; - } else { - leadingCrossDim += remainingCrossDim; - } + leadingCrossDim += remainingCrossDim; } - // And we apply the position - child->setLayoutPosition( - child->getLayout().position(flexStartEdge(crossAxis)) + - totalLineCrossDim + leadingCrossDim, - flexStartEdge(crossAxis)); } + // And we apply the position + child->setLayoutPosition( + child->getLayout().position(flexStartEdge(crossAxis)) + + totalLineCrossDim + leadingCrossDim, + flexStartEdge(crossAxis)); } } diff --git a/yoga/enums/Errata.h b/yoga/enums/Errata.h index 1b43742e03..2f47a94175 100644 --- a/yoga/enums/Errata.h +++ b/yoga/enums/Errata.h @@ -18,7 +18,7 @@ namespace facebook::yoga { enum class Errata : uint32_t { None = YGErrataNone, StretchFlexBasis = YGErrataStretchFlexBasis, - AbsolutePositioningIncorrect = YGErrataAbsolutePositioningIncorrect, + AbsolutePositionWithoutInsetsExcludesPadding = YGErrataAbsolutePositionWithoutInsetsExcludesPadding, AbsolutePercentAgainstInnerSize = YGErrataAbsolutePercentAgainstInnerSize, All = YGErrataAll, Classic = YGErrataClassic,