From 629e401debe1e50fd13c25a39e14fb7111fa8c13 Mon Sep 17 00:00:00 2001 From: yihuang Date: Mon, 22 May 2017 02:56:19 -0700 Subject: [PATCH] Fix right/bottom in absolute layout. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: 1, Change bottom to be based� on height of parent. 2, Respect margin value when layout with right/bottom. Closes https://github.com/facebook/yoga/pull/552 Differential Revision: D5102090 Pulled By: emilsjolander fbshipit-source-id: dca291413ffc2027d7628f4c8b8eeeb0b4823bc2 --- .../Facebook.Yoga/YGAbsolutePositionTest.cs | 120 +++++++++++++++++ gentest/fixtures/YGAbsolutePositionTest.html | 8 ++ .../facebook/yoga/YGAbsolutePositionTest.java | 119 +++++++++++++++++ .../Facebook.Yoga/YGAbsolutePositionTest.js | 123 ++++++++++++++++++ tests/YGAbsolutePositionTest.cpp | 120 +++++++++++++++++ yoga/Yoga.c | 6 +- 6 files changed, 494 insertions(+), 2 deletions(-) diff --git a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs index 274123db..1e2e4086 100644 --- a/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs +++ b/csharp/tests/Facebook.Yoga/YGAbsolutePositionTest.cs @@ -285,6 +285,30 @@ namespace Facebook.Yoga root_child1.Width = 50; root_child1.Height = 50; root.Insert(1, root_child1); + + YogaNode root_child2 = new YogaNode(config); + root_child2.PositionType = YogaPositionType.Absolute; + root_child2.Left = 0; + root_child2.Top = 0; + root_child2.MarginLeft = 10; + root_child2.MarginTop = 10; + root_child2.MarginRight = 10; + root_child2.MarginBottom = 10; + root_child2.Width = 50; + root_child2.Height = 50; + root.Insert(2, root_child2); + + YogaNode root_child3 = new YogaNode(config); + root_child3.PositionType = YogaPositionType.Absolute; + root_child3.Right = 0; + root_child3.Bottom = 0; + root_child3.MarginLeft = 10; + root_child3.MarginTop = 10; + root_child3.MarginRight = 10; + root_child3.MarginBottom = 10; + root_child3.Width = 50; + root_child3.Height = 50; + root.Insert(3, root_child3); root.StyleDirection = YogaDirection.LTR; root.CalculateLayout(); @@ -303,6 +327,16 @@ namespace Facebook.Yoga Assert.AreEqual(50f, root_child1.LayoutWidth); Assert.AreEqual(50f, root_child1.LayoutHeight); + Assert.AreEqual(20f, root_child2.LayoutX); + Assert.AreEqual(20f, root_child2.LayoutY); + Assert.AreEqual(50f, root_child2.LayoutWidth); + Assert.AreEqual(50f, root_child2.LayoutHeight); + + Assert.AreEqual(30f, root_child3.LayoutX); + Assert.AreEqual(30f, root_child3.LayoutY); + Assert.AreEqual(50f, root_child3.LayoutWidth); + Assert.AreEqual(50f, root_child3.LayoutHeight); + root.StyleDirection = YogaDirection.RTL; root.CalculateLayout(); @@ -320,6 +354,16 @@ namespace Facebook.Yoga Assert.AreEqual(40f, root_child1.LayoutY); Assert.AreEqual(50f, root_child1.LayoutWidth); Assert.AreEqual(50f, root_child1.LayoutHeight); + + Assert.AreEqual(20f, root_child2.LayoutX); + Assert.AreEqual(20f, root_child2.LayoutY); + Assert.AreEqual(50f, root_child2.LayoutWidth); + Assert.AreEqual(50f, root_child2.LayoutHeight); + + Assert.AreEqual(30f, root_child3.LayoutX); + Assert.AreEqual(30f, root_child3.LayoutY); + Assert.AreEqual(50f, root_child3.LayoutWidth); + Assert.AreEqual(50f, root_child3.LayoutHeight); } [Test] @@ -745,5 +789,81 @@ namespace Facebook.Yoga Assert.AreEqual(52f, root.LayoutHeight); } + [Test] + public void Test_absolute_layout_percentage_bottom_based_on_parent_height() + { + YogaConfig config = new YogaConfig(); + + YogaNode root = new YogaNode(config); + root.Width = 100; + root.Height = 200; + + YogaNode root_child0 = new YogaNode(config); + root_child0.PositionType = YogaPositionType.Absolute; + root_child0.Top = 50.Percent(); + root_child0.Width = 10; + root_child0.Height = 10; + root.Insert(0, root_child0); + + YogaNode root_child1 = new YogaNode(config); + root_child1.PositionType = YogaPositionType.Absolute; + root_child1.Bottom = 50.Percent(); + root_child1.Width = 10; + root_child1.Height = 10; + root.Insert(1, root_child1); + + YogaNode root_child2 = new YogaNode(config); + root_child2.PositionType = YogaPositionType.Absolute; + root_child2.Top = 10.Percent(); + root_child2.Bottom = 10.Percent(); + root_child2.Width = 10; + root.Insert(2, root_child2); + root.StyleDirection = YogaDirection.LTR; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(0f, root_child0.LayoutX); + Assert.AreEqual(100f, root_child0.LayoutY); + Assert.AreEqual(10f, root_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0.LayoutHeight); + + Assert.AreEqual(0f, root_child1.LayoutX); + Assert.AreEqual(90f, root_child1.LayoutY); + Assert.AreEqual(10f, root_child1.LayoutWidth); + Assert.AreEqual(10f, root_child1.LayoutHeight); + + Assert.AreEqual(0f, root_child2.LayoutX); + Assert.AreEqual(20f, root_child2.LayoutY); + Assert.AreEqual(10f, root_child2.LayoutWidth); + Assert.AreEqual(160f, root_child2.LayoutHeight); + + root.StyleDirection = YogaDirection.RTL; + root.CalculateLayout(); + + Assert.AreEqual(0f, root.LayoutX); + Assert.AreEqual(0f, root.LayoutY); + Assert.AreEqual(100f, root.LayoutWidth); + Assert.AreEqual(200f, root.LayoutHeight); + + Assert.AreEqual(90f, root_child0.LayoutX); + Assert.AreEqual(100f, root_child0.LayoutY); + Assert.AreEqual(10f, root_child0.LayoutWidth); + Assert.AreEqual(10f, root_child0.LayoutHeight); + + Assert.AreEqual(90f, root_child1.LayoutX); + Assert.AreEqual(90f, root_child1.LayoutY); + Assert.AreEqual(10f, root_child1.LayoutWidth); + Assert.AreEqual(10f, root_child1.LayoutHeight); + + Assert.AreEqual(90f, root_child2.LayoutX); + Assert.AreEqual(20f, root_child2.LayoutY); + Assert.AreEqual(10f, root_child2.LayoutWidth); + Assert.AreEqual(160f, root_child2.LayoutHeight); + } + } } diff --git a/gentest/fixtures/YGAbsolutePositionTest.html b/gentest/fixtures/YGAbsolutePositionTest.html index 31864672..b0566889 100644 --- a/gentest/fixtures/YGAbsolutePositionTest.html +++ b/gentest/fixtures/YGAbsolutePositionTest.html @@ -23,6 +23,8 @@
+
+
@@ -63,3 +65,9 @@
+ +
+
+
+
+
diff --git a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java index 42413fc7..bab24718 100644 --- a/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java +++ b/java/tests/com/facebook/yoga/YGAbsolutePositionTest.java @@ -278,6 +278,30 @@ public class YGAbsolutePositionTest { root_child1.setWidth(50f); root_child1.setHeight(50f); root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = new YogaNode(config); + root_child2.setPositionType(YogaPositionType.ABSOLUTE); + root_child2.setPosition(YogaEdge.LEFT, 0f); + root_child2.setPosition(YogaEdge.TOP, 0f); + root_child2.setMargin(YogaEdge.LEFT, 10f); + root_child2.setMargin(YogaEdge.TOP, 10f); + root_child2.setMargin(YogaEdge.RIGHT, 10f); + root_child2.setMargin(YogaEdge.BOTTOM, 10f); + root_child2.setWidth(50f); + root_child2.setHeight(50f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = new YogaNode(config); + root_child3.setPositionType(YogaPositionType.ABSOLUTE); + root_child3.setPosition(YogaEdge.RIGHT, 0f); + root_child3.setPosition(YogaEdge.BOTTOM, 0f); + root_child3.setMargin(YogaEdge.LEFT, 10f); + root_child3.setMargin(YogaEdge.TOP, 10f); + root_child3.setMargin(YogaEdge.RIGHT, 10f); + root_child3.setMargin(YogaEdge.BOTTOM, 10f); + root_child3.setWidth(50f); + root_child3.setHeight(50f); + root.addChildAt(root_child3, 3); root.setDirection(YogaDirection.LTR); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -296,6 +320,16 @@ public class YGAbsolutePositionTest { assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + assertEquals(20f, root_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child2.getLayoutY(), 0.0f); + assertEquals(50f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(30f, root_child3.getLayoutX(), 0.0f); + assertEquals(30f, root_child3.getLayoutY(), 0.0f); + assertEquals(50f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child3.getLayoutHeight(), 0.0f); + root.setDirection(YogaDirection.RTL); root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); @@ -313,6 +347,16 @@ public class YGAbsolutePositionTest { assertEquals(40f, root_child1.getLayoutY(), 0.0f); assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); assertEquals(50f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child2.getLayoutY(), 0.0f); + assertEquals(50f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(30f, root_child3.getLayoutX(), 0.0f); + assertEquals(30f, root_child3.getLayoutY(), 0.0f); + assertEquals(50f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(50f, root_child3.getLayoutHeight(), 0.0f); } @Test @@ -728,4 +772,79 @@ public class YGAbsolutePositionTest { assertEquals(52f, root.getLayoutHeight(), 0.0f); } + @Test + public void test_absolute_layout_percentage_bottom_based_on_parent_height() { + YogaConfig config = new YogaConfig(); + + final YogaNode root = new YogaNode(config); + root.setWidth(100f); + root.setHeight(200f); + + final YogaNode root_child0 = new YogaNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPositionPercent(YogaEdge.TOP, 50f); + root_child0.setWidth(10f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = new YogaNode(config); + root_child1.setPositionType(YogaPositionType.ABSOLUTE); + root_child1.setPositionPercent(YogaEdge.BOTTOM, 50f); + root_child1.setWidth(10f); + root_child1.setHeight(10f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = new YogaNode(config); + root_child2.setPositionType(YogaPositionType.ABSOLUTE); + root_child2.setPositionPercent(YogaEdge.TOP, 10f); + root_child2.setPositionPercent(YogaEdge.BOTTOM, 10f); + root_child2.setWidth(10f); + root.addChildAt(root_child2, 2); + 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(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(100f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(90f, root_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child2.getLayoutY(), 0.0f); + assertEquals(10f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(160f, root_child2.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(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(90f, root_child0.getLayoutX(), 0.0f); + assertEquals(100f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(90f, root_child1.getLayoutX(), 0.0f); + assertEquals(90f, root_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(90f, root_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child2.getLayoutY(), 0.0f); + assertEquals(10f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(160f, root_child2.getLayoutHeight(), 0.0f); + } + } diff --git a/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js b/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js index d6049fa0..7435a955 100644 --- a/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js +++ b/javascript/tests/Facebook.Yoga/YGAbsolutePositionTest.js @@ -293,6 +293,30 @@ it("absolute_layout_within_border", function () { root_child1.setWidth(50); root_child1.setHeight(50); root.insertChild(root_child1, 1); + + var root_child2 = Yoga.Node.create(config); + root_child2.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child2.setPosition(Yoga.EDGE_LEFT, 0); + root_child2.setPosition(Yoga.EDGE_TOP, 0); + root_child2.setMargin(Yoga.EDGE_LEFT, 10); + root_child2.setMargin(Yoga.EDGE_TOP, 10); + root_child2.setMargin(Yoga.EDGE_RIGHT, 10); + root_child2.setMargin(Yoga.EDGE_BOTTOM, 10); + root_child2.setWidth(50); + root_child2.setHeight(50); + root.insertChild(root_child2, 2); + + var root_child3 = Yoga.Node.create(config); + root_child3.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child3.setPosition(Yoga.EDGE_RIGHT, 0); + root_child3.setPosition(Yoga.EDGE_BOTTOM, 0); + root_child3.setMargin(Yoga.EDGE_LEFT, 10); + root_child3.setMargin(Yoga.EDGE_TOP, 10); + root_child3.setMargin(Yoga.EDGE_RIGHT, 10); + root_child3.setMargin(Yoga.EDGE_BOTTOM, 10); + root_child3.setWidth(50); + root_child3.setHeight(50); + root.insertChild(root_child3, 3); root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_LTR); console.assert(10 === root.getComputedLeft(), "10 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); @@ -310,6 +334,16 @@ it("absolute_layout_within_border", function () { console.assert(50 === root_child1.getComputedWidth(), "50 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); console.assert(50 === root_child1.getComputedHeight(), "50 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + console.assert(20 === root_child2.getComputedLeft(), "20 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(20 === root_child2.getComputedTop(), "20 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(50 === root_child2.getComputedWidth(), "50 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(50 === root_child2.getComputedHeight(), "50 === root_child2.getComputedHeight() (" + root_child2.getComputedHeight() + ")"); + + console.assert(30 === root_child3.getComputedLeft(), "30 === root_child3.getComputedLeft() (" + root_child3.getComputedLeft() + ")"); + console.assert(30 === root_child3.getComputedTop(), "30 === root_child3.getComputedTop() (" + root_child3.getComputedTop() + ")"); + console.assert(50 === root_child3.getComputedWidth(), "50 === root_child3.getComputedWidth() (" + root_child3.getComputedWidth() + ")"); + console.assert(50 === root_child3.getComputedHeight(), "50 === root_child3.getComputedHeight() (" + root_child3.getComputedHeight() + ")"); + root.calculateLayout(Yoga.UNDEFINED, Yoga.UNDEFINED, Yoga.DIRECTION_RTL); console.assert(10 === root.getComputedLeft(), "10 === root.getComputedLeft() (" + root.getComputedLeft() + ")"); @@ -326,6 +360,16 @@ it("absolute_layout_within_border", function () { console.assert(40 === root_child1.getComputedTop(), "40 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); console.assert(50 === root_child1.getComputedWidth(), "50 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); console.assert(50 === root_child1.getComputedHeight(), "50 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + console.assert(20 === root_child2.getComputedLeft(), "20 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(20 === root_child2.getComputedTop(), "20 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(50 === root_child2.getComputedWidth(), "50 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(50 === root_child2.getComputedHeight(), "50 === root_child2.getComputedHeight() (" + root_child2.getComputedHeight() + ")"); + + console.assert(30 === root_child3.getComputedLeft(), "30 === root_child3.getComputedLeft() (" + root_child3.getComputedLeft() + ")"); + console.assert(30 === root_child3.getComputedTop(), "30 === root_child3.getComputedTop() (" + root_child3.getComputedTop() + ")"); + console.assert(50 === root_child3.getComputedWidth(), "50 === root_child3.getComputedWidth() (" + root_child3.getComputedWidth() + ")"); + console.assert(50 === root_child3.getComputedHeight(), "50 === root_child3.getComputedHeight() (" + root_child3.getComputedHeight() + ")"); } finally { if (typeof root !== "undefined") { root.freeRecursive(); @@ -787,3 +831,82 @@ it("position_root_with_rtl_should_position_withoutdirection", function () { config.free(); } }); +it("absolute_layout_percentage_bottom_based_on_parent_height", function () { + var config = Yoga.Config.create(); + + try { + var root = Yoga.Node.create(config); + root.setWidth(100); + root.setHeight(200); + + var root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child0.setPosition(Yoga.EDGE_TOP, "50%"); + root_child0.setWidth(10); + root_child0.setHeight(10); + root.insertChild(root_child0, 0); + + var root_child1 = Yoga.Node.create(config); + root_child1.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child1.setPosition(Yoga.EDGE_BOTTOM, "50%"); + root_child1.setWidth(10); + root_child1.setHeight(10); + root.insertChild(root_child1, 1); + + var root_child2 = Yoga.Node.create(config); + root_child2.setPositionType(Yoga.POSITION_TYPE_ABSOLUTE); + root_child2.setPosition(Yoga.EDGE_TOP, "10%"); + root_child2.setPosition(Yoga.EDGE_BOTTOM, "10%"); + root_child2.setWidth(10); + root.insertChild(root_child2, 2); + 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(200 === root.getComputedHeight(), "200 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(0 === root_child0.getComputedLeft(), "0 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(100 === root_child0.getComputedTop(), "100 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(10 === root_child0.getComputedWidth(), "10 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(10 === root_child0.getComputedHeight(), "10 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(0 === root_child1.getComputedLeft(), "0 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(90 === root_child1.getComputedTop(), "90 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(10 === root_child1.getComputedWidth(), "10 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(10 === root_child1.getComputedHeight(), "10 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + console.assert(0 === root_child2.getComputedLeft(), "0 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(20 === root_child2.getComputedTop(), "20 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(10 === root_child2.getComputedWidth(), "10 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(160 === root_child2.getComputedHeight(), "160 === root_child2.getComputedHeight() (" + root_child2.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(200 === root.getComputedHeight(), "200 === root.getComputedHeight() (" + root.getComputedHeight() + ")"); + + console.assert(90 === root_child0.getComputedLeft(), "90 === root_child0.getComputedLeft() (" + root_child0.getComputedLeft() + ")"); + console.assert(100 === root_child0.getComputedTop(), "100 === root_child0.getComputedTop() (" + root_child0.getComputedTop() + ")"); + console.assert(10 === root_child0.getComputedWidth(), "10 === root_child0.getComputedWidth() (" + root_child0.getComputedWidth() + ")"); + console.assert(10 === root_child0.getComputedHeight(), "10 === root_child0.getComputedHeight() (" + root_child0.getComputedHeight() + ")"); + + console.assert(90 === root_child1.getComputedLeft(), "90 === root_child1.getComputedLeft() (" + root_child1.getComputedLeft() + ")"); + console.assert(90 === root_child1.getComputedTop(), "90 === root_child1.getComputedTop() (" + root_child1.getComputedTop() + ")"); + console.assert(10 === root_child1.getComputedWidth(), "10 === root_child1.getComputedWidth() (" + root_child1.getComputedWidth() + ")"); + console.assert(10 === root_child1.getComputedHeight(), "10 === root_child1.getComputedHeight() (" + root_child1.getComputedHeight() + ")"); + + console.assert(90 === root_child2.getComputedLeft(), "90 === root_child2.getComputedLeft() (" + root_child2.getComputedLeft() + ")"); + console.assert(20 === root_child2.getComputedTop(), "20 === root_child2.getComputedTop() (" + root_child2.getComputedTop() + ")"); + console.assert(10 === root_child2.getComputedWidth(), "10 === root_child2.getComputedWidth() (" + root_child2.getComputedWidth() + ")"); + console.assert(160 === root_child2.getComputedHeight(), "160 === root_child2.getComputedHeight() (" + root_child2.getComputedHeight() + ")"); + } finally { + if (typeof root !== "undefined") { + root.freeRecursive(); + } + + config.free(); + } +}); diff --git a/tests/YGAbsolutePositionTest.cpp b/tests/YGAbsolutePositionTest.cpp index dd52824f..ddc89e10 100644 --- a/tests/YGAbsolutePositionTest.cpp +++ b/tests/YGAbsolutePositionTest.cpp @@ -278,6 +278,30 @@ TEST(YogaTest, absolute_layout_within_border) { YGNodeStyleSetWidth(root_child1, 50); YGNodeStyleSetHeight(root_child1, 50); YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child2, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child2, YGEdgeLeft, 0); + YGNodeStyleSetPosition(root_child2, YGEdgeTop, 0); + YGNodeStyleSetMargin(root_child2, YGEdgeLeft, 10); + YGNodeStyleSetMargin(root_child2, YGEdgeTop, 10); + YGNodeStyleSetMargin(root_child2, YGEdgeRight, 10); + YGNodeStyleSetMargin(root_child2, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child2, 50); + YGNodeStyleSetHeight(root_child2, 50); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child3, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child3, YGEdgeRight, 0); + YGNodeStyleSetPosition(root_child3, YGEdgeBottom, 0); + YGNodeStyleSetMargin(root_child3, YGEdgeLeft, 10); + YGNodeStyleSetMargin(root_child3, YGEdgeTop, 10); + YGNodeStyleSetMargin(root_child3, YGEdgeRight, 10); + YGNodeStyleSetMargin(root_child3, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child3, 50); + YGNodeStyleSetHeight(root_child3, 50); + YGNodeInsertChild(root, root_child3, 3); YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); @@ -295,6 +319,16 @@ TEST(YogaTest, absolute_layout_within_border) { ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3)); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); @@ -312,6 +346,16 @@ TEST(YogaTest, absolute_layout_within_border) { ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child1)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetHeight(root_child3)); + YGNodeFreeRecursive(root); YGConfigFree(config); @@ -739,3 +783,79 @@ TEST(YogaTest, position_root_with_rtl_should_position_withoutdirection) { YGConfigFree(config); } + +TEST(YogaTest, absolute_layout_percentage_bottom_based_on_parent_height) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 200); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPositionPercent(root_child0, YGEdgeTop, 50); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child1, YGPositionTypeAbsolute); + YGNodeStyleSetPositionPercent(root_child1, YGEdgeBottom, 50); + YGNodeStyleSetWidth(root_child1, 10); + YGNodeStyleSetHeight(root_child1, 10); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child2, YGPositionTypeAbsolute); + YGNodeStyleSetPositionPercent(root_child2, YGEdgeTop, 10); + YGNodeStyleSetPositionPercent(root_child2, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child2, 10); + YGNodeInsertChild(root, root_child2, 2); + 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(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child2)); + + 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(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(160, YGNodeLayoutGetHeight(root_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/Yoga.c b/yoga/Yoga.c index c8c92e05..9aaa6333 100644 --- a/yoga/Yoga.c +++ b/yoga/Yoga.c @@ -1687,7 +1687,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->layout.position[leading[mainAxis]] = node->layout.measuredDimensions[dim[mainAxis]] - child->layout.measuredDimensions[dim[mainAxis]] - YGNodeTrailingBorder(node, mainAxis) - - YGNodeTrailingPosition(child, mainAxis, width); + YGNodeTrailingMargin(child, mainAxis, width) - + YGNodeTrailingPosition(child, mainAxis, isMainAxisRow ? width : height); } else if (!YGNodeIsLeadingPosDefined(child, mainAxis) && node->style.justifyContent == YGJustifyCenter) { child->layout.position[leading[mainAxis]] = (node->layout.measuredDimensions[dim[mainAxis]] - @@ -1704,7 +1705,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->layout.position[leading[crossAxis]] = node->layout.measuredDimensions[dim[crossAxis]] - child->layout.measuredDimensions[dim[crossAxis]] - YGNodeTrailingBorder(node, crossAxis) - - YGNodeTrailingPosition(child, crossAxis, width); + YGNodeTrailingMargin(child, crossAxis, width) - + YGNodeTrailingPosition(child, crossAxis, isMainAxisRow ? height : width); } else if (!YGNodeIsLeadingPosDefined(child, crossAxis) && YGNodeAlignItem(node, child) == YGAlignCenter) { child->layout.position[leading[crossAxis]] =