From ede28883262af1b852bb0e72f4231475f9d13f6c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 04:09:39 -0700 Subject: [PATCH 01/29] Lint / reformat `YGJNI.cpp` Summary: Run clangformat on `YGJNI.cpp` @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785660 fbshipit-source-id: 9748a5297e7b55e897de0280a79c2ea6ae1c1298 --- java/jni/YGJNI.cpp | 387 +++++++++++++++++++++++++++------------------ 1 file changed, 230 insertions(+), 157 deletions(-) diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 5649ef7e..1d6f464c 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -33,13 +33,17 @@ struct YGConfigContext { } }; -static inline weak_ref *YGNodeJobject(YGNodeRef node) { +static inline weak_ref* YGNodeJobject(YGNodeRef node) { return reinterpret_cast*>(node->getContext()); } -static void YGTransferLayoutDirection(YGNodeRef node, alias_ref javaNode) { - static auto layoutDirectionField = javaNode->getClass()->getField("mLayoutDirection"); - javaNode->setFieldValue(layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); +static void YGTransferLayoutDirection( + YGNodeRef node, + alias_ref javaNode) { + static auto layoutDirectionField = + javaNode->getClass()->getField("mLayoutDirection"); + javaNode->setFieldValue( + layoutDirectionField, static_cast(YGNodeLayoutGetDirection(node))); } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { @@ -50,23 +54,37 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { static auto leftField = obj->getClass()->getField("mLeft"); static auto topField = obj->getClass()->getField("mTop"); - static auto marginLeftField = obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = obj->getClass()->getField("mMarginTop"); - static auto marginRightField = obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = obj->getClass()->getField("mMarginBottom"); + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = + obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); - static auto paddingLeftField = obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = obj->getClass()->getField("mPaddingBottom"); + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); - static auto borderLeftField = obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = obj->getClass()->getField("mBorderTop"); - static auto borderRightField = obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = obj->getClass()->getField("mBorderBottom"); + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = + obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); - static auto edgeSetFlagField = obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = obj->getClass()->getField("mHasNewLayout"); + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); static auto doesLegacyStretchBehaviour = obj->getClass()->getField( "mDoesLegacyStretchFlagAffectsLayout"); @@ -76,7 +94,7 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { const int PADDING = 2; const int BORDER = 4; - int hasEdgeSetFlag = (int) obj->getFieldValue(edgeSetFlagField); + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); @@ -98,17 +116,25 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { } if ((hasEdgeSetFlag & PADDING) == PADDING) { - obj->setFieldValue(paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); - obj->setFieldValue(paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); - obj->setFieldValue(paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); - obj->setFieldValue(paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); + obj->setFieldValue( + paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); + obj->setFieldValue( + paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); + obj->setFieldValue( + paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); + obj->setFieldValue( + paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); } if ((hasEdgeSetFlag & BORDER) == BORDER) { - obj->setFieldValue(borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); - obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); - obj->setFieldValue(borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); - obj->setFieldValue(borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); + obj->setFieldValue( + borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); + obj->setFieldValue( + borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); + obj->setFieldValue( + borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); + obj->setFieldValue( + borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); } obj->setFieldValue(hasNewLayoutField, true); @@ -119,7 +145,10 @@ static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } else { - YGLog(root, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } } @@ -128,14 +157,18 @@ static void YGPrint(YGNodeRef node) { if (auto obj = YGNodeJobject(node)->lockLocal()) { cout << obj->toString() << endl; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); } } static float YGJNIBaselineFunc(YGNodeRef node, float width, float height) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto baselineFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("baseline"); + static auto baselineFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("baseline"); return baselineFunc(obj, width, height); } else { return height; @@ -150,20 +183,17 @@ static inline YGConfigRef _jlong2YGConfigRef(jlong addr) { return reinterpret_cast(static_cast(addr)); } -static YGNodeRef YGJNIOnNodeClonedFunc( - YGNodeRef oldNode, - YGNodeRef owner, - int childIndex) { +static YGNodeRef +YGJNIOnNodeClonedFunc(YGNodeRef oldNode, YGNodeRef owner, int childIndex) { auto config = oldNode->getConfig(); if (!config) { return nullptr; } - static auto onNodeClonedFunc = findClassStatic("com/facebook/yoga/YogaConfig") - ->getMethod( - local_ref, - local_ref, - jint)>("cloneNode"); + static auto onNodeClonedFunc = + findClassStatic("com/facebook/yoga/YogaConfig") + ->getMethod( + local_ref, local_ref, jint)>("cloneNode"); auto context = reinterpret_cast(YGConfigGetContext(config)); auto javaConfig = context->config; @@ -174,15 +204,12 @@ static YGNodeRef YGJNIOnNodeClonedFunc( YGNodeJobject(owner)->lockLocal(), childIndex); - static auto replaceChild = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod, - jint)>("replaceChild"); + static auto replaceChild = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod, jint)>("replaceChild"); - jlong newNodeNativePointer = replaceChild( - YGNodeJobject(owner)->lockLocal(), - newNode, - childIndex); + jlong newNodeNativePointer = + replaceChild(YGNodeJobject(owner)->lockLocal(), newNode, childIndex); return _jlong2YGNodeRef(newNodeNativePointer); } @@ -194,24 +221,30 @@ static YGSize YGJNIMeasureFunc( float height, YGMeasureMode heightMode) { if (auto obj = YGNodeJobject(node)->lockLocal()) { - static auto measureFunc = findClassStatic("com/facebook/yoga/YogaNode") - ->getMethod("measure"); + static auto measureFunc = + findClassStatic("com/facebook/yoga/YogaNode") + ->getMethod("measure"); YGTransferLayoutDirection(node, obj); - const auto measureResult = measureFunc(obj, width, widthMode, height, heightMode); + const auto measureResult = + measureFunc(obj, width, widthMode, height, heightMode); - static_assert(sizeof(measureResult) == 8, - "Expected measureResult to be 8 bytes, or two 32 bit ints"); + static_assert( + sizeof(measureResult) == 8, + "Expected measureResult to be 8 bytes, or two 32 bit ints"); int32_t wBits = 0xFFFFFFFF & (measureResult >> 32); int32_t hBits = 0xFFFFFFFF & measureResult; - const float *measuredWidth = reinterpret_cast(&wBits); - const float *measuredHeight = reinterpret_cast(&hBits); + const float* measuredWidth = reinterpret_cast(&wBits); + const float* measuredHeight = reinterpret_cast(&hBits); return YGSize{*measuredWidth, *measuredHeight}; } else { - YGLog(node, YGLogLevelError, "Java YGNode was GCed during layout calculation\n"); + YGLog( + node, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); return YGSize{ widthMode == YGMeasureModeUndefined ? 0 : width, heightMode == YGMeasureModeUndefined ? 0 : height, @@ -223,24 +256,28 @@ struct JYogaLogLevel : public JavaClass { static constexpr auto kJavaDescriptor = "Lcom/facebook/yoga/YogaLogLevel;"; }; -static int YGJNILogFunc(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGJNILogFunc( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { int result = vsnprintf(NULL, 0, format, args); std::vector buffer(1 + result); vsnprintf(buffer.data(), buffer.size(), format, args); static auto logFunc = findClassStatic("com/facebook/yoga/YogaLogger") - ->getMethod, local_ref, jstring)>("log"); + ->getMethod, local_ref, jstring)>("log"); static auto logLevelFromInt = - JYogaLogLevel::javaClassStatic()->getStaticMethod("fromInt"); + JYogaLogLevel::javaClassStatic() + ->getStaticMethod("fromInt"); if (auto obj = YGNodeJobject(node)->lockLocal()) { - auto jlogger = reinterpret_cast *>(YGConfigGetContext(config)); + auto jlogger = + reinterpret_cast*>(YGConfigGetContext(config)); logFunc( jlogger->get(), obj, @@ -309,13 +346,19 @@ void jni_YGNodeReset(alias_ref thiz, jlong nativePointer) { void jni_YGNodePrint(alias_ref thiz, jlong nativePointer) { const YGNodeRef node = _jlong2YGNodeRef(nativePointer); - YGNodePrint(node, - (YGPrintOptions)(YGPrintOptionsStyle | YGPrintOptionsLayout | - YGPrintOptionsChildren)); + YGNodePrint( + node, + (YGPrintOptions)( + YGPrintOptionsStyle | YGPrintOptionsLayout | YGPrintOptionsChildren)); } -void jni_YGNodeInsertChild(alias_ref, jlong nativePointer, jlong childPointer, jint index) { - YGNodeInsertChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); +void jni_YGNodeInsertChild( + alias_ref, + jlong nativePointer, + jlong childPointer, + jint index) { + YGNodeInsertChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } void jni_YGNodeInsertSharedChild( @@ -327,19 +370,25 @@ void jni_YGNodeInsertSharedChild( _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer), index); } -void jni_YGNodeRemoveChild(alias_ref, jlong nativePointer, jlong childPointer) { - YGNodeRemoveChild(_jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); +void jni_YGNodeRemoveChild( + alias_ref, + jlong nativePointer, + jlong childPointer) { + YGNodeRemoveChild( + _jlong2YGNodeRef(nativePointer), _jlong2YGNodeRef(childPointer)); } -void jni_YGNodeCalculateLayout(alias_ref, - jlong nativePointer, - jfloat width, - jfloat height) { +void jni_YGNodeCalculateLayout( + alias_ref, + jlong nativePointer, + jfloat width, + jfloat height) { const YGNodeRef root = _jlong2YGNodeRef(nativePointer); - YGNodeCalculateLayout(root, - static_cast(width), - static_cast(height), - YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); + YGNodeCalculateLayout( + root, + static_cast(width), + static_cast(height), + YGNodeStyleGetDirection(_jlong2YGNodeRef(nativePointer))); YGTransferLayoutOutputsRecursive(root); } @@ -357,20 +406,28 @@ jboolean jni_YGNodeIsDirty(alias_ref, jlong nativePointer) { return (jboolean)_jlong2YGNodeRef(nativePointer)->isDirty(); } -void jni_YGNodeSetHasMeasureFunc(alias_ref, jlong nativePointer, jboolean hasMeasureFunc) { +void jni_YGNodeSetHasMeasureFunc( + alias_ref, + jlong nativePointer, + jboolean hasMeasureFunc) { _jlong2YGNodeRef(nativePointer) ->setMeasureFunc(hasMeasureFunc ? YGJNIMeasureFunc : nullptr); } -void jni_YGNodeSetHasBaselineFunc(alias_ref, - jlong nativePointer, - jboolean hasBaselineFunc) { +void jni_YGNodeSetHasBaselineFunc( + alias_ref, + jlong nativePointer, + jboolean hasBaselineFunc) { _jlong2YGNodeRef(nativePointer) ->setBaseLineFunc(hasBaselineFunc ? YGJNIBaselineFunc : nullptr); } -void jni_YGNodeCopyStyle(alias_ref, jlong dstNativePointer, jlong srcNativePointer) { - YGNodeCopyStyle(_jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); +void jni_YGNodeCopyStyle( + alias_ref, + jlong dstNativePointer, + jlong srcNativePointer) { + YGNodeCopyStyle( + _jlong2YGNodeRef(dstNativePointer), _jlong2YGNodeRef(srcNativePointer)); } struct JYogaValue : public JavaClass { @@ -392,67 +449,76 @@ struct JYogaValue : public JavaClass { _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer) { \ - return JYogaValue::create(YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, jlong nativePointer, jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), static_cast(value)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer) { \ + return JYogaValue::create( \ + YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ +#define YG_NODE_JNI_STYLE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer) { \ + YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer)); \ } -#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ - javatype jni_YGNodeStyleGet##name(alias_ref, jlong nativePointer, jint edge) { \ - return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge)); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - javatype value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_PROP(javatype, type, name) \ + javatype jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return (javatype)YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, javatype value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - local_ref jni_YGNodeStyleGet##name(alias_ref, \ - jlong nativePointer, \ - jint edge) { \ - return JYogaValue::create( \ - YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer), static_cast(edge))); \ - } \ - \ - void jni_YGNodeStyleSet##name(alias_ref, jlong nativePointer, jint edge, jfloat value) { \ - YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ - } \ - \ - void jni_YGNodeStyleSet##name##Percent(alias_ref, \ - jlong nativePointer, \ - jint edge, \ - jfloat value) { \ - YGNodeStyleSet##name##Percent(_jlong2YGNodeRef(nativePointer), \ - static_cast(edge), \ - static_cast(value)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + local_ref jni_YGNodeStyleGet##name( \ + alias_ref, jlong nativePointer, jint edge) { \ + return JYogaValue::create(YGNodeStyleGet##name( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge))); \ + } \ + \ + void jni_YGNodeStyleSet##name( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ + } \ + \ + void jni_YGNodeStyleSet##name##Percent( \ + alias_ref, jlong nativePointer, jint edge, jfloat value) { \ + YGNodeStyleSet##name##Percent( \ + _jlong2YGNodeRef(nativePointer), \ + static_cast(edge), \ + static_cast(value)); \ } -#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ - YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ - void jni_YGNodeStyleSet##name##Auto(alias_ref, jlong nativePointer, jint edge) { \ - YGNodeStyleSet##name##Auto(_jlong2YGNodeRef(nativePointer), static_cast(edge)); \ +#define YG_NODE_JNI_STYLE_EDGE_UNIT_PROP_AUTO(name) \ + YG_NODE_JNI_STYLE_EDGE_UNIT_PROP(name) \ + void jni_YGNodeStyleSet##name##Auto( \ + alias_ref, jlong nativePointer, jint edge) { \ + YGNodeStyleSet##name##Auto( \ + _jlong2YGNodeRef(nativePointer), static_cast(edge)); \ } YG_NODE_JNI_STYLE_PROP(jint, YGDirection, Direction); @@ -466,8 +532,12 @@ YG_NODE_JNI_STYLE_PROP(jint, YGWrap, FlexWrap); YG_NODE_JNI_STYLE_PROP(jint, YGOverflow, Overflow); YG_NODE_JNI_STYLE_PROP(jint, YGDisplay, Display); -void jni_YGNodeStyleSetFlex(alias_ref, jlong nativePointer, jfloat value) { - YGNodeStyleSetFlex(_jlong2YGNodeRef(nativePointer), static_cast(value)); +void jni_YGNodeStyleSetFlex( + alias_ref, + jlong nativePointer, + jfloat value) { + YGNodeStyleSetFlex( + _jlong2YGNodeRef(nativePointer), static_cast(value)); } YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexGrow); YG_NODE_JNI_STYLE_PROP(jfloat, float, FlexShrink); @@ -501,14 +571,14 @@ void jni_YGConfigFree(alias_ref, jlong nativePointer) { YGConfigFree(config); } -void jni_YGConfigSetExperimentalFeatureEnabled(alias_ref, - jlong nativePointer, - jint feature, - jboolean enabled) { +void jni_YGConfigSetExperimentalFeatureEnabled( + alias_ref, + jlong nativePointer, + jint feature, + jboolean enabled) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); - YGConfigSetExperimentalFeatureEnabled(config, - static_cast(feature), - enabled); + YGConfigSetExperimentalFeatureEnabled( + config, static_cast(feature), enabled); } void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( @@ -519,23 +589,26 @@ void jni_YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour(config, enabled); } -void jni_YGConfigSetUseWebDefaults(alias_ref, - jlong nativePointer, - jboolean useWebDefaults) { +void jni_YGConfigSetUseWebDefaults( + alias_ref, + jlong nativePointer, + jboolean useWebDefaults) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseWebDefaults(config, useWebDefaults); } -void jni_YGConfigSetPointScaleFactor(alias_ref, - jlong nativePointer, - jfloat pixelsInPoint) { +void jni_YGConfigSetPointScaleFactor( + alias_ref, + jlong nativePointer, + jfloat pixelsInPoint) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetPointScaleFactor(config, pixelsInPoint); } -void jni_YGConfigSetUseLegacyStretchBehaviour(alias_ref, - jlong nativePointer, - jboolean useLegacyStretchBehaviour) { +void jni_YGConfigSetUseLegacyStretchBehaviour( + alias_ref, + jlong nativePointer, + jboolean useLegacyStretchBehaviour) { const YGConfigRef config = _jlong2YGConfigRef(nativePointer); YGConfigSetUseLegacyStretchBehaviour(config, useLegacyStretchBehaviour); } @@ -592,7 +665,7 @@ jint jni_YGNodeGetInstanceCount(alias_ref clazz) { #define YGMakeNativeMethod(name) makeNativeMethod(#name, name) -jint JNI_OnLoad(JavaVM *vm, void *) { +jint JNI_OnLoad(JavaVM* vm, void*) { return initialize(vm, [] { registerNatives( "com/facebook/yoga/YogaNode", From 966f5ece4ad8610ebc6dee45efeaf6380b6e623c Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 04:09:40 -0700 Subject: [PATCH 02/29] guards instead of nested if Summary: Replaces two nested if-blocks with guards. This is intended to help with restructuring this function in follow-ups. @public Reviewed By: priteshrnandgaonkar Differential Revision: D8785659 fbshipit-source-id: 7b9d63e9814b83b999397c016ad67ad348bb0f72 --- java/jni/YGJNI.cpp | 180 ++++++++++++++++++++++----------------------- 1 file changed, 89 insertions(+), 91 deletions(-) diff --git a/java/jni/YGJNI.cpp b/java/jni/YGJNI.cpp index 1d6f464c..0b552055 100644 --- a/java/jni/YGJNI.cpp +++ b/java/jni/YGJNI.cpp @@ -47,109 +47,107 @@ static void YGTransferLayoutDirection( } static void YGTransferLayoutOutputsRecursive(YGNodeRef root) { - if (root->getHasNewLayout()) { - if (auto obj = YGNodeJobject(root)->lockLocal()) { - static auto widthField = obj->getClass()->getField("mWidth"); - static auto heightField = obj->getClass()->getField("mHeight"); - static auto leftField = obj->getClass()->getField("mLeft"); - static auto topField = obj->getClass()->getField("mTop"); + if (!root->getHasNewLayout()) { + return; + } + auto obj = YGNodeJobject(root)->lockLocal(); + if (!obj) { + YGLog( + root, + YGLogLevelError, + "Java YGNode was GCed during layout calculation\n"); + return; + } - static auto marginLeftField = - obj->getClass()->getField("mMarginLeft"); - static auto marginTopField = - obj->getClass()->getField("mMarginTop"); - static auto marginRightField = - obj->getClass()->getField("mMarginRight"); - static auto marginBottomField = - obj->getClass()->getField("mMarginBottom"); + static auto widthField = obj->getClass()->getField("mWidth"); + static auto heightField = obj->getClass()->getField("mHeight"); + static auto leftField = obj->getClass()->getField("mLeft"); + static auto topField = obj->getClass()->getField("mTop"); - static auto paddingLeftField = - obj->getClass()->getField("mPaddingLeft"); - static auto paddingTopField = - obj->getClass()->getField("mPaddingTop"); - static auto paddingRightField = - obj->getClass()->getField("mPaddingRight"); - static auto paddingBottomField = - obj->getClass()->getField("mPaddingBottom"); + static auto marginLeftField = + obj->getClass()->getField("mMarginLeft"); + static auto marginTopField = obj->getClass()->getField("mMarginTop"); + static auto marginRightField = + obj->getClass()->getField("mMarginRight"); + static auto marginBottomField = + obj->getClass()->getField("mMarginBottom"); - static auto borderLeftField = - obj->getClass()->getField("mBorderLeft"); - static auto borderTopField = - obj->getClass()->getField("mBorderTop"); - static auto borderRightField = - obj->getClass()->getField("mBorderRight"); - static auto borderBottomField = - obj->getClass()->getField("mBorderBottom"); + static auto paddingLeftField = + obj->getClass()->getField("mPaddingLeft"); + static auto paddingTopField = + obj->getClass()->getField("mPaddingTop"); + static auto paddingRightField = + obj->getClass()->getField("mPaddingRight"); + static auto paddingBottomField = + obj->getClass()->getField("mPaddingBottom"); - static auto edgeSetFlagField = - obj->getClass()->getField("mEdgeSetFlag"); - static auto hasNewLayoutField = - obj->getClass()->getField("mHasNewLayout"); - static auto doesLegacyStretchBehaviour = - obj->getClass()->getField( - "mDoesLegacyStretchFlagAffectsLayout"); + static auto borderLeftField = + obj->getClass()->getField("mBorderLeft"); + static auto borderTopField = obj->getClass()->getField("mBorderTop"); + static auto borderRightField = + obj->getClass()->getField("mBorderRight"); + static auto borderBottomField = + obj->getClass()->getField("mBorderBottom"); - /* Those flags needs be in sync with YogaNode.java */ - const int MARGIN = 1; - const int PADDING = 2; - const int BORDER = 4; + static auto edgeSetFlagField = + obj->getClass()->getField("mEdgeSetFlag"); + static auto hasNewLayoutField = + obj->getClass()->getField("mHasNewLayout"); + static auto doesLegacyStretchBehaviour = obj->getClass()->getField( + "mDoesLegacyStretchFlagAffectsLayout"); - int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); + /* Those flags needs be in sync with YogaNode.java */ + const int MARGIN = 1; + const int PADDING = 2; + const int BORDER = 4; - obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); - obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); - obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); - obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); - obj->setFieldValue( - doesLegacyStretchBehaviour, - YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); + int hasEdgeSetFlag = (int)obj->getFieldValue(edgeSetFlagField); - if ((hasEdgeSetFlag & MARGIN) == MARGIN) { - obj->setFieldValue( - marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); - obj->setFieldValue( - marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); - obj->setFieldValue( - marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); - obj->setFieldValue( - marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); - } + obj->setFieldValue(widthField, YGNodeLayoutGetWidth(root)); + obj->setFieldValue(heightField, YGNodeLayoutGetHeight(root)); + obj->setFieldValue(leftField, YGNodeLayoutGetLeft(root)); + obj->setFieldValue(topField, YGNodeLayoutGetTop(root)); + obj->setFieldValue( + doesLegacyStretchBehaviour, + YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(root)); - if ((hasEdgeSetFlag & PADDING) == PADDING) { - obj->setFieldValue( - paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); - obj->setFieldValue( - paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); - obj->setFieldValue( - paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); - obj->setFieldValue( - paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); - } + if ((hasEdgeSetFlag & MARGIN) == MARGIN) { + obj->setFieldValue( + marginLeftField, YGNodeLayoutGetMargin(root, YGEdgeLeft)); + obj->setFieldValue(marginTopField, YGNodeLayoutGetMargin(root, YGEdgeTop)); + obj->setFieldValue( + marginRightField, YGNodeLayoutGetMargin(root, YGEdgeRight)); + obj->setFieldValue( + marginBottomField, YGNodeLayoutGetMargin(root, YGEdgeBottom)); + } - if ((hasEdgeSetFlag & BORDER) == BORDER) { - obj->setFieldValue( - borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); - obj->setFieldValue( - borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); - obj->setFieldValue( - borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); - obj->setFieldValue( - borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); - } + if ((hasEdgeSetFlag & PADDING) == PADDING) { + obj->setFieldValue( + paddingLeftField, YGNodeLayoutGetPadding(root, YGEdgeLeft)); + obj->setFieldValue( + paddingTopField, YGNodeLayoutGetPadding(root, YGEdgeTop)); + obj->setFieldValue( + paddingRightField, YGNodeLayoutGetPadding(root, YGEdgeRight)); + obj->setFieldValue( + paddingBottomField, YGNodeLayoutGetPadding(root, YGEdgeBottom)); + } - obj->setFieldValue(hasNewLayoutField, true); - YGTransferLayoutDirection(root, obj); - root->setHasNewLayout(false); + if ((hasEdgeSetFlag & BORDER) == BORDER) { + obj->setFieldValue( + borderLeftField, YGNodeLayoutGetBorder(root, YGEdgeLeft)); + obj->setFieldValue(borderTopField, YGNodeLayoutGetBorder(root, YGEdgeTop)); + obj->setFieldValue( + borderRightField, YGNodeLayoutGetBorder(root, YGEdgeRight)); + obj->setFieldValue( + borderBottomField, YGNodeLayoutGetBorder(root, YGEdgeBottom)); + } - for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { - YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); - } - } else { - YGLog( - root, - YGLogLevelError, - "Java YGNode was GCed during layout calculation\n"); - } + obj->setFieldValue(hasNewLayoutField, true); + YGTransferLayoutDirection(root, obj); + root->setHasNewLayout(false); + + for (uint32_t i = 0; i < YGNodeGetChildCount(root); i++) { + YGTransferLayoutOutputsRecursive(YGNodeGetChild(root, i)); } } From 6548dddec368c235824fe2f5e1e6fe753d3fd43a Mon Sep 17 00:00:00 2001 From: Pritesh Nandgaonkar Date: Wed, 11 Jul 2018 05:55:02 -0700 Subject: [PATCH 03/29] Fix SingleFlex Child condition Summary: Fixes the improper `singleFlexChild` optimization. In the case when all the childs have `flex-grow:0 flex-grow:0` except one child with `flex-grow:1 flex-shrink:1`, then one can simply measure all the non-flexing children and then give the flexing child all the remaining space. Also added a test case which reproduced the bug Reviewed By: IanChilds Differential Revision: D8782684 fbshipit-source-id: ffd4d35b6122f82111b987540efb23bd2a8da5a2 --- tests/YGFlexTest.cpp | 94 ++++++++++++++++++++++++++++++++++++++--- tests/YGMeasureTest.cpp | 10 ++--- yoga/Yoga.cpp | 15 ++++--- 3 files changed, 102 insertions(+), 17 deletions(-) diff --git a/tests/YGFlexTest.cpp b/tests/YGFlexTest.cpp index e1a8ba89..388bcaca 100644 --- a/tests/YGFlexTest.cpp +++ b/tests/YGFlexTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - // @Generated by gentest/gentest.rb from gentest/fixtures/YGFlexTest.html #include @@ -64,6 +64,90 @@ TEST(YogaTest, flex_basis_flex_grow_column) { YGConfigFree(config); } +TEST(YogaTest, flex_shrink_flex_grow_row) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 500); + YGNodeStyleSetHeight(root, 500); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetWidth(root_child0, 500); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 0); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + +TEST(YogaTest, flex_shrink_flex_grow_child_flex_shrink_other_child) { + const YGConfigRef config = YGConfigNew(); + + const YGNodeRef root = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexDirection(root, YGFlexDirectionRow); + YGNodeStyleSetWidth(root, 500); + YGNodeStyleSetHeight(root, 500); + + const YGNodeRef root_child0 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child0, 0); + YGNodeStyleSetFlexShrink(root_child0, 1); + YGNodeStyleSetWidth(root_child0, 500); + YGNodeStyleSetHeight(root_child0, 100); + YGNodeInsertChild(root, root_child0, 0); + + const YGNodeRef root_child1 = YGNodeNewWithConfig(config); + YGNodeStyleSetFlexGrow(root_child1, 1); + YGNodeStyleSetFlexShrink(root_child1, 1); + YGNodeStyleSetWidth(root_child1, 500); + YGNodeStyleSetHeight(root_child1, 100); + YGNodeInsertChild(root, root_child1, 1); + YGNodeCalculateLayout(root, YGUndefined, YGUndefined, YGDirectionLTR); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetWidth(root)); + ASSERT_FLOAT_EQ(500, YGNodeLayoutGetHeight(root)); + + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetLeft(root_child0)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child0)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child0)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child0)); + + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetLeft(root_child1)); + ASSERT_FLOAT_EQ(0, YGNodeLayoutGetTop(root_child1)); + ASSERT_FLOAT_EQ(250, YGNodeLayoutGetWidth(root_child1)); + ASSERT_FLOAT_EQ(100, YGNodeLayoutGetHeight(root_child1)); + YGNodeFreeRecursive(root); + + YGConfigFree(config); +} + TEST(YogaTest, flex_basis_flex_grow_row) { const YGConfigRef config = YGConfigNew(); diff --git a/tests/YGMeasureTest.cpp b/tests/YGMeasureTest.cpp index aea2cd59..0e599cdc 100644 --- a/tests/YGMeasureTest.cpp +++ b/tests/YGMeasureTest.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index e5d1aabb..3684aae4 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1788,16 +1788,17 @@ static void YGNodeComputeFlexBasisForChildren( // child to exactly match the remaining space if (measureModeMainDim == YGMeasureModeExactly) { for (auto child : children) { - if (singleFlexChild != nullptr) { - if (child->isNodeFlexible()) { - // There is already a flexible child, abort + if (child->isNodeFlexible()) { + if (singleFlexChild != nullptr || + YGFloatsEqual(child->resolveFlexGrow(), 0.0f) || + YGFloatsEqual(child->resolveFlexShrink(), 0.0f)) { + // There is already a flexible child, or this flexible child doesn't + // have flexGrow and flexShrink, abort singleFlexChild = nullptr; break; + } else { + singleFlexChild = child; } - } else if ( - child->resolveFlexGrow() > 0.0f && - child->resolveFlexShrink() > 0.0f) { - singleFlexChild = child; } } } From 765bb85d1e33e7ba35159fb38bd89fe0b343d71d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:30 -0700 Subject: [PATCH 04/29] Fix warnings when building benchmark Summary: There were a few missing prototypes and a -Wshadow violation. Merged YGBenchmark.h into YGBenchmark.c, added static where needed, fixed shadow violation. Reviewed By: davidaurelio Differential Revision: D8793124 fbshipit-source-id: c4b2dd348c38aa599169b5e9bea543c172439432 --- benchmark/YGBenchmark.c | 66 ++++++++++++++++++++++++++++++++++++-- benchmark/YGBenchmark.h | 71 ----------------------------------------- 2 files changed, 64 insertions(+), 73 deletions(-) delete mode 100644 benchmark/YGBenchmark.h diff --git a/benchmark/YGBenchmark.c b/benchmark/YGBenchmark.c index 1c5521ae..c06ca276 100644 --- a/benchmark/YGBenchmark.c +++ b/benchmark/YGBenchmark.c @@ -5,10 +5,72 @@ * LICENSE file in the root directory of this source tree. */ -#include "YGBenchmark.h" +#include +#include +#include +#include +#include #include +#define NUM_REPETITIONS 1000 + +#define YGBENCHMARKS(BLOCK) \ + int main(int argc, char const *argv[]) { \ + clock_t __start; \ + clock_t __endTimes[NUM_REPETITIONS]; \ + { BLOCK } \ + return 0; \ + } + +#define YGBENCHMARK(NAME, BLOCK) \ + __start = clock(); \ + for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \ + { BLOCK } \ + __endTimes[__i] = clock(); \ + } \ + __printBenchmarkResult(NAME, __start, __endTimes); + +static int __compareDoubles(const void *a, const void *b) { + double arg1 = *(const double *) a; + double arg2 = *(const double *) b; + + if (arg1 < arg2) { + return -1; + } + + if (arg1 > arg2) { + return 1; + } + + return 0; +} + +static void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) { + double timesInMs[NUM_REPETITIONS]; + double mean = 0; + clock_t lastEnd = start; + for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { + timesInMs[i] = (endTimes[i] - lastEnd) / (double) CLOCKS_PER_SEC * 1000; + lastEnd = endTimes[i]; + mean += timesInMs[i]; + } + mean /= NUM_REPETITIONS; + + qsort(timesInMs, NUM_REPETITIONS, sizeof(double), __compareDoubles); + double median = timesInMs[NUM_REPETITIONS / 2]; + + double variance = 0; + for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { + variance += pow(timesInMs[i] - mean, 2); + } + variance /= NUM_REPETITIONS; + double stddev = sqrt(variance); + + printf("%s: median: %lf ms, stddev: %lf ms\n", name, median, stddev); +} + + static YGSize _measure(YGNodeRef node, float width, YGMeasureMode widthMode, @@ -97,7 +159,7 @@ YGBENCHMARKS({ YGNodeStyleSetHeight(grandGrandChild, 10); YGNodeInsertChild(grandChild, grandGrandChild, 0); - for (uint32_t iii = 0; iii < 10; iii++) { + for (uint32_t iiii = 0; iiii < 10; iiii++) { const YGNodeRef grandGrandGrandChild = YGNodeNew(); YGNodeStyleSetFlexDirection(grandGrandGrandChild, YGFlexDirectionRow); YGNodeStyleSetFlexGrow(grandGrandGrandChild, 1); diff --git a/benchmark/YGBenchmark.h b/benchmark/YGBenchmark.h deleted file mode 100644 index 54a625b7..00000000 --- a/benchmark/YGBenchmark.h +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. - * - * 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 - -#define NUM_REPETITIONS 1000 - -#define YGBENCHMARKS(BLOCK) \ - int main(int argc, char const *argv[]) { \ - clock_t __start; \ - clock_t __endTimes[NUM_REPETITIONS]; \ - { BLOCK } \ - return 0; \ - } - -#define YGBENCHMARK(NAME, BLOCK) \ - __start = clock(); \ - for (uint32_t __i = 0; __i < NUM_REPETITIONS; __i++) { \ - { BLOCK } \ - __endTimes[__i] = clock(); \ - } \ - __printBenchmarkResult(NAME, __start, __endTimes); - -int __compareDoubles(const void *a, const void *b) { - double arg1 = *(const double *) a; - double arg2 = *(const double *) b; - - if (arg1 < arg2) { - return -1; - } - - if (arg1 > arg2) { - return 1; - } - - return 0; -} - -void __printBenchmarkResult(char *name, clock_t start, clock_t *endTimes) { - double timesInMs[NUM_REPETITIONS]; - double mean = 0; - clock_t lastEnd = start; - for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { - timesInMs[i] = (endTimes[i] - lastEnd) / (double) CLOCKS_PER_SEC * 1000; - lastEnd = endTimes[i]; - mean += timesInMs[i]; - } - mean /= NUM_REPETITIONS; - - qsort(timesInMs, NUM_REPETITIONS, sizeof(double), __compareDoubles); - double median = timesInMs[NUM_REPETITIONS / 2]; - - double variance = 0; - for (uint32_t i = 0; i < NUM_REPETITIONS; i++) { - variance += pow(timesInMs[i] - mean, 2); - } - variance /= NUM_REPETITIONS; - double stddev = sqrt(variance); - - printf("%s: median: %lf ms, stddev: %lf ms\n", name, median, stddev); -} From 9ceed4b6014ebdbdb88d3f2d3fc6f3f7112e2706 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:31 -0700 Subject: [PATCH 05/29] Remove unused YGNode::*nextChild Summary: This linked list was never used, and YGNodeDeepClone was doing scary things to maintain it. Reviewed By: davidaurelio Differential Revision: D8792864 fbshipit-source-id: c578fabe65c837f0791aa9ac3e18f31d93691abd --- yoga/YGNode.cpp | 13 ------------- yoga/YGNode.h | 4 ---- yoga/Yoga.cpp | 4 ---- 3 files changed, 21 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 16f9e4d0..67d991a4 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -69,10 +69,6 @@ YGNodeRef YGNode::getChild(uint32_t index) const { return children_.at(index); } -YGNodeRef YGNode::getNextChild() const { - return nextChild_; -} - YGConfigRef YGNode::getConfig() const { return config_; } @@ -249,10 +245,6 @@ void YGNode::setChildren(const YGVector& children) { children_ = children; } -void YGNode::setNextChild(YGNodeRef nextChild) { - nextChild_ = nextChild; -} - void YGNode::replaceChild(YGNodeRef child, uint32_t index) { children_[index] = child; } @@ -405,7 +397,6 @@ YGNode::YGNode() lineIndex_(0), owner_(nullptr), children_(YGVector()), - nextChild_(nullptr), config_(nullptr), isDirty_(false), resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} @@ -423,7 +414,6 @@ YGNode::YGNode(const YGNode& node) lineIndex_(node.lineIndex_), owner_(node.owner_), children_(node.children_), - nextChild_(node.nextChild_), config_(node.config_), isDirty_(node.isDirty_), resolvedDimensions_(node.resolvedDimensions_) {} @@ -445,7 +435,6 @@ YGNode::YGNode( uint32_t lineIndex, YGNodeRef owner, const YGVector& children, - YGNodeRef nextChild, YGConfigRef config, bool isDirty, std::array resolvedDimensions) @@ -461,7 +450,6 @@ YGNode::YGNode( lineIndex_(lineIndex), owner_(owner), children_(children), - nextChild_(nextChild), config_(config), isDirty_(isDirty), resolvedDimensions_(resolvedDimensions) {} @@ -487,7 +475,6 @@ YGNode& YGNode::operator=(const YGNode& node) { lineIndex_ = node.getLineIndex(); owner_ = node.getOwner(); children_ = node.getChildren(); - nextChild_ = node.getNextChild(); config_ = node.getConfig(); isDirty_ = node.isDirty(); resolvedDimensions_ = node.getResolvedDimensions(); diff --git a/yoga/YGNode.h b/yoga/YGNode.h index e3562bb6..e4d50dcf 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -26,7 +26,6 @@ struct YGNode { uint32_t lineIndex_; YGNodeRef owner_; YGVector children_; - YGNodeRef nextChild_; YGConfigRef config_; bool isDirty_; std::array resolvedDimensions_; @@ -54,7 +53,6 @@ struct YGNode { uint32_t lineIndex, YGNodeRef owner, const YGVector& children, - YGNodeRef nextChild, YGConfigRef config, bool isDirty, std::array resolvedDimensions); @@ -83,7 +81,6 @@ struct YGNode { YGVector getChildren() const; uint32_t getChildrenCount() const; YGNodeRef getChild(uint32_t index) const; - YGNodeRef getNextChild() const; YGConfigRef getConfig() const; bool isDirty() const; std::array getResolvedDimensions() const; @@ -136,7 +133,6 @@ struct YGNode { void setLineIndex(uint32_t lineIndex); void setOwner(YGNodeRef owner); void setChildren(const YGVector& children); - void setNextChild(YGNodeRef nextChild); void setConfig(YGConfigRef config); void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 3684aae4..5b5a9088 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -275,10 +275,6 @@ static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) { node->setConfig(YGConfigClone(*(oldNode->getConfig()))); } - if (oldNode->getNextChild() != nullptr) { - node->setNextChild(YGNodeDeepClone(oldNode->getNextChild())); - } - return node; } From e384002878858dfaa4ed13463f498f7aeeccf9c1 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 11 Jul 2018 08:51:33 -0700 Subject: [PATCH 06/29] Inline simple YGNode getters/setters Summary: Simple getters/setters are usually inlined like this. Reviewed By: priteshrnandgaonkar, davidaurelio Differential Revision: D8793588 fbshipit-source-id: 436bd54880e41a5e403e3f4ae0d9dd4a413df79c --- yoga/YGNode.cpp | 130 ----------------------------------- yoga/YGNode.h | 175 +++++++++++++++++++++++++++++++++++++++--------- 2 files changed, 142 insertions(+), 163 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 67d991a4..13571a9d 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -9,82 +9,6 @@ #include #include "Utils.h" -void* YGNode::getContext() const { - return context_; -} - -YGPrintFunc YGNode::getPrintFunc() const { - return print_; -} - -bool YGNode::getHasNewLayout() const { - return hasNewLayout_; -} - -YGNodeType YGNode::getNodeType() const { - return nodeType_; -} - -YGMeasureFunc YGNode::getMeasure() const { - return measure_; -} - -YGBaselineFunc YGNode::getBaseline() const { - return baseline_; -} - -YGDirtiedFunc YGNode::getDirtied() const { - return dirtied_; -} - -YGStyle& YGNode::getStyle() { - return style_; -} - -YGLayout& YGNode::getLayout() { - return layout_; -} - -uint32_t YGNode::getLineIndex() const { - return lineIndex_; -} - -YGNodeRef YGNode::getOwner() const { - return owner_; -} - -YGNodeRef YGNode::getParent() const { - return getOwner(); -} - -YGVector YGNode::getChildren() const { - return children_; -} - -uint32_t YGNode::getChildrenCount() const { - return static_cast(children_.size()); -} - -YGNodeRef YGNode::getChild(uint32_t index) const { - return children_.at(index); -} - -YGConfigRef YGNode::getConfig() const { - return config_; -} - -bool YGNode::isDirty() const { - return isDirty_; -} - -YGValue YGNode::getResolvedDimension(int index) { - return resolvedDimensions_[index]; -} - -std::array YGNode::getResolvedDimensions() const { - return resolvedDimensions_; -} - YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection& axis, const float& axisSize) const { @@ -173,29 +97,7 @@ YGFloatOptional YGNode::getMarginForAxis( // Setters -void YGNode::setContext(void* context) { - context_ = context; -} -void YGNode::setPrintFunc(YGPrintFunc printFunc) { - print_ = printFunc; -} - -void YGNode::setHasNewLayout(bool hasNewLayout) { - hasNewLayout_ = hasNewLayout; -} - -void YGNode::setNodeType(YGNodeType nodeType) { - nodeType_ = nodeType; -} - -void YGNode::setStyleFlexDirection(YGFlexDirection direction) { - style_.flexDirection = direction; -} - -void YGNode::setStyleAlignContent(YGAlign alignContent) { - style_.alignContent = alignContent; -} void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { if (measureFunc == nullptr) { @@ -217,34 +119,6 @@ void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { measure_ = measureFunc; } -void YGNode::setBaseLineFunc(YGBaselineFunc baseLineFunc) { - baseline_ = baseLineFunc; -} - -void YGNode::setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { - dirtied_ = dirtiedFunc; -} - -void YGNode::setStyle(const YGStyle& style) { - style_ = style; -} - -void YGNode::setLayout(const YGLayout& layout) { - layout_ = layout; -} - -void YGNode::setLineIndex(uint32_t lineIndex) { - lineIndex_ = lineIndex; -} - -void YGNode::setOwner(YGNodeRef owner) { - owner_ = owner; -} - -void YGNode::setChildren(const YGVector& children) { - children_ = children; -} - void YGNode::replaceChild(YGNodeRef child, uint32_t index) { children_[index] = child; } @@ -257,10 +131,6 @@ void YGNode::insertChild(YGNodeRef child, uint32_t index) { children_.insert(children_.begin() + index, child); } -void YGNode::setConfig(YGConfigRef config) { - config_ = config; -} - void YGNode::setDirty(bool isDirty) { if (isDirty == isDirty_) { return; diff --git a/yoga/YGNode.h b/yoga/YGNode.h index e4d50dcf..ab302e06 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -58,33 +58,97 @@ struct YGNode { std::array resolvedDimensions); // Getters - void* getContext() const; - YGPrintFunc getPrintFunc() const; - bool getHasNewLayout() const; - YGNodeType getNodeType() const; - YGMeasureFunc getMeasure() const; - YGBaselineFunc getBaseline() const; - YGDirtiedFunc getDirtied() const; + void* getContext() const { + return context_; + } + + YGPrintFunc getPrintFunc() const { + return print_; + } + + bool getHasNewLayout() const { + return hasNewLayout_; + } + + YGNodeType getNodeType() const { + return nodeType_; + } + + YGMeasureFunc getMeasure() const { + return measure_; + } + + YGBaselineFunc getBaseline() const { + return baseline_; + } + + YGDirtiedFunc getDirtied() const { + return dirtied_; + } + // For Performance reasons passing as reference. - YGStyle& getStyle(); + YGStyle& getStyle() { + return style_; + } + + const YGStyle& getStyle() const { + return style_; + } + // For Performance reasons passing as reference. - YGLayout& getLayout(); - uint32_t getLineIndex() const; + YGLayout& getLayout() { + return layout_; + } + + const YGLayout& getLayout() const { + return layout_; + } + + uint32_t getLineIndex() const { + return lineIndex_; + } + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs // to one YogaTree or nullptr when the YGNode is shared between two or more // YogaTrees. - YGNodeRef getOwner() const; + YGNodeRef getOwner() const { + return owner_; + } + // Deprecated, use getOwner() instead. - YGNodeRef getParent() const; - YGVector getChildren() const; - uint32_t getChildrenCount() const; - YGNodeRef getChild(uint32_t index) const; - YGConfigRef getConfig() const; - bool isDirty() const; - std::array getResolvedDimensions() const; - YGValue getResolvedDimension(int index); + YGNodeRef getParent() const { + return getOwner(); + } + + YGVector getChildren() const { + return children_; + } + + uint32_t getChildrenCount() const { + return static_cast(children_.size()); + } + + YGNodeRef getChild(uint32_t index) const { + return children_.at(index); + } + + YGConfigRef getConfig() const { + return config_; + } + + bool isDirty() const { + return isDirty_; + } + + std::array getResolvedDimensions() const { + return resolvedDimensions_; + } + + YGValue getResolvedDimension(int index) const { + return resolvedDimensions_[index]; + } // Methods related to positions, margin, padding and border YGFloatOptional getLeadingPosition(const YGFlexDirection& axis, @@ -119,21 +183,66 @@ struct YGNode { const float& widthSize) const; // Setters - void setContext(void* context); - void setPrintFunc(YGPrintFunc printFunc); - void setHasNewLayout(bool hasNewLayout); - void setNodeType(YGNodeType nodeTye); + void setContext(void* context) { + context_ = context; + } + + void setPrintFunc(YGPrintFunc printFunc) { + print_ = printFunc; + } + + void setHasNewLayout(bool hasNewLayout) { + hasNewLayout_ = hasNewLayout; + } + + void setNodeType(YGNodeType nodeType) { + nodeType_ = nodeType; + } + + void setStyleFlexDirection(YGFlexDirection direction) { + style_.flexDirection = direction; + } + + void setStyleAlignContent(YGAlign alignContent) { + style_.alignContent = alignContent; + } + void setMeasureFunc(YGMeasureFunc measureFunc); - void setBaseLineFunc(YGBaselineFunc baseLineFunc); - void setDirtiedFunc(YGDirtiedFunc dirtiedFunc); - void setStyle(const YGStyle& style); - void setStyleFlexDirection(YGFlexDirection direction); - void setStyleAlignContent(YGAlign alignContent); - void setLayout(const YGLayout& layout); - void setLineIndex(uint32_t lineIndex); - void setOwner(YGNodeRef owner); - void setChildren(const YGVector& children); - void setConfig(YGConfigRef config); + + void setBaseLineFunc(YGBaselineFunc baseLineFunc) { + baseline_ = baseLineFunc; + } + + void setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { + dirtied_ = dirtiedFunc; + } + + void setStyle(const YGStyle& style) { + style_ = style; + } + + void setLayout(const YGLayout& layout) { + layout_ = layout; + } + + void setLineIndex(uint32_t lineIndex) { + lineIndex_ = lineIndex; + } + + void setOwner(YGNodeRef owner) { + owner_ = owner; + } + + void setChildren(const YGVector& children) { + children_ = children; + } + + // TODO: rvalue override for setChildren + + void setConfig(YGConfigRef config) { + config_ = config; + } + void setDirty(bool isDirty); void setLayoutLastOwnerDirection(YGDirection direction); void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis); From b6231ee0edd43145e582b2ed0207b65cc29c3e7f Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 11 Jul 2018 09:33:24 -0700 Subject: [PATCH 07/29] Lint java files Summary: @public Applies lint auto-fixes to java files. Reviewed By: priteshrnandgaonkar Differential Revision: D8803814 fbshipit-source-id: 2e4dc285b233091a9fbadf38fc22dd6e36f11f8e --- java/com/facebook/yoga/YogaAlign.java | 8 ++++---- java/com/facebook/yoga/YogaBaselineFunction.java | 8 ++++---- java/com/facebook/yoga/YogaConfig.java | 8 ++++---- java/com/facebook/yoga/YogaConstants.java | 8 ++++---- java/com/facebook/yoga/YogaDimension.java | 8 ++++---- java/com/facebook/yoga/YogaDirection.java | 8 ++++---- java/com/facebook/yoga/YogaDisplay.java | 8 ++++---- java/com/facebook/yoga/YogaEdge.java | 8 ++++---- java/com/facebook/yoga/YogaExperimentalFeature.java | 8 ++++---- java/com/facebook/yoga/YogaFlexDirection.java | 8 ++++---- java/com/facebook/yoga/YogaJustify.java | 8 ++++---- java/com/facebook/yoga/YogaLogLevel.java | 8 ++++---- java/com/facebook/yoga/YogaLogger.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureFunction.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureMode.java | 8 ++++---- java/com/facebook/yoga/YogaMeasureOutput.java | 8 ++++---- java/com/facebook/yoga/YogaNodeCloneFunction.java | 8 ++++---- java/com/facebook/yoga/YogaNodeType.java | 8 ++++---- java/com/facebook/yoga/YogaOverflow.java | 8 ++++---- java/com/facebook/yoga/YogaPositionType.java | 8 ++++---- java/com/facebook/yoga/YogaPrintOptions.java | 8 ++++---- java/com/facebook/yoga/YogaUnit.java | 8 ++++---- java/com/facebook/yoga/YogaValue.java | 8 ++++---- java/com/facebook/yoga/YogaWrap.java | 8 ++++---- 24 files changed, 96 insertions(+), 96 deletions(-) diff --git a/java/com/facebook/yoga/YogaAlign.java b/java/com/facebook/yoga/YogaAlign.java index bea5aebd..5687ab9d 100644 --- a/java/com/facebook/yoga/YogaAlign.java +++ b/java/com/facebook/yoga/YogaAlign.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaBaselineFunction.java b/java/com/facebook/yoga/YogaBaselineFunction.java index 9ec41e7e..20feae33 100644 --- a/java/com/facebook/yoga/YogaBaselineFunction.java +++ b/java/com/facebook/yoga/YogaBaselineFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaConfig.java b/java/com/facebook/yoga/YogaConfig.java index 12aa0d8e..128f5328 100644 --- a/java/com/facebook/yoga/YogaConfig.java +++ b/java/com/facebook/yoga/YogaConfig.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaConstants.java b/java/com/facebook/yoga/YogaConstants.java index 4e081ce4..68c5c982 100644 --- a/java/com/facebook/yoga/YogaConstants.java +++ b/java/com/facebook/yoga/YogaConstants.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; public class YogaConstants { diff --git a/java/com/facebook/yoga/YogaDimension.java b/java/com/facebook/yoga/YogaDimension.java index b0d89226..3a950e01 100644 --- a/java/com/facebook/yoga/YogaDimension.java +++ b/java/com/facebook/yoga/YogaDimension.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaDirection.java b/java/com/facebook/yoga/YogaDirection.java index dd6444e1..ccd46e84 100644 --- a/java/com/facebook/yoga/YogaDirection.java +++ b/java/com/facebook/yoga/YogaDirection.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaDisplay.java b/java/com/facebook/yoga/YogaDisplay.java index e6e52aad..75c2b687 100644 --- a/java/com/facebook/yoga/YogaDisplay.java +++ b/java/com/facebook/yoga/YogaDisplay.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaEdge.java b/java/com/facebook/yoga/YogaEdge.java index 053490da..36a893f6 100644 --- a/java/com/facebook/yoga/YogaEdge.java +++ b/java/com/facebook/yoga/YogaEdge.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaExperimentalFeature.java b/java/com/facebook/yoga/YogaExperimentalFeature.java index a8a4be14..790bd056 100644 --- a/java/com/facebook/yoga/YogaExperimentalFeature.java +++ b/java/com/facebook/yoga/YogaExperimentalFeature.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaFlexDirection.java b/java/com/facebook/yoga/YogaFlexDirection.java index cf192d6c..5c66d92f 100644 --- a/java/com/facebook/yoga/YogaFlexDirection.java +++ b/java/com/facebook/yoga/YogaFlexDirection.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaJustify.java b/java/com/facebook/yoga/YogaJustify.java index 9e15dc4a..13d3a001 100644 --- a/java/com/facebook/yoga/YogaJustify.java +++ b/java/com/facebook/yoga/YogaJustify.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaLogLevel.java b/java/com/facebook/yoga/YogaLogLevel.java index 458e1b95..0cf7f70c 100644 --- a/java/com/facebook/yoga/YogaLogLevel.java +++ b/java/com/facebook/yoga/YogaLogLevel.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaLogger.java b/java/com/facebook/yoga/YogaLogger.java index 66f62c89..6d1a6a1e 100644 --- a/java/com/facebook/yoga/YogaLogger.java +++ b/java/com/facebook/yoga/YogaLogger.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaMeasureFunction.java b/java/com/facebook/yoga/YogaMeasureFunction.java index 2d2b304d..cc54caec 100644 --- a/java/com/facebook/yoga/YogaMeasureFunction.java +++ b/java/com/facebook/yoga/YogaMeasureFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaMeasureMode.java b/java/com/facebook/yoga/YogaMeasureMode.java index 97193776..5cfc24a4 100644 --- a/java/com/facebook/yoga/YogaMeasureMode.java +++ b/java/com/facebook/yoga/YogaMeasureMode.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaMeasureOutput.java b/java/com/facebook/yoga/YogaMeasureOutput.java index 1d2141d1..e68af410 100644 --- a/java/com/facebook/yoga/YogaMeasureOutput.java +++ b/java/com/facebook/yoga/YogaMeasureOutput.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; /** diff --git a/java/com/facebook/yoga/YogaNodeCloneFunction.java b/java/com/facebook/yoga/YogaNodeCloneFunction.java index 0733776a..ccf7f5c5 100644 --- a/java/com/facebook/yoga/YogaNodeCloneFunction.java +++ b/java/com/facebook/yoga/YogaNodeCloneFunction.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2017-present, Facebook, Inc. + * Copyright (c) 2017-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaNodeType.java b/java/com/facebook/yoga/YogaNodeType.java index fb767b05..7eb7246c 100644 --- a/java/com/facebook/yoga/YogaNodeType.java +++ b/java/com/facebook/yoga/YogaNodeType.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaOverflow.java b/java/com/facebook/yoga/YogaOverflow.java index 9563d303..85bc8b20 100644 --- a/java/com/facebook/yoga/YogaOverflow.java +++ b/java/com/facebook/yoga/YogaOverflow.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaPositionType.java b/java/com/facebook/yoga/YogaPositionType.java index be42a999..17073f47 100644 --- a/java/com/facebook/yoga/YogaPositionType.java +++ b/java/com/facebook/yoga/YogaPositionType.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaPrintOptions.java b/java/com/facebook/yoga/YogaPrintOptions.java index 5a804adf..3b59960d 100644 --- a/java/com/facebook/yoga/YogaPrintOptions.java +++ b/java/com/facebook/yoga/YogaPrintOptions.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaUnit.java b/java/com/facebook/yoga/YogaUnit.java index 8eb2b316..e4002dd0 100644 --- a/java/com/facebook/yoga/YogaUnit.java +++ b/java/com/facebook/yoga/YogaUnit.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaValue.java b/java/com/facebook/yoga/YogaValue.java index a99d5641..c0bb6e22 100644 --- a/java/com/facebook/yoga/YogaValue.java +++ b/java/com/facebook/yoga/YogaValue.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; diff --git a/java/com/facebook/yoga/YogaWrap.java b/java/com/facebook/yoga/YogaWrap.java index 1eaa9f7a..3c10dd3a 100644 --- a/java/com/facebook/yoga/YogaWrap.java +++ b/java/com/facebook/yoga/YogaWrap.java @@ -1,10 +1,10 @@ /* - * Copyright (c) 2014-present, Facebook, Inc. + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - package com.facebook.yoga; import com.facebook.proguard.annotations.DoNotStrip; From 89ba4f282dc6ec71ae66038f044b309d5bcde083 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Wed, 11 Jul 2018 20:05:22 -0700 Subject: [PATCH 08/29] Removed misleading comment in YGPersistenceTest Summary: Trivial... but quite confusing. :) Created from Diffusion's 'Open in Editor' feature. Reviewed By: priteshrnandgaonkar Differential Revision: D7151891 fbshipit-source-id: d09a6434d6327736c2d5ce672b3e9c5b5573508a --- tests/YGPersistenceTest.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/tests/YGPersistenceTest.cpp b/tests/YGPersistenceTest.cpp index 9df861a8..d7fb98d4 100644 --- a/tests/YGPersistenceTest.cpp +++ b/tests/YGPersistenceTest.cpp @@ -5,8 +5,6 @@ * LICENSE file in the root directory of this source tree. */ -// @Generated by gentest/gentest.rb from gentest/fixtures/YGPercentageTest.html - #include #include From a7f430a5ef391f830f7828c01002c0c42a5c9c97 Mon Sep 17 00:00:00 2001 From: Marc Terns Date: Thu, 12 Jul 2018 07:26:17 -0700 Subject: [PATCH 09/29] Feature podspec modules (#793) Summary: This PR adds support for using Yoga Swift dependents when Yoga is pulled as a static library. Currently swift projects trying to pull static libraries are unable to import the module. The reason for that is because the `DEFINES_MODULES` build setting is set to`NO`. If a Swift Framework is trying to `pod spec lint --use-libraries` with `Yoga` as a dependency, the validation will fail. With the `DEFINES_MODULE` enabled, the product will be treated as defining its own module. This enables automatic production of LLVM module map files when appropriate, and allows the product to be imported as a module. A workaround to this issue would be passing the `:modular_headers` flag to the `Podfile`, but that would not fix the `pod spec lint` validation for framework/library dependencies, it would just allow consuming applications to build and run. An example of this issue would be [SonarKit](https://github.com/facebook/Sonar/blob/master/iOS/SonarKit.podspec). `SonarKit` wasn't able to validate its podspec due to `YogaKit` (Swift Framework) depending on `Yoga` and SonarKit validating with the `--use-libraries` flag due to the c++ dependencies. We had to create a new version of [Yoga 1.9 podspec](https://github.com/facebook/Sonar/blob/master/Specs/Yoga/1.9/Yoga.podspec.json) and make sure to set the `DEFINES_MODULE` flag of the pod target. After that, we were able to `pod spec lint` `SonarKit.podspec` successfully. After merging a new `tag` should be created and the new podspec should be pushed to cocoapods master repository. Pull Request resolved: https://github.com/facebook/yoga/pull/793 Reviewed By: passy Differential Revision: D8820126 Pulled By: priteshrnandgaonkar fbshipit-source-id: 98eae3c31ec67a03c0fe97e05ab9e79446fa9f78 --- Yoga.podspec | 7 +++++-- YogaKit.podspec | 6 +++--- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/Yoga.podspec b/Yoga.podspec index 7d4553e8..a13fb02f 100644 --- a/Yoga.podspec +++ b/Yoga.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |spec| spec.name = 'Yoga' - spec.version = '1.8.1' + spec.version = '1.9.0' spec.license = { :type => 'MIT', :file => "LICENSE" } spec.homepage = 'https://yogalayout.com/' spec.documentation_url = 'https://yogalayout.com/docs' @@ -11,11 +11,14 @@ Pod::Spec.new do |spec| spec.authors = 'Facebook' spec.source = { :git => 'https://github.com/facebook/yoga.git', - :tag => '1.8.0', + :tag => spec.version.to_s, } spec.platforms = { :ios => "8.0", :tvos => "10.0" } spec.module_name = 'yoga' spec.requires_arc = false + spec.pod_target_xcconfig = { + 'DEFINES_MODULE' => 'YES' + } spec.compiler_flags = [ '-fno-omit-frame-pointer', '-fexceptions', diff --git a/YogaKit.podspec b/YogaKit.podspec index e21f6808..59af6974 100644 --- a/YogaKit.podspec +++ b/YogaKit.podspec @@ -1,6 +1,6 @@ podspec = Pod::Spec.new do |spec| spec.name = 'YogaKit' - spec.version = '1.8.1' + spec.version = '1.9.0' spec.license = { :type => 'MIT', :file => "LICENSE" } spec.homepage = 'https://facebook.github.io/yoga/' spec.documentation_url = 'https://facebook.github.io/yoga/docs/api/yogakit/' @@ -11,14 +11,14 @@ podspec = Pod::Spec.new do |spec| spec.authors = 'Facebook' spec.source = { :git => 'https://github.com/facebook/yoga.git', - :tag => '1.7.0', + :tag => spec.version.to_s, } spec.platform = :ios spec.ios.deployment_target = '8.0' spec.ios.frameworks = 'UIKit' - spec.dependency 'Yoga', '~> 1.8.1' + spec.dependency 'Yoga', '~> 1.9' spec.source_files = 'YogaKit/Source/*.{h,m,swift}' spec.public_header_files = 'YogaKit/Source/{YGLayout,UIView+Yoga}.h' spec.private_header_files = 'YogaKit/Source/YGLayout+Private.h' From 4ed3dd4b822232ded081259d5015d496cd5b2674 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 12 Jul 2018 07:55:17 -0700 Subject: [PATCH 10/29] Add `YogaNodeProperties` interface Summary: `YogaNodeProperties` will serve as abstraction over JNI adapters / storage backends in follow-ups. @public Reviewed By: IanChilds Differential Revision: D8818805 fbshipit-source-id: 7998a56daebea60dd13b07228dffdf14be852554 --- .../com/facebook/yoga/YogaNodeProperties.java | 167 ++++++++++++++++++ 1 file changed, 167 insertions(+) create mode 100644 java/com/facebook/yoga/YogaNodeProperties.java diff --git a/java/com/facebook/yoga/YogaNodeProperties.java b/java/com/facebook/yoga/YogaNodeProperties.java new file mode 100644 index 00000000..fbad2ea2 --- /dev/null +++ b/java/com/facebook/yoga/YogaNodeProperties.java @@ -0,0 +1,167 @@ +/* + * Copyright (c) 2018-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +public interface YogaNodeProperties { + + YogaNodeProperties clone(YogaNode node); + + long getNativePointer(); + + void onAfterCalculateLayout(); + + void reset(); + + boolean hasNewLayout(); + + boolean isDirty(); + + void markLayoutSeen(); + + YogaDirection getStyleDirection(); + + void setDirection(YogaDirection direction); + + YogaFlexDirection getFlexDirection(); + + void setFlexDirection(YogaFlexDirection flexDirection); + + YogaJustify getJustifyContent(); + + void setJustifyContent(YogaJustify justifyContent); + + YogaAlign getAlignItems(); + + void setAlignItems(YogaAlign alignItems); + + YogaAlign getAlignSelf(); + + void setAlignSelf(YogaAlign alignSelf); + + YogaAlign getAlignContent(); + + void setAlignContent(YogaAlign alignContent); + + YogaPositionType getPositionType(); + + void setPositionType(YogaPositionType positionType); + + void setWrap(YogaWrap flexWrap); + + YogaOverflow getOverflow(); + + void setOverflow(YogaOverflow overflow); + + YogaDisplay getDisplay(); + + void setDisplay(YogaDisplay display); + + void setFlex(float flex); + + float getFlexGrow(); + + void setFlexGrow(float flexGrow); + + float getFlexShrink(); + + void setFlexShrink(float flexShrink); + + YogaValue getFlexBasis(); + + void setFlexBasis(float flexBasis); + + void setFlexBasisPercent(float percent); + + void setFlexBasisAuto(); + + YogaValue getMargin(YogaEdge edge); + + void setMargin(YogaEdge edge, float margin); + + void setMarginPercent(YogaEdge edge, float percent); + + void setMarginAuto(YogaEdge edge); + + YogaValue getPadding(YogaEdge edge); + + void setPadding(YogaEdge edge, float padding); + + void setPaddingPercent(YogaEdge edge, float percent); + + float getBorder(YogaEdge edge); + + void setBorder(YogaEdge edge, float border); + + YogaValue getPosition(YogaEdge edge); + + void setPosition(YogaEdge edge, float position); + + void setPositionPercent(YogaEdge edge, float percent); + + YogaValue getWidth(); + + void setWidth(float width); + + void setWidthPercent(float percent); + + void setWidthAuto(); + + YogaValue getHeight(); + + void setHeight(float height); + + void setHeightPercent(float percent); + + void setHeightAuto(); + + YogaValue getMinWidth(); + + void setMinWidth(float minWidth); + + void setMinWidthPercent(float percent); + + YogaValue getMinHeight(); + + void setMinHeight(float minHeight); + + void setMinHeightPercent(float percent); + + YogaValue getMaxWidth(); + + void setMaxWidth(float maxWidth); + + void setMaxWidthPercent(float percent); + + YogaValue getMaxHeight(); + + void setMaxHeight(float maxheight); + + void setMaxHeightPercent(float percent); + + float getAspectRatio(); + + void setAspectRatio(float aspectRatio); + + float getLayoutX(); + + float getLayoutY(); + + float getLayoutWidth(); + + float getLayoutHeight(); + + boolean getDoesLegacyStretchFlagAffectsLayout(); + + float getLayoutMargin(YogaEdge edge); + + float getLayoutPadding(YogaEdge edge); + + float getLayoutBorder(YogaEdge edge); + + YogaDirection getLayoutDirection(); +} From e9e2ae28e046758d4e457defdba74955a4b38a8c Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Thu, 12 Jul 2018 08:40:52 -0700 Subject: [PATCH 11/29] Tidy up YGFloatOptional Summary: Just some convention/weird style things. `float` should be passed by value, weird use of ?: operator instead of ||. Reviewed By: priteshrnandgaonkar Differential Revision: D8804407 fbshipit-source-id: e0d67363ccde36ec5bccec7497ed0ffd364b3fcf --- yoga/YGFloatOptional.cpp | 33 ++++++++++++--------------------- yoga/YGFloatOptional.h | 25 +++++++++++++++---------- 2 files changed, 27 insertions(+), 31 deletions(-) diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index 00bfc71e..ceee1dc2 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -1,16 +1,16 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGFloatOptional.h" #include #include #include "Yoga.h" -YGFloatOptional::YGFloatOptional(const float& value) { +YGFloatOptional::YGFloatOptional(float value) { if (YGFloatIsUndefined(value)) { isUndefined_ = true; value_ = 0; @@ -31,18 +31,9 @@ const float& YGFloatOptional::getValue() const { return value_; } -void YGFloatOptional::setValue(const float& val) { - value_ = val; - isUndefined_ = false; -} - -const bool& YGFloatOptional::isUndefined() const { - return isUndefined_; -} - bool YGFloatOptional::operator==(const YGFloatOptional& op) const { if (isUndefined_ == op.isUndefined()) { - return isUndefined_ ? true : value_ == op.getValue(); + return isUndefined_ || value_ == op.getValue(); } return false; } @@ -51,14 +42,14 @@ bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { return !(*this == op); } -bool YGFloatOptional::operator==(const float& val) const { +bool YGFloatOptional::operator==(float val) const { if (YGFloatIsUndefined(val) == isUndefined_) { - return isUndefined_ ? true : val == value_; + return isUndefined_ || val == value_; } return false; } -bool YGFloatOptional::operator!=(const float& val) const { +bool YGFloatOptional::operator!=(float val) const { return !(*this == val); } @@ -84,9 +75,9 @@ bool YGFloatOptional::operator<(const YGFloatOptional& op) const { } bool YGFloatOptional::operator>=(const YGFloatOptional& op) const { - return *this == op ? true : *this > op; + return *this == op || *this > op; } bool YGFloatOptional::operator<=(const YGFloatOptional& op) const { - return *this == op ? true : *this < op; + return *this == op || *this < op; } diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index 21af2a80..d426d849 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #pragma once struct YGFloatOptional { @@ -13,7 +13,7 @@ struct YGFloatOptional { bool isUndefined_; public: - explicit YGFloatOptional(const float& value); + explicit YGFloatOptional(float value); explicit YGFloatOptional(); // Program will terminate if the value of an undefined is accessed. Please @@ -22,9 +22,14 @@ struct YGFloatOptional { const float& getValue() const; // Sets the value of float optional, and thus isUndefined is assigned false. - void setValue(const float& val); + void setValue(float val) { + value_ = val; + isUndefined_ = false; + } - const bool& isUndefined() const; + bool isUndefined() const { + return isUndefined_; + } YGFloatOptional operator+(const YGFloatOptional& op); bool operator>(const YGFloatOptional& op) const; @@ -34,6 +39,6 @@ struct YGFloatOptional { bool operator==(const YGFloatOptional& op) const; bool operator!=(const YGFloatOptional& op) const; - bool operator==(const float& val) const; - bool operator!=(const float& val) const; + bool operator==(float val) const; + bool operator!=(float val) const; }; From 0b1780a081ba4167030eac847c18737bca1cc2c8 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:46 -0700 Subject: [PATCH 12/29] YGNode::getChildren() should return const ref Summary: It's wasteful to do it by value. I'm fairly sure this is safe, especially because https://github.com/facebook/yoga/commit/fbd332dee86237cae6f9c9bae8ea9a7bbe7c7d87#diff-ade2a4bbd6582e2898cbd9e0fa142ab5R215 shows that we did access by reference before. Reviewed By: priteshrnandgaonkar, davidaurelio Differential Revision: D8822697 fbshipit-source-id: 791bcf0fa37453f67795af727c85c8adce3b0f69 --- yoga/YGNode.h | 6 +----- yoga/Yoga.cpp | 8 ++++---- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/yoga/YGNode.h b/yoga/YGNode.h index ab302e06..c204d460 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -122,14 +122,10 @@ struct YGNode { return getOwner(); } - YGVector getChildren() const { + const YGVector& getChildren() const { return children_; } - uint32_t getChildrenCount() const { - return static_cast(children_.size()); - } - YGNodeRef getChild(uint32_t index) const { return children_.at(index); } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 5b5a9088..df186c7c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -264,7 +264,7 @@ static YGNodeRef YGNodeDeepClone(YGNodeRef oldNode) { YGVector vec = YGVector(); vec.reserve(oldNode->getChildren().size()); YGNodeRef childNode = nullptr; - for (auto& item : oldNode->getChildren()) { + for (auto* item : oldNode->getChildren()) { childNode = YGNodeDeepClone(item); childNode->setOwner(node); vec.push_back(childNode); @@ -301,8 +301,8 @@ static void YGConfigFreeRecursive(const YGNodeRef root) { delete root->getConfig(); } // Delete configs recursively for childrens - for (uint32_t i = 0; i < root->getChildrenCount(); ++i) { - YGConfigFreeRecursive(root->getChild(i)); + for (auto* child : root->getChildren()) { + YGConfigFreeRecursive(child); } } @@ -1868,7 +1868,7 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues( // Add items to the current line until it's full or we run out of items. uint32_t endOfLineIndex = startOfLineIndex; - for (; endOfLineIndex < node->getChildrenCount(); endOfLineIndex++) { + for (; endOfLineIndex < node->getChildren().size(); endOfLineIndex++) { const YGNodeRef child = node->getChild(endOfLineIndex); if (child->getStyle().display == YGDisplayNone || child->getStyle().positionType == YGPositionTypeAbsolute) { From 2562c029b1cf95e8119eaf6505bed224d3c1ec6b Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:49 -0700 Subject: [PATCH 13/29] Tidy up YGFloatOptional further Summary: I missed these two things: inline default ctor, getValue() should return a float. Reviewed By: priteshrnandgaonkar Differential Revision: D8826640 fbshipit-source-id: e6324dea0268ef276e6fa1722e72dffb5241e676 --- yoga/YGFloatOptional.cpp | 4 +--- yoga/YGFloatOptional.h | 4 ++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index ceee1dc2..d3407fa2 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -20,9 +20,7 @@ YGFloatOptional::YGFloatOptional(float value) { } } -YGFloatOptional::YGFloatOptional() : value_(0), isUndefined_(true) {} - -const float& YGFloatOptional::getValue() const { +float YGFloatOptional::getValue() const { if (isUndefined_) { // Abort, accessing a value of an undefined float optional std::cerr << "Tried to get value of an undefined YGFloatOptional\n"; diff --git a/yoga/YGFloatOptional.h b/yoga/YGFloatOptional.h index d426d849..114f3577 100644 --- a/yoga/YGFloatOptional.h +++ b/yoga/YGFloatOptional.h @@ -14,12 +14,12 @@ struct YGFloatOptional { public: explicit YGFloatOptional(float value); - explicit YGFloatOptional(); + explicit YGFloatOptional() : value_(0), isUndefined_(true) {} // Program will terminate if the value of an undefined is accessed. Please // make sure to check if the optional is defined before calling this function. // To check if float optional is defined, use `isUndefined()`. - const float& getValue() const; + float getValue() const; // Sets the value of float optional, and thus isUndefined is assigned false. void setValue(float val) { From 910aa77c0189bce6cc7d45875aeb7c080407171d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Fri, 13 Jul 2018 12:34:51 -0700 Subject: [PATCH 14/29] Remove some unnecessary `const float &` uses Summary: Holding floats by reference is unnecessary at best and may be detrimental to performance. Reviewed By: davidaurelio Differential Revision: D8826496 fbshipit-source-id: 2391f8aa26ebfbb440f6e4b7d57975be688f791c --- yoga/Yoga.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index df186c7c..1ea109e2 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -1249,9 +1249,9 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, childWidthMeasureMode = YGMeasureModeUndefined; childHeightMeasureMode = YGMeasureModeUndefined; - const float& marginRow = YGUnwrapFloatOptional( + auto marginRow = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); - const float& marginColumn = YGUnwrapFloatOptional( + auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); if (isRowStyleDimDefined) { @@ -1377,9 +1377,9 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGMeasureMode childWidthMeasureMode = YGMeasureModeUndefined; YGMeasureMode childHeightMeasureMode = YGMeasureModeUndefined; - const float& marginRow = + auto marginRow = YGUnwrapFloatOptional(child->getMarginForAxis(YGFlexDirectionRow, width)); - const float& marginColumn = YGUnwrapFloatOptional( + auto marginColumn = YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionColumn, width)); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { @@ -1679,9 +1679,9 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) || (widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) { - const float& marginAxisColumn = YGUnwrapFloatOptional( + auto marginAxisColumn = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); - const float& marginAxisRow = YGUnwrapFloatOptional( + auto marginAxisRow = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionRow, ownerWidth)); node->setLayoutMeasuredDimension( From 896cfbdfdedc3a0ed0a95357173704bde8f5a7f2 Mon Sep 17 00:00:00 2001 From: Taras Tsugrii Date: Sat, 14 Jul 2018 00:14:58 -0700 Subject: [PATCH 15/29] Skylarkify yoga build defs. Summary: Top-level `if` statements are not allowed in a new Buck parser - Skylark. https://buckbuild.com/concept/skylark.html Reviewed By: grzmiel Differential Revision: D8849590 fbshipit-source-id: 6648135f23e058adfeddf574932f8a98c7831fee --- csharp/BUCK | 48 +++++++++--------------------------------------- yoga_defs.bzl | 40 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 39 deletions(-) diff --git a/csharp/BUCK b/csharp/BUCK index d29f35a3..e679803a 100644 --- a/csharp/BUCK +++ b/csharp/BUCK @@ -3,7 +3,14 @@ # This source code is licensed under the MIT license found in the # LICENSE file in the root directory of this source tree. -load("//:yoga_defs.bzl", "BASE_COMPILER_FLAGS", "is_apple_platform", "yoga_cxx_library", "yoga_dep") +load( + "//:yoga_defs.bzl", + "BASE_COMPILER_FLAGS", + "is_apple_platform", + "yoga_cxx_library", + "yoga_dep", + "yoga_apple_binary", +) COMPILER_FLAGS = BASE_COMPILER_FLAGS + ["-std=c++11"] @@ -32,41 +39,4 @@ yoga_cxx_library( deps = [yoga_dep(":yoga")], ) -if is_apple_platform(): - yoganet_ios_srcs = [] - for arch in [ - "iphonesimulator-x86_64", - "iphoneos-arm64", - ]: - name = "yoganet-" + arch - yoganet_ios_srcs.append(":" + name) - genrule( - name = name, - srcs = [ - yoga_dep(":yogaApple#%s,static" % arch), - yoga_dep("YogaKit:YogaKitApple#%s,static" % arch), - yoga_dep("csharp:yoganetApple#%s,static" % arch), - ], - out = "libyoga-%s.a" % arch, - cmd = "libtool -static -o $OUT $SRCS", - visibility = [yoga_dep("csharp:yoganet-ios")], - ) - - genrule( - name = "yoganet-ios", - srcs = yoganet_ios_srcs, - out = "libyoga.a", - cmd = "lipo $SRCS -create -output $OUT", - visibility = ["PUBLIC"], - ) - - yoganet_macosx_target = "csharp:yoganetAppleMac#macosx-%s,dynamic" - genrule( - name = "yoganet-macosx", - srcs = [ - yoga_dep(yoganet_macosx_target % "x86_64"), - ], - out = "libyoga.dylib", - cmd = "lipo $SRCS -create -output $OUT", - visibility = ["PUBLIC"], - ) +yoga_apple_binary() diff --git a/yoga_defs.bzl b/yoga_defs.bzl index 9f33a825..1a574c04 100644 --- a/yoga_defs.bzl +++ b/yoga_defs.bzl @@ -190,3 +190,43 @@ def yoga_prebuilt_jar(*args, **kwargs): def is_apple_platform(): return True + +def yoga_apple_binary(): + if is_apple_platform(): + yoganet_ios_srcs = [] + for arch in [ + "iphonesimulator-x86_64", + "iphoneos-arm64", + ]: + name = "yoganet-" + arch + yoganet_ios_srcs.append(":" + name) + native.genrule( + name = name, + srcs = [ + yoga_dep(":yogaApple#%s,static" % arch), + yoga_dep("YogaKit:YogaKitApple#%s,static" % arch), + yoga_dep("csharp:yoganetApple#%s,static" % arch), + ], + out = "libyoga-%s.a" % arch, + cmd = "libtool -static -o $OUT $SRCS", + visibility = [yoga_dep("csharp:yoganet-ios")], + ) + + native.genrule( + name = "yoganet-ios", + srcs = yoganet_ios_srcs, + out = "libyoga.a", + cmd = "lipo $SRCS -create -output $OUT", + visibility = ["PUBLIC"], + ) + + yoganet_macosx_target = "csharp:yoganetAppleMac#macosx-%s,dynamic" + native.genrule( + name = "yoganet-macosx", + srcs = [ + yoga_dep(yoganet_macosx_target % "x86_64"), + ], + out = "libyoga.dylib", + cmd = "lipo $SRCS -create -output $OUT", + visibility = ["PUBLIC"], + ) From 1b32c4f0546cabcc0d71a09bbca44eab8fbfe317 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 18 Jul 2018 00:57:52 -0700 Subject: [PATCH 16/29] Lint Utils.cpp YGLayout.cpp YGNode.cpp Yoga-internal.h Summary: @public Auto-fixes formatting of YGLayout.cpp YGNode.cpp Yoga-internal.h Reviewed By: astreet Differential Revision: D8875514 fbshipit-source-id: 38d709831349c4ad015f20451421aea89fc6f007 --- yoga/Utils.cpp | 10 +++++----- yoga/YGLayout.cpp | 10 +++++----- yoga/YGNode.cpp | 14 ++++++-------- yoga/Yoga-internal.h | 20 ++++++++++---------- 4 files changed, 26 insertions(+), 28 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 6fa8df82..5f6c960d 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "Utils.h" YGFlexDirection YGFlexDirectionCross( diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index 6e367bd5..604d7109 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGLayout.h" #include "Utils.h" diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 13571a9d..9e7a182b 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGNode.h" #include #include "Utils.h" @@ -97,8 +97,6 @@ YGFloatOptional YGNode::getMarginForAxis( // Setters - - void YGNode::setMeasureFunc(YGMeasureFunc measureFunc) { if (measureFunc == nullptr) { measure_ = nullptr; @@ -396,7 +394,7 @@ void YGNode::resolveDimension() { YGDirection YGNode::resolveDirection(const YGDirection ownerDirection) { if (style_.direction == YGDirectionInherit) { return ownerDirection > YGDirectionInherit ? ownerDirection - : YGDirectionLTR; + : YGDirectionLTR; } else { return style_.direction; } diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index be1d9632..84c4596b 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -16,10 +16,11 @@ using YGVector = std::vector; YG_EXTERN_C_BEGIN -WIN_EXPORT float YGRoundValueToPixelGrid(const float value, - const float pointScaleFactor, - const bool forceCeil, - const bool forceFloor); +WIN_EXPORT float YGRoundValueToPixelGrid( + const float value, + const float pointScaleFactor, + const bool forceCeil, + const bool forceFloor); YG_EXTERN_C_END @@ -87,7 +88,6 @@ struct YGCachedMeasurement { // layouts should not require more than 16 entries to fit within the cache. #define YG_MAX_CACHED_RESULT_COUNT 16 - static const float kDefaultFlexGrow = 0.0f; static const float kDefaultFlexShrink = 0.0f; static const float kWebDefaultFlexShrink = 1.0f; From c1a9f6120a92bb6b1f1fa4306e45a3b30e1f2333 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Wed, 18 Jul 2018 02:23:58 -0700 Subject: [PATCH 17/29] Make `YGFloatIsUndefined` inlineable Summary: @public Makes `YGFloatIsUndefined` inlineable Reviewed By: swolchok Differential Revision: D8875520 fbshipit-source-id: 7ac653e002512b1a8d5f9c04e0a21381aeb02e67 --- yoga/Utils.cpp | 18 ++++++++++-------- yoga/YGFloatOptional.cpp | 7 +++++-- yoga/YGLayout.cpp | 10 ++++++---- yoga/YGNode.cpp | 6 ++++-- yoga/Yoga-internal.h | 36 ++++++++++++++++++++++++++++-------- yoga/Yoga.cpp | 10 +--------- 6 files changed, 54 insertions(+), 33 deletions(-) diff --git a/yoga/Utils.cpp b/yoga/Utils.cpp index 5f6c960d..83995221 100644 --- a/yoga/Utils.cpp +++ b/yoga/Utils.cpp @@ -7,6 +7,8 @@ */ #include "Utils.h" +using namespace facebook; + YGFlexDirection YGFlexDirectionCross( const YGFlexDirection flexDirection, const YGDirection direction) { @@ -16,18 +18,18 @@ YGFlexDirection YGFlexDirectionCross( } float YGFloatMax(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fmaxf(a, b); } - return YGFloatIsUndefined(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } float YGFloatMin(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fminf(a, b); } - return YGFloatIsUndefined(a) ? b : a; + return yoga::isUndefined(a) ? b : a; } bool YGValueEqual(const YGValue a, const YGValue b) { @@ -36,7 +38,7 @@ bool YGValueEqual(const YGValue a, const YGValue b) { } if (a.unit == YGUnitUndefined || - (YGFloatIsUndefined(a.value) && YGFloatIsUndefined(b.value))) { + (yoga::isUndefined(a.value) && yoga::isUndefined(b.value))) { return true; } @@ -44,14 +46,14 @@ bool YGValueEqual(const YGValue a, const YGValue b) { } bool YGFloatsEqual(const float a, const float b) { - if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) { + if (!yoga::isUndefined(a) && !yoga::isUndefined(b)) { return fabs(a - b) < 0.0001f; } - return YGFloatIsUndefined(a) && YGFloatIsUndefined(b); + return yoga::isUndefined(a) && yoga::isUndefined(b); } float YGFloatSanitize(const float& val) { - return YGFloatIsUndefined(val) ? 0 : val; + return yoga::isUndefined(val) ? 0 : val; } float YGUnwrapFloatOptional(const YGFloatOptional& op) { diff --git a/yoga/YGFloatOptional.cpp b/yoga/YGFloatOptional.cpp index d3407fa2..cb867f3a 100644 --- a/yoga/YGFloatOptional.cpp +++ b/yoga/YGFloatOptional.cpp @@ -9,9 +9,12 @@ #include #include #include "Yoga.h" +#include "Yoga-internal.h" + +using namespace facebook; YGFloatOptional::YGFloatOptional(float value) { - if (YGFloatIsUndefined(value)) { + if (yoga::isUndefined(value)) { isUndefined_ = true; value_ = 0; } else { @@ -41,7 +44,7 @@ bool YGFloatOptional::operator!=(const YGFloatOptional& op) const { } bool YGFloatOptional::operator==(float val) const { - if (YGFloatIsUndefined(val) == isUndefined_) { + if (yoga::isUndefined(val) == isUndefined_) { return isUndefined_ || val == value_; } return false; diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index 604d7109..dfd7be08 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -8,6 +8,8 @@ #include "YGLayout.h" #include "Utils.h" +using namespace facebook; + const std::array kYGDefaultDimensionValues = { {YGUndefined, YGUndefined}}; @@ -46,13 +48,13 @@ bool YGLayout::operator==(YGLayout layout) const { isEqual = isEqual && cachedMeasurements[i] == layout.cachedMeasurements[i]; } - if (!YGFloatIsUndefined(measuredDimensions[0]) || - !YGFloatIsUndefined(layout.measuredDimensions[0])) { + if (!yoga::isUndefined(measuredDimensions[0]) || + !yoga::isUndefined(layout.measuredDimensions[0])) { isEqual = isEqual && (measuredDimensions[0] == layout.measuredDimensions[0]); } - if (!YGFloatIsUndefined(measuredDimensions[1]) || - !YGFloatIsUndefined(layout.measuredDimensions[1])) { + if (!yoga::isUndefined(measuredDimensions[1]) || + !yoga::isUndefined(layout.measuredDimensions[1])) { isEqual = isEqual && (measuredDimensions[1] == layout.measuredDimensions[1]); } diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 9e7a182b..70dd655d 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -9,6 +9,8 @@ #include #include "Utils.h" +using namespace facebook; + YGFloatOptional YGNode::getLeadingPosition( const YGFlexDirection& axis, const float& axisSize) const { @@ -500,7 +502,7 @@ bool YGNode::isNodeFlexible() { float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { if (YGFlexDirectionIsRow(axis) && style_.border[YGEdgeStart].unit != YGUnitUndefined && - !YGFloatIsUndefined(style_.border[YGEdgeStart].value) && + !yoga::isUndefined(style_.border[YGEdgeStart].value) && style_.border[YGEdgeStart].value >= 0.0f) { return style_.border[YGEdgeStart].value; } @@ -513,7 +515,7 @@ float YGNode::getLeadingBorder(const YGFlexDirection& axis) const { float YGNode::getTrailingBorder(const YGFlexDirection& flexDirection) const { if (YGFlexDirectionIsRow(flexDirection) && style_.border[YGEdgeEnd].unit != YGUnitUndefined && - !YGFloatIsUndefined(style_.border[YGEdgeEnd].value) && + !yoga::isUndefined(style_.border[YGEdgeEnd].value) && style_.border[YGEdgeEnd].value >= 0.0f) { return style_.border[YGEdgeEnd].value; } diff --git a/yoga/Yoga-internal.h b/yoga/Yoga-internal.h index 84c4596b..941147e8 100644 --- a/yoga/Yoga-internal.h +++ b/yoga/Yoga-internal.h @@ -24,6 +24,26 @@ WIN_EXPORT float YGRoundValueToPixelGrid( YG_EXTERN_C_END +namespace facebook { +namespace yoga { + +inline bool isUndefined(float value) { + // Value of a float in the case of it being not defined is 10.1E20. Earlier + // it used to be NAN, the benefit of which was that if NAN is involved in any + // mathematical expression the result was NAN. But since we want to have + // `-ffast-math` flag being used by compiler which assumes that the floating + // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But + // now if YGUndefined is involved in any mathematical operations this + // value(10.1E20) would change. So the following check makes sure that if the + // value is outside a range (-10E8, 10E8) then it is undefined. + return value >= 10E8 || value <= -10E8; +} + +} // namespace yoga +} // namespace facebook + +using namespace facebook; + extern const std::array trailing; extern const std::array leading; extern bool YGValueEqual(const YGValue a, const YGValue b); @@ -63,20 +83,20 @@ struct YGCachedMeasurement { bool isEqual = widthMeasureMode == measurement.widthMeasureMode && heightMeasureMode == measurement.heightMeasureMode; - if (!YGFloatIsUndefined(availableWidth) || - !YGFloatIsUndefined(measurement.availableWidth)) { + if (!yoga::isUndefined(availableWidth) || + !yoga::isUndefined(measurement.availableWidth)) { isEqual = isEqual && availableWidth == measurement.availableWidth; } - if (!YGFloatIsUndefined(availableHeight) || - !YGFloatIsUndefined(measurement.availableHeight)) { + if (!yoga::isUndefined(availableHeight) || + !yoga::isUndefined(measurement.availableHeight)) { isEqual = isEqual && availableHeight == measurement.availableHeight; } - if (!YGFloatIsUndefined(computedWidth) || - !YGFloatIsUndefined(measurement.computedWidth)) { + if (!yoga::isUndefined(computedWidth) || + !yoga::isUndefined(measurement.computedWidth)) { isEqual = isEqual && computedWidth == measurement.computedWidth; } - if (!YGFloatIsUndefined(computedHeight) || - !YGFloatIsUndefined(measurement.computedHeight)) { + if (!yoga::isUndefined(computedHeight) || + !yoga::isUndefined(measurement.computedHeight)) { isEqual = isEqual && computedHeight == measurement.computedHeight; } diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index 1ea109e2..fe419207 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -104,15 +104,7 @@ static int YGDefaultLog(const YGConfigRef config, #endif bool YGFloatIsUndefined(const float value) { - // Value of a float in the case of it being not defined is 10.1E20. Earlier - // it used to be NAN, the benefit of which was that if NAN is involved in any - // mathematical expression the result was NAN. But since we want to have - // `-ffast-math` flag being used by compiler which assumes that the floating - // point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But - // now if YGUndefined is involved in any mathematical operations this - // value(10.1E20) would change. So the following check makes sure that if the - // value is outside a range (-10E8, 10E8) then it is undefined. - return value >= 10E8 || value <= -10E8; + return facebook::yoga::isUndefined(value); } const YGValue* YGComputedEdgeValue( From 4c47dcbd0f4446d504d94de3e10aa5e2e6444a8d Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 18 Jul 2018 15:45:34 -0700 Subject: [PATCH 18/29] Delete YGNode ctor w/arg per member Summary: It doesn't seem to be used internally, it hurts greppability, and there are setters for these properties as needed anyway. Reviewed By: davidaurelio Differential Revision: D8842084 fbshipit-source-id: f0275b490e585ea94df341c97c34b441ed91c4fb --- yoga/YGNode.cpp | 32 -------------------------------- yoga/YGNode.h | 16 ---------------- 2 files changed, 48 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index 70dd655d..dda20a55 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -292,38 +292,6 @@ YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { config_ = newConfig; } -YGNode::YGNode( - void* context, - YGPrintFunc print, - bool hasNewLayout, - YGNodeType nodeType, - YGMeasureFunc measure, - YGBaselineFunc baseline, - YGDirtiedFunc dirtied, - YGStyle style, - const YGLayout& layout, - uint32_t lineIndex, - YGNodeRef owner, - const YGVector& children, - YGConfigRef config, - bool isDirty, - std::array resolvedDimensions) - : context_(context), - print_(print), - hasNewLayout_(hasNewLayout), - nodeType_(nodeType), - measure_(measure), - baseline_(baseline), - dirtied_(dirtied), - style_(style), - layout_(layout), - lineIndex_(lineIndex), - owner_(owner), - children_(children), - config_(config), - isDirty_(isDirty), - resolvedDimensions_(resolvedDimensions) {} - YGNode& YGNode::operator=(const YGNode& node) { if (&node == this) { return *this; diff --git a/yoga/YGNode.h b/yoga/YGNode.h index c204d460..cba72163 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -40,22 +40,6 @@ struct YGNode { explicit YGNode(const YGConfigRef newConfig); YGNode(const YGNode& node); YGNode& operator=(const YGNode& node); - YGNode( - void* context, - YGPrintFunc print, - bool hasNewLayout, - YGNodeType nodeType, - YGMeasureFunc measure, - YGBaselineFunc baseline, - YGDirtiedFunc dirtied, - YGStyle style, - const YGLayout& layout, - uint32_t lineIndex, - YGNodeRef owner, - const YGVector& children, - YGConfigRef config, - bool isDirty, - std::array resolvedDimensions); // Getters void* getContext() const { From 0bc4d23e2e7f942e0699b3bd6ac31660698e0e85 Mon Sep 17 00:00:00 2001 From: Scott Wolchok Date: Wed, 18 Jul 2018 15:45:36 -0700 Subject: [PATCH 19/29] Explicitly default YGNode copy ctor Summary: No need to type out the old version. This is exactly equivalent (unless I've misread and the old version did something other than memberwise copy). Reviewed By: davidaurelio Differential Revision: D8842326 fbshipit-source-id: c575ea4cee6caef9ea15aaf5967597385ed26ec3 --- yoga/YGNode.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index dda20a55..fc97e172 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -271,22 +271,7 @@ YGNode::YGNode() isDirty_(false), resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} -YGNode::YGNode(const YGNode& node) - : context_(node.context_), - print_(node.print_), - hasNewLayout_(node.hasNewLayout_), - nodeType_(node.nodeType_), - measure_(node.measure_), - baseline_(node.baseline_), - dirtied_(node.dirtied_), - style_(node.style_), - layout_(node.layout_), - lineIndex_(node.lineIndex_), - owner_(node.owner_), - children_(node.children_), - config_(node.config_), - isDirty_(node.isDirty_), - resolvedDimensions_(node.resolvedDimensions_) {} +YGNode::YGNode(const YGNode& node) = default; YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { config_ = newConfig; From 51a4601e18b5dabd70245fbb5e08190a40a99dea Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 06:43:06 -0700 Subject: [PATCH 20/29] Update soloader to 0.5.1 Summary: There's been a breaking change in 0.5 and old versions are ABI-incompatible with new ones. Reviewed By: muraziz Differential Revision: D8913456 fbshipit-source-id: 89221c5ac95c7c2197083a5390403c72e7e33af1 --- java/build.gradle | 2 +- lib/fb/build.gradle | 2 +- lib/soloader/BUCK | 2 +- lib/soloader/soloader-0.1.0.aar | Bin 41801 -> 0 bytes lib/soloader/soloader-0.5.1.aar | Bin 0 -> 58583 bytes 5 files changed, 3 insertions(+), 3 deletions(-) delete mode 100644 lib/soloader/soloader-0.1.0.aar create mode 100644 lib/soloader/soloader-0.5.1.aar diff --git a/java/build.gradle b/java/build.gradle index da30fe9b..21034e42 100644 --- a/java/build.gradle +++ b/java/build.gradle @@ -52,7 +52,7 @@ android { dependencies { compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') - implementation 'com.facebook.soloader:soloader:0.2.0' + implementation 'com.facebook.soloader:soloader:0.5.1' testImplementation 'junit:junit:4.12' } diff --git a/lib/fb/build.gradle b/lib/fb/build.gradle index 7a419b0b..fde3f88a 100644 --- a/lib/fb/build.gradle +++ b/lib/fb/build.gradle @@ -26,7 +26,7 @@ android { } dependencies { - implementation 'com.facebook.soloader:soloader:0.2.0' + implementation 'com.facebook.soloader:soloader:0.5.1' compileOnly 'com.google.code.findbugs:jsr305:3.0.1' compileOnly project(':yoga:proguard-annotations') } diff --git a/lib/soloader/BUCK b/lib/soloader/BUCK index 595c35eb..7ab9627f 100644 --- a/lib/soloader/BUCK +++ b/lib/soloader/BUCK @@ -7,6 +7,6 @@ load("//:yoga_defs.bzl", "YOGA_ROOTS") android_prebuilt_aar( name = "soloader", - aar = "soloader-0.1.0.aar", + aar = "soloader-0.5.1.aar", visibility = YOGA_ROOTS, ) diff --git a/lib/soloader/soloader-0.1.0.aar b/lib/soloader/soloader-0.1.0.aar deleted file mode 100644 index 497494a925fac15188520c32e25417fef4c58c8a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 41801 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
K!~cZ(eNd=n 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 literal 0 HcmV?d00001 From 5e1796505d8cf9113ad9e176f71c3d8862caa00e Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 09:00:03 -0700 Subject: [PATCH 21/29] v1.9.0 Summary: New release against soloader ~0.5.0. Reviewed By: muraziz Differential Revision: D8914103 fbshipit-source-id: b1eb3f608ac7cf3791fefe88e596383483ae3474 --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index 85411523..d645737a 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1536M -VERSION_NAME=1.8.1-SNAPSHOT +VERSION_NAME=1.9.0 POM_URL=https://github.com/facebook/yoga POM_SCM_URL=https://github.com/facebook/yoga.git POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git From 7be9fd1a795f6a83827f2f5e959d469a97904a79 Mon Sep 17 00:00:00 2001 From: Pascal Hartig Date: Thu, 19 Jul 2018 09:00:05 -0700 Subject: [PATCH 22/29] 1.9.1-SNAPSHOT Summary: Reenable snapshot releases. Reviewed By: muraziz Differential Revision: D8914105 fbshipit-source-id: f9fcd74912f3ef2f9fb94ec832c41353e3f890bb --- gradle.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle.properties b/gradle.properties index d645737a..51ca14c1 100644 --- a/gradle.properties +++ b/gradle.properties @@ -2,7 +2,7 @@ org.gradle.jvmargs=-Xmx1536M -VERSION_NAME=1.9.0 +VERSION_NAME=1.9.1-SNAPSHOT POM_URL=https://github.com/facebook/yoga POM_SCM_URL=https://github.com/facebook/yoga.git POM_SCM_CONNECTION=scm:git:https://github.com/facebook/yoga.git From f172d5d41c6f5a5e35c6fee949e62c8192770e4b Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:51:23 -0700 Subject: [PATCH 23/29] auto-lint YGLayout.h YGNode.h YGStyle.cpp YGStyle.h Summary: @public automatically applies lint fixes to YGLayout.h YGNode.h YGStyle.cpp YGStyle.h Reviewed By: astreet Differential Revision: D8913432 fbshipit-source-id: 488bf25db041ddb527565c26c1762c6ee4cae736 --- yoga/YGLayout.h | 10 +++++----- yoga/YGNode.h | 49 ++++++++++++++++++++++++------------------------ yoga/YGStyle.cpp | 10 +++++----- yoga/YGStyle.h | 10 +++++----- 4 files changed, 40 insertions(+), 39 deletions(-) diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index 46ca130d..ebd93433 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "YGFloatOptional.h" #include "Yoga-internal.h" diff --git a/yoga/YGNode.h b/yoga/YGNode.h index cba72163..b02c02cb 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "YGConfig.h" @@ -53,23 +53,23 @@ struct YGNode { bool getHasNewLayout() const { return hasNewLayout_; } - + YGNodeType getNodeType() const { return nodeType_; } - + YGMeasureFunc getMeasure() const { return measure_; } - + YGBaselineFunc getBaseline() const { return baseline_; } - + YGDirtiedFunc getDirtied() const { return dirtied_; } - + // For Performance reasons passing as reference. YGStyle& getStyle() { return style_; @@ -87,11 +87,11 @@ struct YGNode { const YGLayout& getLayout() const { return layout_; } - + uint32_t getLineIndex() const { return lineIndex_; } - + // returns the YGNodeRef that owns this YGNode. An owner is used to identify // the YogaTree that a YGNode belongs to. // This method will return the parent of the YGNode when a YGNode only belongs @@ -100,16 +100,16 @@ struct YGNode { YGNodeRef getOwner() const { return owner_; } - + // Deprecated, use getOwner() instead. YGNodeRef getParent() const { return getOwner(); } - + const YGVector& getChildren() const { return children_; } - + YGNodeRef getChild(uint32_t index) const { return children_.at(index); } @@ -117,21 +117,22 @@ struct YGNode { YGConfigRef getConfig() const { return config_; } - + bool isDirty() const { return isDirty_; } - + std::array getResolvedDimensions() const { return resolvedDimensions_; } - + YGValue getResolvedDimension(int index) const { return resolvedDimensions_[index]; } // Methods related to positions, margin, padding and border - YGFloatOptional getLeadingPosition(const YGFlexDirection& axis, + YGFloatOptional getLeadingPosition( + const YGFlexDirection& axis, const float& axisSize) const; bool isLeadingPositionDefined(const YGFlexDirection& axis) const; bool isTrailingPosDefined(const YGFlexDirection& axis) const; @@ -174,7 +175,7 @@ struct YGNode { void setHasNewLayout(bool hasNewLayout) { hasNewLayout_ = hasNewLayout; } - + void setNodeType(YGNodeType nodeType) { nodeType_ = nodeType; } @@ -200,15 +201,15 @@ struct YGNode { void setStyle(const YGStyle& style) { style_ = style; } - + void setLayout(const YGLayout& layout) { layout_ = layout; } - + void setLineIndex(uint32_t lineIndex) { lineIndex_ = lineIndex; } - + void setOwner(YGNodeRef owner) { owner_ = owner; } @@ -218,7 +219,7 @@ struct YGNode { } // TODO: rvalue override for setChildren - + void setConfig(YGConfigRef config) { config_ = config; } diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 7664dcf8..738d36fb 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. */ - #include "YGStyle.h" const YGValue kYGValueUndefined = {0, YGUnitUndefined}; diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index f0f97bd8..b18ac0a6 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 "YGFloatOptional.h" #include "Yoga-internal.h" From f95e3b49e9c19e1e4f925955cf358ffdf4e90630 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:51:25 -0700 Subject: [PATCH 24/29] inline trivial constructors / methods Summary: @public inlines some trivial constructors, destructors, and methods. Reviewed By: astreet Differential Revision: D8912691 fbshipit-source-id: 79840ef3322676deebed99391390d6c1796963b5 --- yoga/YGLayout.cpp | 4 ---- yoga/YGLayout.h | 4 +++- yoga/YGNode.cpp | 28 ---------------------------- yoga/YGNode.h | 39 ++++++++++++++++++++------------------- yoga/YGStyle.cpp | 6 ------ yoga/YGStyle.h | 8 +++++--- 6 files changed, 28 insertions(+), 61 deletions(-) diff --git a/yoga/YGLayout.cpp b/yoga/YGLayout.cpp index dfd7be08..03933ac9 100644 --- a/yoga/YGLayout.cpp +++ b/yoga/YGLayout.cpp @@ -61,7 +61,3 @@ bool YGLayout::operator==(YGLayout layout) const { return isEqual; } - -bool YGLayout::operator!=(YGLayout layout) const { - return !(*this == layout); -} diff --git a/yoga/YGLayout.h b/yoga/YGLayout.h index ebd93433..1df905d0 100644 --- a/yoga/YGLayout.h +++ b/yoga/YGLayout.h @@ -38,5 +38,7 @@ struct YGLayout { YGLayout(); bool operator==(YGLayout layout) const; - bool operator!=(YGLayout layout) const; + bool operator!=(YGLayout layout) const { + return !(*this == layout); + } }; diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index fc97e172..a80484f1 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -254,29 +254,6 @@ void YGNode::setPosition( trailing[crossAxis]); } -YGNode::YGNode() - : context_(nullptr), - print_(nullptr), - hasNewLayout_(true), - nodeType_(YGNodeTypeDefault), - measure_(nullptr), - baseline_(nullptr), - dirtied_(nullptr), - style_(YGStyle()), - layout_(YGLayout()), - lineIndex_(0), - owner_(nullptr), - children_(YGVector()), - config_(nullptr), - isDirty_(false), - resolvedDimensions_({{YGValueUndefined, YGValueUndefined}}) {} - -YGNode::YGNode(const YGNode& node) = default; - -YGNode::YGNode(const YGConfigRef newConfig) : YGNode() { - config_ = newConfig; -} - YGNode& YGNode::operator=(const YGNode& node) { if (&node == this) { return *this; @@ -360,11 +337,6 @@ void YGNode::clearChildren() { children_.shrink_to_fit(); } -YGNode::~YGNode() { - // All the member variables are deallocated externally, so no need to - // deallocate here -} - // Other Methods void YGNode::cloneChildrenIfNeeded() { diff --git a/yoga/YGNode.h b/yoga/YGNode.h index b02c02cb..7120846e 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -14,31 +14,32 @@ struct YGNode { private: - void* context_; - YGPrintFunc print_; - bool hasNewLayout_; - YGNodeType nodeType_; - YGMeasureFunc measure_; - YGBaselineFunc baseline_; - YGDirtiedFunc dirtied_; - YGStyle style_; - YGLayout layout_; - uint32_t lineIndex_; - YGNodeRef owner_; - YGVector children_; - YGConfigRef config_; - bool isDirty_; - std::array resolvedDimensions_; + void* context_ = nullptr; + YGPrintFunc print_ = nullptr; + bool hasNewLayout_ = true; + YGNodeType nodeType_ = YGNodeTypeDefault; + YGMeasureFunc measure_ = nullptr; + YGBaselineFunc baseline_ = nullptr; + YGDirtiedFunc dirtied_ = nullptr; + YGStyle style_ = {}; + YGLayout layout_ = {}; + uint32_t lineIndex_ = 0; + YGNodeRef owner_ = nullptr; + YGVector children_ = {}; + YGConfigRef config_ = nullptr; + bool isDirty_ = false; + std::array resolvedDimensions_ = { + {YGValueUndefined, YGValueUndefined}}; YGFloatOptional relativePosition( const YGFlexDirection& axis, const float& axisSize) const; public: - YGNode(); - ~YGNode(); - explicit YGNode(const YGConfigRef newConfig); - YGNode(const YGNode& node); + YGNode() = default; + ~YGNode() = default; // cleanup of owner/children relationships in YGNodeFree + explicit YGNode(const YGConfigRef newConfig) : config_(newConfig){}; + YGNode(const YGNode& node) = default; YGNode& operator=(const YGNode& node); // Getters diff --git a/yoga/YGStyle.cpp b/yoga/YGStyle.cpp index 738d36fb..06d0f2a4 100644 --- a/yoga/YGStyle.cpp +++ b/yoga/YGStyle.cpp @@ -98,9 +98,3 @@ bool YGStyle::operator==(const YGStyle& style) { return areNonFloatValuesEqual; } - -bool YGStyle::operator!=(YGStyle style) { - return !(*this == style); -} - -YGStyle::~YGStyle() {} diff --git a/yoga/YGStyle.h b/yoga/YGStyle.h index b18ac0a6..3f4bbd34 100644 --- a/yoga/YGStyle.h +++ b/yoga/YGStyle.h @@ -32,12 +32,14 @@ struct YGStyle { std::array dimensions; std::array minDimensions; std::array maxDimensions; + // Yoga specific properties, not compatible with flexbox specification YGFloatOptional aspectRatio; YGStyle(); - // Yoga specific properties, not compatible with flexbox specification bool operator==(const YGStyle& style); - bool operator!=(YGStyle style); - ~YGStyle(); + bool operator!=(YGStyle style) { + return !(*this == style); + } + ~YGStyle() = default; }; From 389f2fd85ddd28c3fc65a050291aa9601e7ec863 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:04 -0700 Subject: [PATCH 25/29] Run lint on `Yoga.cpp`/`Yoga.h` Summary: @public auto-fixes formatting for `Yoga.cpp`/`Yoga.h`. Submitted separately to keep other diffs cleaner. Reviewed By: astreet Differential Revision: D8868179 fbshipit-source-id: d0667f8bb909bb5ada1263aac6e22b0a8f8875ad --- yoga/Yoga.cpp | 1128 ++++++++++++++++++++++++++++--------------------- yoga/Yoga.h | 231 +++++----- 2 files changed, 789 insertions(+), 570 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index fe419207..c9404dec 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -29,17 +29,19 @@ __forceinline const float fmaxf(const float a, const float b) { #endif #ifdef ANDROID -static int YGAndroidLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +static int YGAndroidLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); #else -static int YGDefaultLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +static int YGDefaultLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); #endif const YGValue YGValueZero = {0, YGUnitPoint}; @@ -48,11 +50,12 @@ const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; #ifdef ANDROID #include -static int YGAndroidLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGAndroidLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { int androidLevel = YGLogLevelDebug; switch (level) { case YGLogLevelFatal: @@ -80,11 +83,12 @@ static int YGAndroidLog(const YGConfigRef config, #else #define YG_UNUSED(x) (void)(x); -static int YGDefaultLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { +static int YGDefaultLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { YG_UNUSED(config); YG_UNUSED(node); switch (level) { @@ -120,7 +124,8 @@ const YGValue* YGComputedEdgeValue( return &edges[YGEdgeVertical]; } - if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || edge == YGEdgeEnd) && + if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart || + edge == YGEdgeEnd) && edges[YGEdgeHorizontal].unit != YGUnitUndefined) { return &edges[YGEdgeHorizontal]; } @@ -312,9 +317,10 @@ void YGNodeFreeRecursive(const YGNodeRef root) { } void YGNodeReset(const YGNodeRef node) { - YGAssertWithNode(node, - YGNodeGetChildCount(node) == 0, - "Cannot reset a node which still has children attached"); + YGAssertWithNode( + node, + YGNodeGetChildCount(node) == 0, + "Cannot reset a node which still has children attached"); YGAssertWithNode( node, node->getOwner() == nullptr, @@ -340,11 +346,11 @@ int32_t YGConfigGetInstanceCount(void) { } YGConfigRef YGConfigNew(void) { - #ifdef ANDROID +#ifdef ANDROID const YGConfigRef config = new YGConfig(YGAndroidLog); - #else +#else const YGConfigRef config = new YGConfig(YGDefaultLog); - #endif +#endif gConfigInstanceCount++; return config; } @@ -358,7 +364,10 @@ void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src) { memcpy(dest, src, sizeof(YGConfig)); } -void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { +void YGNodeInsertChild( + const YGNodeRef node, + const YGNodeRef child, + const uint32_t index) { YGAssertWithNode( node, child->getOwner() == nullptr, @@ -401,8 +410,8 @@ void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) { } const YGNodeRef firstChild = YGNodeGetChild(owner, 0); if (firstChild->getOwner() == owner) { - // If the first child has this node as its owner, we assume that it is already unique. - // We can now try to delete a child in this list. + // If the first child has this node as its owner, we assume that it is + // already unique. We can now try to delete a child in this list. if (owner->removeChild(excludedChild)) { excludedChild->setLayout( YGNode().getLayout()); // layout is no longer valid @@ -411,18 +420,18 @@ void YGNodeRemoveChild(const YGNodeRef owner, const YGNodeRef excludedChild) { } return; } - // Otherwise we have to clone the node list except for the child we're trying to delete. - // We don't want to simply clone all children, because then the host will need to free - // the clone of the child that was just deleted. + // Otherwise we have to clone the node list except for the child we're trying + // to delete. We don't want to simply clone all children, because then the + // host will need to free the clone of the child that was just deleted. const YGCloneNodeFunc cloneNodeCallback = owner->getConfig()->cloneNodeCallback; uint32_t nextInsertIndex = 0; for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef oldChild = owner->getChild(i); if (excludedChild == oldChild) { - // Ignore the deleted child. Don't reset its layout or owner since it is still valid - // in the other owner. However, since this owner has now changed, we need to mark it - // as dirty. + // Ignore the deleted child. Don't reset its layout or owner since it is + // still valid in the other owner. However, since this owner has now + // changed, we need to mark it as dirty. owner->markDirtyAndPropogate(); continue; } @@ -452,7 +461,8 @@ void YGNodeRemoveAllChildren(const YGNodeRef owner) { } const YGNodeRef firstChild = YGNodeGetChild(owner, 0); if (firstChild->getOwner() == owner) { - // If the first child has this node as its owner, we assume that this child set is unique. + // If the first child has this node as its owner, we assume that this child + // set is unique. for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef oldChild = YGNodeGetChild(owner, i); oldChild->setLayout(YGNode().getLayout()); // layout is no longer valid @@ -462,13 +472,15 @@ void YGNodeRemoveAllChildren(const YGNodeRef owner) { owner->markDirtyAndPropogate(); return; } - // Otherwise, we are not the owner of the child set. We don't have to do anything to clear it. + // Otherwise, we are not the owner of the child set. We don't have to do + // anything to clear it. owner->setChildren(YGVector()); owner->markDirtyAndPropogate(); } -static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector &children) -{ +static void YGNodeSetChildrenInternal( + YGNodeRef const owner, + const std::vector& children) { if (!owner) { return; } @@ -484,8 +496,10 @@ static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector 0) { for (YGNodeRef const 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(children.begin(), children.end(), oldChild) == children.end()) { + // Our new children may have nodes in common with the old children. We + // don't reset these common nodes. + if (std::find(children.begin(), children.end(), oldChild) == + children.end()) { oldChild->setLayout(YGLayout()); oldChild->setOwner(nullptr); } @@ -499,13 +513,17 @@ static void YGNodeSetChildrenInternal(YGNodeRef const owner, const std::vector &children) -{ +void YGNodeSetChildren( + YGNodeRef const owner, + const std::vector& children) { YGNodeSetChildrenInternal(owner, children); } @@ -766,12 +784,24 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { // YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType); YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction); -YG_NODE_STYLE_PROPERTY_IMPL(YGFlexDirection, FlexDirection, flexDirection, flexDirection); -YG_NODE_STYLE_PROPERTY_IMPL(YGJustify, JustifyContent, justifyContent, justifyContent); +YG_NODE_STYLE_PROPERTY_IMPL( + YGFlexDirection, + FlexDirection, + flexDirection, + flexDirection); +YG_NODE_STYLE_PROPERTY_IMPL( + YGJustify, + JustifyContent, + justifyContent, + justifyContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems); YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY_IMPL(YGPositionType, PositionType, positionType, positionType); +YG_NODE_STYLE_PROPERTY_IMPL( + YGPositionType, + PositionType, + positionType, + positionType); YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap); YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display); @@ -925,12 +955,36 @@ void YGNodeStyleSetAspectRatio(const YGNodeRef node, const float aspectRatio) { } } -YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Width, width, dimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL(YGValue, Height, height, dimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinWidth, minWidth, minDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MinHeight, minHeight, minDimensions[YGDimensionHeight]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxWidth, maxWidth, maxDimensions[YGDimensionWidth]); -YG_NODE_STYLE_PROPERTY_UNIT_IMPL(YGValue, MaxHeight, maxHeight, maxDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( + YGValue, + Width, + width, + dimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_AUTO_IMPL( + YGValue, + Height, + height, + dimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MinWidth, + minWidth, + minDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MinHeight, + minHeight, + minDimensions[YGDimensionHeight]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MaxWidth, + maxWidth, + maxDimensions[YGDimensionWidth]); +YG_NODE_STYLE_PROPERTY_UNIT_IMPL( + YGValue, + MaxHeight, + maxHeight, + maxDimensions[YGDimensionHeight]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Left, position[YGEdgeLeft]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Top, position[YGEdgeTop]); YG_NODE_LAYOUT_PROPERTY_IMPL(float, Right, position[YGEdgeRight]); @@ -950,20 +1004,22 @@ bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef node) { uint32_t gCurrentGenerationCount = 0; -bool YGLayoutNodeInternal(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const char *reason, - const YGConfigRef config); +bool YGLayoutNodeInternal( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const char* reason, + const YGConfigRef config); -static void YGNodePrintInternal(const YGNodeRef node, - const YGPrintOptions options) { +static void YGNodePrintInternal( + const YGNodeRef node, + const YGPrintOptions options) { std::string str; facebook::yoga::YGNodeToString(&str, node, options, 0); YGLog(node, YGLogLevelDebug, str.c_str()); @@ -988,15 +1044,18 @@ static const std::array pos = {{ static const std::array dim = { {YGDimensionHeight, YGDimensionHeight, YGDimensionWidth, YGDimensionWidth}}; -static inline float YGNodePaddingAndBorderForAxis(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { +static inline float YGNodePaddingAndBorderForAxis( + const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { return YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(axis, widthSize) + node->getTrailingPaddingAndBorder(axis, widthSize)); } -static inline YGAlign YGNodeAlignItem(const YGNodeRef node, const YGNodeRef child) { +static inline YGAlign YGNodeAlignItem( + const YGNodeRef node, + const YGNodeRef child) { const YGAlign align = child->getStyle().alignSelf == YGAlignAuto ? node->getStyle().alignItems : child->getStyle().alignSelf; @@ -1013,9 +1072,10 @@ static float YGBaseline(const YGNodeRef node) { node, node->getLayout().measuredDimensions[YGDimensionWidth], node->getLayout().measuredDimensions[YGDimensionHeight]); - YGAssertWithNode(node, - !YGFloatIsUndefined(baseline), - "Expect custom baseline function to not return NaN"); + YGAssertWithNode( + node, + !YGFloatIsUndefined(baseline), + "Expect custom baseline function to not return NaN"); return baseline; } @@ -1066,18 +1126,20 @@ static bool YGIsBaselineLayout(const YGNodeRef node) { return false; } -static inline float YGNodeDimWithMargin(const YGNodeRef node, - const YGFlexDirection axis, - const float widthSize) { +static inline float YGNodeDimWithMargin( + const YGNodeRef node, + const YGFlexDirection axis, + const float widthSize) { return node->getLayout().measuredDimensions[dim[axis]] + YGUnwrapFloatOptional( node->getLeadingMargin(axis, widthSize) + node->getTrailingMargin(axis, widthSize)); } -static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, - const YGFlexDirection axis, - const float ownerSize) { +static inline bool YGNodeIsStyleDimDefined( + const YGNodeRef node, + const YGFlexDirection axis, + const float ownerSize) { bool isUndefined = YGFloatIsUndefined(node->getResolvedDimension(dim[axis]).value); return !( @@ -1091,7 +1153,9 @@ static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node, YGFloatIsUndefined(ownerSize)))); } -static inline bool YGNodeIsLayoutDimDefined(const YGNodeRef node, const YGFlexDirection axis) { +static inline bool YGNodeIsLayoutDimDefined( + const YGNodeRef node, + const YGFlexDirection axis) { const float value = node->getLayout().measuredDimensions[dim[axis]]; return !YGFloatIsUndefined(value) && value >= 0.0f; } @@ -1127,23 +1191,24 @@ static YGFloatOptional YGNodeBoundAxisWithinMinAndMax( return YGFloatOptional(value); } -// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't go -// below the -// padding and border amount. -static inline float YGNodeBoundAxis(const YGNodeRef node, - const YGFlexDirection axis, - const float value, - const float axisSize, - const float widthSize) { +// Like YGNodeBoundAxisWithinMinAndMax but also ensures that the value doesn't +// go below the padding and border amount. +static inline float YGNodeBoundAxis( + const YGNodeRef node, + const YGFlexDirection axis, + const float value, + const float axisSize, + const float widthSize) { return YGFloatMax( YGUnwrapFloatOptional( YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize)), YGNodePaddingAndBorderForAxis(node, axis, widthSize)); } -static void YGNodeSetChildTrailingPosition(const YGNodeRef node, - const YGNodeRef child, - const YGFlexDirection axis) { +static void YGNodeSetChildTrailingPosition( + const YGNodeRef node, + const YGNodeRef child, + const YGFlexDirection axis) { const float size = child->getLayout().measuredDimensions[dim[axis]]; child->setLayoutPosition( node->getLayout().measuredDimensions[dim[axis]] - size - @@ -1151,15 +1216,15 @@ static void YGNodeSetChildTrailingPosition(const YGNodeRef node, trailing[axis]); } -static void YGConstrainMaxSizeForMode(const YGNodeRef node, - const enum YGFlexDirection axis, - const float ownerAxisSize, - const float ownerWidth, - YGMeasureMode *mode, - float *size) { +static void YGConstrainMaxSizeForMode( + const YGNodeRef node, + const enum YGFlexDirection axis, + const float ownerAxisSize, + const float ownerWidth, + YGMeasureMode* mode, + float* size) { const YGFloatOptional maxSize = - YGResolveValue( - node->getStyle().maxDimensions[dim[axis]], ownerAxisSize) + + YGResolveValue(node->getStyle().maxDimensions[dim[axis]], ownerAxisSize) + YGFloatOptional(node->getMarginForAxis(axis, ownerWidth)); switch (*mode) { case YGMeasureModeExactly: @@ -1177,16 +1242,17 @@ static void YGConstrainMaxSizeForMode(const YGNodeRef node, } } -static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, - const YGNodeRef child, - const float width, - const YGMeasureMode widthMode, - const float height, - const float ownerWidth, - const float ownerHeight, - const YGMeasureMode heightMode, - const YGDirection direction, - const YGConfigRef config) { +static void YGNodeComputeFlexBasisForChild( + const YGNodeRef node, + const YGNodeRef child, + const float width, + const YGMeasureMode widthMode, + const float height, + const float ownerWidth, + const float ownerHeight, + const YGMeasureMode heightMode, + const YGDirection direction, + const YGConfigRef config) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis); @@ -1200,7 +1266,8 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, const YGFloatOptional resolvedFlexBasis = YGResolveValue(child->resolveFlexBasisPtr(), mainAxisownerSize); - const bool isRowStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth); + const bool isRowStyleDimDefined = + YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, ownerWidth); const bool isColumnStyleDimDefined = YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, ownerHeight); @@ -1284,7 +1351,8 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, childHeight = marginColumn + (childWidth - marginRow) / child->getStyle().aspectRatio.getValue(); childHeightMeasureMode = YGMeasureModeExactly; - } else if (isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { + } else if ( + isMainAxisRow && childHeightMeasureMode == YGMeasureModeExactly) { childWidth = marginRow + (childHeight - marginColumn) * child->getStyle().aspectRatio.getValue(); @@ -1296,10 +1364,13 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, // set the cross // axis to be measured exactly with the available inner width - const bool hasExactWidth = !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; - const bool childWidthStretch = YGNodeAlignItem(node, child) == YGAlignStretch && - childWidthMeasureMode != YGMeasureModeExactly; - if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && childWidthStretch) { + const bool hasExactWidth = + !YGFloatIsUndefined(width) && widthMode == YGMeasureModeExactly; + const bool childWidthStretch = + YGNodeAlignItem(node, child) == YGAlignStretch && + childWidthMeasureMode != YGMeasureModeExactly; + if (!isMainAxisRow && !isRowStyleDimDefined && hasExactWidth && + childWidthStretch) { childWidth = width; childWidthMeasureMode = YGMeasureModeExactly; if (!child->getStyle().aspectRatio.isUndefined()) { @@ -1309,10 +1380,13 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, } } - const bool hasExactHeight = !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly; - const bool childHeightStretch = YGNodeAlignItem(node, child) == YGAlignStretch && - childHeightMeasureMode != YGMeasureModeExactly; - if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && childHeightStretch) { + const bool hasExactHeight = + !YGFloatIsUndefined(height) && heightMode == YGMeasureModeExactly; + const bool childHeightStretch = + YGNodeAlignItem(node, child) == YGAlignStretch && + childHeightMeasureMode != YGMeasureModeExactly; + if (isMainAxisRow && !isColumnStyleDimDefined && hasExactHeight && + childHeightStretch) { childHeight = height; childHeightMeasureMode = YGMeasureModeExactly; @@ -1324,26 +1398,33 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, } YGConstrainMaxSizeForMode( - child, YGFlexDirectionRow, ownerWidth, ownerWidth, &childWidthMeasureMode, &childWidth); - YGConstrainMaxSizeForMode(child, - YGFlexDirectionColumn, - ownerHeight, - ownerWidth, - &childHeightMeasureMode, - &childHeight); + child, + YGFlexDirectionRow, + ownerWidth, + ownerWidth, + &childWidthMeasureMode, + &childWidth); + YGConstrainMaxSizeForMode( + child, + YGFlexDirectionColumn, + ownerHeight, + ownerWidth, + &childHeightMeasureMode, + &childHeight); // Measure the child - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - childWidthMeasureMode, - childHeightMeasureMode, - ownerWidth, - ownerHeight, - false, - "measure", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + childWidthMeasureMode, + childHeightMeasureMode, + ownerWidth, + ownerHeight, + false, + "measure", + config); child->setLayoutComputedFlexBasis(YGFloatOptional(YGFloatMax( child->getLayout().measuredDimensions[dim[mainAxis]], @@ -1352,13 +1433,14 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node, child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount); } -static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, - const YGNodeRef child, - const float width, - const YGMeasureMode widthMode, - const float height, - const YGDirection direction, - const YGConfigRef config) { +static void YGNodeAbsoluteLayoutChild( + const YGNodeRef node, + const YGNodeRef child, + const float width, + const YGMeasureMode widthMode, + const float height, + const YGDirection direction, + const YGConfigRef config) { const YGFlexDirection mainAxis = YGResolveFlexDirection(node->getStyle().flexDirection, direction); const YGFlexDirection crossAxis = YGFlexDirectionCross(mainAxis, direction); @@ -1375,8 +1457,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->getMarginForAxis(YGFlexDirectionColumn, width)); if (YGNodeIsStyleDimDefined(child, YGFlexDirectionRow, width)) { - childWidth = - YGUnwrapFloatOptional(YGResolveValue(child->getResolvedDimension(YGDimensionWidth), width)) + + childWidth = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionWidth), width)) + marginRow; } else { // If the child doesn't have a specified width, compute the width based @@ -1390,13 +1472,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGUnwrapFloatOptional( child->getLeadingPosition(YGFlexDirectionRow, width) + child->getTrailingPosition(YGFlexDirectionRow, width)); - childWidth = YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); + childWidth = + YGNodeBoundAxis(child, YGFlexDirectionRow, childWidth, width, width); } } if (YGNodeIsStyleDimDefined(child, YGFlexDirectionColumn, height)) { - childHeight = - YGUnwrapFloatOptional(YGResolveValue(child->getResolvedDimension(YGDimensionHeight), height)) + + childHeight = YGUnwrapFloatOptional(YGResolveValue( + child->getResolvedDimension(YGDimensionHeight), height)) + marginColumn; } else { // If the child doesn't have a specified height, compute the height @@ -1411,12 +1494,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, YGUnwrapFloatOptional( child->getLeadingPosition(YGFlexDirectionColumn, height) + child->getTrailingPosition(YGFlexDirectionColumn, height)); - childHeight = YGNodeBoundAxis(child, YGFlexDirectionColumn, childHeight, height, width); + childHeight = YGNodeBoundAxis( + child, YGFlexDirectionColumn, childHeight, height, width); } } - // Exactly one dimension needs to be defined for us to be able to do aspect ratio - // calculation. One dimension being the anchor and the other being flexible. + // Exactly one dimension needs to be defined for us to be able to do aspect + // ratio calculation. One dimension being the anchor and the other being + // flexible. if (YGFloatIsUndefined(childWidth) ^ YGFloatIsUndefined(childHeight)) { if (!child->getStyle().aspectRatio.isUndefined()) { if (YGFloatIsUndefined(childWidth)) { @@ -1432,14 +1517,17 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, // If we're still missing one or the other dimension, measure the content. if (YGFloatIsUndefined(childWidth) || YGFloatIsUndefined(childHeight)) { - childWidthMeasureMode = - YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined : YGMeasureModeExactly; - childHeightMeasureMode = - YGFloatIsUndefined(childHeight) ? YGMeasureModeUndefined : YGMeasureModeExactly; + childWidthMeasureMode = YGFloatIsUndefined(childWidth) + ? YGMeasureModeUndefined + : YGMeasureModeExactly; + childHeightMeasureMode = YGFloatIsUndefined(childHeight) + ? YGMeasureModeUndefined + : YGMeasureModeExactly; - // If the size of the owner is defined then try to constrain the absolute child to that size - // as well. This allows text within the absolute child to wrap to the size of its owner. - // This is the same behavior as many browsers implement. + // If the size of the owner is defined then try to constrain the absolute + // child to that size as well. This allows text within the absolute child to + // wrap to the size of its owner. This is the same behavior as many browsers + // implement. if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) && width > 0) { @@ -1447,17 +1535,18 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, childWidthMeasureMode = YGMeasureModeAtMost; } - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - childWidthMeasureMode, - childHeightMeasureMode, - childWidth, - childHeight, - false, - "abs-measure", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + childWidthMeasureMode, + childHeightMeasureMode, + childWidth, + childHeight, + false, + "abs-measure", + config); childWidth = child->getLayout().measuredDimensions[YGDimensionWidth] + YGUnwrapFloatOptional( child->getMarginForAxis(YGFlexDirectionRow, width)); @@ -1466,17 +1555,18 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, child->getMarginForAxis(YGFlexDirectionColumn, width)); } - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - YGMeasureModeExactly, - YGMeasureModeExactly, - childWidth, - childHeight, - true, - "abs-layout", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + YGMeasureModeExactly, + YGMeasureModeExactly, + childWidth, + childHeight, + true, + "abs-layout", + config); if (child->isTrailingPosDefined(mainAxis) && !child->isLeadingPositionDefined(mainAxis)) { @@ -1535,13 +1625,14 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node, } } -static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static void YGNodeWithMeasureFuncSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { YGAssertWithNode( node, node->getMeasure() != nullptr, @@ -1549,8 +1640,8 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, availableWidth); - const float paddingAndBorderAxisColumn = - YGNodePaddingAndBorderForAxis(node, YGFlexDirectionColumn, availableWidth); + const float paddingAndBorderAxisColumn = YGNodePaddingAndBorderForAxis( + node, YGFlexDirectionColumn, availableWidth); const float marginAxisRow = YGUnwrapFloatOptional( node->getMarginForAxis(YGFlexDirectionRow, availableWidth)); const float marginAxisColumn = YGUnwrapFloatOptional( @@ -1617,13 +1708,14 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node, // For nodes with no children, use the available values if they were provided, // or the minimum size as indicated by the padding and border sizes. -static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static void YGNodeEmptyContainerSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { const float paddingAndBorderAxisRow = YGNodePaddingAndBorderForAxis(node, YGFlexDirectionRow, ownerWidth); const float paddingAndBorderAxisColumn = @@ -1658,13 +1750,14 @@ static void YGNodeEmptyContainerSetMeasuredDimensions(const YGNodeRef node, YGDimensionHeight); } -static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight) { +static bool YGNodeFixedSizeSetMeasuredDimensions( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight) { if ((!YGFloatIsUndefined(availableWidth) && widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) || (!YGFloatIsUndefined(availableHeight) && @@ -1739,12 +1832,14 @@ static float YGNodeCalculateAvailableInnerDim( if (!YGFloatIsUndefined(availableInnerDim)) { // We want to make sure our available height does not violate min and max // constraints - const YGFloatOptional minDimensionOptional = YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); + const YGFloatOptional minDimensionOptional = + YGResolveValue(node->getStyle().minDimensions[dimension], ownerDim); const float minInnerDim = minDimensionOptional.isUndefined() ? 0.0f : minDimensionOptional.getValue() - paddingAndBorder; - const YGFloatOptional maxDimensionOptional = YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim) ; + const YGFloatOptional maxDimensionOptional = + YGResolveValue(node->getStyle().maxDimensions[dimension], ownerDim); const float maxInnerDim = maxDimensionOptional.isUndefined() ? FLT_MAX @@ -2523,37 +2618,42 @@ static void YGJustifyMainAxis( // - YGMeasureModeExactly: fill available // - YGMeasureModeAtMost: fit content // -// When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller passes -// an available size of -// undefined then it must also pass a measure mode of YGMeasureModeUndefined -// in that dimension. +// When calling YGNodelayoutImpl and YGLayoutNodeInternal, if the caller +// passes an available size of undefined then it must also pass a measure +// mode of YGMeasureModeUndefined in that dimension. // -static void YGNodelayoutImpl(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const YGConfigRef config) { - YGAssertWithNode(node, - YGFloatIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined - : true, - "availableWidth is indefinite so widthMeasureMode must be " - "YGMeasureModeUndefined"); - YGAssertWithNode(node, - YGFloatIsUndefined(availableHeight) ? heightMeasureMode == YGMeasureModeUndefined - : true, - "availableHeight is indefinite so heightMeasureMode must be " - "YGMeasureModeUndefined"); +static void YGNodelayoutImpl( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const YGConfigRef config) { + YGAssertWithNode( + node, + YGFloatIsUndefined(availableWidth) + ? widthMeasureMode == YGMeasureModeUndefined + : true, + "availableWidth is indefinite so widthMeasureMode must be " + "YGMeasureModeUndefined"); + YGAssertWithNode( + node, + YGFloatIsUndefined(availableHeight) + ? heightMeasureMode == YGMeasureModeUndefined + : true, + "availableHeight is indefinite so heightMeasureMode must be " + "YGMeasureModeUndefined"); // Set the resolved resolution in the node's layout. const YGDirection direction = node->resolveDirection(ownerDirection); node->setLayoutDirection(direction); - const YGFlexDirection flexRowDirection = YGResolveFlexDirection(YGFlexDirectionRow, direction); + const YGFlexDirection flexRowDirection = + YGResolveFlexDirection(YGFlexDirectionRow, direction); const YGFlexDirection flexColumnDirection = YGResolveFlexDirection(YGFlexDirectionColumn, direction); @@ -2598,41 +2698,46 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGEdgeBottom); if (node->getMeasure() != nullptr) { - YGNodeWithMeasureFuncSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight); + YGNodeWithMeasureFuncSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight); return; } const uint32_t childCount = YGNodeGetChildCount(node); if (childCount == 0) { - YGNodeEmptyContainerSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight); + YGNodeEmptyContainerSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight); return; } - // If we're not being asked to perform a full layout we can skip the algorithm if we already know - // the size - if (!performLayout && YGNodeFixedSizeSetMeasuredDimensions(node, - availableWidth, - availableHeight, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight)) { + // If we're not being asked to perform a full layout we can skip the algorithm + // if we already know the size + if (!performLayout && + YGNodeFixedSizeSetMeasuredDimensions( + node, + availableWidth, + availableHeight, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight)) { return; } - // At this point we know we're going to perform work. Ensure that each child has a mutable copy. + // At this point we know we're going to perform work. Ensure that each child + // has a mutable copy. node->cloneChildrenIfNeeded(); // Reset layout flags, as they could have changed. node->setLayoutHadOverflow(false); @@ -2649,12 +2754,15 @@ static void YGNodelayoutImpl(const YGNodeRef node, const float leadingPaddingAndBorderCross = YGUnwrapFloatOptional( node->getLeadingPaddingAndBorder(crossAxis, ownerWidth)); - const float paddingAndBorderAxisMain = YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); + const float paddingAndBorderAxisMain = + YGNodePaddingAndBorderForAxis(node, mainAxis, ownerWidth); const float paddingAndBorderAxisCross = YGNodePaddingAndBorderForAxis(node, crossAxis, ownerWidth); - YGMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode; - YGMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode; + YGMeasureMode measureModeMainDim = + isMainAxisRow ? widthMeasureMode : heightMeasureMode; + YGMeasureMode measureModeCrossDim = + isMainAxisRow ? heightMeasureMode : widthMeasureMode; const float paddingAndBorderAxisRow = isMainAxisRow ? paddingAndBorderAxisMain : paddingAndBorderAxisCross; @@ -2667,13 +2775,16 @@ static void YGNodelayoutImpl(const YGNodeRef node, node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); const float minInnerWidth = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float maxInnerWidth = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionWidth], ownerWidth)) - paddingAndBorderAxisRow; const float minInnerHeight = - YGUnwrapFloatOptional(YGResolveValue(node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - + YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().minDimensions[YGDimensionHeight], ownerHeight)) - paddingAndBorderAxisColumn; const float maxInnerHeight = YGUnwrapFloatOptional(YGResolveValue( @@ -2756,7 +2867,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, // the line length, so there's no more space left to distribute. bool sizeBasedOnContent = false; - // If we don't measure with exact main dimension we want to ensure we don't violate min and max + // If we don't measure with exact main dimension we want to ensure we don't + // violate min and max if (measureModeMainDim != YGMeasureModeExactly) { if (!YGFloatIsUndefined(minInnerMainDim) && collectedFlexItemsValues.sizeConsumedOnCurrentLine < @@ -2792,10 +2904,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, collectedFlexItemsValues.remainingFreeSpace = availableInnerMainDim - collectedFlexItemsValues.sizeConsumedOnCurrentLine; } else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0) { - // availableInnerMainDim is indefinite which means the node is being sized based on its - // content. - // sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for - // its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine. + // availableInnerMainDim is indefinite which means the node is being sized + // based on its content. sizeConsumedOnCurrentLine is negative which means + // the node will allocate 0 points for its content. Consequently, + // remainingFreeSpace is 0 - sizeConsumedOnCurrentLine. collectedFlexItemsValues.remainingFreeSpace = -collectedFlexItemsValues.sizeConsumedOnCurrentLine; } @@ -2897,7 +3009,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, crossAxis, availableInnerWidth)), pos[crossAxis]); } - // If leading position is not defined or calculations result in Nan, default to border + margin + // If leading position is not defined or calculations result in Nan, + // default to border + margin if (!isChildLeadingPosDefined || YGFloatIsUndefined(child->getLayout().position[pos[crossAxis]])) { child->setLayoutPosition( @@ -2923,7 +3036,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, child->marginTrailingValue(crossAxis).unit != YGUnitAuto) { // If the child defines a definite size for its cross axis, there's // no need to stretch. - if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) { + if (!YGNodeIsStyleDimDefined( + child, crossAxis, availableInnerCrossDim)) { float childMainSize = child->getLayout().measuredDimensions[dim[mainAxis]]; float childCrossSize = @@ -2941,21 +3055,25 @@ static void YGNodelayoutImpl(const YGNodeRef node, YGMeasureMode childMainMeasureMode = YGMeasureModeExactly; YGMeasureMode childCrossMeasureMode = YGMeasureModeExactly; - YGConstrainMaxSizeForMode(child, - mainAxis, - availableInnerMainDim, - availableInnerWidth, - &childMainMeasureMode, - &childMainSize); - YGConstrainMaxSizeForMode(child, - crossAxis, - availableInnerCrossDim, - availableInnerWidth, - &childCrossMeasureMode, - &childCrossSize); + YGConstrainMaxSizeForMode( + child, + mainAxis, + availableInnerMainDim, + availableInnerWidth, + &childMainMeasureMode, + &childMainSize); + YGConstrainMaxSizeForMode( + child, + crossAxis, + availableInnerCrossDim, + availableInnerWidth, + &childCrossMeasureMode, + &childCrossSize); - const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; - const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; + const float childWidth = + isMainAxisRow ? childMainSize : childCrossSize; + const float childHeight = + !isMainAxisRow ? childMainSize : childCrossSize; const YGMeasureMode childWidthMeasureMode = YGFloatIsUndefined(childWidth) ? YGMeasureModeUndefined @@ -3015,7 +3133,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, // STEP 8: MULTI-LINE CONTENT ALIGNMENT if (performLayout && (lineCount > 1 || YGIsBaselineLayout(node)) && !YGFloatIsUndefined(availableInnerCrossDim)) { - const float remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim; + const float remainingAlignContentDim = + availableInnerCrossDim - totalLineCrossDim; float crossDimLead = 0; float currentLead = leadingPaddingAndBorderCross; @@ -3140,9 +3259,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, crossAxis, availableInnerWidth)), pos[crossAxis]); - // Remeasure child with the line height as it as been only measured with the - // owners height yet. - if (!YGNodeIsStyleDimDefined(child, crossAxis, availableInnerCrossDim)) { + // Remeasure child with the line height as it as been only + // measured with the owners height yet. + if (!YGNodeIsStyleDimDefined( + child, crossAxis, availableInnerCrossDim)) { const float childWidth = isMainAxisRow ? (child->getLayout() .measuredDimensions[YGDimensionWidth] + @@ -3165,17 +3285,18 @@ static void YGNodelayoutImpl(const YGNodeRef node, childHeight, child->getLayout() .measuredDimensions[YGDimensionHeight]))) { - YGLayoutNodeInternal(child, - childWidth, - childHeight, - direction, - YGMeasureModeExactly, - YGMeasureModeExactly, - availableInnerWidth, - availableInnerHeight, - true, - "multiline-stretch", - config); + YGLayoutNodeInternal( + child, + childWidth, + childHeight, + direction, + YGMeasureModeExactly, + YGMeasureModeExactly, + availableInnerWidth, + availableInnerHeight, + true, + "multiline-stretch", + config); } } break; @@ -3278,7 +3399,8 @@ static void YGNodelayoutImpl(const YGNodeRef node, dim[crossAxis]); } - // As we only wrapped in normal direction yet, we need to reverse the positions on wrap-reverse. + // As we only wrapped in normal direction yet, we need to reverse the + // positions on wrap-reverse. if (performLayout && node->getStyle().flexWrap == YGWrapWrapReverse) { for (uint32_t i = 0; i < childCount; i++) { const YGNodeRef child = YGNodeGetChild(node, i); @@ -3309,10 +3431,10 @@ static void YGNodelayoutImpl(const YGNodeRef node, } // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN - const bool needsMainTrailingPos = - mainAxis == YGFlexDirectionRowReverse || mainAxis == YGFlexDirectionColumnReverse; - const bool needsCrossTrailingPos = - crossAxis == YGFlexDirectionRowReverse || crossAxis == YGFlexDirectionColumnReverse; + const bool needsMainTrailingPos = mainAxis == YGFlexDirectionRowReverse || + mainAxis == YGFlexDirectionColumnReverse; + const bool needsCrossTrailingPos = crossAxis == YGFlexDirectionRowReverse || + crossAxis == YGFlexDirectionColumnReverse; // Set trailing position if necessary. if (needsMainTrailingPos || needsCrossTrailingPos) { @@ -3338,9 +3460,10 @@ bool gPrintTree = false; bool gPrintChanges = false; bool gPrintSkips = false; -static const char *spacer = " "; +static const char* spacer = + " "; -static const char *YGSpacer(const unsigned long level) { +static const char* YGSpacer(const unsigned long level) { const size_t spacerLen = strlen(spacer); if (level > spacerLen) { return &spacer[0]; @@ -3349,9 +3472,12 @@ static const char *YGSpacer(const unsigned long level) { } } -static const char *YGMeasureModeName(const YGMeasureMode mode, const bool performLayout) { - const char *kMeasureModeNames[YGMeasureModeCount] = {"UNDEFINED", "EXACTLY", "AT_MOST"}; - const char *kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", +static const char* YGMeasureModeName( + const YGMeasureMode mode, + const bool performLayout) { + const char* kMeasureModeNames[YGMeasureModeCount] = { + "UNDEFINED", "EXACTLY", "AT_MOST"}; + const char* kLayoutModeNames[YGMeasureModeCount] = {"LAY_UNDEFINED", "LAY_EXACTLY", "LAY_AT_" "MOST"}; @@ -3363,25 +3489,30 @@ static const char *YGMeasureModeName(const YGMeasureMode mode, const bool perfor return performLayout ? kLayoutModeNames[mode] : kMeasureModeNames[mode]; } -static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(YGMeasureMode sizeMode, - float size, - float lastComputedSize) { - return sizeMode == YGMeasureModeExactly && YGFloatsEqual(size, lastComputedSize); +static inline bool YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + YGMeasureMode sizeMode, + float size, + float lastComputedSize) { + return sizeMode == YGMeasureModeExactly && + YGFloatsEqual(size, lastComputedSize); } -static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits(YGMeasureMode sizeMode, - float size, - YGMeasureMode lastSizeMode, - float lastComputedSize) { - return sizeMode == YGMeasureModeAtMost && lastSizeMode == YGMeasureModeUndefined && - (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize)); +static inline bool YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + YGMeasureMode sizeMode, + float size, + YGMeasureMode lastSizeMode, + float lastComputedSize) { + return sizeMode == YGMeasureModeAtMost && + lastSizeMode == YGMeasureModeUndefined && + (size >= lastComputedSize || YGFloatsEqual(size, lastComputedSize)); } -static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureMode sizeMode, - float size, - YGMeasureMode lastSizeMode, - float lastSize, - float lastComputedSize) { +static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid( + YGMeasureMode sizeMode, + float size, + YGMeasureMode lastSizeMode, + float lastSize, + float lastComputedSize) { return lastSizeMode == YGMeasureModeAtMost && sizeMode == YGMeasureModeAtMost && !YGFloatIsUndefined(lastSize) && !YGFloatIsUndefined(size) && !YGFloatIsUndefined(lastComputedSize) && @@ -3389,10 +3520,11 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize)); } -float YGRoundValueToPixelGrid(const float value, - const float pointScaleFactor, - const bool forceCeil, - const bool forceFloor) { +float YGRoundValueToPixelGrid( + const float value, + const float pointScaleFactor, + const bool forceCeil, + const bool forceFloor) { float scaledValue = value * pointScaleFactor; float fractial = fmodf(scaledValue, 1.0f); if (YGFloatsEqual(fractial, 0)) { @@ -3419,66 +3551,74 @@ float YGRoundValueToPixelGrid(const float value, : scaledValue / pointScaleFactor; } -bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, - const float width, - const YGMeasureMode heightMode, - const float height, - const YGMeasureMode lastWidthMode, - const float lastWidth, - const YGMeasureMode lastHeightMode, - const float lastHeight, - const float lastComputedWidth, - const float lastComputedHeight, - const float marginRow, - const float marginColumn, - const YGConfigRef config) { +bool YGNodeCanUseCachedMeasurement( + const YGMeasureMode widthMode, + const float width, + const YGMeasureMode heightMode, + const float height, + const YGMeasureMode lastWidthMode, + const float lastWidth, + const YGMeasureMode lastHeightMode, + const float lastHeight, + const float lastComputedWidth, + const float lastComputedHeight, + const float marginRow, + const float marginColumn, + const YGConfigRef config) { if ((!YGFloatIsUndefined(lastComputedHeight) && lastComputedHeight < 0) || (!YGFloatIsUndefined(lastComputedWidth) && lastComputedWidth < 0)) { return false; } bool useRoundedComparison = config != nullptr && config->pointScaleFactor != 0; - const float effectiveWidth = - useRoundedComparison ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) - : width; - const float effectiveHeight = - useRoundedComparison ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false) - : height; - const float effectiveLastWidth = - useRoundedComparison - ? YGRoundValueToPixelGrid(lastWidth, config->pointScaleFactor, false, false) - : lastWidth; - const float effectiveLastHeight = - useRoundedComparison - ? YGRoundValueToPixelGrid(lastHeight, config->pointScaleFactor, false, false) - : lastHeight; + const float effectiveWidth = useRoundedComparison + ? YGRoundValueToPixelGrid(width, config->pointScaleFactor, false, false) + : width; + const float effectiveHeight = useRoundedComparison + ? YGRoundValueToPixelGrid(height, config->pointScaleFactor, false, false) + : height; + const float effectiveLastWidth = useRoundedComparison + ? YGRoundValueToPixelGrid( + lastWidth, config->pointScaleFactor, false, false) + : lastWidth; + const float effectiveLastHeight = useRoundedComparison + ? YGRoundValueToPixelGrid( + lastHeight, config->pointScaleFactor, false, false) + : lastHeight; - const bool hasSameWidthSpec = - lastWidthMode == widthMode && YGFloatsEqual(effectiveLastWidth, effectiveWidth); - const bool hasSameHeightSpec = - lastHeightMode == heightMode && YGFloatsEqual(effectiveLastHeight, effectiveHeight); + const bool hasSameWidthSpec = lastWidthMode == widthMode && + YGFloatsEqual(effectiveLastWidth, effectiveWidth); + const bool hasSameHeightSpec = lastHeightMode == heightMode && + YGFloatsEqual(effectiveLastHeight, effectiveHeight); const bool widthIsCompatible = - hasSameWidthSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(widthMode, - width - marginRow, - lastComputedWidth) || - YGMeasureModeOldSizeIsUnspecifiedAndStillFits(widthMode, - width - marginRow, - lastWidthMode, - lastComputedWidth) || + hasSameWidthSpec || + YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + widthMode, width - marginRow, lastComputedWidth) || + YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + widthMode, width - marginRow, lastWidthMode, lastComputedWidth) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( - widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth); + widthMode, + width - marginRow, + lastWidthMode, + lastWidth, + lastComputedWidth); const bool heightIsCompatible = - hasSameHeightSpec || YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize(heightMode, - height - marginColumn, - lastComputedHeight) || - YGMeasureModeOldSizeIsUnspecifiedAndStillFits(heightMode, - height - marginColumn, - lastHeightMode, - lastComputedHeight) || + hasSameHeightSpec || + YGMeasureModeSizeIsExactAndMatchesOldMeasuredSize( + heightMode, height - marginColumn, lastComputedHeight) || + YGMeasureModeOldSizeIsUnspecifiedAndStillFits( + heightMode, + height - marginColumn, + lastHeightMode, + lastComputedHeight) || YGMeasureModeNewMeasureSizeIsStricterAndStillValid( - heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight); + heightMode, + height - marginColumn, + lastHeightMode, + lastHeight, + lastComputedHeight); return widthIsCompatible && heightIsCompatible; } @@ -3491,17 +3631,18 @@ bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, // Input parameters are the same as YGNodelayoutImpl (see above) // Return parameter is true if layout was performed, false if skipped // -bool YGLayoutNodeInternal(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection, - const YGMeasureMode widthMeasureMode, - const YGMeasureMode heightMeasureMode, - const float ownerWidth, - const float ownerHeight, - const bool performLayout, - const char *reason, - const YGConfigRef config) { +bool YGLayoutNodeInternal( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection, + const YGMeasureMode widthMeasureMode, + const YGMeasureMode heightMeasureMode, + const float ownerWidth, + const float ownerHeight, + const bool performLayout, + const char* reason, + const YGConfigRef config) { YGLayout* layout = &node->getLayout(); gDepth++; @@ -3513,8 +3654,8 @@ bool YGLayoutNodeInternal(const YGNodeRef node, if (needToVisitNode) { // Invalidate the cached results. layout->nextCachedMeasurementsIndex = 0; - layout->cachedLayout.widthMeasureMode = (YGMeasureMode) -1; - layout->cachedLayout.heightMeasureMode = (YGMeasureMode) -1; + layout->cachedLayout.widthMeasureMode = (YGMeasureMode)-1; + layout->cachedLayout.heightMeasureMode = (YGMeasureMode)-1; layout->cachedLayout.computedWidth = -1; layout->cachedLayout.computedHeight = -1; } @@ -3540,36 +3681,38 @@ bool YGLayoutNodeInternal(const YGNodeRef node, node->getMarginForAxis(YGFlexDirectionColumn, ownerWidth)); // First, try to use the layout cache. - if (YGNodeCanUseCachedMeasurement(widthMeasureMode, - availableWidth, - heightMeasureMode, - availableHeight, - layout->cachedLayout.widthMeasureMode, - layout->cachedLayout.availableWidth, - layout->cachedLayout.heightMeasureMode, - layout->cachedLayout.availableHeight, - layout->cachedLayout.computedWidth, - layout->cachedLayout.computedHeight, - marginAxisRow, - marginAxisColumn, - config)) { + if (YGNodeCanUseCachedMeasurement( + widthMeasureMode, + availableWidth, + heightMeasureMode, + availableHeight, + layout->cachedLayout.widthMeasureMode, + layout->cachedLayout.availableWidth, + layout->cachedLayout.heightMeasureMode, + layout->cachedLayout.availableHeight, + layout->cachedLayout.computedWidth, + layout->cachedLayout.computedHeight, + marginAxisRow, + marginAxisColumn, + config)) { cachedResults = &layout->cachedLayout; } else { // Try to use the measurement cache. for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { - if (YGNodeCanUseCachedMeasurement(widthMeasureMode, - availableWidth, - heightMeasureMode, - availableHeight, - layout->cachedMeasurements[i].widthMeasureMode, - layout->cachedMeasurements[i].availableWidth, - layout->cachedMeasurements[i].heightMeasureMode, - layout->cachedMeasurements[i].availableHeight, - layout->cachedMeasurements[i].computedWidth, - layout->cachedMeasurements[i].computedHeight, - marginAxisRow, - marginAxisColumn, - config)) { + if (YGNodeCanUseCachedMeasurement( + widthMeasureMode, + availableWidth, + heightMeasureMode, + availableHeight, + layout->cachedMeasurements[i].widthMeasureMode, + layout->cachedMeasurements[i].availableWidth, + layout->cachedMeasurements[i].heightMeasureMode, + layout->cachedMeasurements[i].availableHeight, + layout->cachedMeasurements[i].computedWidth, + layout->cachedMeasurements[i].computedHeight, + marginAxisRow, + marginAxisColumn, + config)) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -3584,10 +3727,13 @@ bool YGLayoutNodeInternal(const YGNodeRef node, } } else { for (uint32_t i = 0; i < layout->nextCachedMeasurementsIndex; i++) { - if (YGFloatsEqual(layout->cachedMeasurements[i].availableWidth, availableWidth) && - YGFloatsEqual(layout->cachedMeasurements[i].availableHeight, availableHeight) && + if (YGFloatsEqual( + layout->cachedMeasurements[i].availableWidth, availableWidth) && + YGFloatsEqual( + layout->cachedMeasurements[i].availableHeight, availableHeight) && layout->cachedMeasurements[i].widthMeasureMode == widthMeasureMode && - layout->cachedMeasurements[i].heightMeasureMode == heightMeasureMode) { + layout->cachedMeasurements[i].heightMeasureMode == + heightMeasureMode) { cachedResults = &layout->cachedMeasurements[i]; break; } @@ -3596,10 +3742,16 @@ bool YGLayoutNodeInternal(const YGNodeRef node, if (!needToVisitNode && cachedResults != nullptr) { layout->measuredDimensions[YGDimensionWidth] = cachedResults->computedWidth; - layout->measuredDimensions[YGDimensionHeight] = cachedResults->computedHeight; + layout->measuredDimensions[YGDimensionHeight] = + cachedResults->computedHeight; if (gPrintChanges && gPrintSkips) { - YGLog(node, YGLogLevelVerbose, "%s%d.{[skipped] ", YGSpacer(gDepth), gDepth); + YGLog( + node, + YGLogLevelVerbose, + "%s%d.{[skipped] ", + YGSpacer(gDepth), + gDepth); if (node->getPrintFunc() != nullptr) { node->getPrintFunc()(node); } @@ -3638,16 +3790,17 @@ bool YGLayoutNodeInternal(const YGNodeRef node, reason); } - YGNodelayoutImpl(node, - availableWidth, - availableHeight, - ownerDirection, - widthMeasureMode, - heightMeasureMode, - ownerWidth, - ownerHeight, - performLayout, - config); + YGNodelayoutImpl( + node, + availableWidth, + availableHeight, + ownerDirection, + widthMeasureMode, + heightMeasureMode, + ownerWidth, + ownerHeight, + performLayout, + config); if (gPrintChanges) { YGLog( @@ -3681,13 +3834,14 @@ bool YGLayoutNodeInternal(const YGNodeRef node, layout->nextCachedMeasurementsIndex = 0; } - YGCachedMeasurement *newCacheEntry; + YGCachedMeasurement* newCacheEntry; if (performLayout) { // Use the single layout cache entry. newCacheEntry = &layout->cachedLayout; } else { // Allocate a new measurement cache entry. - newCacheEntry = &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; + newCacheEntry = + &layout->cachedMeasurements[layout->nextCachedMeasurementsIndex]; layout->nextCachedMeasurementsIndex++; } @@ -3695,8 +3849,10 @@ bool YGLayoutNodeInternal(const YGNodeRef node, newCacheEntry->availableHeight = availableHeight; newCacheEntry->widthMeasureMode = widthMeasureMode; newCacheEntry->heightMeasureMode = heightMeasureMode; - newCacheEntry->computedWidth = layout->measuredDimensions[YGDimensionWidth]; - newCacheEntry->computedHeight = layout->measuredDimensions[YGDimensionHeight]; + newCacheEntry->computedWidth = + layout->measuredDimensions[YGDimensionWidth]; + newCacheEntry->computedHeight = + layout->measuredDimensions[YGDimensionHeight]; } } @@ -3717,8 +3873,13 @@ bool YGLayoutNodeInternal(const YGNodeRef node, return (needToVisitNode || cachedResults == nullptr); } -void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint) { - YGAssertWithConfig(config, pixelsInPoint >= 0.0f, "Scale factor should not be less than zero"); +void YGConfigSetPointScaleFactor( + const YGConfigRef config, + const float pixelsInPoint) { + YGAssertWithConfig( + 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) { @@ -3729,10 +3890,11 @@ void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInP } } -static void YGRoundToPixelGrid(const YGNodeRef node, - const float pointScaleFactor, - const float absoluteLeft, - const float absoluteTop) { +static void YGRoundToPixelGrid( + const YGNodeRef node, + const float pointScaleFactor, + const float absoluteLeft, + const float absoluteTop) { if (pointScaleFactor == 0.0f) { return; } @@ -3749,8 +3911,8 @@ static void YGRoundToPixelGrid(const YGNodeRef node, const float absoluteNodeRight = absoluteNodeLeft + nodeWidth; const float absoluteNodeBottom = absoluteNodeTop + nodeHeight; - // If a node has a custom measure function we never want to round down its size as this could - // lead to unwanted text truncation. + // If a node has a custom measure function we never want to round down its + // size as this could lead to unwanted text truncation. const bool textRounding = node->getNodeType() == YGNodeTypeText; node->setLayoutPosition( @@ -3761,13 +3923,15 @@ static void YGRoundToPixelGrid(const YGNodeRef node, YGRoundValueToPixelGrid(nodeTop, pointScaleFactor, false, textRounding), YGEdgeTop); - // We multiply dimension by scale factor and if the result is close to the whole number, we don't - // have any fraction - // To verify if the result is close to whole number we want to check both floor and ceil numbers - const bool hasFractionalWidth = !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) && - !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0); - const bool hasFractionalHeight = !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) && - !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0); + // We multiply dimension by scale factor and if the result is close to the + // whole number, we don't have any fraction To verify if the result is close + // to whole number we want to check both floor and ceil numbers + const bool hasFractionalWidth = + !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 0) && + !YGFloatsEqual(fmodf(nodeWidth * pointScaleFactor, 1.0), 1.0); + const bool hasFractionalHeight = + !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 0) && + !YGFloatsEqual(fmodf(nodeHeight * pointScaleFactor, 1.0), 1.0); node->setLayoutDimension( YGRoundValueToPixelGrid( @@ -3844,7 +4008,8 @@ void YGNodeCalculateLayout( node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight) .isUndefined()) { - height = YGUnwrapFloatOptional(YGResolveValue(node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); + height = YGUnwrapFloatOptional(YGResolveValue( + node->getStyle().maxDimensions[YGDimensionHeight], ownerHeight)); heightMeasureMode = YGMeasureModeAtMost; } else { height = ownerHeight; @@ -3950,12 +4115,14 @@ void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( config->shouldDiffLayoutWithoutLegacyStretchBehaviour = shouldDiffLayout; } -static void YGVLog(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { - const YGConfigRef logConfig = config != nullptr ? config : YGConfigGetDefault(); +static void YGVLog( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args) { + const YGConfigRef logConfig = + config != nullptr ? config : YGConfigGetDefault(); logConfig->logger(logConfig, node, level, format, args); if (level == YGLogLevelFatal) { @@ -3963,14 +4130,18 @@ static void YGVLog(const YGConfigRef config, } } -void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...) { +void YGLogWithConfig( + const YGConfigRef config, + YGLogLevel level, + const char* format, + ...) { va_list args; va_start(args, format); YGVLog(config, nullptr, level, format, args); va_end(args); } -void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) { +void YGLog(const YGNodeRef node, YGLogLevel level, const char* format, ...) { va_list args; va_start(args, format); YGVLog( @@ -3978,32 +4149,40 @@ void YGLog(const YGNodeRef node, YGLogLevel level, const char *format, ...) { va_end(args); } -void YGAssert(const bool condition, const char *message) { +void YGAssert(const bool condition, const char* message) { if (!condition) { YGLog(nullptr, YGLogLevelFatal, "%s\n", message); } } -void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message) { +void YGAssertWithNode( + const YGNodeRef node, + const bool condition, + const char* message) { if (!condition) { YGLog(node, YGLogLevelFatal, "%s\n", message); } } -void YGAssertWithConfig(const YGConfigRef config, const bool condition, const char *message) { +void YGAssertWithConfig( + const YGConfigRef config, + const bool condition, + const char* message) { if (!condition) { YGLogWithConfig(config, YGLogLevelFatal, "%s\n", message); } } -void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature, - const bool enabled) { +void YGConfigSetExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature, + const bool enabled) { config->experimentalFeatures[feature] = enabled; } -inline bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature) { +inline bool YGConfigIsExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature) { return config->experimentalFeatures[feature]; } @@ -4011,8 +4190,9 @@ void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled) { config->useWebDefaults = enabled; } -void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config, - const bool useLegacyStretchBehaviour) { +void YGConfigSetUseLegacyStretchBehaviour( + const YGConfigRef config, + const bool useLegacyStretchBehaviour) { config->useLegacyStretchBehaviour = useLegacyStretchBehaviour; } @@ -4020,26 +4200,32 @@ bool YGConfigGetUseWebDefaults(const YGConfigRef config) { return config->useWebDefaults; } -void YGConfigSetContext(const YGConfigRef config, void *context) { +void YGConfigSetContext(const YGConfigRef config, void* context) { config->context = context; } -void *YGConfigGetContext(const YGConfigRef config) { +void* YGConfigGetContext(const YGConfigRef config) { return config->context; } -void YGConfigSetCloneNodeFunc(const YGConfigRef config, const YGCloneNodeFunc callback) { +void YGConfigSetCloneNodeFunc( + const YGConfigRef config, + const YGCloneNodeFunc callback) { config->cloneNodeCallback = callback; } -static void YGTraverseChildrenPreOrder(const YGVector& children, const std::function& f) { +static void YGTraverseChildrenPreOrder( + const YGVector& children, + const std::function& f) { for (YGNodeRef node : children) { f(node); YGTraverseChildrenPreOrder(node->getChildren(), f); } } -void YGTraversePreOrder(YGNodeRef const node, std::function&& f) { +void YGTraversePreOrder( + YGNodeRef const node, + std::function&& f) { if (!node) { return; } diff --git a/yoga/Yoga.h b/yoga/Yoga.h index a9fc89d7..fee2e328 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -1,10 +1,10 @@ -/** - * Copyright (c) 2014-present, Facebook, Inc. +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. * - * 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 @@ -45,23 +45,26 @@ typedef struct YGValue { extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto; -typedef struct YGConfig *YGConfigRef; +typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; -typedef YGSize (*YGMeasureFunc)(YGNodeRef node, - float width, - YGMeasureMode widthMode, - float height, - YGMeasureMode heightMode); -typedef float (*YGBaselineFunc)(YGNodeRef node, const float width, const float height); +typedef YGSize (*YGMeasureFunc)( + YGNodeRef node, + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode); +typedef float ( + *YGBaselineFunc)(YGNodeRef node, const float width, const float height); typedef void (*YGDirtiedFunc)(YGNodeRef node); typedef void (*YGPrintFunc)(YGNodeRef node); -typedef int (*YGLogger)(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args); +typedef int (*YGLogger)( + const YGConfigRef config, + const YGNodeRef node, + YGLogLevel level, + const char* format, + va_list args); typedef YGNodeRef ( *YGCloneNodeFunc)(YGNodeRef oldNode, YGNodeRef owner, int childIndex); @@ -74,9 +77,10 @@ WIN_EXPORT void YGNodeFreeRecursive(const YGNodeRef node); WIN_EXPORT void YGNodeReset(const YGNodeRef node); WIN_EXPORT int32_t YGNodeGetInstanceCount(void); -WIN_EXPORT void YGNodeInsertChild(const YGNodeRef node, - const YGNodeRef child, - const uint32_t index); +WIN_EXPORT void YGNodeInsertChild( + const YGNodeRef node, + const YGNodeRef child, + const uint32_t index); // This function inserts the child YGNodeRef as a children of the node received // by parameter and set the Owner of the child object to null. This function is @@ -99,10 +103,11 @@ WIN_EXPORT void YGNodeSetChildren( const YGNodeRef children[], const uint32_t count); -WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node, - const float availableWidth, - const float availableHeight, - const YGDirection ownerDirection); +WIN_EXPORT void YGNodeCalculateLayout( + const YGNodeRef node, + const float availableWidth, + const float availableHeight, + const YGDirection ownerDirection); // Mark a node as dirty. Only valid for nodes with a custom measure function // set. @@ -112,70 +117,78 @@ WIN_EXPORT void YGNodeCalculateLayout(const YGNodeRef node, // marking manually. WIN_EXPORT void YGNodeMarkDirty(const YGNodeRef node); -// This function marks the current node and all its descendants as dirty. This function is added to test yoga benchmarks. -// This function is not expected to be used in production as calling `YGCalculateLayout` will cause the recalculation of each and every node. +// This function marks the current node and all its descendants as dirty. This +// function is added to test yoga benchmarks. This function is not expected to +// be used in production as calling `YGCalculateLayout` will cause the +// recalculation of each and every node. WIN_EXPORT void YGNodeMarkDirtyAndPropogateToDescendants(const YGNodeRef node); WIN_EXPORT void YGNodePrint(const YGNodeRef node, const YGPrintOptions options); WIN_EXPORT bool YGFloatIsUndefined(const float value); -WIN_EXPORT bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode, - const float width, - const YGMeasureMode heightMode, - const float height, - const YGMeasureMode lastWidthMode, - const float lastWidth, - const YGMeasureMode lastHeightMode, - const float lastHeight, - const float lastComputedWidth, - const float lastComputedHeight, - const float marginRow, - const float marginColumn, - const YGConfigRef config); +WIN_EXPORT bool YGNodeCanUseCachedMeasurement( + const YGMeasureMode widthMode, + const float width, + const YGMeasureMode heightMode, + const float height, + const YGMeasureMode lastWidthMode, + const float lastWidth, + const YGMeasureMode lastHeightMode, + const float lastHeight, + const float lastComputedWidth, + const float lastComputedHeight, + const float marginRow, + const float marginColumn, + const YGConfigRef config); -WIN_EXPORT void YGNodeCopyStyle(const YGNodeRef dstNode, const YGNodeRef srcNode); +WIN_EXPORT void YGNodeCopyStyle( + const YGNodeRef dstNode, + const YGNodeRef srcNode); #define YG_NODE_PROPERTY(type, name, paramName) \ WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \ WIN_EXPORT type YGNodeGet##name(const YGNodeRef node); -#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const type paramName); \ +#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); -#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, const float paramName); \ +#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const float paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); #define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \ YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node); -#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ - const YGEdge edge, \ - const type paramName); \ +#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const type paramName); \ WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name(const YGNodeRef node, \ - const YGEdge edge, \ - const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent(const YGNodeRef node, \ - const YGEdge edge, \ - const float paramName); \ - WIN_EXPORT WIN_STRUCT(type) YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); +#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ + WIN_EXPORT void YGNodeStyleSet##name( \ + const YGNodeRef node, const YGEdge edge, const float paramName); \ + WIN_EXPORT void YGNodeStyleSet##name##Percent( \ + const YGNodeRef node, const YGEdge edge, const float paramName); \ + WIN_EXPORT WIN_STRUCT(type) \ + YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); #define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node, const YGEdge edge); + WIN_EXPORT void YGNodeStyleSet##name##Auto( \ + const YGNodeRef node, const YGEdge edge); #define YG_NODE_LAYOUT_PROPERTY(type, name) \ WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); #define YG_NODE_LAYOUT_EDGE_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge); + WIN_EXPORT type YGNodeLayoutGet##name( \ + const YGNodeRef node, const YGEdge edge); void* YGNodeGetContext(YGNodeRef node); void YGNodeSetContext(YGNodeRef node, void* context); @@ -224,16 +237,18 @@ YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); // 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. +// 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 +// - 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_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); @@ -247,37 +262,48 @@ YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow); bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef 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. +// 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_NODE_LAYOUT_EDGE_PROPERTY(float, Margin); YG_NODE_LAYOUT_EDGE_PROPERTY(float, Border); YG_NODE_LAYOUT_EDGE_PROPERTY(float, Padding); WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger); -WIN_EXPORT void YGLog(const YGNodeRef node, YGLogLevel level, const char *message, ...); -WIN_EXPORT void YGLogWithConfig(const YGConfigRef config, YGLogLevel level, const char *format, ...); -WIN_EXPORT void YGAssert(const bool condition, const char *message); -WIN_EXPORT void YGAssertWithNode(const YGNodeRef node, const bool condition, const char *message); -WIN_EXPORT void YGAssertWithConfig(const YGConfigRef config, - const bool condition, - const char *message); +WIN_EXPORT void +YGLog(const YGNodeRef node, YGLogLevel level, const char* message, ...); +WIN_EXPORT void YGLogWithConfig( + const YGConfigRef config, + YGLogLevel level, + const char* format, + ...); +WIN_EXPORT void YGAssert(const bool condition, const char* message); +WIN_EXPORT void YGAssertWithNode( + const YGNodeRef node, + const bool condition, + const char* message); +WIN_EXPORT void YGAssertWithConfig( + const YGConfigRef config, + const bool condition, + const char* message); // Set this to number of pixels in 1 point to round calculation results // If you want to avoid rounding - set PointScaleFactor to 0 -WIN_EXPORT void YGConfigSetPointScaleFactor(const YGConfigRef config, const float pixelsInPoint); +WIN_EXPORT void YGConfigSetPointScaleFactor( + const YGConfigRef config, + const float pixelsInPoint); void YGConfigSetShouldDiffLayoutWithoutLegacyStretchBehaviour( const YGConfigRef config, const bool shouldDiffLayout); -// Yoga previously had an error where containers would take the maximum space possible instead of -// the minimum -// like they are supposed to. In practice this resulted in implicit behaviour similar to align-self: -// stretch; -// Because this was such a long-standing bug we must allow legacy users to switch back to this -// behaviour. -WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour(const YGConfigRef config, - const bool useLegacyStretchBehaviour); +// Yoga previously had an error where containers would take the maximum space +// possible instead of the minimum like they are supposed to. In practice this +// resulted in implicit behaviour similar to align-self: stretch; Because this +// was such a long-standing bug we must allow legacy users to switch back to +// this behaviour. +WIN_EXPORT void YGConfigSetUseLegacyStretchBehaviour( + const YGConfigRef config, + const bool useLegacyStretchBehaviour); // YGConfig WIN_EXPORT YGConfigRef YGConfigNew(void); @@ -285,25 +311,30 @@ WIN_EXPORT void YGConfigFree(const YGConfigRef config); WIN_EXPORT void YGConfigCopy(const YGConfigRef dest, const YGConfigRef src); WIN_EXPORT int32_t YGConfigGetInstanceCount(void); -WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature, - const bool enabled); -WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled(const YGConfigRef config, - const YGExperimentalFeature feature); +WIN_EXPORT void YGConfigSetExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature, + const bool enabled); +WIN_EXPORT bool YGConfigIsExperimentalFeatureEnabled( + const YGConfigRef config, + const YGExperimentalFeature feature); // Using the web defaults is the prefered configuration for new projects. // Usage of non web defaults should be considered as legacy. -WIN_EXPORT void YGConfigSetUseWebDefaults(const YGConfigRef config, const bool enabled); +WIN_EXPORT void YGConfigSetUseWebDefaults( + const YGConfigRef config, + const bool enabled); WIN_EXPORT bool YGConfigGetUseWebDefaults(const YGConfigRef config); -WIN_EXPORT void YGConfigSetCloneNodeFunc(const YGConfigRef config, - const YGCloneNodeFunc callback); +WIN_EXPORT void YGConfigSetCloneNodeFunc( + const YGConfigRef config, + const YGCloneNodeFunc callback); // Export only for C# WIN_EXPORT YGConfigRef YGConfigGetDefault(void); -WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void *context); -WIN_EXPORT void *YGConfigGetContext(const YGConfigRef config); +WIN_EXPORT void YGConfigSetContext(const YGConfigRef config, void* context); +WIN_EXPORT void* YGConfigGetContext(const YGConfigRef config); WIN_EXPORT float YGRoundValueToPixelGrid( const float value, @@ -319,7 +350,9 @@ YG_EXTERN_C_END #include // Calls f on each node in the tree including the given node argument. -extern void YGTraversePreOrder(YGNodeRef const node, std::function&& f); +extern void YGTraversePreOrder( + YGNodeRef const node, + std::function&& f); extern void YGNodeSetChildren( YGNodeRef const owner, From 4be229059c75d01542be6af35f422debb5e07623 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:06 -0700 Subject: [PATCH 26/29] Yoga.h: inline function declaring macros Summary: @public Inlines macros used for declarations of `YGNodeStyle*` and `YGNodeLayout*` functions. Benefits easier grepping and code base navigation. Reviewed By: astreet Differential Revision: D8868168 fbshipit-source-id: d6b1b70981a59a2214dc7d166435a1d1a844e1b7 --- yoga/Yoga.h | 255 +++++++++++++++++++++++++++++++++++----------------- 1 file changed, 174 insertions(+), 81 deletions(-) diff --git a/yoga/Yoga.h b/yoga/Yoga.h index fee2e328..d6b12d29 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -146,50 +146,6 @@ WIN_EXPORT void YGNodeCopyStyle( const YGNodeRef dstNode, const YGNodeRef srcNode); -#define YG_NODE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeSet##name(const YGNodeRef node, type paramName); \ - WIN_EXPORT type YGNodeGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const type paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const float paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node); - -#define YG_NODE_STYLE_PROPERTY_UNIT_AUTO(type, name, paramName) \ - YG_NODE_STYLE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto(const YGNodeRef node); - -#define YG_NODE_STYLE_EDGE_PROPERTY(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const type paramName); \ - WIN_EXPORT type YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT(type, name, paramName) \ - WIN_EXPORT void YGNodeStyleSet##name( \ - const YGNodeRef node, const YGEdge edge, const float paramName); \ - WIN_EXPORT void YGNodeStyleSet##name##Percent( \ - const YGNodeRef node, const YGEdge edge, const float paramName); \ - WIN_EXPORT WIN_STRUCT(type) \ - YGNodeStyleGet##name(const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(type, name) \ - WIN_EXPORT void YGNodeStyleSet##name##Auto( \ - const YGNodeRef node, const YGEdge edge); - -#define YG_NODE_LAYOUT_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name(const YGNodeRef node); - -#define YG_NODE_LAYOUT_EDGE_PROPERTY(type, name) \ - WIN_EXPORT type YGNodeLayoutGet##name( \ - const YGNodeRef node, const YGEdge edge); - void* YGNodeGetContext(YGNodeRef node); void YGNodeSetContext(YGNodeRef node, void* context); YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node); @@ -207,33 +163,165 @@ void YGNodeSetNodeType(YGNodeRef node, YGNodeType nodeType); bool YGNodeIsDirty(YGNodeRef node); bool YGNodeLayoutGetDidUseLegacyFlag(const YGNodeRef node); -YG_NODE_STYLE_PROPERTY(YGDirection, Direction, direction); -YG_NODE_STYLE_PROPERTY(YGFlexDirection, FlexDirection, flexDirection); -YG_NODE_STYLE_PROPERTY(YGJustify, JustifyContent, justifyContent); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignContent, alignContent); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignItems, alignItems); -YG_NODE_STYLE_PROPERTY(YGAlign, AlignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY(YGPositionType, PositionType, positionType); -YG_NODE_STYLE_PROPERTY(YGWrap, FlexWrap, flexWrap); -YG_NODE_STYLE_PROPERTY(YGOverflow, Overflow, overflow); -YG_NODE_STYLE_PROPERTY(YGDisplay, Display, display); -YG_NODE_STYLE_PROPERTY(float, Flex, flex); -YG_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow); -YG_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, FlexBasis, flexBasis); +WIN_EXPORT void YGNodeStyleSetDirection( + const YGNodeRef node, + const YGDirection direction); +WIN_EXPORT YGDirection YGNodeStyleGetDirection(const YGNodeRef node); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Position, position); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Margin, margin); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT_AUTO(YGValue, Margin); -YG_NODE_STYLE_EDGE_PROPERTY_UNIT(YGValue, Padding, padding); -YG_NODE_STYLE_EDGE_PROPERTY(float, Border, border); +WIN_EXPORT void YGNodeStyleSetFlexDirection( + const YGNodeRef node, + const YGFlexDirection flexDirection); +WIN_EXPORT YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Width, width); -YG_NODE_STYLE_PROPERTY_UNIT_AUTO(YGValue, Height, height); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinWidth, minWidth); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MinHeight, minHeight); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxWidth, maxWidth); -YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); +WIN_EXPORT void YGNodeStyleSetJustifyContent( + const YGNodeRef node, + const YGJustify justifyContent); +WIN_EXPORT YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignContent( + const YGNodeRef node, + const YGAlign alignContent); +WIN_EXPORT YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignItems( + const YGNodeRef node, + const YGAlign alignItems); +WIN_EXPORT YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetAlignSelf( + const YGNodeRef node, + const YGAlign alignSelf); +WIN_EXPORT YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetPositionType( + const YGNodeRef node, + const YGPositionType positionType); +WIN_EXPORT YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexWrap( + const YGNodeRef node, + const YGWrap flexWrap); +WIN_EXPORT YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetOverflow( + const YGNodeRef node, + const YGOverflow overflow); +WIN_EXPORT YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetDisplay( + const YGNodeRef node, + const YGDisplay display); +WIN_EXPORT YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlex(const YGNodeRef node, const float flex); +WIN_EXPORT float YGNodeStyleGetFlex(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexGrow( + const YGNodeRef node, + const float flexGrow); +WIN_EXPORT float YGNodeStyleGetFlexGrow(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexShrink( + const YGNodeRef node, + const float flexShrink); +WIN_EXPORT float YGNodeStyleGetFlexShrink(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetFlexBasis( + const YGNodeRef node, + const float flexBasis); +WIN_EXPORT void YGNodeStyleSetFlexBasisPercent( + const YGNodeRef node, + const float flexBasis); +WIN_EXPORT void YGNodeStyleSetFlexBasisAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetFlexBasis(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetPosition( + const YGNodeRef node, + const YGEdge edge, + const float position); +WIN_EXPORT void YGNodeStyleSetPositionPercent( + const YGNodeRef node, + const YGEdge edge, + const float position); +WIN_EXPORT WIN_STRUCT(YGValue) + YGNodeStyleGetPosition(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetMargin( + const YGNodeRef node, + const YGEdge edge, + const float margin); +WIN_EXPORT void YGNodeStyleSetMarginPercent( + const YGNodeRef node, + const YGEdge edge, + const float margin); +WIN_EXPORT void YGNodeStyleSetMarginAuto( + const YGNodeRef node, + const YGEdge edge); +WIN_EXPORT YGValue +YGNodeStyleGetMargin(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetPadding( + const YGNodeRef node, + const YGEdge edge, + const float padding); +WIN_EXPORT void YGNodeStyleSetPaddingPercent( + const YGNodeRef node, + const YGEdge edge, + const float padding); +WIN_EXPORT YGValue +YGNodeStyleGetPadding(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetBorder( + const YGNodeRef node, + const YGEdge edge, + const float border); +WIN_EXPORT float YGNodeStyleGetBorder(const YGNodeRef node, const YGEdge edge); + +WIN_EXPORT void YGNodeStyleSetWidth(const YGNodeRef node, const float width); +WIN_EXPORT void YGNodeStyleSetWidthPercent( + const YGNodeRef node, + const float width); +WIN_EXPORT void YGNodeStyleSetWidthAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetHeight(const YGNodeRef node, const float height); +WIN_EXPORT void YGNodeStyleSetHeightPercent( + const YGNodeRef node, + const float height); +WIN_EXPORT void YGNodeStyleSetHeightAuto(const YGNodeRef node); +WIN_EXPORT YGValue YGNodeStyleGetHeight(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMinWidth( + const YGNodeRef node, + const float minWidth); +WIN_EXPORT void YGNodeStyleSetMinWidthPercent( + const YGNodeRef node, + const float minWidth); +WIN_EXPORT YGValue YGNodeStyleGetMinWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMinHeight( + const YGNodeRef node, + const float minHeight); +WIN_EXPORT void YGNodeStyleSetMinHeightPercent( + const YGNodeRef node, + const float minHeight); +WIN_EXPORT YGValue YGNodeStyleGetMinHeight(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMaxWidth( + const YGNodeRef node, + const float maxWidth); +WIN_EXPORT void YGNodeStyleSetMaxWidthPercent( + const YGNodeRef node, + const float maxWidth); +WIN_EXPORT YGValue YGNodeStyleGetMaxWidth(const YGNodeRef node); + +WIN_EXPORT void YGNodeStyleSetMaxHeight( + const YGNodeRef node, + const float maxHeight); +WIN_EXPORT void YGNodeStyleSetMaxHeightPercent( + const YGNodeRef node, + const float maxHeight); +WIN_EXPORT YGValue YGNodeStyleGetMaxHeight(const YGNodeRef node); // Yoga specific properties, not compatible with flexbox specification // Aspect ratio control the size of the undefined dimension of a node. @@ -250,25 +338,30 @@ YG_NODE_STYLE_PROPERTY_UNIT(YGValue, MaxHeight, maxHeight); // - 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_NODE_STYLE_PROPERTY(float, AspectRatio, aspectRatio); +WIN_EXPORT void YGNodeStyleSetAspectRatio( + const YGNodeRef node, + const float aspectRatio); +WIN_EXPORT float YGNodeStyleGetAspectRatio(const YGNodeRef node); -YG_NODE_LAYOUT_PROPERTY(float, Left); -YG_NODE_LAYOUT_PROPERTY(float, Top); -YG_NODE_LAYOUT_PROPERTY(float, Right); -YG_NODE_LAYOUT_PROPERTY(float, Bottom); -YG_NODE_LAYOUT_PROPERTY(float, Width); -YG_NODE_LAYOUT_PROPERTY(float, Height); -YG_NODE_LAYOUT_PROPERTY(YGDirection, Direction); -YG_NODE_LAYOUT_PROPERTY(bool, HadOverflow); +WIN_EXPORT float YGNodeLayoutGetLeft(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetTop(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetRight(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetBottom(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetWidth(const YGNodeRef node); +WIN_EXPORT float YGNodeLayoutGetHeight(const YGNodeRef node); +WIN_EXPORT YGDirection YGNodeLayoutGetDirection(const YGNodeRef node); +WIN_EXPORT bool YGNodeLayoutGetHadOverflow(const YGNodeRef node); bool YGNodeLayoutGetDidLegacyStretchFlagAffectLayout(const YGNodeRef 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_NODE_LAYOUT_EDGE_PROPERTY(float, Margin); -YG_NODE_LAYOUT_EDGE_PROPERTY(float, Border); -YG_NODE_LAYOUT_EDGE_PROPERTY(float, Padding); +WIN_EXPORT float YGNodeLayoutGetMargin(const YGNodeRef node, const YGEdge edge); +WIN_EXPORT float YGNodeLayoutGetBorder(const YGNodeRef node, const YGEdge edge); +WIN_EXPORT float YGNodeLayoutGetPadding( + const YGNodeRef node, + const YGEdge edge); WIN_EXPORT void YGConfigSetLogger(const YGConfigRef config, YGLogger logger); WIN_EXPORT void From 4caed8feb5189fdcae9c9a7f8b3e3c995093f708 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Thu, 19 Jul 2018 09:57:08 -0700 Subject: [PATCH 27/29] Replace `YG_NODE_STYLE_PROPERTY_IMPL` macro with template Summary: @public Replacing the `YG_NODE_STYLE_PROPERTY_IMPL` macro with template code, in order to make code easier to edit and grep. Reviewed By: astreet Differential Revision: D8868184 fbshipit-source-id: f52537376fa8d4dd53aa98bb43e93279699dbdd5 --- yoga/Yoga.cpp | 137 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 95 insertions(+), 42 deletions(-) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c9404dec..c9799c3c 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -576,16 +576,24 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { : node->getStyle().flexShrink.getValue(); } -#define YG_NODE_STYLE_PROPERTY_SETTER_IMPL( \ - type, name, paramName, instanceName) \ - void YGNodeStyleSet##name(const YGNodeRef node, const type paramName) { \ - if (node->getStyle().instanceName != paramName) { \ - YGStyle style = node->getStyle(); \ - style.instanceName = paramName; \ - node->setStyle(style); \ - node->markDirtyAndPropogate(); \ - } \ +namespace { + +template +struct StyleProp { + static T get(YGNodeRef node) { + return node->getStyle().*P; } + static void set(YGNodeRef node, T newValue) { + if (node->getStyle().*P != newValue) { + YGStyle style = node->getStyle(); + style.*P = newValue; + node->setStyle(style); + node->markDirtyAndPropogate(); + } + } +}; + +} // namespace #define YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ type, name, paramName, instanceName) \ @@ -661,13 +669,6 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { } \ } -#define YG_NODE_STYLE_PROPERTY_IMPL(type, name, paramName, instanceName) \ - YG_NODE_STYLE_PROPERTY_SETTER_IMPL(type, name, paramName, instanceName) \ - \ - type YGNodeStyleGet##name(const YGNodeRef node) { \ - return node->getStyle().instanceName; \ - } - #define YG_NODE_STYLE_PROPERTY_UNIT_IMPL(type, name, paramName, instanceName) \ YG_NODE_STYLE_PROPERTY_SETTER_UNIT_IMPL( \ float, name, paramName, instanceName) \ @@ -778,33 +779,85 @@ float YGNodeStyleGetFlexShrink(const YGNodeRef node) { return node->getLayout().instanceName[edge]; \ } -// YG_NODE_PROPERTY_IMPL(void *, Context, context, context); -// YG_NODE_PROPERTY_IMPL(YGPrintFunc, PrintFunc, printFunc, print); -// YG_NODE_PROPERTY_IMPL(bool, HasNewLayout, hasNewLayout, hasNewLayout); -// YG_NODE_PROPERTY_IMPL(YGNodeType, NodeType, nodeType, nodeType); +void YGNodeStyleSetDirection( + const YGNodeRef node, + const YGDirection direction) { + StyleProp::set(node, direction); +} +YGDirection YGNodeStyleGetDirection(const YGNodeRef node) { + return StyleProp::get(node); +} -YG_NODE_STYLE_PROPERTY_IMPL(YGDirection, Direction, direction, direction); -YG_NODE_STYLE_PROPERTY_IMPL( - YGFlexDirection, - FlexDirection, - flexDirection, - flexDirection); -YG_NODE_STYLE_PROPERTY_IMPL( - YGJustify, - JustifyContent, - justifyContent, - justifyContent); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignContent, alignContent, alignContent); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignItems, alignItems, alignItems); -YG_NODE_STYLE_PROPERTY_IMPL(YGAlign, AlignSelf, alignSelf, alignSelf); -YG_NODE_STYLE_PROPERTY_IMPL( - YGPositionType, - PositionType, - positionType, - positionType); -YG_NODE_STYLE_PROPERTY_IMPL(YGWrap, FlexWrap, flexWrap, flexWrap); -YG_NODE_STYLE_PROPERTY_IMPL(YGOverflow, Overflow, overflow, overflow); -YG_NODE_STYLE_PROPERTY_IMPL(YGDisplay, Display, display, display); +void YGNodeStyleSetFlexDirection( + const YGNodeRef node, + const YGFlexDirection flexDirection) { + StyleProp::set(node, flexDirection); +} +YGFlexDirection YGNodeStyleGetFlexDirection(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetJustifyContent( + const YGNodeRef node, + const YGJustify justifyContent) { + StyleProp::set(node, justifyContent); +} +YGJustify YGNodeStyleGetJustifyContent(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignContent( + const YGNodeRef node, + const YGAlign alignContent) { + StyleProp::set(node, alignContent); +} +YGAlign YGNodeStyleGetAlignContent(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignItems(const YGNodeRef node, const YGAlign alignItems) { + StyleProp::set(node, alignItems); +} +YGAlign YGNodeStyleGetAlignItems(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetAlignSelf(const YGNodeRef node, const YGAlign alignSelf) { + StyleProp::set(node, alignSelf); +} +YGAlign YGNodeStyleGetAlignSelf(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetPositionType( + const YGNodeRef node, + const YGPositionType positionType) { + StyleProp::set(node, positionType); +} +YGPositionType YGNodeStyleGetPositionType(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetFlexWrap(const YGNodeRef node, const YGWrap flexWrap) { + StyleProp::set(node, flexWrap); +} +YGWrap YGNodeStyleGetFlexWrap(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetOverflow(const YGNodeRef node, const YGOverflow overflow) { + StyleProp::set(node, overflow); +} +YGOverflow YGNodeStyleGetOverflow(const YGNodeRef node) { + return StyleProp::get(node); +} + +void YGNodeStyleSetDisplay(const YGNodeRef node, const YGDisplay display) { + StyleProp::set(node, display); +} +YGDisplay YGNodeStyleGetDisplay(const YGNodeRef node) { + return StyleProp::get(node); +} // TODO(T26792433): Change the API to accept YGFloatOptional. void YGNodeStyleSetFlex(const YGNodeRef node, const float flex) { From eaaf0fdfe29d47d76135222d3500d0426992b149 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Mon, 23 Jul 2018 13:24:21 -0700 Subject: [PATCH 28/29] Implementation of `operator==` for YGValue Summary: @public It's very useful sometimes for product code to compare `YGValue`s (e.g. in Fabric). Reviewed By: priteshrnandgaonkar Differential Revision: D8937594 fbshipit-source-id: b93e1ab4a6419ada6746f233b587e8c9cb32c6d4 --- yoga/Yoga.cpp | 13 +++++++++++++ yoga/Yoga.h | 7 +++++++ 2 files changed, 20 insertions(+) diff --git a/yoga/Yoga.cpp b/yoga/Yoga.cpp index c9799c3c..b9a5f781 100644 --- a/yoga/Yoga.cpp +++ b/yoga/Yoga.cpp @@ -48,6 +48,19 @@ const YGValue YGValueZero = {0, YGUnitPoint}; const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined}; const YGValue YGValueAuto = {YGUndefined, YGUnitAuto}; +bool operator==(const YGValue& lhs, const YGValue& rhs) { + if ((lhs.unit == YGUnitUndefined && rhs.unit == YGUnitUndefined) || + (lhs.unit == YGUnitAuto && rhs.unit == YGUnitAuto)) { + return true; + } + + return lhs.unit == rhs.unit && lhs.value == rhs.value; +} + +bool operator!=(const YGValue& lhs, const YGValue& rhs) { + return !(lhs == rhs); +} + #ifdef ANDROID #include static int YGAndroidLog( diff --git a/yoga/Yoga.h b/yoga/Yoga.h index d6b12d29..5bcbe2ab 100644 --- a/yoga/Yoga.h +++ b/yoga/Yoga.h @@ -45,6 +45,13 @@ typedef struct YGValue { extern const YGValue YGValueUndefined; extern const YGValue YGValueAuto; +#ifdef __cplusplus + +extern bool operator==(const YGValue& lhs, const YGValue& rhs); +extern bool operator!=(const YGValue& lhs, const YGValue& rhs); + +#endif + typedef struct YGConfig* YGConfigRef; typedef struct YGNode* YGNodeRef; From 7b87ded288dbdb5c44a7cb52ef9643a58ce76623 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Mon, 23 Jul 2018 14:50:46 -0700 Subject: [PATCH 29/29] Add tests for style properties Summary: @public The existing test suite does not check every single style property settable in Java for defaults, reads, and effect on layout. Here, we add these test, in order to make evolving the Java/C++ bridge as safe as possible. Reviewed By: pasqualeanatriello Differential Revision: D8952470 fbshipit-source-id: a94933adff01c313b3f440eb5207d2cb6a54a85d --- .../yoga/YogaNodeStylePropertiesTest.java | 983 ++++++++++++++++++ 1 file changed, 983 insertions(+) create mode 100644 java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java diff --git a/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java new file mode 100644 index 00000000..8efcdd13 --- /dev/null +++ b/java/tests/com/facebook/yoga/YogaNodeStylePropertiesTest.java @@ -0,0 +1,983 @@ +/* + * Copyright (c) 2014-present, Facebook, Inc. + * + * This source code is licensed under the MIT license found in the LICENSE + * file in the root directory of this source tree. + * + */ +package com.facebook.yoga; + +import static org.junit.Assert.assertEquals; + +import org.junit.Test; + +public class YogaNodeStylePropertiesTest { + + private static final float UNDEFINED = YogaValue.UNDEFINED.value; + + @Test + public void testDirectionDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(node.getStyleDirection(), YogaDirection.INHERIT); + assertEquals(node.getLayoutDirection(), YogaDirection.INHERIT); + } + + @Test + public void testDirectionAssignment() { + final YogaNode node = new YogaNode(); + node.setDirection(YogaDirection.LTR); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(YogaDirection.LTR, node.getStyleDirection()); + assertEquals(YogaDirection.LTR, node.getLayoutDirection()); + } + + @Test + public void testDirectionAffectsLayout() { + final YogaNode node = + style().direction(YogaDirection.RTL).width(200).children(style().widthPercent(40)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(120, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testFlexDirectionDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaFlexDirection.COLUMN, node.getFlexDirection()); + } + + @Test + public void testFlexDirectionAssignment() { + final YogaNode node = style().flexDirection(YogaFlexDirection.COLUMN_REVERSE).node(); + + assertEquals(YogaFlexDirection.COLUMN_REVERSE, node.getFlexDirection()); + } + + @Test + public void testFlexDirectionAffectsLayout() { + final YogaNode node = + style() + .flexDirection(YogaFlexDirection.ROW_REVERSE) + .width(200) + .children(style().widthPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(120, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testJustifyContentDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaJustify.FLEX_START, node.getJustifyContent()); + } + + @Test + public void testJustifyContentAssignment() { + final YogaNode node = new YogaNode(); + node.setJustifyContent(YogaJustify.SPACE_EVENLY); + + assertEquals(YogaJustify.SPACE_EVENLY, node.getJustifyContent()); + } + + @Test + public void testJustifyContentAffectsLayout() { + final YogaNode node = + style() + .justifyContent(YogaJustify.CENTER) + .height(200) + .children(style().heightPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testAlignItemsDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.STRETCH, node.getAlignItems()); + } + + @Test + public void testAlignItemsAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignItems(YogaAlign.SPACE_AROUND); + + assertEquals(YogaAlign.SPACE_AROUND, node.getAlignItems()); + } + + @Test + public void testAlignItemsAffectsLayout() { + final YogaNode node = + style().alignItems(YogaAlign.CENTER).height(200).children(style().widthPercent(40)).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testAlignSelfDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.AUTO, node.getAlignSelf()); + } + + @Test + public void testAlignSelfAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignSelf(YogaAlign.FLEX_END); + + assertEquals(YogaAlign.FLEX_END, node.getAlignSelf()); + } + + @Test + public void testAlignSelfAffectsLayout() { + final YogaNode node = + style().height(200).children(style().alignSelf(YogaAlign.CENTER).widthPercent(40)).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(60, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testAlignContentDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaAlign.FLEX_START, node.getAlignContent()); + } + + @Test + public void testAlignContentAssignment() { + final YogaNode node = new YogaNode(); + node.setAlignContent(YogaAlign.BASELINE); + + assertEquals(YogaAlign.BASELINE, node.getAlignContent()); + } + + @Test + public void testAlignContentAffectsLayout() { + final YogaNode node = + style() + .alignContent(YogaAlign.SPACE_AROUND) + .flexWrap(YogaWrap.WRAP) + .height(200) + .width(200) + .children( + style().widthPercent(20).heightPercent(60), + style().widthPercent(20).heightPercent(60)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(30, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testPositionTypeDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaPositionType.RELATIVE, node.getPositionType()); + } + + @Test + public void testPositionTypeAssignment() { + final YogaNode node = new YogaNode(); + node.setPositionType(YogaPositionType.ABSOLUTE); + + assertEquals(YogaPositionType.ABSOLUTE, node.getPositionType()); + } + + @Test + public void testPositionTypeAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children( + style().height(100), style().height(100).positionType(YogaPositionType.ABSOLUTE)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(0, node.getChildAt(1).getLayoutY(), 0); + } + + @Test + public void testWrapAffectsLayout() { + final YogaNode node = + style() + .width(200) + .height(200) + .flexWrap(YogaWrap.WRAP_REVERSE) + .children(style().width(10).heightPercent(60), style().heightPercent(60)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(190, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testOverflowDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaOverflow.VISIBLE, node.getOverflow()); + } + + @Test + public void testOverflowAssignment() { + final YogaNode node = new YogaNode(); + node.setOverflow(YogaOverflow.SCROLL); + + assertEquals(YogaOverflow.SCROLL, node.getOverflow()); + } + + // TODO add testOverflowAffectsLayout() + + @Test + public void testDisplayDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaDisplay.FLEX, node.getDisplay()); + } + + @Test + public void testDisplayAssignment() { + final YogaNode node = new YogaNode(); + node.setDisplay(YogaDisplay.NONE); + + assertEquals(YogaDisplay.NONE, node.getDisplay()); + } + + @Test + public void testDisplayAffectsLayout() { + final YogaNode node = + style().children(style().flexGrow(1).display(YogaDisplay.NONE), style().flexGrow(1)).node(); + node.calculateLayout(200, 200); + + assertEquals(200, node.getChildAt(1).getLayoutHeight(), 0); + } + + @Test + public void testFlexAffectsLayoutGrowing() { + final YogaNode node = style().height(200).children(style().height(100).flex(1.25f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexAffectsLayoutShrinking() { + final YogaNode node = style().height(200).children(style().height(300).flex(1.25f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexGrowDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(0, node.getFlexGrow(), 0); + } + + @Test + public void testFlexGrowAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexGrow(2.5f); + + assertEquals(2.5f, node.getFlexGrow(), 0); + } + + @Test + public void testFlexGrowAffectsLayout() { + final YogaNode node = + style().height(200).children(style().height(50).flexGrow(1), style().height(50)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(150, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexShrinkDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(0, node.getFlexShrink(), 0); + } + + @Test + public void testFlexShrinkAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexShrink(2.5f); + + assertEquals(2.5f, node.getFlexShrink(), 0); + } + + @Test + public void testFlexShrinkAffectsLayout() { + final YogaNode node = + style().height(200).children(style().height(150).flexShrink(1), style().height(150)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(50, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexBasisDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getFlexBasis()); + } + + @Test + public void testFlexBasisAssignment() { + final YogaNode node = new YogaNode(); + node.setFlexBasis(50); + assertEquals(new YogaValue(50, YogaUnit.POINT), node.getFlexBasis()); + + node.setFlexBasisPercent(20); + assertEquals(new YogaValue(20, YogaUnit.PERCENT), node.getFlexBasis()); + + node.setFlexBasisAuto(); + assertEquals(YogaValue.AUTO, node.getFlexBasis()); + } + + @Test + public void testFlexBasisAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children(style().flexBasis(150).flexShrink(1), style().flexBasis(150).flexShrink(1)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(100, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testFlexBasisPercentAffectsLayout() { + final YogaNode node = + style() + .height(200) + .children(style().flexBasisPercent(60), style().flexBasisPercent(40)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(80, node.getChildAt(1).getLayoutHeight(), 0); + } + + @Test + public void testMarginDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getMargin(edge)); + } + } + + @Test + public void testMarginAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setMargin(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getMargin(edge)); + + node.setMarginPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getMargin(edge)); + + node.setMarginAuto(edge); + assertEquals(YogaValue.AUTO, node.getMargin(edge)); + } + } + + @Test + public void testMarginPointAffectsLayout() { + final YogaNode node = style().margin(YogaEdge.TOP, 42).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getLayoutY(), 0); + } + + @Test + public void testMarginPercentAffectsLayout() { + final YogaNode node = + style().height(200).children(style().flexGrow(1).marginPercent(YogaEdge.TOP, 20)).node(); + node.calculateLayout(200, 200); + + assertEquals(40, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testMarginAutoAffectsLayout() { + final YogaNode node = + style() + .width(200) + .flexDirection(YogaFlexDirection.ROW) + .children(style().marginAuto(YogaEdge.LEFT).marginAuto(YogaEdge.RIGHT).width(100)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(50, node.getChildAt(0).getLayoutX(), 0); + } + + @Test + public void testPaddingDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getPadding(edge)); + } + } + + @Test + public void testPaddingAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setPadding(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPadding(edge)); + + node.setPaddingPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getPadding(edge)); + } + } + + @Test + public void testPaddingPointAffectsLayout() { + final YogaNode node = style().padding(YogaEdge.TOP, 42).children(style()).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testPaddingPercentAffectsLayout() { + final YogaNode node = + style().height(200).paddingPercent(YogaEdge.TOP, 20).children(style().flexGrow(1)).node(); + node.calculateLayout(200, 200); + + assertEquals(40, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testBorderDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(UNDEFINED, node.getBorder(edge), 0); + } + } + + @Test + public void testBorderAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setBorder(edge, 2.5f); + assertEquals(2.5f, node.getBorder(edge), 0); + } + } + + @Test + public void testBorderAffectsLayout() { + final YogaNode node = style().border(YogaEdge.TOP, 42).children(style()).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(42, node.getChildAt(0).getLayoutY(), 0); + } + + @Test + public void testPositionDefault() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + assertEquals(YogaValue.UNDEFINED, node.getPosition(edge)); + } + } + + @Test + public void testPositionAssignment() { + final YogaNode node = new YogaNode(); + for (YogaEdge edge : YogaEdge.values()) { + node.setPosition(edge, 25); + assertEquals(new YogaValue(25, YogaUnit.POINT), node.getPosition(edge)); + + node.setPositionPercent(edge, 5); + assertEquals(new YogaValue(5, YogaUnit.PERCENT), node.getPosition(edge)); + } + } + + @Test + public void testPositionAffectsLayout() { + final YogaNode node = + style() + .height(100) + .children( + style() + .positionType(YogaPositionType.ABSOLUTE) + .position(YogaEdge.TOP, 11) + .position(YogaEdge.BOTTOM, 22)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(67, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testPositionPercentAffectsLayout() { + final YogaNode node = + style() + .width(100) + .children( + style() + .positionType(YogaPositionType.ABSOLUTE) + .positionPercent(YogaEdge.LEFT, 11) + .positionPercent(YogaEdge.RIGHT, 22)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(67, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getWidth()); + } + + @Test + public void testWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getWidth()); + + node.setWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getWidth()); + } + + @Test + public void testWidthAffectsLayout() { + final YogaNode node = style().width(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutWidth(), 0); + } + + @Test + public void testWidthPercentAffectsLayout() { + final YogaNode node = style().widthPercent(75).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(150, node.getLayoutWidth(), 0); + } + + // TODO: testWidthAutoAffectsLayout + + @Test + public void testHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.AUTO, node.getHeight()); + } + + @Test + public void testHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getHeight()); + + node.setHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getHeight()); + } + + @Test + public void testHeightAffectsLayout() { + final YogaNode node = style().height(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutHeight(), 0); + } + + @Test + public void testHeightPercentAffectsLayout() { + final YogaNode node = style().heightPercent(75).node(); + node.calculateLayout(UNDEFINED, 200); + + assertEquals(150, node.getLayoutHeight(), 0); + } + + // TODO: testHeightAutoAffectsLayout + + @Test + public void testMinWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMinWidth()); + } + + @Test + public void testMinWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setMinWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinWidth()); + + node.setMinWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMinWidth()); + } + + @Test + public void testMinWidthAffectsLayout() { + final YogaNode node = style().minWidth(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutWidth(), 0); + } + + @Test + public void testMinWidthPercentAffectsLayout() { + final YogaNode node = style().minWidthPercent(120).node(); + node.calculateLayout(200, UNDEFINED); + + assertEquals(240, node.getLayoutWidth(), 0); + } + + @Test + public void testMinHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMinHeight()); + } + + @Test + public void testMinHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setMinHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMinHeight()); + + node.setMinHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMinHeight()); + } + + @Test + public void testMinHeightAffectsLayout() { + final YogaNode node = style().minHeight(123).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getLayoutHeight(), 0); + } + + @Test + public void testMinHeightPercentAffectsLayout() { + final YogaNode node = style().minHeightPercent(120).node(); + node.calculateLayout(UNDEFINED, 200); + + assertEquals(240, node.getLayoutHeight(), 0); + } + + @Test + public void testMaxWidthDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMaxWidth()); + } + + @Test + public void testMaxWidthAssignment() { + final YogaNode node = new YogaNode(); + node.setMaxWidth(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxWidth()); + + node.setMaxWidthPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMaxWidth()); + } + + @Test + public void testMaxWidthAffectsLayout() { + final YogaNode node = style().width(200).children(style().maxWidth(123)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testMaxWidthPercentAffectsLayout() { + final YogaNode node = style().width(200).children(style().maxWidthPercent(80)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(160, node.getChildAt(0).getLayoutWidth(), 0); + } + + @Test + public void testMaxHeightDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(YogaValue.UNDEFINED, node.getMaxHeight()); + } + + @Test + public void testMaxHeightAssignment() { + final YogaNode node = new YogaNode(); + node.setMaxHeight(123); + assertEquals(new YogaValue(123, YogaUnit.POINT), node.getMaxHeight()); + + node.setMaxHeightPercent(45); + assertEquals(new YogaValue(45, YogaUnit.PERCENT), node.getMaxHeight()); + } + + @Test + public void testMaxHeightAffectsLayout() { + final YogaNode node = + style() + .height(200) + .flexDirection(YogaFlexDirection.ROW) + .children(style().maxHeight(123)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(123, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testMaxHeightPercentAffectsLayout() { + final YogaNode node = + style() + .flexDirection(YogaFlexDirection.ROW) + .height(200) + .children(style().maxHeightPercent(80)) + .node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(160, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void testAspectRatioDefault() { + final YogaNode node = new YogaNode(); + + assertEquals(UNDEFINED, node.getAspectRatio(), 0); + } + + @Test + public void testAspectRatioAssignment() { + final YogaNode node = new YogaNode(); + node.setAspectRatio(2.75f); + + assertEquals(2.75f, node.getAspectRatio(), 0); + } + + @Test + public void aspectRatioAffectsLayoutWithGivenWidth() { + final YogaNode node = style().children(style().width(300).aspectRatio(1.5f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(200, node.getChildAt(0).getLayoutHeight(), 0); + } + + @Test + public void aspectRatioAffectsLayoutWithGivenHeight() { + final YogaNode node = style().children(style().height(300).aspectRatio(1.5f)).node(); + node.calculateLayout(UNDEFINED, UNDEFINED); + + assertEquals(450, node.getChildAt(0).getLayoutWidth(), 0); + } + + private static StyledNode style() { + return new StyledNode(); + } + + private static class StyledNode { + + private YogaNode mNode = new YogaNode(); + + YogaNode node() { + return mNode; + } + + StyledNode children(StyledNode... children) { + for (int i = mNode.getChildCount(); --i >= 0; ) { + mNode.removeChildAt(i); + } + for (int i = 0; i < children.length; i++) { + mNode.addChildAt(children[i].node(), i); + } + return this; + } + + StyledNode direction(YogaDirection direction) { + mNode.setDirection(direction); + return this; + } + + StyledNode width(float width) { + mNode.setWidth(width); + return this; + } + + StyledNode widthPercent(float width) { + mNode.setWidthPercent(width); + return this; + } + + StyledNode flexDirection(YogaFlexDirection direction) { + mNode.setFlexDirection(direction); + return this; + } + + StyledNode justifyContent(YogaJustify justify) { + mNode.setJustifyContent(justify); + return this; + } + + StyledNode height(float height) { + mNode.setHeight(height); + return this; + } + + StyledNode heightPercent(float height) { + mNode.setHeightPercent(height); + return this; + } + + StyledNode alignItems(YogaAlign align) { + mNode.setAlignItems(align); + return this; + } + + StyledNode alignSelf(YogaAlign align) { + mNode.setAlignSelf(align); + return this; + } + + StyledNode alignContent(YogaAlign align) { + mNode.setAlignContent(align); + return this; + } + + StyledNode flexWrap(YogaWrap wrap) { + mNode.setWrap(wrap); + return this; + } + + StyledNode positionType(YogaPositionType positionType) { + mNode.setPositionType(positionType); + return this; + } + + StyledNode overflow(YogaOverflow overflow) { + mNode.setOverflow(overflow); + return this; + } + + StyledNode flexShrink(float flexShrink) { + mNode.setFlexShrink(flexShrink); + return this; + } + + StyledNode display(YogaDisplay display) { + mNode.setDisplay(display); + return this; + } + + StyledNode flexGrow(float flexGrow) { + mNode.setFlexGrow(flexGrow); + return this; + } + + StyledNode flex(float flex) { + mNode.setFlex(flex); + return this; + } + + StyledNode flexBasis(float flexBasis) { + mNode.setFlexBasis(flexBasis); + return this; + } + + StyledNode flexBasisPercent(float flexBasis) { + mNode.setFlexBasisPercent(flexBasis); + return this; + } + + StyledNode margin(YogaEdge edge, float margin) { + mNode.setMargin(edge, margin); + return this; + } + + StyledNode marginPercent(YogaEdge edge, float margin) { + mNode.setMarginPercent(edge, margin); + return this; + } + + StyledNode marginAuto(YogaEdge edge) { + mNode.setMarginAuto(edge); + return this; + } + + StyledNode padding(YogaEdge edge, float padding) { + mNode.setPadding(edge, padding); + return this; + } + + StyledNode paddingPercent(YogaEdge edge, float padding) { + mNode.setPaddingPercent(edge, padding); + return this; + } + + StyledNode border(YogaEdge edge, float border) { + mNode.setBorder(edge, border); + return this; + } + + StyledNode position(YogaEdge edge, float position) { + mNode.setPosition(edge, position); + return this; + } + + StyledNode positionPercent(YogaEdge edge, float position) { + mNode.setPositionPercent(edge, position); + return this; + } + + StyledNode minWidth(float minWidth) { + mNode.setMinWidth(minWidth); + return this; + } + + StyledNode minWidthPercent(float minWidth) { + mNode.setMinWidthPercent(minWidth); + return this; + } + + StyledNode minHeight(float minHeight) { + mNode.setMinHeight(minHeight); + return this; + } + + StyledNode minHeightPercent(float minHeight) { + mNode.setMinHeightPercent(minHeight); + return this; + } + + StyledNode maxWidth(float maxWidth) { + mNode.setMaxWidth(maxWidth); + return this; + } + + StyledNode maxWidthPercent(float maxWidth) { + mNode.setMaxWidthPercent(maxWidth); + return this; + } + + StyledNode maxHeight(float maxHeight) { + mNode.setMaxHeight(maxHeight); + return this; + } + + StyledNode maxHeightPercent(float maxHeight) { + mNode.setMaxHeightPercent(maxHeight); + return this; + } + + StyledNode aspectRatio(float aspectRatio) { + mNode.setAspectRatio(aspectRatio); + return this; + } + } +}