From 5e7779c42409a71a48ae20cd9ebbfa50a34a0560 Mon Sep 17 00:00:00 2001 From: Soe Lynn Date: Mon, 15 Apr 2024 13:32:33 -0700 Subject: [PATCH] Implement Percentage support for gap styles (#1643) Summary: X-link: https://github.com/facebook/react-native/pull/44067 X-link: https://github.com/facebook/litho/pull/980 Changelog [Internal]: - Added percentage value for flex layout gap - Wired up to pass proper available width and height to implement this feature Reviewed By: NickGerleman Differential Revision: D56002340 --- gentest/fixtures/YGGapTest.html | 69 ++ java/com/facebook/yoga/YogaNative.java | 1 + java/com/facebook/yoga/YogaNode.java | 2 + java/com/facebook/yoga/YogaNodeJNIBase.java | 5 + java/jni/YGJNIVanilla.cpp | 15 + java/tests/com/facebook/yoga/YGGapTest.java | 921 +++++++++++++++++- javascript/src/Node.cpp | 4 + javascript/src/Node.h | 1 + javascript/src/embind.cpp | 1 + javascript/src/wrapAssembly.ts | 4 +- javascript/tests/generated/YGGapTest.test.ts | 965 ++++++++++++++++++- tests/StyleTest.cpp | 2 +- tests/generated/YGGapTest.cpp | 931 +++++++++++++++++- yoga/YGNodeStyle.cpp | 5 + yoga/YGNodeStyle.h | 2 + yoga/algorithm/CalculateLayout.cpp | 9 +- yoga/algorithm/FlexLine.cpp | 3 +- yoga/style/Style.h | 6 +- 18 files changed, 2933 insertions(+), 13 deletions(-) diff --git a/gentest/fixtures/YGGapTest.html b/gentest/fixtures/YGGapTest.html index e714265953..9f18bbc1b7 100644 --- a/gentest/fixtures/YGGapTest.html +++ b/gentest/fixtures/YGGapTest.html @@ -171,3 +171,72 @@
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+
+
+ +
+
+
+
+
+ +
+
+
+
+
+ + +
+
+
+
+
+
+
diff --git a/java/com/facebook/yoga/YogaNative.java b/java/com/facebook/yoga/YogaNative.java index 9be9edcf87..363e85f584 100644 --- a/java/com/facebook/yoga/YogaNative.java +++ b/java/com/facebook/yoga/YogaNative.java @@ -108,6 +108,7 @@ public class YogaNative { static native void jni_YGNodeStyleSetAspectRatioJNI(long nativePointer, float aspectRatio); static native float jni_YGNodeStyleGetGapJNI(long nativePointer, int gutter); static native void jni_YGNodeStyleSetGapJNI(long nativePointer, int gutter, float gapLength); + static native void jni_YGNodeStyleSetGapPercentJNI(long nativePointer, int gutter, float gapLength); static native void jni_YGNodeSetHasMeasureFuncJNI(long nativePointer, boolean hasMeasureFunc); static native void jni_YGNodeSetHasBaselineFuncJNI(long nativePointer, boolean hasMeasureFunc); static native void jni_YGNodeSetStyleInputsJNI(long nativePointer, float[] styleInputsArray, int size); diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 4875ac3e8c..97ad8ac2c2 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -192,6 +192,8 @@ public interface Inputs { public abstract void setGap(YogaGutter gutter, float gapLength); + public abstract void setGapPercent(YogaGutter gutter, float gapLength); + public abstract float getLayoutX(); public abstract float getLayoutY(); diff --git a/java/com/facebook/yoga/YogaNodeJNIBase.java b/java/com/facebook/yoga/YogaNodeJNIBase.java index df958df166..2f3c446c34 100644 --- a/java/com/facebook/yoga/YogaNodeJNIBase.java +++ b/java/com/facebook/yoga/YogaNodeJNIBase.java @@ -721,4 +721,9 @@ public float getGap(YogaGutter gutter) { public void setGap(YogaGutter gutter, float gapLength) { YogaNative.jni_YGNodeStyleSetGapJNI(mNativePointer, gutter.intValue(), gapLength); } + + @Override + public void setGapPercent(YogaGutter gutter, float gapLength) { + YogaNative.jni_YGNodeStyleSetGapPercentJNI(mNativePointer, gutter.intValue(), gapLength); + } } diff --git a/java/jni/YGJNIVanilla.cpp b/java/jni/YGJNIVanilla.cpp index 82e0dc17b1..4d017037b4 100644 --- a/java/jni/YGJNIVanilla.cpp +++ b/java/jni/YGJNIVanilla.cpp @@ -715,6 +715,18 @@ static void jni_YGNodeStyleSetGapJNI( static_cast(gapLength)); } +static void jni_YGNodeStyleSetGapPercentJNI( + JNIEnv* /*env*/, + jobject /*obj*/, + jlong nativePointer, + jint gutter, + jfloat gapLength) { + YGNodeStyleSetGapPercent( + _jlong2YGNodeRef(nativePointer), + static_cast(gutter), + static_cast(gapLength)); +} + // Yoga specific properties, not compatible with flexbox specification YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio); @@ -944,6 +956,9 @@ static JNINativeMethod methods[] = { (void*)jni_YGNodeSetHasMeasureFuncJNI}, {"jni_YGNodeStyleGetGapJNI", "(JI)F", (void*)jni_YGNodeStyleGetGapJNI}, {"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*)jni_YGNodeStyleSetGapJNI}, + {"jni_YGNodeStyleSetGapPercentJNI", + "(JIF)V", + (void*)jni_YGNodeStyleSetGapPercentJNI}, {"jni_YGNodeSetHasBaselineFuncJNI", "(JZ)V", (void*)jni_YGNodeSetHasBaselineFuncJNI}, diff --git a/java/tests/com/facebook/yoga/YGGapTest.java b/java/tests/com/facebook/yoga/YGGapTest.java index 17e7ae079f..7124cfb6c9 100644 --- a/java/tests/com/facebook/yoga/YGGapTest.java +++ b/java/tests/com/facebook/yoga/YGGapTest.java @@ -4,7 +4,7 @@ * 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 SignedSource<> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGGapTest.html */ @@ -2216,6 +2216,925 @@ public void test_row_gap_determines_parent_height() { assertEquals(30f, root_child2.getLayoutHeight(), 0.0f); } + @Test + public void test_row_gap_percent_wrapping() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setPadding(YogaEdge.LEFT, 10); + root.setPadding(YogaEdge.TOP, 10); + root.setPadding(YogaEdge.RIGHT, 10); + root.setPadding(YogaEdge.BOTTOM, 10); + root.setWidth(300f); + root.setHeight(700f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_determines_parent_height() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setWidth(300f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child3.getLayoutX(), 0.0f); + assertEquals(100f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child4.getLayoutX(), 0.0f); + assertEquals(200f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child3.getLayoutX(), 0.0f); + assertEquals(100f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child4.getLayoutX(), 0.0f); + assertEquals(200f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_both_content_padding_and_item_padding() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setPadding(YogaEdge.LEFT, 10); + root.setPadding(YogaEdge.TOP, 10); + root.setPadding(YogaEdge.RIGHT, 10); + root.setPadding(YogaEdge.BOTTOM, 10); + root.setWidth(300f); + root.setHeight(700f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPadding(YogaEdge.LEFT, 10); + root_child0.setPadding(YogaEdge.TOP, 10); + root_child0.setPadding(YogaEdge.RIGHT, 10); + root_child0.setPadding(YogaEdge.BOTTOM, 10); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setPadding(YogaEdge.LEFT, 10); + root_child1.setPadding(YogaEdge.TOP, 10); + root_child1.setPadding(YogaEdge.RIGHT, 10); + root_child1.setPadding(YogaEdge.BOTTOM, 10); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setPadding(YogaEdge.LEFT, 10); + root_child2.setPadding(YogaEdge.TOP, 10); + root_child2.setPadding(YogaEdge.RIGHT, 10); + root_child2.setPadding(YogaEdge.BOTTOM, 10); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setPadding(YogaEdge.LEFT, 10); + root_child3.setPadding(YogaEdge.TOP, 10); + root_child3.setPadding(YogaEdge.RIGHT, 10); + root_child3.setPadding(YogaEdge.BOTTOM, 10); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setPadding(YogaEdge.LEFT, 10); + root_child4.setPadding(YogaEdge.TOP, 10); + root_child4.setPadding(YogaEdge.RIGHT, 10); + root_child4.setPadding(YogaEdge.BOTTOM, 10); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_both_content_padding() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setPadding(YogaEdge.LEFT, 10); + root.setPadding(YogaEdge.TOP, 10); + root.setPadding(YogaEdge.RIGHT, 10); + root.setPadding(YogaEdge.BOTTOM, 10); + root.setWidth(300f); + root.setHeight(700f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_content_margin() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setMargin(YogaEdge.LEFT, 10f); + root.setMargin(YogaEdge.TOP, 10f); + root.setMargin(YogaEdge.RIGHT, 10f); + root.setMargin(YogaEdge.BOTTOM, 10f); + root.setWidth(300f); + root.setHeight(700f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(10f, root.getLayoutX(), 0.0f); + assertEquals(10f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, 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(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(170f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child3.getLayoutX(), 0.0f); + assertEquals(170f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child4.getLayoutX(), 0.0f); + assertEquals(340f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(10f, root.getLayoutX(), 0.0f); + assertEquals(10f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, 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(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child2.getLayoutX(), 0.0f); + assertEquals(170f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child3.getLayoutX(), 0.0f); + assertEquals(170f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child4.getLayoutX(), 0.0f); + assertEquals(340f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_content_margin_and_padding() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setMargin(YogaEdge.LEFT, 10f); + root.setMargin(YogaEdge.TOP, 10f); + root.setMargin(YogaEdge.RIGHT, 10f); + root.setMargin(YogaEdge.BOTTOM, 10f); + root.setPadding(YogaEdge.LEFT, 10); + root.setPadding(YogaEdge.TOP, 10); + root.setPadding(YogaEdge.RIGHT, 10); + root.setPadding(YogaEdge.BOTTOM, 10); + root.setWidth(300f); + root.setHeight(700f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(10f, root.getLayoutX(), 0.0f); + assertEquals(10f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(138f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(10f, root.getLayoutX(), 0.0f); + assertEquals(10f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(700f, root.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child0.getLayoutX(), 0.0f); + assertEquals(10f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child1.getLayoutX(), 0.0f); + assertEquals(10f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child2.getLayoutX(), 0.0f); + assertEquals(178f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(62f, root_child3.getLayoutX(), 0.0f); + assertEquals(178f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(190f, root_child4.getLayoutX(), 0.0f); + assertEquals(346f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_flexible_content() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(300f); + root.setHeight(300f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setFlexGrow(1f); + root_child0.setFlexShrink(1f); + root_child0.setFlexBasisPercent(0f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setFlexGrow(1f); + root_child1.setFlexShrink(1f); + root_child1.setFlexBasisPercent(0f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setFlexGrow(1f); + root_child2.setFlexShrink(1f); + root_child2.setFlexBasisPercent(0f); + 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(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(80f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(110f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(220f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(80f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(300f, 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(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(220f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(80f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(110f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(80f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(80f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child2.getLayoutHeight(), 0.0f); + } + + @Test + public void test_row_gap_percent_wrapping_with_mixed_flexible_content() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(300f); + root.setHeight(300f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(10f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setFlexGrow(1f); + root_child1.setFlexShrink(1f); + root_child1.setFlexBasisPercent(0f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidthPercent(10f); + root.addChildAt(root_child2, 2); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(40f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(270f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(30f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(300f, 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(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, 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(300f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(60f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(200f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(0f, root_child2.getLayoutY(), 0.0f); + assertEquals(30f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(300f, root_child2.getLayoutHeight(), 0.0f); + } + + @Test + @Ignore + public void test_row_gap_percent_wrapping_with_min_width() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setFlexDirection(YogaFlexDirection.ROW); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWrap(YogaWrap.WRAP); + root.setMinWidth(300f); + root.setGapPercent(YogaGutter.COLUMN, 10f); + root.setGapPercent(YogaGutter.ROW, 10f); + + final YogaNode root_child0 = createNode(config); + root_child0.setWidth(100f); + root_child0.setHeight(100f); + root.addChildAt(root_child0, 0); + + final YogaNode root_child1 = createNode(config); + root_child1.setWidth(100f); + root_child1.setHeight(100f); + root.addChildAt(root_child1, 1); + + final YogaNode root_child2 = createNode(config); + root_child2.setWidth(100f); + root_child2.setHeight(100f); + root.addChildAt(root_child2, 2); + + final YogaNode root_child3 = createNode(config); + root_child3.setWidth(100f); + root_child3.setHeight(100f); + root.addChildAt(root_child3, 3); + + final YogaNode root_child4 = createNode(config); + root_child4.setWidth(100f); + root_child4.setHeight(100f); + root.addChildAt(root_child4, 4); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(130f, root_child3.getLayoutX(), 0.0f); + assertEquals(100f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child4.getLayoutX(), 0.0f); + assertEquals(200f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(300f, root.getLayoutWidth(), 0.0f); + assertEquals(300f, root.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(100f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child0.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child1.getLayoutX(), 0.0f); + assertEquals(0f, root_child1.getLayoutY(), 0.0f); + assertEquals(100f, root_child1.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child1.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child2.getLayoutX(), 0.0f); + assertEquals(100f, root_child2.getLayoutY(), 0.0f); + assertEquals(100f, root_child2.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child2.getLayoutHeight(), 0.0f); + + assertEquals(70f, root_child3.getLayoutX(), 0.0f); + assertEquals(100f, root_child3.getLayoutY(), 0.0f); + assertEquals(100f, root_child3.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child3.getLayoutHeight(), 0.0f); + + assertEquals(200f, root_child4.getLayoutX(), 0.0f); + assertEquals(200f, root_child4.getLayoutY(), 0.0f); + assertEquals(100f, root_child4.getLayoutWidth(), 0.0f); + assertEquals(100f, root_child4.getLayoutHeight(), 0.0f); + } + private YogaNode createNode(YogaConfig config) { return mNodeFactory.create(config); } diff --git a/javascript/src/Node.cpp b/javascript/src/Node.cpp index 06ca672cdc..e8bcaf6e53 100644 --- a/javascript/src/Node.cpp +++ b/javascript/src/Node.cpp @@ -240,6 +240,10 @@ void Node::setGap(int gutter, double gapLength) { YGNodeStyleSetGap(m_node, static_cast(gutter), gapLength); } +void Node::setGapPercent(int gutter, double gapLength) { + YGNodeStyleSetGapPercent(m_node, static_cast(gutter), gapLength); +} + int Node::getPositionType(void) const { return YGNodeStyleGetPositionType(m_node); } diff --git a/javascript/src/Node.h b/javascript/src/Node.h index 57494db275..f5cb7a34e6 100644 --- a/javascript/src/Node.h +++ b/javascript/src/Node.h @@ -124,6 +124,7 @@ class Node { void setPaddingPercent(int edge, double padding); void setGap(int gutter, double gapLength); + void setGapPercent(int gutter, double gapLength); public: // Style getters int getPositionType(void) const; diff --git a/javascript/src/embind.cpp b/javascript/src/embind.cpp index 5ed4807ba4..b8e1bbcb9b 100644 --- a/javascript/src/embind.cpp +++ b/javascript/src/embind.cpp @@ -116,6 +116,7 @@ EMSCRIPTEN_BINDINGS(YOGA_LAYOUT) { .function("setPadding", &Node::setPadding) .function("setPaddingPercent", &Node::setPaddingPercent) .function("setGap", &Node::setGap) + .function("setGapPercent", &Node::setGapPercent) .function("setDirection", &Node::setDirection) diff --git a/javascript/src/wrapAssembly.ts b/javascript/src/wrapAssembly.ts index 797a42c7d7..bc6c7c546b 100644 --- a/javascript/src/wrapAssembly.ts +++ b/javascript/src/wrapAssembly.ts @@ -144,7 +144,8 @@ export type Node = { setHeightAuto(): void; setHeightPercent(height: number | undefined): void; setJustifyContent(justifyContent: Justify): void; - setGap(gutter: Gutter, gapLength: number | undefined): Value; + setGap(gutter: Gutter, gapLength: number | `${number}%` | undefined): Value; + setGapPercent(gutter: Gutter, gapLength: number | undefined): Value; setMargin( edge: Edge, margin: number | 'auto' | `${number}%` | undefined, @@ -209,6 +210,7 @@ export default function wrapAssembly(lib: any): Yoga { 'setMaxWidth', 'setMaxHeight', 'setPadding', + 'setGap', ]) { const methods = { [Unit.Point]: lib.Node.prototype[fnName], diff --git a/javascript/tests/generated/YGGapTest.test.ts b/javascript/tests/generated/YGGapTest.test.ts index d40fe15fcd..1a1604f028 100644 --- a/javascript/tests/generated/YGGapTest.test.ts +++ b/javascript/tests/generated/YGGapTest.test.ts @@ -4,7 +4,7 @@ * 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 SignedSource<> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGGapTest.html */ @@ -2336,3 +2336,966 @@ test('row_gap_determines_parent_height', () => { config.free(); } }); +test('row_gap_percent_wrapping', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setPadding(Edge.Left, 10); + root.setPadding(Edge.Top, 10); + root.setPadding(Edge.Right, 10); + root.setPadding(Edge.Bottom, 10); + root.setWidth(300); + root.setHeight(700); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + 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(700); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(138); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(10); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(138); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(10); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + 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(700); + + expect(root_child0.getComputedLeft()).toBe(190); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(62); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(190); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(62); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(190); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_determines_parent_height', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setWidth(300); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + 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(300); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(130); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(130); + expect(root_child3.getComputedTop()).toBe(100); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(0); + expect(root_child4.getComputedTop()).toBe(200); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + 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(300); + + expect(root_child0.getComputedLeft()).toBe(200); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(70); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(200); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(70); + expect(root_child3.getComputedTop()).toBe(100); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(200); + expect(root_child4.getComputedTop()).toBe(200); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_both_content_padding_and_item_padding', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setPadding(Edge.Left, 10); + root.setPadding(Edge.Top, 10); + root.setPadding(Edge.Right, 10); + root.setPadding(Edge.Bottom, 10); + root.setWidth(300); + root.setHeight(700); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPadding(Edge.Left, 10); + root_child0.setPadding(Edge.Top, 10); + root_child0.setPadding(Edge.Right, 10); + root_child0.setPadding(Edge.Bottom, 10); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setPadding(Edge.Left, 10); + root_child1.setPadding(Edge.Top, 10); + root_child1.setPadding(Edge.Right, 10); + root_child1.setPadding(Edge.Bottom, 10); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setPadding(Edge.Left, 10); + root_child2.setPadding(Edge.Top, 10); + root_child2.setPadding(Edge.Right, 10); + root_child2.setPadding(Edge.Bottom, 10); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setPadding(Edge.Left, 10); + root_child3.setPadding(Edge.Top, 10); + root_child3.setPadding(Edge.Right, 10); + root_child3.setPadding(Edge.Bottom, 10); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setPadding(Edge.Left, 10); + root_child4.setPadding(Edge.Top, 10); + root_child4.setPadding(Edge.Right, 10); + root_child4.setPadding(Edge.Bottom, 10); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + 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(700); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(138); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(10); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(138); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(10); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + 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(700); + + expect(root_child0.getComputedLeft()).toBe(190); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(62); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(190); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(62); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(190); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_both_content_padding', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setPadding(Edge.Left, 10); + root.setPadding(Edge.Top, 10); + root.setPadding(Edge.Right, 10); + root.setPadding(Edge.Bottom, 10); + root.setWidth(300); + root.setHeight(700); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + 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(700); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(138); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(10); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(138); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(10); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + 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(700); + + expect(root_child0.getComputedLeft()).toBe(190); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(62); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(190); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(62); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(190); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_content_margin', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setMargin(Edge.Left, 10); + root.setMargin(Edge.Top, 10); + root.setMargin(Edge.Right, 10); + root.setMargin(Edge.Bottom, 10); + root.setWidth(300); + root.setHeight(700); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(10); + expect(root.getComputedTop()).toBe(10); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(700); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(130); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(170); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(130); + expect(root_child3.getComputedTop()).toBe(170); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(0); + expect(root_child4.getComputedTop()).toBe(340); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(10); + expect(root.getComputedTop()).toBe(10); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(700); + + expect(root_child0.getComputedLeft()).toBe(200); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(70); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(200); + expect(root_child2.getComputedTop()).toBe(170); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(70); + expect(root_child3.getComputedTop()).toBe(170); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(200); + expect(root_child4.getComputedTop()).toBe(340); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_content_margin_and_padding', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setMargin(Edge.Left, 10); + root.setMargin(Edge.Top, 10); + root.setMargin(Edge.Right, 10); + root.setMargin(Edge.Bottom, 10); + root.setPadding(Edge.Left, 10); + root.setPadding(Edge.Top, 10); + root.setPadding(Edge.Right, 10); + root.setPadding(Edge.Bottom, 10); + root.setWidth(300); + root.setHeight(700); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(10); + expect(root.getComputedTop()).toBe(10); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(700); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(138); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(10); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(138); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(10); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(10); + expect(root.getComputedTop()).toBe(10); + expect(root.getComputedWidth()).toBe(300); + expect(root.getComputedHeight()).toBe(700); + + expect(root_child0.getComputedLeft()).toBe(190); + expect(root_child0.getComputedTop()).toBe(10); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(62); + expect(root_child1.getComputedTop()).toBe(10); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(190); + expect(root_child2.getComputedTop()).toBe(178); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(62); + expect(root_child3.getComputedTop()).toBe(178); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(190); + expect(root_child4.getComputedTop()).toBe(346); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_flexible_content', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setWidth(300); + root.setHeight(300); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setFlexGrow(1); + root_child0.setFlexShrink(1); + root_child0.setFlexBasis("0%"); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setFlexGrow(1); + root_child1.setFlexShrink(1); + root_child1.setFlexBasis("0%"); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setFlexGrow(1); + root_child2.setFlexShrink(1); + root_child2.setFlexBasis("0%"); + 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(300); + expect(root.getComputedHeight()).toBe(300); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(80); + expect(root_child0.getComputedHeight()).toBe(300); + + expect(root_child1.getComputedLeft()).toBe(110); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(80); + expect(root_child1.getComputedHeight()).toBe(300); + + expect(root_child2.getComputedLeft()).toBe(220); + expect(root_child2.getComputedTop()).toBe(0); + expect(root_child2.getComputedWidth()).toBe(80); + expect(root_child2.getComputedHeight()).toBe(300); + + 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(300); + + expect(root_child0.getComputedLeft()).toBe(220); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(80); + expect(root_child0.getComputedHeight()).toBe(300); + + expect(root_child1.getComputedLeft()).toBe(110); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(80); + expect(root_child1.getComputedHeight()).toBe(300); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(0); + expect(root_child2.getComputedWidth()).toBe(80); + expect(root_child2.getComputedHeight()).toBe(300); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('row_gap_percent_wrapping_with_mixed_flexible_content', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setWidth(300); + root.setHeight(300); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(10); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setFlexGrow(1); + root_child1.setFlexShrink(1); + root_child1.setFlexBasis("0%"); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth("10%"); + 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(300); + expect(root.getComputedHeight()).toBe(300); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(300); + + expect(root_child1.getComputedLeft()).toBe(40); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(200); + expect(root_child1.getComputedHeight()).toBe(300); + + expect(root_child2.getComputedLeft()).toBe(270); + expect(root_child2.getComputedTop()).toBe(0); + expect(root_child2.getComputedWidth()).toBe(30); + expect(root_child2.getComputedHeight()).toBe(300); + + 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(300); + + expect(root_child0.getComputedLeft()).toBe(290); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(300); + + expect(root_child1.getComputedLeft()).toBe(60); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(200); + expect(root_child1.getComputedHeight()).toBe(300); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(0); + expect(root_child2.getComputedWidth()).toBe(30); + expect(root_child2.getComputedHeight()).toBe(300); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test.skip('row_gap_percent_wrapping_with_min_width', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setFlexDirection(FlexDirection.Row); + root.setPositionType(PositionType.Absolute); + root.setFlexWrap(Wrap.Wrap); + root.setMinWidth(300); + root.setGap(Gutter.Column, "10%"); + root.setGap(Gutter.Row, "10%"); + + const root_child0 = Yoga.Node.create(config); + root_child0.setWidth(100); + root_child0.setHeight(100); + root.insertChild(root_child0, 0); + + const root_child1 = Yoga.Node.create(config); + root_child1.setWidth(100); + root_child1.setHeight(100); + root.insertChild(root_child1, 1); + + const root_child2 = Yoga.Node.create(config); + root_child2.setWidth(100); + root_child2.setHeight(100); + root.insertChild(root_child2, 2); + + const root_child3 = Yoga.Node.create(config); + root_child3.setWidth(100); + root_child3.setHeight(100); + root.insertChild(root_child3, 3); + + const root_child4 = Yoga.Node.create(config); + root_child4.setWidth(100); + root_child4.setHeight(100); + root.insertChild(root_child4, 4); + 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(300); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(130); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(0); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(130); + expect(root_child3.getComputedTop()).toBe(100); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(0); + expect(root_child4.getComputedTop()).toBe(200); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + + 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(300); + + expect(root_child0.getComputedLeft()).toBe(200); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(100); + expect(root_child0.getComputedHeight()).toBe(100); + + expect(root_child1.getComputedLeft()).toBe(70); + expect(root_child1.getComputedTop()).toBe(0); + expect(root_child1.getComputedWidth()).toBe(100); + expect(root_child1.getComputedHeight()).toBe(100); + + expect(root_child2.getComputedLeft()).toBe(200); + expect(root_child2.getComputedTop()).toBe(100); + expect(root_child2.getComputedWidth()).toBe(100); + expect(root_child2.getComputedHeight()).toBe(100); + + expect(root_child3.getComputedLeft()).toBe(70); + expect(root_child3.getComputedTop()).toBe(100); + expect(root_child3.getComputedWidth()).toBe(100); + expect(root_child3.getComputedHeight()).toBe(100); + + expect(root_child4.getComputedLeft()).toBe(200); + expect(root_child4.getComputedTop()).toBe(200); + expect(root_child4.getComputedWidth()).toBe(100); + expect(root_child4.getComputedHeight()).toBe(100); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); diff --git a/tests/StyleTest.cpp b/tests/StyleTest.cpp index 5a85fe6fc8..4832aeaead 100644 --- a/tests/StyleTest.cpp +++ b/tests/StyleTest.cpp @@ -29,7 +29,7 @@ TEST(Style, computed_border_is_floored) { TEST(Style, computed_gap_is_floored) { yoga::Style style; style.setGap(Gutter::Column, value::points(-1.0f)); - auto gapBetweenColumns = style.computeGapForAxis(FlexDirection::Row); + auto gapBetweenColumns = style.computeGapForAxis(FlexDirection::Row, 0.0); ASSERT_EQ(gapBetweenColumns, 0.0f); } diff --git a/tests/generated/YGGapTest.cpp b/tests/generated/YGGapTest.cpp index 06cb8ae449..433d90c46b 100644 --- a/tests/generated/YGGapTest.cpp +++ b/tests/generated/YGGapTest.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * clang-format off - * @generated SignedSource<<708ff5088d96b0a989669c1d86006e37>> + * @generated SignedSource<<74302d39e18c0539a6a9f75d1dcd3fd3>> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGGapTest.html */ @@ -2225,3 +2225,932 @@ TEST(YogaTest, row_gap_determines_parent_height) { YGConfigFree(config); } + +TEST(YogaTest, row_gap_percent_wrapping) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetPadding(root, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root, YGEdgeTop, 10); + YGNodeStyleSetPadding(root, YGEdgeRight, 10); + YGNodeStyleSetPadding(root, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 700); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_determines_parent_height) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_both_content_padding_and_item_padding) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetPadding(root, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root, YGEdgeTop, 10); + YGNodeStyleSetPadding(root, YGEdgeRight, 10); + YGNodeStyleSetPadding(root, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 700); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPadding(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root_child0, YGEdgeTop, 10); + YGNodeStyleSetPadding(root_child0, YGEdgeRight, 10); + YGNodeStyleSetPadding(root_child0, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetPadding(root_child1, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root_child1, YGEdgeTop, 10); + YGNodeStyleSetPadding(root_child1, YGEdgeRight, 10); + YGNodeStyleSetPadding(root_child1, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetPadding(root_child2, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root_child2, YGEdgeTop, 10); + YGNodeStyleSetPadding(root_child2, YGEdgeRight, 10); + YGNodeStyleSetPadding(root_child2, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetPadding(root_child3, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root_child3, YGEdgeTop, 10); + YGNodeStyleSetPadding(root_child3, YGEdgeRight, 10); + YGNodeStyleSetPadding(root_child3, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetPadding(root_child4, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root_child4, YGEdgeTop, 10); + YGNodeStyleSetPadding(root_child4, YGEdgeRight, 10); + YGNodeStyleSetPadding(root_child4, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_both_content_padding) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetPadding(root, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root, YGEdgeTop, 10); + YGNodeStyleSetPadding(root, YGEdgeRight, 10); + YGNodeStyleSetPadding(root, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 700); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_content_margin) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetMargin(root, YGEdgeLeft, 10); + YGNodeStyleSetMargin(root, YGEdgeTop, 10); + YGNodeStyleSetMargin(root, YGEdgeRight, 10); + YGNodeStyleSetMargin(root, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 700); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, 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(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(170, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(170, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(340, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, 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(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(170, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(170, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(340, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_content_margin_and_padding) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetMargin(root, YGEdgeLeft, 10); + YGNodeStyleSetMargin(root, YGEdgeTop, 10); + YGNodeStyleSetMargin(root, YGEdgeRight, 10); + YGNodeStyleSetMargin(root, YGEdgeBottom, 10); + YGNodeStyleSetPadding(root, YGEdgeLeft, 10); + YGNodeStyleSetPadding(root, YGEdgeTop, 10); + YGNodeStyleSetPadding(root, YGEdgeRight, 10); + YGNodeStyleSetPadding(root, YGEdgeBottom, 10); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 700); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(138, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(700, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(62, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(178, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(190, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(346, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_flexible_content) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 300); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 1); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetFlexBasisPercent(root_child0, 0); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetFlexBasisPercent(root_child1, 0); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child2, 1); + YGNodeStyleSetFlexShrink(root_child2, 1); + YGNodeStyleSetFlexBasisPercent(root_child2, 0); + 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(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(110, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(220, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child2)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(220, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(110, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_mixed_flexible_content) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 300); + YGNodeStyleSetHeight(root, 300); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetFlexBasisPercent(root_child1, 0); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidthPercent(root_child2, 10); + YGNodeInsertChild(root, root_child2, 2); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(40, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(270, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child2)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(290, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(60, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(30, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root_child2)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, row_gap_percent_wrapping_with_min_width) { + GTEST_SKIP(); + + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetFlexWrap(root, YGWrapWrap); + YGNodeStyleSetMinWidth(root, 300); + YGNodeStyleSetGapPercent(root, YGGutterColumn, 10); + YGNodeStyleSetGapPercent(root, YGGutterRow, 10); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child0, 100); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child1, 100); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + + const YGNodeRef root_child2 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child2, 100); + YGNodeStyleSetHeight(root_child2, 100); + YGNodeInsertChild(root, root_child2, 2); + + const YGNodeRef root_child3 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child3, 100); + YGNodeStyleSetHeight(root_child3, 100); + YGNodeInsertChild(root, root_child3, 3); + + const YGNodeRef root_child4 = YGNodeNewWithConfig(config); + YGNodeStyleSetWidth(root_child4, 100); + YGNodeStyleSetHeight(root_child4, 100); + YGNodeInsertChild(root, root_child4, 4); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(130, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(300, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child2)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child2)); + + ASSERT_FLOAT_EQ(70, YGNodeLayoutGetLeft(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetTop(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child3)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child3)); + + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetLeft(root_child4)); + ASSERT_FLOAT_EQ(200, YGNodeLayoutGetTop(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root_child4)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child4)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index d8454053de..d14d70930f 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -267,6 +267,11 @@ void YGNodeStyleSetGap( node, scopedEnum(gutter), value::points(gapLength)); } +void YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float percent) { + updateStyle<&Style::gap, &Style::setGap>( + node, scopedEnum(gutter), value::percent(percent)); +} + float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { auto gapLength = resolveRef(node)->style().gap(scopedEnum(gutter)); if (gapLength.isUndefined() || gapLength.isAuto()) { diff --git a/yoga/YGNodeStyle.h b/yoga/YGNodeStyle.h index 09727087ba..2934194f85 100644 --- a/yoga/YGNodeStyle.h +++ b/yoga/YGNodeStyle.h @@ -89,6 +89,8 @@ YG_EXPORT float YGNodeStyleGetBorder(YGNodeConstRef node, YGEdge edge); YG_EXPORT void YGNodeStyleSetGap(YGNodeRef node, YGGutter gutter, float gapLength); +YG_EXPORT void +YGNodeStyleSetGapPercent(YGNodeRef node, YGGutter gutter, float gapLength); YG_EXPORT float YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter); YG_EXPORT void YGNodeStyleSetWidth(YGNodeRef node, float width); diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 19cf4a2359..62d8a24b76 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -929,7 +929,8 @@ static void justifyMainAxis( node->style().computeFlexEndPaddingAndBorder( mainAxis, direction, ownerWidth); - const float gap = node->style().computeGapForAxis(mainAxis); + const float gap = + node->style().computeGapForAxis(mainAxis, availableInnerMainDim); // If we are using "at most" rules in the main axis, make sure that // remainingFreeSpace is 0 when min main dimension is not given if (sizingModeMainDim == SizingMode::FitContent && @@ -1380,7 +1381,8 @@ static void calculateLayoutImpl( generationCount); if (childCount > 1) { - totalMainDim += node->style().computeGapForAxis(mainAxis) * + totalMainDim += + node->style().computeGapForAxis(mainAxis, availableInnerMainDim) * static_cast(childCount - 1); } @@ -1404,7 +1406,8 @@ static void calculateLayoutImpl( // Accumulated cross dimensions of all lines so far. float totalLineCrossDim = 0; - const float crossAxisGap = node->style().computeGapForAxis(crossAxis); + const float crossAxisGap = + node->style().computeGapForAxis(crossAxis, availableInnerCrossDim); // Max main dimension of all the lines. float maxLineMainDim = 0; diff --git a/yoga/algorithm/FlexLine.cpp b/yoga/algorithm/FlexLine.cpp index 1fe3e48692..50cd6f0abe 100644 --- a/yoga/algorithm/FlexLine.cpp +++ b/yoga/algorithm/FlexLine.cpp @@ -34,7 +34,8 @@ FlexLine calculateFlexLine( const FlexDirection mainAxis = resolveDirection( node->style().flexDirection(), node->resolveDirection(ownerDirection)); const bool isNodeFlexWrap = node->style().flexWrap() != Wrap::NoWrap; - const float gap = node->style().computeGapForAxis(mainAxis); + const float gap = + node->style().computeGapForAxis(mainAxis, availableInnerMainDim); // Add items to the current line until it's full or we run out of items. for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) { diff --git a/yoga/style/Style.h b/yoga/style/Style.h index 113a8e1df1..ac769f1d76 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -428,11 +428,9 @@ class YG_EXPORT Style { computeInlineEndMargin(axis, Direction::LTR, widthSize); } - float computeGapForAxis(FlexDirection axis) const { + float computeGapForAxis(FlexDirection axis, float ownerSize) const { auto gap = isRow(axis) ? computeColumnGap() : computeRowGap(); - // TODO: Validate percentage gap, and expose ability to set percentage to - // public API - return maxOrDefined(gap.resolve(0.0f /*ownerSize*/).unwrap(), 0.0f); + return maxOrDefined(gap.resolve(ownerSize).unwrap(), 0.0f); } bool flexStartMarginIsAuto(FlexDirection axis, Direction direction) const {