Skip to content

Commit b221265

Browse files
NickGerlemanfacebook-github-bot
authored andcommitted
Fix sizing and alignment issues with multi-line containers (#41916)
Summary: X-link: facebook/yoga#1513 Pull Request resolved: #41916 Fixes facebook/yoga#1300 Fixes facebook/yoga#1008 This fixes a smattering of issues related to both sizing and aligment of multi-line-containers: 1. We were previously incorrectly bounding the size of each flex line to the min/max of the entire container. 2. Per-line leads were sometimes incorrectly contributing to alignment within the line 3. The cross dim size used for multi-line alignment is not correct, or correctly clamped. If the available size comes from a max constraint, that was incorrectly used instead of a definite size, or size of content. Leads were entirely skipped for min constraint. Need to test how breaking this is, to see if it might need to go behind an errata. See related PRs: 1. facebook/yoga#1491 2. facebook/yoga#1493 3. facebook/yoga#1013 Changelog: [General][Fixed] - Fix Yoga sizing and alignment issues with multi-line containers Reviewed By: joevilches Differential Revision: D52087013 fbshipit-source-id: 8d95ad17e58c1fec1cceab9756413d0b3bd4cd8f
1 parent ce69213 commit b221265

File tree

1 file changed

+74
-64
lines changed

1 file changed

+74
-64
lines changed

packages/react-native/ReactCommon/yoga/yoga/algorithm/CalculateLayout.cpp

+74-64
Original file line numberDiff line numberDiff line change
@@ -1569,15 +1569,20 @@ static void calculateLayoutImpl(
15691569
flexLine.layout.crossDim = availableInnerCrossDim;
15701570
}
15711571

1572-
// Clamp to the min/max size specified on the container.
1573-
flexLine.layout.crossDim =
1574-
boundAxis(
1575-
node,
1576-
crossAxis,
1577-
flexLine.layout.crossDim + paddingAndBorderAxisCross,
1578-
crossAxisownerSize,
1579-
ownerWidth) -
1580-
paddingAndBorderAxisCross;
1572+
// As-per https://www.w3.org/TR/css-flexbox-1/#cross-sizing, the
1573+
// cross-size of the line within a single-line container should be bound to
1574+
// min/max constraints before alignment within the line. In a multi-line
1575+
// container, affecting alignment between the lines.
1576+
if (!isNodeFlexWrap) {
1577+
flexLine.layout.crossDim =
1578+
boundAxis(
1579+
node,
1580+
crossAxis,
1581+
flexLine.layout.crossDim + paddingAndBorderAxisCross,
1582+
crossAxisownerSize,
1583+
ownerWidth) -
1584+
paddingAndBorderAxisCross;
1585+
}
15811586

15821587
// STEP 7: CROSS-AXIS ALIGNMENT
15831588
// We can skip child alignment if we're just measuring the container.
@@ -1735,59 +1740,65 @@ static void calculateLayoutImpl(
17351740
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
17361741
// currentLead stores the size of the cross dim
17371742
if (performLayout && (isNodeFlexWrap || isBaselineLayout(node))) {
1738-
float crossDimLead = 0;
1743+
float leadPerLine = 0;
17391744
float currentLead = leadingPaddingAndBorderCross;
1740-
if (yoga::isDefined(availableInnerCrossDim)) {
1741-
const float remainingAlignContentDim =
1742-
availableInnerCrossDim - totalLineCrossDim;
1743-
switch (node->getStyle().alignContent()) {
1744-
case Align::FlexEnd:
1745-
currentLead += remainingAlignContentDim;
1746-
break;
1747-
case Align::Center:
1745+
1746+
const float unclampedCrossDim =
1747+
node->styleDefinesDimension(crossAxis, crossAxisownerSize)
1748+
? yoga::resolveValue(
1749+
node->getResolvedDimension(dimension(crossAxis)),
1750+
crossAxisownerSize)
1751+
.unwrap()
1752+
: totalLineCrossDim + paddingAndBorderAxisCross;
1753+
1754+
const float innerCrossDim =
1755+
boundAxis(node, crossAxis, unclampedCrossDim, ownerHeight, ownerWidth) -
1756+
paddingAndBorderAxisCross;
1757+
1758+
const float remainingAlignContentDim = innerCrossDim - totalLineCrossDim;
1759+
switch (node->getStyle().alignContent()) {
1760+
case Align::FlexEnd:
1761+
currentLead += remainingAlignContentDim;
1762+
break;
1763+
case Align::Center:
1764+
currentLead += remainingAlignContentDim / 2;
1765+
break;
1766+
case Align::Stretch:
1767+
if (innerCrossDim > totalLineCrossDim) {
1768+
leadPerLine =
1769+
remainingAlignContentDim / static_cast<float>(lineCount);
1770+
}
1771+
break;
1772+
case Align::SpaceAround:
1773+
if (innerCrossDim > totalLineCrossDim) {
1774+
currentLead +=
1775+
remainingAlignContentDim / (2 * static_cast<float>(lineCount));
1776+
leadPerLine =
1777+
remainingAlignContentDim / static_cast<float>(lineCount);
1778+
} else {
17481779
currentLead += remainingAlignContentDim / 2;
1749-
break;
1750-
case Align::Stretch:
1751-
if (availableInnerCrossDim > totalLineCrossDim) {
1752-
crossDimLead =
1753-
remainingAlignContentDim / static_cast<float>(lineCount);
1754-
}
1755-
break;
1756-
case Align::SpaceAround:
1757-
if (availableInnerCrossDim > totalLineCrossDim) {
1758-
currentLead +=
1759-
remainingAlignContentDim / (2 * static_cast<float>(lineCount));
1760-
if (lineCount > 1) {
1761-
crossDimLead =
1762-
remainingAlignContentDim / static_cast<float>(lineCount);
1763-
}
1764-
} else {
1765-
currentLead += remainingAlignContentDim / 2;
1766-
}
1767-
break;
1768-
case Align::SpaceEvenly:
1769-
if (availableInnerCrossDim > totalLineCrossDim) {
1770-
currentLead +=
1771-
remainingAlignContentDim / static_cast<float>(lineCount + 1);
1772-
if (lineCount > 1) {
1773-
crossDimLead =
1774-
remainingAlignContentDim / static_cast<float>(lineCount + 1);
1775-
}
1776-
} else {
1777-
currentLead += remainingAlignContentDim / 2;
1778-
}
1779-
break;
1780-
case Align::SpaceBetween:
1781-
if (availableInnerCrossDim > totalLineCrossDim && lineCount > 1) {
1782-
crossDimLead =
1783-
remainingAlignContentDim / static_cast<float>(lineCount - 1);
1784-
}
1785-
break;
1786-
case Align::Auto:
1787-
case Align::FlexStart:
1788-
case Align::Baseline:
1789-
break;
1790-
}
1780+
}
1781+
break;
1782+
case Align::SpaceEvenly:
1783+
if (innerCrossDim > totalLineCrossDim) {
1784+
currentLead +=
1785+
remainingAlignContentDim / static_cast<float>(lineCount + 1);
1786+
leadPerLine =
1787+
remainingAlignContentDim / static_cast<float>(lineCount + 1);
1788+
} else {
1789+
currentLead += remainingAlignContentDim / 2;
1790+
}
1791+
break;
1792+
case Align::SpaceBetween:
1793+
if (innerCrossDim > totalLineCrossDim && lineCount > 1) {
1794+
leadPerLine =
1795+
remainingAlignContentDim / static_cast<float>(lineCount - 1);
1796+
}
1797+
break;
1798+
case Align::Auto:
1799+
case Align::FlexStart:
1800+
case Align::Baseline:
1801+
break;
17911802
}
17921803
size_t endIndex = 0;
17931804
for (size_t i = 0; i < lineCount; i++) {
@@ -1832,7 +1843,6 @@ static void calculateLayoutImpl(
18321843
}
18331844
}
18341845
endIndex = ii;
1835-
lineHeight += crossDimLead;
18361846
currentLead += i != 0 ? crossAxisGap : 0;
18371847

18381848
if (performLayout) {
@@ -1885,14 +1895,14 @@ static void calculateLayoutImpl(
18851895
? (child->getLayout().measuredDimension(
18861896
Dimension::Width) +
18871897
child->getMarginForAxis(mainAxis, availableInnerWidth))
1888-
: lineHeight;
1898+
: leadPerLine + lineHeight;
18891899

18901900
const float childHeight = !isMainAxisRow
18911901
? (child->getLayout().measuredDimension(
18921902
Dimension::Height) +
18931903
child->getMarginForAxis(
18941904
crossAxis, availableInnerWidth))
1895-
: lineHeight;
1905+
: leadPerLine + lineHeight;
18961906

18971907
if (!(yoga::inexactEquals(
18981908
childWidth,
@@ -1941,7 +1951,7 @@ static void calculateLayoutImpl(
19411951
}
19421952
}
19431953
}
1944-
currentLead += lineHeight;
1954+
currentLead = currentLead + leadPerLine + lineHeight;
19451955
}
19461956
}
19471957

0 commit comments

Comments
 (0)