Refactored step3 of flexbox algorithm
Summary: Previously flexbasis calculation was doing more than one task of accumulating absolutelypositioned child and flexbasis calculation. So this diff refactors the logic and moves out absolutely positioned child calculation to our step 1(which is calculating the variables which are required for rest of the algorithm). This diff also moves the flexbasis logic into separate function Reviewed By: emilsjolander Differential Revision: D6702749 fbshipit-source-id: 15dcc94ae30ac185e4d1c7d6e3744a40cfa47317
This commit is contained in:
committed by
Facebook Github Bot
parent
db3d20b7b7
commit
a9dd527748
183
yoga/Yoga.cpp
183
yoga/Yoga.cpp
@@ -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,28 +1923,36 @@ 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 +
|
// STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS
|
||||||
YGNodeMarginForAxis(child, mainAxis, availableInnerWidth);
|
|
||||||
;
|
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
|
||||||
@@ -1922,7 +1960,6 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
|||||||
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.
|
||||||
|
Reference in New Issue
Block a user