diff --git a/gentest/fixtures/YGAbsolutePositionTest.html b/gentest/fixtures/YGAbsolutePositionTest.html index 673d257b8a..c2573995e2 100644 --- a/gentest/fixtures/YGAbsolutePositionTest.html +++ b/gentest/fixtures/YGAbsolutePositionTest.html @@ -2,6 +2,18 @@
+
+
+
+ +
+
+
+ +
+
+
+
diff --git a/gentest/gentest-cpp.js b/gentest/gentest-cpp.js index 8feecac988..b29b8bfe1d 100644 --- a/gentest/gentest-cpp.js +++ b/gentest/gentest-cpp.js @@ -451,6 +451,12 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, { YGNodeStyleSetPosition: { value: function (nodeName, edge, value) { + let valueStr = toValueCpp(value); + if (valueStr != 'YGAuto') { + valueStr = ', ' + valueStr; + } else { + valueStr = ''; + } this.push( 'YGNodeStyleSetPosition' + toFunctionName(value) + @@ -458,8 +464,7 @@ CPPEmitter.prototype = Object.create(Emitter.prototype, { nodeName + ', ' + edge + - ', ' + - toValueCpp(value) + + valueStr + ');', ); }, diff --git a/gentest/gentest-java.js b/gentest/gentest-java.js index 584a22e310..ac0ce0f6ed 100644 --- a/gentest/gentest-java.js +++ b/gentest/gentest-java.js @@ -420,15 +420,21 @@ JavaEmitter.prototype = Object.create(Emitter.prototype, { YGNodeStyleSetPosition: { value: function (nodeName, edge, value) { + let valueStr = toValueJava(value); + + if (valueStr == 'YogaConstants.AUTO') { + valueStr = ''; + } else { + valueStr = ', ' + valueStr + 'f'; + } this.push( nodeName + '.setPosition' + toMethodName(value) + '(' + edge + - ', ' + - toValueJava(value) + - 'f);', + valueStr + + ');', ); }, }, diff --git a/gentest/gentest-javascript.js b/gentest/gentest-javascript.js index 418443daa9..c36cee6bf4 100644 --- a/gentest/gentest-javascript.js +++ b/gentest/gentest-javascript.js @@ -364,14 +364,22 @@ JavascriptEmitter.prototype = Object.create(Emitter.prototype, { YGNodeStyleSetPosition: { value: function (nodeName, edge, value) { - this.push( - nodeName + - '.setPosition(' + - toValueJavascript(edge) + - ', ' + - toValueJavascript(value) + - ');', - ); + const valueStr = toValueJavascript(value); + + if (valueStr == "'auto'") { + this.push( + nodeName + '.setPositionAuto(' + toValueJavascript(edge) + ');', + ); + } else { + this.push( + nodeName + + '.setPosition(' + + toValueJavascript(edge) + + ', ' + + valueStr + + ');', + ); + } }, }, diff --git a/java/com/facebook/yoga/YogaNative.java b/java/com/facebook/yoga/YogaNative.java index 363e85f584..0ab5391331 100644 --- a/java/com/facebook/yoga/YogaNative.java +++ b/java/com/facebook/yoga/YogaNative.java @@ -84,6 +84,7 @@ public class YogaNative { static native long jni_YGNodeStyleGetPositionJNI(long nativePointer, int edge); static native void jni_YGNodeStyleSetPositionJNI(long nativePointer, int edge, float position); static native void jni_YGNodeStyleSetPositionPercentJNI(long nativePointer, int edge, float percent); + static native void jni_YGNodeStyleSetPositionAutoJNI(long nativePointer, int edge); static native long jni_YGNodeStyleGetWidthJNI(long nativePointer); static native void jni_YGNodeStyleSetWidthJNI(long nativePointer, float width); static native void jni_YGNodeStyleSetWidthPercentJNI(long nativePointer, float percent); diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index 97ad8ac2c2..c83b577880 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -144,6 +144,8 @@ public interface Inputs { public abstract void setPositionPercent(YogaEdge edge, float percent); + public abstract void setPositionAuto(YogaEdge edge); + public abstract YogaValue getWidth(); public abstract void setWidth(float width); diff --git a/java/com/facebook/yoga/YogaNodeJNIBase.java b/java/com/facebook/yoga/YogaNodeJNIBase.java index 2f3c446c34..75a318984e 100644 --- a/java/com/facebook/yoga/YogaNodeJNIBase.java +++ b/java/com/facebook/yoga/YogaNodeJNIBase.java @@ -411,6 +411,10 @@ public void setPositionPercent(YogaEdge edge, float percent) { YogaNative.jni_YGNodeStyleSetPositionPercentJNI(mNativePointer, edge.intValue(), percent); } + public void setPositionAuto(YogaEdge edge) { + YogaNative.jni_YGNodeStyleSetPositionAutoJNI(mNativePointer, edge.intValue()); + } + public YogaValue getWidth() { return valueFromLong(YogaNative.jni_YGNodeStyleGetWidthJNI(mNativePointer)); } diff --git a/java/jni/YGJNIVanilla.cpp b/java/jni/YGJNIVanilla.cpp index 4d017037b4..9f4e211bd0 100644 --- a/java/jni/YGJNIVanilla.cpp +++ b/java/jni/YGJNIVanilla.cpp @@ -460,6 +460,14 @@ static void jni_YGNodeCopyStyleJNI( static_cast(value)); \ } +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + static void jni_YGNodeStyleSet##name##AutoJNI( \ + JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer, jint edge) { \ + YGNodeStyleSet##name##Auto( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ + } + YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); YG_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection); YG_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent); @@ -482,7 +490,7 @@ YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height); YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight); YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight); -YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position); +YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(Position); static jlong jni_YGNodeStyleGetMarginJNI( JNIEnv* /*env*/, @@ -891,6 +899,9 @@ static JNINativeMethod methods[] = { {"jni_YGNodeStyleSetPositionPercentJNI", "(JIF)V", (void*)jni_YGNodeStyleSetPositionPercentJNI}, + {"jni_YGNodeStyleSetPositionAutoJNI", + "(JI)V", + (void*)jni_YGNodeStyleSetPositionAutoJNI}, {"jni_YGNodeStyleGetWidthJNI", "(J)J", (void*)jni_YGNodeStyleGetWidthJNI}, {"jni_YGNodeStyleSetWidthJNI", "(JF)V", (void*)jni_YGNodeStyleSetWidthJNI}, {"jni_YGNodeStyleSetWidthPercentJNI", diff --git a/java/tests/generated/com/facebook/yoga/YGAbsolutePositionTest.java b/java/tests/generated/com/facebook/yoga/YGAbsolutePositionTest.java index 38a269e8a7..d8b808e52a 100644 --- a/java/tests/generated/com/facebook/yoga/YGAbsolutePositionTest.java +++ b/java/tests/generated/com/facebook/yoga/YGAbsolutePositionTest.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<<30a9046ab7f9c7bda2d4f3b2ae12afcd>> + * @generated SignedSource<> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGAbsolutePositionTest.html */ @@ -70,6 +70,135 @@ public void test_absolute_layout_width_height_start_top() { assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); } + @Test + public void test_absolute_layout_width_height_left_auto_right() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPositionAuto(YogaEdge.LEFT); + root_child0.setPosition(YogaEdge.RIGHT, 10f); + root_child0.setWidth(10f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(80f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_absolute_layout_width_height_left_right_auto() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPosition(YogaEdge.LEFT, 10f); + root_child0.setPositionAuto(YogaEdge.RIGHT); + root_child0.setWidth(10f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(10f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + } + + @Test + public void test_absolute_layout_width_height_left_auto_right_auto() { + YogaConfig config = YogaConfigFactory.create(); + + final YogaNode root = createNode(config); + root.setPositionType(YogaPositionType.ABSOLUTE); + root.setWidth(100f); + root.setHeight(100f); + + final YogaNode root_child0 = createNode(config); + root_child0.setPositionType(YogaPositionType.ABSOLUTE); + root_child0.setPositionAuto(YogaEdge.LEFT); + root_child0.setPositionAuto(YogaEdge.RIGHT); + root_child0.setWidth(10f); + root_child0.setHeight(10f); + root.addChildAt(root_child0, 0); + root.setDirection(YogaDirection.LTR); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(0f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + + root.setDirection(YogaDirection.RTL); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + + assertEquals(0f, root.getLayoutX(), 0.0f); + assertEquals(0f, root.getLayoutY(), 0.0f); + assertEquals(100f, root.getLayoutWidth(), 0.0f); + assertEquals(100f, root.getLayoutHeight(), 0.0f); + + assertEquals(90f, root_child0.getLayoutX(), 0.0f); + assertEquals(0f, root_child0.getLayoutY(), 0.0f); + assertEquals(10f, root_child0.getLayoutWidth(), 0.0f); + assertEquals(10f, root_child0.getLayoutHeight(), 0.0f); + } + @Test public void test_absolute_layout_width_height_end_bottom() { YogaConfig config = YogaConfigFactory.create(); diff --git a/javascript/src/Node.cpp b/javascript/src/Node.cpp index e8bcaf6e53..57aac36c4e 100644 --- a/javascript/src/Node.cpp +++ b/javascript/src/Node.cpp @@ -87,6 +87,10 @@ void Node::setPositionPercent(int edge, double position) { YGNodeStyleSetPositionPercent(m_node, static_cast(edge), position); } +void Node::setPositionAuto(int edge) { + YGNodeStyleSetPositionAuto(m_node, static_cast(edge)); +} + void Node::setAlignContent(int alignContent) { YGNodeStyleSetAlignContent(m_node, static_cast(alignContent)); } diff --git a/javascript/src/Node.h b/javascript/src/Node.h index f5cb7a34e6..b55b1dfdb3 100644 --- a/javascript/src/Node.h +++ b/javascript/src/Node.h @@ -76,6 +76,7 @@ class Node { void setPositionType(int positionType); void setPosition(int edge, double position); void setPositionPercent(int edge, double position); + void setPositionAuto(int edge); void setAlignContent(int alignContent); void setAlignItems(int alignItems); diff --git a/javascript/src/embind.cpp b/javascript/src/embind.cpp index b8e1bbcb9b..d37ce1b74f 100644 --- a/javascript/src/embind.cpp +++ b/javascript/src/embind.cpp @@ -70,6 +70,7 @@ EMSCRIPTEN_BINDINGS(YOGA_LAYOUT) { .function("setPositionType", &Node::setPositionType) .function("setPosition", &Node::setPosition) .function("setPositionPercent", &Node::setPositionPercent) + .function("setPositionAuto", &Node::setPositionAuto) .function("setAlignContent", &Node::setAlignContent) .function("setAlignItems", &Node::setAlignItems) diff --git a/javascript/src/wrapAssembly.ts b/javascript/src/wrapAssembly.ts index bc6c7c546b..eacecfbfa5 100644 --- a/javascript/src/wrapAssembly.ts +++ b/javascript/src/wrapAssembly.ts @@ -168,6 +168,7 @@ export type Node = { setPosition(edge: Edge, position: number | `${number}%` | undefined): void; setPositionPercent(edge: Edge, position: number | undefined): void; setPositionType(positionType: PositionType): void; + setPositionAuto(edge: Edge): void; setWidth(width: number | 'auto' | `${number}%` | undefined): void; setWidthAuto(): void; setWidthPercent(width: number | undefined): void; diff --git a/javascript/tests/generated/YGAbsolutePositionTest.test.ts b/javascript/tests/generated/YGAbsolutePositionTest.test.ts index 99dc9f8c21..c21771bced 100644 --- a/javascript/tests/generated/YGAbsolutePositionTest.test.ts +++ b/javascript/tests/generated/YGAbsolutePositionTest.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<<133e2d77cd6267d4bfb0fe992d437fd1>> + * @generated SignedSource<<3ac965030750351f007587f3ae1dec10>> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGAbsolutePositionTest.html */ @@ -75,6 +75,150 @@ test('absolute_layout_width_height_start_top', () => { config.free(); } }); +test('absolute_layout_width_height_left_auto_right', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setPositionAuto(Edge.Left); + root_child0.setPosition(Edge.Right, 10); + root_child0.setWidth(10); + root_child0.setHeight(10); + root.insertChild(root_child0, 0); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(80); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(80); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('absolute_layout_width_height_left_right_auto', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setPosition(Edge.Left, 10); + root_child0.setPositionAuto(Edge.Right); + root_child0.setWidth(10); + root_child0.setHeight(10); + root.insertChild(root_child0, 0); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(10); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); +test('absolute_layout_width_height_left_auto_right_auto', () => { + const config = Yoga.Config.create(); + let root; + + try { + root = Yoga.Node.create(config); + root.setPositionType(PositionType.Absolute); + root.setWidth(100); + root.setHeight(100); + + const root_child0 = Yoga.Node.create(config); + root_child0.setPositionType(PositionType.Absolute); + root_child0.setPositionAuto(Edge.Left); + root_child0.setPositionAuto(Edge.Right); + root_child0.setWidth(10); + root_child0.setHeight(10); + root.insertChild(root_child0, 0); + root.calculateLayout(undefined, undefined, Direction.LTR); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(0); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + + root.calculateLayout(undefined, undefined, Direction.RTL); + + expect(root.getComputedLeft()).toBe(0); + expect(root.getComputedTop()).toBe(0); + expect(root.getComputedWidth()).toBe(100); + expect(root.getComputedHeight()).toBe(100); + + expect(root_child0.getComputedLeft()).toBe(90); + expect(root_child0.getComputedTop()).toBe(0); + expect(root_child0.getComputedWidth()).toBe(10); + expect(root_child0.getComputedHeight()).toBe(10); + } finally { + if (typeof root !== 'undefined') { + root.freeRecursive(); + } + + config.free(); + } +}); test('absolute_layout_width_height_end_bottom', () => { const config = Yoga.Config.create(); let root; diff --git a/tests/generated/YGAbsolutePositionTest.cpp b/tests/generated/YGAbsolutePositionTest.cpp index 1cf21edb0e..c3d5302927 100644 --- a/tests/generated/YGAbsolutePositionTest.cpp +++ b/tests/generated/YGAbsolutePositionTest.cpp @@ -5,7 +5,7 @@ * LICENSE file in the root directory of this source tree. * * clang-format off - * @generated SignedSource<<425ef3591b2f5cf0bc6d9daa9c5db96c>> + * @generated SignedSource<<499316b3f7b7ec5c406abf5ac77837f1>> * generated by gentest/gentest-driver.ts from gentest/fixtures/YGAbsolutePositionTest.html */ @@ -57,6 +57,138 @@ TEST(YogaTest, absolute_layout_width_height_start_top) { YGConfigFree(config); } +TEST(YogaTest, absolute_layout_width_height_left_auto_right) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPositionAuto(root_child0, YGEdgeLeft); + YGNodeStyleSetPosition(root_child0, YGEdgeRight, 10); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(80, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, absolute_layout_width_height_left_right_auto) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPosition(root_child0, YGEdgeLeft, 10); + YGNodeStyleSetPositionAuto(root_child0, YGEdgeRight); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, absolute_layout_width_height_left_auto_right_auto) { + YGConfigRef config = YGConfigNew(); + + YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root, YGPositionTypeAbsolute); + YGNodeStyleSetWidth(root, 100); + YGNodeStyleSetHeight(root, 100); + + YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetPositionType(root_child0, YGPositionTypeAbsolute); + YGNodeStyleSetPositionAuto(root_child0, YGEdgeLeft); + YGNodeStyleSetPositionAuto(root_child0, YGEdgeRight); + YGNodeStyleSetWidth(root_child0, 10); + YGNodeStyleSetHeight(root_child0, 10); + YGNodeInsertChild(root, root_child0, 0); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionRTL); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(90, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(10, YGNodeLayoutGetHeight(root_child0)); + + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, absolute_layout_width_height_end_bottom) { YGConfigRef config = YGConfigNew(); diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp index d14d70930f..67e6e42e77 100644 --- a/yoga/YGNodeStyle.cpp +++ b/yoga/YGNodeStyle.cpp @@ -205,6 +205,11 @@ void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { node, scopedEnum(edge), value::percent(percent)); } +void YGNodeStyleSetPositionAuto(YGNodeRef node, YGEdge edge) { + updateStyle<&Style::position, &Style::setPosition>( + node, scopedEnum(edge), value::ofAuto()); +} + YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { return (YGValue)resolveRef(node)->style().position(scopedEnum(edge)); } diff --git a/yoga/YGNodeStyle.h b/yoga/YGNodeStyle.h index 2934194f85..fad71e4f07 100644 --- a/yoga/YGNodeStyle.h +++ b/yoga/YGNodeStyle.h @@ -71,8 +71,10 @@ YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float position); YG_EXPORT void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float position); YG_EXPORT YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge); +YG_EXPORT void YGNodeStyleSetPositionAuto(YGNodeRef node, YGEdge edge); -YG_EXPORT void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin); +YG_EXPORT +void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin); YG_EXPORT void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float margin); YG_EXPORT void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge); diff --git a/yoga/algorithm/AbsoluteLayout.cpp b/yoga/algorithm/AbsoluteLayout.cpp index 26603554ef..b3651b40b6 100644 --- a/yoga/algorithm/AbsoluteLayout.cpp +++ b/yoga/algorithm/AbsoluteLayout.cpp @@ -154,7 +154,8 @@ static void positionAbsoluteChildLegacy( (parent->style().flexWrap() == Wrap::WrapReverse)); if (child->style().isFlexEndPositionDefined(axis, direction) && - !child->style().isFlexStartPositionDefined(axis, direction)) { + (!child->style().isFlexStartPositionDefined(axis, direction) || + child->style().isFlexStartPositionAuto(axis, direction))) { child->setLayoutPosition( containingNode->getLayout().measuredDimension(dimension(axis)) - child->getLayout().measuredDimension(dimension(axis)) - @@ -169,7 +170,8 @@ static void positionAbsoluteChildLegacy( isAxisRow ? containingBlockWidth : containingBlockHeight), flexStartEdge(axis)); } else if ( - !child->style().isFlexStartPositionDefined(axis, direction) && + (!child->style().isFlexStartPositionDefined(axis, direction) || + child->style().isFlexStartPositionAuto(axis, direction)) && shouldCenter) { child->setLayoutPosition( (parent->getLayout().measuredDimension(dimension(axis)) - @@ -177,7 +179,8 @@ static void positionAbsoluteChildLegacy( 2.0f, flexStartEdge(axis)); } else if ( - !child->style().isFlexStartPositionDefined(axis, direction) && + (!child->style().isFlexStartPositionDefined(axis, direction) || + child->style().isFlexStartPositionAuto(axis, direction)) && shouldFlexEnd) { child->setLayoutPosition( (parent->getLayout().measuredDimension(dimension(axis)) - @@ -223,7 +226,8 @@ static void positionAbsoluteChildImpl( // to the flex-start edge because this algorithm works by positioning on the // flex-start edge and then filling in the flex-end direction at the end if // necessary. - if (child->style().isInlineStartPositionDefined(axis, direction)) { + if (child->style().isInlineStartPositionDefined(axis, direction) && + !child->style().isInlineStartPositionAuto(axis, direction)) { const float positionRelativeToInlineStart = child->style().computeInlineStartPosition( axis, direction, containingBlockSize) + @@ -237,7 +241,9 @@ static void positionAbsoluteChildImpl( : positionRelativeToInlineStart; child->setLayoutPosition(positionRelativeToFlexStart, flexStartEdge(axis)); - } else if (child->style().isInlineEndPositionDefined(axis, direction)) { + } else if ( + child->style().isInlineEndPositionDefined(axis, direction) && + !child->style().isInlineEndPositionAuto(axis, direction)) { const float positionRelativeToInlineStart = containingNode->getLayout().measuredDimension(dimension(axis)) - child->getLayout().measuredDimension(dimension(axis)) - @@ -328,7 +334,10 @@ void layoutAbsoluteChild( if (child->style().isFlexStartPositionDefined( FlexDirection::Row, direction) && child->style().isFlexEndPositionDefined( - FlexDirection::Row, direction)) { + FlexDirection::Row, direction) && + !child->style().isFlexStartPositionAuto( + FlexDirection::Row, direction) && + !child->style().isFlexEndPositionAuto(FlexDirection::Row, direction)) { childWidth = containingNode->getLayout().measuredDimension(Dimension::Width) - (containingNode->style().computeFlexStartBorder( @@ -360,6 +369,10 @@ void layoutAbsoluteChild( if (child->style().isFlexStartPositionDefined( FlexDirection::Column, direction) && child->style().isFlexEndPositionDefined( + FlexDirection::Column, direction) && + !child->style().isFlexStartPositionAuto( + FlexDirection::Column, direction) && + !child->style().isFlexEndPositionAuto( FlexDirection::Column, direction)) { childHeight = containingNode->getLayout().measuredDimension(Dimension::Height) - diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index 2cbeac6957..c9c8b00183 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -1059,7 +1059,8 @@ static void justifyMainAxis( continue; } if (childStyle.positionType() == PositionType::Absolute && - child->style().isFlexStartPositionDefined(mainAxis, direction)) { + child->style().isFlexStartPositionDefined(mainAxis, direction) && + !child->style().isFlexStartPositionAuto(mainAxis, direction)) { if (performLayout) { // In case the child is position absolute and has left/top being // defined, we override the position to whatever the user said (and @@ -1629,7 +1630,8 @@ static void calculateLayoutImpl( // top/left/bottom/right set, override all the previously computed // positions to set it correctly. const bool isChildLeadingPosDefined = - child->style().isFlexStartPositionDefined(crossAxis, direction); + child->style().isFlexStartPositionDefined(crossAxis, direction) && + !child->style().isFlexStartPositionAuto(crossAxis, direction); if (isChildLeadingPosDefined) { child->setLayoutPosition( child->style().computeFlexStartPosition( diff --git a/yoga/node/Node.cpp b/yoga/node/Node.cpp index f1f9633901..eb10f15267 100644 --- a/yoga/node/Node.cpp +++ b/yoga/node/Node.cpp @@ -226,7 +226,8 @@ float Node::relativePosition( if (style_.positionType() == PositionType::Static) { return 0; } - if (style_.isInlineStartPositionDefined(axis, direction)) { + if (style_.isInlineStartPositionDefined(axis, direction) && + !style_.isInlineStartPositionAuto(axis, direction)) { return style_.computeInlineStartPosition(axis, direction, axisSize); } diff --git a/yoga/style/Style.h b/yoga/style/Style.h index ac769f1d76..c8cbe56eb9 100644 --- a/yoga/style/Style.h +++ b/yoga/style/Style.h @@ -223,22 +223,40 @@ class YG_EXPORT Style { return computePosition(flexStartEdge(axis), direction).isDefined(); } + bool isFlexStartPositionAuto(FlexDirection axis, Direction direction) const { + return computePosition(flexStartEdge(axis), direction).isAuto(); + } + bool isInlineStartPositionDefined(FlexDirection axis, Direction direction) const { return computePosition(inlineStartEdge(axis, direction), direction) .isDefined(); } + bool isInlineStartPositionAuto(FlexDirection axis, Direction direction) + const { + return computePosition(inlineStartEdge(axis, direction), direction) + .isAuto(); + } + bool isFlexEndPositionDefined(FlexDirection axis, Direction direction) const { return computePosition(flexEndEdge(axis), direction).isDefined(); } + bool isFlexEndPositionAuto(FlexDirection axis, Direction direction) const { + return computePosition(flexEndEdge(axis), direction).isAuto(); + } + bool isInlineEndPositionDefined(FlexDirection axis, Direction direction) const { return computePosition(inlineEndEdge(axis, direction), direction) .isDefined(); } + bool isInlineEndPositionAuto(FlexDirection axis, Direction direction) const { + return computePosition(inlineEndEdge(axis, direction), direction).isAuto(); + } + float computeFlexStartPosition( FlexDirection axis, Direction direction,