Use vector instead of linked list

Summary: Currently in the flexbox algorithm we were using linked list for maintaining the nodes which had relative/absolute position types, this diff uses STL vector instead of linked list.

Reviewed By: emilsjolander

Differential Revision: D6722959

fbshipit-source-id: 4e81176802b9a9319bc5f385c824a06be14a83a2
This commit is contained in:
Pritesh Nandgaonkar
2018-01-16 09:31:21 -08:00
committed by Facebook Github Bot
parent 288adc49c9
commit 9ecdff14fa

View File

@@ -1782,9 +1782,6 @@ static void YGNodelayoutImpl(const YGNodeRef node,
const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight; const float mainAxisParentSize = isMainAxisRow ? parentWidth : parentHeight;
const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth; const float crossAxisParentSize = isMainAxisRow ? parentHeight : parentWidth;
YGNodeRef firstAbsoluteChild = nullptr;
YGNodeRef currentAbsoluteChild = nullptr;
const float leadingPaddingAndBorderMain = const float leadingPaddingAndBorderMain =
node->getLeadingPaddingAndBorder(mainAxis, parentWidth); node->getLeadingPaddingAndBorder(mainAxis, parentWidth);
const float trailingPaddingAndBorderMain = const float trailingPaddingAndBorderMain =
@@ -1822,27 +1819,10 @@ static void YGNodelayoutImpl(const YGNodeRef node,
YGResolveValue( YGResolveValue(
node->getStyle().maxDimensions[YGDimensionHeight], parentHeight) - node->getStyle().maxDimensions[YGDimensionHeight], parentHeight) -
paddingAndBorderAxisColumn; paddingAndBorderAxisColumn;
const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight; const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight;
const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight; const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight;
// Make a private linkedlist of absolutely positioned child
for (auto child : node->getChildren()) {
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (child->getStyle().positionType == YGPositionTypeAbsolute) {
// Store a private linked list of absolutely positioned children
// so that we can efficiently traverse them later.
if (firstAbsoluteChild == nullptr) {
firstAbsoluteChild = child;
}
if (currentAbsoluteChild != nullptr) {
currentAbsoluteChild->setNextChild(child);
}
currentAbsoluteChild = child;
child->setNextChild(nullptr);
}
}
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
float availableInnerWidth = YGNodeCalculateAvailableInnerDim( float availableInnerWidth = YGNodeCalculateAvailableInnerDim(
@@ -1909,65 +1889,54 @@ static void YGNodelayoutImpl(const YGNodeRef node,
float totalFlexGrowFactors = 0; float totalFlexGrowFactors = 0;
float totalFlexShrinkScaledFactors = 0; float totalFlexShrinkScaledFactors = 0;
// Maintain a linked list of the child nodes that can shrink and/or grow. // Maintain a vector of the child nodes that can shrink and/or grow.
YGNodeRef firstRelativeChild = nullptr; std::vector<YGNodeRef> relativeChildren;
YGNodeRef currentRelativeChild = nullptr;
// Add items to the current line until it's full or we run out of items. // Add items to the current line until it's full or we run out of items.
for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) { for (uint32_t i = startOfLineIndex; i < childCount; i++, endOfLineIndex++) {
const YGNodeRef child = node->getChild(i); const YGNodeRef child = node->getChild(i);
if (child->getStyle().display == YGDisplayNone) { if (child->getStyle().display == YGDisplayNone ||
child->getStyle().positionType == YGPositionTypeAbsolute) {
continue; continue;
} }
child->setLineIndex(lineCount); child->setLineIndex(lineCount);
const float childMarginMainAxis =
YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
const float flexBasisWithMinAndMaxConstraints =
YGNodeBoundAxisWithinMinAndMax(
child,
mainAxis,
child->getLayout().computedFlexBasis,
mainAxisParentSize);
if (child->getStyle().positionType != YGPositionTypeAbsolute) { // If this is a multi-line flow and this item pushes us over the
const float childMarginMainAxis = YGNodeMarginForAxis(child, mainAxis, availableInnerWidth); // available size, we've
const float flexBasisWithMaxConstraints = fminf( // hit the end of the current line. Break out of the loop and lay out
YGResolveValue( // the current line.
child->getStyle().maxDimensions[dim[mainAxis]], if (sizeConsumedOnCurrentLineIncludingMinConstraint +
mainAxisParentSize), flexBasisWithMinAndMaxConstraints + childMarginMainAxis >
child->getLayout().computedFlexBasis); availableInnerMainDim &&
const float flexBasisWithMinAndMaxConstraints = fmaxf( isNodeFlexWrap && itemsOnLine > 0) {
YGResolveValue( break;
child->getStyle().minDimensions[dim[mainAxis]],
mainAxisParentSize),
flexBasisWithMaxConstraints);
// If this is a multi-line flow and this item pushes us over the
// available size, we've
// hit the end of the current line. Break out of the loop and lay out
// the current line.
if (sizeConsumedOnCurrentLineIncludingMinConstraint + flexBasisWithMinAndMaxConstraints +
childMarginMainAxis >
availableInnerMainDim &&
isNodeFlexWrap && itemsOnLine > 0) {
break;
}
sizeConsumedOnCurrentLineIncludingMinConstraint +=
flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
sizeConsumedOnCurrentLine += flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
itemsOnLine++;
if (child->isNodeFlexible()) {
totalFlexGrowFactors += child->resolveFlexGrow();
// Unlike the grow factor, the shrink factor is scaled relative to the child dimension.
totalFlexShrinkScaledFactors += -child->resolveFlexShrink() *
child->getLayout().computedFlexBasis;
}
// Store a private linked list of children that need to be layed out.
if (firstRelativeChild == nullptr) {
firstRelativeChild = child;
}
if (currentRelativeChild != nullptr) {
currentRelativeChild->setNextChild(child);
}
currentRelativeChild = child;
child->setNextChild(nullptr);
} }
sizeConsumedOnCurrentLineIncludingMinConstraint +=
flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
sizeConsumedOnCurrentLine +=
flexBasisWithMinAndMaxConstraints + childMarginMainAxis;
itemsOnLine++;
if (child->isNodeFlexible()) {
totalFlexGrowFactors += child->resolveFlexGrow();
// Unlike the grow factor, the shrink factor is scaled relative to the
// child dimension.
totalFlexShrinkScaledFactors +=
-child->resolveFlexShrink() * child->getLayout().computedFlexBasis;
}
// Store a private linked list of children that need to be layed out.
relativeChildren.push_back(child);
} }
// The total flex factor needs to be floored to 1. // The total flex factor needs to be floored to 1.
@@ -2060,18 +2029,13 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// First pass: detect the flex items whose min/max constraints trigger // First pass: detect the flex items whose min/max constraints trigger
float deltaFlexShrinkScaledFactors = 0; float deltaFlexShrinkScaledFactors = 0;
float deltaFlexGrowFactors = 0; float deltaFlexGrowFactors = 0;
currentRelativeChild = firstRelativeChild;
while (currentRelativeChild != nullptr) { for (auto currentRelativeChild : relativeChildren) {
childFlexBasis = fminf( childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
YGResolveValue( currentRelativeChild,
currentRelativeChild->getStyle().maxDimensions[dim[mainAxis]], mainAxis,
mainAxisParentSize), currentRelativeChild->getLayout().computedFlexBasis,
fmaxf( mainAxisParentSize);
YGResolveValue(
currentRelativeChild->getStyle()
.minDimensions[dim[mainAxis]],
mainAxisParentSize),
currentRelativeChild->getLayout().computedFlexBasis));
if (remainingFreeSpace < 0) { if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = flexShrinkScaledFactor =
@@ -2079,14 +2043,15 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// Is this child able to shrink? // Is this child able to shrink?
if (flexShrinkScaledFactor != 0) { if (flexShrinkScaledFactor != 0) {
baseMainSize = baseMainSize = childFlexBasis +
childFlexBasis + remainingFreeSpace / totalFlexShrinkScaledFactors *
remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor; flexShrinkScaledFactor;
boundMainSize = YGNodeBoundAxis(currentRelativeChild, boundMainSize = YGNodeBoundAxis(
mainAxis, currentRelativeChild,
baseMainSize, mainAxis,
availableInnerMainDim, baseMainSize,
availableInnerWidth); availableInnerMainDim,
availableInnerWidth);
if (baseMainSize != boundMainSize) { if (baseMainSize != boundMainSize) {
// By excluding this item's size and flex factor from remaining, // By excluding this item's size and flex factor from remaining,
// this item's // this item's
@@ -2103,13 +2068,14 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// Is this child able to grow? // Is this child able to grow?
if (flexGrowFactor != 0) { if (flexGrowFactor != 0) {
baseMainSize = baseMainSize = childFlexBasis +
childFlexBasis + remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor; remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor;
boundMainSize = YGNodeBoundAxis(currentRelativeChild, boundMainSize = YGNodeBoundAxis(
mainAxis, currentRelativeChild,
baseMainSize, mainAxis,
availableInnerMainDim, baseMainSize,
availableInnerWidth); availableInnerMainDim,
availableInnerWidth);
if (baseMainSize != boundMainSize) { if (baseMainSize != boundMainSize) {
// By excluding this item's size and flex factor from remaining, // By excluding this item's size and flex factor from remaining,
@@ -2133,18 +2099,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// Second pass: resolve the sizes of the flexible items // Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0; deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild; for (auto currentRelativeChild : relativeChildren) {
while (currentRelativeChild != nullptr) { childFlexBasis = YGNodeBoundAxisWithinMinAndMax(
childFlexBasis = fminf( currentRelativeChild,
YGResolveValue( mainAxis,
currentRelativeChild->getStyle().maxDimensions[dim[mainAxis]], currentRelativeChild->getLayout().computedFlexBasis,
mainAxisParentSize), mainAxisParentSize);
fmaxf(
YGResolveValue(
currentRelativeChild->getStyle()
.minDimensions[dim[mainAxis]],
mainAxisParentSize),
currentRelativeChild->getLayout().computedFlexBasis));
float updatedMainSize = childFlexBasis; float updatedMainSize = childFlexBasis;
if (remainingFreeSpace < 0) { if (remainingFreeSpace < 0) {
@@ -2157,38 +2117,39 @@ static void YGNodelayoutImpl(const YGNodeRef node,
if (totalFlexShrinkScaledFactors == 0) { if (totalFlexShrinkScaledFactors == 0) {
childSize = childFlexBasis + flexShrinkScaledFactor; childSize = childFlexBasis + flexShrinkScaledFactor;
} else { } else {
childSize = childSize = childFlexBasis +
childFlexBasis + (remainingFreeSpace / totalFlexShrinkScaledFactors) *
(remainingFreeSpace / totalFlexShrinkScaledFactors) * flexShrinkScaledFactor; flexShrinkScaledFactor;
} }
updatedMainSize = YGNodeBoundAxis(currentRelativeChild, updatedMainSize = YGNodeBoundAxis(
mainAxis, currentRelativeChild,
childSize, mainAxis,
availableInnerMainDim, childSize,
availableInnerWidth); availableInnerMainDim,
availableInnerWidth);
} }
} else if (remainingFreeSpace > 0) { } else if (remainingFreeSpace > 0) {
flexGrowFactor = currentRelativeChild->resolveFlexGrow(); flexGrowFactor = currentRelativeChild->resolveFlexGrow();
// Is this child able to grow? // Is this child able to grow?
if (flexGrowFactor != 0) { if (flexGrowFactor != 0) {
updatedMainSize = updatedMainSize = YGNodeBoundAxis(
YGNodeBoundAxis(currentRelativeChild, currentRelativeChild,
mainAxis, mainAxis,
childFlexBasis + childFlexBasis +
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor, remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor,
availableInnerMainDim, availableInnerMainDim,
availableInnerWidth); availableInnerWidth);
} }
} }
deltaFreeSpace -= updatedMainSize - childFlexBasis; deltaFreeSpace -= updatedMainSize - childFlexBasis;
const float marginMain = const float marginMain = YGNodeMarginForAxis(
YGNodeMarginForAxis(currentRelativeChild, mainAxis, availableInnerWidth); currentRelativeChild, mainAxis, availableInnerWidth);
const float marginCross = const float marginCross = YGNodeMarginForAxis(
YGNodeMarginForAxis(currentRelativeChild, crossAxis, availableInnerWidth); currentRelativeChild, crossAxis, availableInnerWidth);
float childCrossSize; float childCrossSize;
float childMainSize = updatedMainSize + marginMain; float childMainSize = updatedMainSize + marginMain;
@@ -2216,12 +2177,14 @@ static void YGNodelayoutImpl(const YGNodeRef node,
YGUnitAuto) { YGUnitAuto) {
childCrossSize = availableInnerCrossDim; childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = YGMeasureModeExactly; childCrossMeasureMode = YGMeasureModeExactly;
} else if (!YGNodeIsStyleDimDefined(currentRelativeChild, } else if (!YGNodeIsStyleDimDefined(
crossAxis, currentRelativeChild,
availableInnerCrossDim)) { crossAxis,
availableInnerCrossDim)) {
childCrossSize = availableInnerCrossDim; childCrossSize = availableInnerCrossDim;
childCrossMeasureMode = childCrossMeasureMode = YGFloatIsUndefined(childCrossSize)
YGFloatIsUndefined(childCrossSize) ? YGMeasureModeUndefined : YGMeasureModeAtMost; ? YGMeasureModeUndefined
: YGMeasureModeAtMost;
} else { } else {
childCrossSize = childCrossSize =
YGResolveValue( YGResolveValue(
@@ -2263,7 +2226,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
YGUnitAuto; YGUnitAuto;
const float childWidth = isMainAxisRow ? childMainSize : childCrossSize; const float childWidth = isMainAxisRow ? childMainSize : childCrossSize;
const float childHeight = !isMainAxisRow ? childMainSize : childCrossSize; const float childHeight =
!isMainAxisRow ? childMainSize : childCrossSize;
const YGMeasureMode childWidthMeasureMode = const YGMeasureMode childWidthMeasureMode =
isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode; isMainAxisRow ? childMainMeasureMode : childCrossMeasureMode;
@@ -2272,17 +2236,18 @@ static void YGNodelayoutImpl(const YGNodeRef node,
// Recursively call the layout algorithm for this child with the updated // Recursively call the layout algorithm for this child with the updated
// main size. // main size.
YGLayoutNodeInternal(currentRelativeChild, YGLayoutNodeInternal(
childWidth, currentRelativeChild,
childHeight, childWidth,
direction, childHeight,
childWidthMeasureMode, direction,
childHeightMeasureMode, childWidthMeasureMode,
availableInnerWidth, childHeightMeasureMode,
availableInnerHeight, availableInnerWidth,
performLayout && !requiresStretchLayout, availableInnerHeight,
"flex", performLayout && !requiresStretchLayout,
config); "flex",
config);
node->setLayoutHadOverflow( node->setLayoutHadOverflow(
node->getLayout().hadOverflow | node->getLayout().hadOverflow |
currentRelativeChild->getLayout().hadOverflow); currentRelativeChild->getLayout().hadOverflow);
@@ -2866,16 +2831,18 @@ static void YGNodelayoutImpl(const YGNodeRef node,
if (performLayout) { if (performLayout) {
// STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN // STEP 10: SIZING AND POSITIONING ABSOLUTE CHILDREN
for (currentAbsoluteChild = firstAbsoluteChild; for (auto child : node->getChildren()) {
currentAbsoluteChild != nullptr; if (child->getStyle().positionType != YGPositionTypeAbsolute) {
currentAbsoluteChild = currentAbsoluteChild->getNextChild()) { continue;
YGNodeAbsoluteLayoutChild(node, }
currentAbsoluteChild, YGNodeAbsoluteLayoutChild(
availableInnerWidth, node,
isMainAxisRow ? measureModeMainDim : measureModeCrossDim, child,
availableInnerHeight, availableInnerWidth,
direction, isMainAxisRow ? measureModeMainDim : measureModeCrossDim,
config); availableInnerHeight,
direction,
config);
} }
// STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN // STEP 11: SETTING TRAILING POSITIONS FOR CHILDREN