Summary: X-link: https://github.com/facebook/react-native/pull/37243 X-link: https://github.com/facebook/litho/pull/944 Pull Request resolved: https://github.com/facebook/yoga/pull/1279 Java bindings for Yoga rely solely on garbage collection for memory management. Each Java `YogaNode` has references to its children and parent Java Nodes. This means, for a node to be garbage collected, it cannot be reachable from any user accessible node. Each node then has single ownership of a `YGNodeRef`. When the `YogaNode` is garbage collected, a finalizer is run to call `YGNodeFree` and free the underlying native Yoga Node. This may cause a use-after-free if finalizers are run from multiple threads. This is because `YGNodeFree` does more than just freeing, but instead also interacts with its parent and children nodes to detach itself, and remove any dangling pointers. If multiple threads run finalizers at once, one may traverse and try to mutate a node which another is freeing. Because we know the entire connected tree is dead, there is no need to remove dangling pointers, so I want to expose a way to just free a Yoga Node, without it mutating the tree as a side effect. This adds a currently private `YGNodeDeallocate` that frees without traversal. Ideally from naming this is what `YGNodeFree` would do, but we think changing the behavior of that might be too disruptive to OSS. At the same time there may be other memory safety related API changes we would like to eventually make, so this isn't made public beyond the JNI bindings to prevent needing to transition more APIs. Changelog: [Internal] Reviewed By: rshest Differential Revision: D45556206 fbshipit-source-id: 62a1394c6f6bdc2b437b388098ea362a0fbcd0f7
1001 lines
34 KiB
C++
1001 lines
34 KiB
C++
/*
|
|
* Copyright (c) Meta Platforms, Inc. and affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "jni.h"
|
|
#include "YGJNIVanilla.h"
|
|
#include <cstring>
|
|
#include "YGJNI.h"
|
|
#include "common.h"
|
|
#include "YGJTypesVanilla.h"
|
|
#include <iostream>
|
|
#include <memory>
|
|
#include "YogaJniException.h"
|
|
|
|
// TODO: Reconcile missing layoutContext functionality from callbacks in the C
|
|
// API and use that
|
|
#include <yoga/YGNode.h>
|
|
|
|
using namespace facebook::yoga::vanillajni;
|
|
|
|
static inline ScopedLocalRef<jobject> YGNodeJobject(
|
|
YGNodeRef node,
|
|
void* layoutContext) {
|
|
return reinterpret_cast<PtrJNodeMapVanilla*>(layoutContext)->ref(node);
|
|
}
|
|
|
|
static inline YGNodeRef _jlong2YGNodeRef(jlong addr) {
|
|
return reinterpret_cast<YGNodeRef>(static_cast<intptr_t>(addr));
|
|
}
|
|
|
|
static inline YGConfigRef _jlong2YGConfigRef(jlong addr) {
|
|
return reinterpret_cast<YGConfigRef>(static_cast<intptr_t>(addr));
|
|
}
|
|
|
|
static jlong jni_YGConfigNewJNI(JNIEnv* env, jobject obj) {
|
|
return reinterpret_cast<jlong>(YGConfigNew());
|
|
}
|
|
|
|
static void jni_YGConfigFreeJNI(JNIEnv* env, jobject obj, jlong nativePointer) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
// unique_ptr will destruct the underlying global_ref, if present.
|
|
auto context = std::unique_ptr<ScopedGlobalRef<jobject>>{
|
|
static_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config))};
|
|
YGConfigFree(config);
|
|
}
|
|
|
|
static void jni_YGConfigSetExperimentalFeatureEnabledJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint feature,
|
|
jboolean enabled) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
YGConfigSetExperimentalFeatureEnabled(
|
|
config, static_cast<YGExperimentalFeature>(feature), enabled);
|
|
}
|
|
|
|
static void jni_YGConfigSetUseWebDefaultsJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean useWebDefaults) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
YGConfigSetUseWebDefaults(config, useWebDefaults);
|
|
}
|
|
|
|
static void jni_YGConfigSetPrintTreeFlagJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean enable) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
YGConfigSetPrintTreeFlag(config, enable);
|
|
}
|
|
|
|
static void jni_YGConfigSetPointScaleFactorJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jfloat pixelsInPoint) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
YGConfigSetPointScaleFactor(config, pixelsInPoint);
|
|
}
|
|
|
|
static void jni_YGConfigSetUseLegacyStretchBehaviourJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean useLegacyStretchBehaviour) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
#pragma clang diagnostic push
|
|
#pragma clang diagnostic ignored "-Wdeprecated"
|
|
YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour);
|
|
#pragma clang diagnostic pop
|
|
}
|
|
|
|
static void jni_YGConfigSetErrataJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint errata) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
YGConfigSetErrata(config, static_cast<YGErrata>(errata));
|
|
}
|
|
|
|
static jint jni_YGConfigGetErrataJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
return static_cast<jint>(YGConfigGetErrata(config));
|
|
}
|
|
|
|
static jlong jni_YGNodeNewJNI(JNIEnv* env, jobject obj) {
|
|
const YGNodeRef node = YGNodeNew();
|
|
YGNodeSetContext(node, YGNodeContext{}.asVoidPtr);
|
|
return reinterpret_cast<jlong>(node);
|
|
}
|
|
|
|
static jlong jni_YGNodeNewWithConfigJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong configPointer) {
|
|
const YGNodeRef node = YGNodeNewWithConfig(_jlong2YGConfigRef(configPointer));
|
|
YGNodeSetContext(node, YGNodeContext{}.asVoidPtr);
|
|
return reinterpret_cast<jlong>(node);
|
|
}
|
|
|
|
static int YGJNILogFunc(
|
|
const YGConfigRef config,
|
|
const YGNodeRef node,
|
|
YGLogLevel level,
|
|
void* layoutContext,
|
|
const char* format,
|
|
va_list args) {
|
|
int result = vsnprintf(NULL, 0, format, args);
|
|
std::vector<char> buffer(1 + result);
|
|
vsnprintf(buffer.data(), buffer.size(), format, args);
|
|
|
|
auto jloggerPtr =
|
|
static_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config));
|
|
if (jloggerPtr != nullptr) {
|
|
if (*jloggerPtr) {
|
|
JNIEnv* env = getCurrentEnv();
|
|
|
|
jclass cl = env->FindClass("com/facebook/yoga/YogaLogLevel");
|
|
static const jmethodID smethodId =
|
|
facebook::yoga::vanillajni::getStaticMethodId(
|
|
env, cl, "fromInt", "(I)Lcom/facebook/yoga/YogaLogLevel;");
|
|
ScopedLocalRef<jobject> logLevel =
|
|
facebook::yoga::vanillajni::callStaticObjectMethod(
|
|
env, cl, smethodId, level);
|
|
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
env, env->GetObjectClass((*jloggerPtr).get()));
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
env,
|
|
objectClass.get(),
|
|
"log",
|
|
"(Lcom/facebook/yoga/YogaLogLevel;Ljava/lang/String;)V");
|
|
facebook::yoga::vanillajni::callVoidMethod(
|
|
env,
|
|
(*jloggerPtr).get(),
|
|
methodId,
|
|
logLevel.get(),
|
|
env->NewStringUTF(buffer.data()));
|
|
}
|
|
}
|
|
|
|
return result;
|
|
}
|
|
|
|
static void jni_YGConfigSetLoggerJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jobject logger) {
|
|
const YGConfigRef config = _jlong2YGConfigRef(nativePointer);
|
|
auto context =
|
|
reinterpret_cast<ScopedGlobalRef<jobject>*>(YGConfigGetContext(config));
|
|
|
|
if (logger) {
|
|
if (context == nullptr) {
|
|
context = new ScopedGlobalRef<jobject>();
|
|
YGConfigSetContext(config, context);
|
|
}
|
|
|
|
*context = newGlobalRef(env, logger);
|
|
config->setLogger(YGJNILogFunc);
|
|
} else {
|
|
if (context != nullptr) {
|
|
delete context;
|
|
YGConfigSetContext(config, nullptr);
|
|
}
|
|
YGConfigSetLogger(config, nullptr);
|
|
}
|
|
}
|
|
|
|
static void jni_YGNodeDeallocateJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
if (nativePointer == 0) {
|
|
return;
|
|
}
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeFree(node);
|
|
}
|
|
|
|
static void jni_YGNodeResetJNI(JNIEnv* env, jobject obj, jlong nativePointer) {
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
|
void* context = YGNodeGetContext(node);
|
|
YGNodeReset(node);
|
|
YGNodeSetContext(node, context);
|
|
}
|
|
|
|
static void jni_YGNodeInsertChildJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jlong childPointer,
|
|
jint index) {
|
|
YGNodeInsertChild(
|
|
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
|
|
}
|
|
|
|
static void jni_YGNodeSwapChildJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jlong childPointer,
|
|
jint index) {
|
|
YGNodeSwapChild(
|
|
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index);
|
|
}
|
|
|
|
static void jni_YGNodeSetIsReferenceBaselineJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean isReferenceBaseline) {
|
|
YGNodeSetIsReferenceBaseline(
|
|
_jlong2YGNodeRef(nativePointer), isReferenceBaseline);
|
|
}
|
|
|
|
static jboolean jni_YGNodeIsReferenceBaselineJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
return YGNodeIsReferenceBaseline(_jlong2YGNodeRef(nativePointer));
|
|
}
|
|
|
|
static void jni_YGNodeRemoveAllChildrenJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeRemoveAllChildren(node);
|
|
}
|
|
|
|
static void jni_YGNodeRemoveChildJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jlong childPointer) {
|
|
YGNodeRemoveChild(
|
|
_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer));
|
|
}
|
|
|
|
static void YGTransferLayoutOutputsRecursive(
|
|
JNIEnv* env,
|
|
jobject thiz,
|
|
YGNodeRef root,
|
|
void* layoutContext) {
|
|
if (!YGNodeGetHasNewLayout(root)) {
|
|
return;
|
|
}
|
|
auto obj = YGNodeJobject(root, layoutContext);
|
|
if (!obj) {
|
|
return;
|
|
}
|
|
|
|
auto edgesSet = YGNodeEdges{root};
|
|
|
|
bool marginFieldSet = edgesSet.has(YGNodeEdges::MARGIN);
|
|
bool paddingFieldSet = edgesSet.has(YGNodeEdges::PADDING);
|
|
bool borderFieldSet = edgesSet.has(YGNodeEdges::BORDER);
|
|
|
|
int fieldFlags = edgesSet.get();
|
|
fieldFlags |= HAS_NEW_LAYOUT;
|
|
|
|
const int arrSize = 6 + (marginFieldSet ? 4 : 0) + (paddingFieldSet ? 4 : 0) +
|
|
(borderFieldSet ? 4 : 0);
|
|
float arr[18];
|
|
arr[LAYOUT_EDGE_SET_FLAG_INDEX] = fieldFlags;
|
|
arr[LAYOUT_WIDTH_INDEX] = YGNodeLayoutGetWidth(root);
|
|
arr[LAYOUT_HEIGHT_INDEX] = YGNodeLayoutGetHeight(root);
|
|
arr[LAYOUT_LEFT_INDEX] = YGNodeLayoutGetLeft(root);
|
|
arr[LAYOUT_TOP_INDEX] = YGNodeLayoutGetTop(root);
|
|
arr[LAYOUT_DIRECTION_INDEX] =
|
|
static_cast<jint>(YGNodeLayoutGetDirection(root));
|
|
if (marginFieldSet) {
|
|
arr[LAYOUT_MARGIN_START_INDEX] = YGNodeLayoutGetMargin(root, YGEdgeLeft);
|
|
arr[LAYOUT_MARGIN_START_INDEX + 1] = YGNodeLayoutGetMargin(root, YGEdgeTop);
|
|
arr[LAYOUT_MARGIN_START_INDEX + 2] =
|
|
YGNodeLayoutGetMargin(root, YGEdgeRight);
|
|
arr[LAYOUT_MARGIN_START_INDEX + 3] =
|
|
YGNodeLayoutGetMargin(root, YGEdgeBottom);
|
|
}
|
|
if (paddingFieldSet) {
|
|
int paddingStartIndex =
|
|
LAYOUT_PADDING_START_INDEX - (marginFieldSet ? 0 : 4);
|
|
arr[paddingStartIndex] = YGNodeLayoutGetPadding(root, YGEdgeLeft);
|
|
arr[paddingStartIndex + 1] = YGNodeLayoutGetPadding(root, YGEdgeTop);
|
|
arr[paddingStartIndex + 2] = YGNodeLayoutGetPadding(root, YGEdgeRight);
|
|
arr[paddingStartIndex + 3] = YGNodeLayoutGetPadding(root, YGEdgeBottom);
|
|
}
|
|
|
|
if (borderFieldSet) {
|
|
int borderStartIndex = LAYOUT_BORDER_START_INDEX -
|
|
(marginFieldSet ? 0 : 4) - (paddingFieldSet ? 0 : 4);
|
|
arr[borderStartIndex] = YGNodeLayoutGetBorder(root, YGEdgeLeft);
|
|
arr[borderStartIndex + 1] = YGNodeLayoutGetBorder(root, YGEdgeTop);
|
|
arr[borderStartIndex + 2] = YGNodeLayoutGetBorder(root, YGEdgeRight);
|
|
arr[borderStartIndex + 3] = YGNodeLayoutGetBorder(root, YGEdgeBottom);
|
|
}
|
|
|
|
// Don't change this field name without changing the name of the field in
|
|
// Database.java
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
env, env->GetObjectClass(obj.get()));
|
|
static const jfieldID arrField = facebook::yoga::vanillajni::getFieldId(
|
|
env, objectClass.get(), "arr", "[F");
|
|
|
|
ScopedLocalRef<jfloatArray> arrFinal =
|
|
make_local_ref(env, env->NewFloatArray(arrSize));
|
|
env->SetFloatArrayRegion(arrFinal.get(), 0, arrSize, arr);
|
|
env->SetObjectField(obj.get(), arrField, arrFinal.get());
|
|
|
|
YGNodeSetHasNewLayout(root, false);
|
|
|
|
for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) {
|
|
YGTransferLayoutOutputsRecursive(
|
|
env, thiz, YGNodeGetChild(root, i), layoutContext);
|
|
}
|
|
}
|
|
|
|
static void jni_YGNodeCalculateLayoutJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jfloat width,
|
|
jfloat height,
|
|
jlongArray nativePointers,
|
|
jobjectArray javaNodes) {
|
|
|
|
try {
|
|
void* layoutContext = nullptr;
|
|
auto map = PtrJNodeMapVanilla{};
|
|
if (nativePointers) {
|
|
map = PtrJNodeMapVanilla{nativePointers, javaNodes};
|
|
layoutContext = ↦
|
|
}
|
|
|
|
const YGNodeRef root = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeCalculateLayoutWithContext(
|
|
root,
|
|
static_cast<float>(width),
|
|
static_cast<float>(height),
|
|
YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer)),
|
|
layoutContext);
|
|
YGTransferLayoutOutputsRecursive(env, obj, root, layoutContext);
|
|
} catch (const YogaJniException& jniException) {
|
|
ScopedLocalRef<jthrowable> throwable = jniException.getThrowable();
|
|
if (throwable.get()) {
|
|
env->Throw(throwable.get());
|
|
}
|
|
} catch (const std::logic_error& ex) {
|
|
env->ExceptionClear();
|
|
jclass cl = env->FindClass("java/lang/IllegalStateException");
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
env, cl, "<init>", "(Ljava/lang/String;)V");
|
|
auto throwable = env->NewObject(cl, methodId, env->NewStringUTF(ex.what()));
|
|
env->Throw(static_cast<jthrowable>(throwable));
|
|
}
|
|
}
|
|
|
|
static void jni_YGNodeMarkDirtyJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
YGNodeMarkDirty(_jlong2YGNodeRef(nativePointer));
|
|
}
|
|
|
|
static void jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
YGNodeMarkDirtyAndPropagateToDescendants(_jlong2YGNodeRef(nativePointer));
|
|
}
|
|
|
|
static jboolean jni_YGNodeIsDirtyJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer) {
|
|
return (jboolean) YGNodeIsDirty(_jlong2YGNodeRef(nativePointer));
|
|
}
|
|
|
|
static void jni_YGNodeCopyStyleJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong dstNativePointer,
|
|
jlong srcNativePointer) {
|
|
YGNodeCopyStyle(
|
|
_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer));
|
|
}
|
|
|
|
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
|
static javatype jni_YGNodeStyleGet##name##JNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer) { \
|
|
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
|
|
} \
|
|
\
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer, javatype value) { \
|
|
YGNodeStyleSet##name( \
|
|
_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
|
|
}
|
|
|
|
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
|
|
static jlong jni_YGNodeStyleGet##name##JNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer) { \
|
|
return YogaValue::asJavaLong( \
|
|
YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \
|
|
} \
|
|
\
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer, jfloat value) { \
|
|
YGNodeStyleSet##name( \
|
|
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
|
|
} \
|
|
\
|
|
static void jni_YGNodeStyleSet##name##PercentJNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer, jfloat value) { \
|
|
YGNodeStyleSet##name##Percent( \
|
|
_jlong2YGNodeRef(nativePointer), static_cast<float>(value)); \
|
|
}
|
|
|
|
#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \
|
|
YG_NODE_JNI_STYLE_UNIT_PROP(name) \
|
|
static void jni_YGNodeStyleSet##name##AutoJNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer) { \
|
|
YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \
|
|
}
|
|
|
|
#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \
|
|
static jlong jni_YGNodeStyleGet##name##JNI( \
|
|
JNIEnv* env, jobject obj, jlong nativePointer, jint edge) { \
|
|
return YogaValue::asJavaLong(YGNodeStyleGet##name( \
|
|
_jlong2YGNodeRef(nativePointer), static_cast<YGEdge>(edge))); \
|
|
} \
|
|
\
|
|
static void jni_YGNodeStyleSet##name##JNI( \
|
|
JNIEnv* env, \
|
|
jobject obj, \
|
|
jlong nativePointer, \
|
|
jint edge, \
|
|
jfloat value) { \
|
|
YGNodeStyleSet##name( \
|
|
_jlong2YGNodeRef(nativePointer), \
|
|
static_cast<YGEdge>(edge), \
|
|
static_cast<float>(value)); \
|
|
} \
|
|
\
|
|
static void jni_YGNodeStyleSet##name##PercentJNI( \
|
|
JNIEnv* env, \
|
|
jobject obj, \
|
|
jlong nativePointer, \
|
|
jint edge, \
|
|
jfloat value) { \
|
|
YGNodeStyleSet##name##Percent( \
|
|
_jlong2YGNodeRef(nativePointer), \
|
|
static_cast<YGEdge>(edge), \
|
|
static_cast<float>(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);
|
|
YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display);
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, Flex);
|
|
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_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);
|
|
|
|
YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(Position);
|
|
|
|
static jlong jni_YGNodeStyleGetMarginJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::MARGIN)) {
|
|
return YogaValue::undefinedAsJavaLong();
|
|
}
|
|
return YogaValue::asJavaLong(
|
|
YGNodeStyleGetMargin(yogaNodeRef, static_cast<YGEdge>(edge)));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetMarginJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge,
|
|
jfloat margin) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
YGNodeStyleSetMargin(
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(margin));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetMarginPercentJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge,
|
|
jfloat percent) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
YGNodeStyleSetMarginPercent(
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetMarginAutoJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::MARGIN).setOn(yogaNodeRef);
|
|
YGNodeStyleSetMarginAuto(yogaNodeRef, static_cast<YGEdge>(edge));
|
|
}
|
|
|
|
static jlong jni_YGNodeStyleGetPaddingJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::PADDING)) {
|
|
return YogaValue::undefinedAsJavaLong();
|
|
}
|
|
return YogaValue::asJavaLong(
|
|
YGNodeStyleGetPadding(yogaNodeRef, static_cast<YGEdge>(edge)));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetPaddingJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge,
|
|
jfloat padding) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
|
|
YGNodeStyleSetPadding(
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(padding));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetPaddingPercentJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge,
|
|
jfloat percent) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::PADDING).setOn(yogaNodeRef);
|
|
YGNodeStyleSetPaddingPercent(
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(percent));
|
|
}
|
|
|
|
static jfloat jni_YGNodeStyleGetBorderJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
if (!YGNodeEdges{yogaNodeRef}.has(YGNodeEdges::BORDER)) {
|
|
return (jfloat) YGUndefined;
|
|
}
|
|
return (jfloat) YGNodeStyleGetBorder(yogaNodeRef, static_cast<YGEdge>(edge));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetBorderJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint edge,
|
|
jfloat border) {
|
|
YGNodeRef yogaNodeRef = _jlong2YGNodeRef(nativePointer);
|
|
YGNodeEdges{yogaNodeRef}.add(YGNodeEdges::BORDER).setOn(yogaNodeRef);
|
|
YGNodeStyleSetBorder(
|
|
yogaNodeRef, static_cast<YGEdge>(edge), static_cast<float>(border));
|
|
}
|
|
|
|
static void YGTransferLayoutDirection(YGNodeRef node, jobject javaNode) {
|
|
// Don't change this field name without changing the name of the field in
|
|
// Database.java
|
|
JNIEnv* env = getCurrentEnv();
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
env, env->GetObjectClass(javaNode));
|
|
static const jfieldID layoutDirectionField =
|
|
facebook::yoga::vanillajni::getFieldId(
|
|
env, objectClass.get(), "mLayoutDirection", "I");
|
|
env->SetIntField(
|
|
javaNode,
|
|
layoutDirectionField,
|
|
static_cast<jint>(YGNodeLayoutGetDirection(node)));
|
|
}
|
|
|
|
static YGSize YGJNIMeasureFunc(
|
|
YGNodeRef node,
|
|
float width,
|
|
YGMeasureMode widthMode,
|
|
float height,
|
|
YGMeasureMode heightMode,
|
|
void* layoutContext) {
|
|
if (auto obj = YGNodeJobject(node, layoutContext)) {
|
|
YGTransferLayoutDirection(node, obj.get());
|
|
JNIEnv* env = getCurrentEnv();
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
env, env->GetObjectClass(obj.get()));
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
env, objectClass.get(), "measure", "(FIFI)J");
|
|
const auto measureResult = facebook::yoga::vanillajni::callLongMethod(
|
|
env, obj.get(), methodId, 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<float*>(&wBits);
|
|
const float* measuredHeight = reinterpret_cast<float*>(&hBits);
|
|
|
|
return YGSize{*measuredWidth, *measuredHeight};
|
|
} else {
|
|
return YGSize{
|
|
widthMode == YGMeasureModeUndefined ? 0 : width,
|
|
heightMode == YGMeasureModeUndefined ? 0 : height,
|
|
};
|
|
}
|
|
}
|
|
|
|
static void jni_YGNodeSetHasMeasureFuncJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean hasMeasureFunc) {
|
|
_jlong2YGNodeRef(nativePointer)
|
|
->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr);
|
|
}
|
|
|
|
static float YGJNIBaselineFunc(
|
|
YGNodeRef node,
|
|
float width,
|
|
float height,
|
|
void* layoutContext) {
|
|
if (auto obj = YGNodeJobject(node, layoutContext)) {
|
|
JNIEnv* env = getCurrentEnv();
|
|
auto objectClass = facebook::yoga::vanillajni::make_local_ref(
|
|
env, env->GetObjectClass(obj.get()));
|
|
static const jmethodID methodId = facebook::yoga::vanillajni::getMethodId(
|
|
env, objectClass.get(), "baseline", "(FF)F");
|
|
return facebook::yoga::vanillajni::callFloatMethod(
|
|
env, obj.get(), methodId, width, height);
|
|
} else {
|
|
return height;
|
|
}
|
|
}
|
|
|
|
static void jni_YGNodeSetHasBaselineFuncJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jboolean hasBaselineFunc) {
|
|
_jlong2YGNodeRef(nativePointer)
|
|
->setBaselineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr);
|
|
}
|
|
|
|
static void jni_YGNodePrintJNI(JNIEnv* env, jobject obj, jlong nativePointer) {
|
|
#ifdef DEBUG
|
|
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
|
|
YGNodePrint(
|
|
node,
|
|
(YGPrintOptions) (YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren));
|
|
#endif
|
|
}
|
|
|
|
static jlong jni_YGNodeCloneJNI(JNIEnv* env, jobject obj, jlong nativePointer) {
|
|
auto node = _jlong2YGNodeRef(nativePointer);
|
|
const YGNodeRef clonedYogaNode = YGNodeClone(node);
|
|
YGNodeSetContext(clonedYogaNode, YGNodeGetContext(node));
|
|
|
|
return reinterpret_cast<jlong>(clonedYogaNode);
|
|
}
|
|
|
|
static jfloat jni_YGNodeStyleGetGapJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint gutter) {
|
|
return (jfloat) YGNodeStyleGetGap(
|
|
_jlong2YGNodeRef(nativePointer), static_cast<YGGutter>(gutter));
|
|
}
|
|
|
|
static void jni_YGNodeStyleSetGapJNI(
|
|
JNIEnv* env,
|
|
jobject obj,
|
|
jlong nativePointer,
|
|
jint gutter,
|
|
jfloat gapLength) {
|
|
YGNodeStyleSetGap(
|
|
_jlong2YGNodeRef(nativePointer),
|
|
static_cast<YGGutter>(gutter),
|
|
static_cast<float>(gapLength));
|
|
}
|
|
|
|
// Yoga specific properties, not compatible with flexbox specification
|
|
YG_NODE_JNI_STYLE_PROP(jfloat, float, AspectRatio);
|
|
|
|
static JNINativeMethod methods[] = {
|
|
{"jni_YGConfigNewJNI", "()J", (void*) jni_YGConfigNewJNI},
|
|
{"jni_YGConfigFreeJNI", "(J)V", (void*) jni_YGConfigFreeJNI},
|
|
{"jni_YGConfigSetExperimentalFeatureEnabledJNI",
|
|
"(JIZ)V",
|
|
(void*) jni_YGConfigSetExperimentalFeatureEnabledJNI},
|
|
{"jni_YGConfigSetUseWebDefaultsJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGConfigSetUseWebDefaultsJNI},
|
|
{"jni_YGConfigSetPrintTreeFlagJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGConfigSetPrintTreeFlagJNI},
|
|
{"jni_YGConfigSetPointScaleFactorJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGConfigSetPointScaleFactorJNI},
|
|
{"jni_YGConfigSetUseLegacyStretchBehaviourJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGConfigSetUseLegacyStretchBehaviourJNI},
|
|
{"jni_YGConfigSetErrataJNI", "(JI)V", (void*) jni_YGConfigSetErrataJNI},
|
|
{"jni_YGConfigGetErrataJNI", "(J)I", (void*) jni_YGConfigGetErrataJNI},
|
|
{"jni_YGConfigSetLoggerJNI",
|
|
"(JLcom/facebook/yoga/YogaLogger;)V",
|
|
(void*) jni_YGConfigSetLoggerJNI},
|
|
{"jni_YGNodeNewJNI", "()J", (void*) jni_YGNodeNewJNI},
|
|
{"jni_YGNodeNewWithConfigJNI", "(J)J", (void*) jni_YGNodeNewWithConfigJNI},
|
|
{"jni_YGNodeDeallocateJNI", "(J)V", (void*) jni_YGNodeDeallocateJNI},
|
|
{"jni_YGNodeResetJNI", "(J)V", (void*) jni_YGNodeResetJNI},
|
|
{"jni_YGNodeInsertChildJNI", "(JJI)V", (void*) jni_YGNodeInsertChildJNI},
|
|
{"jni_YGNodeSwapChildJNI", "(JJI)V", (void*) jni_YGNodeSwapChildJNI},
|
|
{"jni_YGNodeSetIsReferenceBaselineJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGNodeSetIsReferenceBaselineJNI},
|
|
{"jni_YGNodeIsReferenceBaselineJNI",
|
|
"(J)Z",
|
|
(void*) jni_YGNodeIsReferenceBaselineJNI},
|
|
{"jni_YGNodeRemoveAllChildrenJNI",
|
|
"(J)V",
|
|
(void*) jni_YGNodeRemoveAllChildrenJNI},
|
|
{"jni_YGNodeRemoveChildJNI", "(JJ)V", (void*) jni_YGNodeRemoveChildJNI},
|
|
{"jni_YGNodeCalculateLayoutJNI",
|
|
"(JFF[J[Lcom/facebook/yoga/YogaNodeJNIBase;)V",
|
|
(void*) jni_YGNodeCalculateLayoutJNI},
|
|
{"jni_YGNodeMarkDirtyJNI", "(J)V", (void*) jni_YGNodeMarkDirtyJNI},
|
|
{"jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI",
|
|
"(J)V",
|
|
(void*) jni_YGNodeMarkDirtyAndPropagateToDescendantsJNI},
|
|
{"jni_YGNodeIsDirtyJNI", "(J)Z", (void*) jni_YGNodeIsDirtyJNI},
|
|
{"jni_YGNodeCopyStyleJNI", "(JJ)V", (void*) jni_YGNodeCopyStyleJNI},
|
|
{"jni_YGNodeStyleGetDirectionJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetDirectionJNI},
|
|
{"jni_YGNodeStyleSetDirectionJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetDirectionJNI},
|
|
{"jni_YGNodeStyleGetFlexDirectionJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetFlexDirectionJNI},
|
|
{"jni_YGNodeStyleSetFlexDirectionJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetFlexDirectionJNI},
|
|
{"jni_YGNodeStyleGetJustifyContentJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetJustifyContentJNI},
|
|
{"jni_YGNodeStyleSetJustifyContentJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetJustifyContentJNI},
|
|
{"jni_YGNodeStyleGetAlignItemsJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetAlignItemsJNI},
|
|
{"jni_YGNodeStyleSetAlignItemsJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetAlignItemsJNI},
|
|
{"jni_YGNodeStyleGetAlignSelfJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetAlignSelfJNI},
|
|
{"jni_YGNodeStyleSetAlignSelfJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetAlignSelfJNI},
|
|
{"jni_YGNodeStyleGetAlignContentJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetAlignContentJNI},
|
|
{"jni_YGNodeStyleSetAlignContentJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetAlignContentJNI},
|
|
{"jni_YGNodeStyleGetPositionTypeJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetPositionTypeJNI},
|
|
{"jni_YGNodeStyleSetPositionTypeJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetPositionTypeJNI},
|
|
{"jni_YGNodeStyleGetFlexWrapJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetFlexWrapJNI},
|
|
{"jni_YGNodeStyleSetFlexWrapJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetFlexWrapJNI},
|
|
{"jni_YGNodeStyleGetOverflowJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetOverflowJNI},
|
|
{"jni_YGNodeStyleSetOverflowJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetOverflowJNI},
|
|
{"jni_YGNodeStyleGetDisplayJNI",
|
|
"(J)I",
|
|
(void*) jni_YGNodeStyleGetDisplayJNI},
|
|
{"jni_YGNodeStyleSetDisplayJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetDisplayJNI},
|
|
{"jni_YGNodeStyleGetFlexJNI", "(J)F", (void*) jni_YGNodeStyleGetFlexJNI},
|
|
{"jni_YGNodeStyleSetFlexJNI", "(JF)V", (void*) jni_YGNodeStyleSetFlexJNI},
|
|
{"jni_YGNodeStyleGetFlexGrowJNI",
|
|
"(J)F",
|
|
(void*) jni_YGNodeStyleGetFlexGrowJNI},
|
|
{"jni_YGNodeStyleSetFlexGrowJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetFlexGrowJNI},
|
|
{"jni_YGNodeStyleGetFlexShrinkJNI",
|
|
"(J)F",
|
|
(void*) jni_YGNodeStyleGetFlexShrinkJNI},
|
|
{"jni_YGNodeStyleSetFlexShrinkJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetFlexShrinkJNI},
|
|
{"jni_YGNodeStyleGetFlexBasisJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetFlexBasisJNI},
|
|
{"jni_YGNodeStyleSetFlexBasisJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetFlexBasisJNI},
|
|
{"jni_YGNodeStyleSetFlexBasisPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetFlexBasisPercentJNI},
|
|
{"jni_YGNodeStyleSetFlexBasisAutoJNI",
|
|
"(J)V",
|
|
(void*) jni_YGNodeStyleSetFlexBasisAutoJNI},
|
|
{"jni_YGNodeStyleGetMarginJNI",
|
|
"(JI)J",
|
|
(void*) jni_YGNodeStyleGetMarginJNI},
|
|
{"jni_YGNodeStyleSetMarginJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetMarginJNI},
|
|
{"jni_YGNodeStyleSetMarginPercentJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetMarginPercentJNI},
|
|
{"jni_YGNodeStyleSetMarginAutoJNI",
|
|
"(JI)V",
|
|
(void*) jni_YGNodeStyleSetMarginAutoJNI},
|
|
{"jni_YGNodeStyleGetPaddingJNI",
|
|
"(JI)J",
|
|
(void*) jni_YGNodeStyleGetPaddingJNI},
|
|
{"jni_YGNodeStyleSetPaddingJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetPaddingJNI},
|
|
{"jni_YGNodeStyleSetPaddingPercentJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetPaddingPercentJNI},
|
|
{"jni_YGNodeStyleGetBorderJNI",
|
|
"(JI)F",
|
|
(void*) jni_YGNodeStyleGetBorderJNI},
|
|
{"jni_YGNodeStyleSetBorderJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetBorderJNI},
|
|
{"jni_YGNodeStyleGetPositionJNI",
|
|
"(JI)J",
|
|
(void*) jni_YGNodeStyleGetPositionJNI},
|
|
{"jni_YGNodeStyleSetPositionJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetPositionJNI},
|
|
{"jni_YGNodeStyleSetPositionPercentJNI",
|
|
"(JIF)V",
|
|
(void*) jni_YGNodeStyleSetPositionPercentJNI},
|
|
{"jni_YGNodeStyleGetWidthJNI", "(J)J", (void*) jni_YGNodeStyleGetWidthJNI},
|
|
{"jni_YGNodeStyleSetWidthJNI", "(JF)V", (void*) jni_YGNodeStyleSetWidthJNI},
|
|
{"jni_YGNodeStyleSetWidthPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetWidthPercentJNI},
|
|
{"jni_YGNodeStyleSetWidthAutoJNI",
|
|
"(J)V",
|
|
(void*) jni_YGNodeStyleSetWidthAutoJNI},
|
|
{"jni_YGNodeStyleGetHeightJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetHeightJNI},
|
|
{"jni_YGNodeStyleSetHeightJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetHeightJNI},
|
|
{"jni_YGNodeStyleSetHeightPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetHeightPercentJNI},
|
|
{"jni_YGNodeStyleSetHeightAutoJNI",
|
|
"(J)V",
|
|
(void*) jni_YGNodeStyleSetHeightAutoJNI},
|
|
{"jni_YGNodeStyleGetMinWidthJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetMinWidthJNI},
|
|
{"jni_YGNodeStyleSetMinWidthJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMinWidthJNI},
|
|
{"jni_YGNodeStyleSetMinWidthPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMinWidthPercentJNI},
|
|
{"jni_YGNodeStyleGetMinHeightJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetMinHeightJNI},
|
|
{"jni_YGNodeStyleSetMinHeightJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMinHeightJNI},
|
|
{"jni_YGNodeStyleSetMinHeightPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMinHeightPercentJNI},
|
|
{"jni_YGNodeStyleGetMaxWidthJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetMaxWidthJNI},
|
|
{"jni_YGNodeStyleSetMaxWidthJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMaxWidthJNI},
|
|
{"jni_YGNodeStyleSetMaxWidthPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMaxWidthPercentJNI},
|
|
{"jni_YGNodeStyleGetMaxHeightJNI",
|
|
"(J)J",
|
|
(void*) jni_YGNodeStyleGetMaxHeightJNI},
|
|
{"jni_YGNodeStyleSetMaxHeightJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMaxHeightJNI},
|
|
{"jni_YGNodeStyleSetMaxHeightPercentJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetMaxHeightPercentJNI},
|
|
{"jni_YGNodeStyleGetAspectRatioJNI",
|
|
"(J)F",
|
|
(void*) jni_YGNodeStyleGetAspectRatioJNI},
|
|
{"jni_YGNodeStyleSetAspectRatioJNI",
|
|
"(JF)V",
|
|
(void*) jni_YGNodeStyleSetAspectRatioJNI},
|
|
{"jni_YGNodeSetHasMeasureFuncJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGNodeSetHasMeasureFuncJNI},
|
|
{"jni_YGNodeStyleGetGapJNI", "(JI)F", (void*) jni_YGNodeStyleGetGapJNI},
|
|
{"jni_YGNodeStyleSetGapJNI", "(JIF)V", (void*) jni_YGNodeStyleSetGapJNI},
|
|
{"jni_YGNodeSetHasBaselineFuncJNI",
|
|
"(JZ)V",
|
|
(void*) jni_YGNodeSetHasBaselineFuncJNI},
|
|
{"jni_YGNodePrintJNI", "(J)V", (void*) jni_YGNodePrintJNI},
|
|
{"jni_YGNodeCloneJNI", "(J)J", (void*) jni_YGNodeCloneJNI},
|
|
};
|
|
|
|
void YGJNIVanilla::registerNatives(JNIEnv* env) {
|
|
facebook::yoga::vanillajni::registerNatives(
|
|
env,
|
|
"com/facebook/yoga/YogaNative",
|
|
methods,
|
|
sizeof(methods) / sizeof(JNINativeMethod));
|
|
}
|