From 2cac77eaa1c0827078d260bc7676930f86ac4dcc Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Thu, 27 Oct 2016 10:52:12 -0700 Subject: [PATCH] Set layout outputs on java object from C Summary: Set layout outputs on CSSNode from C after layout calculation finishes instead of relying on calling jni gettings from java code. This should be much more efficient as it avoids a lot of jni overhead and also allows for calling getLayoutWidth() etc multiple times without incurring a penalty. Reviewed By: lexs Differential Revision: D4077968 fbshipit-source-id: bce86ba610cd5ae36cfb45d78b2609c63a14cfa3 --- java/com/facebook/csslayout/CSSNode.java | 40 ++++++++++++------- java/jni/CSSJNI.cpp | 49 +++++++++++++++--------- 2 files changed, 57 insertions(+), 32 deletions(-) diff --git a/java/com/facebook/csslayout/CSSNode.java b/java/com/facebook/csslayout/CSSNode.java index 103784f4..f07ad7de 100644 --- a/java/com/facebook/csslayout/CSSNode.java +++ b/java/com/facebook/csslayout/CSSNode.java @@ -45,6 +45,17 @@ public class CSSNode implements CSSNodeAPI { private boolean mHasSetBorder = false; private boolean mHasSetPosition = false; + @DoNotStrip + private float mWidth = CSSConstants.UNDEFINED; + @DoNotStrip + private float mHeight = CSSConstants.UNDEFINED; + @DoNotStrip + private float mTop = CSSConstants.UNDEFINED; + @DoNotStrip + private float mLeft = CSSConstants.UNDEFINED; + @DoNotStrip + private int mLayoutDirection = 0; + private native long jni_CSSNodeNew(); public CSSNode() { mNativePointer = jni_CSSNodeNew(); @@ -73,6 +84,12 @@ public class CSSNode implements CSSNodeAPI { mHasSetBorder = false; mHasSetPosition = false; + mWidth = CSSConstants.UNDEFINED; + mHeight = CSSConstants.UNDEFINED; + mTop = CSSConstants.UNDEFINED; + mLeft = CSSConstants.UNDEFINED; + mLayoutDirection = 0; + mMeasureFunction = null; mData = null; @@ -176,12 +193,6 @@ public class CSSNode implements CSSNodeAPI { jni_CSSNodeStyleSetDirection(mNativePointer, direction.ordinal()); } - private native int jni_CSSNodeLayoutGetDirection(long nativePointer); - @Override - public CSSDirection getLayoutDirection() { - return CSSDirection.values()[jni_CSSNodeLayoutGetDirection(mNativePointer)]; - } - private native int jni_CSSNodeStyleGetFlexDirection(long nativePointer); @Override public CSSFlexDirection getFlexDirection() { @@ -450,28 +461,29 @@ public class CSSNode implements CSSNodeAPI { jni_CSSNodeStyleSetMaxHeight(mNativePointer, maxheight); } - private native float jni_CSSNodeLayoutGetLeft(long nativePointer); @Override public float getLayoutX() { - return jni_CSSNodeLayoutGetLeft(mNativePointer); + return mLeft; } - private native float jni_CSSNodeLayoutGetTop(long nativePointer); @Override public float getLayoutY() { - return jni_CSSNodeLayoutGetTop(mNativePointer); + return mTop; } - private native float jni_CSSNodeLayoutGetWidth(long nativePointer); @Override public float getLayoutWidth() { - return jni_CSSNodeLayoutGetWidth(mNativePointer); + return mWidth; } - private native float jni_CSSNodeLayoutGetHeight(long nativePointer); @Override public float getLayoutHeight() { - return jni_CSSNodeLayoutGetHeight(mNativePointer); + return mHeight; + } + + @Override + public CSSDirection getLayoutDirection() { + return CSSDirection.values()[mLayoutDirection]; } private native void jni_CSSNodeSetHasMeasureFunc(long nativePointer, boolean hasMeasureFunc); diff --git a/java/jni/CSSJNI.cpp b/java/jni/CSSJNI.cpp index 944ae211..3d9d488b 100644 --- a/java/jni/CSSJNI.cpp +++ b/java/jni/CSSJNI.cpp @@ -14,6 +14,31 @@ using namespace facebook::jni; using namespace std; +static void _jniTransferLayoutDirection(CSSNodeRef node, alias_ref javaNode) { + static auto layoutDirectionField = javaNode->getClass()->getField("mLayoutDirection"); + javaNode->setFieldValue(layoutDirectionField, static_cast(CSSNodeLayoutGetDirection(node))); +} + +static void _jniTransferLayoutOutputsRecursive(CSSNodeRef root) { + auto javaNode = adopt_local( + Environment::current()->NewLocalRef(reinterpret_cast(CSSNodeGetContext(root)))); + + static auto widthField = javaNode->getClass()->getField("mWidth"); + static auto heightField = javaNode->getClass()->getField("mHeight"); + static auto leftField = javaNode->getClass()->getField("mLeft"); + static auto topField = javaNode->getClass()->getField("mTop"); + + javaNode->setFieldValue(widthField, CSSNodeLayoutGetWidth(root)); + javaNode->setFieldValue(heightField, CSSNodeLayoutGetHeight(root)); + javaNode->setFieldValue(leftField, CSSNodeLayoutGetLeft(root)); + javaNode->setFieldValue(topField, CSSNodeLayoutGetTop(root)); + _jniTransferLayoutDirection(root, javaNode); + + for (uint32_t i = 0; i < CSSNodeChildCount(root); i++) { + _jniTransferLayoutOutputsRecursive(CSSNodeGetChild(root, i)); + } +} + static void _jniPrint(CSSNodeRef node) { auto obj = adopt_local(Environment::current()->NewLocalRef(reinterpret_cast(CSSNodeGetContext(node)))); cout << obj->toString() << endl; @@ -25,8 +50,11 @@ static CSSSize _jniMeasureFunc(CSSNodeRef node, float height, CSSMeasureMode heightMode) { auto obj = adopt_local(Environment::current()->NewLocalRef(reinterpret_cast(CSSNodeGetContext(node)))); + static auto measureFunc = obj->getClass()->getMethod("measure"); + + _jniTransferLayoutDirection(node, obj); const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); static_assert(sizeof(measureResult) == 8, @@ -79,10 +107,12 @@ void jni_CSSNodeRemoveChild(alias_ref, jlong nativePointer, jlong child } void jni_CSSNodeCalculateLayout(alias_ref, jlong nativePointer) { - CSSNodeCalculateLayout(_jlong2CSSNodeRef(nativePointer), + const CSSNodeRef root = _jlong2CSSNodeRef(nativePointer); + CSSNodeCalculateLayout(root, CSSUndefined, CSSUndefined, CSSNodeStyleGetDirection(_jlong2CSSNodeRef(nativePointer))); + _jniTransferLayoutOutputsRecursive(root); } void jni_CSSNodeMarkDirty(alias_ref, jlong nativePointer) { @@ -139,11 +169,6 @@ void jni_CSSNodeMarkLayoutSeen(alias_ref, jlong nativePointer) { static_cast(value)); \ } -#define CSS_NODE_JNI_LAYOUT_PROP(javatype, type, name) \ - javatype jni_CSSNodeLayoutGet##name(alias_ref, jlong nativePointer) { \ - return (javatype) CSSNodeLayoutGet##name(_jlong2CSSNodeRef(nativePointer)); \ - } - CSS_NODE_JNI_STYLE_PROP(jint, CSSDirection, Direction); CSS_NODE_JNI_STYLE_PROP(jint, CSSFlexDirection, FlexDirection); CSS_NODE_JNI_STYLE_PROP(jint, CSSJustify, JustifyContent); @@ -173,12 +198,6 @@ CSS_NODE_JNI_STYLE_PROP(jfloat, float, Height); CSS_NODE_JNI_STYLE_PROP(jfloat, float, MinHeight); CSS_NODE_JNI_STYLE_PROP(jfloat, float, MaxHeight); -CSS_NODE_JNI_LAYOUT_PROP(jfloat, float, Width); -CSS_NODE_JNI_LAYOUT_PROP(jfloat, float, Height); -CSS_NODE_JNI_LAYOUT_PROP(jfloat, float, Left); -CSS_NODE_JNI_LAYOUT_PROP(jfloat, float, Top); -CSS_NODE_JNI_LAYOUT_PROP(jint, CSSDirection, Direction); - #define CSSMakeNativeMethod(name) makeNativeMethod(#name, name) jint JNI_OnLoad(JavaVM *vm, void *) { @@ -244,12 +263,6 @@ jint JNI_OnLoad(JavaVM *vm, void *) { CSSMakeNativeMethod(jni_CSSNodeStyleGetMaxHeight), CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxHeight), - CSSMakeNativeMethod(jni_CSSNodeLayoutGetLeft), - CSSMakeNativeMethod(jni_CSSNodeLayoutGetTop), - CSSMakeNativeMethod(jni_CSSNodeLayoutGetWidth), - CSSMakeNativeMethod(jni_CSSNodeLayoutGetHeight), - CSSMakeNativeMethod(jni_CSSNodeLayoutGetDirection), - CSSMakeNativeMethod(jni_CSSNodeGetInstanceCount), }); });