/** * Copyright (c) 2014-present, Facebook, Inc. * All rights reserved. * * This source code is licensed under the BSD-style license found in the * LICENSE file in the root directory of this source tree. An additional grant * of patent rights can be found in the PATENTS file in the same directory. */ #include #include #define JNI_VERSION JNI_VERSION_1_6 #define CSS_NODE_JNI(type, func) \ JNIEXPORT type JNICALL Java_com_facebook_csslayout_CSSNodeJNI_jni_1##func #define CSS_NODE_JNI_STYLE_PROP(javatype, type, name) \ CSS_NODE_JNI(javatype, \ CSSNodeStyleGet##name(JNIEnv *env, jobject instance, jlong nativePointer) { \ return (javatype) CSSNodeStyleGet##name((CSSNodeRef)(intptr_t) nativePointer); \ }) \ \ CSS_NODE_JNI( \ void, \ CSSNodeStyleSet##name(JNIEnv *env, jobject instance, jlong nativePointer, javatype value) { \ CSSNodeStyleSet##name((CSSNodeRef)(intptr_t) nativePointer, (type) value); \ }) #define CSS_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ CSS_NODE_JNI( \ javatype, \ CSSNodeStyleGet##name(JNIEnv *env, jobject instance, jlong nativePointer, jint edge) { \ return (javatype) CSSNodeStyleGet##name((CSSNodeRef)(intptr_t) nativePointer, \ (CSSEdge) edge); \ }) \ \ CSS_NODE_JNI( \ void, \ CSSNodeStyleSet##name( \ JNIEnv *env, jobject instance, jlong nativePointer, jint edge, javatype value) { \ CSSNodeStyleSet##name((CSSNodeRef)(intptr_t) nativePointer, (CSSEdge) edge, (type) value); \ }) #define CSS_NODE_JNI_LAYOUT_PROP(javatype, type, name) \ CSS_NODE_JNI(javatype, \ CSSNodeLayoutGet##name(JNIEnv *env, jobject instance, jlong nativePointer) { \ return (javatype) CSSNodeLayoutGet##name((CSSNodeRef)(intptr_t) nativePointer); \ }) static JavaVM *jvm = NULL; jint JNI_OnLoad(JavaVM *vm, void *reserved) { jvm = vm; return JNI_VERSION; } static void _jniPrint(void *context) { JNIEnv *env = NULL; CSS_ASSERT((*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION) == JNI_OK, "Must have valid jni env"); static jclass cssNodeClass = NULL; if (!cssNodeClass) { cssNodeClass = (*env)->FindClass(env, "com/facebook/csslayout/CSSNodeJNI"); CSS_ASSERT(cssNodeClass, "Could not find CSSNode class"); } static jmethodID toStringID = NULL; if (!toStringID) { toStringID = (*env)->GetMethodID(env, cssNodeClass, "toString", "()Ljava/lang/String"); CSS_ASSERT(toStringID, "Could not find toString method"); } jstring javaString = (jstring)(*env)->CallObjectMethod(env, context, toStringID); const char *nativeString = (*env)->GetStringUTFChars(env, javaString, 0); printf("%s\n", nativeString); (*env)->ReleaseStringUTFChars(env, javaString, nativeString); } static CSSSize _jniMeasureFunc(void *context, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode) { JNIEnv *env = NULL; CSS_ASSERT((*jvm)->GetEnv(jvm, (void **) &env, JNI_VERSION) == JNI_OK, "Must have valid jni env"); static jclass cssNodeClass = NULL; if (!cssNodeClass) { cssNodeClass = (*env)->FindClass(env, "com/facebook/csslayout/CSSNodeJNI"); CSS_ASSERT(cssNodeClass, "Could not find CSSNode class"); } static jmethodID measureID = NULL; if (!measureID) { measureID = (*env)->GetMethodID(env, cssNodeClass, "measure", "(FIFI)J"); CSS_ASSERT(measureID, "Could not find measure method"); } jlong measureResult = (*env)->CallLongMethod(env, context, measureID, width, widthMode, height, heightMode); return (CSSSize){ .width = (int32_t)(measureResult >> 32), .height = (int32_t) measureResult, }; } CSS_NODE_JNI(jlong, CSSNodeNew(JNIEnv *env, jobject thiz) { const CSSNodeRef node = CSSNodeNew(); CSSNodeSetContext(node, (*env)->NewGlobalRef(env, thiz)); CSSNodeSetPrintFunc(node, _jniPrint); return (jlong)(intptr_t) node; }) CSS_NODE_JNI(void, CSSNodeFree(JNIEnv *env, jobject thiz, jlong nativePointer) { (*env)->DeleteGlobalRef(env, (jobject) CSSNodeGetContext((CSSNodeRef)(intptr_t) nativePointer)); CSSNodeFree((CSSNodeRef)(intptr_t) nativePointer); }) CSS_NODE_JNI(void, CSSNodeInsertChild(JNIEnv *env, jobject thiz, jlong nativePointer, jlong childPointer, jint index) { CSSNodeInsertChild((CSSNodeRef)(intptr_t) nativePointer, (CSSNodeRef)(intptr_t) childPointer, index); }) CSS_NODE_JNI( void, CSSNodeRemoveChild(JNIEnv *env, jobject thiz, jlong nativePointer, jlong childPointer) { CSSNodeRemoveChild((CSSNodeRef)(intptr_t) nativePointer, (CSSNodeRef)(intptr_t) childPointer); }) CSS_NODE_JNI(void, CSSNodeCalculateLayout(JNIEnv *env, jobject thiz, jlong nativePointer) { CSSNodeCalculateLayout((CSSNodeRef)(intptr_t) nativePointer, NAN, NAN, CSSNodeStyleGetDirection(((CSSNodeRef)(intptr_t) nativePointer))); }) CSS_NODE_JNI(void, CSSNodeMarkDirty(JNIEnv *env, jobject thiz, jlong nativePointer) { CSSNodeMarkDirty((CSSNodeRef)(intptr_t) nativePointer); }) CSS_NODE_JNI(jboolean, CSSNodeIsDirty(JNIEnv *env, jobject instance, jlong nativePointer) { return (jboolean) CSSNodeIsDirty((CSSNodeRef)(intptr_t) nativePointer); }) CSS_NODE_JNI(void, CSSNodeSetHasMeasureFunc(JNIEnv *env, jobject thiz, jlong nativePointer, jboolean hasMeasureFunc) { CSSNodeSetMeasureFunc((CSSNodeRef)(intptr_t) nativePointer, hasMeasureFunc ? _jniMeasureFunc : NULL); }) CSS_NODE_JNI( void, CSSNodeSetIsTextNode(JNIEnv *env, jobject instance, jlong nativePointer, jboolean isTextNode) { CSSNodeSetIsTextnode((CSSNodeRef)(intptr_t) nativePointer, isTextNode); }) CSS_NODE_JNI(jboolean, CSSNodeGetIsTextNode(JNIEnv *env, jobject instance, jlong nativePointer) { return (jboolean) CSSNodeGetIsTextnode((CSSNodeRef)(intptr_t) nativePointer); }) CSS_NODE_JNI(jboolean, CSSNodeHasNewLayout(JNIEnv *env, jobject instance, jlong nativePointer) { return (jboolean) CSSNodeGetHasNewLayout((CSSNodeRef)(intptr_t) nativePointer); }) CSS_NODE_JNI(void, CSSNodeMarkLayoutSeen(JNIEnv *env, jobject instance, jlong nativePointer) { CSSNodeSetHasNewLayout((CSSNodeRef)(intptr_t) nativePointer, false); }) CSS_NODE_JNI_STYLE_PROP(jint, CSSDirection, Direction); CSS_NODE_JNI_STYLE_PROP(jint, CSSFlexDirection, FlexDirection); CSS_NODE_JNI_STYLE_PROP(jint, CSSJustify, JustifyContent); CSS_NODE_JNI_STYLE_PROP(jint, CSSAlign, AlignItems); CSS_NODE_JNI_STYLE_PROP(jint, CSSAlign, AlignSelf); CSS_NODE_JNI_STYLE_PROP(jint, CSSAlign, AlignContent); CSS_NODE_JNI_STYLE_PROP(jint, CSSPositionType, PositionType); CSS_NODE_JNI_STYLE_PROP(jint, CSSWrapType, FlexWrap); CSS_NODE_JNI_STYLE_PROP(jint, CSSOverflow, Overflow); CSS_NODE_JNI_STYLE_PROP(jfloat, float, Flex); CSS_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); CSS_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); CSS_NODE_JNI_STYLE_PROP(jfloat, float, FlexBasis); CSS_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Position); CSS_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Margin); CSS_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Padding); CSS_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Border); CSS_NODE_JNI_STYLE_PROP(jfloat, float, Width); CSS_NODE_JNI_STYLE_PROP(jfloat, float, MinWidth); CSS_NODE_JNI_STYLE_PROP(jfloat, float, MaxWidth); 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);