Skip to content

Commit 4500e4d

Browse files
Emil SjolanderFacebook Github Bot
authored andcommitted
Dont measure single flex grow+shrink child
Reviewed By: gkassabli Differential Revision: D4147298 fbshipit-source-id: 51152e57eff8e322a833a6d698c30f8c5e2dcc35
1 parent 75d940d commit 4500e4d

File tree

1 file changed

+54
-31
lines changed

1 file changed

+54
-31
lines changed

React/CSSLayout/CSSLayout.c

Lines changed: 54 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -259,7 +259,8 @@ static void _CSSNodeMarkDirty(const CSSNodeRef node) {
259259
}
260260

261261
void CSSNodeSetMeasureFunc(const CSSNodeRef node, CSSMeasureFunc measureFunc) {
262-
CSS_ASSERT(CSSNodeChildCount(node) == 0, "Cannot set measure function: Nodes with measure functions cannot have children.");
262+
CSS_ASSERT(CSSNodeChildCount(node) == 0,
263+
"Cannot set measure function: Nodes with measure functions cannot have children.");
263264
node->measure = measureFunc;
264265
}
265266

@@ -269,7 +270,8 @@ CSSMeasureFunc CSSNodeGetMeasureFunc(const CSSNodeRef node) {
269270

270271
void CSSNodeInsertChild(const CSSNodeRef node, const CSSNodeRef child, const uint32_t index) {
271272
CSS_ASSERT(child->parent == NULL, "Child already has a parent, it must be removed first.");
272-
CSS_ASSERT(node->measure == NULL, "Cannot add child: Nodes with measure functions cannot have children.");
273+
CSS_ASSERT(node->measure == NULL,
274+
"Cannot add child: Nodes with measure functions cannot have children.");
273275
CSSNodeListInsert(&node->children, child, index);
274276
child->parent = node;
275277
_CSSNodeMarkDirty(node);
@@ -1367,6 +1369,26 @@ static void layoutNodeImpl(const CSSNodeRef node,
13671369
const float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
13681370
const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
13691371

1372+
// If there is only one child with flexGrow + flexShrink it means we can set the
1373+
// computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly
1374+
// match the remaining space
1375+
CSSNodeRef singleFlexChild = NULL;
1376+
if ((isMainAxisRow && widthMeasureMode != CSSMeasureModeUndefined) ||
1377+
(!isMainAxisRow && heightMeasureMode != CSSMeasureModeUndefined)) {
1378+
for (uint32_t i = 0; i < childCount; i++) {
1379+
const CSSNodeRef child = CSSNodeGetChild(node, i);
1380+
if (singleFlexChild) {
1381+
if (isFlex(child)) {
1382+
// There is already a flexible child, abort.
1383+
singleFlexChild = NULL;
1384+
break;
1385+
}
1386+
} else if (CSSNodeStyleGetFlexGrow(child) > 0 && CSSNodeStyleGetFlexShrink(child) > 0) {
1387+
singleFlexChild = child;
1388+
}
1389+
}
1390+
}
1391+
13701392
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
13711393
for (uint32_t i = 0; i < childCount; i++) {
13721394
const CSSNodeRef child = CSSNodeListGet(node->children, i);
@@ -1391,13 +1413,17 @@ static void layoutNodeImpl(const CSSNodeRef node,
13911413
currentAbsoluteChild = child;
13921414
child->nextChild = NULL;
13931415
} else {
1394-
computeChildFlexBasis(node,
1395-
child,
1396-
availableInnerWidth,
1397-
widthMeasureMode,
1398-
availableInnerHeight,
1399-
heightMeasureMode,
1400-
direction);
1416+
if (child == singleFlexChild) {
1417+
child->layout.computedFlexBasis = 0;
1418+
} else {
1419+
computeChildFlexBasis(node,
1420+
child,
1421+
availableInnerWidth,
1422+
widthMeasureMode,
1423+
availableInnerHeight,
1424+
heightMeasureMode,
1425+
direction);
1426+
}
14011427
}
14021428
}
14031429

@@ -2133,17 +2159,17 @@ static inline bool newMeasureSizeIsStricterAndStillValid(CSSMeasureMode sizeMode
21332159
}
21342160

21352161
bool CSSNodeCanUseCachedMeasurement(const CSSMeasureMode widthMode,
2136-
const float width,
2137-
const CSSMeasureMode heightMode,
2138-
const float height,
2139-
const CSSMeasureMode lastWidthMode,
2140-
const float lastWidth,
2141-
const CSSMeasureMode lastHeightMode,
2142-
const float lastHeight,
2143-
const float lastComputedWidth,
2144-
const float lastComputedHeight,
2145-
const float marginRow,
2146-
const float marginColumn) {
2162+
const float width,
2163+
const CSSMeasureMode heightMode,
2164+
const float height,
2165+
const CSSMeasureMode lastWidthMode,
2166+
const float lastWidth,
2167+
const CSSMeasureMode lastHeightMode,
2168+
const float lastHeight,
2169+
const float lastComputedWidth,
2170+
const float lastComputedHeight,
2171+
const float marginRow,
2172+
const float marginColumn) {
21472173
if (lastComputedHeight < 0 || lastComputedWidth < 0) {
21482174
return false;
21492175
}
@@ -2161,19 +2187,16 @@ bool CSSNodeCanUseCachedMeasurement(const CSSMeasureMode widthMode,
21612187
newMeasureSizeIsStricterAndStillValid(
21622188
widthMode, width - marginRow, lastWidthMode, lastWidth, lastComputedWidth);
21632189

2164-
const bool heightIsCompatible = hasSameHeightSpec ||
2165-
newSizeIsExactAndMatchesOldMeasuredSize(heightMode,
2166-
height - marginColumn,
2167-
lastComputedHeight) ||
2168-
oldSizeIsUnspecifiedAndStillFits(heightMode,
2190+
const bool heightIsCompatible =
2191+
hasSameHeightSpec || newSizeIsExactAndMatchesOldMeasuredSize(heightMode,
21692192
height - marginColumn,
2170-
lastHeightMode,
21712193
lastComputedHeight) ||
2172-
newMeasureSizeIsStricterAndStillValid(heightMode,
2173-
height - marginColumn,
2174-
lastHeightMode,
2175-
lastHeight,
2176-
lastComputedHeight);
2194+
oldSizeIsUnspecifiedAndStillFits(heightMode,
2195+
height - marginColumn,
2196+
lastHeightMode,
2197+
lastComputedHeight) ||
2198+
newMeasureSizeIsStricterAndStillValid(
2199+
heightMode, height - marginColumn, lastHeightMode, lastHeight, lastComputedHeight);
21772200

21782201
return widthIsCompatible && heightIsCompatible;
21792202
}

0 commit comments

Comments
 (0)