From 54548894d010409d1ff32eaf34395faabd6328b8 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Fri, 12 May 2017 09:03:22 -0700 Subject: [PATCH] Fix flex basis not accounting for max size constraint Reviewed By: gkassabli Differential Revision: D5044314 fbshipit-source-id: d9f9db832e4943a57a89c9d162ff6077b709795a --- .../jni/first-party/yogajni/jni/YGJNI.cpp | 8 +- ReactCommon/yoga/yoga/Yoga.c | 102 ++++++++++-------- 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp index bf2d4c3330..e4dc0bb5d1 100644 --- a/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp +++ b/ReactAndroid/src/main/jni/first-party/yogajni/jni/YGJNI.cpp @@ -153,10 +153,10 @@ struct JYogaLogLevel : public JavaClass { }; static int YGJNILogFunc(const YGConfigRef config, - const YGNodeRef node, - YGLogLevel level, - const char *format, - va_list args) { + const YGNodeRef node, + YGLogLevel level, + const char *format, + va_list args) { char buffer[256]; int result = vsnprintf(buffer, sizeof(buffer), format, args); diff --git a/ReactCommon/yoga/yoga/Yoga.c b/ReactCommon/yoga/yoga/Yoga.c index 3a4faf85b8..dabd4c4e70 100644 --- a/ReactCommon/yoga/yoga/Yoga.c +++ b/ReactCommon/yoga/yoga/Yoga.c @@ -387,8 +387,8 @@ void YGNodeFreeRecursive(const YGNodeRef root) { void YGNodeReset(const YGNodeRef node) { YGAssertWithNode(node, - YGNodeGetChildCount(node) == 0, - "Cannot reset a node which still has children attached"); + YGNodeGetChildCount(node) == 0, + "Cannot reset a node which still has children attached"); YGAssertWithNode(node, node->parent == NULL, "Cannot reset a node still attached to a parent"); YGNodeListFree(node->children); @@ -449,9 +449,10 @@ void YGNodeSetMeasureFunc(const YGNodeRef node, YGMeasureFunc measureFunc) { // TODO: t18095186 Move nodeType to opt-in function and mark appropriate places in Litho node->nodeType = YGNodeTypeDefault; } else { - YGAssertWithNode(node, - YGNodeGetChildCount(node) == 0, - "Cannot set measure function: Nodes with measure functions cannot have children."); + YGAssertWithNode( + node, + YGNodeGetChildCount(node) == 0, + "Cannot set measure function: Nodes with measure functions cannot have children."); node->measure = measureFunc; // TODO: t18095186 Move nodeType to opt-in function and mark appropriate places in Litho node->nodeType = YGNodeTypeText; @@ -471,10 +472,12 @@ YGBaselineFunc YGNodeGetBaselineFunc(const YGNodeRef node) { } void YGNodeInsertChild(const YGNodeRef node, const YGNodeRef child, const uint32_t index) { - YGAssertWithNode(node, child->parent == NULL, "Child already has a parent, it must be removed first."); YGAssertWithNode(node, - node->measure == NULL, - "Cannot add child: Nodes with measure functions cannot have children."); + child->parent == NULL, + "Child already has a parent, it must be removed first."); + YGAssertWithNode(node, + node->measure == NULL, + "Cannot add child: Nodes with measure functions cannot have children."); YGNodeListInsert(&node->children, child, index); child->parent = node; @@ -503,9 +506,9 @@ inline uint32_t YGNodeGetChildCount(const YGNodeRef node) { void YGNodeMarkDirty(const YGNodeRef node) { YGAssertWithNode(node, - node->measure != NULL, - "Only leaf nodes with custom measure functions" - "should manually mark themselves as dirty"); + node->measure != NULL, + "Only leaf nodes with custom measure functions" + "should manually mark themselves as dirty"); YGNodeMarkDirtyInternal(node); } @@ -702,27 +705,29 @@ static inline const YGValue *YGNodeResolveFlexBasisPtr(const YGNodeRef node) { return node->layout.instanceName; \ } -#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \ - type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge) { \ - YGAssertWithNode(node, edge < YGEdgeEnd, "Cannot get layout properties of multi-edge shorthands"); \ - \ - if (edge == YGEdgeLeft) { \ - if (node->layout.direction == YGDirectionRTL) { \ - return node->layout.instanceName[YGEdgeEnd]; \ - } else { \ - return node->layout.instanceName[YGEdgeStart]; \ - } \ - } \ - \ - if (edge == YGEdgeRight) { \ - if (node->layout.direction == YGDirectionRTL) { \ - return node->layout.instanceName[YGEdgeStart]; \ - } else { \ - return node->layout.instanceName[YGEdgeEnd]; \ - } \ - } \ - \ - return node->layout.instanceName[edge]; \ +#define YG_NODE_LAYOUT_RESOLVED_PROPERTY_IMPL(type, name, instanceName) \ + type YGNodeLayoutGet##name(const YGNodeRef node, const YGEdge edge) { \ + YGAssertWithNode(node, \ + edge < YGEdgeEnd, \ + "Cannot get layout properties of multi-edge shorthands"); \ + \ + if (edge == YGEdgeLeft) { \ + if (node->layout.direction == YGDirectionRTL) { \ + return node->layout.instanceName[YGEdgeEnd]; \ + } else { \ + return node->layout.instanceName[YGEdgeStart]; \ + } \ + } \ + \ + if (edge == YGEdgeRight) { \ + if (node->layout.direction == YGDirectionRTL) { \ + return node->layout.instanceName[YGEdgeStart]; \ + } else { \ + return node->layout.instanceName[YGEdgeEnd]; \ + } \ + } \ + \ + return node->layout.instanceName[edge]; \ } YG_NODE_PROPERTY_IMPL(void *, Context, context, context); @@ -1143,8 +1148,8 @@ static float YGBaseline(const YGNodeRef node) { node->layout.measuredDimensions[YGDimensionWidth], node->layout.measuredDimensions[YGDimensionHeight]); YGAssertWithNode(node, - !YGFloatIsUndefined(baseline), - "Expect custom baseline function to not return NaN"); + !YGFloatIsUndefined(baseline), + "Expect custom baseline function to not return NaN"); return baseline; } @@ -1949,13 +1954,15 @@ static void YGNodelayoutImpl(const YGNodeRef node, const bool performLayout, const YGConfigRef config) { YGAssertWithNode(node, - YGFloatIsUndefined(availableWidth) ? widthMeasureMode == YGMeasureModeUndefined : true, - "availableWidth is indefinite so widthMeasureMode must be " - "YGMeasureModeUndefined"); + 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"); + 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 = YGNodeResolveDirection(node, parentDirection); @@ -2337,7 +2344,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, float deltaFlexGrowFactors = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { - childFlexBasis = currentRelativeChild->layout.computedFlexBasis; + childFlexBasis = + fminf(YGResolveValue(¤tRelativeChild->style.maxDimensions[dim[mainAxis]], + mainAxisParentSize), + fmaxf(YGResolveValue(¤tRelativeChild->style.minDimensions[dim[mainAxis]], + mainAxisParentSize), + currentRelativeChild->layout.computedFlexBasis)); if (remainingFreeSpace < 0) { flexShrinkScaledFactor = -YGNodeResolveFlexShrink(currentRelativeChild) * childFlexBasis; @@ -2375,6 +2387,7 @@ static void YGNodelayoutImpl(const YGNodeRef node, baseMainSize, availableInnerMainDim, availableInnerWidth); + if (baseMainSize != boundMainSize) { // By excluding this item's size and flex factor from remaining, // this item's @@ -2399,7 +2412,12 @@ static void YGNodelayoutImpl(const YGNodeRef node, deltaFreeSpace = 0; currentRelativeChild = firstRelativeChild; while (currentRelativeChild != NULL) { - childFlexBasis = currentRelativeChild->layout.computedFlexBasis; + childFlexBasis = + fminf(YGResolveValue(¤tRelativeChild->style.maxDimensions[dim[mainAxis]], + mainAxisParentSize), + fmaxf(YGResolveValue(¤tRelativeChild->style.minDimensions[dim[mainAxis]], + mainAxisParentSize), + currentRelativeChild->layout.computedFlexBasis)); float updatedMainSize = childFlexBasis; if (remainingFreeSpace < 0) {