Refactored step3 of flexbox algorithm
Reviewed By: emilsjolander Differential Revision: D6702749 fbshipit-source-id: 15dcc94ae30ac185e4d1c7d6e3744a40cfa47317
This commit is contained in:
parent
ac1c8c265e
commit
fcf2c7cf61
|
@ -1590,6 +1590,87 @@ static float YGNodeCalculateAvailableInnerDim(
|
||||||
return availableInnerDim;
|
return availableInnerDim;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void YGNodeComputeFlexBasisForChildren(
|
||||||
|
const YGNodeRef node,
|
||||||
|
const float availableInnerWidth,
|
||||||
|
const float availableInnerHeight,
|
||||||
|
YGMeasureMode widthMeasureMode,
|
||||||
|
YGMeasureMode heightMeasureMode,
|
||||||
|
YGDirection direction,
|
||||||
|
YGFlexDirection mainAxis,
|
||||||
|
const YGConfigRef config,
|
||||||
|
bool performLayout,
|
||||||
|
float& totalOuterFlexBasis) {
|
||||||
|
YGNodeRef singleFlexChild = nullptr;
|
||||||
|
YGVector children = node->getChildren();
|
||||||
|
YGMeasureMode measureModeMainDim =
|
||||||
|
YGFlexDirectionIsRow(mainAxis) ? widthMeasureMode : heightMeasureMode;
|
||||||
|
// If there is only one child with flexGrow + flexShrink it means we can set
|
||||||
|
// the computedFlexBasis to 0 instead of measuring and shrinking / flexing the
|
||||||
|
// child to exactly match the remaining space
|
||||||
|
if (measureModeMainDim == YGMeasureModeExactly) {
|
||||||
|
for (auto child : children) {
|
||||||
|
if (singleFlexChild != nullptr) {
|
||||||
|
if (YGNodeIsFlex(child)) {
|
||||||
|
// There is already a flexible child, abort
|
||||||
|
singleFlexChild = nullptr;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
} else if (
|
||||||
|
child->resolveFlexGrow() > 0.0f &&
|
||||||
|
child->resolveFlexShrink() > 0.0f) {
|
||||||
|
singleFlexChild = child;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (auto child : children) {
|
||||||
|
child->resolveDimension();
|
||||||
|
if (child->getStyle().display == YGDisplayNone) {
|
||||||
|
YGZeroOutLayoutRecursivly(child);
|
||||||
|
child->setHasNewLayout(true);
|
||||||
|
child->setDirty(false);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (child->getStyle().positionType == YGPositionTypeAbsolute) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (performLayout) {
|
||||||
|
// Set the initial position (relative to the parent).
|
||||||
|
const YGDirection childDirection =
|
||||||
|
YGNodeResolveDirection(child, direction);
|
||||||
|
const float mainDim = YGFlexDirectionIsRow(mainAxis)
|
||||||
|
? availableInnerWidth
|
||||||
|
: availableInnerHeight;
|
||||||
|
const float crossDim = YGFlexDirectionIsRow(mainAxis)
|
||||||
|
? availableInnerHeight
|
||||||
|
: availableInnerWidth;
|
||||||
|
child->setPosition(
|
||||||
|
childDirection, mainDim, crossDim, availableInnerWidth);
|
||||||
|
}
|
||||||
|
if (child == singleFlexChild) {
|
||||||
|
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);
|
||||||
|
child->setLayoutComputedFlexBasis(0);
|
||||||
|
} else {
|
||||||
|
YGNodeComputeFlexBasisForChild(
|
||||||
|
node,
|
||||||
|
child,
|
||||||
|
availableInnerWidth,
|
||||||
|
widthMeasureMode,
|
||||||
|
availableInnerHeight,
|
||||||
|
availableInnerWidth,
|
||||||
|
availableInnerHeight,
|
||||||
|
heightMeasureMode,
|
||||||
|
direction,
|
||||||
|
config);
|
||||||
|
}
|
||||||
|
|
||||||
|
totalOuterFlexBasis += child->getLayout().computedFlexBasis +
|
||||||
|
YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
|
||||||
|
;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
// This is the main routine that implements a subset of the flexbox layout
|
// This is the main routine that implements a subset of the flexbox layout
|
||||||
// algorithm
|
// algorithm
|
||||||
|
@ -1827,59 +1908,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||||
const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight;
|
const float minInnerMainDim = isMainAxisRow ? minInnerWidth : minInnerHeight;
|
||||||
const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight;
|
const float maxInnerMainDim = isMainAxisRow ? maxInnerWidth : maxInnerHeight;
|
||||||
|
|
||||||
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
// Make a private linkedlist of absolutely positioned child
|
||||||
|
for (auto child : node->getChildren()) {
|
||||||
float availableInnerWidth = YGNodeCalculateAvailableInnerDim(
|
|
||||||
node, YGFlexDirectionRow, availableWidth, parentWidth);
|
|
||||||
float availableInnerHeight = YGNodeCalculateAvailableInnerDim(
|
|
||||||
node, YGFlexDirectionColumn, availableHeight, parentHeight);
|
|
||||||
|
|
||||||
float availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
|
||||||
const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
|
||||||
|
|
||||||
// If there is only one child with flexGrow + flexShrink it means we can set the
|
|
||||||
// computedFlexBasis to 0 instead of measuring and shrinking / flexing the child to exactly
|
|
||||||
// match the remaining space
|
|
||||||
YGNodeRef singleFlexChild = nullptr;
|
|
||||||
if (measureModeMainDim == YGMeasureModeExactly) {
|
|
||||||
for (uint32_t i = 0; i < childCount; i++) {
|
|
||||||
const YGNodeRef child = YGNodeGetChild(node, i);
|
|
||||||
if (singleFlexChild) {
|
|
||||||
if (YGNodeIsFlex(child)) {
|
|
||||||
// There is already a flexible child, abort.
|
|
||||||
singleFlexChild = nullptr;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
} else if (
|
|
||||||
child->resolveFlexGrow() > 0.0f &&
|
|
||||||
child->resolveFlexShrink() > 0.0f) {
|
|
||||||
singleFlexChild = child;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
float totalOuterFlexBasis = 0;
|
|
||||||
|
|
||||||
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
|
||||||
for (uint32_t i = 0; i < childCount; i++) {
|
|
||||||
const YGNodeRef child = node->getChild(i);
|
|
||||||
if (child->getStyle().display == YGDisplayNone) {
|
|
||||||
YGZeroOutLayoutRecursivly(child);
|
|
||||||
child->setHasNewLayout(true);
|
|
||||||
child->setDirty(false);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
child->resolveDimension();
|
|
||||||
if (performLayout) {
|
|
||||||
// Set the initial position (relative to the parent).
|
|
||||||
const YGDirection childDirection = YGNodeResolveDirection(child, direction);
|
|
||||||
child->setPosition(
|
|
||||||
childDirection,
|
|
||||||
availableInnerMainDim,
|
|
||||||
availableInnerCrossDim,
|
|
||||||
availableInnerWidth);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Absolute-positioned children don't participate in flex layout. Add them
|
// Absolute-positioned children don't participate in flex layout. Add them
|
||||||
// to a list that we can process later.
|
// to a list that we can process later.
|
||||||
if (child->getStyle().positionType == YGPositionTypeAbsolute) {
|
if (child->getStyle().positionType == YGPositionTypeAbsolute) {
|
||||||
|
@ -1893,36 +1923,43 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||||
}
|
}
|
||||||
currentAbsoluteChild = child;
|
currentAbsoluteChild = child;
|
||||||
child->setNextChild(nullptr);
|
child->setNextChild(nullptr);
|
||||||
} else {
|
|
||||||
if (child == singleFlexChild) {
|
|
||||||
child->setLayoutComputedFlexBasisGeneration(gCurrentGenerationCount);
|
|
||||||
child->setLayoutComputedFlexBasis(0);
|
|
||||||
} else {
|
|
||||||
YGNodeComputeFlexBasisForChild(node,
|
|
||||||
child,
|
|
||||||
availableInnerWidth,
|
|
||||||
widthMeasureMode,
|
|
||||||
availableInnerHeight,
|
|
||||||
availableInnerWidth,
|
|
||||||
availableInnerHeight,
|
|
||||||
heightMeasureMode,
|
|
||||||
direction,
|
|
||||||
config);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
totalOuterFlexBasis += child->getLayout().computedFlexBasis +
|
|
||||||
YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
|
|
||||||
;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
||||||
|
|
||||||
|
float availableInnerWidth = YGNodeCalculateAvailableInnerDim(
|
||||||
|
node, YGFlexDirectionRow, availableWidth, parentWidth);
|
||||||
|
float availableInnerHeight = YGNodeCalculateAvailableInnerDim(
|
||||||
|
node, YGFlexDirectionColumn, availableHeight, parentHeight);
|
||||||
|
|
||||||
|
float availableInnerMainDim =
|
||||||
|
isMainAxisRow ? availableInnerWidth : availableInnerHeight;
|
||||||
|
const float availableInnerCrossDim =
|
||||||
|
isMainAxisRow ? availableInnerHeight : availableInnerWidth;
|
||||||
|
|
||||||
|
float totalOuterFlexBasis = 0;
|
||||||
|
|
||||||
|
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
|
||||||
|
|
||||||
|
YGNodeComputeFlexBasisForChildren(
|
||||||
|
node,
|
||||||
|
availableInnerWidth,
|
||||||
|
availableInnerHeight,
|
||||||
|
widthMeasureMode,
|
||||||
|
heightMeasureMode,
|
||||||
|
direction,
|
||||||
|
mainAxis,
|
||||||
|
config,
|
||||||
|
performLayout,
|
||||||
|
totalOuterFlexBasis);
|
||||||
|
|
||||||
const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined
|
const bool flexBasisOverflows = measureModeMainDim == YGMeasureModeUndefined
|
||||||
? false
|
? false
|
||||||
: totalOuterFlexBasis > availableInnerMainDim;
|
: totalOuterFlexBasis > availableInnerMainDim;
|
||||||
if (isNodeFlexWrap && flexBasisOverflows && measureModeMainDim == YGMeasureModeAtMost) {
|
if (isNodeFlexWrap && flexBasisOverflows && measureModeMainDim == YGMeasureModeAtMost) {
|
||||||
measureModeMainDim = YGMeasureModeExactly;
|
measureModeMainDim = YGMeasureModeExactly;
|
||||||
}
|
}
|
||||||
|
|
||||||
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
|
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
|
||||||
|
|
||||||
// Indexes of children that represent the first and last items in the line.
|
// Indexes of children that represent the first and last items in the line.
|
||||||
|
|
Loading…
Reference in New Issue