Skip to content

Commit fda861a

Browse files
Replaced first pass with a function
Reviewed By: emilsjolander Differential Revision: D6819719 fbshipit-source-id: e5e77c21d1dca2255433da3388887d9db3f7b642
1 parent 34b7ec8 commit fda861a

File tree

2 files changed

+119
-99
lines changed

2 files changed

+119
-99
lines changed

ReactCommon/yoga/yoga/Utils.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,7 @@ struct YGCollectFlexItemsRowValues {
4444
float totalFlexShrinkScaledFactors;
4545
float endOfLineIndex;
4646
std::vector<YGNodeRef> relativeChildren;
47+
float remainingFreeSpace;
4748
};
4849

4950
bool YGValueEqual(const YGValue a, const YGValue b);

ReactCommon/yoga/yoga/Yoga.cpp

Lines changed: 118 additions & 99 deletions
Original file line numberDiff line numberDiff line change
@@ -1701,6 +1701,87 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
17011701
return flexAlgoRowMeasurement;
17021702
}
17031703

1704+
// It distributes the free space to the flexible items, for those flexible items
1705+
// whose min and max constraints are triggered, the clamped size is removed from
1706+
// the remaingfreespace.
1707+
static void YGDistributeFreeSpaceFirstPass(
1708+
YGCollectFlexItemsRowValues& collectedFlexItemsValues,
1709+
const YGFlexDirection mainAxis,
1710+
const float mainAxisParentSize,
1711+
const float availableInnerMainDim,
1712+
const float availableInnerWidth) {
1713+
float flexShrinkScaledFactor = 0;
1714+
float flexGrowFactor = 0;
1715+
float baseMainSize = 0;
1716+
float boundMainSize = 0;
1717+
float deltaFreeSpace = 0;
1718+
1719+
for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) {
1720+
float childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
1721+
currentRelativeChild,
1722+
mainAxis,
1723+
currentRelativeChild->getLayout().computedFlexBasis,
1724+
mainAxisParentSize);
1725+
1726+
if (collectedFlexItemsValues.remainingFreeSpace < 0) {
1727+
flexShrinkScaledFactor =
1728+
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
1729+
1730+
// Is this child able to shrink?
1731+
if (flexShrinkScaledFactor != 0) {
1732+
baseMainSize = childFlexBasis +
1733+
collectedFlexItemsValues.remainingFreeSpace /
1734+
collectedFlexItemsValues.totalFlexShrinkScaledFactors *
1735+
flexShrinkScaledFactor;
1736+
boundMainSize = YGNodeBoundAxis(
1737+
currentRelativeChild,
1738+
mainAxis,
1739+
baseMainSize,
1740+
availableInnerMainDim,
1741+
availableInnerWidth);
1742+
if (baseMainSize != boundMainSize) {
1743+
// By excluding this item's size and flex factor from remaining,
1744+
// this item's
1745+
// min/max constraints should also trigger in the second pass
1746+
// resulting in the
1747+
// item's size calculation being identical in the first and second
1748+
// passes.
1749+
deltaFreeSpace += boundMainSize - childFlexBasis;
1750+
collectedFlexItemsValues.totalFlexShrinkScaledFactors -=
1751+
flexShrinkScaledFactor;
1752+
}
1753+
}
1754+
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
1755+
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
1756+
1757+
// Is this child able to grow?
1758+
if (flexGrowFactor != 0) {
1759+
baseMainSize = childFlexBasis +
1760+
collectedFlexItemsValues.remainingFreeSpace /
1761+
collectedFlexItemsValues.totalFlexGrowFactors * flexGrowFactor;
1762+
boundMainSize = YGNodeBoundAxis(
1763+
currentRelativeChild,
1764+
mainAxis,
1765+
baseMainSize,
1766+
availableInnerMainDim,
1767+
availableInnerWidth);
1768+
1769+
if (baseMainSize != boundMainSize) {
1770+
// By excluding this item's size and flex factor from remaining,
1771+
// this item's
1772+
// min/max constraints should also trigger in the second pass
1773+
// resulting in the
1774+
// item's size calculation being identical in the first and second
1775+
// passes.
1776+
deltaFreeSpace += boundMainSize - childFlexBasis;
1777+
collectedFlexItemsValues.totalFlexGrowFactors -= flexGrowFactor;
1778+
}
1779+
}
1780+
}
1781+
}
1782+
collectedFlexItemsValues.remainingFreeSpace -= deltaFreeSpace;
1783+
}
1784+
17041785
//
17051786
// This is the main routine that implements a subset of the flexbox layout
17061787
// algorithm
@@ -2033,27 +2114,26 @@ static void YGNodelayoutImpl(const YGNodeRef node,
20332114
}
20342115
}
20352116

