Dont measure single flex grow+shrink child

Reviewed By: gkassabli

Differential Revision: D4147298

fbshipit-source-id: 51152e57eff8e322a833a6d698c30f8c5e2dcc35
This commit is contained in:
Emil Sjolander 2016-11-08 15:23:08 -08:00 committed by Facebook Github Bot
parent 75d940d541
commit 4500e4d0ff
1 changed files with 54 additions and 31 deletions

View File

@ -259,7 +259,8 @@ static void _CSSNodeMarkDirty(const CSSNodeRef node) {
} }
void CSSNodeSetMeasureFunc(const CSSNodeRef node, CSSMeasureFunc measureFunc) { void CSSNodeSetMeasureFunc(const CSSNodeRef node, CSSMeasureFunc measureFunc) {
CSS_ASSERT(CSSNodeChildCount(node) == 0, "Cannot set measure function: Nodes with measure functions cannot have children."); CSS_ASSERT(CSSNodeChildCount(node) == 0,
"Cannot set measure function: Nodes with measure functions cannot have children.");
node->measure = measureFunc; node->measure = measureFunc;
} }
@ -269,7 +270,8 @@ CSSMeasureFunc CSSNodeGetMeasureFunc(const CSSNodeRef node) {
void CSSNodeInsertChild(const CSSNodeRef node, const CSSNodeRef child, const uint32_t index) { void CSSNodeInsertChild(const CSSNodeRef node, const CSSNodeRef child, const uint32_t index) {
CSS_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first."); CSS_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first.");
CSS_ASSERT(node->measure == NULL, "Cannot add child: Nodes with measure functions cannot have children."); CSS_ASSERT(node->measure == NULL,
"Cannot add child: Nodes with measure functions cannot have children.");
CSSNodeListInsert(&node->children, child, index); CSSNodeListInsert(&node->children, child, index);
child->parent = node; child->parent = node;
_CSSNodeMarkDirty(node); _CSSNodeMarkDirty(node);
@ -1367,6 +1369,26 @@ static void layoutNodeImpl(const CSSNodeRef node,
const float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight; const float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth; const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
// If there is only one child with flexGrow + flexShrink it means we can set the
// computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly
// match the remaining space
CSSNodeRef singleFlexChild = NULL;
if ((isMainAxisRow && widthMeasureMode != CSSMeasureModeUndefined) ||
(!isMainAxisRow && heightMeasureMode != CSSMeasureModeUndefined)) {
for (uint32_t i = 0; i < childCount; i++) {
const CSSNodeRef child = CSSNodeGetChild(node, i);
if (singleFlexChild) {
if (isFlex(child)) {
// There is already a flexible child, abort.
singleFlexChild = NULL;
break;
}
} else if (CSSNodeStyleGetFlexGrow(child) > 0 && CSSNodeStyleGetFlexShrink(child) > 0) {
singleFlexChild = child;
}
}
}
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
for (uint32_t i = 0; i < childCount; i++) { for (uint32_t i = 0; i < childCount; i++) {
const CSSNodeRef child = CSSNodeListGet(node->children, i); const CSSNodeRef child = CSSNodeListGet(node->children, i);
@ -1390,6 +1412,9 @@ static void layoutNodeImpl(const CSSNodeRef node,
} }
currentAbsoluteChild = child; currentAbsoluteChild = child;
child->nextChild = NULL; child->nextChild = NULL;
} else {
if (child == singleFlexChild) {
child->layout.computedFlexBasis = 0;
} else { } else {
computeChildFlexBasis(node, computeChildFlexBasis(node,
child, child,
@ -1400,6 +1425,7 @@ static void layoutNodeImpl(const CSSNodeRef node,
direction); direction);
} }
} }
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
@ -2161,19 +2187,16 @@ bool CSSNodeCanUseCachedMeasurement(const CSSMeasureMode widthMode,
newMeasureSizeIsStricterAndStillValid( newMeasureSizeIsStricterAndStillValid(
widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth); widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth);
const bool heightIsCompatible = hasSameHeightSpec || const bool heightIsCompatible =
newSizeIsExactAndMatchesOldMeasuredSize(heightMode, hasSameHeightSpec || newSizeIsExactAndMatchesOldMeasuredSize(heightMode,
height - marginColumn, height - marginColumn,
lastComputedHeight) || lastComputedHeight) ||
oldSizeIsUnspecifiedAndStillFits(heightMode, oldSizeIsUnspecifiedAndStillFits(heightMode,
height - marginColumn, height - marginColumn,
lastHeightMode, lastHeightMode,
lastComputedHeight) || lastComputedHeight) ||
newMeasureSizeIsStricterAndStillValid(heightMode, newMeasureSizeIsStricterAndStillValid(
height - marginColumn, heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight);
lastHeightMode,
lastHeight,
lastComputedHeight);
return widthIsCompatible && heightIsCompatible; return widthIsCompatible && heightIsCompatible;
} }