From a20bde8444474e7a34352a78073de23c26e08fc5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Lukas=20W=C3=B6hrl?= Date: Thu, 1 Jun 2017 05:30:17 -0700 Subject: [PATCH] Fix absolute position if wrap-reverse and align-items: flex-end Summary: This is a fix on top of 56b10fc. It takes the case into account were you have `wrap-reverse` and `align-items: flex-end` set. Closes https://github.com/facebook/yoga/pull/568 Differential Revision: D5155521 Pulled By: emilsjolander fbshipit-source-id: 7e5fcfa2fbb48b6c6279da46cc648a071ff2b079 --- .../Facebook.Yoga/YGAbsolutePositionTest.cs | 87 +++++++++++++++++ gentest/fixtures/YGAbsolutePositionTest.html | 8 ++ .../facebook/yoga/YGAbsolutePositionTest.java | 85 +++++++++++++++++ .../Facebook.Yoga/YGAbsolutePositionTest.js | 93 +++++++++++++++++++ tests/YGAbsolutePositionTest.cpp | 87 +++++++++++++++++ yoga/Yoga.c | 2 +- 6 files changed, 361 insertions(+), 1 deletion(-) diff --git a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs index dd4a908d..08a50497 100644 --- a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs @@ -950,5 +950,92 @@ namespace Facebook.Yoga Assert.AreEqual(20f, root_child0.LayoutHeight); } + [Test] + public void Test_absolute_layout_in_wrap_reverse_column_container_flex_end() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.Wrap = YogaWrap.WrapReverse; + root.Width = 100; + root.Height = 100; + + YogaNode root_child0 = new YogaNode(config); + root_child0.AlignSelf = YogaAlign.FlexEnd; + root_child0.PositionType = YogaPositionType.Absolute; + root_child0.Width = 20; + root_child0.Height = 20; + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(20f, root_child0.LayoutWidth); + Assert.AreEqual(20f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(80f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(20f, root_child0.LayoutWidth); + Assert.AreEqual(20f, root_child0.LayoutHeight); + } + + [Test] + public void Test_absolute_layout_in_wrap_reverse_row_container_flex_end() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.FlexDirection = YogaFlexDirection.Row; + root.Wrap = YogaWrap.WrapReverse; + root.Width = 100; + root.Height = 100; + + YogaNode root_child0 = new YogaNode(config); + root_child0.AlignSelf = YogaAlign.FlexEnd; + root_child0.PositionType = YogaPositionType.Absolute; + root_child0.Width = 20; + root_child0.Height = 20; + root.Insert(0, root_child0); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(20f, root_child0.LayoutWidth); + Assert.AreEqual(20f, root_child0.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(100f, root.LayoutHeight); + + Assert.AreEqual(80f, root_child0.LayoutX); + Assert.AreEqual(0f, root_child0.LayoutY); + Assert.AreEqual(20f, root_child0.LayoutWidth); + Assert.AreEqual(20f, root_child0.LayoutHeight); + } + } } diff --git a/gentest/fixtures/YGAbsolutePositionTest.html b/gentest/fixtures/YGAbsolutePositionTest.html index b2b1563d..39f8e980 100644 --- a/gentest/fixtures/YGAbsolutePositionTest.html +++ b/gentest/fixtures/YGAbsolutePositionTest.html @@ -80,3 +80,11 @@
+
+
+
+ +
+
+
+ diff --git a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java index ea73510e..9ff2bc5e 100644 --- a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java +++ b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java @@ -930,4 +930,89 @@ public class YGAbsolutePositionTest { assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); } + @Test + public void test_absolute_layout_in_wrap_reverse_column_container_flex_end() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = new YogaNode(config); + root.setWrap(YogaWrap.WRAP_REVERSE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(config); + root_child0.setAlignSelf(YogaAlign.FLEX_END); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setWidth(20f); + root_child0.setHeight(20f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + 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(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(20f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.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(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(20f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_absolute_layout_in_wrap_reverse_row_container_flex_end() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = new YogaNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWrap(YogaWrap.WRAP_REVERSE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = new YogaNode(config); + root_child0.setAlignSelf(YogaAlign.FLEX_END); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setWidth(20f); + root_child0.setHeight(20f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + 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(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(20f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.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(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(20f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + } + } diff --git a/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js b/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js index 3da74e9c..6f3ef8a4 100644 --- a/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js +++ b/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js @@ -1001,3 +1001,96 @@ it("absolute_layout_in_wrap_reverse_row_container", function () { config.free(); } }); +it("absolute_layout_in_wrap_reverse_column_container_flex_end", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexWrap(Yoga.WRAP_WRAP_REVERSE); + root.setWidth(100); + root.setHeight(100); + + var root_child0 = Yoga.Node.create(config); + root_child0.setAlignSelf(Yoga.ALIGN_FLEX_END); + root_child0.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child0.setWidth(20); + root_child0.setHeight(20); + root.insertChild(root_child0, 0); + 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(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(100 === root.getComputedHeight(), "100 === 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(20 === root_child0.getComputedWidth(), "20 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(20 === root_child0.getComputedHeight(), "20 === root_child0.getComputedHeight() (" + root_child0.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(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(100 === root.getComputedHeight(), "100 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(80 === root_child0.getComputedLeft(), "80 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(20 === root_child0.getComputedWidth(), "20 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(20 === root_child0.getComputedHeight(), "20 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); +it("absolute_layout_in_wrap_reverse_row_container_flex_end", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setFlexDirection(Yoga.FLEX_DIRECTION_ROW); + root.setFlexWrap(Yoga.WRAP_WRAP_REVERSE); + root.setWidth(100); + root.setHeight(100); + + var root_child0 = Yoga.Node.create(config); + root_child0.setAlignSelf(Yoga.ALIGN_FLEX_END); + root_child0.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child0.setWidth(20); + root_child0.setHeight(20); + root.insertChild(root_child0, 0); + 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(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(100 === root.getComputedHeight(), "100 === 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(20 === root_child0.getComputedWidth(), "20 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(20 === root_child0.getComputedHeight(), "20 === root_child0.getComputedHeight() (" + root_child0.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(100 === root.getComputedWidth(), "100 === root.getComputedWidth() (" + root.getComputedWidth() + ")"); + console.assert(100 === root.getComputedHeight(), "100 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(80 === root_child0.getComputedLeft(), "80 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(0 === root_child0.getComputedTop(), "0 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(20 === root_child0.getComputedWidth(), "20 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(20 === root_child0.getComputedHeight(), "20 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); diff --git a/tests/YGAbsolutePositionTest.cpp b/tests/YGAbsolutePositionTest.cpp index 96a6db89..14159d08 100644 --- a/tests/YGAbsolutePositionTest.cpp +++ b/tests/YGAbsolutePositionTest.cpp @@ -944,3 +944,90 @@ TEST(YogaTest, absolute_layout_in_wrap_reverse_row_container) { YGConfigFree(config); } + +TEST(YogaTest, absolute_layout_in_wrap_reverse_column_container_flex_end) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root_child0, 20); + YGNodeStyleSetHeight(root_child0, 20); + 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(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, 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(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, absolute_layout_in_wrap_reverse_row_container_flex_end) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root, YGWrapWrapReverse); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetAlignSelf(root_child0, YGAlignFlexEnd); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root_child0, 20); + YGNodeStyleSetHeight(root_child0, 20); + 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(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, 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(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/Yoga.c b/yoga/Yoga.c index eb2e2137..5ed9e1af 100644 --- a/yoga/Yoga.c +++ b/yoga/Yoga.c @@ -1714,7 +1714,7 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->layout.measuredDimensions[dim[crossAxis]]) / 2.0f; } else if (!YGNodeIsLeadingPosDefined(child, crossAxis) && - (YGNodeAlignItem(node, child) == YGAlignFlexEnd || node->style.flexWrap == YGWrapWrapReverse)) { + ((YGNodeAlignItem(node, child) == YGAlignFlexEnd) ^ (node->style.flexWrap == YGWrapWrapReverse))) { child->layout.position[leading[crossAxis]] = (node->layout.measuredDimensions[dim[crossAxis]] - child->layout.measuredDimensions[dim[crossAxis]]); }