2036-
float remainingFreeSpace = 0;
20372117
if (!sizeBasedOnContent && !YGFloatIsUndefined(availableInnerMainDim)) {
2038-
remainingFreeSpace = availableInnerMainDim -
2118+
collectedFlexItemsValues.remainingFreeSpace = availableInnerMainDim -
20392119
collectedFlexItemsValues.sizeConsumedOnCurrentLine;
20402120
} else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0) {
20412121
// availableInnerMainDim is indefinite which means the node is being sized based on its
20422122
// content.
20432123
// sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for
20442124
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
2045-
remainingFreeSpace = -collectedFlexItemsValues.sizeConsumedOnCurrentLine;
2125+
collectedFlexItemsValues.remainingFreeSpace =
2126+
-collectedFlexItemsValues.sizeConsumedOnCurrentLine;
20462127
}
20472128

2048-
const float originalRemainingFreeSpace = remainingFreeSpace;
2129+
const float originalRemainingFreeSpace =
2130+
collectedFlexItemsValues.remainingFreeSpace;
20492131
float deltaFreeSpace = 0;
20502132

20512133
if (!canSkipFlex) {
20522134
float childFlexBasis;
20532135
float flexShrinkScaledFactor;
20542136
float flexGrowFactor;
2055-
float baseMainSize;
2056-
float boundMainSize;
20572137

20582138
// Do two passes over the flex items to figure out how to distribute the
20592139
// remaining space.
@@ -2078,80 +2158,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
20782158
// concerns because we know exactly how many passes it'll do.
20792159

20802160
// First pass: detect the flex items whose min/max constraints trigger
2081-
float deltaFlexShrinkScaledFactors = 0;
2082-
float deltaFlexGrowFactors = 0;
2083-
2084-
for (auto currentRelativeChild :
2085-
collectedFlexItemsValues.relativeChildren) {
2086-
childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
2087-
currentRelativeChild,
2088-
mainAxis,
2089-
currentRelativeChild->getLayout().computedFlexBasis,
2090-
mainAxisParentSize);
2091-
2092-
if (remainingFreeSpace < 0) {
2093-
flexShrinkScaledFactor =
2094-
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
2095-
2096-
// Is this child able to shrink?
2097-
if (flexShrinkScaledFactor != 0) {
2098-
baseMainSize = childFlexBasis +
2099-
remainingFreeSpace /
2100-
collectedFlexItemsValues.totalFlexShrinkScaledFactors *
2101-
flexShrinkScaledFactor;
2102-
boundMainSize = YGNodeBoundAxis(
2103-
currentRelativeChild,
2104-
mainAxis,
2105-
baseMainSize,
2106-
availableInnerMainDim,
2107-
availableInnerWidth);
2108-
if (baseMainSize != boundMainSize) {
2109-
// By excluding this item's size and flex factor from remaining,
2110-
// this item's
2111-
// min/max constraints should also trigger in the second pass
2112-
// resulting in the
2113-
// item's size calculation being identical in the first and second
2114-
// passes.
2115-
deltaFreeSpace -= boundMainSize - childFlexBasis;
2116-
deltaFlexShrinkScaledFactors -= flexShrinkScaledFactor;
2117-
}
2118-
}
2119-
} else if (remainingFreeSpace > 0) {
2120-
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
2121-
2122-
// Is this child able to grow?
2123-
if (flexGrowFactor != 0) {
2124-
baseMainSize = childFlexBasis +
2125-
remainingFreeSpace /
2126-
collectedFlexItemsValues.totalFlexGrowFactors *
2127-
flexGrowFactor;
2128-
boundMainSize = YGNodeBoundAxis(
2129-
currentRelativeChild,
2130-
mainAxis,
2131-
baseMainSize,
2132-
availableInnerMainDim,
2133-
availableInnerWidth);
2134-
2135-
if (baseMainSize != boundMainSize) {
2136-
// By excluding this item's size and flex factor from remaining,
2137-
// this item's
2138-
// min/max constraints should also trigger in the second pass
2139-
// resulting in the
2140-
// item's size calculation being identical in the first and second
2141-
// passes.
2142-
deltaFreeSpace -= boundMainSize - childFlexBasis;
2143-
deltaFlexGrowFactors -= flexGrowFactor;
2144-
}
2145-
}
2146-
}
2147-
2148-
currentRelativeChild = currentRelativeChild->getNextChild();
2149-
}
2150-
2151-
collectedFlexItemsValues.totalFlexShrinkScaledFactors +=
2152-
deltaFlexShrinkScaledFactors;
2153-
collectedFlexItemsValues.totalFlexGrowFactors += deltaFlexGrowFactors;
2154-
remainingFreeSpace += deltaFreeSpace;
2161+
YGDistributeFreeSpaceFirstPass(
2162+
collectedFlexItemsValues,
2163+
mainAxis,
2164+
mainAxisParentSize,
2165+
availableInnerMainDim,
2166+
availableInnerWidth);
21552167

