diff --git a/Yoga.podspec b/Yoga.podspec index e8e4dc0cc1..0dd171e297 100644 --- a/Yoga.podspec +++ b/Yoga.podspec @@ -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' diff --git a/java/com/facebook/yoga/YogaNative.java b/java/com/facebook/yoga/YogaNative.java index 6ae00f0f2e..a0b7c165f1 100644 --- a/java/com/facebook/yoga/YogaNative.java +++ b/java/com/facebook/yoga/YogaNative.java @@ -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); diff --git a/java/com/facebook/yoga/YogaNodeJNIFinalizer.java b/java/com/facebook/yoga/YogaNodeJNIFinalizer.java index ab617c7f16..23cf2a31e5 100644 --- a/java/com/facebook/yoga/YogaNodeJNIFinalizer.java +++ b/java/com/facebook/yoga/YogaNodeJNIFinalizer.java @@ -29,7 +29,7 @@ public void freeNatives() { if (mNativePointer != 0) { long nativePointer = mNativePointer; mNativePointer = 0; - YogaNative.jni_YGNodeDeallocateJNI(nativePointer); + YogaNative.jni_YGNodeFinalizeJNI(nativePointer); } } } diff --git a/java/jni/YGJNIVanilla.cpp b/java/jni/YGJNIVanilla.cpp index e01aa24875..213ff8ccea 100644 --- a/java/jni/YGJNIVanilla.cpp +++ b/java/jni/YGJNIVanilla.cpp @@ -16,9 +16,6 @@ #include "common.h" #include "jni.h" -#include -#include - using namespace facebook; using namespace facebook::yoga; using namespace facebook::yoga::vanillajni; @@ -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 @@ -638,8 +635,11 @@ static YGSize YGJNIMeasureFunc( uint32_t wBits = 0xFFFFFFFF & (measureResult >> 32); uint32_t hBits = 0xFFFFFFFF & measureResult; - const float measuredWidth = yoga::bit_cast(wBits); - const float measuredHeight = yoga::bit_cast(hBits); + float measuredWidth{}; + std::memcpy(&measuredWidth, &wBits, sizeof(measuredWidth)); + + float measuredHeight{}; + std::memcpy(&measuredHeight, &hBits, sizeof(measuredHeight)); return YGSize{measuredWidth, measuredHeight}; } else { @@ -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}, diff --git a/tests/YGRoundingFunctionTest.cpp b/tests/YGRoundingFunctionTest.cpp index 7fb2d30bdb..9639a92088 100644 --- a/tests/YGRoundingFunctionTest.cpp +++ b/tests/YGRoundingFunctionTest.cpp @@ -6,7 +6,6 @@ */ #include -#include #include TEST(YogaTest, rounding_value) { diff --git a/yoga/YGConfig.cpp b/yoga/YGConfig.cpp new file mode 100644 index 0000000000..2cdc7af995 --- /dev/null +++ b/yoga/YGConfig.cpp @@ -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 +#include +#include + +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); +} diff --git a/yoga/YGConfig.h b/yoga/YGConfig.h new file mode 100644 index 0000000000..b8fe27f424 --- /dev/null +++ b/yoga/YGConfig.h @@ -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 +#include +#include + +#include +#include + +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 diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp new file mode 100644 index 0000000000..c928f53535 --- /dev/null +++ b/yoga/YGNode.cpp @@ -0,0 +1,365 @@ +/* + * 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 + +#include +#include +#include +#include +#include +#include +#include + +using namespace facebook; +using namespace facebook::yoga; + +YGNodeRef YGNodeNew(void) { + return YGNodeNewWithConfig(YGConfigGetDefault()); +} + +YGNodeRef YGNodeNewWithConfig(const YGConfigConstRef config) { + auto* node = new yoga::Node{resolveRef(config)}; + yoga::assertFatal( + config != nullptr, "Tried to construct YGNode with null config"); + Event::publish(node, {config}); + + return node; +} + +YGNodeRef YGNodeClone(YGNodeConstRef oldNodeRef) { + auto oldNode = resolveRef(oldNodeRef); + const auto node = new yoga::Node(*oldNode); + Event::publish(node, {node->getConfig()}); + node->setOwner(nullptr); + return node; +} + +void YGNodeFree(const YGNodeRef nodeRef) { + const auto node = resolveRef(nodeRef); + + if (auto owner = node->getOwner()) { + owner->removeChild(node); + node->setOwner(nullptr); + } + + const size_t childCount = node->getChildCount(); + for (size_t i = 0; i < childCount; i++) { + auto child = node->getChild(i); + child->setOwner(nullptr); + } + + node->clearChildren(); + YGNodeFinalize(node); +} + +void YGNodeFreeRecursive(YGNodeRef rootRef) { + const auto root = resolveRef(rootRef); + + size_t skipped = 0; + while (root->getChildCount() > skipped) { + const auto child = root->getChild(skipped); + if (child->getOwner() != root) { + // Don't free shared nodes that we don't own. + skipped += 1; + } else { + YGNodeRemoveChild(root, child); + YGNodeFreeRecursive(child); + } + } + YGNodeFree(root); +} + +void YGNodeFinalize(const YGNodeRef node) { + Event::publish(node, {YGNodeGetConfig(node)}); + delete resolveRef(node); +} + +void YGNodeReset(YGNodeRef node) { + resolveRef(node)->reset(); +} + +void YGNodeCalculateLayout( + const YGNodeRef node, + const float ownerWidth, + const float ownerHeight, + const YGDirection ownerDirection) { + yoga::calculateLayout( + resolveRef(node), ownerWidth, ownerHeight, scopedEnum(ownerDirection)); +} + +bool YGNodeGetHasNewLayout(YGNodeConstRef node) { + return resolveRef(node)->getHasNewLayout(); +} + +void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) { + resolveRef(node)->setHasNewLayout(hasNewLayout); +} + +bool YGNodeIsDirty(YGNodeConstRef node) { + return resolveRef(node)->isDirty(); +} + +void YGNodeMarkDirty(const YGNodeRef nodeRef) { + const auto node = resolveRef(nodeRef); + + yoga::assertFatalWithNode( + node, + node->hasMeasureFunc(), + "Only leaf nodes with custom measure functions " + "should manually mark themselves as dirty"); + + node->markDirtyAndPropagate(); +} + +void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc) { + resolveRef(node)->setDirtiedFunc(dirtiedFunc); +} + +YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeConstRef node) { + return resolveRef(node)->getDirtiedFunc(); +} + +void YGNodeInsertChild( + const YGNodeRef ownerRef, + const YGNodeRef childRef, + const size_t index) { + auto owner = resolveRef(ownerRef); + auto child = resolveRef(childRef); + + yoga::assertFatalWithNode( + owner, + child->getOwner() == nullptr, + "Child already has a owner, it must be removed first."); + + yoga::assertFatalWithNode( + owner, + !owner->hasMeasureFunc(), + "Cannot add child: Nodes with measure functions cannot have children."); + + owner->insertChild(child, index); + child->setOwner(owner); + owner->markDirtyAndPropagate(); +} + +void YGNodeSwapChild( + const YGNodeRef ownerRef, + const YGNodeRef childRef, + const size_t index) { + auto owner = resolveRef(ownerRef); + auto child = resolveRef(childRef); + + owner->replaceChild(child, index); + child->setOwner(owner); +} + +void YGNodeRemoveChild( + const YGNodeRef ownerRef, + const YGNodeRef excludedChildRef) { + auto owner = resolveRef(ownerRef); + auto excludedChild = resolveRef(excludedChildRef); + + if (owner->getChildCount() == 0) { + // This is an empty set. Nothing to remove. + return; + } + + // Children may be shared between parents, which is indicated by not having an + // owner. We only want to reset the child completely if it is owned + // exclusively by one node. + auto childOwner = excludedChild->getOwner(); + if (owner->removeChild(excludedChild)) { + if (owner == childOwner) { + excludedChild->setLayout({}); // layout is no longer valid + excludedChild->setOwner(nullptr); + } + owner->markDirtyAndPropagate(); + } +} + +void YGNodeRemoveAllChildren(const YGNodeRef ownerRef) { + auto owner = resolveRef(ownerRef); + + const size_t childCount = owner->getChildCount(); + if (childCount == 0) { + // This is an empty set already. Nothing to do. + return; + } + auto* firstChild = owner->getChild(0); + if (firstChild->getOwner() == owner) { + // If the first child has this node as its owner, we assume that this child + // set is unique. + for (size_t i = 0; i < childCount; i++) { + yoga::Node* oldChild = owner->getChild(i); + oldChild->setLayout({}); // layout is no longer valid + oldChild->setOwner(nullptr); + } + owner->clearChildren(); + owner->markDirtyAndPropagate(); + return; + } + // Otherwise, we are not the owner of the child set. We don't have to do + // anything to clear it. + owner->setChildren({}); + owner->markDirtyAndPropagate(); +} + +void YGNodeSetChildren( + const YGNodeRef ownerRef, + const YGNodeRef* childrenRefs, + const size_t count) { + auto owner = resolveRef(ownerRef); + auto children = reinterpret_cast(childrenRefs); + + if (!owner) { + return; + } + + const std::vector childrenVector = {children, children + count}; + if (childrenVector.size() == 0) { + if (owner->getChildCount() > 0) { + for (auto* child : owner->getChildren()) { + child->setLayout({}); + child->setOwner(nullptr); + } + owner->setChildren({}); + owner->markDirtyAndPropagate(); + } + } else { + if (owner->getChildCount() > 0) { + for (auto* oldChild : owner->getChildren()) { + // Our new children may have nodes in common with the old children. We + // don't reset these common nodes. + if (std::find(childrenVector.begin(), childrenVector.end(), oldChild) == + childrenVector.end()) { + oldChild->setLayout({}); + oldChild->setOwner(nullptr); + } + } + } + owner->setChildren(childrenVector); + for (yoga::Node* child : childrenVector) { + child->setOwner(owner); + } + owner->markDirtyAndPropagate(); + } +} + +YGNodeRef YGNodeGetChild(const YGNodeRef nodeRef, const size_t index) { + const auto node = resolveRef(nodeRef); + + if (index < node->getChildren().size()) { + return node->getChild(index); + } + return nullptr; +} + +size_t YGNodeGetChildCount(const YGNodeConstRef node) { + return resolveRef(node)->getChildren().size(); +} + +YGNodeRef YGNodeGetOwner(const YGNodeRef node) { + return resolveRef(node)->getOwner(); +} + +YGNodeRef YGNodeGetParent(const YGNodeRef node) { + return resolveRef(node)->getOwner(); +} + +void YGNodeSetConfig(YGNodeRef node, YGConfigRef config) { + resolveRef(node)->setConfig(resolveRef(config)); +} + +YGConfigConstRef YGNodeGetConfig(YGNodeRef node) { + return resolveRef(node)->getConfig(); +} + +void YGNodeSetContext(YGNodeRef node, void* context) { + return resolveRef(node)->setContext(context); +} + +void* YGNodeGetContext(YGNodeConstRef node) { + return resolveRef(node)->getContext(); +} + +void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc) { + resolveRef(node)->setMeasureFunc(measureFunc); +} + +bool YGNodeHasMeasureFunc(YGNodeConstRef node) { + return resolveRef(node)->hasMeasureFunc(); +} + +void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) { + resolveRef(node)->setBaselineFunc(baselineFunc); +} + +bool YGNodeHasBaselineFunc(YGNodeConstRef node) { + return resolveRef(node)->hasBaselineFunc(); +} + +void YGNodeSetIsReferenceBaseline(YGNodeRef nodeRef, bool isReferenceBaseline) { + const auto node = resolveRef(nodeRef); + if (node->isReferenceBaseline() != isReferenceBaseline) { + node->setIsReferenceBaseline(isReferenceBaseline); + node->markDirtyAndPropagate(); + } +} + +bool YGNodeIsReferenceBaseline(YGNodeConstRef node) { + return resolveRef(node)->isReferenceBaseline(); +} + +void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType) { + return resolveRef(node)->setNodeType(scopedEnum(nodeType)); +} + +YGNodeType YGNodeGetNodeType(YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getNodeType()); +} + +void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc) { + resolveRef(node)->setPrintFunc(printFunc); +} + +#ifdef DEBUG +void YGNodePrint(const YGNodeConstRef node, const YGPrintOptions options) { + yoga::print(resolveRef(node), scopedEnum(options)); +} +#endif + +// TODO: This leaks internal details to the public API. Remove after removing +// ComponentKit usage of it. +bool YGNodeCanUseCachedMeasurement( + YGMeasureMode widthMode, + float availableWidth, + YGMeasureMode heightMode, + float availableHeight, + YGMeasureMode lastWidthMode, + float lastAvailableWidth, + YGMeasureMode lastHeightMode, + float lastAvailableHeight, + float lastComputedWidth, + float lastComputedHeight, + float marginRow, + float marginColumn, + YGConfigRef config) { + return yoga::canUseCachedMeasurement( + scopedEnum(widthMode), + availableWidth, + scopedEnum(heightMode), + availableHeight, + scopedEnum(lastWidthMode), + lastAvailableWidth, + scopedEnum(lastHeightMode), + lastAvailableHeight, + lastComputedWidth, + lastComputedHeight, + marginRow, + marginColumn, + resolveRef(config)); +} diff --git a/yoga/YGNode.h b/yoga/YGNode.h new file mode 100644 index 0000000000..01ee143fd5 --- /dev/null +++ b/yoga/YGNode.h @@ -0,0 +1,285 @@ +/* + * 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 +#include + +#include +#include +#include + +YG_EXTERN_C_BEGIN + +/** + * Handle to a mutable Yoga Node + */ +typedef struct YGNode* YGNodeRef; + +/** + * Handle to an immutable Yoga Node + */ +typedef const struct YGNode* YGNodeConstRef; + +/** + * Heap allocates and returns a new Yoga node using Yoga settings. + */ +YG_EXPORT YGNodeRef YGNodeNew(void); + +/** + * Heap allocates and returns a new Yoga node, with customized settings. + */ +YG_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigConstRef config); + +/** + * Returns a mutable copy of an existing node, with the same context and + * children, but no owner set. Does not call the function set by + * YGConfigSetCloneNodeFunc(). + */ +YG_EXPORT YGNodeRef YGNodeClone(YGNodeConstRef node); + +/** + * Frees the Yoga node, disconnecting it from its owner and children. + */ +YG_EXPORT void YGNodeFree(YGNodeRef node); + +/** + * Frees the subtree of Yoga nodes rooted at the given node. + */ +YG_EXPORT void YGNodeFreeRecursive(YGNodeRef node); + +/** + * Frees the Yoga node without disconnecting it from its owner or children. + * Allows garbage collecting Yoga nodes in parallel when the entire tree is + * unrechable. + */ +YG_EXPORT void YGNodeFinalize(YGNodeRef node); + +/** + * Resets the node to its default state. + */ +YG_EXPORT void YGNodeReset(YGNodeRef node); + +/** + * Calculates the layout of the tree rooted at the given node. + * + * Layout results may be read after calling YGNodeCalculateLayout() using + * functions like YGNodeLayoutGetLeft(), YGNodeLayoutGetTop(), etc. + * + * YGNodeGetHasNewLayout() may be read to know if the layout of the node or its + * subtrees may have changed since the last time YGNodeCalculate() was called. + */ +YG_EXPORT void YGNodeCalculateLayout( + YGNodeRef node, + float availableWidth, + float availableHeight, + YGDirection ownerDirection); + +/** + * Whether the given node may have new layout results. Must be reset by calling + * YGNodeSetHasNewLayout(). + */ +YG_EXPORT bool YGNodeGetHasNewLayout(YGNodeConstRef node); + +/** + * Sets whether a nodes layout is considered new. + */ +YG_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout); + +/** + * Whether the node's layout results are dirty due to it or its children + * changing. + */ +YG_EXPORT bool YGNodeIsDirty(YGNodeConstRef node); + +/** + * Marks a node with custom measure function as dirty. + */ +YG_EXPORT void YGNodeMarkDirty(YGNodeRef node); + +typedef void (*YGDirtiedFunc)(YGNodeConstRef node); + +/** + * Called when a change is made to the Yoga tree which dirties this node. + */ +YG_EXPORT void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc); + +/** + * Returns a dirtied func if set. + */ +YG_EXPORT YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeConstRef node); + +/** + * Inserts a child node at the given index. + */ +YG_EXPORT void YGNodeInsertChild(YGNodeRef node, YGNodeRef child, size_t index); + +/** + * Replaces the child node at a given index with a new one. + */ +YG_EXPORT void YGNodeSwapChild(YGNodeRef node, YGNodeRef child, size_t index); + +/** + * Removes the given child node + */ +YG_EXPORT void YGNodeRemoveChild(YGNodeRef node, YGNodeRef child); + +/** + * Removes all children nodes + */ +YG_EXPORT void YGNodeRemoveAllChildren(YGNodeRef node); + +/** + * Sets children according to the given list of nodes + */ +YG_EXPORT void +YGNodeSetChildren(YGNodeRef owner, const YGNodeRef* children, size_t count); + +/** + * Get the child node at a given index + */ +YG_EXPORT YGNodeRef YGNodeGetChild(YGNodeRef node, size_t index); + +/** + * The number of child nodes + */ +YG_EXPORT size_t YGNodeGetChildCount(YGNodeConstRef node); + +/** + * Get the parent/owner currently set for a node + */ +YG_EXPORT YGNodeRef YGNodeGetOwner(YGNodeRef node); + +/** + * Get the parent/owner currently set for a node + */ +YG_EXPORT YGNodeRef YGNodeGetParent(YGNodeRef node); + +/** + * Set a new config for the node after creation + */ +YG_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config); + +/** + * Get the config currently set on the node + */ +YG_EXPORT YGConfigConstRef YGNodeGetConfig(YGNodeRef node); + +/** + * Sets extra data on the Yoga node which may be read from during callbacks. + */ +YG_EXPORT void YGNodeSetContext(YGNodeRef node, void* context); + +/** + * Returns the context or NULL if no context has been set. + */ +YG_EXPORT void* YGNodeGetContext(YGNodeConstRef node); + +typedef struct YGSize { + float width; + float height; +} YGSize; + +/** + * @returns the size of the leaf node, measured under the given contraints + */ +typedef YGSize (*YGMeasureFunc)( + YGNodeConstRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode); + +/** + * Allows providing custom measurements for a Yoga leaf node (usually for + * measuring text). YGNodeMarkDirty() must be set if content effecting the + * measurements of the node changes. + */ +YG_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); + +/** + * Whether a measure function is set. + */ +YG_EXPORT bool YGNodeHasMeasureFunc(YGNodeConstRef node); + +/** + * @returns a defined offet to baseline (ascent) + */ +typedef float (*YGBaselineFunc)(YGNodeConstRef node, float width, float height); + +/** + * Set a custom function for determining the text baseline for use in baseline + * alignment. + */ +YG_EXPORT void YGNodeSetBaselineFunc( + YGNodeRef node, + YGBaselineFunc baselineFunc); + +/** + * Whether a baseline function is set. + */ +YG_EXPORT bool YGNodeHasBaselineFunc(YGNodeConstRef node); + +/** + * Sets this node should be considered the reference baseline among siblings. + */ +YG_EXPORT void YGNodeSetIsReferenceBaseline( + YGNodeRef node, + bool isReferenceBaseline); + +/** + * Whether this node is set as the reference baseline. + */ +YG_EXPORT bool YGNodeIsReferenceBaseline(YGNodeConstRef node); + +/** + * Sets whether a leaf node's layout results may be truncated during layout + * rounding. + */ +YG_EXPORT void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType); + +/** + * Wwhether a leaf node's layout results may be truncated during layout + * rounding. + */ +YG_EXPORT YGNodeType YGNodeGetNodeType(YGNodeConstRef node); + +typedef void (*YGPrintFunc)(YGNodeConstRef node); + +/** + * Set a function to be called when configured to print nodes during layout for + * debugging + */ +YG_EXPORT void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc); + +/** + * Print a node to log output + */ +YG_EXPORT void YGNodePrint(YGNodeConstRef node, YGPrintOptions options); + +/** + * @deprecated + */ +YG_DEPRECATED( + "YGNodeCanUseCachedMeasurement may be removed in a future version of Yoga") +YG_EXPORT bool YGNodeCanUseCachedMeasurement( + YGMeasureMode widthMode, + float availableWidth, + YGMeasureMode heightMode, + float availableHeight, + YGMeasureMode lastWidthMode, + float lastAvailableWidth, + YGMeasureMode lastHeightMode, + float lastAvailableHeight, + float lastComputedWidth, + float lastComputedHeight, + float marginRow, + float marginColumn, + YGConfigRef config); + +YG_EXTERN_C_END diff --git a/yoga/YGNodeLayout.cpp b/yoga/YGNodeLayout.cpp new file mode 100644 index 0000000000..39f67f9dc9 --- /dev/null +++ b/yoga/YGNodeLayout.cpp @@ -0,0 +1,90 @@ +/* + * 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 +#include +#include + +using namespace facebook; +using namespace facebook::yoga; + +namespace { + +template +float getResolvedLayoutProperty( + const YGNodeConstRef nodeRef, + const YGEdge edge) { + const auto node = resolveRef(nodeRef); + yoga::assertFatalWithNode( + node, + edge <= YGEdgeEnd, + "Cannot get layout properties of multi-edge shorthands"); + + if (edge == YGEdgeStart) { + if (node->getLayout().direction() == Direction::RTL) { + return (node->getLayout().*LayoutMember)[YGEdgeRight]; + } else { + return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + } + } + + if (edge == YGEdgeEnd) { + if (node->getLayout().direction() == Direction::RTL) { + return (node->getLayout().*LayoutMember)[YGEdgeLeft]; + } else { + return (node->getLayout().*LayoutMember)[YGEdgeRight]; + } + } + + return (node->getLayout().*LayoutMember)[edge]; +} + +} // namespace + +float YGNodeLayoutGetLeft(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeLeft]; +} + +float YGNodeLayoutGetTop(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeTop]; +} + +float YGNodeLayoutGetRight(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeRight]; +} + +float YGNodeLayoutGetBottom(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().position[YGEdgeBottom]; +} + +float YGNodeLayoutGetWidth(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().dimension(Dimension::Width); +} + +float YGNodeLayoutGetHeight(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().dimension(Dimension::Height); +} + +YGDirection YGNodeLayoutGetDirection(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getLayout().direction()); +} + +bool YGNodeLayoutGetHadOverflow(const YGNodeConstRef node) { + return resolveRef(node)->getLayout().hadOverflow(); +} + +float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::margin>(node, edge); +} + +float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::border>(node, edge); +} + +float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) { + return getResolvedLayoutProperty<&LayoutResults::padding>(node, edge); +} diff --git a/yoga/YGNodeLayout.h b/yoga/YGNodeLayout.h new file mode 100644 index 0000000000..02ead5883b --- /dev/null +++ b/yoga/YGNodeLayout.h @@ -0,0 +1,35 @@ +/* + * 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 + +#include +#include +#include + +YG_EXTERN_C_BEGIN + +YG_EXPORT float YGNodeLayoutGetLeft(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetTop(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetRight(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetBottom(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetWidth(YGNodeConstRef node); +YG_EXPORT float YGNodeLayoutGetHeight(YGNodeConstRef node); +YG_EXPORT YGDirection YGNodeLayoutGetDirection(YGNodeConstRef node); +YG_EXPORT bool YGNodeLayoutGetHadOverflow(YGNodeConstRef node); + +// Get the computed values for these nodes after performing layout. If they were +// set using point values then the returned value will be the same as +// YGNodeStyleGetXXX. However if they were set using a percentage value then the +// returned value is the computed value used during layout. +YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge); +YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge); +YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge); + +YG_EXTERN_C_END diff --git a/yoga/YGNodeStyle.cpp b/yoga/YGNodeStyle.cpp new file mode 100644 index 0000000000..57d352cd01 --- /dev/null +++ b/yoga/YGNodeStyle.cpp @@ -0,0 +1,442 @@ +/* + * 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 +#include +#include + +using namespace facebook; +using namespace facebook::yoga; + +namespace { + +template +void updateStyle( + yoga::Node* node, + T value, + NeedsUpdate&& needsUpdate, + Update&& update) { + if (needsUpdate(node->getStyle(), value)) { + update(node->getStyle(), value); + node->markDirtyAndPropagate(); + } +} + +template +void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { + updateStyle( + resolveRef(node), + value, + [prop](Style& s, T x) { return (s.*prop)() != x; }, + [prop](Style& s, T x) { (s.*prop)() = x; }); +} + +template +void updateIndexedStyleProp( + YGNodeRef node, + Ref (Style::*prop)(), + Idx idx, + CompactValue value) { + updateStyle( + resolveRef(node), + value, + [idx, prop](Style& s, CompactValue x) { return (s.*prop)()[idx] != x; }, + [idx, prop](Style& s, CompactValue x) { (s.*prop)()[idx] = x; }); +} + +template +void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { + updateStyle( + resolveRef(node), + value, + [idx](Style& s, CompactValue x) { return (s.*GetterT)(idx) != x; }, + [idx](Style& s, CompactValue x) { (s.*SetterT)(idx, x); }); +} + +} // namespace + +// MSVC has trouble inferring the return type of pointer to member functions +// with const and non-const overloads, instead of preferring the non-const +// overload like clang and GCC. For the purposes of updateStyle(), we can help +// MSVC by specifying that return type explicitly. In combination with +// decltype, MSVC will prefer the non-const version. +#define MSVC_HINT(PROP) decltype(Style{}.PROP()) + +void YGNodeCopyStyle( + const YGNodeRef dstNodeRef, + const YGNodeConstRef srcNodeRef) { + auto dstNode = resolveRef(dstNodeRef); + auto srcNode = resolveRef(srcNodeRef); + + if (!(dstNode->getStyle() == srcNode->getStyle())) { + dstNode->setStyle(srcNode->getStyle()); + dstNode->markDirtyAndPropagate(); + } +} + +void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { + updateStyle(node, &Style::direction, scopedEnum(value)); +} + +YGDirection YGNodeStyleGetDirection(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().direction()); +} + +void YGNodeStyleSetFlexDirection( + const YGNodeRef node, + const YGFlexDirection flexDirection) { + updateStyle( + node, &Style::flexDirection, scopedEnum(flexDirection)); +} + +YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().flexDirection()); +} + +void YGNodeStyleSetJustifyContent( + const YGNodeRef node, + const YGJustify justifyContent) { + updateStyle( + node, &Style::justifyContent, scopedEnum(justifyContent)); +} + +YGJustify YGNodeStyleGetJustifyContent(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().justifyContent()); +} + +void YGNodeStyleSetAlignContent( + const YGNodeRef node, + const YGAlign alignContent) { + updateStyle( + node, &Style::alignContent, scopedEnum(alignContent)); +} + +YGAlign YGNodeStyleGetAlignContent(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().alignContent()); +} + +void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { + updateStyle( + node, &Style::alignItems, scopedEnum(alignItems)); +} + +YGAlign YGNodeStyleGetAlignItems(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().alignItems()); +} + +void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { + updateStyle( + node, &Style::alignSelf, scopedEnum(alignSelf)); +} + +YGAlign YGNodeStyleGetAlignSelf(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().alignSelf()); +} + +void YGNodeStyleSetPositionType( + const YGNodeRef node, + const YGPositionType positionType) { + updateStyle( + node, &Style::positionType, scopedEnum(positionType)); +} + +YGPositionType YGNodeStyleGetPositionType(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().positionType()); +} + +void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { + updateStyle( + node, &Style::flexWrap, scopedEnum(flexWrap)); +} + +YGWrap YGNodeStyleGetFlexWrap(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().flexWrap()); +} + +void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { + updateStyle( + node, &Style::overflow, scopedEnum(overflow)); +} + +YGOverflow YGNodeStyleGetOverflow(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().overflow()); +} + +void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { + updateStyle(node, &Style::display, scopedEnum(display)); +} + +YGDisplay YGNodeStyleGetDisplay(const YGNodeConstRef node) { + return unscopedEnum(resolveRef(node)->getStyle().display()); +} + +void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { + updateStyle(node, &Style::flex, FloatOptional{flex}); +} + +float YGNodeStyleGetFlex(const YGNodeConstRef nodeRef) { + const auto node = resolveRef(nodeRef); + return node->getStyle().flex().isUndefined() + ? YGUndefined + : node->getStyle().flex().unwrap(); +} + +void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) { + updateStyle( + node, &Style::flexGrow, FloatOptional{flexGrow}); +} + +float YGNodeStyleGetFlexGrow(const YGNodeConstRef nodeRef) { + const auto node = resolveRef(nodeRef); + return node->getStyle().flexGrow().isUndefined() + ? Style::DefaultFlexGrow + : node->getStyle().flexGrow().unwrap(); +} + +void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) { + updateStyle( + node, &Style::flexShrink, FloatOptional{flexShrink}); +} + +float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { + const auto node = resolveRef(nodeRef); + return node->getStyle().flexShrink().isUndefined() + ? (node->getConfig()->useWebDefaults() ? Style::WebDefaultFlexShrink + : Style::DefaultFlexShrink) + : node->getStyle().flexShrink().unwrap(); +} + +void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { + auto value = CompactValue::ofMaybe(flexBasis); + updateStyle(node, &Style::flexBasis, value); +} + +void YGNodeStyleSetFlexBasisPercent( + const YGNodeRef node, + const float flexBasisPercent) { + auto value = CompactValue::ofMaybe(flexBasisPercent); + updateStyle(node, &Style::flexBasis, value); +} + +void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { + updateStyle( + node, &Style::flexBasis, CompactValue::ofAuto()); +} + +YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { + YGValue flexBasis = resolveRef(node)->getStyle().flexBasis(); + if (flexBasis.unit == YGUnitUndefined || flexBasis.unit == YGUnitAuto) { + flexBasis.value = YGUndefined; + } + return flexBasis; +} + +void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { + auto value = CompactValue::ofMaybe(points); + updateIndexedStyleProp( + node, &Style::position, edge, value); +} + +void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { + auto value = CompactValue::ofMaybe(percent); + updateIndexedStyleProp( + node, &Style::position, edge, value); +} + +YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { + return resolveRef(node)->getStyle().position()[edge]; +} + +void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { + auto value = CompactValue::ofMaybe(points); + updateIndexedStyleProp(node, &Style::margin, edge, value); +} + +void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { + auto value = CompactValue::ofMaybe(percent); + updateIndexedStyleProp(node, &Style::margin, edge, value); +} + +void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { + updateIndexedStyleProp( + node, &Style::margin, edge, CompactValue::ofAuto()); +} + +YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { + return resolveRef(node)->getStyle().margin()[edge]; +} + +void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { + auto value = CompactValue::ofMaybe(points); + updateIndexedStyleProp( + node, &Style::padding, edge, value); +} + +void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { + auto value = CompactValue::ofMaybe(percent); + updateIndexedStyleProp( + node, &Style::padding, edge, value); +} + +YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { + return resolveRef(node)->getStyle().padding()[edge]; +} + +void YGNodeStyleSetBorder( + const YGNodeRef node, + const YGEdge edge, + const float border) { + auto value = CompactValue::ofMaybe(border); + updateIndexedStyleProp(node, &Style::border, edge, value); +} + +float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { + auto border = resolveRef(node)->getStyle().border()[edge]; + if (border.isUndefined() || border.isAuto()) { + return YGUndefined; + } + + return static_cast(border).value; +} + +void YGNodeStyleSetGap( + const YGNodeRef node, + const YGGutter gutter, + const float gapLength) { + auto length = CompactValue::ofMaybe(gapLength); + updateIndexedStyleProp<&Style::gap, &Style::setGap>( + node, scopedEnum(gutter), length); +} + +float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { + auto gapLength = resolveRef(node)->getStyle().gap(scopedEnum(gutter)); + if (gapLength.isUndefined() || gapLength.isAuto()) { + return YGUndefined; + } + + return static_cast(gapLength).value; +} + +void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { + updateStyle( + node, &Style::aspectRatio, FloatOptional{aspectRatio}); +} + +float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { + const FloatOptional op = resolveRef(node)->getStyle().aspectRatio(); + return op.isUndefined() ? YGUndefined : op.unwrap(); +} + +void YGNodeStyleSetWidth(YGNodeRef node, float points) { + auto value = CompactValue::ofMaybe(points); + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Width, value); +} + +void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { + auto value = CompactValue::ofMaybe(percent); + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Width, value); +} + +void YGNodeStyleSetWidthAuto(YGNodeRef node) { + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Width, CompactValue::ofAuto()); +} + +YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { + return resolveRef(node)->getStyle().dimension(Dimension::Width); +} + +void YGNodeStyleSetHeight(YGNodeRef node, float points) { + auto value = CompactValue::ofMaybe(points); + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Height, value); +} + +void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { + auto value = CompactValue::ofMaybe(percent); + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Height, value); +} + +void YGNodeStyleSetHeightAuto(YGNodeRef node) { + updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( + node, Dimension::Height, CompactValue::ofAuto()); +} + +YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { + return resolveRef(node)->getStyle().dimension(Dimension::Height); +} + +void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { + auto value = CompactValue::ofMaybe(minWidth); + updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + node, Dimension::Width, value); +} + +void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { + auto value = CompactValue::ofMaybe(minWidth); + updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + node, Dimension::Width, value); +} + +YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { + return resolveRef(node)->getStyle().minDimension(Dimension::Width); +} + +void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { + auto value = CompactValue::ofMaybe(minHeight); + updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + node, Dimension::Height, value); +} + +void YGNodeStyleSetMinHeightPercent( + const YGNodeRef node, + const float minHeight) { + auto value = CompactValue::ofMaybe(minHeight); + updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( + node, Dimension::Height, value); +} + +YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { + return resolveRef(node)->getStyle().minDimension(Dimension::Height); +} + +void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { + auto value = CompactValue::ofMaybe(maxWidth); + updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + node, Dimension::Width, value); +} + +void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { + auto value = CompactValue::ofMaybe(maxWidth); + updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + node, Dimension::Width, value); +} + +YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { + return resolveRef(node)->getStyle().maxDimension(Dimension::Width); +} + +void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { + auto value = CompactValue::ofMaybe(maxHeight); + updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + node, Dimension::Height, value); +} + +void YGNodeStyleSetMaxHeightPercent( + const YGNodeRef node, + const float maxHeight) { + auto value = CompactValue::ofMaybe(maxHeight); + updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( + node, Dimension::Height, value); +} + +YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { + return resolveRef(node)->getStyle().maxDimension(Dimension::Height); +} diff --git a/yoga/YGNodeStyle.h b/yoga/YGNodeStyle.h new file mode 100644 index 0000000000..09727087ba --- /dev/null +++ b/yoga/YGNodeStyle.h @@ -0,0 +1,123 @@ +/* + * 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 + +#include +#include + +YG_EXTERN_C_BEGIN + +YG_EXPORT void YGNodeCopyStyle(YGNodeRef dstNode, YGNodeConstRef srcNode); + +YG_EXPORT void YGNodeStyleSetDirection(YGNodeRef node, YGDirection direction); +YG_EXPORT YGDirection YGNodeStyleGetDirection(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlexDirection( + YGNodeRef node, + YGFlexDirection flexDirection); +YG_EXPORT YGFlexDirection YGNodeStyleGetFlexDirection(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetJustifyContent( + YGNodeRef node, + YGJustify justifyContent); +YG_EXPORT YGJustify YGNodeStyleGetJustifyContent(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetAlignContent(YGNodeRef node, YGAlign alignContent); +YG_EXPORT YGAlign YGNodeStyleGetAlignContent(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetAlignItems(YGNodeRef node, YGAlign alignItems); +YG_EXPORT YGAlign YGNodeStyleGetAlignItems(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetAlignSelf(YGNodeRef node, YGAlign alignSelf); +YG_EXPORT YGAlign YGNodeStyleGetAlignSelf(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetPositionType( + YGNodeRef node, + YGPositionType positionType); +YG_EXPORT YGPositionType YGNodeStyleGetPositionType(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlexWrap(YGNodeRef node, YGWrap flexWrap); +YG_EXPORT YGWrap YGNodeStyleGetFlexWrap(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetOverflow(YGNodeRef node, YGOverflow overflow); +YG_EXPORT YGOverflow YGNodeStyleGetOverflow(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetDisplay(YGNodeRef node, YGDisplay display); +YG_EXPORT YGDisplay YGNodeStyleGetDisplay(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlex(YGNodeRef node, float flex); +YG_EXPORT float YGNodeStyleGetFlex(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlexGrow(YGNodeRef node, float flexGrow); +YG_EXPORT float YGNodeStyleGetFlexGrow(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlexShrink(YGNodeRef node, float flexShrink); +YG_EXPORT float YGNodeStyleGetFlexShrink(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetFlexBasis(YGNodeRef node, float flexBasis); +YG_EXPORT void YGNodeStyleSetFlexBasisPercent(YGNodeRef node, float flexBasis); +YG_EXPORT void YGNodeStyleSetFlexBasisAuto(YGNodeRef node); +YG_EXPORT YGValue YGNodeStyleGetFlexBasis(YGNodeConstRef node); + +YG_EXPORT void +YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float position); +YG_EXPORT void +YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float position); +YG_EXPORT YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge); + +YG_EXPORT void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin); +YG_EXPORT void +YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float margin); +YG_EXPORT void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge); +YG_EXPORT YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge); + +YG_EXPORT void +YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float padding); +YG_EXPORT void +YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float padding); +YG_EXPORT YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge); + +YG_EXPORT void YGNodeStyleSetBorder(YGNodeRef node, YGEdge edge, float border); +YG_EXPORT float YGNodeStyleGetBorder(YGNodeConstRef node, YGEdge edge); + +YG_EXPORT void +YGNodeStyleSetGap(YGNodeRef node, YGGutter gutter, float gapLength); +YG_EXPORT float YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter); + +YG_EXPORT void YGNodeStyleSetWidth(YGNodeRef node, float width); +YG_EXPORT void YGNodeStyleSetWidthPercent(YGNodeRef node, float width); +YG_EXPORT void YGNodeStyleSetWidthAuto(YGNodeRef node); +YG_EXPORT YGValue YGNodeStyleGetWidth(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetHeight(YGNodeRef node, float height); +YG_EXPORT void YGNodeStyleSetHeightPercent(YGNodeRef node, float height); +YG_EXPORT void YGNodeStyleSetHeightAuto(YGNodeRef node); +YG_EXPORT YGValue YGNodeStyleGetHeight(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetMinWidth(YGNodeRef node, float minWidth); +YG_EXPORT void YGNodeStyleSetMinWidthPercent(YGNodeRef node, float minWidth); +YG_EXPORT YGValue YGNodeStyleGetMinWidth(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetMinHeight(YGNodeRef node, float minHeight); +YG_EXPORT void YGNodeStyleSetMinHeightPercent(YGNodeRef node, float minHeight); +YG_EXPORT YGValue YGNodeStyleGetMinHeight(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetMaxWidth(YGNodeRef node, float maxWidth); +YG_EXPORT void YGNodeStyleSetMaxWidthPercent(YGNodeRef node, float maxWidth); +YG_EXPORT YGValue YGNodeStyleGetMaxWidth(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetMaxHeight(YGNodeRef node, float maxHeight); +YG_EXPORT void YGNodeStyleSetMaxHeightPercent(YGNodeRef node, float maxHeight); +YG_EXPORT YGValue YGNodeStyleGetMaxHeight(YGNodeConstRef node); + +YG_EXPORT void YGNodeStyleSetAspectRatio(YGNodeRef node, float aspectRatio); +YG_EXPORT float YGNodeStyleGetAspectRatio(YGNodeConstRef node); + +YG_EXTERN_C_END diff --git a/yoga/YGPixelGrid.cpp b/yoga/YGPixelGrid.cpp new file mode 100644 index 0000000000..a855a292c2 --- /dev/null +++ b/yoga/YGPixelGrid.cpp @@ -0,0 +1,22 @@ +/* + * 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 + +#include + +using namespace facebook; +using namespace facebook::yoga; + +float YGRoundValueToPixelGrid( + const double value, + const double pointScaleFactor, + const bool forceCeil, + const bool forceFloor) { + return yoga::roundValueToPixelGrid( + value, pointScaleFactor, forceCeil, forceFloor); +} diff --git a/yoga/YGPixelGrid.h b/yoga/YGPixelGrid.h new file mode 100644 index 0000000000..e2a6aeb698 --- /dev/null +++ b/yoga/YGPixelGrid.h @@ -0,0 +1,29 @@ +/* + * 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 + +#include +#include +#include + +YG_EXTERN_C_BEGIN + +/** + * Rounds a point value to the nearest whole pixel, given a pointScaleFactor + * describing pixel density. + * @returns the rounded value in points + */ +YG_EXPORT float YGRoundValueToPixelGrid( + double value, + double pointScaleFactor, + bool forceCeil, + bool forceFloor); + +YG_EXTERN_C_END diff --git a/yoga/YGValue.cpp b/yoga/YGValue.cpp index 194d22caa8..7a469b9cc4 100644 --- a/yoga/YGValue.cpp +++ b/yoga/YGValue.cpp @@ -6,7 +6,15 @@ */ #include +#include + +using namespace facebook; +using namespace facebook::yoga; const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; + +bool YGFloatIsUndefined(const float value) { + return yoga::isUndefined(value); +} diff --git a/yoga/YGValue.h b/yoga/YGValue.h index d6051070b0..be957028b5 100644 --- a/yoga/YGValue.h +++ b/yoga/YGValue.h @@ -7,30 +7,55 @@ #pragma once +#include + #include #include +/** + * Float value to represent "undefined" in style values + */ +#ifdef __cplusplus +#include +constexpr float YGUndefined = std::numeric_limits::quiet_NaN(); +#else +#include +#define YGUndefined NAN +#endif + YG_EXTERN_C_BEGIN +/** + * Structure used to represent a dimension in a style + */ typedef struct YGValue { float value; YGUnit unit; } YGValue; +/** + * Constant for a dimension of "auto" + */ YG_EXPORT extern const YGValue YGValueAuto; + +/** + * Constant for a dimension which is not defined + */ YG_EXPORT extern const YGValue YGValueUndefined; + +/** + * Constant for a dimension that is zero-length + */ YG_EXPORT extern const YGValue YGValueZero; -YG_EXTERN_C_END +/** + * Whether a dimension represented as a float is defined + */ +YG_EXPORT bool YGFloatIsUndefined(float value); -#ifdef __cplusplus -#include -constexpr float YGUndefined = std::numeric_limits::quiet_NaN(); -#else -#include -#define YGUndefined NAN -#endif +YG_EXTERN_C_END +// Equality operators for comparison of YGValue in C++ #ifdef __cplusplus inline bool operator==(const YGValue& lhs, const YGValue& rhs) { if (lhs.unit != rhs.unit) { diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h deleted file mode 100644 index 7c1caaa378..0000000000 --- a/yoga/Yoga-internal.h +++ /dev/null @@ -1,22 +0,0 @@ -/* - * 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 -#include -#include - -#include - -YG_EXTERN_C_BEGIN - -// Deallocates a Yoga Node. Unlike YGNodeFree, does not remove the node from -// its parent or children. -YG_EXPORT void YGNodeDeallocate(YGNodeRef node); - -YG_EXTERN_C_END diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp deleted file mode 100644 index 5109223fe3..0000000000 --- a/yoga/Yoga.cpp +++ /dev/null @@ -1,959 +0,0 @@ -/* - * 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 -#include - -#include -#include -#include -#include -#include -#include -#include -#include - -using namespace facebook; -using namespace facebook::yoga; - -bool YGFloatIsUndefined(const float value) { - return yoga::isUndefined(value); -} - -void* YGNodeGetContext(YGNodeConstRef node) { - return resolveRef(node)->getContext(); -} - -void YGNodeSetContext(YGNodeRef node, void* context) { - return resolveRef(node)->setContext(context); -} - -YGConfigConstRef YGNodeGetConfig(YGNodeRef node) { - return resolveRef(node)->getConfig(); -} - -void YGNodeSetConfig(YGNodeRef node, YGConfigRef config) { - resolveRef(node)->setConfig(resolveRef(config)); -} - -bool YGNodeHasMeasureFunc(YGNodeConstRef node) { - return resolveRef(node)->hasMeasureFunc(); -} - -void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc) { - resolveRef(node)->setMeasureFunc(measureFunc); -} - -bool YGNodeHasBaselineFunc(YGNodeConstRef node) { - return resolveRef(node)->hasBaselineFunc(); -} - -void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) { - resolveRef(node)->setBaselineFunc(baselineFunc); -} - -YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeConstRef node) { - return resolveRef(node)->getDirtiedFunc(); -} - -void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc) { - resolveRef(node)->setDirtiedFunc(dirtiedFunc); -} - -void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc) { - resolveRef(node)->setPrintFunc(printFunc); -} - -bool YGNodeGetHasNewLayout(YGNodeConstRef node) { - return resolveRef(node)->getHasNewLayout(); -} - -void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) { - resolveRef(config)->setShouldPrintTree(enabled); -} - -void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) { - resolveRef(node)->setHasNewLayout(hasNewLayout); -} - -YGNodeType YGNodeGetNodeType(YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getNodeType()); -} - -void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType) { - return resolveRef(node)->setNodeType(scopedEnum(nodeType)); -} - -bool YGNodeIsDirty(YGNodeConstRef node) { - return resolveRef(node)->isDirty(); -} - -YGNodeRef YGNodeNewWithConfig(const YGConfigConstRef config) { - auto* node = new yoga::Node{resolveRef(config)}; - yoga::assertFatal( - config != nullptr, "Tried to construct YGNode with null config"); - Event::publish(node, {config}); - - return node; -} - -YGConfigConstRef YGConfigGetDefault() { - return &yoga::Config::getDefault(); -} - -YGNodeRef YGNodeNew(void) { - return YGNodeNewWithConfig(YGConfigGetDefault()); -} - -YGNodeRef YGNodeClone(YGNodeConstRef oldNodeRef) { - auto oldNode = resolveRef(oldNodeRef); - const auto node = new yoga::Node(*oldNode); - yoga::assertFatalWithConfig( - oldNode->getConfig(), - node != nullptr, - "Could not allocate memory for node"); - Event::publish(node, {node->getConfig()}); - node->setOwner(nullptr); - return node; -} - -void YGNodeFree(const YGNodeRef nodeRef) { - const auto node = resolveRef(nodeRef); - - if (auto owner = node->getOwner()) { - owner->removeChild(node); - node->setOwner(nullptr); - } - - const size_t childCount = node->getChildCount(); - for (size_t i = 0; i < childCount; i++) { - auto child = node->getChild(i); - child->setOwner(nullptr); - } - - node->clearChildren(); - YGNodeDeallocate(node); -} - -void YGNodeDeallocate(const YGNodeRef node) { - Event::publish(node, {YGNodeGetConfig(node)}); - delete resolveRef(node); -} - -void YGNodeFreeRecursiveWithCleanupFunc( - const YGNodeRef rootRef, - YGNodeCleanupFunc cleanup) { - const auto root = resolveRef(rootRef); - - size_t skipped = 0; - while (root->getChildCount() > skipped) { - const auto child = root->getChild(skipped); - if (child->getOwner() != root) { - // Don't free shared nodes that we don't own. - skipped += 1; - } else { - YGNodeRemoveChild(root, child); - YGNodeFreeRecursive(child); - } - } - if (cleanup != nullptr) { - cleanup(root); - } - YGNodeFree(root); -} - -void YGNodeFreeRecursive(const YGNodeRef root) { - return YGNodeFreeRecursiveWithCleanupFunc(root, nullptr); -} - -void YGNodeReset(YGNodeRef node) { - resolveRef(node)->reset(); -} - -YGConfigRef YGConfigNew(void) { - return new yoga::Config(getDefaultLogger()); -} - -void YGConfigFree(const YGConfigRef config) { - delete resolveRef(config); -} - -void YGNodeSetIsReferenceBaseline(YGNodeRef nodeRef, bool isReferenceBaseline) { - const auto node = resolveRef(nodeRef); - if (node->isReferenceBaseline() != isReferenceBaseline) { - node->setIsReferenceBaseline(isReferenceBaseline); - node->markDirtyAndPropagate(); - } -} - -bool YGNodeIsReferenceBaseline(YGNodeConstRef node) { - return resolveRef(node)->isReferenceBaseline(); -} - -void YGNodeInsertChild( - const YGNodeRef ownerRef, - const YGNodeRef childRef, - const size_t index) { - auto owner = resolveRef(ownerRef); - auto child = resolveRef(childRef); - - yoga::assertFatalWithNode( - owner, - child->getOwner() == nullptr, - "Child already has a owner, it must be removed first."); - - yoga::assertFatalWithNode( - owner, - !owner->hasMeasureFunc(), - "Cannot add child: Nodes with measure functions cannot have children."); - - owner->insertChild(child, index); - child->setOwner(owner); - owner->markDirtyAndPropagate(); -} - -void YGNodeSwapChild( - const YGNodeRef ownerRef, - const YGNodeRef childRef, - const size_t index) { - auto owner = resolveRef(ownerRef); - auto child = resolveRef(childRef); - - owner->replaceChild(child, index); - child->setOwner(owner); -} - -void YGNodeRemoveChild( - const YGNodeRef ownerRef, - const YGNodeRef excludedChildRef) { - auto owner = resolveRef(ownerRef); - auto excludedChild = resolveRef(excludedChildRef); - - if (owner->getChildCount() == 0) { - // This is an empty set. Nothing to remove. - return; - } - - // Children may be shared between parents, which is indicated by not having an - // owner. We only want to reset the child completely if it is owned - // exclusively by one node. - auto childOwner = excludedChild->getOwner(); - if (owner->removeChild(excludedChild)) { - if (owner == childOwner) { - excludedChild->setLayout({}); // layout is no longer valid - excludedChild->setOwner(nullptr); - } - owner->markDirtyAndPropagate(); - } -} - -void YGNodeRemoveAllChildren(const YGNodeRef ownerRef) { - auto owner = resolveRef(ownerRef); - - const size_t childCount = owner->getChildCount(); - if (childCount == 0) { - // This is an empty set already. Nothing to do. - return; - } - auto* firstChild = owner->getChild(0); - if (firstChild->getOwner() == owner) { - // If the first child has this node as its owner, we assume that this child - // set is unique. - for (size_t i = 0; i < childCount; i++) { - yoga::Node* oldChild = owner->getChild(i); - oldChild->setLayout({}); // layout is no longer valid - oldChild->setOwner(nullptr); - } - owner->clearChildren(); - owner->markDirtyAndPropagate(); - return; - } - // Otherwise, we are not the owner of the child set. We don't have to do - // anything to clear it. - owner->setChildren({}); - owner->markDirtyAndPropagate(); -} - -void YGNodeSetChildren( - const YGNodeRef ownerRef, - const YGNodeRef* childrenRefs, - const size_t count) { - auto owner = resolveRef(ownerRef); - auto children = reinterpret_cast(childrenRefs); - - if (!owner) { - return; - } - - const std::vector childrenVector = {children, children + count}; - if (childrenVector.size() == 0) { - if (owner->getChildCount() > 0) { - for (auto* child : owner->getChildren()) { - child->setLayout({}); - child->setOwner(nullptr); - } - owner->setChildren({}); - owner->markDirtyAndPropagate(); - } - } else { - if (owner->getChildCount() > 0) { - for (auto* oldChild : owner->getChildren()) { - // Our new children may have nodes in common with the old children. We - // don't reset these common nodes. - if (std::find(childrenVector.begin(), childrenVector.end(), oldChild) == - childrenVector.end()) { - oldChild->setLayout({}); - oldChild->setOwner(nullptr); - } - } - } - owner->setChildren(childrenVector); - for (yoga::Node* child : childrenVector) { - child->setOwner(owner); - } - owner->markDirtyAndPropagate(); - } -} - -YGNodeRef YGNodeGetChild(const YGNodeRef nodeRef, const size_t index) { - const auto node = resolveRef(nodeRef); - - if (index < node->getChildren().size()) { - return node->getChild(index); - } - return nullptr; -} - -size_t YGNodeGetChildCount(const YGNodeConstRef node) { - return resolveRef(node)->getChildren().size(); -} - -YGNodeRef YGNodeGetOwner(const YGNodeRef node) { - return resolveRef(node)->getOwner(); -} - -YGNodeRef YGNodeGetParent(const YGNodeRef node) { - return resolveRef(node)->getOwner(); -} - -void YGNodeMarkDirty(const YGNodeRef nodeRef) { - const auto node = resolveRef(nodeRef); - - yoga::assertFatalWithNode( - node, - node->hasMeasureFunc(), - "Only leaf nodes with custom measure functions " - "should manually mark themselves as dirty"); - - node->markDirtyAndPropagate(); -} - -void YGNodeCopyStyle( - const YGNodeRef dstNodeRef, - const YGNodeConstRef srcNodeRef) { - auto dstNode = resolveRef(dstNodeRef); - auto srcNode = resolveRef(srcNodeRef); - - if (!(dstNode->getStyle() == srcNode->getStyle())) { - dstNode->setStyle(srcNode->getStyle()); - dstNode->markDirtyAndPropagate(); - } -} - -float YGNodeStyleGetFlexGrow(const YGNodeConstRef nodeRef) { - const auto node = resolveRef(nodeRef); - return node->getStyle().flexGrow().isUndefined() - ? Style::DefaultFlexGrow - : node->getStyle().flexGrow().unwrap(); -} - -float YGNodeStyleGetFlexShrink(const YGNodeConstRef nodeRef) { - const auto node = resolveRef(nodeRef); - return node->getStyle().flexShrink().isUndefined() - ? (node->getConfig()->useWebDefaults() ? Style::WebDefaultFlexShrink - : Style::DefaultFlexShrink) - : node->getStyle().flexShrink().unwrap(); -} - -namespace { - -template -void updateStyle( - yoga::Node* node, - T value, - NeedsUpdate&& needsUpdate, - Update&& update) { - if (needsUpdate(node->getStyle(), value)) { - update(node->getStyle(), value); - node->markDirtyAndPropagate(); - } -} - -template -void updateStyle(YGNodeRef node, Ref (Style::*prop)(), T value) { - updateStyle( - resolveRef(node), - value, - [prop](Style& s, T x) { return (s.*prop)() != x; }, - [prop](Style& s, T x) { (s.*prop)() = x; }); -} - -template -void updateIndexedStyleProp( - YGNodeRef node, - Ref (Style::*prop)(), - Idx idx, - CompactValue value) { - updateStyle( - resolveRef(node), - value, - [idx, prop](Style& s, CompactValue x) { return (s.*prop)()[idx] != x; }, - [idx, prop](Style& s, CompactValue x) { (s.*prop)()[idx] = x; }); -} - -template -void updateIndexedStyleProp(YGNodeRef node, IdxT idx, CompactValue value) { - updateStyle( - resolveRef(node), - value, - [idx](Style& s, CompactValue x) { return (s.*GetterT)(idx) != x; }, - [idx](Style& s, CompactValue x) { (s.*SetterT)(idx, x); }); -} - -} // namespace - -// MSVC has trouble inferring the return type of pointer to member functions -// with const and non-const overloads, instead of preferring the non-const -// overload like clang and GCC. For the purposes of updateStyle(), we can help -// MSVC by specifying that return type explicitly. In combination with -// decltype, MSVC will prefer the non-const version. -#define MSVC_HINT(PROP) decltype(Style{}.PROP()) - -void YGNodeStyleSetDirection(const YGNodeRef node, const YGDirection value) { - updateStyle(node, &Style::direction, scopedEnum(value)); -} -YGDirection YGNodeStyleGetDirection(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().direction()); -} - -void YGNodeStyleSetFlexDirection( - const YGNodeRef node, - const YGFlexDirection flexDirection) { - updateStyle( - node, &Style::flexDirection, scopedEnum(flexDirection)); -} -YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().flexDirection()); -} - -void YGNodeStyleSetJustifyContent( - const YGNodeRef node, - const YGJustify justifyContent) { - updateStyle( - node, &Style::justifyContent, scopedEnum(justifyContent)); -} -YGJustify YGNodeStyleGetJustifyContent(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().justifyContent()); -} - -void YGNodeStyleSetAlignContent( - const YGNodeRef node, - const YGAlign alignContent) { - updateStyle( - node, &Style::alignContent, scopedEnum(alignContent)); -} -YGAlign YGNodeStyleGetAlignContent(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().alignContent()); -} - -void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { - updateStyle( - node, &Style::alignItems, scopedEnum(alignItems)); -} -YGAlign YGNodeStyleGetAlignItems(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().alignItems()); -} - -void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { - updateStyle( - node, &Style::alignSelf, scopedEnum(alignSelf)); -} -YGAlign YGNodeStyleGetAlignSelf(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().alignSelf()); -} - -void YGNodeStyleSetPositionType( - const YGNodeRef node, - const YGPositionType positionType) { - updateStyle( - node, &Style::positionType, scopedEnum(positionType)); -} -YGPositionType YGNodeStyleGetPositionType(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().positionType()); -} - -void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { - updateStyle( - node, &Style::flexWrap, scopedEnum(flexWrap)); -} -YGWrap YGNodeStyleGetFlexWrap(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().flexWrap()); -} - -void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { - updateStyle( - node, &Style::overflow, scopedEnum(overflow)); -} -YGOverflow YGNodeStyleGetOverflow(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().overflow()); -} - -void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { - updateStyle(node, &Style::display, scopedEnum(display)); -} -YGDisplay YGNodeStyleGetDisplay(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getStyle().display()); -} - -void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { - updateStyle(node, &Style::flex, FloatOptional{flex}); -} - -float YGNodeStyleGetFlex(const YGNodeConstRef nodeRef) { - const auto node = resolveRef(nodeRef); - return node->getStyle().flex().isUndefined() - ? YGUndefined - : node->getStyle().flex().unwrap(); -} - -void YGNodeStyleSetFlexGrow(const YGNodeRef node, const float flexGrow) { - updateStyle( - node, &Style::flexGrow, FloatOptional{flexGrow}); -} - -void YGNodeStyleSetFlexShrink(const YGNodeRef node, const float flexShrink) { - updateStyle( - node, &Style::flexShrink, FloatOptional{flexShrink}); -} - -YGValue YGNodeStyleGetFlexBasis(const YGNodeConstRef node) { - YGValue flexBasis = resolveRef(node)->getStyle().flexBasis(); - if (flexBasis.unit == YGUnitUndefined || flexBasis.unit == YGUnitAuto) { - flexBasis.value = YGUndefined; - } - return flexBasis; -} - -void YGNodeStyleSetFlexBasis(const YGNodeRef node, const float flexBasis) { - auto value = CompactValue::ofMaybe(flexBasis); - updateStyle(node, &Style::flexBasis, value); -} - -void YGNodeStyleSetFlexBasisPercent( - const YGNodeRef node, - const float flexBasisPercent) { - auto value = CompactValue::ofMaybe(flexBasisPercent); - updateStyle(node, &Style::flexBasis, value); -} - -void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node) { - updateStyle( - node, &Style::flexBasis, CompactValue::ofAuto()); -} - -void YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::position, edge, value); -} -void YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::position, edge, value); -} -YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().position()[edge]; -} - -void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp(node, &Style::margin, edge, value); -} -void YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp(node, &Style::margin, edge, value); -} -void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge) { - updateIndexedStyleProp( - node, &Style::margin, edge, CompactValue::ofAuto()); -} -YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().margin()[edge]; -} - -void YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp( - node, &Style::padding, edge, value); -} -void YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp( - node, &Style::padding, edge, value); -} -YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge) { - return resolveRef(node)->getStyle().padding()[edge]; -} - -void YGNodeStyleSetBorder( - const YGNodeRef node, - const YGEdge edge, - const float border) { - auto value = CompactValue::ofMaybe(border); - updateIndexedStyleProp(node, &Style::border, edge, value); -} - -float YGNodeStyleGetBorder(const YGNodeConstRef node, const YGEdge edge) { - auto border = resolveRef(node)->getStyle().border()[edge]; - if (border.isUndefined() || border.isAuto()) { - return YGUndefined; - } - - return static_cast(border).value; -} - -void YGNodeStyleSetGap( - const YGNodeRef node, - const YGGutter gutter, - const float gapLength) { - auto length = CompactValue::ofMaybe(gapLength); - updateIndexedStyleProp<&Style::gap, &Style::setGap>( - node, scopedEnum(gutter), length); -} - -float YGNodeStyleGetGap(const YGNodeConstRef node, const YGGutter gutter) { - auto gapLength = resolveRef(node)->getStyle().gap(scopedEnum(gutter)); - if (gapLength.isUndefined() || gapLength.isAuto()) { - return YGUndefined; - } - - return static_cast(gapLength).value; -} - -// Yoga specific properties, not compatible with flexbox specification - -float YGNodeStyleGetAspectRatio(const YGNodeConstRef node) { - const FloatOptional op = resolveRef(node)->getStyle().aspectRatio(); - return op.isUndefined() ? YGUndefined : op.unwrap(); -} - -void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { - updateStyle( - node, &Style::aspectRatio, FloatOptional{aspectRatio}); -} - -void YGNodeStyleSetWidth(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); -} -void YGNodeStyleSetWidthPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, value); -} -void YGNodeStyleSetWidthAuto(YGNodeRef node) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Width, CompactValue::ofAuto()); -} -YGValue YGNodeStyleGetWidth(YGNodeConstRef node) { - return resolveRef(node)->getStyle().dimension(Dimension::Width); -} - -void YGNodeStyleSetHeight(YGNodeRef node, float points) { - auto value = CompactValue::ofMaybe(points); - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); -} -void YGNodeStyleSetHeightPercent(YGNodeRef node, float percent) { - auto value = CompactValue::ofMaybe(percent); - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, value); -} -void YGNodeStyleSetHeightAuto(YGNodeRef node) { - updateIndexedStyleProp<&Style::dimension, &Style::setDimension>( - node, Dimension::Height, CompactValue::ofAuto()); -} -YGValue YGNodeStyleGetHeight(YGNodeConstRef node) { - return resolveRef(node)->getStyle().dimension(Dimension::Height); -} - -void YGNodeStyleSetMinWidth(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); -} -void YGNodeStyleSetMinWidthPercent(const YGNodeRef node, const float minWidth) { - auto value = CompactValue::ofMaybe(minWidth); - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Width, value); -} -YGValue YGNodeStyleGetMinWidth(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().minDimension(Dimension::Width); -} - -void YGNodeStyleSetMinHeight(const YGNodeRef node, const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); -} -void YGNodeStyleSetMinHeightPercent( - const YGNodeRef node, - const float minHeight) { - auto value = CompactValue::ofMaybe(minHeight); - updateIndexedStyleProp<&Style::minDimension, &Style::setMinDimension>( - node, Dimension::Height, value); -} -YGValue YGNodeStyleGetMinHeight(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().minDimension(Dimension::Height); -} - -void YGNodeStyleSetMaxWidth(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); -} -void YGNodeStyleSetMaxWidthPercent(const YGNodeRef node, const float maxWidth) { - auto value = CompactValue::ofMaybe(maxWidth); - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Width, value); -} -YGValue YGNodeStyleGetMaxWidth(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().maxDimension(Dimension::Width); -} - -void YGNodeStyleSetMaxHeight(const YGNodeRef node, const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); -} -void YGNodeStyleSetMaxHeightPercent( - const YGNodeRef node, - const float maxHeight) { - auto value = CompactValue::ofMaybe(maxHeight); - updateIndexedStyleProp<&Style::maxDimension, &Style::setMaxDimension>( - node, Dimension::Height, value); -} -YGValue YGNodeStyleGetMaxHeight(const YGNodeConstRef node) { - return resolveRef(node)->getStyle().maxDimension(Dimension::Height); -} - -namespace { - -template -float getResolvedLayoutProperty( - const YGNodeConstRef nodeRef, - const YGEdge edge) { - const auto node = resolveRef(nodeRef); - yoga::assertFatalWithNode( - node, - edge <= YGEdgeEnd, - "Cannot get layout properties of multi-edge shorthands"); - - if (edge == YGEdgeStart) { - if (node->getLayout().direction() == Direction::RTL) { - return (node->getLayout().*LayoutMember)[YGEdgeRight]; - } else { - return (node->getLayout().*LayoutMember)[YGEdgeLeft]; - } - } - - if (edge == YGEdgeEnd) { - if (node->getLayout().direction() == Direction::RTL) { - return (node->getLayout().*LayoutMember)[YGEdgeLeft]; - } else { - return (node->getLayout().*LayoutMember)[YGEdgeRight]; - } - } - - return (node->getLayout().*LayoutMember)[edge]; -} - -} // namespace - -float YGNodeLayoutGetLeft(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeLeft]; -} - -float YGNodeLayoutGetTop(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeTop]; -} - -float YGNodeLayoutGetRight(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeRight]; -} - -float YGNodeLayoutGetBottom(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().position[YGEdgeBottom]; -} - -float YGNodeLayoutGetWidth(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().dimension(Dimension::Width); -} - -float YGNodeLayoutGetHeight(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().dimension(Dimension::Height); -} - -YGDirection YGNodeLayoutGetDirection(const YGNodeConstRef node) { - return unscopedEnum(resolveRef(node)->getLayout().direction()); -} - -bool YGNodeLayoutGetHadOverflow(const YGNodeConstRef node) { - return resolveRef(node)->getLayout().hadOverflow(); -} - -float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::margin>(node, edge); -} - -float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::border>(node, edge); -} - -float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge) { - return getResolvedLayoutProperty<&LayoutResults::padding>(node, edge); -} - -#ifdef DEBUG -void YGNodePrint(const YGNodeConstRef node, const YGPrintOptions options) { - yoga::print(resolveRef(node), scopedEnum(options)); -} -#endif - -void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) { - if (logger != nullptr) { - resolveRef(config)->setLogger(logger); - } else { - resolveRef(config)->setLogger(getDefaultLogger()); - } -} - -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(); -} - -float YGRoundValueToPixelGrid( - const double value, - const double pointScaleFactor, - const bool forceCeil, - const bool forceFloor) { - return yoga::roundValueToPixelGrid( - value, pointScaleFactor, forceCeil, forceFloor); -} - -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 YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) { - resolveRef(config)->setUseWebDefaults(enabled); -} - -bool YGConfigGetUseWebDefaults(const YGConfigConstRef config) { - return resolveRef(config)->useWebDefaults(); -} - -void YGConfigSetContext(const YGConfigRef config, void* context) { - resolveRef(config)->setContext(context); -} - -void* YGConfigGetContext(const YGConfigConstRef config) { - return resolveRef(config)->getContext(); -} - -void YGConfigSetErrata(YGConfigRef config, YGErrata errata) { - resolveRef(config)->setErrata(scopedEnum(errata)); -} - -YGErrata YGConfigGetErrata(YGConfigConstRef config) { - return unscopedEnum(resolveRef(config)->getErrata()); -} - -void YGConfigSetCloneNodeFunc( - const YGConfigRef config, - const YGCloneNodeFunc callback) { - resolveRef(config)->setCloneNodeCallback(callback); -} - -// TODO: This should not be part of the public API. Remove after removing -// ComponentKit usage of it. -bool YGNodeCanUseCachedMeasurement( - YGMeasureMode widthMode, - float availableWidth, - YGMeasureMode heightMode, - float availableHeight, - YGMeasureMode lastWidthMode, - float lastAvailableWidth, - YGMeasureMode lastHeightMode, - float lastAvailableHeight, - float lastComputedWidth, - float lastComputedHeight, - float marginRow, - float marginColumn, - YGConfigRef config) { - return yoga::canUseCachedMeasurement( - scopedEnum(widthMode), - availableWidth, - scopedEnum(heightMode), - availableHeight, - scopedEnum(lastWidthMode), - lastAvailableWidth, - scopedEnum(lastHeightMode), - lastAvailableHeight, - lastComputedWidth, - lastComputedHeight, - marginRow, - marginColumn, - resolveRef(config)); -} - -void YGNodeCalculateLayout( - const YGNodeRef node, - const float ownerWidth, - const float ownerHeight, - const YGDirection ownerDirection) { - yoga::calculateLayout( - resolveRef(node), ownerWidth, ownerHeight, scopedEnum(ownerDirection)); -} diff --git a/yoga/Yoga.h b/yoga/Yoga.h index 86f09fa0c4..e4b16e4441 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -7,315 +7,11 @@ #pragma once -#include -#include -#include -#include - +#include #include #include +#include +#include +#include +#include #include - -YG_EXTERN_C_BEGIN - -typedef struct YGSize { - float width; - float height; -} YGSize; - -typedef struct YGConfig* YGConfigRef; -typedef const struct YGConfig* YGConfigConstRef; - -typedef struct YGNode* YGNodeRef; -typedef const struct YGNode* YGNodeConstRef; - -typedef YGSize (*YGMeasureFunc)( - YGNodeConstRef node, - float width, - YGMeasureMode widthMode, - float height, - YGMeasureMode heightMode); -typedef float (*YGBaselineFunc)(YGNodeConstRef node, float width, float height); -typedef void (*YGDirtiedFunc)(YGNodeConstRef node); -typedef void (*YGPrintFunc)(YGNodeConstRef node); -typedef void (*YGNodeCleanupFunc)(YGNodeConstRef node); -typedef int (*YGLogger)( - YGConfigConstRef config, - YGNodeConstRef node, - YGLogLevel level, - const char* format, - va_list args); -typedef YGNodeRef (*YGCloneNodeFunc)( - YGNodeConstRef oldNode, - YGNodeConstRef owner, - size_t childIndex); - -// YGNode -YG_EXPORT YGNodeRef YGNodeNew(void); -YG_EXPORT YGNodeRef YGNodeNewWithConfig(YGConfigConstRef config); -YG_EXPORT YGNodeRef YGNodeClone(YGNodeConstRef node); -YG_EXPORT void YGNodeFree(YGNodeRef node); -YG_EXPORT void YGNodeFreeRecursiveWithCleanupFunc( - YGNodeRef node, - YGNodeCleanupFunc cleanup); -YG_EXPORT void YGNodeFreeRecursive(YGNodeRef node); -YG_EXPORT void YGNodeReset(YGNodeRef node); - -YG_EXPORT void YGNodeInsertChild(YGNodeRef node, YGNodeRef child, size_t index); - -YG_EXPORT void YGNodeSwapChild(YGNodeRef node, YGNodeRef child, size_t index); - -YG_EXPORT void YGNodeRemoveChild(YGNodeRef node, YGNodeRef child); -YG_EXPORT void YGNodeRemoveAllChildren(YGNodeRef node); -YG_EXPORT YGNodeRef YGNodeGetChild(YGNodeRef node, size_t index); -YG_EXPORT YGNodeRef YGNodeGetOwner(YGNodeRef node); -YG_EXPORT YGNodeRef YGNodeGetParent(YGNodeRef node); -YG_EXPORT size_t YGNodeGetChildCount(YGNodeConstRef node); -YG_EXPORT void -YGNodeSetChildren(YGNodeRef owner, const YGNodeRef* children, size_t count); - -YG_EXPORT void YGNodeSetIsReferenceBaseline( - YGNodeRef node, - bool isReferenceBaseline); - -YG_EXPORT bool YGNodeIsReferenceBaseline(YGNodeConstRef node); - -YG_EXPORT void YGNodeCalculateLayout( - YGNodeRef node, - float availableWidth, - float availableHeight, - YGDirection ownerDirection); - -// Mark a node as dirty. Only valid for nodes with a custom measure function -// set. -// -// Yoga knows when to mark all other nodes as dirty but because nodes with -// measure functions depend on information not known to Yoga they must perform -// this dirty marking manually. -YG_EXPORT void YGNodeMarkDirty(YGNodeRef node); - -YG_EXPORT void YGNodePrint(YGNodeConstRef node, YGPrintOptions options); - -YG_EXPORT bool YGFloatIsUndefined(float value); - -// TODO: This should not be part of the public API. Remove after removing -// ComponentKit usage of it. -YG_EXPORT bool YGNodeCanUseCachedMeasurement( - YGMeasureMode widthMode, - float availableWidth, - YGMeasureMode heightMode, - float availableHeight, - YGMeasureMode lastWidthMode, - float lastAvailableWidth, - YGMeasureMode lastHeightMode, - float lastAvailableHeight, - float lastComputedWidth, - float lastComputedHeight, - float marginRow, - float marginColumn, - YGConfigRef config); - -YG_EXPORT void YGNodeCopyStyle(YGNodeRef dstNode, YGNodeConstRef srcNode); - -YG_EXPORT void* YGNodeGetContext(YGNodeConstRef node); -YG_EXPORT void YGNodeSetContext(YGNodeRef node, void* context); - -YG_EXPORT YGConfigConstRef YGNodeGetConfig(YGNodeRef node); -YG_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config); - -YG_EXPORT void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled); -YG_EXPORT bool YGNodeHasMeasureFunc(YGNodeConstRef node); -YG_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); -YG_EXPORT bool YGNodeHasBaselineFunc(YGNodeConstRef node); -YG_EXPORT void YGNodeSetBaselineFunc( - YGNodeRef node, - YGBaselineFunc baselineFunc); -YG_EXPORT YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeConstRef node); -YG_EXPORT void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc); -YG_EXPORT void YGNodeSetPrintFunc(YGNodeRef node, YGPrintFunc printFunc); -YG_EXPORT bool YGNodeGetHasNewLayout(YGNodeConstRef node); -YG_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout); -YG_EXPORT YGNodeType YGNodeGetNodeType(YGNodeConstRef node); -YG_EXPORT void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType); -YG_EXPORT bool YGNodeIsDirty(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetDirection(YGNodeRef node, YGDirection direction); -YG_EXPORT YGDirection YGNodeStyleGetDirection(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlexDirection( - YGNodeRef node, - YGFlexDirection flexDirection); -YG_EXPORT YGFlexDirection YGNodeStyleGetFlexDirection(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetJustifyContent( - YGNodeRef node, - YGJustify justifyContent); -YG_EXPORT YGJustify YGNodeStyleGetJustifyContent(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetAlignContent(YGNodeRef node, YGAlign alignContent); -YG_EXPORT YGAlign YGNodeStyleGetAlignContent(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetAlignItems(YGNodeRef node, YGAlign alignItems); -YG_EXPORT YGAlign YGNodeStyleGetAlignItems(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetAlignSelf(YGNodeRef node, YGAlign alignSelf); -YG_EXPORT YGAlign YGNodeStyleGetAlignSelf(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetPositionType( - YGNodeRef node, - YGPositionType positionType); -YG_EXPORT YGPositionType YGNodeStyleGetPositionType(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlexWrap(YGNodeRef node, YGWrap flexWrap); -YG_EXPORT YGWrap YGNodeStyleGetFlexWrap(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetOverflow(YGNodeRef node, YGOverflow overflow); -YG_EXPORT YGOverflow YGNodeStyleGetOverflow(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetDisplay(YGNodeRef node, YGDisplay display); -YG_EXPORT YGDisplay YGNodeStyleGetDisplay(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlex(YGNodeRef node, float flex); -YG_EXPORT float YGNodeStyleGetFlex(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlexGrow(YGNodeRef node, float flexGrow); -YG_EXPORT float YGNodeStyleGetFlexGrow(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlexShrink(YGNodeRef node, float flexShrink); -YG_EXPORT float YGNodeStyleGetFlexShrink(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetFlexBasis(YGNodeRef node, float flexBasis); -YG_EXPORT void YGNodeStyleSetFlexBasisPercent(YGNodeRef node, float flexBasis); -YG_EXPORT void YGNodeStyleSetFlexBasisAuto(YGNodeRef node); -YG_EXPORT YGValue YGNodeStyleGetFlexBasis(YGNodeConstRef node); - -YG_EXPORT void -YGNodeStyleSetPosition(YGNodeRef node, YGEdge edge, float position); -YG_EXPORT void -YGNodeStyleSetPositionPercent(YGNodeRef node, YGEdge edge, float position); -YG_EXPORT YGValue YGNodeStyleGetPosition(YGNodeConstRef node, YGEdge edge); - -YG_EXPORT void YGNodeStyleSetMargin(YGNodeRef node, YGEdge edge, float margin); -YG_EXPORT void -YGNodeStyleSetMarginPercent(YGNodeRef node, YGEdge edge, float margin); -YG_EXPORT void YGNodeStyleSetMarginAuto(YGNodeRef node, YGEdge edge); -YG_EXPORT YGValue YGNodeStyleGetMargin(YGNodeConstRef node, YGEdge edge); - -YG_EXPORT void -YGNodeStyleSetPadding(YGNodeRef node, YGEdge edge, float padding); -YG_EXPORT void -YGNodeStyleSetPaddingPercent(YGNodeRef node, YGEdge edge, float padding); -YG_EXPORT YGValue YGNodeStyleGetPadding(YGNodeConstRef node, YGEdge edge); - -YG_EXPORT void YGNodeStyleSetBorder(YGNodeRef node, YGEdge edge, float border); -YG_EXPORT float YGNodeStyleGetBorder(YGNodeConstRef node, YGEdge edge); - -YG_EXPORT void -YGNodeStyleSetGap(YGNodeRef node, YGGutter gutter, float gapLength); -YG_EXPORT float YGNodeStyleGetGap(YGNodeConstRef node, YGGutter gutter); - -YG_EXPORT void YGNodeStyleSetWidth(YGNodeRef node, float width); -YG_EXPORT void YGNodeStyleSetWidthPercent(YGNodeRef node, float width); -YG_EXPORT void YGNodeStyleSetWidthAuto(YGNodeRef node); -YG_EXPORT YGValue YGNodeStyleGetWidth(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetHeight(YGNodeRef node, float height); -YG_EXPORT void YGNodeStyleSetHeightPercent(YGNodeRef node, float height); -YG_EXPORT void YGNodeStyleSetHeightAuto(YGNodeRef node); -YG_EXPORT YGValue YGNodeStyleGetHeight(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetMinWidth(YGNodeRef node, float minWidth); -YG_EXPORT void YGNodeStyleSetMinWidthPercent(YGNodeRef node, float minWidth); -YG_EXPORT YGValue YGNodeStyleGetMinWidth(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetMinHeight(YGNodeRef node, float minHeight); -YG_EXPORT void YGNodeStyleSetMinHeightPercent(YGNodeRef node, float minHeight); -YG_EXPORT YGValue YGNodeStyleGetMinHeight(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetMaxWidth(YGNodeRef node, float maxWidth); -YG_EXPORT void YGNodeStyleSetMaxWidthPercent(YGNodeRef node, float maxWidth); -YG_EXPORT YGValue YGNodeStyleGetMaxWidth(YGNodeConstRef node); - -YG_EXPORT void YGNodeStyleSetMaxHeight(YGNodeRef node, float maxHeight); -YG_EXPORT void YGNodeStyleSetMaxHeightPercent(YGNodeRef node, float maxHeight); -YG_EXPORT YGValue YGNodeStyleGetMaxHeight(YGNodeConstRef node); - -// Yoga specific properties, not compatible with flexbox specification Aspect -// ratio control the size of the undefined dimension of a node. Aspect ratio is -// encoded as a floating point value width/height. e.g. A value of 2 leads to a -// node with a width twice the size of its height while a value of 0.5 gives the -// opposite effect. -// -// - On a node with a set width/height aspect ratio control the size of the -// unset dimension -// - On a node with a set flex basis aspect ratio controls the size of the node -// in the cross axis if unset -// - On a node with a measure function aspect ratio works as though the measure -// function measures the flex basis -// - On a node with flex grow/shrink aspect ratio controls the size of the node -// in the cross axis if unset -// - Aspect ratio takes min/max dimensions into account -YG_EXPORT void YGNodeStyleSetAspectRatio(YGNodeRef node, float aspectRatio); -YG_EXPORT float YGNodeStyleGetAspectRatio(YGNodeConstRef node); - -YG_EXPORT float YGNodeLayoutGetLeft(YGNodeConstRef node); -YG_EXPORT float YGNodeLayoutGetTop(YGNodeConstRef node); -YG_EXPORT float YGNodeLayoutGetRight(YGNodeConstRef node); -YG_EXPORT float YGNodeLayoutGetBottom(YGNodeConstRef node); -YG_EXPORT float YGNodeLayoutGetWidth(YGNodeConstRef node); -YG_EXPORT float YGNodeLayoutGetHeight(YGNodeConstRef node); -YG_EXPORT YGDirection YGNodeLayoutGetDirection(YGNodeConstRef node); -YG_EXPORT bool YGNodeLayoutGetHadOverflow(YGNodeConstRef node); - -// Get the computed values for these nodes after performing layout. If they were -// set using point values then the returned value will be the same as -// YGNodeStyleGetXXX. However if they were set using a percentage value then the -// returned value is the computed value used during layout. -YG_EXPORT float YGNodeLayoutGetMargin(YGNodeConstRef node, YGEdge edge); -YG_EXPORT float YGNodeLayoutGetBorder(YGNodeConstRef node, YGEdge edge); -YG_EXPORT float YGNodeLayoutGetPadding(YGNodeConstRef node, YGEdge edge); - -YG_EXPORT void YGConfigSetLogger(YGConfigRef config, YGLogger logger); -// Set this to number of pixels in 1 point to round calculation results If you -// want to avoid rounding - set PointScaleFactor to 0 -YG_EXPORT void YGConfigSetPointScaleFactor( - YGConfigRef config, - float pixelsInPoint); -YG_EXPORT float YGConfigGetPointScaleFactor(YGConfigConstRef config); - -// YGConfig -YG_EXPORT YGConfigRef YGConfigNew(void); -YG_EXPORT void YGConfigFree(YGConfigRef config); - -YG_EXPORT void YGConfigSetExperimentalFeatureEnabled( - YGConfigRef config, - YGExperimentalFeature feature, - bool enabled); -YG_EXPORT bool YGConfigIsExperimentalFeatureEnabled( - YGConfigConstRef config, - YGExperimentalFeature feature); - -// Using the web defaults is the preferred configuration for new projects. Usage -// of non web defaults should be considered as legacy. -YG_EXPORT void YGConfigSetUseWebDefaults(YGConfigRef config, bool enabled); -YG_EXPORT bool YGConfigGetUseWebDefaults(YGConfigConstRef config); - -YG_EXPORT void YGConfigSetCloneNodeFunc( - YGConfigRef config, - YGCloneNodeFunc callback); - -YG_EXPORT YGConfigConstRef YGConfigGetDefault(void); - -YG_EXPORT void YGConfigSetContext(YGConfigRef config, void* context); -YG_EXPORT void* YGConfigGetContext(YGConfigConstRef config); - -YG_EXPORT void YGConfigSetErrata(YGConfigRef config, YGErrata errata); -YG_EXPORT YGErrata YGConfigGetErrata(YGConfigConstRef config); - -YG_EXPORT float YGRoundValueToPixelGrid( - double value, - double pointScaleFactor, - bool forceCeil, - bool forceFloor); - -YG_EXTERN_C_END diff --git a/yoga/module.modulemap b/yoga/module.modulemap index 91c6db2934..5a8aad8ff2 100644 --- a/yoga/module.modulemap +++ b/yoga/module.modulemap @@ -7,8 +7,13 @@ module yoga [system] { module core { + header "YGConfig.h" header "YGEnums.h" header "YGMacros.h" + header "YGNode.h" + header "YGNodeLayout.h" + header "YGNodeStye.h" + header "YGPixelGrid.h" header "YGValue.h" header "Yoga.h" export *