Move flex basis calculation out into seperate function

Reviewed By: gkassabli

Differential Revision: D4028328

fbshipit-source-id: 6d5f3bf1321077675eaa65408a70c9dc92a675be
This commit is contained in:
Emil Sjolander 2016-10-17 05:28:50 -07:00 committed by Facebook Github Bot
parent d376155e2c
commit 72cd12ed13

View File

@ -826,6 +826,111 @@ static void setPosition(const CSSNodeRef node, const CSSDirection direction) {
getTrailingMargin(node, crossAxis) + getRelativePosition(node, crossAxis);
}
static void computeChildFlexBasis(
const CSSNodeRef node,
const CSSNodeRef child,
const float width,
const CSSMeasureMode widthMode,
const float height,
const CSSMeasureMode heightMode,
const CSSDirection direction) {
const CSSFlexDirection mainAxis = resolveAxis(node->style.flexDirection, direction);
const bool isMainAxisRow = isRowDirection(mainAxis);
float childWidth;
float childHeight;
CSSMeasureMode childWidthMeasureMode;
CSSMeasureMode childHeightMeasureMode;
if (isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow)) {
// The width is definite, so use that as the flex basis.
child->layout.computedFlexBasis =
fmaxf(child->style.dimensions[CSSDimensionWidth],
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionColumn)) {
// The height is definite, so use that as the flex basis.
child->layout.computedFlexBasis =
fmaxf(child->style.dimensions[CSSDimensionHeight],
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
} else if (!CSSValueIsUndefined(child->style.flexBasis) &&
!CSSValueIsUndefined(isMainAxisRow ? width : height)) {
if (CSSValueIsUndefined(child->layout.computedFlexBasis)) {
child->layout.computedFlexBasis =
fmaxf(child->style.flexBasis, getPaddingAndBorderAxis(child, mainAxis));
}
} else {
// Compute the flex basis and hypothetical main size (i.e. the clamped
// flex basis).
childWidth = CSSUndefined;
childHeight = CSSUndefined;
childWidthMeasureMode = CSSMeasureModeUndefined;
childHeightMeasureMode = CSSMeasureModeUndefined;
if (isStyleDimDefined(child, CSSFlexDirectionRow)) {
childWidth = child->style.dimensions[CSSDimensionWidth] +
getMarginAxis(child, CSSFlexDirectionRow);
childWidthMeasureMode = CSSMeasureModeExactly;
}
if (isStyleDimDefined(child, CSSFlexDirectionColumn)) {
childHeight = child->style.dimensions[CSSDimensionHeight] +
getMarginAxis(child, CSSFlexDirectionColumn);
childHeightMeasureMode = CSSMeasureModeExactly;
}
// The W3C spec doesn't say anything about the 'overflow' property,
// but all major browsers appear to implement the following logic.
if ((!isMainAxisRow && node->style.overflow == CSSOverflowScroll) ||
node->style.overflow != CSSOverflowScroll) {
if (CSSValueIsUndefined(childWidth) && !CSSValueIsUndefined(width)) {
childWidth = width;
childWidthMeasureMode = CSSMeasureModeAtMost;
}
}
if ((isMainAxisRow && node->style.overflow == CSSOverflowScroll) ||
node->style.overflow != CSSOverflowScroll) {
if (CSSValueIsUndefined(childHeight) && !CSSValueIsUndefined(height)) {
childHeight = height;
childHeightMeasureMode = CSSMeasureModeAtMost;
}
}
// If child has no defined size in the cross axis and is set to stretch,
// set the cross
// axis to be measured exactly with the available inner width
if (!isMainAxisRow && !CSSValueIsUndefined(width) &&
!isStyleDimDefined(child, CSSFlexDirectionRow) &&
widthMode == CSSMeasureModeExactly &&
getAlignItem(node, child) == CSSAlignStretch) {
childWidth = width;
childWidthMeasureMode = CSSMeasureModeExactly;
}
if (isMainAxisRow && !CSSValueIsUndefined(height) &&
!isStyleDimDefined(child, CSSFlexDirectionColumn) &&
heightMode == CSSMeasureModeExactly &&
getAlignItem(node, child) == CSSAlignStretch) {
childHeight = height;
childHeightMeasureMode = CSSMeasureModeExactly;
}
// Measure the child
layoutNodeInternal(child,
childWidth,
childHeight,
direction,
childWidthMeasureMode,
childHeightMeasureMode,
false,
"measure");
child->layout.computedFlexBasis =
fmaxf(isMainAxisRow ? child->layout.measuredDimensions[CSSDimensionWidth]
: child->layout.measuredDimensions[CSSDimensionHeight],
getPaddingAndBorderAxis(child, mainAxis));
}
}
//
// This is the main routine that implements a subset of the flexbox layout
// algorithm
@ -1101,10 +1206,6 @@ static void layoutNodeImpl(const CSSNodeRef node,
const float availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;
// STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM
float childWidth;
float childHeight;
CSSMeasureMode childWidthMeasureMode;
CSSMeasureMode childHeightMeasureMode;
for (uint32_t i = 0; i < childCount; i++) {
const CSSNodeRef child = CSSNodeListGet(node->children, i);
@ -1128,92 +1229,14 @@ static void layoutNodeImpl(const CSSNodeRef node,
currentAbsoluteChild = child;
child->nextChild = NULL;
} else {
if (isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow)) {
// The width is definite, so use that as the flex basis.
child->layout.computedFlexBasis =
fmaxf(child->style.dimensions[CSSDimensionWidth],
getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionColumn)) {
// The height is definite, so use that as the flex basis.
child->layout.computedFlexBasis =
fmaxf(child->style.dimensions[CSSDimensionHeight],
getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
} else if (!CSSValueIsUndefined(child->style.flexBasis) &&
!CSSValueIsUndefined(availableInnerMainDim)) {
if (CSSValueIsUndefined(child->layout.computedFlexBasis)) {
child->layout.computedFlexBasis =
fmaxf(child->style.flexBasis, getPaddingAndBorderAxis(child, mainAxis));
}
} else {
// Compute the flex basis and hypothetical main size (i.e. the clamped
// flex basis).
childWidth = CSSUndefined;
childHeight = CSSUndefined;
childWidthMeasureMode = CSSMeasureModeUndefined;
childHeightMeasureMode = CSSMeasureModeUndefined;
if (isStyleDimDefined(child, CSSFlexDirectionRow)) {
childWidth = child->style.dimensions[CSSDimensionWidth] +
getMarginAxis(child, CSSFlexDirectionRow);
childWidthMeasureMode = CSSMeasureModeExactly;
}
if (isStyleDimDefined(child, CSSFlexDirectionColumn)) {
childHeight = child->style.dimensions[CSSDimensionHeight] +
getMarginAxis(child, CSSFlexDirectionColumn);
childHeightMeasureMode = CSSMeasureModeExactly;
}
// The W3C spec doesn't say anything about the 'overflow' property,
// but all major browsers appear to implement the following logic.
if ((!isMainAxisRow && node->style.overflow == CSSOverflowScroll) ||
node->style.overflow != CSSOverflowScroll) {
if (CSSValueIsUndefined(childWidth) && !CSSValueIsUndefined(availableInnerWidth)) {
childWidth = availableInnerWidth;
childWidthMeasureMode = CSSMeasureModeAtMost;
}
}
if ((isMainAxisRow && node->style.overflow == CSSOverflowScroll) ||
node->style.overflow != CSSOverflowScroll) {
if (CSSValueIsUndefined(childHeight) && !CSSValueIsUndefined(availableInnerHeight)) {
childHeight = availableInnerHeight;
childHeightMeasureMode = CSSMeasureModeAtMost;
}
}
// If child has no defined size in the cross axis and is set to stretch,
// set the cross
// axis to be measured exactly with the available inner width
if (!isMainAxisRow && !CSSValueIsUndefined(availableInnerWidth) &&
!isStyleDimDefined(child, CSSFlexDirectionRow) &&
widthMeasureMode == CSSMeasureModeExactly &&
getAlignItem(node, child) == CSSAlignStretch) {
childWidth = availableInnerWidth;
childWidthMeasureMode = CSSMeasureModeExactly;
}
if (isMainAxisRow && !CSSValueIsUndefined(availableInnerHeight) &&
!isStyleDimDefined(child, CSSFlexDirectionColumn) &&
heightMeasureMode == CSSMeasureModeExactly &&
getAlignItem(node, child) == CSSAlignStretch) {
childHeight = availableInnerHeight;
childHeightMeasureMode = CSSMeasureModeExactly;
}
// Measure the child
layoutNodeInternal(child,
childWidth,
childHeight,
direction,
childWidthMeasureMode,
childHeightMeasureMode,
false,
"measure");
child->layout.computedFlexBasis =
fmaxf(isMainAxisRow ? child->layout.measuredDimensions[CSSDimensionWidth]
: child->layout.measuredDimensions[CSSDimensionHeight],
getPaddingAndBorderAxis(child, mainAxis));
}
computeChildFlexBasis(
node,
child,
availableInnerWidth,
widthMeasureMode,
availableInnerHeight,
heightMeasureMode,
direction);
}
}
@ -1443,6 +1466,11 @@ static void layoutNodeImpl(const CSSNodeRef node,
deltaFreeSpace -= updatedMainSize - childFlexBasis;
float childWidth;
float childHeight;
CSSMeasureMode childWidthMeasureMode;
CSSMeasureMode childHeightMeasureMode;
if (isMainAxisRow) {
childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSSFlexDirectionRow);
childWidthMeasureMode = CSSMeasureModeExactly;
@ -1654,6 +1682,11 @@ static void layoutNodeImpl(const CSSNodeRef node,
(isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionColumn)) ||
(!isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow));
float childWidth;
float childHeight;
CSSMeasureMode childWidthMeasureMode;
CSSMeasureMode childHeightMeasureMode;
if (isMainAxisRow) {
childHeight = crossDim;
childWidth = child->layout.measuredDimensions[CSSDimensionWidth] +
@ -1749,26 +1782,30 @@ static void layoutNodeImpl(const CSSNodeRef node,
if (child->style.positionType == CSSPositionTypeRelative) {
switch (getAlignItem(node, child)) {
case CSSAlignFlexStart:
case CSSAlignFlexStart: {
child->layout.position[pos[crossAxis]] =
currentLead + getLeadingMargin(child, crossAxis);
break;
case CSSAlignFlexEnd:
}
case CSSAlignFlexEnd: {
child->layout.position[pos[crossAxis]] =
currentLead + lineHeight - getTrailingMargin(child, crossAxis) -
child->layout.measuredDimensions[dim[crossAxis]];
break;
case CSSAlignCenter:
childHeight = child->layout.measuredDimensions[dim[crossAxis]];
}
case CSSAlignCenter: {
float childHeight = child->layout.measuredDimensions[dim[crossAxis]];
child->layout.position[pos[crossAxis]] =
currentLead + (lineHeight - childHeight) / 2;
break;
case CSSAlignStretch:
}
case CSSAlignStretch: {
child->layout.position[pos[crossAxis]] =
currentLead + getLeadingMargin(child, crossAxis);
// TODO(prenaux): Correctly set the height of items with indefinite
// (auto) crossAxis dimension.
break;
}
default:
break;
}
@ -1819,8 +1856,10 @@ static void layoutNodeImpl(const CSSNodeRef node,
// Now that we know the bounds of the container, perform layout again on the
// absolutely-positioned children.
if (performLayout) {
childWidth = CSSUndefined;
childHeight = CSSUndefined;
float childWidth = CSSUndefined;
float childHeight = CSSUndefined;
CSSMeasureMode childWidthMeasureMode = CSSMeasureModeUndefined;
CSSMeasureMode childHeightMeasureMode = CSSMeasureModeUndefined;
if (isStyleDimDefined(currentAbsoluteChild, CSSFlexDirectionRow)) {
childWidth = currentAbsoluteChild->style.dimensions[CSSDimensionWidth] +