@@ -1619,6 +1619,88 @@ static void YGNodeComputeFlexBasisForChildren(
1619
1619
}
1620
1620
}
1621
1621
1622
+ // This function assumes that all the children of node have their
1623
+ // computedFlexBasis properly computed(To do this use
1624
+ // YGNodeComputeFlexBasisForChildren function).
1625
+ // This function calculates YGCollectFlexItemsRowMeasurement
1626
+ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues (
1627
+ const YGNodeRef& node,
1628
+ const YGDirection parentDirection,
1629
+ const float mainAxisParentSize,
1630
+ const float availableInnerWidth,
1631
+ const float availableInnerMainDim,
1632
+ const uint32_t startOfLineIndex,
1633
+ const uint32_t lineCount) {
1634
+ YGCollectFlexItemsRowValues flexAlgoRowMeasurement = {};
1635
+ flexAlgoRowMeasurement.relativeChildren .reserve (node->getChildren ().size ());
1636
+
1637
+ float sizeConsumedOnCurrentLineIncludingMinConstraint = 0 ;
1638
+ const YGFlexDirection mainAxis = YGResolveFlexDirection (
1639
+ node->getStyle ().flexDirection , node->resolveDirection (parentDirection));
1640
+ const bool isNodeFlexWrap = node->getStyle ().flexWrap != YGWrapNoWrap;
1641
+
1642
+ // Add items to the current line until it's full or we run out of items.
1643
+ uint32_t endOfLineIndex = startOfLineIndex;
1644
+ for (; endOfLineIndex < node->getChildrenCount (); endOfLineIndex++) {
1645
+ const YGNodeRef child = node->getChild (endOfLineIndex);
1646
+ if (child->getStyle ().display == YGDisplayNone ||
1647
+ child->getStyle ().positionType == YGPositionTypeAbsolute) {
1648
+ continue ;
1649
+ }
1650
+ child->setLineIndex (lineCount);
1651
+ const float childMarginMainAxis =
1652
+ YGNodeMarginForAxis (child, mainAxis, availableInnerWidth);
1653
+ const float flexBasisWithMinAndMaxConstraints =
1654
+ YGNodeBoundAxisWithinMinAndMax (
1655
+ child,
1656
+ mainAxis,
1657
+ child->getLayout ().computedFlexBasis ,
1658
+ mainAxisParentSize);
1659
+
1660
+ // If this is a multi-line flow and this item pushes us over the
1661
+ // available size, we've
1662
+ // hit the end of the current line. Break out of the loop and lay out
1663
+ // the current line.
1664
+ if (sizeConsumedOnCurrentLineIncludingMinConstraint +
1665
+ flexBasisWithMinAndMaxConstraints + childMarginMainAxis >
1666
+ availableInnerMainDim &&
1667
+ isNodeFlexWrap && flexAlgoRowMeasurement.itemsOnLine > 0 ) {
1668
+ break ;
1669
+ }
1670
+
1671
+ sizeConsumedOnCurrentLineIncludingMinConstraint +=
1672
+ flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
1673
+ flexAlgoRowMeasurement.sizeConsumedOnCurrentLine +=
1674
+ flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
1675
+ flexAlgoRowMeasurement.itemsOnLine ++;
1676
+
1677
+ if (child->isNodeFlexible ()) {
1678
+ flexAlgoRowMeasurement.totalFlexGrowFactors += child->resolveFlexGrow ();
1679
+
1680
+ // Unlike the grow factor, the shrink factor is scaled relative to the
1681
+ // child dimension.
1682
+ flexAlgoRowMeasurement.totalFlexShrinkScaledFactors +=
1683
+ -child->resolveFlexShrink () * child->getLayout ().computedFlexBasis ;
1684
+ }
1685
+
1686
+ flexAlgoRowMeasurement.relativeChildren .push_back (child);
1687
+ }
1688
+
1689
+ // The total flex factor needs to be floored to 1.
1690
+ if (flexAlgoRowMeasurement.totalFlexGrowFactors > 0 &&
1691
+ flexAlgoRowMeasurement.totalFlexGrowFactors < 1 ) {
1692
+ flexAlgoRowMeasurement.totalFlexGrowFactors = 1 ;
1693
+ }
1694
+
1695
+ // The total flex shrink factor needs to be floored to 1.
1696
+ if (flexAlgoRowMeasurement.totalFlexShrinkScaledFactors > 0 &&
1697
+ flexAlgoRowMeasurement.totalFlexShrinkScaledFactors < 1 ) {
1698
+ flexAlgoRowMeasurement.totalFlexShrinkScaledFactors = 1 ;
1699
+ }
1700
+ flexAlgoRowMeasurement.endOfLineIndex = endOfLineIndex;
1701
+ return flexAlgoRowMeasurement;
1702
+ }
1703
+
1622
1704
//
1623
1705
// This is the main routine that implements a subset of the flexbox layout
1624
1706
// algorithm
@@ -1803,7 +1885,6 @@ static void YGNodelayoutImpl(const YGNodeRef node,
1803
1885
YGResolveFlexDirection (node->getStyle ().flexDirection , direction);
1804
1886
const YGFlexDirection crossAxis = YGFlexDirectionCross (mainAxis, direction);
1805
1887
const bool isMainAxisRow = YGFlexDirectionIsRow (mainAxis);
1806
- const YGJustify justifyContent = node->getStyle ().justifyContent ;
1807
1888
const bool isNodeFlexWrap = node->getStyle ().flexWrap != YGWrapNoWrap;
1808
1889
1809
1890
const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight;
@@ -1879,9 +1960,10 @@ static void YGNodelayoutImpl(const YGNodeRef node,
1879
1960
totalOuterFlexBasis);
1880
1961
1881
1962
const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined
1882
- ? false
1883
- : totalOuterFlexBasis > availableInnerMainDim;
1884
- if (isNodeFlexWrap && flexBasisOverflows && measureModeMainDim == YGMeasureModeAtMost) {
1963
+ ? false
1964
+ : totalOuterFlexBasis > availableInnerMainDim;
1965
+ if (isNodeFlexWrap && flexBasisOverflows &&
1966
+ measureModeMainDim == YGMeasureModeAtMost) {
1885
1967
measureModeMainDim = YGMeasureModeExactly;
1886
1968
}
1887
1969
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
@@ -1898,93 +1980,23 @@ static void YGNodelayoutImpl(const YGNodeRef node,
1898
1980
1899
1981
// Max main dimension of all the lines.
1900
1982
float maxLineMainDim = 0 ;
1901
-
1902
- for (; endOfLineIndex < childCount; lineCount++, startOfLineIndex = endOfLineIndex) {
1903
- // Number of items on the currently line. May be different than the
1904
- // difference
1905
- // between start and end indicates because we skip over absolute-positioned
1906
- // items.
1907
- uint32_t itemsOnLine = 0 ;
1908
-
1909
- // sizeConsumedOnCurrentLine is accumulation of the dimensions and margin
1910
- // of all the children on the current line. This will be used in order to
1911
- // either set the dimensions of the node if none already exist or to compute
1912
- // the remaining space left for the flexible children.
1913
- float sizeConsumedOnCurrentLine = 0 ;
1914
- float sizeConsumedOnCurrentLineIncludingMinConstraint = 0 ;
1915
-
1916
- float totalFlexGrowFactors = 0 ;
1917
- float totalFlexShrinkScaledFactors = 0 ;
1918
-
1919
- // Maintain a vector of the child nodes that can shrink and/or grow.
1920
- std::vector<YGNodeRef> relativeChildren;
1921
-
1922
- // Add items to the current line until it's full or we run out of items.
1923
- for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) {
1924
- const YGNodeRef child = node->getChild (i);
1925
- if (child->getStyle ().display == YGDisplayNone ||
1926
- child->getStyle ().positionType == YGPositionTypeAbsolute) {
1927
- continue ;
1928
- }
1929
- child->setLineIndex (lineCount);
1930
- const float childMarginMainAxis =
1931
- YGNodeMarginForAxis (child, mainAxis, availableInnerWidth);
1932
- const float flexBasisWithMinAndMaxConstraints =
1933
- YGNodeBoundAxisWithinMinAndMax (
1934
- child,
1935
- mainAxis,
1936
- child->getLayout ().computedFlexBasis ,
1937
- mainAxisParentSize);
1938
-
1939
- // If this is a multi-line flow and this item pushes us over the
1940
- // available size, we've
1941
- // hit the end of the current line. Break out of the loop and lay out
1942
- // the current line.
1943
- if (sizeConsumedOnCurrentLineIncludingMinConstraint +
1944
- flexBasisWithMinAndMaxConstraints + childMarginMainAxis >
1945
- availableInnerMainDim &&
1946
- isNodeFlexWrap && itemsOnLine > 0 ) {
1947
- break ;
1948
- }
1949
-
1950
- sizeConsumedOnCurrentLineIncludingMinConstraint +=
1951
- flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
1952
- sizeConsumedOnCurrentLine +=
1953
- flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
1954
- itemsOnLine++;
1955
-
1956
- if (child->isNodeFlexible ()) {
1957
- totalFlexGrowFactors += child->resolveFlexGrow ();
1958
-
1959
- // Unlike the grow factor, the shrink factor is scaled relative to the
1960
- // child dimension.
1961
- totalFlexShrinkScaledFactors +=
1962
- -child->resolveFlexShrink () * child->getLayout ().computedFlexBasis ;
1963
- }
1964
-
1965
- // Store a private linked list of children that need to be layed out.
1966
- relativeChildren.push_back (child);
1967
- }
1968
-
1969
- // The total flex factor needs to be floored to 1.
1970
- if (totalFlexGrowFactors > 0 && totalFlexGrowFactors < 1 ) {
1971
- totalFlexGrowFactors = 1 ;
1972
- }
1973
-
1974
- // The total flex shrink factor needs to be floored to 1.
1975
- if (totalFlexShrinkScaledFactors > 0 && totalFlexShrinkScaledFactors < 1 ) {
1976
- totalFlexShrinkScaledFactors = 1 ;
1977
- }
1983
+ YGCollectFlexItemsRowValues collectedFlexItemsValues;
1984
+ for (; endOfLineIndex < childCount;
1985
+ lineCount++, startOfLineIndex = endOfLineIndex) {
1986
+ collectedFlexItemsValues = YGCalculateCollectFlexItemsRowValues (
1987
+ node,
1988
+ parentDirection,
1989
+ mainAxisParentSize,
1990
+ availableInnerWidth,
1991
+ availableInnerMainDim,
1992
+ startOfLineIndex,
1993
+ lineCount);
1994
+ endOfLineIndex = collectedFlexItemsValues.endOfLineIndex ;
1978
1995
1979
1996
// If we don't need to measure the cross axis, we can skip the entire flex
1980
1997
// step.
1981
- const bool canSkipFlex = !performLayout && measureModeCrossDim == YGMeasureModeExactly;
1982
-
1983
- // In order to position the elements in the main axis, we have two
1984
- // controls. The space between the beginning and the first element
1985
- // and the space between each two elements.
1986
- float leadingMainDim = 0 ;
1987
- float betweenMainDim = 0 ;
1998
+ const bool canSkipFlex =
1999
+ !performLayout && measureModeCrossDim == YGMeasureModeExactly;
1988
2000
1989
2001
// STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS
1990
2002
// Calculate the remaining available space that needs to be allocated.
@@ -1994,18 +2006,24 @@ static void YGNodelayoutImpl(const YGNodeRef node,
1994
2006
bool sizeBasedOnContent = false ;
1995
2007
// If we don't measure with exact main dimension we want to ensure we don't violate min and max
1996
2008
if (measureModeMainDim != YGMeasureModeExactly) {
1997
- if (!YGFloatIsUndefined (minInnerMainDim) && sizeConsumedOnCurrentLine < minInnerMainDim) {
2009
+ if (!YGFloatIsUndefined (minInnerMainDim) &&
2010
+ collectedFlexItemsValues.sizeConsumedOnCurrentLine <
2011
+ minInnerMainDim) {
1998
2012
availableInnerMainDim = minInnerMainDim;
1999
- } else if (!YGFloatIsUndefined (maxInnerMainDim) &&
2000
- sizeConsumedOnCurrentLine > maxInnerMainDim) {
2013
+ } else if (
2014
+ !YGFloatIsUndefined (maxInnerMainDim) &&
2015
+ collectedFlexItemsValues.sizeConsumedOnCurrentLine >
2016
+ maxInnerMainDim) {
2001
2017
availableInnerMainDim = maxInnerMainDim;
2002
2018
} else {
2003
2019
if (!node->getConfig ()->useLegacyStretchBehaviour &&
2004
- (totalFlexGrowFactors == 0 || node->resolveFlexGrow () == 0 )) {
2020
+ (collectedFlexItemsValues.totalFlexGrowFactors == 0 ||
2021
+ node->resolveFlexGrow () == 0 )) {
2005
2022
// If we don't have any children to flex or we can't flex the node
2006
2023
// itself, space we've used is all space we need. Root node also
2007
2024
// should be shrunk to minimum
2008
- availableInnerMainDim = sizeConsumedOnCurrentLine;
2025
+ availableInnerMainDim =
2026
+ collectedFlexItemsValues.sizeConsumedOnCurrentLine ;
2009
2027
}
2010
2028
2011
2029
if (node->getConfig ()->useLegacyStretchBehaviour ) {
@@ -2017,13 +2035,14 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2017
2035
2018
2036
float remainingFreeSpace = 0 ;
2019
2037
if (!sizeBasedOnContent && !YGFloatIsUndefined (availableInnerMainDim)) {
2020
- remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine;
2021
- } else if (sizeConsumedOnCurrentLine < 0 ) {
2038
+ remainingFreeSpace = availableInnerMainDim -
2039
+ collectedFlexItemsValues.sizeConsumedOnCurrentLine ;
2040
+ } else if (collectedFlexItemsValues.sizeConsumedOnCurrentLine < 0 ) {
2022
2041
// availableInnerMainDim is indefinite which means the node is being sized based on its
2023
2042
// content.
2024
2043
// sizeConsumedOnCurrentLine is negative which means the node will allocate 0 points for
2025
2044
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
2026
- remainingFreeSpace = -sizeConsumedOnCurrentLine;
2045
+ remainingFreeSpace = -collectedFlexItemsValues. sizeConsumedOnCurrentLine ;
2027
2046
}
2028
2047
2029
2048
const float originalRemainingFreeSpace = remainingFreeSpace;
@@ -2062,7 +2081,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2062
2081
float deltaFlexShrinkScaledFactors = 0 ;
2063
2082
float deltaFlexGrowFactors = 0 ;
2064
2083
2065
- for (auto currentRelativeChild : relativeChildren) {
2084
+ for (auto currentRelativeChild :
2085
+ collectedFlexItemsValues.relativeChildren ) {
2066
2086
childFlexBasis = YGNodeBoundAxisWithinMinAndMax (
2067
2087
currentRelativeChild,
2068
2088
mainAxis,
@@ -2076,7 +2096,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2076
2096
// Is this child able to shrink?
2077
2097
if (flexShrinkScaledFactor != 0 ) {
2078
2098
baseMainSize = childFlexBasis +
2079
- remainingFreeSpace / totalFlexShrinkScaledFactors *
2099
+ remainingFreeSpace /
2100
+ collectedFlexItemsValues.totalFlexShrinkScaledFactors *
2080
2101
flexShrinkScaledFactor;
2081
2102
boundMainSize = YGNodeBoundAxis (
2082
2103
currentRelativeChild,
@@ -2101,7 +2122,9 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2101
2122
// Is this child able to grow?
2102
2123
if (flexGrowFactor != 0 ) {
2103
2124
baseMainSize = childFlexBasis +
2104
- remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor;
2125
+ remainingFreeSpace /
2126
+ collectedFlexItemsValues.totalFlexGrowFactors *
2127
+ flexGrowFactor;
2105
2128
boundMainSize = YGNodeBoundAxis (
2106
2129
currentRelativeChild,
2107
2130
mainAxis,
@@ -2125,13 +2148,15 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2125
2148
currentRelativeChild = currentRelativeChild->getNextChild ();
2126
2149
}
2127
2150
2128
- totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
2129
- totalFlexGrowFactors += deltaFlexGrowFactors;
2151
+ collectedFlexItemsValues.totalFlexShrinkScaledFactors +=
2152
+ deltaFlexShrinkScaledFactors;
2153
+ collectedFlexItemsValues.totalFlexGrowFactors += deltaFlexGrowFactors;
2130
2154
remainingFreeSpace += deltaFreeSpace;
2131
2155
2132
2156
// Second pass: resolve the sizes of the flexible items
2133
2157
deltaFreeSpace = 0 ;
2134
- for (auto currentRelativeChild : relativeChildren) {
2158
+ for (auto currentRelativeChild :
2159
+ collectedFlexItemsValues.relativeChildren ) {
2135
2160
childFlexBasis = YGNodeBoundAxisWithinMinAndMax (
2136
2161
currentRelativeChild,
2137
2162
mainAxis,
@@ -2146,11 +2171,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2146
2171
if (flexShrinkScaledFactor != 0 ) {
2147
2172
float childSize;
2148
2173
2149
- if (totalFlexShrinkScaledFactors == 0 ) {
2174
+ if (collectedFlexItemsValues. totalFlexShrinkScaledFactors == 0 ) {
2150
2175
childSize = childFlexBasis + flexShrinkScaledFactor;
2151
2176
} else {
2152
2177
childSize = childFlexBasis +
2153
- (remainingFreeSpace / totalFlexShrinkScaledFactors) *
2178
+ (remainingFreeSpace /
2179
+ collectedFlexItemsValues.totalFlexShrinkScaledFactors ) *
2154
2180
flexShrinkScaledFactor;
2155
2181
}
2156
2182
@@ -2170,7 +2196,9 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2170
2196
currentRelativeChild,
2171
2197
mainAxis,
2172
2198
childFlexBasis +
2173
- remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor,
2199
+ remainingFreeSpace /
2200
+ collectedFlexItemsValues.totalFlexGrowFactors *
2201
+ flexGrowFactor,
2174
2202
availableInnerMainDim,
2175
2203
availableInnerWidth);
2176
2204
}
@@ -2333,6 +2361,13 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2333
2361
}
2334
2362
}
2335
2363
2364
+ // In order to position the elements in the main axis, we have two
2365
+ // controls. The space between the beginning and the first element
2366
+ // and the space between each two elements.
2367
+ float leadingMainDim = 0 ;
2368
+ float betweenMainDim = 0 ;
2369
+ const YGJustify justifyContent = node->getStyle ().justifyContent ;
2370
+
2336
2371
if (numberOfAutoMarginsOnCurrentLine == 0 ) {
2337
2372
switch (justifyContent) {
2338
2373
case YGJustifyCenter:
@@ -2342,20 +2377,23 @@ static void YGNodelayoutImpl(const YGNodeRef node,
2342
2377
leadingMainDim = remainingFreeSpace;
2343
2378
break ;
2344
2379
case YGJustifySpaceBetween:
2345
- if (itemsOnLine > 1 ) {
2346
- betweenMainDim = fmaxf (remainingFreeSpace, 0 ) / (itemsOnLine - 1 );
2380
+ if (collectedFlexItemsValues.itemsOnLine > 1 ) {
2381
+ betweenMainDim = fmaxf (remainingFreeSpace, 0 ) /
2382
+ (collectedFlexItemsValues.itemsOnLine - 1 );
2347
2383
} else {
2348
2384
betweenMainDim = 0 ;
2349
2385
}
2350
2386
break ;
2351
2387
case YGJustifySpaceEvenly:
2352
2388
// Space is distributed evenly across all elements
2353
- betweenMainDim = remainingFreeSpace / (itemsOnLine + 1 );
2389
+ betweenMainDim =
2390
+ remainingFreeSpace / (collectedFlexItemsValues.itemsOnLine + 1 );
2354
2391
leadingMainDim = betweenMainDim;
2355
2392
break ;
2356
2393
case YGJustifySpaceAround:
2357
2394
// Space on the edges is half of the space between elements
2358
- betweenMainDim = remainingFreeSpace / itemsOnLine;
2395
+ betweenMainDim =
2396
+ remainingFreeSpace / collectedFlexItemsValues.itemsOnLine ;
2359
2397
leadingMainDim = betweenMainDim / 2 ;
2360
2398
break ;
2361
2399
case YGJustifyFlexStart:
0 commit comments