From 3dfb68887db34a8a77e894c66a50e747d831b0b9 Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Wed, 14 Mar 2018 08:37:55 -0700 Subject: [PATCH] Expose layout diffing flag to java Summary: This diff exposes `shouldDiffLayoutWithoutLegacyStretchBehaviour` from YGConfig and `doesLegacyStretchFlagAffectsLayout` from YGLayout to YogaConfig and YogaNode respectively Also added a positive test case. Didn't find the negative test case example. @[508947467:ianc] or @[759512522:emilsj], can you suggest a negative test case example. Reviewed By: emilsjolander Differential Revision: D7272067 fbshipit-source-id: e67e82eb057e4c7124904c715f9dca4dcfea21ea --- java/com/facebook/yoga/YogaConfig.java | 13 +++++ java/com/facebook/yoga/YogaNode.java | 6 +++ java/jni/YGJNI.cpp | 51 +++++++++++++------ .../tests/com/facebook/yoga/YogaNodeTest.java | 24 +++++++++ yoga/Yoga.cpp | 10 ++++ yoga/Yoga.h | 5 +- 6 files changed, 93 insertions(+), 16 deletions(-) diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index e68c5121..2d90eec9 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -74,6 +74,19 @@ public class YogaConfig { jni_YGConfigSetUseLegacyStretchBehaviour(mNativePointer, useLegacyStretchBehaviour); } + private native void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( + long nativePointer, boolean shouldDiffLayoutWithoutLegacyStretchBehaviour); + /** + * If this flag is set then yoga would diff the layout without legacy flag and would set a bool in + * YogaNode(mDoesLegacyStretchFlagAffectsLayout) with true if the layouts were different and false + * if not + */ + public void setShouldDiffLayoutWithoutLegacyStretchBehaviour( + boolean shouldDiffLayoutWithoutLegacyStretchBehaviour) { + jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( + mNativePointer, shouldDiffLayoutWithoutLegacyStretchBehaviour); + } + private native void jni_YGConfigSetLogger(long nativePointer, Object logger); public void setLogger(YogaLogger logger) { mLogger = logger; diff --git a/java/com/facebook/yoga/YogaNode.java b/java/com/facebook/yoga/YogaNode.java index df5fae91..1c6e67a5 100644 --- a/java/com/facebook/yoga/YogaNode.java +++ b/java/com/facebook/yoga/YogaNode.java @@ -82,6 +82,7 @@ public class YogaNode implements Cloneable { private int mLayoutDirection = 0; @DoNotStrip private boolean mHasNewLayout = true; + @DoNotStrip private boolean mDoesLegacyStretchFlagAffectsLayout = false; private native long jni_YGNodeNew(); public YogaNode() { @@ -136,6 +137,7 @@ public class YogaNode implements Cloneable { mMeasureFunction = null; mBaselineFunction = null; mData = null; + mDoesLegacyStretchFlagAffectsLayout = false; jni_YGNodeReset(mNativePointer); } @@ -573,6 +575,10 @@ public class YogaNode implements Cloneable { return mHeight; } + public boolean getDoesLegacyStretchFlagAffectsLayout() { + return mDoesLegacyStretchFlagAffectsLayout; + } + public float getLayoutMargin(YogaEdge edge) { switch (edge) { case LEFT: diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 46d73b44..cc75df96 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -67,6 +67,9 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto edgeSetFlagField = obj->getClass()->getField("mEdgeSetFlag"); static auto hasNewLayoutField = obj->getClass()->getField("mHasNewLayout"); + static auto doesLegacyStretchBehaviour = + obj->getClass()->getField( + "mDoesLegacyStretchFlagAffectsLayout"); /* Those flags needs be in sync with YogaNode.java */ const int MARGIN = 1; @@ -79,12 +82,19 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); + obj->setFieldValue( + doesLegacyStretchBehaviour, + YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); if ((hasEdgeSetFlag & MARGIN) == MARGIN) { - obj->setFieldValue(marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); - obj->setFieldValue(marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); - obj->setFieldValue(marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); - obj->setFieldValue(marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); + obj->setFieldValue( + marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); + obj->setFieldValue( + marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); + obj->setFieldValue( + marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); + obj->setFieldValue( + marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); } if ((hasEdgeSetFlag & PADDING) == PADDING) { @@ -467,6 +477,14 @@ void jni_YGConfigSetExperimentalFeatureEnabled(alias_ref, enabled); } +void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( + alias_ref, + jlong nativePointer, + jboolean enabled) { + const YGConfigRef config = _jlong2YGConfigRef(nativePointer); + YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(config, enabled); +} + void jni_YGConfigSetUseWebDefaults(alias_ref, jlong nativePointer, jboolean useWebDefaults) { @@ -624,16 +642,19 @@ jint JNI_OnLoad(JavaVM *vm, void *) { YGMakeNativeMethod(jni_YGNodePrint), YGMakeNativeMethod(jni_YGNodeClone), }); - registerNatives("com/facebook/yoga/YogaConfig", - { - YGMakeNativeMethod(jni_YGConfigNew), - YGMakeNativeMethod(jni_YGConfigFree), - YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), - YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), - YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), - YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), - YGMakeNativeMethod(jni_YGConfigSetLogger), - YGMakeNativeMethod(jni_YGConfigSetHasNodeClonedFunc), - }); + registerNatives( + "com/facebook/yoga/YogaConfig", + { + YGMakeNativeMethod(jni_YGConfigNew), + YGMakeNativeMethod(jni_YGConfigFree), + YGMakeNativeMethod(jni_YGConfigSetExperimentalFeatureEnabled), + YGMakeNativeMethod(jni_YGConfigSetUseWebDefaults), + YGMakeNativeMethod(jni_YGConfigSetPointScaleFactor), + YGMakeNativeMethod(jni_YGConfigSetUseLegacyStretchBehaviour), + YGMakeNativeMethod(jni_YGConfigSetLogger), + YGMakeNativeMethod(jni_YGConfigSetHasNodeClonedFunc), + YGMakeNativeMethod( + jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), + }); }); } diff --git a/java/tests/com/facebook/yoga/YogaNodeTest.java b/java/tests/com/facebook/yoga/YogaNodeTest.java index 3b22b49f..4087232a 100644 --- a/java/tests/com/facebook/yoga/YogaNodeTest.java +++ b/java/tests/com/facebook/yoga/YogaNodeTest.java @@ -8,6 +8,7 @@ package com.facebook.yoga; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -302,4 +303,27 @@ public class YogaNodeTest { } fail("YogaConfig leaked"); } + + @Test + public void testFlagShouldDiffLayoutWithoutLegacyStretchBehaviour() throws Exception { + YogaConfig config = new YogaConfig(); + config.setShouldDiffLayoutWithoutLegacyStretchBehaviour(true); + config.setUseLegacyStretchBehaviour(true); + YogaNode root = new YogaNode(config); + root.setWidth(500); + root.setHeight(500); + YogaNode root_child0 = new YogaNode(config); + root_child0.setAlignItems(YogaAlign.FLEX_START); + root.addChildAt(root_child0, 0); + YogaNode root_child0_child0 = new YogaNode(config); + root_child0_child0.setFlexGrow(1); + root_child0_child0.setFlexShrink(1); + root_child0.addChildAt(root_child0_child0, 0); + YogaNode root_child0_child0_child0 = new YogaNode(config); + root_child0_child0_child0.setFlexGrow(1); + root_child0_child0_child0.setFlexShrink(1); + root_child0_child0.addChildAt(root_child0_child0_child0, 0); + root.calculateLayout(YogaConstants.UNDEFINED, YogaConstants.UNDEFINED); + assertFalse(root.getDoesLegacyStretchFlagAffectsLayout()); + } } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index b3f3e220..b5e1e4c0 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -905,6 +905,10 @@ YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Margin, margin); YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Border, border); YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(float, Padding, padding); +bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) { + return node->getLayout().doesLegacyStretchFlagAffectsLayout; +} + uint32_t gCurrentGenerationCount = 0; bool YGLayoutNodeInternal(const YGNodeRef node, @@ -3842,6 +3846,12 @@ void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) { } } +void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( + const YGConfigRef config, + const bool shouldDiffLayout) { + config->shouldDiffLayoutWithoutLegacyStretchBehaviour = shouldDiffLayout; +} + static void YGVLog(const YGConfigRef config, const YGNodeRef node, YGLogLevel level, diff --git a/yoga/Yoga.h b/yoga/Yoga.h index baeb28e2..83eefa02 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -236,6 +236,7 @@ YG_NODE_LAYOUT_PROPERTY(float, Width); YG_NODE_LAYOUT_PROPERTY(float, Height); YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow); +bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node); // Get the computed values for these nodes after performing layout. If they were set using // point values then the returned value will be the same as YGNodeStyleGetXXX. However if @@ -253,10 +254,12 @@ WIN_EXPORT void YGAssertWithNode(const YGNodeRef node, const bool condition, con WIN_EXPORT void YGAssertWithConfig(const YGConfigRef config, const bool condition, const char *message); - // Set this to number of pixels in 1 point to round calculation results // If you want to avoid rounding - set PointScaleFactor to 0 WIN_EXPORT void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint); +void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( + const YGConfigRef config, + const bool shouldDiffLayout); // Yoga previously had an error where containers would take the maximum space possible instead of // the minimum