@@ -1701,6 +1701,87 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
1701
1701
return flexAlgoRowMeasurement;
1702
1702
}
1703
1703
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
+
1704
1785
//
1705
1786
// This is the main routine that implements a subset of the flexbox layout
1706
1787
// algorithm
@@ -2033,27 +2114,26 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2033
2114
}
2034
2115
}
2035
2116
2036
- float remainingFreeSpace = 0 ;
2037
2117
if (!sizeBasedOnContent && !YGFloatIsUndefined (availableInnerMainDim)) {
2038
- remainingFreeSpace = availableInnerMainDim -
2118
+ collectedFlexItemsValues. remainingFreeSpace = availableInnerMainDim -
2039
2119
collectedFlexItemsValues.sizeConsumedOnCurrentLine ;
2040
2120
} else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0 ) {
2041
2121
// availableInnerMainDim is indefinite which means the node is being sized based on its
2042
2122
// content.
2043
2123
// sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for
2044
2124
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
2045
- remainingFreeSpace = -collectedFlexItemsValues.sizeConsumedOnCurrentLine ;
2125
+ collectedFlexItemsValues.remainingFreeSpace =
2126
+ -collectedFlexItemsValues.sizeConsumedOnCurrentLine ;
2046
2127
}
2047
2128
2048
- const float originalRemainingFreeSpace = remainingFreeSpace;
2129
+ const float originalRemainingFreeSpace =
2130
+ collectedFlexItemsValues.remainingFreeSpace ;
2049
2131
float deltaFreeSpace = 0 ;
2050
2132
2051
2133
if (!canSkipFlex) {
2052
2134
float childFlexBasis;
2053
2135
float flexShrinkScaledFactor;
2054
2136
float flexGrowFactor;
2055
- float baseMainSize;
2056
- float boundMainSize;
2057
2137
2058
2138
// Do two passes over the flex items to figure out how to distribute the
2059
2139
// remaining space.
@@ -2078,80 +2158,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2078
2158
// concerns because we know exactly how many passes it'll do.
2079
2159
2080
2160
// 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);
2155
2167
2156
2168
// Second pass: resolve the sizes of the flexible items
2157
2169
deltaFreeSpace = 0 ;
@@ -2164,7 +2176,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2164
2176
mainAxisParentSize);
2165
2177
float updatedMainSize = childFlexBasis;
2166
2178
2167
- if (remainingFreeSpace < 0 ) {
2179
+ if (collectedFlexItemsValues. remainingFreeSpace < 0 ) {
2168
2180
flexShrinkScaledFactor =
2169
2181
-currentRelativeChild->resolveFlexShrink () * childFlexBasis;
2170
2182
// Is this child able to shrink?
@@ -2175,7 +2187,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2175
2187
childSize = childFlexBasis + flexShrinkScaledFactor;
2176
2188
} else {
2177
2189
childSize = childFlexBasis +
2178
- (remainingFreeSpace /
2190
+ (collectedFlexItemsValues. remainingFreeSpace /
2179
2191
collectedFlexItemsValues.totalFlexShrinkScaledFactors ) *
2180
2192
flexShrinkScaledFactor;
2181
2193
}
@@ -2187,7 +2199,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2187
2199
availableInnerMainDim,
2188
2200
availableInnerWidth);
2189
2201
}
2190
- } else if (remainingFreeSpace > 0 ) {
2202
+ } else if (collectedFlexItemsValues. remainingFreeSpace > 0 ) {
2191
2203
flexGrowFactor = currentRelativeChild->resolveFlexGrow ();
2192
2204
2193
2205
// Is this child able to grow?
@@ -2196,7 +2208,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2196
2208
currentRelativeChild,
2197
2209
mainAxis,
2198
2210
childFlexBasis +
2199
- remainingFreeSpace /
2211
+ collectedFlexItemsValues. remainingFreeSpace /
2200
2212
collectedFlexItemsValues.totalFlexGrowFactors *
2201
2213
flexGrowFactor,
2202
2214
availableInnerMainDim,
@@ -2315,9 +2327,11 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2315
2327
}
2316
2328
}
2317
2329
2318
- remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
2330
+ collectedFlexItemsValues.remainingFreeSpace =
2331
+ originalRemainingFreeSpace + deltaFreeSpace;
2319
2332
node->setLayoutHadOverflow (
2320
- node->getLayout ().hadOverflow | (remainingFreeSpace < 0 ));
2333
+ node->getLayout ().hadOverflow |
2334
+ (collectedFlexItemsValues.remainingFreeSpace < 0 ));
2321
2335
2322
2336
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
2323
2337
@@ -2331,20 +2345,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2331
2345
// If we are using "at most" rules in the main axis. Calculate the remaining space when
2332
2346
// constraint by the min size defined for the main axis.
2333
2347
2334
- if (measureModeMainDim == YGMeasureModeAtMost && remainingFreeSpace > 0 ) {
2348
+ if (measureModeMainDim == YGMeasureModeAtMost &&
2349
+ collectedFlexItemsValues.remainingFreeSpace > 0 ) {
2335
2350
if (node->getStyle ().minDimensions [dim[mainAxis]].unit !=
2336
2351
YGUnitUndefined &&
2337
2352
YGResolveValue (
2338
2353
node->getStyle ().minDimensions [dim[mainAxis]],
2339
2354
mainAxisParentSize) >= 0 ) {
2340
- remainingFreeSpace = fmaxf (
2355
+ collectedFlexItemsValues. remainingFreeSpace = fmaxf (
2341
2356
0 ,
2342
2357
YGResolveValue (
2343
2358
node->getStyle ().minDimensions [dim[mainAxis]],
2344
2359
mainAxisParentSize) -
2345
- (availableInnerMainDim - remainingFreeSpace));
2360
+ (availableInnerMainDim -
2361
+ collectedFlexItemsValues.remainingFreeSpace ));
2346
2362
} else {
2347
- remainingFreeSpace = 0 ;
2363
+ collectedFlexItemsValues. remainingFreeSpace = 0 ;
2348
2364
}
2349
2365
}
2350
2366
@@ -2371,29 +2387,30 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2371
2387
if (numberOfAutoMarginsOnCurrentLine == 0 ) {
2372
2388
switch (justifyContent) {
2373
2389
case YGJustifyCenter:
2374
- leadingMainDim = remainingFreeSpace / 2 ;
2390
+ leadingMainDim = collectedFlexItemsValues. remainingFreeSpace / 2 ;
2375
2391
break ;
2376
2392
case YGJustifyFlexEnd:
2377
- leadingMainDim = remainingFreeSpace;
2393
+ leadingMainDim = collectedFlexItemsValues. remainingFreeSpace ;
2378
2394
break ;
2379
2395
case YGJustifySpaceBetween:
2380
2396
if (collectedFlexItemsValues.itemsOnLine > 1 ) {
2381
- betweenMainDim = fmaxf (remainingFreeSpace, 0 ) /
2397
+ betweenMainDim =
2398
+ fmaxf (collectedFlexItemsValues.remainingFreeSpace , 0 ) /
2382
2399
(collectedFlexItemsValues.itemsOnLine - 1 );
2383
2400
} else {
2384
2401
betweenMainDim = 0 ;
2385
2402
}
2386
2403
break ;
2387
2404
case YGJustifySpaceEvenly:
2388
2405
// Space is distributed evenly across all elements
2389
- betweenMainDim =
2390
- remainingFreeSpace / (collectedFlexItemsValues.itemsOnLine + 1 );
2406
+ betweenMainDim = collectedFlexItemsValues. remainingFreeSpace /
2407
+ (collectedFlexItemsValues.itemsOnLine + 1 );
2391
2408
leadingMainDim = betweenMainDim;
2392
2409
break ;
2393
2410
case YGJustifySpaceAround:
2394
2411
// Space on the edges is half of the space between elements
2395
- betweenMainDim =
2396
- remainingFreeSpace / collectedFlexItemsValues.itemsOnLine ;
2412
+ betweenMainDim = collectedFlexItemsValues. remainingFreeSpace /
2413
+ collectedFlexItemsValues.itemsOnLine ;
2397
2414
leadingMainDim = betweenMainDim / 2 ;
2398
2415
break ;
2399
2416
case YGJustifyFlexStart:
@@ -2427,7 +2444,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2427
2444
// do not take part in that phase.
2428
2445
if (child->getStyle ().positionType == YGPositionTypeRelative) {
2429
2446
if (child->marginLeadingValue (mainAxis).unit == YGUnitAuto) {
2430
- mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
2447
+ mainDim += collectedFlexItemsValues.remainingFreeSpace /
2448
+ numberOfAutoMarginsOnCurrentLine;
2431
2449
}
2432
2450
2433
2451
if (performLayout) {
@@ -2437,7 +2455,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2437
2455
}
2438
2456
2439
2457
if (child->marginTrailingValue (mainAxis).unit == YGUnitAuto) {
2440
- mainDim += remainingFreeSpace / numberOfAutoMarginsOnCurrentLine;
2458
+ mainDim += collectedFlexItemsValues.remainingFreeSpace /
2459
+ numberOfAutoMarginsOnCurrentLine;
2441
2460
}
2442
2461
2443
2462
if (canSkipFlex) {
0 commit comments