21562168
// Second pass: resolve the sizes of the flexible items
21572169
deltaFreeSpace = 0;
@@ -2164,7 +2176,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
21642176
mainAxisParentSize);
21652177
float updatedMainSize = childFlexBasis;
21662178

2167-
if (remainingFreeSpace < 0) {
2179+
if (collectedFlexItemsValues.remainingFreeSpace < 0) {
21682180
flexShrinkScaledFactor =
21692181
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
21702182
// Is this child able to shrink?
@@ -2175,7 +2187,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
21752187
childSize = childFlexBasis + flexShrinkScaledFactor;
21762188
} else {
21772189
childSize = childFlexBasis +
2178-
(remainingFreeSpace /
2190+
(collectedFlexItemsValues.remainingFreeSpace /
21792191
collectedFlexItemsValues.totalFlexShrinkScaledFactors) *
21802192
flexShrinkScaledFactor;
21812193
}
@@ -2187,7 +2199,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
21872199
availableInnerMainDim,
21882200
availableInnerWidth);
21892201
}
2190-
} else if (remainingFreeSpace > 0) {
2202+
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
21912203
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
21922204

21932205
// Is this child able to grow?
@@ -2196,7 +2208,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
21962208
currentRelativeChild,
21972209
mainAxis,
21982210
childFlexBasis +
2199-
remainingFreeSpace /
2211+
collectedFlexItemsValues.remainingFreeSpace /
22002212
collectedFlexItemsValues.totalFlexGrowFactors *
22012213
flexGrowFactor,
22022214
availableInnerMainDim,
@@ -2315,9 +2327,11 @@ static void YGNodelayoutImpl(const YGNodeRef node,
23152327
}
23162328
}
23172329

2318-
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
2330+
collectedFlexItemsValues.remainingFreeSpace =
2331+
originalRemainingFreeSpace + deltaFreeSpace;
23192332
node->setLayoutHadOverflow(
2320-
node->getLayout().hadOverflow | (remainingFreeSpace < 0));
2333+
node->getLayout().hadOverflow |
2334+
(collectedFlexItemsValues.remainingFreeSpace < 0));
23212335

23222336
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
23232337

@@ -2331,20 +2345,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
23312345
// If we are using "at most" rules in the main axis. Calculate the remaining space when
23322346
// constraint by the min size defined for the main axis.
23332347

