Seperate function for second pass

Reviewed By: emilsjolander

Differential Revision: D6833635

fbshipit-source-id: 7680a67db8bfe22f8fb86407159888882f3a3353
This commit is contained in:
Pritesh Nandgaonkar 2018-02-05 06:33:03 -08:00 committed by Facebook Github Bot
parent fda861a889
commit ca91f0e3ac
1 changed files with 191 additions and 169 deletions

View File

@ -1701,6 +1701,183 @@ static YGCollectFlexItemsRowValues YGCalculateCollectFlexItemsRowValues(
return flexAlgoRowMeasurement;
}
static void YGDistributeFreeSpaceSecondPass(
YGCollectFlexItemsRowValues& collectedFlexItemsValues,
const YGNodeRef node,
const YGFlexDirection mainAxis,
const YGFlexDirection crossAxis,
const float mainAxisParentSize,
const float availableInnerMainDim,
const float availableInnerCrossDim,
const float availableInnerWidth,
const float availableInnerHeight,
const bool flexBasisOverflows,
const YGMeasureMode measureModeCrossDim,
const bool performLayout,
const YGConfigRef config) {
float childFlexBasis = 0;
float flexShrinkScaledFactor = 0;
float flexGrowFactor = 0;
float deltaFreeSpace = 0;
const bool isMainAxisRow = YGFlexDirectionIsRow(mainAxis);
const bool isNodeFlexWrap = node->getStyle().flexWrap != YGWrapNoWrap;
for (auto currentRelativeChild : collectedFlexItemsValues.relativeChildren) {
childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
currentRelativeChild,
mainAxis,
currentRelativeChild->getLayout().computedFlexBasis,
mainAxisParentSize);
float updatedMainSize = childFlexBasis;
if (collectedFlexItemsValues.remainingFreeSpace < 0) {
flexShrinkScaledFactor =
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
float childSize;
if (collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) {
childSize = childFlexBasis + flexShrinkScaledFactor;
} else {
childSize = childFlexBasis +
(collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.totalFlexShrinkScaledFactors) *
flexShrinkScaledFactor;
}
updatedMainSize = YGNodeBoundAxis(
currentRelativeChild,
mainAxis,
childSize,
availableInnerMainDim,
availableInnerWidth);
}
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
// Is this child able to grow?
if (flexGrowFactor != 0) {
updatedMainSize = YGNodeBoundAxis(
currentRelativeChild,
mainAxis,
childFlexBasis +
collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.totalFlexGrowFactors *
flexGrowFactor,
availableInnerMainDim,
availableInnerWidth);
}
}
deltaFreeSpace -= updatedMainSize - childFlexBasis;
const float marginMain = YGNodeMarginForAxis(
currentRelativeChild, mainAxis, availableInnerWidth);
const float marginCross = YGNodeMarginForAxis(
currentRelativeChild, crossAxis, availableInnerWidth);
float childCrossSize;
float childMainSize = updatedMainSize + marginMain;
YGMeasureMode childCrossMeasureMode;
YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
if (!YGFloatIsUndefined(currentRelativeChild->getStyle().aspectRatio)) {
childCrossSize = isMainAxisRow ? (childMainSize - marginMain) /
currentRelativeChild->getStyle().aspectRatio
: (childMainSize - marginMain) *
currentRelativeChild->getStyle().aspectRatio;
childCrossMeasureMode = YGMeasureModeExactly;
childCrossSize += marginCross;
} else if (
!YGFloatIsUndefined(availableInnerCrossDim) &&
!YGNodeIsStyleDimDefined(
currentRelativeChild, crossAxis, availableInnerCrossDim) &&
measureModeCrossDim == YGMeasureModeExactly &&
!(isNodeFlexWrap && flexBasisOverflows) &&
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
currentRelativeChild->marginLeadingValue(crossAxis).unit !=
YGUnitAuto &&
currentRelativeChild->marginTrailingValue(crossAxis).unit !=
YGUnitAuto) {
childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = YGMeasureModeExactly;
} else if (!YGNodeIsStyleDimDefined(
currentRelativeChild, crossAxis, availableInnerCrossDim)) {
childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = YGFloatIsUndefined(childCrossSize)
? YGMeasureModeUndefined
: YGMeasureModeAtMost;
} else {
childCrossSize =
YGResolveValue(
currentRelativeChild->getResolvedDimension(dim[crossAxis]),
availableInnerCrossDim) +
marginCross;
const bool isLoosePercentageMeasurement =
currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit ==
YGUnitPercent &&
measureModeCrossDim != YGMeasureModeExactly;
childCrossMeasureMode =
YGFloatIsUndefined(childCrossSize) || isLoosePercentageMeasurement
? YGMeasureModeUndefined
: YGMeasureModeExactly;
}
YGConstrainMaxSizeForMode(
currentRelativeChild,
mainAxis,
availableInnerMainDim,
availableInnerWidth,
&childMainMeasureMode,
&childMainSize);
YGConstrainMaxSizeForMode(
currentRelativeChild,
crossAxis,
availableInnerCrossDim,
availableInnerWidth,
&childCrossMeasureMode,
&childCrossSize);
const bool requiresStretchLayout =
!YGNodeIsStyleDimDefined(
currentRelativeChild, crossAxis, availableInnerCrossDim) &&
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
currentRelativeChild->marginLeadingValue(crossAxis).unit !=
YGUnitAuto &&
currentRelativeChild->marginTrailingValue(crossAxis).unit != YGUnitAuto;
const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;
const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize;
const YGMeasureMode childWidthMeasureMode =
isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
const YGMeasureMode childHeightMeasureMode =
!isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
// Recursively call the layout algorithm for this child with the updated
// main size.
YGLayoutNodeInternal(
currentRelativeChild,
childWidth,
childHeight,
node->getLayout().direction,
childWidthMeasureMode,
childHeightMeasureMode,
availableInnerWidth,
availableInnerHeight,
performLayout && !requiresStretchLayout,
"flex",
config);
node->setLayoutHadOverflow(
node->getLayout().hadOverflow |
currentRelativeChild->getLayout().hadOverflow);
}
collectedFlexItemsValues.remainingFreeSpace += deltaFreeSpace;
}
// It distributes the free space to the flexible items, for those flexible items
// whose min and max constraints are triggered, the clamped size is removed from
// the remaingfreespace.
@ -2126,15 +2303,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
-collectedFlexItemsValues.sizeConsumedOnCurrentLine;
}
const float originalRemainingFreeSpace =
collectedFlexItemsValues.remainingFreeSpace;
float deltaFreeSpace = 0;
if (!canSkipFlex) {
float childFlexBasis;
float flexShrinkScaledFactor;
float flexGrowFactor;
// Do two passes over the flex items to figure out how to distribute the
// remaining space.
// The first pass finds the items whose min/max constraints trigger,
@ -2166,169 +2335,22 @@ static void YGNodelayoutImpl(const YGNodeRef node,
availableInnerWidth);
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
for (auto currentRelativeChild :
collectedFlexItemsValues.relativeChildren) {
childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
currentRelativeChild,
mainAxis,
currentRelativeChild->getLayout().computedFlexBasis,
mainAxisParentSize);
float updatedMainSize = childFlexBasis;
if (collectedFlexItemsValues.remainingFreeSpace < 0) {
flexShrinkScaledFactor =
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
float childSize;
if (collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) {
childSize = childFlexBasis + flexShrinkScaledFactor;
} else {
childSize = childFlexBasis +
(collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.totalFlexShrinkScaledFactors) *
flexShrinkScaledFactor;
}
updatedMainSize = YGNodeBoundAxis(
currentRelativeChild,
mainAxis,
childSize,
availableInnerMainDim,
availableInnerWidth);
}
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
// Is this child able to grow?
if (flexGrowFactor != 0) {
updatedMainSize = YGNodeBoundAxis(
currentRelativeChild,
mainAxis,
childFlexBasis +
collectedFlexItemsValues.remainingFreeSpace /
collectedFlexItemsValues.totalFlexGrowFactors *
flexGrowFactor,
availableInnerMainDim,
availableInnerWidth);
}
}
deltaFreeSpace -= updatedMainSize - childFlexBasis;
const float marginMain = YGNodeMarginForAxis(
currentRelativeChild, mainAxis, availableInnerWidth);
const float marginCross = YGNodeMarginForAxis(
currentRelativeChild, crossAxis, availableInnerWidth);
float childCrossSize;
float childMainSize = updatedMainSize + marginMain;
YGMeasureMode childCrossMeasureMode;
YGMeasureMode childMainMeasureMode = YGMeasureModeExactly;
if (!YGFloatIsUndefined(currentRelativeChild->getStyle().aspectRatio)) {
childCrossSize = isMainAxisRow ? (childMainSize - marginMain) /
currentRelativeChild->getStyle().aspectRatio
: (childMainSize - marginMain) *
currentRelativeChild->getStyle().aspectRatio;
childCrossMeasureMode = YGMeasureModeExactly;
childCrossSize += marginCross;
} else if (
!YGFloatIsUndefined(availableInnerCrossDim) &&
!YGNodeIsStyleDimDefined(
currentRelativeChild, crossAxis, availableInnerCrossDim) &&
measureModeCrossDim == YGMeasureModeExactly &&
!(isNodeFlexWrap && flexBasisOverflows) &&
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
currentRelativeChild->marginLeadingValue(crossAxis).unit !=
YGUnitAuto &&
currentRelativeChild->marginTrailingValue(crossAxis).unit !=
YGUnitAuto) {
childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = YGMeasureModeExactly;
} else if (!YGNodeIsStyleDimDefined(
currentRelativeChild,
crossAxis,
availableInnerCrossDim)) {
childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = YGFloatIsUndefined(childCrossSize)
? YGMeasureModeUndefined
: YGMeasureModeAtMost;
} else {
childCrossSize =
YGResolveValue(
currentRelativeChild->getResolvedDimension(dim[crossAxis]),
availableInnerCrossDim) +
marginCross;
const bool isLoosePercentageMeasurement =
currentRelativeChild->getResolvedDimension(dim[crossAxis]).unit ==
YGUnitPercent &&
measureModeCrossDim != YGMeasureModeExactly;
childCrossMeasureMode =
YGFloatIsUndefined(childCrossSize) || isLoosePercentageMeasurement
? YGMeasureModeUndefined
: YGMeasureModeExactly;
}
YGConstrainMaxSizeForMode(
currentRelativeChild,
mainAxis,
availableInnerMainDim,
availableInnerWidth,
&childMainMeasureMode,
&childMainSize);
YGConstrainMaxSizeForMode(
currentRelativeChild,
crossAxis,
availableInnerCrossDim,
availableInnerWidth,
&childCrossMeasureMode,
&childCrossSize);
const bool requiresStretchLayout =
!YGNodeIsStyleDimDefined(
currentRelativeChild, crossAxis, availableInnerCrossDim) &&
YGNodeAlignItem(node, currentRelativeChild) == YGAlignStretch &&
currentRelativeChild->marginLeadingValue(crossAxis).unit !=
YGUnitAuto &&
currentRelativeChild->marginTrailingValue(crossAxis).unit !=
YGUnitAuto;
const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;
const float childHeight =
!isMainAxisRow ? childMainSize : childCrossSize;
const YGMeasureMode childWidthMeasureMode =
isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
const YGMeasureMode childHeightMeasureMode =
!isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
// Recursively call the layout algorithm for this child with the updated
// main size.
YGLayoutNodeInternal(
currentRelativeChild,
childWidth,
childHeight,
direction,
childWidthMeasureMode,
childHeightMeasureMode,
availableInnerWidth,
availableInnerHeight,
performLayout && !requiresStretchLayout,
"flex",
config);
node->setLayoutHadOverflow(
node->getLayout().hadOverflow |
currentRelativeChild->getLayout().hadOverflow);
currentRelativeChild = currentRelativeChild->getNextChild();
}
YGDistributeFreeSpaceSecondPass(
collectedFlexItemsValues,
node,
mainAxis,
crossAxis,
mainAxisParentSize,
availableInnerMainDim,
availableInnerCrossDim,
availableInnerWidth,
availableInnerHeight,
flexBasisOverflows,
measureModeCrossDim,
performLayout,
config);
}
collectedFlexItemsValues.remainingFreeSpace =
originalRemainingFreeSpace + deltaFreeSpace;
node->setLayoutHadOverflow(
node->getLayout().hadOverflow |
(collectedFlexItemsValues.remainingFreeSpace < 0));