From 8166c81135cdccc6f1e0cc15f3c2f31b9053880e Mon Sep 17 00:00:00 2001 From: Nick Gerleman Date: Tue, 15 Nov 2022 19:51:48 -0800 Subject: [PATCH] Incorporate gap space into main axis overflow flag (#1173) Summary: Pull Request resolved: https://github.com/facebook/yoga/pull/1173 In https://github.com/facebook/react-native/issues/35351 we see incorrect child item height when the flex-wrap is enabled, the cross-axis is to be stretched, and main-axis overflow is caused by gap. In YGDistributeFreeSpaceSecondPass, if we do not have overflow (determined by flexBasisOverflows), we have stretch cross-alignment, and we reason that nothing can add to main axis dimensions, we know we're a single line and want to take full cross dimensions. and can set YGMeasureModeExactly which uses parent dimensions. Guessing an optimization? If we do have overflow, then we set YGMeasureModeAtMost to find minimum possible cross-axis dimensions instead. `flexBasisOverflows` incorporates both computed flex basis, and margin, so it is more generally a flag for whether we will wrap. So we should incorporate gap spacing into it. E.g. it is also used for whether we should the match main axis parent dimension of the overall container. This change does just that, and renames the flag to `mainAxisOverflows`. We will want to cherry-pick the fix for this into RN 0.71 since we have not yet introduced the community to the incorrect behavior, and we expect a lot of usage of flex-gap. Changelog: [General][Fixed] - Fix incorrect height when gap causes main axis to overflow and cross-axis is stretched Reviewed By: yungsters Differential Revision: D41311424 fbshipit-source-id: bd0c3b5aac478a56878703b6da84fc3993cc14da --- csharp/tests/Facebook.Yoga/YGGapTest.cs | 104 +++++++++++++++++++ gentest/fixtures/YGGapTest.html | 10 +- java/tests/com/facebook/yoga/YGGapTest.java | 103 +++++++++++++++++++ javascript/tests/Facebook.Yoga/YGGapTest.js | 107 ++++++++++++++++++++ tests/YGGapTest.cpp | 104 +++++++++++++++++++ yoga/Yoga.cpp | 29 ++++-- 6 files changed, 445 insertions(+), 12 deletions(-) diff --git a/csharp/tests/Facebook.Yoga/YGGapTest.cs b/csharp/tests/Facebook.Yoga/YGGapTest.cs index 6504beb7..2923aa8d 100644 --- a/csharp/tests/Facebook.Yoga/YGGapTest.cs +++ b/csharp/tests/Facebook.Yoga/YGGapTest.cs @@ -1412,6 +1412,110 @@ namespace Facebook.Yoga Assert.AreEqual(20f, root_child5.LayoutHeight); } + [Test] + public void Test_column_gap_wrap_align_stretch() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.FlexDirection = YogaFlexDirection.Row; + root.AlignContent = YogaAlign.Stretch; + root.Wrap = YogaWrap.Wrap; + root.Width = 300; + root.Height = 300; + root.ColumnGap = 5; + + YogaNode root_child0 = new YogaNode(config); + root_child0.FlexGrow = 1; + root_child0.MinWidth = 60; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(config); + root_child1.FlexGrow = 1; + root_child1.MinWidth = 60; + root.Insert(1, root_child1); + + YogaNode root_child2 = new YogaNode(config); + root_child2.FlexGrow = 1; + root_child2.MinWidth = 60; + root.Insert(2, root_child2); + + YogaNode root_child3 = new YogaNode(config); + root_child3.FlexGrow = 1; + root_child3.MinWidth = 60; + root.Insert(3, root_child3); + + YogaNode root_child4 = new YogaNode(config); + root_child4.FlexGrow = 1; + root_child4.MinWidth = 60; + root.Insert(4, root_child4); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(300f, root.LayoutWidth); + Assert.AreEqual(300f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(71f, root_child0.LayoutWidth); + Assert.AreEqual(150f, root_child0.LayoutHeight); + + Assert.AreEqual(76f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(72f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + Assert.AreEqual(153f, root_child2.LayoutX); + Assert.AreEqual(0f, root_child2.LayoutY); + Assert.AreEqual(71f, root_child2.LayoutWidth); + Assert.AreEqual(150f, root_child2.LayoutHeight); + + Assert.AreEqual(229f, root_child3.LayoutX); + Assert.AreEqual(0f, root_child3.LayoutY); + Assert.AreEqual(71f, root_child3.LayoutWidth); + Assert.AreEqual(150f, root_child3.LayoutHeight); + + Assert.AreEqual(0f, root_child4.LayoutX); + Assert.AreEqual(150f, root_child4.LayoutY); + Assert.AreEqual(300f, root_child4.LayoutWidth); + Assert.AreEqual(150f, root_child4.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(300f, root.LayoutWidth); + Assert.AreEqual(300f, root.LayoutHeight); + + Assert.AreEqual(229f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(71f, root_child0.LayoutWidth); + Assert.AreEqual(150f, root_child0.LayoutHeight); + + Assert.AreEqual(153f, root_child1.LayoutX); + Assert.AreEqual(0f, root_child1.LayoutY); + Assert.AreEqual(71f, root_child1.LayoutWidth); + Assert.AreEqual(150f, root_child1.LayoutHeight); + + Assert.AreEqual(76f, root_child2.LayoutX); + Assert.AreEqual(0f, root_child2.LayoutY); + Assert.AreEqual(72f, root_child2.LayoutWidth); + Assert.AreEqual(150f, root_child2.LayoutHeight); + + Assert.AreEqual(0f, root_child3.LayoutX); + Assert.AreEqual(0f, root_child3.LayoutY); + Assert.AreEqual(71f, root_child3.LayoutWidth); + Assert.AreEqual(150f, root_child3.LayoutHeight); + + Assert.AreEqual(0f, root_child4.LayoutX); + Assert.AreEqual(150f, root_child4.LayoutY); + Assert.AreEqual(300f, root_child4.LayoutWidth); + Assert.AreEqual(150f, root_child4.LayoutHeight); + } + [Test] public void Test_row_gap_align_items_stretch() { diff --git a/gentest/fixtures/YGGapTest.html b/gentest/fixtures/YGGapTest.html index 70e3affe..e3f5bcb1 100644 --- a/gentest/fixtures/YGGapTest.html +++ b/gentest/fixtures/YGGapTest.html @@ -109,6 +109,14 @@
+
+
+
+
+
+
+
+
@@ -118,7 +126,6 @@
-
@@ -127,4 +134,3 @@
- diff --git a/java/tests/com/facebook/yoga/YGGapTest.java b/java/tests/com/facebook/yoga/YGGapTest.java index f4f7898c..826ab82a 100644 --- a/java/tests/com/facebook/yoga/YGGapTest.java +++ b/java/tests/com/facebook/yoga/YGGapTest.java @@ -1406,6 +1406,109 @@ public class YGGapTest { assertEquals(20f, root_child5.getLayoutHeight(), 0.0f); } + @Test + public void test_column_gap_wrap_align_stretch() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setAlignContent(YogaAlign.STRETCH); + root.setWrap(YogaWrap.WRAP); + root.setWidth(300f); + root.setHeight(300f); + root.setGap(YogaGutter.COLUMN, 5f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexGrow(1f); + root_child0.setMinWidth(60f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setFlexGrow(1f); + root_child1.setMinWidth(60f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setFlexGrow(1f); + root_child2.setMinWidth(60f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setFlexGrow(1f); + root_child3.setMinWidth(60f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setFlexGrow(1f); + root_child4.setMinWidth(60f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(71f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(76f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(72f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(153f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(71f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(229f, root_child3.getLayoutX(), 0.0f); + assertEquals(0f, root_child3.getLayoutY(), 0.0f); + assertEquals(71f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child4.getLayoutX(), 0.0f); + assertEquals(150f, root_child4.getLayoutY(), 0.0f); + assertEquals(300f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(229f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(71f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(153f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(71f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(76f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(72f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child3.getLayoutX(), 0.0f); + assertEquals(0f, root_child3.getLayoutY(), 0.0f); + assertEquals(71f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child4.getLayoutX(), 0.0f); + assertEquals(150f, root_child4.getLayoutY(), 0.0f); + assertEquals(300f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(150f, root_child4.getLayoutHeight(), 0.0f); + } + @Test public void test_row_gap_align_items_stretch() { YogaConfig config = YogaConfigFactory.create(); diff --git a/javascript/tests/Facebook.Yoga/YGGapTest.js b/javascript/tests/Facebook.Yoga/YGGapTest.js index dfe77fd1..31516eb7 100644 --- a/javascript/tests/Facebook.Yoga/YGGapTest.js +++ b/javascript/tests/Facebook.Yoga/YGGapTest.js @@ -1451,6 +1451,113 @@ it("column_gap_wrap_align_space_around", function () { config.free(); } }); +it("column_gap_wrap_align_stretch", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setAlignContent(Yoga.ALIGN_STRETCH); + root.setFlexWrap(Yoga.WRAP_WRAP); + root.setWidth(300); + root.setHeight(300); + root.setGap(Yoga.GUTTER_COLUMN, 5); + + var root_child0 = Yoga.Node.create(config); + root_child0.setFlexGrow(1); + root_child0.setMinWidth(60); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setFlexGrow(1); + root_child1.setMinWidth(60); + root.insertChild(root_child1, 1); + + var root_child2 = Yoga.Node.create(config); + root_child2.setFlexGrow(1); + root_child2.setMinWidth(60); + root.insertChild(root_child2, 2); + + var root_child3 = Yoga.Node.create(config); + root_child3.setFlexGrow(1); + root_child3.setMinWidth(60); + root.insertChild(root_child3, 3); + + var root_child4 = Yoga.Node.create(config); + root_child4.setFlexGrow(1); + root_child4.setMinWidth(60); + root.insertChild(root_child4, 4); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(300 === root.getComputedWidth(), "300 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(300 === root.getComputedHeight(), "300 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(71 === root_child0.getComputedWidth(), "71 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(150 === root_child0.getComputedHeight(), "150 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(76 === root_child1.getComputedLeft(), "76 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(72 === root_child1.getComputedWidth(), "72 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(150 === root_child1.getComputedHeight(), "150 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + console.assert(153 === root_child2.getComputedLeft(), "153 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(0 === root_child2.getComputedTop(), "0 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(71 === root_child2.getComputedWidth(), "71 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(150 === root_child2.getComputedHeight(), "150 === root_child2.getComputedHeight() (" + root_child2.getComputedHeight() + ")"); + + console.assert(229 === root_child3.getComputedLeft(), "229 === root_child3.getComputedLeft() (" + root_child3.getComputedLeft() + ")"); + console.assert(0 === root_child3.getComputedTop(), "0 === root_child3.getComputedTop() (" + root_child3.getComputedTop() + ")"); + console.assert(71 === root_child3.getComputedWidth(), "71 === root_child3.getComputedWidth() (" + root_child3.getComputedWidth() + ")"); + console.assert(150 === root_child3.getComputedHeight(), "150 === root_child3.getComputedHeight() (" + root_child3.getComputedHeight() + ")"); + + console.assert(0 === root_child4.getComputedLeft(), "0 === root_child4.getComputedLeft() (" + root_child4.getComputedLeft() + ")"); + console.assert(150 === root_child4.getComputedTop(), "150 === root_child4.getComputedTop() (" + root_child4.getComputedTop() + ")"); + console.assert(300 === root_child4.getComputedWidth(), "300 === root_child4.getComputedWidth() (" + root_child4.getComputedWidth() + ")"); + console.assert(150 === root_child4.getComputedHeight(), "150 === root_child4.getComputedHeight() (" + root_child4.getComputedHeight() + ")"); + + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); + + console.assert(0 === root.getComputedLeft(), "0 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); + console.assert(0 === root.getComputedTop(), "0 === root.getComputedTop() (" + root.getComputedTop() + ")"); + console.assert(300 === root.getComputedWidth(), "300 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(300 === root.getComputedHeight(), "300 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(229 === root_child0.getComputedLeft(), "229 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(71 === root_child0.getComputedWidth(), "71 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(150 === root_child0.getComputedHeight(), "150 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(153 === root_child1.getComputedLeft(), "153 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(0 === root_child1.getComputedTop(), "0 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(71 === root_child1.getComputedWidth(), "71 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(150 === root_child1.getComputedHeight(), "150 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + console.assert(76 === root_child2.getComputedLeft(), "76 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(0 === root_child2.getComputedTop(), "0 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(72 === root_child2.getComputedWidth(), "72 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(150 === root_child2.getComputedHeight(), "150 === root_child2.getComputedHeight() (" + root_child2.getComputedHeight() + ")"); + + console.assert(0 === root_child3.getComputedLeft(), "0 === root_child3.getComputedLeft() (" + root_child3.getComputedLeft() + ")"); + console.assert(0 === root_child3.getComputedTop(), "0 === root_child3.getComputedTop() (" + root_child3.getComputedTop() + ")"); + console.assert(71 === root_child3.getComputedWidth(), "71 === root_child3.getComputedWidth() (" + root_child3.getComputedWidth() + ")"); + console.assert(150 === root_child3.getComputedHeight(), "150 === root_child3.getComputedHeight() (" + root_child3.getComputedHeight() + ")"); + + console.assert(0 === root_child4.getComputedLeft(), "0 === root_child4.getComputedLeft() (" + root_child4.getComputedLeft() + ")"); + console.assert(150 === root_child4.getComputedTop(), "150 === root_child4.getComputedTop() (" + root_child4.getComputedTop() + ")"); + console.assert(300 === root_child4.getComputedWidth(), "300 === root_child4.getComputedWidth() (" + root_child4.getComputedWidth() + ")"); + console.assert(150 === root_child4.getComputedHeight(), "150 === root_child4.getComputedHeight() (" + root_child4.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); it("row_gap_align_items_stretch", function () { var config = Yoga.Config.create(); diff --git a/tests/YGGapTest.cpp b/tests/YGGapTest.cpp index 34dc6852..4bdc545e 100644 --- a/tests/YGGapTest.cpp +++ b/tests/YGGapTest.cpp @@ -1408,6 +1408,110 @@ TEST(YogaTest, column_gap_wrap_align_space_around) { YGConfigFree(config); } +TEST(YogaTest, column_gap_wrap_align_stretch) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetAlignContent(root, YGAlignStretch); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 300); + YGNodeStyleSetGap(root, YGGutterColumn, 5); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetMinWidth(root_child0, 60); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetMinWidth(root_child1, 60); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child2, 1); + YGNodeStyleSetMinWidth(root_child2, 60); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child3, 1); + YGNodeStyleSetMinWidth(root_child3, 60); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child4, 1); + YGNodeStyleSetMinWidth(root_child4, 60); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(76, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(153, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(229, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(229, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(153, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(76, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(72, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(71, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, row_gap_align_items_stretch) { const YGConfigRef config = YGConfigNew(); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index a5c70b47..88c77ab8 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -2079,7 +2079,7 @@ static float YGDistributeFreeSpaceSecondPass( const float availableInnerCrossDim, const float availableInnerWidth, const float availableInnerHeight, - const bool flexBasisOverflows, + const bool mainAxisOverflows, const YGMeasureMode measureModeCrossDim, const bool performLayout, const YGConfigRef config, @@ -2175,7 +2175,7 @@ static float YGDistributeFreeSpaceSecondPass( !YGNodeIsStyleDimDefined( currentRelativeChild, crossAxis, availableInnerCrossDim) && measureModeCrossDim == YGMeasureModeExactly && - !(isNodeFlexWrap && flexBasisOverflows) && + !(isNodeFlexWrap && mainAxisOverflows) && YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch && currentRelativeChild->marginLeadingValue(crossAxis).unit != YGUnitAuto && @@ -2383,7 +2383,7 @@ static void YGResolveFlexibleLength( const float availableInnerCrossDim, const float availableInnerWidth, const float availableInnerHeight, - const bool flexBasisOverflows, + const bool mainAxisOverflows, const YGMeasureMode measureModeCrossDim, const bool performLayout, const YGConfigRef config, @@ -2411,7 +2411,7 @@ static void YGResolveFlexibleLength( availableInnerCrossDim, availableInnerWidth, availableInnerHeight, - flexBasisOverflows, + mainAxisOverflows, measureModeCrossDim, performLayout, config, @@ -2884,7 +2884,9 @@ static void YGNodelayoutImpl( // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM - float totalOuterFlexBasis = YGNodeComputeFlexBasisForChildren( + // Computed basis + margins + gap + float totalMainDim = 0; + totalMainDim += YGNodeComputeFlexBasisForChildren( node, availableInnerWidth, availableInnerHeight, @@ -2899,10 +2901,17 @@ static void YGNodelayoutImpl( depth, generationCount); - const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined - ? false - : totalOuterFlexBasis > availableInnerMainDim; - if (isNodeFlexWrap && flexBasisOverflows && + if (childCount > 1) { + totalMainDim += + node->getGapForAxis(mainAxis, availableInnerCrossDim).unwrap() * + (childCount - 1); + } + + const bool mainAxisOverflows = + (measureModeMainDim != YGMeasureModeUndefined) && + totalMainDim > availableInnerMainDim; + + if (isNodeFlexWrap && mainAxisOverflows && measureModeMainDim == YGMeasureModeAtMost) { measureModeMainDim = YGMeasureModeExactly; } @@ -3025,7 +3034,7 @@ static void YGNodelayoutImpl( availableInnerCrossDim, availableInnerWidth, availableInnerHeight, - flexBasisOverflows, + mainAxisOverflows, measureModeCrossDim, performLayout, config,