From e69fcb26bb110edaca889aa07c4bd7121bd056d9 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Fri, 4 Oct 2024 17:07:05 -0700 Subject: [PATCH] Fix issue where padding for box sizing is resolved against wrong reference length (#1715) Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1715 X-link: https://github.com/facebook/react-native/pull/46799 Content box impl had a bug where we resolved padding % against the same reference length as the dimensions. Padding should always be against containing block's width. This is also true for width, but not for height, which should be against containing block's height. This just pipes the width into our box sizing functions. Changelog: [Internal] Reviewed By: NickGerleman Differential Revision: D63787577 fbshipit-source-id: e512338770f25b66506cabab5a7cde8f04397ea0 --- gentest/fixtures/YGBoxSizingTest.html | 14 +- .../com/facebook/yoga/YGBoxSizingTest.java | 28 ++-- .../tests/generated/YGBoxSizingTest.test.ts | 28 ++-- tests/generated/YGBoxSizingTest.cpp | 28 ++-- yoga/algorithm/AbsoluteLayout.cpp | 10 +- yoga/algorithm/BoundAxis.h | 13 +- yoga/algorithm/CalculateLayout.cpp | 122 ++++++++++++------ yoga/algorithm/FlexLine.cpp | 4 +- yoga/algorithm/FlexLine.h | 1 + yoga/node/Node.cpp | 8 +- yoga/node/Node.h | 8 +- yoga/style/Style.h | 10 +- 12 files changed, 171 insertions(+), 103 deletions(-) diff --git a/gentest/fixtures/YGBoxSizingTest.html b/gentest/fixtures/YGBoxSizingTest.html index 1cf83121..b8fa7a10 100644 --- a/gentest/fixtures/YGBoxSizingTest.html +++ b/gentest/fixtures/YGBoxSizingTest.html @@ -46,16 +46,16 @@ style="width: 100px; height: 100px; padding: 5px; box-sizing: content-box"> -
-
+
+
-
-
+
+
@@ -197,7 +197,8 @@
-
+
@@ -207,7 +208,8 @@
-
+
diff --git a/java/tests/generated/com/facebook/yoga/YGBoxSizingTest.java b/java/tests/generated/com/facebook/yoga/YGBoxSizingTest.java index bbbc3c5c..d6725118 100644 --- a/java/tests/generated/com/facebook/yoga/YGBoxSizingTest.java +++ b/java/tests/generated/com/facebook/yoga/YGBoxSizingTest.java @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<80fa9cf05afc330a721a756dfaf0d1a3>> + * @generated SignedSource<<7f42121bbd9772cdbc079aac71040dcc>> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html */ @@ -452,14 +452,15 @@ public class YGBoxSizingTest { final YogaNode root = createNode(config); root.setPositionType(YogaPositionType.ABSOLUTE); root.setWidth(100f); - root.setHeight(100f); + root.setHeight(150f); final YogaNode root_child0 = createNode(config); root_child0.setPaddingPercent(YogaEdge.LEFT, 10); root_child0.setPaddingPercent(YogaEdge.TOP, 10); root_child0.setPaddingPercent(YogaEdge.RIGHT, 10); root_child0.setPaddingPercent(YogaEdge.BOTTOM, 10); - root_child0.setWidthPercent(50f); + root_child0.setWidth(50f); + root_child0.setHeight(75f); root_child0.setBoxSizing(YogaBoxSizing.CONTENT_BOX); root.addChildAt(root_child0, 0); root.setDirection(YogaDirection.LTR); @@ -468,12 +469,12 @@ public class YGBoxSizingTest { assertEquals(0f, root.getLayoutX(), 0.0f); assertEquals(0f, root.getLayoutY(), 0.0f); assertEquals(100f, root.getLayoutWidth(), 0.0f); - assertEquals(100f, root.getLayoutHeight(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); assertEquals(0f, root_child0.getLayoutX(), 0.0f); assertEquals(0f, root_child0.getLayoutY(), 0.0f); assertEquals(70f, root_child0.getLayoutWidth(), 0.0f); - assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + assertEquals(95f, root_child0.getLayoutHeight(), 0.0f); root.setDirection(YogaDirection.RTL); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -481,12 +482,12 @@ public class YGBoxSizingTest { assertEquals(0f, root.getLayoutX(), 0.0f); assertEquals(0f, root.getLayoutY(), 0.0f); assertEquals(100f, root.getLayoutWidth(), 0.0f); - assertEquals(100f, root.getLayoutHeight(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); assertEquals(30f, root_child0.getLayoutX(), 0.0f); assertEquals(0f, root_child0.getLayoutY(), 0.0f); assertEquals(70f, root_child0.getLayoutWidth(), 0.0f); - assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + assertEquals(95f, root_child0.getLayoutHeight(), 0.0f); } @Test @@ -525,14 +526,15 @@ public class YGBoxSizingTest { final YogaNode root = createNode(config); root.setPositionType(YogaPositionType.ABSOLUTE); root.setWidth(100f); - root.setHeight(100f); + root.setHeight(150f); final YogaNode root_child0 = createNode(config); root_child0.setPaddingPercent(YogaEdge.LEFT, 10); root_child0.setPaddingPercent(YogaEdge.TOP, 10); root_child0.setPaddingPercent(YogaEdge.RIGHT, 10); root_child0.setPaddingPercent(YogaEdge.BOTTOM, 10); - root_child0.setWidthPercent(50f); + root_child0.setWidth(50f); + root_child0.setHeight(75f); root.addChildAt(root_child0, 0); root.setDirection(YogaDirection.LTR); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -540,12 +542,12 @@ public class YGBoxSizingTest { assertEquals(0f, root.getLayoutX(), 0.0f); assertEquals(0f, root.getLayoutY(), 0.0f); assertEquals(100f, root.getLayoutWidth(), 0.0f); - assertEquals(100f, root.getLayoutHeight(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); assertEquals(0f, root_child0.getLayoutX(), 0.0f); assertEquals(0f, root_child0.getLayoutY(), 0.0f); assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); - assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + assertEquals(75f, root_child0.getLayoutHeight(), 0.0f); root.setDirection(YogaDirection.RTL); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -553,12 +555,12 @@ public class YGBoxSizingTest { assertEquals(0f, root.getLayoutX(), 0.0f); assertEquals(0f, root.getLayoutY(), 0.0f); assertEquals(100f, root.getLayoutWidth(), 0.0f); - assertEquals(100f, root.getLayoutHeight(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); assertEquals(50f, root_child0.getLayoutX(), 0.0f); assertEquals(0f, root_child0.getLayoutY(), 0.0f); assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); - assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + assertEquals(75f, root_child0.getLayoutHeight(), 0.0f); } @Test diff --git a/javascript/tests/generated/YGBoxSizingTest.test.ts b/javascript/tests/generated/YGBoxSizingTest.test.ts index fbbcba9a..d9678705 100644 --- a/javascript/tests/generated/YGBoxSizingTest.test.ts +++ b/javascript/tests/generated/YGBoxSizingTest.test.ts @@ -4,7 +4,7 @@ * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. * - * @generated SignedSource<<48d3d46dec54df38f853a6fa17e6f0c6>> + * @generated SignedSource<> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html */ @@ -499,14 +499,15 @@ test('box_sizing_content_box_padding_only_percent', () => { root = Yoga.Node.create(config); root.setPositionType(PositionType.Absolute); root.setWidth(100); - root.setHeight(100); + root.setHeight(150); const root_child0 = Yoga.Node.create(config); root_child0.setPadding(Edge.Left, "10%"); root_child0.setPadding(Edge.Top, "10%"); root_child0.setPadding(Edge.Right, "10%"); root_child0.setPadding(Edge.Bottom, "10%"); - root_child0.setWidth("50%"); + root_child0.setWidth(50); + root_child0.setHeight(75); root_child0.setBoxSizing(BoxSizing.ContentBox); root.insertChild(root_child0, 0); root.calculateLayout(undefined, undefined, Direction.LTR); @@ -514,24 +515,24 @@ test('box_sizing_content_box_padding_only_percent', () => { expect(root.getComputedLeft()).toBe(0); expect(root.getComputedTop()).toBe(0); expect(root.getComputedWidth()).toBe(100); - expect(root.getComputedHeight()).toBe(100); + expect(root.getComputedHeight()).toBe(150); expect(root_child0.getComputedLeft()).toBe(0); expect(root_child0.getComputedTop()).toBe(0); expect(root_child0.getComputedWidth()).toBe(70); - expect(root_child0.getComputedHeight()).toBe(20); + expect(root_child0.getComputedHeight()).toBe(95); root.calculateLayout(undefined, undefined, Direction.RTL); expect(root.getComputedLeft()).toBe(0); expect(root.getComputedTop()).toBe(0); expect(root.getComputedWidth()).toBe(100); - expect(root.getComputedHeight()).toBe(100); + expect(root.getComputedHeight()).toBe(150); expect(root_child0.getComputedLeft()).toBe(30); expect(root_child0.getComputedTop()).toBe(0); expect(root_child0.getComputedWidth()).toBe(70); - expect(root_child0.getComputedHeight()).toBe(20); + expect(root_child0.getComputedHeight()).toBe(95); } finally { if (typeof root !== 'undefined') { root.freeRecursive(); @@ -582,38 +583,39 @@ test('box_sizing_border_box_padding_only_percent', () => { root = Yoga.Node.create(config); root.setPositionType(PositionType.Absolute); root.setWidth(100); - root.setHeight(100); + root.setHeight(150); const root_child0 = Yoga.Node.create(config); root_child0.setPadding(Edge.Left, "10%"); root_child0.setPadding(Edge.Top, "10%"); root_child0.setPadding(Edge.Right, "10%"); root_child0.setPadding(Edge.Bottom, "10%"); - root_child0.setWidth("50%"); + root_child0.setWidth(50); + root_child0.setHeight(75); root.insertChild(root_child0, 0); root.calculateLayout(undefined, undefined, Direction.LTR); expect(root.getComputedLeft()).toBe(0); expect(root.getComputedTop()).toBe(0); expect(root.getComputedWidth()).toBe(100); - expect(root.getComputedHeight()).toBe(100); + expect(root.getComputedHeight()).toBe(150); expect(root_child0.getComputedLeft()).toBe(0); expect(root_child0.getComputedTop()).toBe(0); expect(root_child0.getComputedWidth()).toBe(50); - expect(root_child0.getComputedHeight()).toBe(20); + expect(root_child0.getComputedHeight()).toBe(75); root.calculateLayout(undefined, undefined, Direction.RTL); expect(root.getComputedLeft()).toBe(0); expect(root.getComputedTop()).toBe(0); expect(root.getComputedWidth()).toBe(100); - expect(root.getComputedHeight()).toBe(100); + expect(root.getComputedHeight()).toBe(150); expect(root_child0.getComputedLeft()).toBe(50); expect(root_child0.getComputedTop()).toBe(0); expect(root_child0.getComputedWidth()).toBe(50); - expect(root_child0.getComputedHeight()).toBe(20); + expect(root_child0.getComputedHeight()).toBe(75); } finally { if (typeof root !== 'undefined') { root.freeRecursive(); diff --git a/tests/generated/YGBoxSizingTest.cpp b/tests/generated/YGBoxSizingTest.cpp index 69438984..e7ee6643 100644 --- a/tests/generated/YGBoxSizingTest.cpp +++ b/tests/generated/YGBoxSizingTest.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * clang-format off - * @generated SignedSource<<36f0f519320608e2c5c6eb6666be7efc>> + * @generated SignedSource<<24bf988fec7e7f72a8f46ba74df63399>> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGBoxSizingTest.html */ @@ -446,14 +446,15 @@ TEST(YogaTest, box_sizing_content_box_padding_only_percent) { YGNodeRef root = YGNodeNewWithConfig(config); YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); YGNodeStyleSetWidth(root, 100); - YGNodeStyleSetHeight(root, 100); + YGNodeStyleSetHeight(root, 150); YGNodeRef root_child0 = YGNodeNewWithConfig(config); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeLeft, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeTop, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeRight, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeBottom, 10); - YGNodeStyleSetWidthPercent(root_child0, 50); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 75); YGNodeStyleSetBoxSizing(root_child0, YGBoxSizingContentBox); YGNodeInsertChild(root, root_child0, 0); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); @@ -461,24 +462,24 @@ TEST(YogaTest, box_sizing_content_box_padding_only_percent) { ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); ASSERT_FLOAT_EQ(70, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + ASSERT_FLOAT_EQ(95, YGNodeLayoutGetHeight(root_child0)); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); ASSERT_FLOAT_EQ(70, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + ASSERT_FLOAT_EQ(95, YGNodeLayoutGetHeight(root_child0)); YGNodeFreeRecursive(root); @@ -521,38 +522,39 @@ TEST(YogaTest, box_sizing_border_box_padding_only_percent) { YGNodeRef root = YGNodeNewWithConfig(config); YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); YGNodeStyleSetWidth(root, 100); - YGNodeStyleSetHeight(root, 100); + YGNodeStyleSetHeight(root, 150); YGNodeRef root_child0 = YGNodeNewWithConfig(config); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeLeft, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeTop, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeRight, 10); YGNodeStyleSetPaddingPercent(root_child0, YGEdgeBottom, 10); - YGNodeStyleSetWidthPercent(root_child0, 50); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 75); YGNodeInsertChild(root, root_child0, 0); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0)); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); - ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0)); ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); - ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetHeight(root_child0)); YGNodeFreeRecursive(root); diff --git a/yoga/algorithm/AbsoluteLayout.cpp b/yoga/algorithm/AbsoluteLayout.cpp index d080844b..de4eef9d 100644 --- a/yoga/algorithm/AbsoluteLayout.cpp +++ b/yoga/algorithm/AbsoluteLayout.cpp @@ -326,7 +326,10 @@ void layoutAbsoluteChild( if (child->hasDefiniteLength(Dimension::Width, containingBlockWidth)) { childWidth = child ->getResolvedDimension( - direction, Dimension::Width, containingBlockWidth) + direction, + Dimension::Width, + containingBlockWidth, + containingBlockWidth) .unwrap() + marginRow; } else { @@ -362,7 +365,10 @@ void layoutAbsoluteChild( if (child->hasDefiniteLength(Dimension::Height, containingBlockHeight)) { childHeight = child ->getResolvedDimension( - direction, Dimension::Height, containingBlockHeight) + direction, + Dimension::Height, + containingBlockHeight, + containingBlockWidth) .unwrap() + marginColumn; } else { diff --git a/yoga/algorithm/BoundAxis.h b/yoga/algorithm/BoundAxis.h index 4342c0d5..d9ebc68c 100644 --- a/yoga/algorithm/BoundAxis.h +++ b/yoga/algorithm/BoundAxis.h @@ -32,20 +32,21 @@ inline FloatOptional boundAxisWithinMinAndMax( const Direction direction, const FlexDirection axis, const FloatOptional value, - const float axisSize) { + const float axisSize, + const float widthSize) { FloatOptional min; FloatOptional max; if (isColumn(axis)) { min = node->style().resolvedMinDimension( - direction, Dimension::Height, axisSize); + direction, Dimension::Height, axisSize, widthSize); max = node->style().resolvedMaxDimension( - direction, Dimension::Height, axisSize); + direction, Dimension::Height, axisSize, widthSize); } else if (isRow(axis)) { min = node->style().resolvedMinDimension( - direction, Dimension::Width, axisSize); + direction, Dimension::Width, axisSize, widthSize); max = node->style().resolvedMaxDimension( - direction, Dimension::Width, axisSize); + direction, Dimension::Width, axisSize, widthSize); } if (max >= FloatOptional{0} && value > max) { @@ -70,7 +71,7 @@ inline float boundAxis( const float widthSize) { return yoga::maxOrDefined( boundAxisWithinMinAndMax( - node, direction, axis, FloatOptional{value}, axisSize) + node, direction, axis, FloatOptional{value}, axisSize, widthSize) .unwrap(), paddingAndBorderForAxis(node, axis, direction, widthSize)); } diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index f78af2b4..3a98c923 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -44,8 +44,9 @@ static void constrainMaxSizeForMode( float ownerWidth, /*in_out*/ SizingMode* mode, /*in_out*/ float* size) { - const FloatOptional maxSize = node->style().resolvedMaxDimension( - direction, dimension(axis), ownerAxisSize) + + const FloatOptional maxSize = + node->style().resolvedMaxDimension( + direction, dimension(axis), ownerAxisSize, ownerWidth) + FloatOptional(node->style().computeMarginForAxis(axis, ownerWidth)); switch (*mode) { case SizingMode::StretchFit: @@ -87,8 +88,8 @@ static void computeFlexBasisForChild( SizingMode childWidthSizingMode; SizingMode childHeightSizingMode; - const FloatOptional resolvedFlexBasis = - child->resolveFlexBasis(direction, mainAxis, mainAxisOwnerSize); + const FloatOptional resolvedFlexBasis = child->resolveFlexBasis( + direction, mainAxis, mainAxisOwnerSize, ownerWidth); const bool isRowStyleDimDefined = child->hasDefiniteLength(Dimension::Width, ownerWidth); const bool isColumnStyleDimDefined = @@ -111,7 +112,8 @@ static void computeFlexBasisForChild( child, FlexDirection::Row, direction, ownerWidth)); child->setLayoutComputedFlexBasis(yoga::maxOrDefined( - child->getResolvedDimension(direction, Dimension::Width, ownerWidth), + child->getResolvedDimension( + direction, Dimension::Width, ownerWidth, ownerWidth), paddingAndBorder)); } else if (!isMainAxisRow && isColumnStyleDimDefined) { // The height is definite, so use that as the flex basis. @@ -119,7 +121,8 @@ static void computeFlexBasisForChild( FloatOptional(paddingAndBorderForAxis( child, FlexDirection::Column, direction, ownerWidth)); child->setLayoutComputedFlexBasis(yoga::maxOrDefined( - child->getResolvedDimension(direction, Dimension::Height, ownerHeight), + child->getResolvedDimension( + direction, Dimension::Height, ownerHeight, ownerWidth), paddingAndBorder)); } else { // Compute the flex basis and hypothetical main size (i.e. the clamped flex @@ -133,15 +136,18 @@ static void computeFlexBasisForChild( child->style().computeMarginForAxis(FlexDirection::Column, ownerWidth); if (isRowStyleDimDefined) { - childWidth = - child->getResolvedDimension(direction, Dimension::Width, ownerWidth) - .unwrap() + + childWidth = child + ->getResolvedDimension( + direction, Dimension::Width, ownerWidth, ownerWidth) + .unwrap() + marginRow; childWidthSizingMode = SizingMode::StretchFit; } if (isColumnStyleDimDefined) { childHeight = - child->getResolvedDimension(direction, Dimension::Height, ownerHeight) + child + ->getResolvedDimension( + direction, Dimension::Height, ownerHeight, ownerWidth) .unwrap() + marginColumn; childHeightSizingMode = SizingMode::StretchFit; @@ -476,7 +482,8 @@ static float calculateAvailableInnerDimension( const Dimension dimension, const float availableDim, const float paddingAndBorder, - const float ownerDim) { + const float ownerDim, + const float ownerWidth) { float availableInnerDim = availableDim - paddingAndBorder; // Max dimension overrides predefined dimension value; Min dimension in turn // overrides both of the above @@ -484,13 +491,15 @@ static float calculateAvailableInnerDimension( // We want to make sure our available height does not violate min and max // constraints const FloatOptional minDimensionOptional = - node->style().resolvedMinDimension(direction, dimension, ownerDim); + node->style().resolvedMinDimension( + direction, dimension, ownerDim, ownerWidth); const float minInnerDim = minDimensionOptional.isUndefined() ? 0.0f : minDimensionOptional.unwrap() - paddingAndBorder; const FloatOptional maxDimensionOptional = - node->style().resolvedMaxDimension(direction, dimension, ownerDim); + node->style().resolvedMaxDimension( + direction, dimension, ownerDim, ownerWidth); const float maxInnerDim = maxDimensionOptional.isUndefined() ? FLT_MAX @@ -594,6 +603,7 @@ static float distributeFreeSpaceSecondPass( const FlexDirection mainAxis, const FlexDirection crossAxis, const Direction direction, + const float ownerWidth, const float mainAxisOwnerSize, const float availableInnerMainDim, const float availableInnerCrossDim, @@ -618,7 +628,8 @@ static float distributeFreeSpaceSecondPass( direction, mainAxis, currentLineChild->getLayout().computedFlexBasis, - mainAxisOwnerSize) + mainAxisOwnerSize, + ownerWidth) .unwrap(); float updatedMainSize = childFlexBasis; @@ -713,11 +724,13 @@ static float distributeFreeSpaceSecondPass( ? SizingMode::MaxContent : SizingMode::FitContent; } else { - childCrossSize = - currentLineChild - ->getResolvedDimension( - direction, dimension(crossAxis), availableInnerCrossDim) - .unwrap() + + childCrossSize = currentLineChild + ->getResolvedDimension( + direction, + dimension(crossAxis), + availableInnerCrossDim, + availableInnerWidth) + .unwrap() + marginCross; const bool isLoosePercentageMeasurement = currentLineChild->getProcessedDimension(dimension(crossAxis)) @@ -808,6 +821,7 @@ static void distributeFreeSpaceFirstPass( FlexLine& flexLine, const Direction direction, const FlexDirection mainAxis, + const float ownerWidth, const float mainAxisOwnerSize, const float availableInnerMainDim, const float availableInnerWidth) { @@ -823,7 +837,8 @@ static void distributeFreeSpaceFirstPass( direction, mainAxis, currentLineChild->getLayout().computedFlexBasis, - mainAxisOwnerSize) + mainAxisOwnerSize, + ownerWidth) .unwrap(); if (flexLine.layout.remainingFreeSpace < 0) { @@ -917,6 +932,7 @@ static void resolveFlexibleLength( const FlexDirection mainAxis, const FlexDirection crossAxis, const Direction direction, + const float ownerWidth, const float mainAxisOwnerSize, const float availableInnerMainDim, const float availableInnerCrossDim, @@ -934,6 +950,7 @@ static void resolveFlexibleLength( flexLine, direction, mainAxis, + ownerWidth, mainAxisOwnerSize, availableInnerMainDim, availableInnerWidth); @@ -945,6 +962,7 @@ static void resolveFlexibleLength( mainAxis, crossAxis, direction, + ownerWidth, mainAxisOwnerSize, availableInnerMainDim, availableInnerCrossDim, @@ -993,7 +1011,7 @@ static void justifyMainAxis( if (style.minDimension(dimension(mainAxis)).isDefined() && style .resolvedMinDimension( - direction, dimension(mainAxis), mainAxisOwnerSize) + direction, dimension(mainAxis), mainAxisOwnerSize, ownerWidth) .isDefined()) { // This condition makes sure that if the size of main dimension(after // considering child nodes main dim, leading and trailing padding etc) @@ -1005,7 +1023,7 @@ static void justifyMainAxis( const float minAvailableMainDim = style .resolvedMinDimension( - direction, dimension(mainAxis), mainAxisOwnerSize) + direction, dimension(mainAxis), mainAxisOwnerSize, ownerWidth) .unwrap() - leadingPaddingAndBorderMain - trailingPaddingAndBorderMain; const float occupiedSpaceByChildNodes = @@ -1403,6 +1421,7 @@ static void calculateLayoutImpl( Dimension::Width, availableWidth - marginAxisRow, paddingAndBorderAxisRow, + ownerWidth, ownerWidth); float availableInnerHeight = calculateAvailableInnerDimension( node, @@ -1410,7 +1429,8 @@ static void calculateLayoutImpl( Dimension::Height, availableHeight - marginAxisColumn, paddingAndBorderAxisColumn, - ownerHeight); + ownerHeight, + ownerWidth); float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; @@ -1470,6 +1490,7 @@ static void calculateLayoutImpl( auto flexLine = calculateFlexLine( node, ownerDirection, + ownerWidth, mainAxisOwnerSize, availableInnerWidth, availableInnerMainDim, @@ -1494,19 +1515,27 @@ static void calculateLayoutImpl( if (sizingModeMainDim != SizingMode::StretchFit) { const auto& style = node->style(); const float minInnerWidth = - style.resolvedMinDimension(direction, Dimension::Width, ownerWidth) + style + .resolvedMinDimension( + direction, Dimension::Width, ownerWidth, ownerWidth) .unwrap() - paddingAndBorderAxisRow; const float maxInnerWidth = - style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth) + style + .resolvedMaxDimension( + direction, Dimension::Width, ownerWidth, ownerWidth) .unwrap() - paddingAndBorderAxisRow; const float minInnerHeight = - style.resolvedMinDimension(direction, Dimension::Height, ownerHeight) + style + .resolvedMinDimension( + direction, Dimension::Height, ownerHeight, ownerWidth) .unwrap() - paddingAndBorderAxisColumn; const float maxInnerHeight = - style.resolvedMaxDimension(direction, Dimension::Height, ownerHeight) + style + .resolvedMaxDimension( + direction, Dimension::Height, ownerHeight, ownerWidth) .unwrap() - paddingAndBorderAxisColumn; @@ -1559,6 +1588,7 @@ static void calculateLayoutImpl( mainAxis, crossAxis, direction, + ownerWidth, mainAxisOwnerSize, availableInnerMainDim, availableInnerCrossDim, @@ -1802,7 +1832,10 @@ static void calculateLayoutImpl( ? availableInnerCrossDim + paddingAndBorderAxisCross : node->hasDefiniteLength(dimension(crossAxis), crossAxisOwnerSize) ? node->getResolvedDimension( - direction, dimension(crossAxis), crossAxisOwnerSize) + direction, + dimension(crossAxis), + crossAxisOwnerSize, + ownerWidth) .unwrap() : totalLineCrossDim + paddingAndBorderAxisCross; @@ -2058,7 +2091,8 @@ static void calculateLayoutImpl( direction, mainAxis, FloatOptional{maxLineMainDim}, - mainAxisOwnerSize) + mainAxisOwnerSize, + ownerWidth) .unwrap()), paddingAndBorderAxisMain), dimension(mainAxis)); @@ -2092,7 +2126,8 @@ static void calculateLayoutImpl( crossAxis, FloatOptional{ totalLineCrossDim + paddingAndBorderAxisCross}, - crossAxisOwnerSize) + crossAxisOwnerSize, + ownerWidth) .unwrap()), paddingAndBorderAxisCross), dimension(crossAxis)); @@ -2384,13 +2419,20 @@ void calculateLayout( if (node->hasDefiniteLength(Dimension::Width, ownerWidth)) { width = (node->getResolvedDimension( - direction, dimension(FlexDirection::Row), ownerWidth) + direction, + dimension(FlexDirection::Row), + ownerWidth, + ownerWidth) .unwrap() + node->style().computeMarginForAxis(FlexDirection::Row, ownerWidth)); widthSizingMode = SizingMode::StretchFit; - } else if (style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth) + } else if (style + .resolvedMaxDimension( + direction, Dimension::Width, ownerWidth, ownerWidth) .isDefined()) { - width = style.resolvedMaxDimension(direction, Dimension::Width, ownerWidth) + width = style + .resolvedMaxDimension( + direction, Dimension::Width, ownerWidth, ownerWidth) .unwrap(); widthSizingMode = SizingMode::FitContent; } else { @@ -2404,17 +2446,21 @@ void calculateLayout( if (node->hasDefiniteLength(Dimension::Height, ownerHeight)) { height = (node->getResolvedDimension( - direction, dimension(FlexDirection::Column), ownerHeight) + direction, + dimension(FlexDirection::Column), + ownerHeight, + ownerWidth) .unwrap() + node->style().computeMarginForAxis(FlexDirection::Column, ownerWidth)); heightSizingMode = SizingMode::StretchFit; } else if (style .resolvedMaxDimension( - direction, Dimension::Height, ownerHeight) + direction, Dimension::Height, ownerHeight, ownerWidth) .isDefined()) { - height = - style.resolvedMaxDimension(direction, Dimension::Height, ownerHeight) - .unwrap(); + height = style + .resolvedMaxDimension( + direction, Dimension::Height, ownerHeight, ownerWidth) + .unwrap(); heightSizingMode = SizingMode::FitContent; } else { height = ownerHeight; diff --git a/yoga/algorithm/FlexLine.cpp b/yoga/algorithm/FlexLine.cpp index 58a261a4..1ad47fa5 100644 --- a/yoga/algorithm/FlexLine.cpp +++ b/yoga/algorithm/FlexLine.cpp @@ -16,6 +16,7 @@ namespace facebook::yoga { FlexLine calculateFlexLine( yoga::Node* const node, const Direction ownerDirection, + const float ownerWidth, const float mainAxisownerSize, const float availableInnerWidth, const float availableInnerMainDim, @@ -71,7 +72,8 @@ FlexLine calculateFlexLine( direction, mainAxis, child->getLayout().computedFlexBasis, - mainAxisownerSize) + mainAxisownerSize, + ownerWidth) .unwrap(); // If this is a multi-line flow and this item pushes us over the available diff --git a/yoga/algorithm/FlexLine.h b/yoga/algorithm/FlexLine.h index 3287cd6c..14141794 100644 --- a/yoga/algorithm/FlexLine.h +++ b/yoga/algorithm/FlexLine.h @@ -68,6 +68,7 @@ struct FlexLine { FlexLine calculateFlexLine( yoga::Node* node, Direction ownerDirection, + float ownerWidth, float mainAxisownerSize, float availableInnerWidth, float availableInnerMainDim, diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index 1491d295..3189f3bb 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -296,16 +296,16 @@ Style::Length Node::processFlexBasis() const { FloatOptional Node::resolveFlexBasis( Direction direction, FlexDirection flexDirection, - float referenceLength) const { + float referenceLength, + float ownerWidth) const { FloatOptional value = processFlexBasis().resolve(referenceLength); if (style_.boxSizing() == BoxSizing::BorderBox) { return value; } Dimension dim = dimension(flexDirection); - FloatOptional dimensionPaddingAndBorder = - FloatOptional{style_.computePaddingAndBorderForDimension( - direction, dim, referenceLength)}; + FloatOptional dimensionPaddingAndBorder = FloatOptional{ + style_.computePaddingAndBorderForDimension(direction, dim, ownerWidth)}; return value + (dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder diff --git a/yoga/node/Node.h b/yoga/node/Node.h index b15a0160..5f38ac13 100644 --- a/yoga/node/Node.h +++ b/yoga/node/Node.h @@ -159,7 +159,8 @@ class YG_EXPORT Node : public ::YGNode { FloatOptional getResolvedDimension( Direction direction, Dimension dimension, - float referenceLength) const { + float referenceLength, + float ownerWidth) const { FloatOptional value = getProcessedDimension(dimension).resolve(referenceLength); if (style_.boxSizing() == BoxSizing::BorderBox) { @@ -168,7 +169,7 @@ class YG_EXPORT Node : public ::YGNode { FloatOptional dimensionPaddingAndBorder = FloatOptional{style_.computePaddingAndBorderForDimension( - direction, dimension, referenceLength)}; + direction, dimension, ownerWidth)}; return value + (dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder @@ -251,7 +252,8 @@ class YG_EXPORT Node : public ::YGNode { FloatOptional resolveFlexBasis( Direction direction, FlexDirection flexDirection, - float referenceLength) const; + float referenceLength, + float ownerWidth) const; void processDimensions(); Direction resolveDirection(Direction ownerDirection); void clearChildren(); diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 8c96dd50..73203e6c 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -192,14 +192,15 @@ class YG_EXPORT Style { FloatOptional resolvedMinDimension( Direction direction, Dimension axis, - float referenceLength) const { + float referenceLength, + float ownerWidth) const { FloatOptional value = minDimension(axis).resolve(referenceLength); if (boxSizing() == BoxSizing::BorderBox) { return value; } FloatOptional dimensionPaddingAndBorder = FloatOptional{ - computePaddingAndBorderForDimension(direction, axis, referenceLength)}; + computePaddingAndBorderForDimension(direction, axis, ownerWidth)}; return value + (dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder @@ -216,14 +217,15 @@ class YG_EXPORT Style { FloatOptional resolvedMaxDimension( Direction direction, Dimension axis, - float referenceLength) const { + float referenceLength, + float ownerWidth) const { FloatOptional value = maxDimension(axis).resolve(referenceLength); if (boxSizing() == BoxSizing::BorderBox) { return value; } FloatOptional dimensionPaddingAndBorder = FloatOptional{ - computePaddingAndBorderForDimension(direction, axis, referenceLength)}; + computePaddingAndBorderForDimension(direction, axis, ownerWidth)}; return value + (dimensionPaddingAndBorder.isDefined() ? dimensionPaddingAndBorder