diff --git a/gentest/fixtures/YGMaxContentsTest.html b/gentest/fixtures/YGMaxContentsTest.html new file mode 100644 index 0000000000..857ef04c9f --- /dev/null +++ b/gentest/fixtures/YGMaxContentsTest.html @@ -0,0 +1,136 @@ +
+
+
+ Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet +
+
+
+ +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+
+ + +
+
+
+
+
+
+ + +
+
+
+ Lorem ipsum dolor sit amet +
+
+
+ + +
+
+
+
+ + +
+
+
+
+
\ No newline at end of file diff --git a/java/tests/generated/com/facebook/yoga/YGMaxContentsTest.java b/java/tests/generated/com/facebook/yoga/YGMaxContentsTest.java new file mode 100644 index 0000000000..02ebf2e114 --- /dev/null +++ b/java/tests/generated/com/facebook/yoga/YGMaxContentsTest.java @@ -0,0 +1,979 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<> + * generated by gentest/src/GentestDriver.ts from gentest/fixtures/YGMaxContentsTest.html + */ + +package com.facebook.yoga; + +import static org.junit.Assert.assertEquals; + +import org.junit.Ignore; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import com.facebook.yoga.utils.TestUtils; + +@RunWith(Parameterized.class) +public class YGMaxContentsTest { + @Parameterized.Parameters(name = "{0}") + public static Iterable nodeFactories() { + return TestParametrization.nodeFactories(); + } + + @Parameterized.Parameter public TestParametrization.NodeFactory mNodeFactory; + + @Test + public void test_max_content_width_with_text() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(200f); + root.setHeight(200f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidthMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.addChildAt(root_child0_child0, 0); + root_child0_child0.setData("Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet"); + root_child0_child0.setMeasureFunction(new TestUtils.intrinsicMeasureFunction()); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1140f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(1140f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(200f, root.getLayoutWidth(), 0.0f); + assertEquals(200f, root.getLayoutHeight(), 0.0f); + + assertEquals(-940f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(1140f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(1140f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_width_does_not_wrap() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(200f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setWrap(YogaWrap.WRAP); + root_child0.setWidthMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(50f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(100f); + root_child0_child1.setHeight(10f); + root_child0.addChildAt(root_child0_child1, 1); + + final YogaNode root_child0_child2 = createNode(config); + root_child0_child2.setWidth(25f); + root_child0_child2.setHeight(10f); + root_child0.addChildAt(root_child0_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(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(-75f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(125f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(25f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_flex_basis_beats_width_row() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(100f); + root.setHeight(200f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setWrap(YogaWrap.WRAP); + root_child0.setFlexBasisMaxContent(); + root_child0.setWidth(300f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(50f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(100f); + root_child0_child1.setHeight(10f); + root_child0.addChildAt(root_child0_child1, 1); + + final YogaNode root_child0_child2 = createNode(config); + root_child0_child2.setWidth(25f); + root_child0_child2.setHeight(10f); + root_child0.addChildAt(root_child0_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(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(-75f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(125f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(25f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_flex_basis_beats_height_column() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(200f); + root.setHeight(80f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexBasisMaxContent(); + root_child0.setHeight(300f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(60f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(10f); + root_child0_child1.setHeight(40f); + root_child0.addChildAt(root_child0_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(80f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.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(200f, root.getLayoutWidth(), 0.0f); + assertEquals(80f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(200f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_flex_basis_shrinks_with_min_width_zero() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(100f); + root.setHeight(200f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setWrap(YogaWrap.WRAP); + root_child0.setFlexBasisMaxContent(); + root_child0.setFlexShrink(1f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(50f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(100f); + root_child0_child1.setHeight(10f); + root_child0.addChildAt(root_child0_child1, 1); + + final YogaNode root_child0_child2 = createNode(config); + root_child0_child2.setWidth(25f); + root_child0_child2.setHeight(10f); + root_child0.addChildAt(root_child0_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(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(200f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(75f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(20f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_width_resolves_percent_child() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(300f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidthMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(100f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidthPercent(50f); + root_child0_child1.setHeight(10f); + root_child0.addChildAt(root_child0_child1, 1); + 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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_height_in_row_parent() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(200f); + root.setHeight(150f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(50f); + root_child0.setHeightMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(60f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(10f); + root_child0_child1.setHeight(40f); + root_child0.addChildAt(root_child0_child1, 1); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(200f, root.getLayoutWidth(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.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(200f, root.getLayoutWidth(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_height_multiline_no_line_stretch() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWrap(YogaWrap.WRAP); + root.setWidth(120f); + root.setHeight(300f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(50f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(50f); + root_child1.setHeightMaxContent(); + root.addChildAt(root_child1, 1); + + final YogaNode root_child1_child0 = createNode(config); + root_child1_child0.setWidth(10f); + root_child1_child0.setHeight(40f); + root_child1.addChildAt(root_child1_child0, 0); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(60f); + root_child2.setHeight(20f); + 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(120f, 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(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child1_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(60f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(20f, 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(120f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(50f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child1_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child1_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child1_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child1_child0.getLayoutHeight(), 0.0f); + + assertEquals(60f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(60f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(20f, root_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_width_absolute_ignores_insets() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPosition(YogaEdge.LEFT, 0f); + root_child0.setPosition(YogaEdge.RIGHT, 0f); + root_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.setWidthMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(50f); + root_child0_child0.setHeight(10f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(100f); + root_child0_child1.setHeight(10f); + root_child0.addChildAt(root_child0_child1, 1); + + final YogaNode root_child0_child2 = createNode(config); + root_child0_child2.setWidth(25f); + root_child0_child2.setHeight(10f); + root_child0.addChildAt(root_child0_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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(150f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(-75f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(175f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(125f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(25f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child2.getLayoutY(), 0.0f); + assertEquals(25f, root_child0_child2.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_height_absolute_ignores_insets() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(80f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPosition(YogaEdge.TOP, 0f); + root_child0.setPosition(YogaEdge.BOTTOM, 0f); + root_child0.setWidth(50f); + root_child0.setHeightMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(60f); + root_child0.addChildAt(root_child0_child0, 0); + + final YogaNode root_child0_child1 = createNode(config); + root_child0_child1.setWidth(10f); + root_child0_child1.setHeight(40f); + root_child0.addChildAt(root_child0_child1, 1); + 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(80f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.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(80f, root.getLayoutHeight(), 0.0f); + + assertEquals(50f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(50f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(60f, root_child0_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child0_child1.getLayoutX(), 0.0f); + assertEquals(60f, root_child0_child1.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child1.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child1.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_width_absolute_text_does_not_wrap() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setWidthMaxContent(); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setFlexDirection(YogaFlexDirection.ROW); + root_child0.addChildAt(root_child0_child0, 0); + root_child0_child0.setData("Lorem ipsum dolor sit amet"); + root_child0_child0.setMeasureFunction(new TestUtils.intrinsicMeasureFunction()); + 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(260f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(260f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_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(-160f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(260f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(260f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_max_content_both_axes_height_remeasured_at_clamped_width() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWrap(YogaWrap.WRAP); + root.setWidthMaxContent(); + root.setHeightMaxContent(); + root.setMaxWidth(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(80f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(80f); + root_child1.setHeight(10f); + root.addChildAt(root_child1, 1); + 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(20f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(80f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child1.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(20f, root.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(80f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(20f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child1.getLayoutHeight(), 0.0f); + } + + @Test + @Ignore + public void test_max_content_with_aspect_ratio() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setWidth(300f); + root.setHeight(150f); + + final YogaNode root_child0 = createNode(config); + root_child0.setHeightMaxContent(); + root_child0.setAspectRatio(2f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child0_child0 = createNode(config); + root_child0_child0.setWidth(10f); + root_child0_child0.setHeight(40f); + root_child0.addChildAt(root_child0_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(300f, root.getLayoutWidth(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_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(300f, root.getLayoutWidth(), 0.0f); + assertEquals(150f, root.getLayoutHeight(), 0.0f); + + assertEquals(290f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0_child0.getLayoutWidth(), 0.0f); + assertEquals(40f, root_child0_child0.getLayoutHeight(), 0.0f); + } + + private YogaNode createNode(YogaConfig config) { + return mNodeFactory.create(config); + } +} diff --git a/javascript/tests/generated/YGMaxContentsTest.test.ts b/javascript/tests/generated/YGMaxContentsTest.test.ts new file mode 100644 index 0000000000..11e2aeb042 --- /dev/null +++ b/javascript/tests/generated/YGMaxContentsTest.test.ts @@ -0,0 +1,921 @@ +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @generated SignedSource<<2fca322efa66c71e116fd224afde7c29>> + * generated by gentest/src/GentestDriver.ts from gentest/fixtures/YGMaxContentsTest.html + */ + +import { intrinsicSizeMeasureFunc } from '../tools/utils.ts' +import Yoga from 'yoga-layout'; +import { + Align, + BoxSizing, + Direction, + Display, + Edge, + Errata, + ExperimentalFeature, + FlexDirection, + Gutter, + Justify, + MeasureMode, + Overflow, + PositionType, + Unit, + Wrap, +} from 'yoga-layout'; + +test('max_content_width_with_text', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(200); + root.setHeight(200); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setFlexDirection(FlexDirection.Row); + root_child0.insertChild(root_child0_child0, 0); + root_child0_child0.setMeasureFunc(intrinsicSizeMeasureFunc.bind({text: "Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet", flexDirection: FlexDirection.Row})); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(1140); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(1140); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(-940); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(1140); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(1140); + expect(root_child0_child0.getComputedHeight()).toBe(10); +}); +test('max_content_width_does_not_wrap', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(200); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(FlexDirection.Row); + root_child0.setFlexWrap(Wrap.Wrap); + root_child0.setWidth("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(50); + root_child0_child0.setHeight(10); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(100); + root_child0_child1.setHeight(10); + root_child0.insertChild(root_child0_child1, 1); + + const root_child0_child2 = Yoga.Node.create(config); + root_child0_child2.setWidth(25); + root_child0_child2.setHeight(10); + root_child0.insertChild(root_child0_child2, 2); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(50); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(150); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(-75); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(125); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(25); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(0); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); +}); +test('max_content_flex_basis_beats_width_row', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setWidth(100); + root.setHeight(200); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(FlexDirection.Row); + root_child0.setFlexWrap(Wrap.Wrap); + root_child0.setFlexBasis("max-content"); + root_child0.setWidth(300); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(50); + root_child0_child0.setHeight(10); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(100); + root_child0_child1.setHeight(10); + root_child0.insertChild(root_child0_child1, 1); + + const root_child0_child2 = Yoga.Node.create(config); + root_child0_child2.setWidth(25); + root_child0_child2.setHeight(10); + root_child0.insertChild(root_child0_child2, 2); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(200); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(50); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(150); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(-75); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(200); + + expect(root_child0_child0.getComputedLeft()).toBe(125); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(25); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(0); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); +}); +test('max_content_flex_basis_beats_height_column', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(200); + root.setHeight(80); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexBasis("max-content"); + root_child0.setHeight(300); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(10); + root_child0_child0.setHeight(60); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(10); + root_child0_child1.setHeight(40); + root_child0.insertChild(root_child0_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(80); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(200); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(80); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(200); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(190); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(190); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); +}); +test('max_content_flex_basis_shrinks_with_min_width_zero', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setWidth(100); + root.setHeight(200); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexDirection(FlexDirection.Row); + root_child0.setFlexWrap(Wrap.Wrap); + root_child0.setFlexBasis("max-content"); + root_child0.setFlexShrink(1); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(50); + root_child0_child0.setHeight(10); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(100); + root_child0_child1.setHeight(10); + root_child0.insertChild(root_child0_child1, 1); + + const root_child0_child2 = Yoga.Node.create(config); + root_child0_child2.setWidth(25); + root_child0_child2.setHeight(10); + root_child0.insertChild(root_child0_child2, 2); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(200); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(10); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(0); + expect(root_child0_child2.getComputedTop()).toBe(20); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(200); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(200); + + expect(root_child0_child0.getComputedLeft()).toBe(50); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(10); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(75); + expect(root_child0_child2.getComputedTop()).toBe(20); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); +}); +test('max_content_width_resolves_percent_child', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(300); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(100); + root_child0_child0.setHeight(10); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth("50%"); + root_child0_child1.setHeight(10); + root_child0.insertChild(root_child0_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(20); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(100); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(10); + expect(root_child0_child1.getComputedWidth()).toBe(50); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(200); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(20); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(100); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(50); + expect(root_child0_child1.getComputedTop()).toBe(10); + expect(root_child0_child1.getComputedWidth()).toBe(50); + expect(root_child0_child1.getComputedHeight()).toBe(10); +}); +test('max_content_height_in_row_parent', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setWidth(200); + root.setHeight(150); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(50); + root_child0.setHeight("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(10); + root_child0_child0.setHeight(60); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(10); + root_child0_child1.setHeight(40); + root_child0.insertChild(root_child0_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(150); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(200); + expect(root.getComputedHeight()).toBe(150); + + expect(root_child0.getComputedLeft()).toBe(150); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(40); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(40); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); +}); +test('max_content_height_multiline_no_line_stretch', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setFlexWrap(Wrap.Wrap); + root.setWidth(120); + root.setHeight(300); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(50); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(50); + root_child1.setHeight("max-content"); + root.insertChild(root_child1, 1); + + const root_child1_child0 = Yoga.Node.create(config); + root_child1_child0.setWidth(10); + root_child1_child0.setHeight(40); + root_child1.insertChild(root_child1_child0, 0); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(60); + root_child2.setHeight(20); + root.insertChild(root_child2, 2); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(120); + expect(root.getComputedHeight()).toBe(300); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(50); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(50); + expect(root_child1.getComputedHeight()).toBe(40); + + expect(root_child1_child0.getComputedLeft()).toBe(0); + expect(root_child1_child0.getComputedTop()).toBe(0); + expect(root_child1_child0.getComputedWidth()).toBe(10); + expect(root_child1_child0.getComputedHeight()).toBe(40); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(60); + expect(root_child2.getComputedHeight()).toBe(20); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(120); + expect(root.getComputedHeight()).toBe(300); + + expect(root_child0.getComputedLeft()).toBe(70); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(20); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(50); + expect(root_child1.getComputedHeight()).toBe(40); + + expect(root_child1_child0.getComputedLeft()).toBe(40); + expect(root_child1_child0.getComputedTop()).toBe(0); + expect(root_child1_child0.getComputedWidth()).toBe(10); + expect(root_child1_child0.getComputedHeight()).toBe(40); + + expect(root_child2.getComputedLeft()).toBe(60); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(60); + expect(root_child2.getComputedHeight()).toBe(20); +}); +test('max_content_width_absolute_ignores_insets', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setPosition(Edge.Left, 0); + root_child0.setPosition(Edge.Right, 0); + root_child0.setFlexDirection(FlexDirection.Row); + root_child0.setWidth("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(50); + root_child0_child0.setHeight(10); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(100); + root_child0_child1.setHeight(10); + root_child0.insertChild(root_child0_child1, 1); + + const root_child0_child2 = Yoga.Node.create(config); + root_child0_child2.setWidth(25); + root_child0_child2.setHeight(10); + root_child0.insertChild(root_child0_child2, 2); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(50); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(150); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(-75); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(175); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(125); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(50); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child1.getComputedLeft()).toBe(25); + expect(root_child0_child1.getComputedTop()).toBe(0); + expect(root_child0_child1.getComputedWidth()).toBe(100); + expect(root_child0_child1.getComputedHeight()).toBe(10); + + expect(root_child0_child2.getComputedLeft()).toBe(0); + expect(root_child0_child2.getComputedTop()).toBe(0); + expect(root_child0_child2.getComputedWidth()).toBe(25); + expect(root_child0_child2.getComputedHeight()).toBe(10); +}); +test('max_content_height_absolute_ignores_insets', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(80); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setPosition(Edge.Top, 0); + root_child0.setPosition(Edge.Bottom, 0); + root_child0.setWidth(50); + root_child0.setHeight("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(10); + root_child0_child0.setHeight(60); + root_child0.insertChild(root_child0_child0, 0); + + const root_child0_child1 = Yoga.Node.create(config); + root_child0_child1.setWidth(10); + root_child0_child1.setHeight(40); + root_child0.insertChild(root_child0_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(80); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(0); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(80); + + expect(root_child0.getComputedLeft()).toBe(50); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(50); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child0_child0.getComputedLeft()).toBe(40); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(60); + + expect(root_child0_child1.getComputedLeft()).toBe(40); + expect(root_child0_child1.getComputedTop()).toBe(60); + expect(root_child0_child1.getComputedWidth()).toBe(10); + expect(root_child0_child1.getComputedHeight()).toBe(40); +}); +test('max_content_width_absolute_text_does_not_wrap', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setWidth("max-content"); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setFlexDirection(FlexDirection.Row); + root_child0.insertChild(root_child0_child0, 0); + root_child0_child0.setMeasureFunc(intrinsicSizeMeasureFunc.bind({text: "Lorem ipsum dolor sit amet", flexDirection: FlexDirection.Row})); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(260); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(260); + expect(root_child0_child0.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(-160); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(260); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(260); + expect(root_child0_child0.getComputedHeight()).toBe(10); +}); +test('max_content_both_axes_height_remeasured_at_clamped_width', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setFlexWrap(Wrap.Wrap); + root.setWidth("max-content"); + root.setHeight("max-content"); + root.setMaxWidth(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(80); + root_child0.setHeight(10); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(80); + root_child1.setHeight(10); + root.insertChild(root_child1, 1); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(20); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(80); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child1.getComputedLeft()).toBe(0); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(80); + expect(root_child1.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(20); + + expect(root_child0.getComputedLeft()).toBe(20); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(80); + expect(root_child0.getComputedHeight()).toBe(10); + + expect(root_child1.getComputedLeft()).toBe(20); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(80); + expect(root_child1.getComputedHeight()).toBe(10); +}); +test.skip('max_content_with_aspect_ratio', () => { + const config = Yoga.Config.create(); + + const root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setFlexDirection(FlexDirection.Row); + root.setWidth(300); + root.setHeight(150); + + const root_child0 = Yoga.Node.create(config); + root_child0.setHeight("max-content"); + root_child0.setAspectRatio(2); + root.insertChild(root_child0, 0); + + const root_child0_child0 = Yoga.Node.create(config); + root_child0_child0.setWidth(10); + root_child0_child0.setHeight(40); + root_child0.insertChild(root_child0_child0, 0); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(150); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(40); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(40); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(150); + + expect(root_child0.getComputedLeft()).toBe(290); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(40); + + expect(root_child0_child0.getComputedLeft()).toBe(0); + expect(root_child0_child0.getComputedTop()).toBe(0); + expect(root_child0_child0.getComputedWidth()).toBe(10); + expect(root_child0_child0.getComputedHeight()).toBe(40); +}); diff --git a/tests/YGMaxContentAspectRatioTest.cpp b/tests/YGMaxContentAspectRatioTest.cpp new file mode 100644 index 0000000000..df9d9daff0 --- /dev/null +++ b/tests/YGMaxContentAspectRatioTest.cpp @@ -0,0 +1,54 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +// Pins Yoga's documented behavior, not the CSS spec: Yoga does not transfer +// the aspect ratio from a resolved max-content axis, so the item takes its +// content width (10). Browsers transfer (height 40 x ratio 2 = width 80); +// that target is recorded in the disabled fixture case +// max_content_with_aspect_ratio in gentest/fixtures/YGMaxContentsTest.html. +// This test also guards the stretch-override guards in +// computeFlexBasisForChild: without them the aspect ratio transfers a +// stretched height that the keyword then discards, producing width 300. +// If aspect-ratio transfer from intrinsic keywords is implemented, update +// this test to 80x40 and enable the fixture case. +// +// Equivalent fixture: +// +//
+//
+//
+//
+//
+TEST(MaxContentAspectRatio, no_transfer_from_max_content_axis) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 150); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetHeightMaxContent(root_child0); + YGNodeStyleSetAspectRatio(root_child0, 2.0f); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 40); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + YGConfigFree(config); +} diff --git a/tests/YGMaxContentRootTest.cpp b/tests/YGMaxContentRootTest.cpp new file mode 100644 index 0000000000..278f08e20d --- /dev/null +++ b/tests/YGMaxContentRootTest.cpp @@ -0,0 +1,175 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include +#include + +// TODO: move these to fixture based tests once gentest supports passing an +// owner size to YGNodeCalculateLayout. With an undefined owner size, +// max-content on the root is indistinguishable from auto, so only these +// hand-written tests can pin the root keyword branches. + +// Equivalent fixture, laid out with an owner size of 500x500 (the part +// gentest cannot express): +// +//
+//
+//
+//
+//
+TEST(MaxContentRoot, width_max_content_with_definite_owner_size) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidthMaxContent(root); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 50); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 25); + YGNodeStyleSetHeight(root_child2, 50); + YGNodeInsertChild(root, root_child2, 2); + + YGNodeCalculateLayout(root, 500, 500, YGDirectionLTR); + + // The max-content axis measures content instead of filling the owner. + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root)); + // The auto axis still fills the owner. + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child2)); + + YGNodeFreeRecursive(root); + YGConfigFree(config); +} + +// A numeric max-width clamps the root's max-content size, and the content +// must lay out (wrap) within the clamped size, not just report it. +// +// Equivalent fixture, laid out with an owner size of 500x500: +// +//
+//
+//
+//
+TEST(MaxContentRoot, width_max_content_wraps_within_numeric_max_width) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetWidthMaxContent(root); + YGNodeStyleSetMaxWidth(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 80); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 80); + YGNodeStyleSetHeight(root_child1, 10); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, 500, 500, YGDirectionLTR); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + + YGNodeFreeRecursive(root); + YGConfigFree(config); +} + +// Percentages inside a max-content root are cyclic: they contribute nothing +// to the measurement, then resolve against the resolved size — the same +// two-pass contract the flex-item path guarantees. +// +// Equivalent fixture, laid out with an owner size of 500x500: +// +//
+//
+//
+//
+TEST(MaxContentRoot, width_max_content_resolves_percent_child) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthMaxContent(root); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthPercent(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 10); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeCalculateLayout(root, 500, 500, YGDirectionLTR); + + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + + YGNodeFreeRecursive(root); + YGConfigFree(config); +} + +// Equivalent fixture, laid out with an owner size of 500x500 (the part +// gentest cannot express): +// +//
+//
+//
+//
+//
+TEST(MaxContentRoot, height_max_content_with_definite_owner_size) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetHeightMaxContent(root); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 50); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 50); + YGNodeStyleSetHeight(root_child2, 25); + YGNodeInsertChild(root, root_child2, 2); + + YGNodeCalculateLayout(root, 500, 500, YGDirectionLTR); + + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetTop(root_child2)); + + YGNodeFreeRecursive(root); + YGConfigFree(config); +} diff --git a/tests/generated/YGMaxContentsTest.cpp b/tests/generated/YGMaxContentsTest.cpp new file mode 100644 index 0000000000..66186adc02 --- /dev/null +++ b/tests/generated/YGMaxContentsTest.cpp @@ -0,0 +1,974 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * clang-format off + * @generated SignedSource<> + * generated by gentest/src/GentestDriver.ts from gentest/fixtures/YGMaxContentsTest.html + */ + +#include +#include +#include "../util/TestUtil.h" + +TEST(YogaTest, max_content_width_with_text) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 200); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + YGNodeSetContext(root_child0_child0, (void*)"Lorem ipsum sdafhasdfkjlasdhlkajsfhasldkfhasdlkahsdflkjasdhflaksdfasdlkjhasdlfjahsdfljkasdhalsdfhas dolor sit amet"); + YGNodeSetMeasureFunc(root_child0_child0, &facebook::yoga::test::IntrinsicSizeMeasure); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1140, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(1140, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(-940, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(1140, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(1140, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_width_does_not_wrap) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 200); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap); + YGNodeStyleSetWidthMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 50); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 100); + YGNodeStyleSetHeight(root_child0_child1, 10); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + + YGNodeRef root_child0_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child2, 25); + YGNodeStyleSetHeight(root_child0_child2, 10); + YGNodeInsertChild(root_child0, root_child0_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(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_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(-75, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_flex_basis_beats_width_row) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 200); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap); + YGNodeStyleSetFlexBasisMaxContent(root_child0); + YGNodeStyleSetWidth(root_child0, 300); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 50); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 100); + YGNodeStyleSetHeight(root_child0_child1, 10); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + + YGNodeRef root_child0_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child2, 25); + YGNodeStyleSetHeight(root_child0_child2, 10); + YGNodeInsertChild(root_child0, root_child0_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(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_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(-75, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_flex_basis_beats_height_column) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 80); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexBasisMaxContent(root_child0); + YGNodeStyleSetHeight(root_child0, 300); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 60); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 10); + YGNodeStyleSetHeight(root_child0_child1, 40); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_flex_basis_shrinks_with_min_width_zero) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 200); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root_child0, YGWrapWrap); + YGNodeStyleSetFlexBasisMaxContent(root_child0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 50); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 100); + YGNodeStyleSetHeight(root_child0_child1, 10); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + + YGNodeRef root_child0_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child2, 25); + YGNodeStyleSetHeight(root_child0_child2, 10); + YGNodeInsertChild(root_child0, root_child0_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(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_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(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(75, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_width_resolves_percent_child) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 100); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthPercent(root_child0_child1, 50); + YGNodeStyleSetHeight(root_child0_child1, 10); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + 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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + 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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_height_in_row_parent) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 200); + YGNodeStyleSetHeight(root, 150); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeightMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 60); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 10); + YGNodeStyleSetHeight(root_child0_child1, 40); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_height_multiline_no_line_stretch) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetWidth(root, 120); + YGNodeStyleSetHeight(root, 300); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 50); + YGNodeStyleSetHeightMaxContent(root_child1); + YGNodeInsertChild(root, root_child1, 1); + + YGNodeRef root_child1_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1_child0, 10); + YGNodeStyleSetHeight(root_child1_child0, 40); + YGNodeInsertChild(root_child1, root_child1_child0, 0); + + YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 60); + YGNodeStyleSetHeight(root_child2, 20); + 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(120, 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(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(120, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child1_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child1_child0)); + + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetHeight(root_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_width_absolute_ignores_insets) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 0); + YGNodeStyleSetPosition(root_child0, YGEdgeRight, 0); + YGNodeStyleSetFlexDirection(root_child0, YGFlexDirectionRow); + YGNodeStyleSetWidthMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 50); + YGNodeStyleSetHeight(root_child0_child0, 10); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 100); + YGNodeStyleSetHeight(root_child0_child1, 10); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + + YGNodeRef root_child0_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child2, 25); + YGNodeStyleSetHeight(root_child0_child2, 10); + YGNodeInsertChild(root_child0, root_child0_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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(150, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_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(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(-75, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(175, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(125, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child2)); + ASSERT_FLOAT_EQ(25, YGNodeLayoutGetWidth(root_child0_child2)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_height_absolute_ignores_insets) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 80); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child0, YGEdgeTop, 0); + YGNodeStyleSetPosition(root_child0, YGEdgeBottom, 0); + YGNodeStyleSetWidth(root_child0, 50); + YGNodeStyleSetHeightMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 60); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + + YGNodeRef root_child0_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child1, 10); + YGNodeStyleSetHeight(root_child0_child1, 40); + YGNodeInsertChild(root_child0, root_child0_child1, 1); + 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(80, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + 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(80, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(50, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetHeight(root_child0_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child0_child1)); + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetTop(root_child0_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child1)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_width_absolute_text_does_not_wrap) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetWidthMaxContent(root_child0); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root_child0_child0, YGFlexDirectionRow); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + YGNodeSetContext(root_child0_child0, (void*)"Lorem ipsum dolor sit amet"); + YGNodeSetMeasureFunc(root_child0_child0, &facebook::yoga::test::IntrinsicSizeMeasure); + 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(260, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(260, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_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(-160, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(260, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(260, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_both_axes_height_remeasured_at_clamped_width) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetWidthMaxContent(root); + YGNodeStyleSetHeightMaxContent(root); + YGNodeStyleSetMaxWidth(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 80); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 80); + YGNodeStyleSetHeight(root_child1, 10); + YGNodeInsertChild(root, root_child1, 1); + 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(20, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1)); + + 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(20, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(20, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child1)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, max_content_with_aspect_ratio) { + GTEST_SKIP(); + + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 150); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetHeightMaxContent(root_child0); + YGNodeStyleSetAspectRatio(root_child0, 2); + YGNodeInsertChild(root, root_child0, 0); + + YGNodeRef root_child0_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0_child0, 10); + YGNodeStyleSetHeight(root_child0_child0, 40); + YGNodeInsertChild(root_child0, root_child0_child0, 0); + 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(150, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0)); + + 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(150, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(290, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0_child0)); + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetHeight(root_child0_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/algorithm/AbsoluteLayout.cpp b/yoga/algorithm/AbsoluteLayout.cpp index a7d15773fc..8767e871f6 100644 --- a/yoga/algorithm/AbsoluteLayout.cpp +++ b/yoga/algorithm/AbsoluteLayout.cpp @@ -279,6 +279,14 @@ void layoutAbsoluteChild( auto marginColumn = child->style().computeMarginForAxis( FlexDirection::Column, containingBlockWidth); + // An axis set to max-content is sized to the box's measured max-content + // size. It ignores insets and available space for sizing. + // https://www.w3.org/TR/css-sizing-3/#valdef-width-max-content + const bool widthIsMaxContent = + child->getProcessedDimension(Dimension::Width).isMaxContent(); + const bool heightIsMaxContent = + child->getProcessedDimension(Dimension::Height).isMaxContent(); + if (child->hasDefiniteLength(Dimension::Width, containingBlockWidth)) { childWidth = child ->getResolvedDimension( @@ -291,7 +299,8 @@ void layoutAbsoluteChild( } else { // If the child doesn't have a specified width, compute the width based on // the left/right offsets if they're defined. - if (child->style().isFlexStartPositionDefined( + if (!widthIsMaxContent && + child->style().isFlexStartPositionDefined( FlexDirection::Row, direction) && child->style().isFlexEndPositionDefined( FlexDirection::Row, direction) && @@ -330,7 +339,8 @@ void layoutAbsoluteChild( } else { // If the child doesn't have a specified height, compute the height based // on the top/bottom offsets if they're defined. - if (child->style().isFlexStartPositionDefined( + if (!heightIsMaxContent && + child->style().isFlexStartPositionDefined( FlexDirection::Column, direction) && child->style().isFlexEndPositionDefined( FlexDirection::Column, direction) && @@ -363,7 +373,13 @@ void layoutAbsoluteChild( // flexible. const auto& childStyle = child->style(); if (yoga::isUndefined(childWidth) ^ yoga::isUndefined(childHeight)) { - if (childStyle.aspectRatio().isDefined()) { + // The aspect ratio never transfers INTO a max-content axis, and cannot yet transfer OUT of one: the measured + // value does not exist until after this point, so the other axis takes + // its content size instead. Browsers do transfer from the resolved value. + // TODO: derive the other axis from the measured value after the measure + // pass, then enable the disabled fixture case max_content_with_aspect_ratio + if (childStyle.aspectRatio().isDefined() && !widthIsMaxContent && + !heightIsMaxContent) { if (yoga::isUndefined(childWidth)) { childWidth = marginRow + (childHeight - marginColumn) * childStyle.aspectRatio().unwrap(); @@ -388,7 +404,7 @@ void layoutAbsoluteChild( // to wrap to the size of its owner. This is the same behavior as many // browsers implement. if (!isMainAxisRow && yoga::isUndefined(childWidth) && - widthMode != SizingMode::MaxContent && + !widthIsMaxContent && widthMode != SizingMode::MaxContent && yoga::isDefined(containingBlockWidth) && containingBlockWidth > 0) { childWidth = containingBlockWidth; childWidthSizingMode = SizingMode::FitContent; diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 4e7930a92b..1c76ea644b 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -257,6 +257,7 @@ static void computeFlexBasisForChild( const FloatOptional resolvedFlexBasis = child->resolveFlexBasis( direction, mainAxis, mainAxisOwnerSize, ownerWidth); + const bool flexBasisIsMaxContent = child->processFlexBasis().isMaxContent(); const bool isRowStyleDimDefined = child->hasDefiniteLength(Dimension::Width, ownerWidth); const bool isColumnStyleDimDefined = @@ -279,7 +280,7 @@ static void computeFlexBasisForChild( child->setLayoutComputedFlexBasis( yoga::maxOrDefined(resolvedFlexBasis, paddingAndBorder)); } - } else if (isMainAxisRow && isRowStyleDimDefined) { + } else if (isMainAxisRow && isRowStyleDimDefined && !flexBasisIsMaxContent) { // The width is definite, so use that as the flex basis. const FloatOptional paddingAndBorder = FloatOptional(paddingAndBorderForAxis( @@ -290,7 +291,8 @@ static void computeFlexBasisForChild( child->getResolvedDimension( direction, Dimension::Width, ownerWidth, ownerWidth), paddingAndBorder)); - } else if (!isMainAxisRow && isColumnStyleDimDefined) { + } else if ( + !isMainAxisRow && isColumnStyleDimDefined && !flexBasisIsMaxContent) { // The height is definite, so use that as the flex basis. const FloatOptional paddingAndBorder = FloatOptional(paddingAndBorderForAxis( @@ -381,8 +383,16 @@ static void computeFlexBasisForChild( } } + const bool childWidthIsMaxContent = + child->getProcessedDimension(Dimension::Width).isMaxContent() || + (isMainAxisRow && flexBasisIsMaxContent); + const bool childHeightIsMaxContent = + child->getProcessedDimension(Dimension::Height).isMaxContent() || + (!isMainAxisRow && flexBasisIsMaxContent); + // If child has no defined size in the cross axis and is set to stretch, set // the cross axis to be measured exactly with the available inner width + // Prevent stretching if child has max-content sizing in axis const bool hasExactWidth = yoga::isDefined(width) && widthMode == SizingMode::StretchFit; @@ -390,7 +400,7 @@ static void computeFlexBasisForChild( resolveChildAlignment(node, child) == Align::Stretch && childWidthSizingMode != SizingMode::StretchFit; if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && - childWidthStretch) { + childWidthStretch && !childWidthIsMaxContent) { childWidth = width; childWidthSizingMode = SizingMode::StretchFit; if (childStyle.aspectRatio().isDefined()) { @@ -406,7 +416,7 @@ static void computeFlexBasisForChild( resolveChildAlignment(node, child) == Align::Stretch && childHeightSizingMode != SizingMode::StretchFit; if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && - childHeightStretch) { + childHeightStretch && !childHeightIsMaxContent) { childHeight = height; childHeightSizingMode = SizingMode::StretchFit; @@ -417,6 +427,15 @@ static void computeFlexBasisForChild( } } + if (childWidthIsMaxContent) { + childWidth = YGUndefined; + childWidthSizingMode = SizingMode::MaxContent; + } + if (childHeightIsMaxContent) { + childHeight = YGUndefined; + childHeightSizingMode = SizingMode::MaxContent; + } + constrainMaxSizeForMode( child, direction, @@ -1161,7 +1180,33 @@ static float distributeFreeSpaceSecondPass( SizingMode childMainSizingMode = SizingMode::StretchFit; const auto& childStyle = currentLineChild->style(); - if (childStyle.aspectRatio().isDefined()) { + const bool childCrossIsMaxContent = + currentLineChild->getProcessedDimension(dimension(crossAxis)) + .isMaxContent(); + if (childCrossIsMaxContent) { + // A max-content cross size resolves to the box's measured max-content + // size, regardless of available space or stretch alignment. Measure + // first, then lay out below with the result as a definite size, so + // descendants resolve percentages against the resolved size. + calculateLayoutInternal( + currentLineChild, + isMainAxisRow ? childMainSize : YGUndefined, + isMainAxisRow ? YGUndefined : childMainSize, + direction, + isMainAxisRow ? SizingMode::StretchFit : SizingMode::MaxContent, + isMainAxisRow ? SizingMode::MaxContent : SizingMode::StretchFit, + availableInnerWidth, + availableInnerHeight, + false, + LayoutPassReason::kFlexMeasure, + layoutMarkerData, + depth, + generationCount); + childCrossSize = currentLineChild->getLayout().measuredDimension( + dimension(crossAxis)) + + marginCross; + childCrossSizingMode = SizingMode::StretchFit; + } else if (childStyle.aspectRatio().isDefined()) { childCrossSize = isMainAxisRow ? (childMainSize - marginMain) / childStyle.aspectRatio().unwrap() : (childMainSize - marginMain) * childStyle.aspectRatio().unwrap(); @@ -1222,7 +1267,7 @@ static float distributeFreeSpaceSecondPass( &childCrossSizingMode, &childCrossSize); - const bool requiresStretchLayout = + const bool requiresStretchLayout = !childCrossIsMaxContent && !currentLineChild->hasDefiniteLength( dimension(crossAxis), availableInnerCrossDim) && resolveChildAlignment(node, currentLineChild) == Align::Stretch && @@ -2154,10 +2199,12 @@ static void calculateLayoutImpl( if (alignItem == Align::Stretch && !child->style().flexStartMarginIsAuto(crossAxis, direction) && !child->style().flexEndMarginIsAuto(crossAxis, direction)) { - // If the child defines a definite size for its cross axis, there's - // no need to stretch. + // If the child defines a definite size for its cross axis, or asks + // for its max-content size there, there's no need to stretch. if (!child->hasDefiniteLength( - dimension(crossAxis), availableInnerCrossDim)) { + dimension(crossAxis), availableInnerCrossDim) && + !child->getProcessedDimension(dimension(crossAxis)) + .isMaxContent()) { float childMainSize = child->getLayout().measuredDimension(dimension(mainAxis)); const auto& childStyle = child->style(); @@ -2423,9 +2470,12 @@ static void calculateLayoutImpl( flexStartEdge(crossAxis)); // Remeasure child with the line height as it as been only - // measured with the owners height yet. + // measured with the owners height yet. Skip children asking + // for their max-content size: they never stretch to the line. if (!child->hasDefiniteLength( - dimension(crossAxis), availableInnerCrossDim)) { + dimension(crossAxis), availableInnerCrossDim) && + !child->getProcessedDimension(dimension(crossAxis)) + .isMaxContent()) { const float childWidth = isMainAxisRow ? (child->getLayout().measuredDimension(Dimension::Width) + child->style().computeMarginForAxis( @@ -2861,10 +2911,18 @@ void calculateLayout( gCurrentGenerationCount.fetch_add(1, std::memory_order_relaxed) + 1; node->processDimensions(); const Direction direction = node->resolveDirection(ownerDirection); + const bool rootWidthIsMaxContent = + node->getProcessedDimension(Dimension::Width).isMaxContent(); + const bool rootHeightIsMaxContent = + node->getProcessedDimension(Dimension::Height).isMaxContent(); + float width = YGUndefined; SizingMode widthSizingMode = SizingMode::MaxContent; const auto& style = node->style(); - if (node->hasDefiniteLength(Dimension::Width, ownerWidth)) { + if (rootWidthIsMaxContent) { + width = YGUndefined; + widthSizingMode = SizingMode::MaxContent; + } else if (node->hasDefiniteLength(Dimension::Width, ownerWidth)) { width = (node->getResolvedDimension( direction, @@ -2891,7 +2949,10 @@ void calculateLayout( float height = YGUndefined; SizingMode heightSizingMode = SizingMode::MaxContent; - if (node->hasDefiniteLength(Dimension::Height, ownerHeight)) { + if (rootHeightIsMaxContent) { + height = YGUndefined; + heightSizingMode = SizingMode::MaxContent; + } else if (node->hasDefiniteLength(Dimension::Height, ownerHeight)) { height = (node->getResolvedDimension( direction, @@ -2920,6 +2981,58 @@ void calculateLayout( ExperimentalFeature::FixFlexBasisFitContent) ? currentGenerationCount : gCurrentGenerationCount.load(std::memory_order_relaxed); + + // A max-content root is measured first, then laid out at the measured, min/max clamped size, so + // descendants resolve percentages against it and wrap within it. + if (rootWidthIsMaxContent || rootHeightIsMaxContent) { + calculateLayoutInternal( + node, + width, + height, + ownerDirection, + widthSizingMode, + heightSizingMode, + ownerWidth, + ownerHeight, + false, + LayoutPassReason::kMeasureChild, + markerData, + 0, // tree root + generationCount); + if (rootWidthIsMaxContent) { + width = node->getLayout().measuredDimension(Dimension::Width) + + style.computeMarginForAxis(FlexDirection::Row, ownerWidth); + widthSizingMode = SizingMode::StretchFit; + // width: max-content; height: max-content; max-width: 100, + // A min/max clamp on the width changes wrapping, and with it the + // content height. Re-measure the height at the resolved width before + // freezing it + if (rootHeightIsMaxContent && + (style.minDimension(Dimension::Width).isDefined() || + style.maxDimension(Dimension::Width).isDefined())) { + calculateLayoutInternal( + node, + width, + height, + ownerDirection, + widthSizingMode, + heightSizingMode, + ownerWidth, + ownerHeight, + false, + LayoutPassReason::kMeasureChild, + markerData, + 0, // tree root + generationCount); + } + } + if (rootHeightIsMaxContent) { + height = node->getLayout().measuredDimension(Dimension::Height) + + style.computeMarginForAxis(FlexDirection::Column, ownerWidth); + heightSizingMode = SizingMode::StretchFit; + } + } + if (calculateLayoutInternal( node, width,