2334-
if (measureModeMainDim == YGMeasureModeAtMost && remainingFreeSpace > 0) {
2348+
if (measureModeMainDim == YGMeasureModeAtMost &&
2349+
collectedFlexItemsValues.remainingFreeSpace > 0) {
23352350
if (node->getStyle().minDimensions[dim[mainAxis]].unit !=
23362351
YGUnitUndefined &&
23372352
YGResolveValue(
23382353
node->getStyle().minDimensions[dim[mainAxis]],
23392354
mainAxisParentSize) >= 0) {
2340-
remainingFreeSpace = fmaxf(
2355+
collectedFlexItemsValues.remainingFreeSpace = fmaxf(
23412356
0,
23422357
YGResolveValue(
23432358
node->getStyle().minDimensions[dim[mainAxis]],
23442359
mainAxisParentSize) -
2345-
(availableInnerMainDim - remainingFreeSpace));
2360+
(availableInnerMainDim -
2361+
collectedFlexItemsValues.remainingFreeSpace));
23462362
} else {
2347-
remainingFreeSpace = 0;
2363+
collectedFlexItemsValues.remainingFreeSpace = 0;
23482364
}
23492365
}
23502366

@@ -2371,29 +2387,30 @@ static void YGNodelayoutImpl(const YGNodeRef node,
23712387
if (numberOfAutoMarginsOnCurrentLine == 0) {
23722388
switch (justifyContent) {
23732389
case YGJustifyCenter:
2374-
leadingMainDim = remainingFreeSpace / 2;
2390+
leadingMainDim = collectedFlexItemsValues.remainingFreeSpace / 2;
23752391
break;
23762392
case YGJustifyFlexEnd:
2377-
leadingMainDim = remainingFreeSpace;
2393+
leadingMainDim = collectedFlexItemsValues.remainingFreeSpace;
23782394
break;
23792395
case YGJustifySpaceBetween:
23802396
if (collectedFlexItemsValues.itemsOnLine > 1) {
2381-
betweenMainDim = fmaxf(remainingFreeSpace, 0) /
2397+
betweenMainDim =
2398+
fmaxf(collectedFlexItemsValues.remainingFreeSpace, 0) /
23822399
(collectedFlexItemsValues.itemsOnLine - 1);
23832400
} else {
23842401
betweenMainDim = 0;
23852402
}
23862403
break;
23872404
case YGJustifySpaceEvenly:
23882405
// Space is distributed evenly across all elements
2389-
betweenMainDim =
2390-
remainingFreeSpace / (collectedFlexItemsValues.itemsOnLine + 1);
2406+
betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /
2407+
(collectedFlexItemsValues.itemsOnLine + 1);
23912408
leadingMainDim = betweenMainDim;
23922409
break;
23932410
case YGJustifySpaceAround:
23942411
// Space on the edges is half of the space between elements
2395-
betweenMainDim =
2396-
remainingFreeSpace / collectedFlexItemsValues.itemsOnLine;
2412+
betweenMainDim = collectedFlexItemsValues.remainingFreeSpace /
2413+
collectedFlexItemsValues.itemsOnLine;
23972414
leadingMainDim = betweenMainDim / 2;
23982415
break;
23992416
case YGJustifyFlexStart:
@@ -2427,7 +2444,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
24272444
// do not take part in that phase.
24282445
if (child->getStyle().positionType == YGPositionTypeRelative) {
24292446
if (child->marginLeadingValue(mainAxis).unit == YGUnitAuto) {
2430-
mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
2447+
mainDim += collectedFlexItemsValues.remainingFreeSpace /
2448+
numberOfAutoMarginsOnCurrentLine;
24312449
}
24322450

24332451
if (performLayout) {
@@ -2437,7 +2455,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
24372455
}
24382456

24392457
if (child->marginTrailingValue(mainAxis).unit == YGUnitAuto) {
2440-
mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
2458+
mainDim += collectedFlexItemsValues.remainingFreeSpace /
2459+
numberOfAutoMarginsOnCurrentLine;
24412460
}
24422461

24432462
if (canSkipFlex) {

0 commit comments

Comments
 (0)