Skip to content

Commit

Permalink
Modularize and document public API (facebook#1449)
Browse files Browse the repository at this point in the history
Summary:
X-link: facebook/react-native#41317


This aims to clean up the public Yoga C API, by:
1. Documenting most public APIs
2. Splitting APIs for specific objects into different header files (because Yoga.h was big enough without documentation)
3. Reordering headers and definitions for consistent grouping
4. Removed `Yoga-internal.h`, making all top-level headers public. `YGNodeDeallocate` is folded into a public `YGNodeFinalize` API with its use-case documented
5. Move JNI bindings fully to public API

Changelog: [Internal]

Differential Revision: D50963424
  • Loading branch information
NickGerleman authored and facebook-github-bot committed Nov 4, 2023
1 parent 0eb6667 commit f9b730a
Show file tree
Hide file tree
Showing 21 changed files with 1,718 additions and 1,310 deletions.
2 changes: 1 addition & 1 deletion Yoga.podspec
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ Pod::Spec.new do |spec|
spec.source_files = 'yoga/**/*.{h,cpp}'
spec.header_mappings_dir = 'yoga'

public_header_files = 'yoga/{Yoga,YGEnums,YGMacros,YGValue}.h'
public_header_files = 'yoga/*.h'
spec.public_header_files = public_header_files

all_header_files = 'yoga/**/*.h'
Expand Down
2 changes: 1 addition & 1 deletion java/com/facebook/yoga/YogaNative.java
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public class YogaNative {
// YGNode related
static native long jni_YGNodeNewJNI();
static native long jni_YGNodeNewWithConfigJNI(long configPointer);
static native void jni_YGNodeDeallocateJNI(long nativePointer);
static native void jni_YGNodeFinalizeJNI(long nativePointer);
static native void jni_YGNodeResetJNI(long nativePointer);
static native void jni_YGNodeInsertChildJNI(long nativePointer, long childPointer, int index);
static native void jni_YGNodeSwapChildJNI(long nativePointer, long childPointer, int index);
Expand Down
2 changes: 1 addition & 1 deletion java/com/facebook/yoga/YogaNodeJNIFinalizer.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public void freeNatives() {
if (mNativePointer != 0) {
long nativePointer = mNativePointer;
mNativePointer = 0;
YogaNative.jni_YGNodeDeallocateJNI(nativePointer);
YogaNative.jni_YGNodeFinalizeJNI(nativePointer);
}
}
}
16 changes: 8 additions & 8 deletions java/jni/YGJNIVanilla.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,6 @@
#include "common.h"
#include "jni.h"

#include <yoga/Yoga-internal.h>
#include <yoga/bits/BitCast.h>

using namespace facebook;
using namespace facebook::yoga;
using namespace facebook::yoga::vanillajni;
Expand Down Expand Up @@ -190,12 +187,12 @@ static void jni_YGConfigSetLoggerJNI(
}

static void
jni_YGNodeDeallocateJNI(JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) {
jni_YGNodeFinalizeJNI(JNIEnv* /*env*/, jobject /*obj*/, jlong nativePointer) {
if (nativePointer == 0) {
return;
}
const YGNodeRef node = _jlong2YGNodeRef(nativePointer);
YGNodeDeallocate(node);
YGNodeFinalize(node);
}

static void
Expand Down Expand Up @@ -638,8 +635,11 @@ static YGSize YGJNIMeasureFunc(
uint32_t wBits = 0xFFFFFFFF & (measureResult >> 32);
uint32_t hBits = 0xFFFFFFFF & measureResult;

const float measuredWidth = yoga::bit_cast<float>(wBits);
const float measuredHeight = yoga::bit_cast<float>(hBits);
float measuredWidth{};
std::memcpy(&measuredWidth, &wBits, sizeof(measuredWidth));

float measuredHeight{};
std::memcpy(&measuredHeight, &hBits, sizeof(measuredHeight));

return YGSize{measuredWidth, measuredHeight};
} else {
Expand Down Expand Up @@ -751,7 +751,7 @@ static JNINativeMethod methods[] = {
(void*)jni_YGConfigSetLoggerJNI},
{"jni_YGNodeNewJNI", "()J", (void*)jni_YGNodeNewJNI},
{"jni_YGNodeNewWithConfigJNI", "(J)J", (void*)jni_YGNodeNewWithConfigJNI},
{"jni_YGNodeDeallocateJNI", "(J)V", (void*)jni_YGNodeDeallocateJNI},
{"jni_YGNodeFinalizeJNI", "(J)V", (void*)jni_YGNodeFinalizeJNI},
{"jni_YGNodeResetJNI", "(J)V", (void*)jni_YGNodeResetJNI},
{"jni_YGNodeInsertChildJNI", "(JJI)V", (void*)jni_YGNodeInsertChildJNI},
{"jni_YGNodeSwapChildJNI", "(JJI)V", (void*)jni_YGNodeSwapChildJNI},
Expand Down
1 change: 0 additions & 1 deletion tests/YGRoundingFunctionTest.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@
*/

#include <gtest/gtest.h>
#include <yoga/Yoga-internal.h>
#include <yoga/Yoga.h>

TEST(YogaTest, rounding_value) {
Expand Down
102 changes: 102 additions & 0 deletions yoga/YGConfig.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
/*
* 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 <yoga/Yoga.h>
#include <yoga/debug/AssertFatal.h>
#include <yoga/debug/Log.h>

using namespace facebook;
using namespace facebook::yoga;

YGConfigRef YGConfigNew(void) {
return new yoga::Config(getDefaultLogger());
}

void YGConfigFree(const YGConfigRef config) {
delete resolveRef(config);
}

YGConfigConstRef YGConfigGetDefault() {
return &yoga::Config::getDefault();
}

void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) {
resolveRef(config)->setUseWebDefaults(enabled);
}

bool YGConfigGetUseWebDefaults(const YGConfigConstRef config) {
return resolveRef(config)->useWebDefaults();
}

void YGConfigSetPointScaleFactor(
const YGConfigRef config,
const float pixelsInPoint) {
yoga::assertFatalWithConfig(
resolveRef(config),
pixelsInPoint >= 0.0f,
"Scale factor should not be less than zero");

// We store points for Pixel as we will use it for rounding
if (pixelsInPoint == 0.0f) {
// Zero is used to skip rounding
resolveRef(config)->setPointScaleFactor(0.0f);
} else {
resolveRef(config)->setPointScaleFactor(pixelsInPoint);
}
}

float YGConfigGetPointScaleFactor(const YGConfigConstRef config) {
return resolveRef(config)->getPointScaleFactor();
}

void YGConfigSetErrata(YGConfigRef config, YGErrata errata) {
resolveRef(config)->setErrata(scopedEnum(errata));
}

YGErrata YGConfigGetErrata(YGConfigConstRef config) {
return unscopedEnum(resolveRef(config)->getErrata());
}

void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {
if (logger != nullptr) {
resolveRef(config)->setLogger(logger);
} else {
resolveRef(config)->setLogger(getDefaultLogger());
}
}

void YGConfigSetContext(const YGConfigRef config, void* context) {
resolveRef(config)->setContext(context);
}

void* YGConfigGetContext(const YGConfigConstRef config) {
return resolveRef(config)->getContext();
}

void YGConfigSetExperimentalFeatureEnabled(
const YGConfigRef config,
const YGExperimentalFeature feature,
const bool enabled) {
resolveRef(config)->setExperimentalFeatureEnabled(
scopedEnum(feature), enabled);
}

bool YGConfigIsExperimentalFeatureEnabled(
const YGConfigConstRef config,
const YGExperimentalFeature feature) {
return resolveRef(config)->isExperimentalFeatureEnabled(scopedEnum(feature));
}

void YGConfigSetCloneNodeFunc(
const YGConfigRef config,
const YGCloneNodeFunc callback) {
resolveRef(config)->setCloneNodeCallback(callback);
}

void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) {
resolveRef(config)->setShouldPrintTree(enabled);
}
163 changes: 163 additions & 0 deletions yoga/YGConfig.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,163 @@
/*
* 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.
*/

#pragma once

#include <stdarg.h>
#include <stdbool.h>
#include <stddef.h>

#include <yoga/YGEnums.h>
#include <yoga/YGMacros.h>

YG_EXTERN_C_BEGIN

typedef struct YGNode* YGNodeRef;
typedef const struct YGNode* YGNodeConstRef;

/**
* Handle to a mutable Yoga configuration
*/
typedef struct YGConfig* YGConfigRef;

/**
* Handle to an immutable Yoga configruation
*/
typedef const struct YGConfig* YGConfigConstRef;

/**
* Allocates a set of configuration options. The configuration may be applied to
* multiple nodes (i.e. a single global config), or can be applied more
* granularly per-node.
*/
YG_EXPORT YGConfigRef YGConfigNew(void);

/**
* Frees the associated Yoga configuration.
*/
YG_EXPORT void YGConfigFree(YGConfigRef config);

/**
* Returns the default config values set by Yoga
*/
YG_EXPORT YGConfigConstRef YGConfigGetDefault(void);

/**
* Yoga by default creates new nodes with style defaults different from flexbox
* on web (e.g. `YGFlexDirectionColumn` and `YGPositionRelative`).
* `UseWebDefaults` instructs Yoga to instead use a default style consistent
* with the web.
*/
YG_EXPORT void YGConfigSetUseWebDefaults(YGConfigRef config, bool enabled);

/**
* Whether the configuration is set to use web defaults
*/
YG_EXPORT bool YGConfigGetUseWebDefaults(YGConfigConstRef config);

/**
* Yoga will by deafult round final layout positions and dimensions to the
* nearst point. `pointScaleFactor` controls the density of the grid used for
* layout rounding (e.g. to round to the closest display pixel).
*
* May be set to 0.0f to avoid rounding the layout results.
*/
YG_EXPORT void YGConfigSetPointScaleFactor(
YGConfigRef config,
float pixelsInPoint);

/**
* Get the currently set point scale factor
*/
YG_EXPORT float YGConfigGetPointScaleFactor(YGConfigConstRef config);

/**
* Configures how Yoga balances W3C conformance vs compatibility with layouts
* created against earlier versions of Yoga.
*
* By deafult Yoga will prioritize W3C conformance. `Errata` may be set to ask
* Yoga to produce specific incorrect behaviors. E.g. `YGConfigSetErrata(config,
* YGErrataPositionStaticBehavesLikeRelative)`.
*
* YGErrata is a bitmask, and multiple errata may be set at once. Predfined
* constants exist for convenience:
* 1. YGErrataNone: No errata
* 2. YGErrataClassic: Match layout behaviors of Yoga 1.x
* 3. YGErrataAll: Match layout behaviors of Yoga 1.x, including
* `UseLegacyStretchBehaviour`
*/
YG_EXPORT void YGConfigSetErrata(YGConfigRef config, YGErrata errata);

/**
* Get the currently set errata
*/
YG_EXPORT YGErrata YGConfigGetErrata(YGConfigConstRef config);

/**
* Function pointer type for YGConfigSetLogger
*/
typedef int (*YGLogger)(
YGConfigConstRef config,
YGNodeConstRef node,
YGLogLevel level,
const char* format,
va_list args);

/**
* Set a custom log function for to use when logging diagnostics or fatal
* errors.
*/
YG_EXPORT void YGConfigSetLogger(YGConfigRef config, YGLogger logger);

/**
* Sets an arbitrary context pointer on the config which may be read from during
* callbacks
*/
YG_EXPORT void YGConfigSetContext(YGConfigRef config, void* context);

/**
* Gets the currently set context
*/
YG_EXPORT void* YGConfigGetContext(YGConfigConstRef config);

/**
* Function pointer type for YGConfigSetCloneNodeFunc
*/
typedef YGNodeRef (*YGCloneNodeFunc)(
YGNodeConstRef oldNode,
YGNodeConstRef owner,
size_t childIndex);

/**
* Enable an experimental/unsupported feature in Yoga.
*/
YG_EXPORT void YGConfigSetExperimentalFeatureEnabled(
YGConfigRef config,
YGExperimentalFeature feature,
bool enabled);

/**
* Whether an experimental feature is set.
*/
YG_EXPORT bool YGConfigIsExperimentalFeatureEnabled(
YGConfigConstRef config,
YGExperimentalFeature feature);

/**
* Sets a callback, called during layout, to create a new mutable Yoga node if
* Yoga must write to it and its owner is not its parent observed during layout.
*/
YG_EXPORT void YGConfigSetCloneNodeFunc(
YGConfigRef config,
YGCloneNodeFunc callback);

/**
* Allows printing the Yoga node tree during layout for debugging purposes.
*/
YG_EXPORT void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled);

YG_EXTERN_C_END
Loading

0 comments on commit f9b730a

Please sign in to comment.