Permalink
Browse files

Add support for flex-grow, flex-shrink, and flex-basis

Reviewed By: lucasr

Differential Revision: D3714520

fbshipit-source-id: 80d3a9a1e2b6f74b863bbe22357f2c9865fa290e
  • Loading branch information...
1 parent 451cc2d commit 0ea41980096968977acde6f19f8c36b1afe382a5 @emilsjolander emilsjolander committed with Facebook Github Bot 4 Aug 15, 2016
Showing with 68 additions and 63 deletions.
  1. +4 −2 React/CSSLayout/CSSLayout-internal.h
  2. +61 −61 React/CSSLayout/CSSLayout.c
  3. +3 −0 React/CSSLayout/CSSLayout.h
@@ -33,7 +33,7 @@ typedef struct CSSLayout {
float dimensions[2];
CSSDirection direction;
- float flexBasis;
+ float computedFlexBasis;
// Instead of recomputing the entire layout every single time, we
// cache some information to break early when nothing changed
@@ -57,7 +57,9 @@ typedef struct CSSStyle {
CSSPositionType positionType;
CSSWrapType flexWrap;
CSSOverflow overflow;
- float flex;
+ float flexGrow;
+ float flexShrink;
+ float flexBasis;
float margin[6];
float position[6];
/**
@@ -23,8 +23,6 @@ __forceinline const float fmaxf(const float a, const float b) {
#endif
#endif
-#define POSITIVE_FLEX_IS_AUTO 0
-
CSSNodeRef CSSNodeNew() {
CSSNodeRef node = calloc(1, sizeof(CSSNode));
CSS_ASSERT(node, "Could not allocate memory for node");
@@ -44,6 +42,10 @@ void CSSNodeInit(CSSNodeRef node) {
node->hasNewLayout = true;
node->isDirty = false;
+ node->style.flexGrow = 0;
+ node->style.flexShrink = 0;
+ node->style.flexBasis = CSSUndefined;
+
node->style.alignItems = CSSAlignStretch;
node->style.alignContent = CSSAlignFlexStart;
@@ -130,6 +132,32 @@ bool CSSNodeIsDirty(CSSNodeRef node) {
return node->isDirty;
}
+void CSSNodeStyleSetFlex(CSSNodeRef node, float flex) {
+ if (CSSValueIsUndefined(flex) || flex == 0) {
+ CSSNodeStyleSetFlexGrow(node, 0);
+ CSSNodeStyleSetFlexShrink(node, 0);
+ CSSNodeStyleSetFlexBasis(node, CSSUndefined);
+ } else if (flex > 0) {
+ CSSNodeStyleSetFlexGrow(node, flex);
+ CSSNodeStyleSetFlexShrink(node, 0);
+ CSSNodeStyleSetFlexBasis(node, 0);
+ } else {
+ CSSNodeStyleSetFlexGrow(node, 0);
+ CSSNodeStyleSetFlexShrink(node, -flex);
+ CSSNodeStyleSetFlexBasis(node, CSSUndefined);
+ }
+}
+
+float CSSNodeStyleGetFlex(CSSNodeRef node) {
+ if (node->style.flexGrow > 0) {
+ return node->style.flexGrow;
+ } else if (node->style.flexShrink > 0) {
+ return -node->style.flexShrink;
+ }
+
+ return 0;
+}
+
#define CSS_NODE_PROPERTY_IMPL(type, name, paramName, instanceName) \
void CSSNodeSet##name(CSSNodeRef node, type paramName) { \
node->instanceName = paramName; \
@@ -171,7 +199,9 @@ CSS_NODE_STYLE_PROPERTY_IMPL(CSSAlign, AlignSelf, alignSelf, alignSelf);
CSS_NODE_STYLE_PROPERTY_IMPL(CSSPositionType, PositionType, positionType, positionType);
CSS_NODE_STYLE_PROPERTY_IMPL(CSSWrapType, FlexWrap, flexWrap, flexWrap);
CSS_NODE_STYLE_PROPERTY_IMPL(CSSOverflow, Overflow, overflow, overflow);
-CSS_NODE_STYLE_PROPERTY_IMPL(float, Flex, flex, flex);
+CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexGrow, flexGrow, flexGrow);
+CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexShrink, flexShrink, flexShrink);
+CSS_NODE_STYLE_PROPERTY_IMPL(float, FlexBasis, flexBasis, flexBasis);
CSS_NODE_STYLE_PROPERTY_IMPL(float, PositionLeft, positionLeft, position[CSSPositionLeft]);
CSS_NODE_STYLE_PROPERTY_IMPL(float, PositionTop, positionTop, position[CSSPositionTop]);
@@ -324,7 +354,9 @@ static void print_css_node_rec(CSSNode *node, CSSPrintOptions options, uint32_t
printf("alignSelf: 'stretch', ");
}
- print_number_nan("flex", node->style.flex);
+ print_number_nan("flexGrow", node->style.flexGrow);
+ print_number_nan("flexShrink", node->style.flexShrink);
+ print_number_nan("flexBasis", node->style.flexBasis);
if (node->style.overflow == CSSOverflowHidden) {
printf("overflow: 'hidden', ");
@@ -432,40 +464,6 @@ static bool isColumnDirection(CSSFlexDirection flexDirection) {
return flexDirection == CSSFlexDirectionColumn || flexDirection == CSSFlexDirectionColumnReverse;
}
-static bool isFlexBasisAuto(CSSNode *node) {
-#if POSITIVE_FLEX_IS_AUTO
- // All flex values are auto.
- (void) node;
- return true;
-#else
- // A flex value > 0 implies a basis of zero.
- return node->style.flex <= 0;
-#endif
-}
-
-static float getFlexGrowFactor(CSSNode *node) {
- // Flex grow is implied by positive values for flex.
- if (node->style.flex > 0) {
- return node->style.flex;
- }
- return 0;
-}
-
-static float getFlexShrinkFactor(CSSNode *node) {
-#if POSITIVE_FLEX_IS_AUTO
- // A flex shrink factor of 1 is implied by non-zero values for flex.
- if (node->style.flex != 0) {
- return 1;
- }
-#else
- // A flex shrink factor of 1 is implied by negative values for flex.
- if (node->style.flex < 0) {
- return 1;
- }
-#endif
- return 0;
-}
-
static float getLeadingMargin(CSSNode *node, CSSFlexDirection axis) {
if (isRowDirection(axis) && !CSSValueIsUndefined(node->style.margin[CSSPositionStart])) {
return node->style.margin[CSSPositionStart];
@@ -592,12 +590,9 @@ static CSSFlexDirection getCrossFlexDirection(CSSFlexDirection flexDirection,
}
}
-static float getFlex(CSSNode *node) {
- return node->style.flex;
-}
-
static bool isFlex(CSSNode *node) {
- return (node->style.positionType == CSSPositionTypeRelative && getFlex(node) != 0);
+ return (node->style.positionType == CSSPositionTypeRelative &&
+ (node->style.flexGrow != 0 || node->style.flexShrink != 0));
}
static bool isFlexWrap(CSSNode *node) {
@@ -1022,15 +1017,18 @@ static void layoutNodeImpl(CSSNode *node,
} else {
if (isMainAxisRow && isStyleDimDefined(child, CSSFlexDirectionRow)) {
// The width is definite, so use that as the flex basis.
- child->layout.flexBasis = fmaxf(child->style.dimensions[CSSDimensionWidth],
- getPaddingAndBorderAxis(child, CSSFlexDirectionRow));
+ 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.flexBasis = fmaxf(child->style.dimensions[CSSDimensionHeight],
- getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
- } else if (!isFlexBasisAuto(child) && !CSSValueIsUndefined(availableInnerMainDim)) {
- // If the basis isn't 'auto', it is assumed to be zero.
- child->layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));
+ child->layout.computedFlexBasis =
+ fmaxf(child->style.dimensions[CSSDimensionHeight],
+ getPaddingAndBorderAxis(child, CSSFlexDirectionColumn));
+ } else if (!CSSValueIsUndefined(child->style.flexBasis) &&
+ !CSSValueIsUndefined(availableInnerMainDim)) {
+ 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).
@@ -1098,7 +1096,7 @@ static void layoutNodeImpl(CSSNode *node,
false,
"measure");
- child->layout.flexBasis =
+ child->layout.computedFlexBasis =
fmaxf(isMainAxisRow ? child->layout.measuredDimensions[CSSDimensionWidth]
: child->layout.measuredDimensions[CSSDimensionHeight],
getPaddingAndBorderAxis(child, mainAxis));
@@ -1149,7 +1147,7 @@ static void layoutNodeImpl(CSSNode *node,
child->lineIndex = lineCount;
if (child->style.positionType != CSSPositionTypeAbsolute) {
- float outerFlexBasis = child->layout.flexBasis + getMarginAxis(child, mainAxis);
+ float outerFlexBasis = child->layout.computedFlexBasis + getMarginAxis(child, mainAxis);
// If this is a multi-line flow and this item pushes us over the
// available size, we've
@@ -1164,12 +1162,13 @@ static void layoutNodeImpl(CSSNode *node,
itemsOnLine++;
if (isFlex(child)) {
- totalFlexGrowFactors += getFlexGrowFactor(child);
+ totalFlexGrowFactors += child->style.flexGrow;
// Unlike the grow factor, the shrink factor is scaled relative to the
// child
// dimension.
- totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child->layout.flexBasis;
+ totalFlexShrinkScaledFactors +=
+ -child->style.flexShrink * child->layout.computedFlexBasis;
}
// Store a private linked list of children that need to be layed out.
@@ -1252,10 +1251,10 @@ static void layoutNodeImpl(CSSNode *node,
float deltaFlexGrowFactors = 0;
currentRelativeChild = firstRelativeChild;
while (currentRelativeChild != NULL) {
- childFlexBasis = currentRelativeChild->layout.flexBasis;
+ childFlexBasis = currentRelativeChild->layout.computedFlexBasis;
if (remainingFreeSpace < 0) {
- flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
+ flexShrinkScaledFactor = -currentRelativeChild->style.flexShrink * childFlexBasis;
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
@@ -1275,7 +1274,7 @@ static void layoutNodeImpl(CSSNode *node,
}
}
} else if (remainingFreeSpace > 0) {
- flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
+ flexGrowFactor = currentRelativeChild->style.flexGrow;
// Is this child able to grow?
if (flexGrowFactor != 0) {
@@ -1306,11 +1305,11 @@ static void layoutNodeImpl(CSSNode *node,
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
while (currentRelativeChild != NULL) {
- childFlexBasis = currentRelativeChild->layout.flexBasis;
+ childFlexBasis = currentRelativeChild->layout.computedFlexBasis;
float updatedMainSize = childFlexBasis;
if (remainingFreeSpace < 0) {
- flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
+ flexShrinkScaledFactor = -currentRelativeChild->style.flexShrink * childFlexBasis;
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
@@ -1321,7 +1320,7 @@ static void layoutNodeImpl(CSSNode *node,
flexShrinkScaledFactor);
}
} else if (remainingFreeSpace > 0) {
- flexGrowFactor = getFlexGrowFactor(currentRelativeChild);
+ flexGrowFactor = currentRelativeChild->style.flexGrow;
// Is this child able to grow?
if (flexGrowFactor != 0) {
@@ -1463,7 +1462,8 @@ static void layoutNodeImpl(CSSNode *node,
// If we skipped the flex step, then we can't rely on the
// measuredDims because
// they weren't computed. This means we can't call getDimWithMargin.
- mainDim += betweenMainDim + getMarginAxis(child, mainAxis) + child->layout.flexBasis;
+ mainDim +=
+ betweenMainDim + getMarginAxis(child, mainAxis) + child->layout.computedFlexBasis;
crossDim = availableInnerCrossDim;
} else {
// The main dimension is the sum of all the elements dimension plus
@@ -174,6 +174,9 @@ CSS_NODE_STYLE_PROPERTY(CSSPositionType, PositionType, positionType);
CSS_NODE_STYLE_PROPERTY(CSSWrapType, FlexWrap, flexWrap);
CSS_NODE_STYLE_PROPERTY(CSSOverflow, Overflow, overflow);
CSS_NODE_STYLE_PROPERTY(float, Flex, flex);
+CSS_NODE_STYLE_PROPERTY(float, FlexGrow, flexGrow);
+CSS_NODE_STYLE_PROPERTY(float, FlexShrink, flexShrink);
+CSS_NODE_STYLE_PROPERTY(float, FlexBasis, flexBasis);
CSS_NODE_STYLE_PROPERTY(float, PositionLeft, positionLeft);
CSS_NODE_STYLE_PROPERTY(float, PositionTop, positionTop);

0 comments on commit 0ea4198

Please sign in to comment.