/** * Copyright (c) 2014-present, Facebook, Inc. * * This source code is licensed under the MIT license found in the * LICENSE file in the root directory of this source tree. */ #include #include #include #include using namespace facebook::jni; using namespace std; struct JYogaNode : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaNode;"; }; struct JYogaConfig : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaConfig;"; }; struct YGConfigContext { global_ref* logger; global_ref* config; YGConfigContext() : logger(nullptr), config(nullptr) {} ~YGConfigContext() { delete config; config = nullptr; delete logger; logger = nullptr; } }; static inline weak_ref *YGNodeJobject(YGNodeRef node) { return reinterpret_cast*>(node->getContext()); } static void YGTransferLayoutDirection(YGNodeRef node, alias_ref javaNode) { static auto layoutDirectionField = javaNode->getClass()->getField("mLayoutDirection"); javaNode->setFieldValue(layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { if (root->getHasNewLayout()) { if (auto obj = YGNodeJobject(root)->lockLocal()) { static auto widthField = obj->getClass()->getField("mWidth"); static auto heightField = obj->getClass()->getField("mHeight"); static auto leftField = obj->getClass()->getField("mLeft"); static auto topField = obj->getClass()->getField("mTop"); static auto marginLeftField = obj->getClass()->getField("mMarginLeft"); static auto marginTopField = obj->getClass()->getField("mMarginTop"); static auto marginRightField = obj->getClass()->getField("mMarginRight"); static auto marginBottomField = obj->getClass()->getField("mMarginBottom"); static auto paddingLeftField = obj->getClass()->getField("mPaddingLeft"); static auto paddingTopField = obj->getClass()->getField("mPaddingTop"); static auto paddingRightField = obj->getClass()->getField("mPaddingRight"); static auto paddingBottomField = obj->getClass()->getField("mPaddingBottom"); static auto borderLeftField = obj->getClass()->getField("mBorderLeft"); static auto borderTopField = obj->getClass()->getField("mBorderTop"); static auto borderRightField = obj->getClass()->getField("mBorderRight"); static auto borderBottomField = obj->getClass()->getField("mBorderBottom"); 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; const int PADDING = 2; const int BORDER = 4; int hasEdgeSetFlag = (int) obj->getFieldValue(edgeSetFlagField); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(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)); } if ((hasEdgeSetFlag & PADDING) == PADDING) { obj->setFieldValue(paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); obj->setFieldValue(paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); obj->setFieldValue(paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); obj->setFieldValue(paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); } if ((hasEdgeSetFlag & BORDER) == BORDER) { obj->setFieldValue(borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); obj->setFieldValue(borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); obj->setFieldValue(borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); } obj->setFieldValue(hasNewLayoutField, true); YGTransferLayoutDirection(root, obj); root->setHasNewLayout(false); for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } else { YGLog(root, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); } } } static void YGPrint(YGNodeRef node) { if (auto obj = YGNodeJobject(node)->lockLocal()) { cout << obj->toString() << endl; } else { YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); } } static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) { if (auto obj = YGNodeJobject(node)->lockLocal()) { static auto baselineFunc = findClassStatic("com/facebook/yoga/YogaNode") ->getMethod("baseline"); return baselineFunc(obj, width, height); } else { return height; } } static void YGJNIOnNodeClonedFunc( YGNodeRef oldNode, YGNodeRef newNode, YGNodeRef parent, int childIndex) { auto config = oldNode->getConfig(); if (!config) { return; } static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig") ->getMethod, local_ref, local_ref, jint)>("onNodeCloned"); auto context = reinterpret_cast(YGConfigGetContext(config)); auto javaConfig = context->config; onNodeClonedFunc( javaConfig->get(), YGNodeJobject(oldNode)->lockLocal(), YGNodeJobject(newNode)->lockLocal(), YGNodeJobject(parent)->lockLocal(), childIndex); } static YGSize YGJNIMeasureFunc( YGNodeRef node, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode) { if (auto obj = YGNodeJobject(node)->lockLocal()) { static auto measureFunc = findClassStatic("com/facebook/yoga/YogaNode") ->getMethod("measure"); YGTransferLayoutDirection(node, obj); const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); static_assert(sizeof(measureResult) == 8, "Expected measureResult to be 8 bytes, or two 32 bit ints"); int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); int32_t hBits = 0xFFFFFFFF & measureResult; const float *measuredWidth = reinterpret_cast(&wBits); const float *measuredHeight = reinterpret_cast(&hBits); return YGSize{*measuredWidth, *measuredHeight}; } else { YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); return YGSize{ widthMode == YGMeasureModeUndefined ? 0 : width, heightMode == YGMeasureModeUndefined ? 0 : height, }; } } struct JYogaLogLevel : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogLevel;"; }; static int YGJNILogFunc(const YGConfigRef config, const YGNodeRef node, YGLogLevel level, const char *format, va_list args) { int result = vsnprintf(NULL, 0, format, args); std::vector buffer(1 + result); vsnprintf(buffer.data(), buffer.size(), format, args); static auto logFunc = findClassStatic("com/facebook/yoga/YogaLogger") ->getMethod, local_ref, jstring)>("log"); static auto logLevelFromInt = JYogaLogLevel::javaClassStatic()->getStaticMethod("fromInt"); if (auto obj = YGNodeJobject(node)->lockLocal()) { auto jlogger = reinterpret_cast *>(YGConfigGetContext(config)); logFunc( jlogger->get(), obj, logLevelFromInt( JYogaLogLevel::javaClassStatic(), static_cast(level)), Environment::current()->NewStringUTF(buffer.data())); } return result; } static inline YGNodeRef _jlong2YGNodeRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } jlong jni_YGNodeNew(alias_ref thiz) { const YGNodeRef node = YGNodeNew(); node->setContext(new weak_ref(make_weak(thiz))); // YGNodeSetContext(node, new weak_ref(make_weak(thiz))); node->setPrintFunc(YGPrint); // YGNodeSetPrintFunc(node, YGPrint); return reinterpret_cast(node); } jlong jni_YGNodeNewWithConfig(alias_ref thiz, jlong configPointer) { const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer)); node->setContext(new weak_ref(make_weak(thiz))); node->setPrintFunc(YGPrint); return reinterpret_cast(node); } jlong jni_YGNodeClone( alias_ref thiz, jlong nativePointer, alias_ref clonedJavaObject) { const YGNodeRef clonedYogaNode = YGNodeClone(_jlong2YGNodeRef(nativePointer)); clonedYogaNode->setContext( new weak_ref(make_weak(clonedJavaObject))); return reinterpret_cast(clonedYogaNode); } void jni_YGNodeFree(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); delete YGNodeJobject(node); YGNodeFree(node); } void jni_YGNodeReset(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); void* context = node->getContext(); YGNodeReset(node); node->setContext(context); node->setPrintFunc(YGPrint); } void jni_YGNodePrint(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); YGNodePrint(node, (YGPrintOptions)(YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren)); } void jni_YGNodeInsertChild(alias_ref, jlong nativePointer, jlong childPointer, jint index) { YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } void jni_YGNodeRemoveChild(alias_ref, jlong nativePointer, jlong childPointer) { YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } void jni_YGNodeCalculateLayout(alias_ref, jlong nativePointer, jfloat width, jfloat height) { const YGNodeRef root = _jlong2YGNodeRef(nativePointer); YGNodeCalculateLayout(root, static_cast(width), static_cast(height), YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); YGTransferLayoutOutputsRecursive(root); } void jni_YGNodeMarkDirty(alias_ref, jlong nativePointer) { YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer)); } void jni_YGNodeMarkDirtyAndPropogateToDescendants( alias_ref, jlong nativePointer) { YGNodeMarkDirtyAndPropogateToDescendants(_jlong2YGNodeRef(nativePointer)); } jboolean jni_YGNodeIsDirty(alias_ref, jlong nativePointer) { return (jboolean)_jlong2YGNodeRef(nativePointer)->isDirty(); } void jni_YGNodeSetHasMeasureFunc(alias_ref, jlong nativePointer, jboolean hasMeasureFunc) { _jlong2YGNodeRef(nativePointer) ->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr); } void jni_YGNodeSetHasBaselineFunc(alias_ref, jlong nativePointer, jboolean hasBaselineFunc) { _jlong2YGNodeRef(nativePointer) ->setBaseLineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr); } void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNativePointer) { YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } struct JYogaValue : public JavaClass { constexpr static auto kJavaDescriptor = "Lcom/facebook/yoga/YogaValue;"; static local_ref create(YGValue value) { return newInstance(value.value, static_cast(value.unit)); } }; #define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ return (javatype)YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \ } \ \ void jni_YGNodeStyleSet##name( \ alias_ref, jlong nativePointer, javatype value) { \ YGNodeStyleSet##name( \ _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } #define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ local_ref jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ return JYogaValue::create(YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ } \ \ void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jfloat value) { \ YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ } \ \ void jni_YGNodeStyleSet##name##Percent(alias_ref, jlong nativePointer, jfloat value) { \ YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ } #define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ YG_NODE_JNI_STYLE_UNIT_PROP(name) \ void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer) { \ YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ } #define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ static_cast(edge)); \ } \ \ void jni_YGNodeStyleSet##name(alias_ref, \ jlong nativePointer, \ jint edge, \ javatype value) { \ YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ static_cast(edge), \ static_cast(value)); \ } #define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ local_ref jni_YGNodeStyleGet##name(alias_ref, \ jlong nativePointer, \ jint edge) { \ return JYogaValue::create( \ YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), static_cast(edge))); \ } \ \ void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jint edge, jfloat value) { \ YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ static_cast(edge), \ static_cast(value)); \ } \ \ void jni_YGNodeStyleSet##name##Percent(alias_ref, \ jlong nativePointer, \ jint edge, \ jfloat value) { \ YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), \ static_cast(edge), \ static_cast(value)); \ } #define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ void jni_YGNodeStyleSet##name##Auto(alias_ref, 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); YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignItems); YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignSelf); YG_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignContent); YG_NODE_JNI_STYLE_PROP(jint, YGPositionType, PositionType); YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap); YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow); YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display); void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat value) { YGNodeStyleSetFlex(_jlong2YGNodeRef(nativePointer), static_cast(value)); } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(FlexBasis); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(Margin); YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Padding); YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Border); YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Width); YG_NODE_JNI_STYLE_UNIT_PROP(MinWidth); YG_NODE_JNI_STYLE_UNIT_PROP(MaxWidth); YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(Height); YG_NODE_JNI_STYLE_UNIT_PROP(MinHeight); YG_NODE_JNI_STYLE_UNIT_PROP(MaxHeight); // Yoga specific properties, not compatible with flexbox specification YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio); jlong jni_YGConfigNew(alias_ref) { return reinterpret_cast(YGConfigNew()); } void jni_YGConfigFree(alias_ref, jlong nativePointer) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); auto context = reinterpret_cast(YGConfigGetContext(config)); if (context) { delete context; } YGConfigFree(config); } void jni_YGConfigSetExperimentalFeatureEnabled(alias_ref, jlong nativePointer, jint feature, jboolean enabled) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetExperimentalFeatureEnabled(config, static_cast(feature), 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) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseWebDefaults(config, useWebDefaults); } void jni_YGConfigSetPointScaleFactor(alias_ref, jlong nativePointer, jfloat pixelsInPoint) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetPointScaleFactor(config, pixelsInPoint); } void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref, jlong nativePointer, jboolean useLegacyStretchBehaviour) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); } void jni_YGConfigSetHasNodeClonedFunc( alias_ref thiz, jlong nativePointer, jboolean hasNodeClonedFunc) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); auto context = reinterpret_cast(YGConfigGetContext(config)); if (context && context->config) { delete context->config; context->config = nullptr; } if (hasNodeClonedFunc) { if (!context) { context = new YGConfigContext(); YGConfigSetContext(config, context); } context->config = new global_ref(make_global(thiz)); YGConfigSetNodeClonedFunc(config, YGJNIOnNodeClonedFunc); } else { YGConfigSetNodeClonedFunc(config, nullptr); } } void jni_YGConfigSetLogger( alias_ref, jlong nativePointer, alias_ref logger) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); auto context = reinterpret_cast(YGConfigGetContext(config)); if (context && context->logger) { delete context->logger; context->logger = nullptr; } if (logger) { if (!context) { context = new YGConfigContext(); YGConfigSetContext(config, context); } context->logger = new global_ref(make_global(logger)); YGConfigSetLogger(config, YGJNILogFunc); } else { YGConfigSetLogger(config, NULL); } } jint jni_YGNodeGetInstanceCount(alias_ref clazz) { return YGNodeGetInstanceCount(); } #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) jint JNI_OnLoad(JavaVM *vm, void *) { return initialize(vm, [] { registerNatives( "com/facebook/yoga/YogaNode", { YGMakeNativeMethod(jni_YGNodeNew), YGMakeNativeMethod(jni_YGNodeNewWithConfig), YGMakeNativeMethod(jni_YGNodeFree), YGMakeNativeMethod(jni_YGNodeReset), YGMakeNativeMethod(jni_YGNodeInsertChild), YGMakeNativeMethod(jni_YGNodeRemoveChild), YGMakeNativeMethod(jni_YGNodeCalculateLayout), YGMakeNativeMethod(jni_YGNodeMarkDirty), YGMakeNativeMethod(jni_YGNodeMarkDirtyAndPropogateToDescendants), YGMakeNativeMethod(jni_YGNodeIsDirty), YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc), YGMakeNativeMethod(jni_YGNodeSetHasBaselineFunc), YGMakeNativeMethod(jni_YGNodeCopyStyle), YGMakeNativeMethod(jni_YGNodeStyleGetDirection), YGMakeNativeMethod(jni_YGNodeStyleSetDirection), YGMakeNativeMethod(jni_YGNodeStyleGetFlexDirection), YGMakeNativeMethod(jni_YGNodeStyleSetFlexDirection), YGMakeNativeMethod(jni_YGNodeStyleGetJustifyContent), YGMakeNativeMethod(jni_YGNodeStyleSetJustifyContent), YGMakeNativeMethod(jni_YGNodeStyleGetAlignItems), YGMakeNativeMethod(jni_YGNodeStyleSetAlignItems), YGMakeNativeMethod(jni_YGNodeStyleGetAlignSelf), YGMakeNativeMethod(jni_YGNodeStyleSetAlignSelf), YGMakeNativeMethod(jni_YGNodeStyleGetAlignContent), YGMakeNativeMethod(jni_YGNodeStyleSetAlignContent), YGMakeNativeMethod(jni_YGNodeStyleGetPositionType), YGMakeNativeMethod(jni_YGNodeStyleSetPositionType), YGMakeNativeMethod(jni_YGNodeStyleSetFlexWrap), YGMakeNativeMethod(jni_YGNodeStyleGetOverflow), YGMakeNativeMethod(jni_YGNodeStyleSetOverflow), YGMakeNativeMethod(jni_YGNodeStyleGetDisplay), YGMakeNativeMethod(jni_YGNodeStyleSetDisplay), YGMakeNativeMethod(jni_YGNodeStyleSetFlex), YGMakeNativeMethod(jni_YGNodeStyleGetFlexGrow), YGMakeNativeMethod(jni_YGNodeStyleSetFlexGrow), YGMakeNativeMethod(jni_YGNodeStyleGetFlexShrink), YGMakeNativeMethod(jni_YGNodeStyleSetFlexShrink), YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasis), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasisPercent), YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasisAuto), YGMakeNativeMethod(jni_YGNodeStyleGetMargin), YGMakeNativeMethod(jni_YGNodeStyleSetMargin), YGMakeNativeMethod(jni_YGNodeStyleSetMarginPercent), YGMakeNativeMethod(jni_YGNodeStyleSetMarginAuto), YGMakeNativeMethod(jni_YGNodeStyleGetPadding), YGMakeNativeMethod(jni_YGNodeStyleSetPadding), YGMakeNativeMethod(jni_YGNodeStyleSetPaddingPercent), YGMakeNativeMethod(jni_YGNodeStyleGetBorder), YGMakeNativeMethod(jni_YGNodeStyleSetBorder), YGMakeNativeMethod(jni_YGNodeStyleGetPosition), YGMakeNativeMethod(jni_YGNodeStyleSetPosition), YGMakeNativeMethod(jni_YGNodeStyleSetPositionPercent), YGMakeNativeMethod(jni_YGNodeStyleGetWidth), YGMakeNativeMethod(jni_YGNodeStyleSetWidth), YGMakeNativeMethod(jni_YGNodeStyleSetWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleSetWidthAuto), YGMakeNativeMethod(jni_YGNodeStyleGetHeight), YGMakeNativeMethod(jni_YGNodeStyleSetHeight), YGMakeNativeMethod(jni_YGNodeStyleSetHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleSetHeightAuto), YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMinWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMinWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMinHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMinHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMaxWidth), YGMakeNativeMethod(jni_YGNodeStyleSetMaxWidthPercent), YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeight), YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeightPercent), YGMakeNativeMethod(jni_YGNodeStyleGetAspectRatio), YGMakeNativeMethod(jni_YGNodeStyleSetAspectRatio), YGMakeNativeMethod(jni_YGNodeGetInstanceCount), 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), YGMakeNativeMethod( jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour), }); }); }