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]] =