C++ Cleanup 2/N: Reorganize YGConfig (#39218)

Summary:
Pull Request resolved: https://github.com/facebook/react-native/pull/39218

Pull Request resolved: https://github.com/facebook/react-native/pull/39169

X-link: https://github.com/facebook/yoga/pull/1348

## This diff

This diff adds a top level `config` directory for code related to configuring Yoga and Yoga Nodes.

The public API for config handles is `YGConfigRef`, which is forward declared to be a pointer to a struct named `YGConfig`. The existing `YGConfig` is split into `yoga::Config`, as the private C++ implementation, inheriting from `YGConfig`, a marker type represented as an empty struct. The public API continues to accept `YGConfigRef`, which continues to be `YGConfig *`, but it must be cast to its concrete internal representation at the API boundary before doing work on it.

## This stack

The organization of the C++ internals of Yoga are in need of attention.
1. Some of the C++ internals are namespaced, but others not.
2. Some of the namespaces include `detail`, but are meant to be used outside of the translation unit (FB Clang Tidy rules warn on any usage of these)
2. Most of the files are in a flat hierarchy, except for event tracing in its own folder
3. Some files and functions begin with YG, others don’t
4. Some functions are uppercase, others are not
5. Almost all of the interesting logic is in Yoga.cpp, and the file is too large to reason about
6. There are multiple grab bag files where folks put random functions they need in (Utils, BitUtils, Yoga-Internal.h)
7. There is no clear indication from file structure or type naming what is private vs not
8. Handles like `YGNodeRef` and `YGConfigRef` can be used to access internals just by importing headers

This stack does some much needed spring cleaning:
1. All non-public headers and C++ implementation details are in separate folders from the root level `yoga`. This will give us room to split up logic and add more files without too large a flat hierarchy
3. All private C++ internals are under the `facebook::yoga` namespace. Details namespaces are only ever used within the same header, as they are intended
4. Utils files are split
5. Most C++ internals drop the YG prefix
6. Most C++ internal function names are all lower camel case
7. We start to split up Yoga.cpp
8. Every header beginning with YG or at the top-level directory is public and C only, with the exception of Yoga-Internal.h which has non-public functions for bindings
9. It is not possible to use private APIs without static casting handles to internal classes

This will give us more leeway to continue splitting monolithic files, and consistent guidelines for style in new files as well.

These changes should not be breaking to any project using only public Yoga headers. This includes every usage of Yoga in fbsource except for RN Fabric which is currently tied to internals. This refactor should make that boundary clearer.

Changelog: [Internal]

Reviewed By: shwanton

Differential Revision: D48847257

fbshipit-source-id: 7a2157d169ba80a6f79620693ae45bb10dfca5a3
This commit is contained in:
Nick Gerleman 2023-08-30 16:27:32 -07:00 коммит произвёл Facebook GitHub Bot
Родитель 294a50db93
Коммит a659065840
11 изменённых файлов: 123 добавлений и 110 удалений

Просмотреть файл

@ -19,6 +19,8 @@
// API and use that // API and use that
#include <yoga/YGNode.h> #include <yoga/YGNode.h>
using namespace facebook;
using namespace facebook::yoga;
using namespace facebook::yoga::vanillajni; using namespace facebook::yoga::vanillajni;
static inline ScopedLocalRef<jobject> YGNodeJobject( static inline ScopedLocalRef<jobject> YGNodeJobject(
@ -194,7 +196,7 @@ static void jni_YGConfigSetLoggerJNI(
} }
*context = newGlobalRef(env, logger); *context = newGlobalRef(env, logger);
config->setLogger(YGJNILogFunc); static_cast<yoga::Config*>(config)->setLogger(YGJNILogFunc);
} else { } else {
if (context != nullptr) { if (context != nullptr) {
delete context; delete context;

Просмотреть файл

@ -473,7 +473,7 @@ void YogaLayoutableShadowNode::configureYogaTree(
const auto &child = *yogaLayoutableChildren_[i]; const auto &child = *yogaLayoutableChildren_[i];
auto childLayoutMetrics = child.getLayoutMetrics(); auto childLayoutMetrics = child.getLayoutMetrics();
auto childErrata = auto childErrata =
YGConfigGetErrata(const_cast<YGConfigRef>(&child.yogaConfig_)); YGConfigGetErrata(const_cast<yoga::Config *>(&child.yogaConfig_));
if (child.yogaTreeHasBeenConfigured_ && if (child.yogaTreeHasBeenConfigured_ &&
childLayoutMetrics.pointScaleFactor == pointScaleFactor && childLayoutMetrics.pointScaleFactor == pointScaleFactor &&
@ -834,8 +834,8 @@ YogaLayoutableShadowNode &YogaLayoutableShadowNode::shadowNodeFromContext(
*static_cast<ShadowNode *>(yogaNode->getContext())); *static_cast<ShadowNode *>(yogaNode->getContext()));
} }
YGConfig &YogaLayoutableShadowNode::initializeYogaConfig( yoga::Config &YogaLayoutableShadowNode::initializeYogaConfig(
YGConfig &config, yoga::Config &config,
const YGConfigRef previousConfig) { const YGConfigRef previousConfig) {
YGConfigSetCloneNodeFunc( YGConfigSetCloneNodeFunc(
&config, YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector); &config, YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector);

Просмотреть файл

@ -93,7 +93,7 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
/* /*
* Yoga config associated (only) with this particular node. * Yoga config associated (only) with this particular node.
*/ */
YGConfig yogaConfig_; yoga::Config yogaConfig_;
/* /*
* All Yoga functions only accept non-const arguments, so we have to mark * All Yoga functions only accept non-const arguments, so we have to mark
@ -153,8 +153,8 @@ class YogaLayoutableShadowNode : public LayoutableShadowNode {
*/ */
YogaLayoutableShadowNode &cloneChildInPlace(int32_t layoutableChildIndex); YogaLayoutableShadowNode &cloneChildInPlace(int32_t layoutableChildIndex);
static YGConfig &initializeYogaConfig( static yoga::Config &initializeYogaConfig(
YGConfig &config, yoga::Config &config,
YGConfigRef previousConfig = nullptr); YGConfigRef previousConfig = nullptr);
static YGNode *yogaNodeCloneCallbackConnector( static YGNode *yogaNodeCloneCallbackConnector(
YGNode *oldYogaNode, YGNode *oldYogaNode,

Просмотреть файл

@ -14,7 +14,7 @@ using namespace facebook;
using namespace facebook::yoga; using namespace facebook::yoga;
using facebook::yoga::CompactValue; using facebook::yoga::CompactValue;
YGNode::YGNode(const YGConfigRef config) : config_{config} { YGNode::YGNode(yoga::Config* config) : config_{config} {
YGAssert( YGAssert(
config != nullptr, "Attempting to construct YGNode with null config"); config != nullptr, "Attempting to construct YGNode with null config");
@ -264,7 +264,7 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) {
children_.insert(children_.begin() + index, child); children_.insert(children_.begin() + index, child);
} }
void YGNode::setConfig(YGConfigRef config) { void YGNode::setConfig(yoga::Config* config) {
YGAssert(config != nullptr, "Attempting to set a null config on a YGNode"); YGAssert(config != nullptr, "Attempting to set a null config on a YGNode");
YGAssertWithConfig( YGAssertWithConfig(
config, config,

Просмотреть файл

@ -9,15 +9,13 @@
#include <cstdint> #include <cstdint>
#include <stdio.h> #include <stdio.h>
#include "YGConfig.h" #include <yoga/config/Config.h>
#include "YGLayout.h" #include "YGLayout.h"
#include <yoga/Yoga-internal.h> #include <yoga/Yoga-internal.h>
#include <yoga/style/CompactValue.h> #include <yoga/style/CompactValue.h>
#include <yoga/style/Style.h> #include <yoga/style/Style.h>
YGConfigRef YGConfigGetDefault();
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
struct YGNodeFlags { struct YGNodeFlags {
@ -58,7 +56,7 @@ private:
uint32_t lineIndex_ = 0; uint32_t lineIndex_ = 0;
YGNodeRef owner_ = nullptr; YGNodeRef owner_ = nullptr;
YGVector children_ = {}; YGVector children_ = {};
YGConfigRef config_; facebook::yoga::Config* config_;
std::array<YGValue, 2> resolvedDimensions_ = { std::array<YGValue, 2> resolvedDimensions_ = {
{YGValueUndefined, YGValueUndefined}}; {YGValueUndefined, YGValueUndefined}};
@ -84,8 +82,11 @@ private:
using CompactValue = facebook::yoga::CompactValue; using CompactValue = facebook::yoga::CompactValue;
public: public:
YGNode() : YGNode{YGConfigGetDefault()} { flags_.hasNewLayout = true; } YGNode()
explicit YGNode(const YGConfigRef config); : YGNode{static_cast<facebook::yoga::Config*>(YGConfigGetDefault())} {
flags_.hasNewLayout = true;
}
explicit YGNode(facebook::yoga::Config* config);
~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree
YGNode(YGNode&&); YGNode(YGNode&&);
@ -166,7 +167,7 @@ public:
YGNodeRef getChild(uint32_t index) const { return children_.at(index); } YGNodeRef getChild(uint32_t index) const { return children_.at(index); }
YGConfigRef getConfig() const { return config_; } facebook::yoga::Config* getConfig() const { return config_; }
bool isDirty() const { return flags_.isDirty; } bool isDirty() const { return flags_.isDirty; }
@ -290,7 +291,7 @@ public:
// TODO: rvalue override for setChildren // TODO: rvalue override for setChildren
void setConfig(YGConfigRef config); void setConfig(facebook::yoga::Config* config);
void setDirty(bool isDirty); void setDirty(bool isDirty);
void setLayoutLastOwnerDirection(YGDirection direction); void setLayoutLastOwnerDirection(YGDirection direction);

Просмотреть файл

@ -20,6 +20,7 @@
#include <yoga/Yoga-internal.h> #include <yoga/Yoga-internal.h>
#include "event/event.h" #include "event/event.h"
using namespace facebook;
using namespace facebook::yoga; using namespace facebook::yoga;
using detail::Log; using detail::Log;
@ -119,7 +120,7 @@ YOGA_EXPORT YGConfigRef YGNodeGetConfig(YGNodeRef node) {
} }
YOGA_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config) { YOGA_EXPORT void YGNodeSetConfig(YGNodeRef node, YGConfigRef config) {
node->setConfig(config); node->setConfig(static_cast<yoga::Config*>(config));
} }
YOGA_EXPORT bool YGNodeHasMeasureFunc(YGNodeRef node) { YOGA_EXPORT bool YGNodeHasMeasureFunc(YGNodeRef node) {
@ -161,7 +162,7 @@ YOGA_EXPORT bool YGNodeGetHasNewLayout(YGNodeRef node) {
} }
YOGA_EXPORT void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) { YOGA_EXPORT void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled) {
config->setShouldPrintTree(enabled); static_cast<yoga::Config*>(config)->setShouldPrintTree(enabled);
} }
YOGA_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) { YOGA_EXPORT void YGNodeSetHasNewLayout(YGNodeRef node, bool hasNewLayout) {
@ -188,7 +189,7 @@ YOGA_EXPORT void YGNodeMarkDirtyAndPropagateToDescendants(
int32_t gConfigInstanceCount = 0; int32_t gConfigInstanceCount = 0;
YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) { YOGA_EXPORT WIN_EXPORT YGNodeRef YGNodeNewWithConfig(const YGConfigRef config) {
const YGNodeRef node = new YGNode{config}; const YGNodeRef node = new YGNode{static_cast<yoga::Config*>(config)};
YGAssert(config != nullptr, "Tried to construct YGNode with null config"); YGAssert(config != nullptr, "Tried to construct YGNode with null config");
YGAssertWithConfig( YGAssertWithConfig(
config, node != nullptr, "Could not allocate memory for node"); config, node != nullptr, "Could not allocate memory for node");
@ -272,23 +273,19 @@ YOGA_EXPORT int32_t YGConfigGetInstanceCount(void) {
YOGA_EXPORT YGConfigRef YGConfigNew(void) { YOGA_EXPORT YGConfigRef YGConfigNew(void) {
#ifdef ANDROID #ifdef ANDROID
const YGConfigRef config = new YGConfig(YGAndroidLog); const YGConfigRef config = new yoga::Config(YGAndroidLog);
#else #else
const YGConfigRef config = new YGConfig(YGDefaultLog); const YGConfigRef config = new yoga::Config(YGDefaultLog);
#endif #endif
gConfigInstanceCount++; gConfigInstanceCount++;
return config; return config;
} }
YOGA_EXPORT void YGConfigFree(const YGConfigRef config) { YOGA_EXPORT void YGConfigFree(const YGConfigRef config) {
delete config; delete static_cast<yoga::Config*>(config);
gConfigInstanceCount--; gConfigInstanceCount--;
} }
void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) {
memcpy(dest, src, sizeof(YGConfig));
}
YOGA_EXPORT void YGNodeSetIsReferenceBaseline( YOGA_EXPORT void YGNodeSetIsReferenceBaseline(
YGNodeRef node, YGNodeRef node,
bool isReferenceBaseline) { bool isReferenceBaseline) {
@ -3715,22 +3712,22 @@ YOGA_EXPORT bool YGNodeCanUseCachedMeasurement(
return false; return false;
} }
bool useRoundedComparison = bool useRoundedComparison =
config != nullptr && config->getPointScaleFactor() != 0; config != nullptr && YGConfigGetPointScaleFactor(config) != 0;
const float effectiveWidth = useRoundedComparison const float effectiveWidth = useRoundedComparison
? YGRoundValueToPixelGrid( ? YGRoundValueToPixelGrid(
width, config->getPointScaleFactor(), false, false) width, YGConfigGetPointScaleFactor(config), false, false)
: width; : width;
const float effectiveHeight = useRoundedComparison const float effectiveHeight = useRoundedComparison
? YGRoundValueToPixelGrid( ? YGRoundValueToPixelGrid(
height, config->getPointScaleFactor(), false, false) height, YGConfigGetPointScaleFactor(config), false, false)
: height; : height;
const float effectiveLastWidth = useRoundedComparison const float effectiveLastWidth = useRoundedComparison
? YGRoundValueToPixelGrid( ? YGRoundValueToPixelGrid(
lastWidth, config->getPointScaleFactor(), false, false) lastWidth, YGConfigGetPointScaleFactor(config), false, false)
: lastWidth; : lastWidth;
const float effectiveLastHeight = useRoundedComparison const float effectiveLastHeight = useRoundedComparison
? YGRoundValueToPixelGrid( ? YGRoundValueToPixelGrid(
lastHeight, config->getPointScaleFactor(), false, false) lastHeight, YGConfigGetPointScaleFactor(config), false, false)
: lastHeight; : lastHeight;
const bool hasSameWidthSpec = lastWidthMode == widthMode && const bool hasSameWidthSpec = lastWidthMode == widthMode &&
@ -4057,14 +4054,14 @@ YOGA_EXPORT void YGConfigSetPointScaleFactor(
// We store points for Pixel as we will use it for rounding // We store points for Pixel as we will use it for rounding
if (pixelsInPoint == 0.0f) { if (pixelsInPoint == 0.0f) {
// Zero is used to skip rounding // Zero is used to skip rounding
config->setPointScaleFactor(0.0f); static_cast<yoga::Config*>(config)->setPointScaleFactor(0.0f);
} else { } else {
config->setPointScaleFactor(pixelsInPoint); static_cast<yoga::Config*>(config)->setPointScaleFactor(pixelsInPoint);
} }
} }
YOGA_EXPORT float YGConfigGetPointScaleFactor(const YGConfigRef config) { YOGA_EXPORT float YGConfigGetPointScaleFactor(const YGConfigRef config) {
return config->getPointScaleFactor(); return static_cast<yoga::Config*>(config)->getPointScaleFactor();
} }
static void YGRoundToPixelGrid( static void YGRoundToPixelGrid(
@ -4239,12 +4236,12 @@ YOGA_EXPORT void YGNodeCalculateLayout(
YOGA_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) { YOGA_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger) {
if (logger != nullptr) { if (logger != nullptr) {
config->setLogger(logger); static_cast<yoga::Config*>(config)->setLogger(logger);
} else { } else {
#ifdef ANDROID #ifdef ANDROID
config->setLogger(&YGAndroidLog); static_cast<yoga::Config*>(config)->setLogger(&YGAndroidLog);
#else #else
config->setLogger(&YGDefaultLog); static_cast<yoga::Config*>(config)->setLogger(&YGDefaultLog);
#endif #endif
} }
} }
@ -4271,7 +4268,12 @@ void YGAssertWithConfig(
const bool condition, const bool condition,
const char* message) { const char* message) {
if (!condition) { if (!condition) {
Log::log(config, YGLogLevelFatal, nullptr, "%s\n", message); Log::log(
static_cast<yoga::Config*>(config),
YGLogLevelFatal,
nullptr,
"%s\n",
message);
throwLogicalErrorWithMessage(message); throwLogicalErrorWithMessage(message);
} }
} }
@ -4280,58 +4282,61 @@ YOGA_EXPORT void YGConfigSetExperimentalFeatureEnabled(
const YGConfigRef config, const YGConfigRef config,
const YGExperimentalFeature feature, const YGExperimentalFeature feature,
const bool enabled) { const bool enabled) {
config->setExperimentalFeatureEnabled(feature, enabled); static_cast<yoga::Config*>(config)->setExperimentalFeatureEnabled(
feature, enabled);
} }
YOGA_EXPORT bool YGConfigIsExperimentalFeatureEnabled( YOGA_EXPORT bool YGConfigIsExperimentalFeatureEnabled(
const YGConfigRef config, const YGConfigRef config,
const YGExperimentalFeature feature) { const YGExperimentalFeature feature) {
return config->isExperimentalFeatureEnabled(feature); return static_cast<yoga::Config*>(config)->isExperimentalFeatureEnabled(
feature);
} }
YOGA_EXPORT void YGConfigSetUseWebDefaults( YOGA_EXPORT void YGConfigSetUseWebDefaults(
const YGConfigRef config, const YGConfigRef config,
const bool enabled) { const bool enabled) {
config->setUseWebDefaults(enabled); static_cast<yoga::Config*>(config)->setUseWebDefaults(enabled);
} }
YOGA_EXPORT bool YGConfigGetUseLegacyStretchBehaviour( YOGA_EXPORT bool YGConfigGetUseLegacyStretchBehaviour(
const YGConfigRef config) { const YGConfigRef config) {
return config->hasErrata(YGErrataStretchFlexBasis); return static_cast<yoga::Config*>(config)->hasErrata(
YGErrataStretchFlexBasis);
} }
YOGA_EXPORT void YGConfigSetUseLegacyStretchBehaviour( YOGA_EXPORT void YGConfigSetUseLegacyStretchBehaviour(
const YGConfigRef config, const YGConfigRef config,
const bool useLegacyStretchBehaviour) { const bool useLegacyStretchBehaviour) {
if (useLegacyStretchBehaviour) { if (useLegacyStretchBehaviour) {
config->addErrata(YGErrataStretchFlexBasis); static_cast<yoga::Config*>(config)->addErrata(YGErrataStretchFlexBasis);
} else { } else {
config->removeErrata(YGErrataStretchFlexBasis); static_cast<yoga::Config*>(config)->removeErrata(YGErrataStretchFlexBasis);
} }
} }
bool YGConfigGetUseWebDefaults(const YGConfigRef config) { bool YGConfigGetUseWebDefaults(const YGConfigRef config) {
return config->useWebDefaults(); return static_cast<yoga::Config*>(config)->useWebDefaults();
} }
YOGA_EXPORT void YGConfigSetContext(const YGConfigRef config, void* context) { YOGA_EXPORT void YGConfigSetContext(const YGConfigRef config, void* context) {
config->setContext(context); static_cast<yoga::Config*>(config)->setContext(context);
} }
YOGA_EXPORT void* YGConfigGetContext(const YGConfigRef config) { YOGA_EXPORT void* YGConfigGetContext(const YGConfigRef config) {
return config->getContext(); return static_cast<yoga::Config*>(config)->getContext();
} }
YOGA_EXPORT void YGConfigSetErrata(YGConfigRef config, YGErrata errata) { YOGA_EXPORT void YGConfigSetErrata(YGConfigRef config, YGErrata errata) {
config->setErrata(errata); static_cast<yoga::Config*>(config)->setErrata(errata);
} }
YOGA_EXPORT YGErrata YGConfigGetErrata(YGConfigRef config) { YOGA_EXPORT YGErrata YGConfigGetErrata(YGConfigRef config) {
return config->getErrata(); return static_cast<yoga::Config*>(config)->getErrata();
} }
YOGA_EXPORT void YGConfigSetCloneNodeFunc( YOGA_EXPORT void YGConfigSetCloneNodeFunc(
const YGConfigRef config, const YGConfigRef config,
const YGCloneNodeFunc callback) { const YGCloneNodeFunc callback) {
config->setCloneNodeCallback(callback); static_cast<yoga::Config*>(config)->setCloneNodeCallback(callback);
} }

Просмотреть файл

@ -343,7 +343,6 @@ void YGConfigSetUseLegacyStretchBehaviour(
// YGConfig // YGConfig
WIN_EXPORT YGConfigRef YGConfigNew(void); WIN_EXPORT YGConfigRef YGConfigNew(void);
WIN_EXPORT void YGConfigFree(YGConfigRef config); WIN_EXPORT void YGConfigFree(YGConfigRef config);
WIN_EXPORT void YGConfigCopy(YGConfigRef dest, YGConfigRef src);
WIN_EXPORT int32_t YGConfigGetInstanceCount(void); WIN_EXPORT int32_t YGConfigGetInstanceCount(void);
WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled( WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(

Просмотреть файл

@ -5,133 +5,129 @@
* LICENSE file in the root directory of this source tree. * LICENSE file in the root directory of this source tree.
*/ */
#include "YGConfig.h" #include <yoga/config/Config.h>
using namespace facebook::yoga;
namespace facebook::yoga { namespace facebook::yoga {
bool configUpdateInvalidatesLayout(YGConfigRef a, YGConfigRef b) {
bool configUpdateInvalidatesLayout(Config* a, Config* b) {
return a->getErrata() != b->getErrata() || return a->getErrata() != b->getErrata() ||
a->getEnabledExperiments() != b->getEnabledExperiments() || a->getEnabledExperiments() != b->getEnabledExperiments() ||
a->getPointScaleFactor() != b->getPointScaleFactor() || a->getPointScaleFactor() != b->getPointScaleFactor() ||
a->useWebDefaults() != b->useWebDefaults(); a->useWebDefaults() != b->useWebDefaults();
} }
} // namespace facebook::yoga
YGConfig::YGConfig(YGLogger logger) : cloneNodeCallback_{nullptr} { Config::Config(YGLogger logger) : cloneNodeCallback_{nullptr} {
setLogger(logger); setLogger(logger);
} }
void YGConfig::setUseWebDefaults(bool useWebDefaults) { void Config::setUseWebDefaults(bool useWebDefaults) {
flags_.useWebDefaults = useWebDefaults; flags_.useWebDefaults = useWebDefaults;
} }
bool YGConfig::useWebDefaults() const { bool Config::useWebDefaults() const {
return flags_.useWebDefaults; return flags_.useWebDefaults;
} }
void YGConfig::setShouldPrintTree(bool printTree) { void Config::setShouldPrintTree(bool printTree) {
flags_.printTree = printTree; flags_.printTree = printTree;
} }
bool YGConfig::shouldPrintTree() const { bool Config::shouldPrintTree() const {
return flags_.printTree; return flags_.printTree;
} }
void YGConfig::setExperimentalFeatureEnabled( void Config::setExperimentalFeatureEnabled(
YGExperimentalFeature feature, YGExperimentalFeature feature,
bool enabled) { bool enabled) {
experimentalFeatures_.set(feature, enabled); experimentalFeatures_.set(feature, enabled);
} }
bool YGConfig::isExperimentalFeatureEnabled( bool Config::isExperimentalFeatureEnabled(YGExperimentalFeature feature) const {
YGExperimentalFeature feature) const {
return experimentalFeatures_.test(feature); return experimentalFeatures_.test(feature);
} }
ExperimentalFeatureSet YGConfig::getEnabledExperiments() const { ExperimentalFeatureSet Config::getEnabledExperiments() const {
return experimentalFeatures_; return experimentalFeatures_;
} }
void YGConfig::setErrata(YGErrata errata) { void Config::setErrata(YGErrata errata) {
errata_ = errata; errata_ = errata;
} }
void YGConfig::addErrata(YGErrata errata) { void Config::addErrata(YGErrata errata) {
errata_ |= errata; errata_ |= errata;
} }
void YGConfig::removeErrata(YGErrata errata) { void Config::removeErrata(YGErrata errata) {
errata_ &= (~errata); errata_ &= (~errata);
} }
YGErrata YGConfig::getErrata() const { YGErrata Config::getErrata() const {
return errata_; return errata_;
} }
bool YGConfig::hasErrata(YGErrata errata) const { bool Config::hasErrata(YGErrata errata) const {
return (errata_ & errata) != YGErrataNone; return (errata_ & errata) != YGErrataNone;
} }
void YGConfig::setPointScaleFactor(float pointScaleFactor) { void Config::setPointScaleFactor(float pointScaleFactor) {
pointScaleFactor_ = pointScaleFactor; pointScaleFactor_ = pointScaleFactor;
} }
float YGConfig::getPointScaleFactor() const { float Config::getPointScaleFactor() const {
return pointScaleFactor_; return pointScaleFactor_;
} }
void YGConfig::setContext(void* context) { void Config::setContext(void* context) {
context_ = context; context_ = context;
} }
void* YGConfig::getContext() const { void* Config::getContext() const {
return context_; return context_;
} }
void YGConfig::setLogger(YGLogger logger) { void Config::setLogger(YGLogger logger) {
logger_.noContext = logger; logger_.noContext = logger;
flags_.loggerUsesContext = false; flags_.loggerUsesContext = false;
} }
void YGConfig::setLogger(LogWithContextFn logger) { void Config::setLogger(LogWithContextFn logger) {
logger_.withContext = logger; logger_.withContext = logger;
flags_.loggerUsesContext = true; flags_.loggerUsesContext = true;
} }
void YGConfig::setLogger(std::nullptr_t) { void Config::setLogger(std::nullptr_t) {
setLogger(YGLogger{nullptr}); setLogger(YGLogger{nullptr});
} }
void YGConfig::log( void Config::log(
YGConfig* config, YGNodeRef node,
YGNode* node,
YGLogLevel logLevel, YGLogLevel logLevel,
void* logContext, void* logContext,
const char* format, const char* format,
va_list args) const { va_list args) {
if (flags_.loggerUsesContext) { if (flags_.loggerUsesContext) {
logger_.withContext(config, node, logLevel, logContext, format, args); logger_.withContext(this, node, logLevel, logContext, format, args);
} else { } else {
logger_.noContext(config, node, logLevel, format, args); logger_.noContext(this, node, logLevel, format, args);
} }
} }
void YGConfig::setCloneNodeCallback(YGCloneNodeFunc cloneNode) { void Config::setCloneNodeCallback(YGCloneNodeFunc cloneNode) {
cloneNodeCallback_.noContext = cloneNode; cloneNodeCallback_.noContext = cloneNode;
flags_.cloneNodeUsesContext = false; flags_.cloneNodeUsesContext = false;
} }
void YGConfig::setCloneNodeCallback(CloneWithContextFn cloneNode) { void Config::setCloneNodeCallback(CloneWithContextFn cloneNode) {
cloneNodeCallback_.withContext = cloneNode; cloneNodeCallback_.withContext = cloneNode;
flags_.cloneNodeUsesContext = true; flags_.cloneNodeUsesContext = true;
} }
void YGConfig::setCloneNodeCallback(std::nullptr_t) { void Config::setCloneNodeCallback(std::nullptr_t) {
setCloneNodeCallback(YGCloneNodeFunc{nullptr}); setCloneNodeCallback(YGCloneNodeFunc{nullptr});
} }
YGNodeRef YGConfig::cloneNode( YGNodeRef Config::cloneNode(
YGNodeRef node, YGNodeRef node,
YGNodeRef owner, YGNodeRef owner,
int childIndex, int childIndex,
@ -147,3 +143,5 @@ YGNodeRef YGConfig::cloneNode(
} }
return clone; return clone;
} }
} // namespace facebook::yoga

Просмотреть файл

@ -12,11 +12,16 @@
#include <yoga/BitUtils.h> #include <yoga/BitUtils.h>
#include <yoga/Yoga-internal.h> #include <yoga/Yoga-internal.h>
// Tag struct used to form the opaque YGConfigRef for the public C API
struct YGConfig {};
namespace facebook::yoga { namespace facebook::yoga {
class Config;
// Whether moving a node from config "a" to config "b" should dirty previously // Whether moving a node from config "a" to config "b" should dirty previously
// calculated layout results. // calculated layout results.
bool configUpdateInvalidatesLayout(YGConfigRef a, YGConfigRef b); bool configUpdateInvalidatesLayout(Config* a, Config* b);
// Internal variants of log functions, currently used only by JNI bindings. // Internal variants of log functions, currently used only by JNI bindings.
// TODO: Reconcile this with the public API // TODO: Reconcile this with the public API
@ -33,13 +38,12 @@ using CloneWithContextFn = YGNodeRef (*)(
int childIndex, int childIndex,
void* cloneContext); void* cloneContext);
using ExperimentalFeatureSet = using ExperimentalFeatureSet = detail::EnumBitset<YGExperimentalFeature>;
facebook::yoga::detail::EnumBitset<YGExperimentalFeature>;
#pragma pack(push) #pragma pack(push)
#pragma pack(1) #pragma pack(1)
// Packed structure of <32-bit options to miminize size per node. // Packed structure of <32-bit options to miminize size per node.
struct YGConfigFlags { struct ConfigFlags {
bool useWebDefaults : 1; bool useWebDefaults : 1;
bool printTree : 1; bool printTree : 1;
bool cloneNodeUsesContext : 1; bool cloneNodeUsesContext : 1;
@ -47,10 +51,9 @@ struct YGConfigFlags {
}; };
#pragma pack(pop) #pragma pack(pop)
} // namespace facebook::yoga class YOGA_EXPORT Config : public ::YGConfig {
public:
struct YOGA_EXPORT YGConfig { Config(YGLogger logger);
YGConfig(YGLogger logger);
void setUseWebDefaults(bool useWebDefaults); void setUseWebDefaults(bool useWebDefaults);
bool useWebDefaults() const; bool useWebDefaults() const;
@ -62,7 +65,7 @@ struct YOGA_EXPORT YGConfig {
YGExperimentalFeature feature, YGExperimentalFeature feature,
bool enabled); bool enabled);
bool isExperimentalFeatureEnabled(YGExperimentalFeature feature) const; bool isExperimentalFeatureEnabled(YGExperimentalFeature feature) const;
facebook::yoga::ExperimentalFeatureSet getEnabledExperiments() const; ExperimentalFeatureSet getEnabledExperiments() const;
void setErrata(YGErrata errata); void setErrata(YGErrata errata);
void addErrata(YGErrata errata); void addErrata(YGErrata errata);
@ -77,12 +80,12 @@ struct YOGA_EXPORT YGConfig {
void* getContext() const; void* getContext() const;
void setLogger(YGLogger logger); void setLogger(YGLogger logger);
void setLogger(facebook::yoga::LogWithContextFn logger); void setLogger(LogWithContextFn logger);
void setLogger(std::nullptr_t); void setLogger(std::nullptr_t);
void log(YGConfig*, YGNode*, YGLogLevel, void*, const char*, va_list) const; void log(YGNodeRef, YGLogLevel, void*, const char*, va_list);
void setCloneNodeCallback(YGCloneNodeFunc cloneNode); void setCloneNodeCallback(YGCloneNodeFunc cloneNode);
void setCloneNodeCallback(facebook::yoga::CloneWithContextFn cloneNode); void setCloneNodeCallback(CloneWithContextFn cloneNode);
void setCloneNodeCallback(std::nullptr_t); void setCloneNodeCallback(std::nullptr_t);
YGNodeRef cloneNode( YGNodeRef cloneNode(
YGNodeRef node, YGNodeRef node,
@ -92,17 +95,19 @@ struct YOGA_EXPORT YGConfig {
private: private:
union { union {
facebook::yoga::CloneWithContextFn withContext; CloneWithContextFn withContext;
YGCloneNodeFunc noContext; YGCloneNodeFunc noContext;
} cloneNodeCallback_; } cloneNodeCallback_;
union { union {
facebook::yoga::LogWithContextFn withContext; LogWithContextFn withContext;
YGLogger noContext; YGLogger noContext;
} logger_; } logger_;
facebook::yoga::YGConfigFlags flags_{}; ConfigFlags flags_{};
facebook::yoga::ExperimentalFeatureSet experimentalFeatures_{}; ExperimentalFeatureSet experimentalFeatures_{};
YGErrata errata_ = YGErrataNone; YGErrata errata_ = YGErrataNone;
float pointScaleFactor_ = 1.0f; float pointScaleFactor_ = 1.0f;
void* context_ = nullptr; void* context_ = nullptr;
}; };
} // namespace facebook::yoga

Просмотреть файл

@ -8,7 +8,7 @@
#include <yoga/Yoga.h> #include <yoga/Yoga.h>
#include "log.h" #include "log.h"
#include "YGConfig.h" #include <yoga/config/Config.h>
#include "YGNode.h" #include "YGNode.h"
namespace facebook::yoga::detail { namespace facebook::yoga::detail {
@ -16,14 +16,16 @@ namespace facebook::yoga::detail {
namespace { namespace {
void vlog( void vlog(
YGConfig* config, yoga::Config* config,
YGNode* node, YGNode* node,
YGLogLevel level, YGLogLevel level,
void* context, void* context,
const char* format, const char* format,
va_list args) { va_list args) {
YGConfig* logConfig = config != nullptr ? config : YGConfigGetDefault(); yoga::Config* logConfig = config != nullptr
logConfig->log(logConfig, node, level, context, format, args); ? config
: static_cast<yoga::Config*>(YGConfigGetDefault());
logConfig->log(node, level, context, format, args);
} }
} // namespace } // namespace
@ -46,7 +48,7 @@ YOGA_EXPORT void Log::log(
} }
void Log::log( void Log::log(
YGConfig* config, yoga::Config* config,
YGLogLevel level, YGLogLevel level,
void* context, void* context,
const char* format, const char* format,

Просмотреть файл

@ -8,6 +8,7 @@
#pragma once #pragma once
#include <yoga/YGEnums.h> #include <yoga/YGEnums.h>
#include <yoga/config/Config.h>
struct YGNode; struct YGNode;
struct YGConfig; struct YGConfig;
@ -23,7 +24,7 @@ struct Log {
...) noexcept; ...) noexcept;
static void log( static void log(
YGConfig* config, yoga::Config* config,
YGLogLevel level, YGLogLevel level,
void*, void*,
const char* format, const char* format,