Rename C api
Summary: This renames the core C api to use the new Yoga branding. Differential Revision: D4259190 fbshipit-source-id: 26c8b356ca464d4304f5f9dc4192bff10cea2dc9
This commit is contained in:
committed by
Facebook Github Bot
parent
f7cc614d67
commit
dda24b1e23
@@ -1,340 +0,0 @@
|
||||
/**
|
||||
* 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 <CSSLayout/CSSLayout.h>
|
||||
#include <fb/fbjni.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace facebook::jni;
|
||||
using namespace std;
|
||||
|
||||
static inline weak_ref<jobject> *jobjectContext(CSSNodeRef node) {
|
||||
return reinterpret_cast<weak_ref<jobject> *>(CSSNodeGetContext(node));
|
||||
}
|
||||
|
||||
static void _jniTransferLayoutDirection(CSSNodeRef node, alias_ref<jobject> javaNode) {
|
||||
static auto layoutDirectionField = javaNode->getClass()->getField<jint>("mLayoutDirection");
|
||||
javaNode->setFieldValue(layoutDirectionField, static_cast<jint>(CSSNodeLayoutGetDirection(node)));
|
||||
}
|
||||
|
||||
static void _jniTransferLayoutOutputsRecursive(CSSNodeRef root) {
|
||||
if (auto obj = jobjectContext(root)->lockLocal()) {
|
||||
static auto widthField = obj->getClass()->getField<jfloat>("mWidth");
|
||||
static auto heightField = obj->getClass()->getField<jfloat>("mHeight");
|
||||
static auto leftField = obj->getClass()->getField<jfloat>("mLeft");
|
||||
static auto topField = obj->getClass()->getField<jfloat>("mTop");
|
||||
|
||||
obj->setFieldValue(widthField, CSSNodeLayoutGetWidth(root));
|
||||
obj->setFieldValue(heightField, CSSNodeLayoutGetHeight(root));
|
||||
obj->setFieldValue(leftField, CSSNodeLayoutGetLeft(root));
|
||||
obj->setFieldValue(topField, CSSNodeLayoutGetTop(root));
|
||||
_jniTransferLayoutDirection(root, obj);
|
||||
|
||||
for (uint32_t i = 0; i < CSSNodeChildCount(root); i++) {
|
||||
_jniTransferLayoutOutputsRecursive(CSSNodeGetChild(root, i));
|
||||
}
|
||||
} else {
|
||||
CSSLog(YGLogLevelError, "Java CSSNode was GCed during layout calculation\n");
|
||||
}
|
||||
}
|
||||
|
||||
static void _jniPrint(CSSNodeRef node) {
|
||||
if (auto obj = jobjectContext(node)->lockLocal()) {
|
||||
cout << obj->toString() << endl;
|
||||
} else {
|
||||
CSSLog(YGLogLevelError, "Java CSSNode was GCed during layout calculation\n");
|
||||
}
|
||||
}
|
||||
|
||||
static CSSSize _jniMeasureFunc(CSSNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode) {
|
||||
if (auto obj = jobjectContext(node)->lockLocal()) {
|
||||
static auto measureFunc = findClassLocal("com/facebook/csslayout/CSSNode")
|
||||
->getMethod<jlong(jfloat, jint, jfloat, jint)>("measure");
|
||||
|
||||
_jniTransferLayoutDirection(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");
|
||||
|
||||
const float measuredWidth = static_cast<float>(0xFFFFFFFF & (measureResult >> 32));
|
||||
const float measuredHeight = static_cast<float>(0xFFFFFFFF & measureResult);
|
||||
|
||||
return CSSSize{measuredWidth, measuredHeight};
|
||||
} else {
|
||||
CSSLog(YGLogLevelError, "Java CSSNode was GCed during layout calculation\n");
|
||||
return CSSSize{
|
||||
widthMode == YGMeasureModeUndefined ? 0 : width,
|
||||
heightMode == YGMeasureModeUndefined ? 0 : height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct JYogaLogLevel : public JavaClass<JYogaLogLevel> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/csslayout/YogaLogLevel;";
|
||||
};
|
||||
|
||||
static global_ref<jobject> *jLogger;
|
||||
static int _jniLog(YGLogLevel level, const char *format, va_list args) {
|
||||
char buffer[256];
|
||||
int result = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
static auto logFunc = findClassLocal("com/facebook/csslayout/CSSLogger")
|
||||
->getMethod<void(local_ref<JYogaLogLevel>, jstring)>("log");
|
||||
|
||||
static auto logLevelFromInt =
|
||||
JYogaLogLevel::javaClassStatic()->getStaticMethod<JYogaLogLevel::javaobject(jint)>("fromInt");
|
||||
|
||||
logFunc(jLogger->get(),
|
||||
logLevelFromInt(JYogaLogLevel::javaClassStatic(), static_cast<jint>(level)),
|
||||
Environment::current()->NewStringUTF(buffer));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline CSSNodeRef _jlong2CSSNodeRef(jlong addr) {
|
||||
return reinterpret_cast<CSSNodeRef>(static_cast<intptr_t>(addr));
|
||||
}
|
||||
|
||||
void jni_CSSLayoutSetLogger(alias_ref<jclass> clazz, alias_ref<jobject> logger) {
|
||||
if (jLogger) {
|
||||
jLogger->releaseAlias();
|
||||
delete jLogger;
|
||||
}
|
||||
|
||||
if (logger) {
|
||||
jLogger = new global_ref<jobject>(make_global(logger));
|
||||
CSSLayoutSetLogger(_jniLog);
|
||||
} else {
|
||||
jLogger = NULL;
|
||||
CSSLayoutSetLogger(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void jni_CSSLog(alias_ref<jclass> clazz, jint level, jstring message) {
|
||||
const char *nMessage = Environment::current()->GetStringUTFChars(message, 0);
|
||||
CSSLog(static_cast<YGLogLevel>(level), "%s", nMessage);
|
||||
Environment::current()->ReleaseStringUTFChars(message, nMessage);
|
||||
}
|
||||
|
||||
void jni_CSSLayoutSetExperimentalFeatureEnabled(alias_ref<jclass> clazz,
|
||||
jint feature,
|
||||
jboolean enabled) {
|
||||
CSSLayoutSetExperimentalFeatureEnabled(static_cast<YGExperimentalFeature>(feature), enabled);
|
||||
}
|
||||
|
||||
jboolean jni_CSSLayoutIsExperimentalFeatureEnabled(alias_ref<jclass> clazz, jint feature) {
|
||||
return CSSLayoutIsExperimentalFeatureEnabled(static_cast<YGExperimentalFeature>(feature));
|
||||
}
|
||||
|
||||
jint jni_CSSNodeGetInstanceCount(alias_ref<jclass> clazz) {
|
||||
return CSSNodeGetInstanceCount();
|
||||
}
|
||||
|
||||
jlong jni_CSSNodeNew(alias_ref<jobject> thiz) {
|
||||
const CSSNodeRef node = CSSNodeNew();
|
||||
CSSNodeSetContext(node, new weak_ref<jobject>(make_weak(thiz)));
|
||||
CSSNodeSetPrintFunc(node, _jniPrint);
|
||||
return reinterpret_cast<jlong>(node);
|
||||
}
|
||||
|
||||
void jni_CSSNodeFree(alias_ref<jobject> thiz, jlong nativePointer) {
|
||||
const CSSNodeRef node = _jlong2CSSNodeRef(nativePointer);
|
||||
delete jobjectContext(node);
|
||||
CSSNodeFree(node);
|
||||
}
|
||||
|
||||
void jni_CSSNodeReset(alias_ref<jobject> thiz, jlong nativePointer) {
|
||||
const CSSNodeRef node = _jlong2CSSNodeRef(nativePointer);
|
||||
void *context = CSSNodeGetContext(node);
|
||||
CSSNodeReset(node);
|
||||
CSSNodeSetContext(node, context);
|
||||
CSSNodeSetPrintFunc(node, _jniPrint);
|
||||
}
|
||||
|
||||
void jni_CSSNodeInsertChild(alias_ref<jobject>,
|
||||
jlong nativePointer,
|
||||
jlong childPointer,
|
||||
jint index) {
|
||||
CSSNodeInsertChild(_jlong2CSSNodeRef(nativePointer), _jlong2CSSNodeRef(childPointer), index);
|
||||
}
|
||||
|
||||
void jni_CSSNodeRemoveChild(alias_ref<jobject>, jlong nativePointer, jlong childPointer) {
|
||||
CSSNodeRemoveChild(_jlong2CSSNodeRef(nativePointer), _jlong2CSSNodeRef(childPointer));
|
||||
}
|
||||
|
||||
void jni_CSSNodeCalculateLayout(alias_ref<jobject>, jlong nativePointer) {
|
||||
const CSSNodeRef root = _jlong2CSSNodeRef(nativePointer);
|
||||
CSSNodeCalculateLayout(root,
|
||||
YGUndefined,
|
||||
YGUndefined,
|
||||
CSSNodeStyleGetDirection(_jlong2CSSNodeRef(nativePointer)));
|
||||
_jniTransferLayoutOutputsRecursive(root);
|
||||
}
|
||||
|
||||
void jni_CSSNodeMarkDirty(alias_ref<jobject>, jlong nativePointer) {
|
||||
CSSNodeMarkDirty(_jlong2CSSNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
jboolean jni_CSSNodeIsDirty(alias_ref<jobject>, jlong nativePointer) {
|
||||
return (jboolean) CSSNodeIsDirty(_jlong2CSSNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
void jni_CSSNodeSetHasMeasureFunc(alias_ref<jobject>,
|
||||
jlong nativePointer,
|
||||
jboolean hasMeasureFunc) {
|
||||
CSSNodeSetMeasureFunc(_jlong2CSSNodeRef(nativePointer), hasMeasureFunc ? _jniMeasureFunc : NULL);
|
||||
}
|
||||
|
||||
jboolean jni_CSSNodeHasNewLayout(alias_ref<jobject>, jlong nativePointer) {
|
||||
return (jboolean) CSSNodeGetHasNewLayout(_jlong2CSSNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
void jni_CSSNodeMarkLayoutSeen(alias_ref<jobject>, jlong nativePointer) {
|
||||
CSSNodeSetHasNewLayout(_jlong2CSSNodeRef(nativePointer), false);
|
||||
}
|
||||
|
||||
void jni_CSSNodeCopyStyle(alias_ref<jobject>, jlong dstNativePointer, jlong srcNativePointer) {
|
||||
CSSNodeCopyStyle(_jlong2CSSNodeRef(dstNativePointer), _jlong2CSSNodeRef(srcNativePointer));
|
||||
}
|
||||
|
||||
#define CSS_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
||||
javatype jni_CSSNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer) { \
|
||||
return (javatype) CSSNodeStyleGet##name(_jlong2CSSNodeRef(nativePointer)); \
|
||||
} \
|
||||
\
|
||||
void jni_CSSNodeStyleSet##name(alias_ref<jobject>, jlong nativePointer, javatype value) { \
|
||||
CSSNodeStyleSet##name(_jlong2CSSNodeRef(nativePointer), static_cast<type>(value)); \
|
||||
}
|
||||
|
||||
#define CSS_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \
|
||||
javatype jni_CSSNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer, jint edge) { \
|
||||
return (javatype) CSSNodeStyleGet##name(_jlong2CSSNodeRef(nativePointer), \
|
||||
static_cast<YGEdge>(edge)); \
|
||||
} \
|
||||
\
|
||||
void jni_CSSNodeStyleSet##name(alias_ref<jobject>, \
|
||||
jlong nativePointer, \
|
||||
jint edge, \
|
||||
javatype value) { \
|
||||
CSSNodeStyleSet##name(_jlong2CSSNodeRef(nativePointer), \
|
||||
static_cast<YGEdge>(edge), \
|
||||
static_cast<type>(value)); \
|
||||
}
|
||||
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGFlexDirection, FlexDirection);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGJustify, JustifyContent);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignItems);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignSelf);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGAlign, AlignContent);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGPositionType, PositionType);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap);
|
||||
CSS_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow);
|
||||
|
||||
void jni_CSSNodeStyleSetFlex(alias_ref<jobject>, jlong nativePointer, jfloat value) {
|
||||
CSSNodeStyleSetFlex(_jlong2CSSNodeRef(nativePointer), static_cast<float>(value));
|
||||
}
|
||||
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);
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
CSS_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
|
||||
|
||||
#define CSSMakeNativeMethod(name) makeNativeMethod(#name, name)
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return initialize(vm, [] {
|
||||
registerNatives("com/facebook/csslayout/CSSNode",
|
||||
{
|
||||
CSSMakeNativeMethod(jni_CSSNodeNew),
|
||||
CSSMakeNativeMethod(jni_CSSNodeFree),
|
||||
CSSMakeNativeMethod(jni_CSSNodeReset),
|
||||
CSSMakeNativeMethod(jni_CSSNodeInsertChild),
|
||||
CSSMakeNativeMethod(jni_CSSNodeRemoveChild),
|
||||
CSSMakeNativeMethod(jni_CSSNodeCalculateLayout),
|
||||
CSSMakeNativeMethod(jni_CSSNodeHasNewLayout),
|
||||
CSSMakeNativeMethod(jni_CSSNodeMarkDirty),
|
||||
CSSMakeNativeMethod(jni_CSSNodeIsDirty),
|
||||
CSSMakeNativeMethod(jni_CSSNodeMarkLayoutSeen),
|
||||
CSSMakeNativeMethod(jni_CSSNodeSetHasMeasureFunc),
|
||||
CSSMakeNativeMethod(jni_CSSNodeCopyStyle),
|
||||
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetDirection),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetDirection),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetFlexDirection),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlexDirection),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetJustifyContent),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetJustifyContent),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetAlignItems),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetAlignItems),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetAlignSelf),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetAlignSelf),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetAlignContent),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetAlignContent),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetPositionType),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetPositionType),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlexWrap),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetOverflow),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetOverflow),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlex),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetFlexGrow),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlexGrow),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetFlexShrink),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlexShrink),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetFlexBasis),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetFlexBasis),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetMargin),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetMargin),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetPadding),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetPadding),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetBorder),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetBorder),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetPosition),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetPosition),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetMinWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetMinWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetMinHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetMinHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetMaxWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxWidth),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetMaxHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetMaxHeight),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleGetAspectRatio),
|
||||
CSSMakeNativeMethod(jni_CSSNodeStyleSetAspectRatio),
|
||||
|
||||
CSSMakeNativeMethod(jni_CSSNodeGetInstanceCount),
|
||||
CSSMakeNativeMethod(jni_CSSLayoutSetLogger),
|
||||
CSSMakeNativeMethod(jni_CSSLog),
|
||||
CSSMakeNativeMethod(jni_CSSLayoutSetExperimentalFeatureEnabled),
|
||||
CSSMakeNativeMethod(jni_CSSLayoutIsExperimentalFeatureEnabled),
|
||||
});
|
||||
});
|
||||
}
|
333
java/jni/YGJNI.cpp
Normal file
333
java/jni/YGJNI.cpp
Normal file
@@ -0,0 +1,333 @@
|
||||
/**
|
||||
* 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 <CSSLayout/Yoga.h>
|
||||
#include <fb/fbjni.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace facebook::jni;
|
||||
using namespace std;
|
||||
|
||||
static inline weak_ref<jobject> *YGNodeJobject(YGNodeRef node) {
|
||||
return reinterpret_cast<weak_ref<jobject> *>(YGNodeGetContext(node));
|
||||
}
|
||||
|
||||
static void YGTransferLayoutDirection(YGNodeRef node, alias_ref<jobject> javaNode) {
|
||||
static auto layoutDirectionField = javaNode->getClass()->getField<jint>("mLayoutDirection");
|
||||
javaNode->setFieldValue(layoutDirectionField, static_cast<jint>(YGNodeLayoutGetDirection(node)));
|
||||
}
|
||||
|
||||
static void YGTransferLayoutOutputsRecursive(YGNodeRef root) {
|
||||
if (auto obj = YGNodeJobject(root)->lockLocal()) {
|
||||
static auto widthField = obj->getClass()->getField<jfloat>("mWidth");
|
||||
static auto heightField = obj->getClass()->getField<jfloat>("mHeight");
|
||||
static auto leftField = obj->getClass()->getField<jfloat>("mLeft");
|
||||
static auto topField = obj->getClass()->getField<jfloat>("mTop");
|
||||
|
||||
obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root));
|
||||
obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root));
|
||||
obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root));
|
||||
obj->setFieldValue(topField, YGNodeLayoutGetTop(root));
|
||||
YGTransferLayoutDirection(root, obj);
|
||||
|
||||
for (uint32_t i = 0; i < YGNodeChildCount(root); i++) {
|
||||
YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i));
|
||||
}
|
||||
} else {
|
||||
YGLog(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(YGLogLevelError, "Java YGNode was GCed during layout calculation\n");
|
||||
}
|
||||
}
|
||||
|
||||
static YGSize YGJNIMeasureFunc(YGNodeRef node,
|
||||
float width,
|
||||
YGMeasureMode widthMode,
|
||||
float height,
|
||||
YGMeasureMode heightMode) {
|
||||
if (auto obj = YGNodeJobject(node)->lockLocal()) {
|
||||
static auto measureFunc = findClassLocal("com/facebook/csslayout/CSSNode")
|
||||
->getMethod<jlong(jfloat, jint, jfloat, jint)>("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");
|
||||
|
||||
const float measuredWidth = static_cast<float>(0xFFFFFFFF & (measureResult >> 32));
|
||||
const float measuredHeight = static_cast<float>(0xFFFFFFFF & measureResult);
|
||||
|
||||
return YGSize{measuredWidth, measuredHeight};
|
||||
} else {
|
||||
YGLog(YGLogLevelError, "Java YGNode was GCed during layout calculation\n");
|
||||
return YGSize{
|
||||
widthMode == YGMeasureModeUndefined ? 0 : width,
|
||||
heightMode == YGMeasureModeUndefined ? 0 : height,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
struct JYogaLogLevel : public JavaClass<JYogaLogLevel> {
|
||||
static constexpr auto kJavaDescriptor = "Lcom/facebook/csslayout/YogaLogLevel;";
|
||||
};
|
||||
|
||||
static global_ref<jobject> *jLogger;
|
||||
static int YGLog(YGLogLevel level, const char *format, va_list args) {
|
||||
char buffer[256];
|
||||
int result = vsnprintf(buffer, sizeof(buffer), format, args);
|
||||
|
||||
static auto logFunc = findClassLocal("com/facebook/csslayout/CSSLogger")
|
||||
->getMethod<void(local_ref<JYogaLogLevel>, jstring)>("log");
|
||||
|
||||
static auto logLevelFromInt =
|
||||
JYogaLogLevel::javaClassStatic()->getStaticMethod<JYogaLogLevel::javaobject(jint)>("fromInt");
|
||||
|
||||
logFunc(jLogger->get(),
|
||||
logLevelFromInt(JYogaLogLevel::javaClassStatic(), static_cast<jint>(level)),
|
||||
Environment::current()->NewStringUTF(buffer));
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
|
||||
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
|
||||
}
|
||||
|
||||
void jni_YGSetLogger(alias_ref<jclass> clazz, alias_ref<jobject> logger) {
|
||||
if (jLogger) {
|
||||
jLogger->releaseAlias();
|
||||
delete jLogger;
|
||||
}
|
||||
|
||||
if (logger) {
|
||||
jLogger = new global_ref<jobject>(make_global(logger));
|
||||
YGSetLogger(YGLog);
|
||||
} else {
|
||||
jLogger = NULL;
|
||||
YGSetLogger(NULL);
|
||||
}
|
||||
}
|
||||
|
||||
void jni_YGLog(alias_ref<jclass> clazz, jint level, jstring message) {
|
||||
const char *nMessage = Environment::current()->GetStringUTFChars(message, 0);
|
||||
YGLog(static_cast<YGLogLevel>(level), "%s", nMessage);
|
||||
Environment::current()->ReleaseStringUTFChars(message, nMessage);
|
||||
}
|
||||
|
||||
void jni_YGSetExperimentalFeatureEnabled(alias_ref<jclass> clazz, jint feature, jboolean enabled) {
|
||||
YGSetExperimentalFeatureEnabled(static_cast<YGExperimentalFeature>(feature), enabled);
|
||||
}
|
||||
|
||||
jboolean jni_YGIsExperimentalFeatureEnabled(alias_ref<jclass> clazz, jint feature) {
|
||||
return YGIsExperimentalFeatureEnabled(static_cast<YGExperimentalFeature>(feature));
|
||||
}
|
||||
|
||||
jint jni_YGNodeGetInstanceCount(alias_ref<jclass> clazz) {
|
||||
return YGNodeGetInstanceCount();
|
||||
}
|
||||
|
||||
jlong jni_YGNodeNew(alias_ref<jobject> thiz) {
|
||||
const YGNodeRef node = YGNodeNew();
|
||||
YGNodeSetContext(node, new weak_ref<jobject>(make_weak(thiz)));
|
||||
YGNodeSetPrintFunc(node, YGPrint);
|
||||
return reinterpret_cast<jlong>(node);
|
||||
}
|
||||
|
||||
void jni_YGNodeFree(alias_ref<jobject> thiz, jlong nativePointer) {
|
||||
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
||||
delete YGNodeJobject(node);
|
||||
YGNodeFree(node);
|
||||
}
|
||||
|
||||
void jni_YGNodeReset(alias_ref<jobject> thiz, jlong nativePointer) {
|
||||
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
||||
void *context = YGNodeGetContext(node);
|
||||
YGNodeReset(node);
|
||||
YGNodeSetContext(node, context);
|
||||
YGNodeSetPrintFunc(node, YGPrint);
|
||||
}
|
||||
|
||||
void jni_YGNodeInsertChild(alias_ref<jobject>, jlong nativePointer, jlong childPointer, jint index) {
|
||||
YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
|
||||
}
|
||||
|
||||
void jni_YGNodeRemoveChild(alias_ref<jobject>, jlong nativePointer, jlong childPointer) {
|
||||
YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
|
||||
}
|
||||
|
||||
void jni_YGNodeCalculateLayout(alias_ref<jobject>, jlong nativePointer) {
|
||||
const YGNodeRef root = _jlong2YGNodeRef(nativePointer);
|
||||
YGNodeCalculateLayout(root,
|
||||
YGUndefined,
|
||||
YGUndefined,
|
||||
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)));
|
||||
YGTransferLayoutOutputsRecursive(root);
|
||||
}
|
||||
|
||||
void jni_YGNodeMarkDirty(alias_ref<jobject>, jlong nativePointer) {
|
||||
YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
jboolean jni_YGNodeIsDirty(alias_ref<jobject>, jlong nativePointer) {
|
||||
return (jboolean) YGNodeIsDirty(_jlong2YGNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
void jni_YGNodeSetHasMeasureFunc(alias_ref<jobject>, jlong nativePointer, jboolean hasMeasureFunc) {
|
||||
YGNodeSetMeasureFunc(_jlong2YGNodeRef(nativePointer), hasMeasureFunc ? YGJNIMeasureFunc : NULL);
|
||||
}
|
||||
|
||||
jboolean jni_YGNodeHasNewLayout(alias_ref<jobject>, jlong nativePointer) {
|
||||
return (jboolean) YGNodeGetHasNewLayout(_jlong2YGNodeRef(nativePointer));
|
||||
}
|
||||
|
||||
void jni_YGNodeMarkLayoutSeen(alias_ref<jobject>, jlong nativePointer) {
|
||||
YGNodeSetHasNewLayout(_jlong2YGNodeRef(nativePointer), false);
|
||||
}
|
||||
|
||||
void jni_YGNodeCopyStyle(alias_ref<jobject>, jlong dstNativePointer, jlong srcNativePointer) {
|
||||
YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer));
|
||||
}
|
||||
|
||||
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
||||
javatype jni_YGNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer) { \
|
||||
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
|
||||
} \
|
||||
\
|
||||
void jni_YGNodeStyleSet##name(alias_ref<jobject>, jlong nativePointer, javatype value) { \
|
||||
YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
|
||||
}
|
||||
|
||||
#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \
|
||||
javatype jni_YGNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer, jint edge) { \
|
||||
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \
|
||||
static_cast<YGEdge>(edge)); \
|
||||
} \
|
||||
\
|
||||
void jni_YGNodeStyleSet##name(alias_ref<jobject>, \
|
||||
jlong nativePointer, \
|
||||
jint edge, \
|
||||
javatype value) { \
|
||||
YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \
|
||||
static_cast<YGEdge>(edge), \
|
||||
static_cast<type>(value)); \
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
void jni_YGNodeStyleSetFlex(alias_ref<jobject>, jlong nativePointer, jfloat value) {
|
||||
YGNodeStyleSetFlex(_jlong2YGNodeRef(nativePointer), static_cast<float>(value));
|
||||
}
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexBasis);
|
||||
|
||||
YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Position);
|
||||
YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Margin);
|
||||
YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Padding);
|
||||
YG_NODE_JNI_STYLE_EDGE_PROP(jfloat, float, Border);
|
||||
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, Width);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, MinWidth);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, MaxWidth);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, Height);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, MinHeight);
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, MaxHeight);
|
||||
|
||||
// Yoga specific properties, not compatible with flexbox specification
|
||||
YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
|
||||
|
||||
#define YGMakeNativeMethod(name) makeNativeMethod(#name, name)
|
||||
|
||||
jint JNI_OnLoad(JavaVM *vm, void *) {
|
||||
return initialize(vm, [] {
|
||||
registerNatives("com/facebook/csslayout/CSSNode",
|
||||
{
|
||||
YGMakeNativeMethod(jni_YGNodeNew),
|
||||
YGMakeNativeMethod(jni_YGNodeFree),
|
||||
YGMakeNativeMethod(jni_YGNodeReset),
|
||||
YGMakeNativeMethod(jni_YGNodeInsertChild),
|
||||
YGMakeNativeMethod(jni_YGNodeRemoveChild),
|
||||
YGMakeNativeMethod(jni_YGNodeCalculateLayout),
|
||||
YGMakeNativeMethod(jni_YGNodeHasNewLayout),
|
||||
YGMakeNativeMethod(jni_YGNodeMarkDirty),
|
||||
YGMakeNativeMethod(jni_YGNodeIsDirty),
|
||||
YGMakeNativeMethod(jni_YGNodeMarkLayoutSeen),
|
||||
YGMakeNativeMethod(jni_YGNodeSetHasMeasureFunc),
|
||||
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_YGNodeStyleSetFlex),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetFlexGrow),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetFlexGrow),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetFlexShrink),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetFlexShrink),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetFlexBasis),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetFlexBasis),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetMargin),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetMargin),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetPadding),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetPadding),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetBorder),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetBorder),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetPosition),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetPosition),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetMinWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetMinWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetMinHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetMinHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetMaxWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetMaxWidth),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetMaxHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetMaxHeight),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleGetAspectRatio),
|
||||
YGMakeNativeMethod(jni_YGNodeStyleSetAspectRatio),
|
||||
|
||||
YGMakeNativeMethod(jni_YGNodeGetInstanceCount),
|
||||
YGMakeNativeMethod(jni_YGSetLogger),
|
||||
YGMakeNativeMethod(jni_YGLog),
|
||||
YGMakeNativeMethod(jni_YGSetExperimentalFeatureEnabled),
|
||||
YGMakeNativeMethod(jni_YGIsExperimentalFeatureEnabled),
|
||||
});
|
||||
});
|
||||
}
|
Reference in New Issue
Block a user