diff --git a/Gruntfile.js b/Gruntfile.js
index 26535e9f..69432cb9 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -150,7 +150,7 @@ module.exports = function(grunt) {
command: 'xbuild /verbosity:m /nologo src/csharp/Facebook.CSSLayout.sln /p:Configuration=Release /t:"Facebook_CSSLayout:Rebuild;Facebook_CSSLayout_Tests:Rebuild"'
},
csharpTestExecute: {
- command: 'nunit-console -nologo src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll'
+ command: 'nunit-console -nologo src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll'
}
},
diff --git a/README.md b/README.md
index 607295e8..6c0dedf6 100644
--- a/README.md
+++ b/README.md
@@ -39,7 +39,7 @@ var nodeTree = {
computeLayout(nodeTree);
// the layout information is written back to the node tree, with
-// each node now having a layout property:
+// each node now having a layout property:
// JSON.stringify(nodeTree, null, 2);
{
@@ -104,7 +104,7 @@ overflow | 'visible', 'hidden'
n (where n > 0) | n 0 0
0 | 0 0 auto
-1 | 0 1 auto
-
+
- `inherit` value is not implemented because it's a way to disambiguate between multiple colliding rules. This should be done in a pre-processing step, not in the actual layout algorithm.
diff --git a/dist/css-layout.h b/dist/css-layout.h
index 15aec895..ed34a69a 100644
--- a/dist/css-layout.h
+++ b/dist/css-layout.h
@@ -259,7 +259,7 @@ void init_css_node(css_node_t* node) {
node->style.direction = CSS_DIRECTION_INHERIT;
node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-
+
node->style.overflow = CSS_OVERFLOW_VISIBLE;
// Some of the fields default to undefined and not 0
@@ -291,7 +291,7 @@ void init_css_node(css_node_t* node) {
node->layout.last_parent_direction = (css_direction_t)-1;
node->layout.should_update = true;
node->layout.next_cached_measurements_index = 0;
-
+
node->layout.measured_dimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->layout.measured_dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
node->layout.cached_layout.width_measure_mode = (css_measure_mode_t)-1;
@@ -771,7 +771,7 @@ static float getRelativePosition(css_node_t* node, css_flex_direction_t axis) {
static void setPosition(css_node_t* node, css_direction_t direction) {
css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node->layout.position[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node->layout.position[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +
@@ -818,8 +818,8 @@ static void setPosition(css_node_t* node, css_direction_t direction) {
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
-// main size. For text blocks, for example, this is the width of the widest word.
-// Calculating the minimum width is expensive, so we forego it and assume a default
+// main size. For text blocks, for example, this is the width of the widest word.
+// Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -853,7 +853,7 @@ static void setPosition(css_node_t* node, css_direction_t direction) {
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
-//
+//
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
@@ -863,7 +863,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
assert(isUndefined(availableWidth) ? widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED
assert(isUndefined(availableHeight) ? heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED
-
+
float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
@@ -877,7 +877,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isMeasureDefined(node)) {
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -909,7 +909,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
measureDim.dimensions[CSS_HEIGHT] + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -939,7 +939,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {
node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -951,7 +951,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) {
node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -975,7 +975,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
-
+
css_measure_mode_t measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
css_measure_mode_t measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -1000,7 +1000,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
css_direction_t childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (child->style.position_type == CSS_POSITION_ABSOLUTE) {
@@ -1016,27 +1016,27 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentAbsoluteChild = child;
child->next_child = NULL;
} else {
-
+
if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
-
+
// The width is definite, so use that as the flex basis.
child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_WIDTH], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {
-
+
// The height is definite, so use that as the flex basis.
child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));
} else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child->layout.flex_basis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSS_UNDEFINED;
childHeight = CSS_UNDEFINED;
childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
-
+
if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
childWidth = child->style.dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
@@ -1045,7 +1045,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childHeight = child->style.dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1066,21 +1066,21 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// Measure the child
layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
-
+
child->layout.flex_basis = fmaxf(isMainAxisRow ? child->layout.measured_dimensions[CSS_WIDTH] : child->layout.measured_dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, mainAxis));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
int startOfLineIndex = 0;
int endOfLineIndex = 0;
-
+
// Number of lines.
int lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
float totalLineCrossDim = 0;
@@ -1088,7 +1088,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
int itemsOnLine = 0;
@@ -1115,7 +1115,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (child->style.position_type != CSS_POSITION_ABSOLUTE) {
float outerFlexBasis = child->layout.flex_basis + getMarginAxis(child, mainAxis);
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -1127,7 +1127,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isFlex(child)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child->layout.flex_basis;
@@ -1143,11 +1143,11 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentRelativeChild = child;
child->next_child = NULL;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
bool canSkipFlex = !performLayout && measureModeCrossDim == CSS_MEASURE_MODE_EXACTLY;
@@ -1170,7 +1170,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
float originalRemainingFreeSpace = remainingFreeSpace;
float deltaFreeSpace = 0;
@@ -1180,20 +1180,20 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float flexGrowFactor;
float baseMainSize;
float boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
float deltaFlexShrinkScaledFactors = 0;
float deltaFlexGrowFactors = 0;
@@ -1203,7 +1203,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
baseMainSize = childFlexBasis +
@@ -1234,14 +1234,14 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
}
}
-
+
currentRelativeChild = currentRelativeChild->next_child;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -1251,7 +1251,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -1266,13 +1266,13 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1283,7 +1283,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
} else {
childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1292,7 +1292,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
}
-
+
bool requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&
getAlignItem(node, currentRelativeChild) == CSS_ALIGN_STRETCH;
@@ -1302,7 +1302,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentRelativeChild = currentRelativeChild->next_child;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -1361,7 +1361,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// we put it at the current accumulated offset.
child->layout.position[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1375,7 +1375,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));
@@ -1385,12 +1385,12 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
mainDim += trailingPaddingAndBorderMain;
-
+
float containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim == CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) {
containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);
}
@@ -1427,14 +1427,14 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
css_align_t alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem == CSS_ALIGN_STRETCH) {
childWidth = child->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childHeight = child->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
bool isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);
childHeight = crossDim;
@@ -1442,7 +1442,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
@@ -1569,7 +1569,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
bool needsMainTrailingPos = false;
@@ -1600,7 +1600,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild != NULL) {
@@ -1622,7 +1622,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = currentAbsoluteChild->style.dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
} else {
@@ -1639,7 +1639,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isUndefined(childWidth) || isUndefined(childHeight)) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1662,9 +1662,9 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidth = currentAbsoluteChild->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);
childHeight = currentAbsoluteChild->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, "abs-layout");
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {
currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1672,7 +1672,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentAbsoluteChild->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);
}
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {
currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
@@ -1713,11 +1713,11 @@ static const char* getModeName(css_measure_mode_t mode, bool performLayout) {
"LAY_EXACTLY",
"LAY_AT_MOST"
};
-
+
if (mode >= CSS_MEASURE_MODE_COUNT) {
return "";
}
-
+
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
}
@@ -1733,7 +1733,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
cachedLayout.height_measure_mode == heightMeasureMode) {
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (cachedLayout.width_measure_mode == widthMeasureMode &&
eq(cachedLayout.available_width, availableWidth) &&
@@ -1741,7 +1741,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
eq(availableHeight - marginColumn, cachedLayout.computed_height)) {
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (cachedLayout.height_measure_mode == heightMeasureMode &&
eq(cachedLayout.available_height, availableHeight) &&
@@ -1764,7 +1764,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableHeight,
css_direction_t parentDirection, css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode, bool performLayout, char* reason) {
css_layout_t* layout = &node->layout;
-
+
gDepth++;
bool needToVisitNode = (node->is_dirty(node->context) && layout->generation_count != gCurrentGenerationCount) ||
@@ -1778,7 +1778,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
css_cached_measurement_t* cachedResults = NULL;
-
+
// Determine whether the results are already cached. We maintain a separate
// cache for layouts and measurements. A layout operation modifies the positions
// and dimensions for nodes in the subtree. The algorithm assumes that each node
@@ -1789,7 +1789,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
if (isMeasureDefined(node)) {
float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-
+
// First, try to use the layout cache.
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
@@ -1809,7 +1809,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
eq(layout->cached_layout.available_height, availableHeight) &&
layout->cached_layout.width_measure_mode == widthMeasureMode &&
layout->cached_layout.height_measure_mode == heightMeasureMode) {
-
+
cachedResults = &layout->cached_layout;
}
} else {
@@ -1854,7 +1854,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);
-
+
if (gPrintChanges) {
printf("%s%d.}%s", getSpacer(gDepth), gDepth, needToVisitNode ? "*" : "");
if (node->print) {
@@ -1867,7 +1867,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
layout->last_parent_direction = parentDirection;
-
+
if (cachedResults == NULL) {
if (layout->next_cached_measurements_index == CSS_MAX_CACHED_RESULT_COUNT) {
if (gPrintChanges) {
@@ -1885,7 +1885,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
newCacheEntry = &layout->cached_measurements[layout->next_cached_measurements_index];
layout->next_cached_measurements_index++;
}
-
+
newCacheEntry->available_width = availableWidth;
newCacheEntry->available_height = availableHeight;
newCacheEntry->width_measure_mode = widthMeasureMode;
@@ -1894,7 +1894,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
newCacheEntry->computed_height = layout->measured_dimensions[CSS_HEIGHT];
}
}
-
+
if (performLayout) {
node->layout.dimensions[CSS_WIDTH] = node->layout.measured_dimensions[CSS_WIDTH];
node->layout.dimensions[CSS_HEIGHT] = node->layout.measured_dimensions[CSS_HEIGHT];
@@ -1911,7 +1911,7 @@ void layoutNode(css_node_t* node, float availableWidth, float availableHeight, c
// all dirty nodes at least once. Subsequent visits will be skipped if the input
// parameters don't change.
gCurrentGenerationCount++;
-
+
// If the caller didn't specify a height/width, use the dimensions
// specified in the style.
if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
@@ -1920,10 +1920,10 @@ void layoutNode(css_node_t* node, float availableWidth, float availableHeight, c
if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
availableHeight = node->style.dimensions[CSS_HEIGHT] + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
css_measure_mode_t widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
css_measure_mode_t heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, "initial")) {
setPosition(node, node->layout.direction);
diff --git a/dist/css-layout.jar b/dist/css-layout.jar
index b4ca4e39..73dc75fd 100644
Binary files a/dist/css-layout.jar and b/dist/css-layout.jar differ
diff --git a/dist/css-layout.js b/dist/css-layout.js
index d199bd33..4a95b4af 100644
--- a/dist/css-layout.js
+++ b/dist/css-layout.js
@@ -27,18 +27,18 @@
*/
var computeLayout = (function() {
-
+
var POSITIVE_FLEX_IS_AUTO = false;
-
+
var gCurrentGenerationCount = 0;
-
+
var CSS_UNDEFINED;
-
+
var CSS_LEFT = 'left';
var CSS_TOP = 'top';
var CSS_RIGHT = 'right';
var CSS_BOTTOM = 'bottom';
-
+
var CSS_DIRECTION_INHERIT = 'inherit';
var CSS_DIRECTION_LTR = 'ltr';
var CSS_DIRECTION_RTL = 'rtl';
@@ -61,10 +61,10 @@ var computeLayout = (function() {
var CSS_POSITION_RELATIVE = 'relative';
var CSS_POSITION_ABSOLUTE = 'absolute';
-
+
var CSS_OVERFLOW_VISIBLE = 'visible';
var CSS_OVERFLOW_HIDDEN = 'hidden';
-
+
var CSS_MEASURE_MODE_UNDEFINED = 'undefined';
var CSS_MEASURE_MODE_EXACTLY = 'exactly';
var CSS_MEASURE_MODE_AT_MOST = 'at-most';
@@ -144,14 +144,14 @@ var computeLayout = (function() {
return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||
flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;
}
-
+
function getFlex(node) {
if (node.style.flex === undefined) {
return 0;
}
return node.style.flex;
}
-
+
function isFlexBasisAuto(node) {
if (POSITIVE_FLEX_IS_AUTO) {
// All flex values are auto.
@@ -161,7 +161,7 @@ var computeLayout = (function() {
return getFlex(node) <= 0;
}
}
-
+
function getFlexGrowFactor(node) {
// Flex grow is implied by positive values for flex.
if (getFlex(node) > 0) {
@@ -169,7 +169,7 @@ var computeLayout = (function() {
}
return 0;
}
-
+
function getFlexShrinkFactor(node) {
if (POSITIVE_FLEX_IS_AUTO) {
// A flex shrink factor of 1 is implied by non-zero values for flex.
@@ -422,7 +422,7 @@ var computeLayout = (function() {
}
return CSS_POSITION_RELATIVE;
}
-
+
function getOverflow(node) {
if (node.style.overflow) {
return node.style.overflow;
@@ -444,12 +444,12 @@ var computeLayout = (function() {
function getDimWithMargin(node, axis) {
return node.layout[measuredDim[axis]] + getMarginAxis(node, axis);
}
-
- function isStyleDimDefined(node, axis) {
+
+ function isStyleDimDefined(node, axis) {
return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;
}
-
- function isLayoutDimDefined(node, axis) {
+
+ function isLayoutDimDefined(node, axis) {
return node.layout[measuredDim[axis]] !== undefined && node.layout[measuredDim[axis]] >= 0;
}
@@ -467,7 +467,7 @@ var computeLayout = (function() {
}
return 0;
}
-
+
function boundAxisWithinMinAndMax(node, axis, value) {
var min = {
'row': node.style.minWidth,
@@ -492,7 +492,7 @@ var computeLayout = (function() {
}
return boundValue;
}
-
+
function fminf(a, b) {
if (a < b) {
return a;
@@ -506,7 +506,7 @@ var computeLayout = (function() {
}
return b;
}
-
+
// Like boundAxisWithinMinAndMax but also ensures that the value doesn't go below the
// padding and border amount.
function boundAxis(node, axis, value) {
@@ -528,11 +528,11 @@ var computeLayout = (function() {
}
return -getPosition(node, trailing[axis]);
}
-
+
function setPosition(node, direction) {
var mainAxis = resolveAxis(getFlexDirection(node), direction);
var crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node.layout[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node.layout[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +
@@ -542,13 +542,13 @@ var computeLayout = (function() {
node.layout[trailing[crossAxis]] = getTrailingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
}
-
+
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
-
+
//
// This is the main routine that implements a subset of the flexbox layout algorithm
// described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.
@@ -585,8 +585,8 @@ var computeLayout = (function() {
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
- // main size. For text blocks, for example, this is the width of the widest word.
- // Calculating the minimum width is expensive, so we forego it and assume a default
+ // main size. For text blocks, for example, this is the width of the widest word.
+ // Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -620,14 +620,14 @@ var computeLayout = (function() {
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
- //
+ //
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
function layoutNodeImpl(node, availableWidth, availableHeight, /*css_direction_t*/parentDirection, widthMeasureMode, heightMeasureMode, performLayout) {
assert(isUndefined(availableWidth) ? widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');
assert(isUndefined(availableHeight) ? heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');
-
+
var/*float*/ paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
var/*float*/ paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
var/*float*/ marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
@@ -641,7 +641,7 @@ var computeLayout = (function() {
if (isMeasureDefined(node)) {
var/*float*/ innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
var/*float*/ innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -673,7 +673,7 @@ var computeLayout = (function() {
measureDim.height + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -703,7 +703,7 @@ var computeLayout = (function() {
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {
node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -715,7 +715,7 @@ var computeLayout = (function() {
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {
node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -739,7 +739,7 @@ var computeLayout = (function() {
var/*float*/ leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
-
+
var/*css_measure_mode_t*/ measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
var/*css_measure_mode_t*/ measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -764,7 +764,7 @@ var computeLayout = (function() {
var/*css_direction_t*/ childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {
@@ -780,27 +780,27 @@ var computeLayout = (function() {
currentAbsoluteChild = child;
child.nextChild = undefined;
} else {
-
+
if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
-
+
// The width is definite, so use that as the flex basis.
child.layout.flexBasis = fmaxf(child.style.width, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {
-
+
// The height is definite, so use that as the flex basis.
child.layout.flexBasis = fmaxf(child.style.height, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));
} else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child.layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSS_UNDEFINED;
childHeight = CSS_UNDEFINED;
childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
-
+
if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
childWidth = child.style.width + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
@@ -809,7 +809,7 @@ var computeLayout = (function() {
childHeight = child.style.height + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -830,21 +830,21 @@ var computeLayout = (function() {
// Measure the child
layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'measure');
-
+
child.layout.flexBasis = fmaxf(isMainAxisRow ? child.layout.measuredWidth : child.layout.measuredHeight, getPaddingAndBorderAxis(child, mainAxis));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
var/*int*/ startOfLineIndex = 0;
var/*int*/ endOfLineIndex = 0;
-
+
// Number of lines.
var/*int*/ lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
var/*float*/ totalLineCrossDim = 0;
@@ -852,7 +852,7 @@ var computeLayout = (function() {
var/*float*/ maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
var/*int*/ itemsOnLine = 0;
@@ -879,7 +879,7 @@ var computeLayout = (function() {
if (getPositionType(child) !== CSS_POSITION_ABSOLUTE) {
var/*float*/ outerFlexBasis = child.layout.flexBasis + getMarginAxis(child, mainAxis);
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -891,7 +891,7 @@ var computeLayout = (function() {
if (isFlex(child)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
@@ -907,11 +907,11 @@ var computeLayout = (function() {
currentRelativeChild = child;
child.nextChild = undefined;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
var/*bool*/ canSkipFlex = !performLayout && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY;
@@ -934,7 +934,7 @@ var computeLayout = (function() {
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
var/*float*/ originalRemainingFreeSpace = remainingFreeSpace;
var/*float*/ deltaFreeSpace = 0;
@@ -944,20 +944,20 @@ var computeLayout = (function() {
var/*float*/ flexGrowFactor;
var/*float*/ baseMainSize;
var/*float*/ boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
var/*float*/ deltaFlexShrinkScaledFactors = 0;
var/*float*/ deltaFlexGrowFactors = 0;
@@ -967,7 +967,7 @@ var computeLayout = (function() {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor !== 0) {
baseMainSize = childFlexBasis +
@@ -998,14 +998,14 @@ var computeLayout = (function() {
}
}
}
-
+
currentRelativeChild = currentRelativeChild.nextChild;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -1015,7 +1015,7 @@ var computeLayout = (function() {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor !== 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -1030,13 +1030,13 @@ var computeLayout = (function() {
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1047,7 +1047,7 @@ var computeLayout = (function() {
} else {
childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1056,7 +1056,7 @@ var computeLayout = (function() {
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
}
-
+
var/*bool*/ requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&
getAlignItem(node, currentRelativeChild) === CSS_ALIGN_STRETCH;
@@ -1066,7 +1066,7 @@ var computeLayout = (function() {
currentRelativeChild = currentRelativeChild.nextChild;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -1125,7 +1125,7 @@ var computeLayout = (function() {
// we put it at the current accumulated offset.
child.layout[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1139,7 +1139,7 @@ var computeLayout = (function() {
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));
@@ -1149,12 +1149,12 @@ var computeLayout = (function() {
}
mainDim += trailingPaddingAndBorderMain;
-
+
var/*float*/ containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {
containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);
}
@@ -1191,14 +1191,14 @@ var computeLayout = (function() {
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
var/*css_align_t*/ alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem === CSS_ALIGN_STRETCH) {
childWidth = child.layout.measuredWidth + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childHeight = child.layout.measuredHeight + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
var/*bool*/ isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);
childHeight = crossDim;
@@ -1206,7 +1206,7 @@ var computeLayout = (function() {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
@@ -1333,7 +1333,7 @@ var computeLayout = (function() {
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
var/*bool*/ needsMainTrailingPos = false;
@@ -1364,7 +1364,7 @@ var computeLayout = (function() {
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild !== undefined) {
@@ -1386,7 +1386,7 @@ var computeLayout = (function() {
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = currentAbsoluteChild.style.height + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
} else {
@@ -1403,7 +1403,7 @@ var computeLayout = (function() {
if (isUndefined(childWidth) || isUndefined(childHeight)) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1426,9 +1426,9 @@ var computeLayout = (function() {
childWidth = currentAbsoluteChild.layout.measuredWidth + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);
childHeight = currentAbsoluteChild.layout.measuredHeight + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, 'abs-layout');
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {
currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1436,7 +1436,7 @@ var computeLayout = (function() {
currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -
getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);
}
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {
currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_COLUMN]] =
@@ -1449,7 +1449,7 @@ var computeLayout = (function() {
currentAbsoluteChild = currentAbsoluteChild.nextChild;
}
}
-
+
function canUseCachedMeasurement(availableWidth, availableHeight,
marginRow, marginColumn,
widthMeasureMode, heightMeasureMode,
@@ -1462,7 +1462,7 @@ var computeLayout = (function() {
cachedLayout.heightMeasureMode === heightMeasureMode) {
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (cachedLayout.availableWidth === availableWidth &&
cachedLayout.widthMeasureMode === widthMeasureMode &&
@@ -1470,7 +1470,7 @@ var computeLayout = (function() {
availableHeight - marginColumn === cachedLayout.computedHeight) {
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (cachedLayout.availableHeight === availableHeight &&
cachedLayout.heightMeasureMode === heightMeasureMode &&
@@ -1481,7 +1481,7 @@ var computeLayout = (function() {
return false;
}
-
+
//
// This is a wrapper around the layoutNodeImpl function. It determines
// whether the layout request is redundant and can be skipped.
@@ -1500,18 +1500,18 @@ var computeLayout = (function() {
if (needToVisitNode) {
// Invalidate the cached results.
if (layout.cachedMeasurements !== undefined) {
- layout.cachedMeasurements = [];
+ layout.cachedMeasurements = [];
}
if (layout.cachedLayout !== undefined) {
layout.cachedLayout.widthMeasureMode = undefined;
layout.cachedLayout.heightMeasureMode = undefined;
}
}
-
+
var i;
var len;
var cachedResults;
-
+
// Determine whether the results are already cached. We maintain a separate
// cache for layouts and measurements. A layout operation modifies the positions
// and dimensions for nodes in the subtree. The algorithm assumes that each node
@@ -1522,7 +1522,7 @@ var computeLayout = (function() {
if (isMeasureDefined(node)) {
var marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
var marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-
+
// First, try to use the layout cache.
if (layout.cachedLayout &&
canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
@@ -1557,14 +1557,14 @@ var computeLayout = (function() {
}
}
}
-
+
if (!needToVisitNode && cachedResults !== undefined) {
layout.measureWidth = cachedResults.computedWidth;
layout.measureHeight = cachedResults.computedHeight;
} else {
layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);
layout.lastParentDirection = parentDirection;
-
+
if (cachedResults === undefined) {
var newCacheEntry;
if (performLayout) {
@@ -1581,7 +1581,7 @@ var computeLayout = (function() {
newCacheEntry = {};
layout.cachedMeasurements.push(newCacheEntry);
}
-
+
newCacheEntry.availableWidth = availableWidth;
newCacheEntry.availableHeight = availableHeight;
newCacheEntry.widthMeasureMode = widthMeasureMode;
@@ -1590,23 +1590,23 @@ var computeLayout = (function() {
newCacheEntry.computedHeight = layout.measuredHeight;
}
}
-
+
if (performLayout) {
node.layout.width = node.layout.measuredWidth;
node.layout.height = node.layout.measuredHeight;
layout.shouldUpdate = true;
}
-
+
layout.generationCount = gCurrentGenerationCount;
return (needToVisitNode || cachedResults === undefined);
}
-
+
function layoutNode(node, availableWidth, availableHeight, parentDirection) {
// Increment the generation count. This will force the recursive routine to visit
// all dirty nodes at least once. Subsequent visits will be skipped if the input
// parameters don't change.
gCurrentGenerationCount++;
-
+
// If the caller didn't specify a height/width, use the dimensions
// specified in the style.
if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
@@ -1615,10 +1615,10 @@ var computeLayout = (function() {
if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
availableHeight = node.style.height + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
var widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
var heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, 'initial')) {
setPosition(node, node.layout.direction);
}
diff --git a/dist/css-layout.min.js b/dist/css-layout.min.js
index 9478f032..85ec797c 100644
--- a/dist/css-layout.min.js
+++ b/dist/css-layout.min.js
@@ -1,2 +1,2 @@
-!function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.computeLayout=b()}(this,function(){var a=function(){function a(b){if(b.layout&&!b.isDirty||(b.layout={width:void 0,height:void 0,top:0,left:0,right:0,bottom:0}),b.style||(b.style={}),b.children||(b.children=[]),b.style.measure&&b.children&&b.children.length)throw new Error("Using custom measure function is supported only for leaf nodes.");return b.children.forEach(a),b}function b(a){return void 0===a||Number.isNaN(a)}function c(a){return a===da||a===ea}function d(a){return a===fa||a===ga}function e(a){return void 0===a.style.flex?0:a.style.flex}function f(a){return W?!0:e(a)<=0}function g(a){return e(a)>0?e(a):0}function h(a){if(W){if(0!==e(a))return 1}else if(e(a)<0)return 1;return 0}function i(a,b){if(void 0!==a.style.marginStart&&c(b))return a.style.marginStart;var d=null;switch(b){case"row":d=a.style.marginLeft;break;case"row-reverse":d=a.style.marginRight;break;case"column":d=a.style.marginTop;break;case"column-reverse":d=a.style.marginBottom}return void 0!==d?d:void 0!==a.style.margin?a.style.margin:0}function j(a,b){if(void 0!==a.style.marginEnd&&c(b))return a.style.marginEnd;var d=null;switch(b){case"row":d=a.style.marginRight;break;case"row-reverse":d=a.style.marginLeft;break;case"column":d=a.style.marginBottom;break;case"column-reverse":d=a.style.marginTop}return null!=d?d:void 0!==a.style.margin?a.style.margin:0}function k(a,b){if(void 0!==a.style.paddingStart&&a.style.paddingStart>=0&&c(b))return a.style.paddingStart;var d=null;switch(b){case"row":d=a.style.paddingLeft;break;case"row-reverse":d=a.style.paddingRight;break;case"column":d=a.style.paddingTop;break;case"column-reverse":d=a.style.paddingBottom}return null!=d&&d>=0?d:void 0!==a.style.padding&&a.style.padding>=0?a.style.padding:0}function l(a,b){if(void 0!==a.style.paddingEnd&&a.style.paddingEnd>=0&&c(b))return a.style.paddingEnd;var d=null;switch(b){case"row":d=a.style.paddingRight;break;case"row-reverse":d=a.style.paddingLeft;break;case"column":d=a.style.paddingBottom;break;case"column-reverse":d=a.style.paddingTop}return null!=d&&d>=0?d:void 0!==a.style.padding&&a.style.padding>=0?a.style.padding:0}function m(a,b){if(void 0!==a.style.borderStartWidth&&a.style.borderStartWidth>=0&&c(b))return a.style.borderStartWidth;var d=null;switch(b){case"row":d=a.style.borderLeftWidth;break;case"row-reverse":d=a.style.borderRightWidth;break;case"column":d=a.style.borderTopWidth;break;case"column-reverse":d=a.style.borderBottomWidth}return null!=d&&d>=0?d:void 0!==a.style.borderWidth&&a.style.borderWidth>=0?a.style.borderWidth:0}function n(a,b){if(void 0!==a.style.borderEndWidth&&a.style.borderEndWidth>=0&&c(b))return a.style.borderEndWidth;var d=null;switch(b){case"row":d=a.style.borderRightWidth;break;case"row-reverse":d=a.style.borderLeftWidth;break;case"column":d=a.style.borderBottomWidth;break;case"column-reverse":d=a.style.borderTopWidth}return null!=d&&d>=0?d:void 0!==a.style.borderWidth&&a.style.borderWidth>=0?a.style.borderWidth:0}function o(a,b){return k(a,b)+m(a,b)}function p(a,b){return l(a,b)+n(a,b)}function q(a,b){return i(a,b)+j(a,b)}function r(a,b){return o(a,b)+p(a,b)}function s(a){return a.style.justifyContent?a.style.justifyContent:"flex-start"}function t(a){return a.style.alignContent?a.style.alignContent:"flex-start"}function u(a,b){return b.style.alignSelf?b.style.alignSelf:a.style.alignItems?a.style.alignItems:"stretch"}function v(a,b){if(b===ca){if(a===da)return ea;if(a===ea)return da}return a}function w(a,b){var c;return c=a.style.direction?a.style.direction:aa,c===aa&&(c=void 0===b?ba:b),c}function x(a){return a.style.flexDirection?a.style.flexDirection:fa}function y(a,b){return d(a)?v(da,b):fa}function z(a){return a.style.position?a.style.position:qa}function A(a){return a.style.overflow?a.style.overflow:sa}function B(a){return z(a)===qa&&void 0!==a.style.flex&&0!==a.style.flex}function C(a){return"wrap"===a.style.flexWrap}function D(a,b){return a.layout[Ba[b]]+q(a,b)}function E(a,b){return void 0!==a.style[Aa[b]]&&a.style[Aa[b]]>=0}function F(a,b){return void 0!==a.layout[Ba[b]]&&a.layout[Ba[b]]>=0}function G(a,b){return void 0!==a.style[b]}function H(a){return void 0!==a.style.measure}function I(a,b){return void 0!==a.style[b]?a.style[b]:0}function J(a,b,c){var d={row:a.style.minWidth,"row-reverse":a.style.minWidth,column:a.style.minHeight,"column-reverse":a.style.minHeight}[b],e={row:a.style.maxWidth,"row-reverse":a.style.maxWidth,column:a.style.maxHeight,"column-reverse":a.style.maxHeight}[b],f=c;return void 0!==e&&e>=0&&f>e&&(f=e),void 0!==d&&d>=0&&d>f&&(f=d),f}function K(a,b){return b>a?a:b}function L(a,b){return a>b?a:b}function M(a,b,c){return L(J(a,b,c),r(a,b))}function N(a,b,c){var d=z(b)===ra?0:b.layout[Ba[c]];b.layout[ya[c]]=a.layout[Ba[c]]-d-b.layout[za[c]]}function O(a,b){return void 0!==a.style[xa[b]]?I(a,xa[b]):-I(a,ya[b])}function P(a,b){var c=v(x(a),b),d=y(c,b);a.layout[xa[c]]=i(a,c)+O(a,c),a.layout[ya[c]]=j(a,c)+O(a,c),a.layout[xa[d]]=i(a,d)+O(a,d),a.layout[ya[d]]=j(a,d)+O(a,d)}function Q(a,b){if(!a)throw new Error(b)}function R(a,d,e,k,l,O,R){Q(b(d)?l===ua:!0,"availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED"),Q(b(e)?O===ua:!0,"availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED");var S=r(a,da),U=r(a,fa),W=q(a,da),X=q(a,fa),aa=w(a,k);if(a.layout.direction=aa,H(a)){var ba=d-W-S,ca=e-X-U;if(l===va&&O===va)a.layout.measuredWidth=M(a,da,d-W),a.layout.measuredHeight=M(a,fa,e-X);else if(0>=ba||0>=ca)a.layout.measuredWidth=M(a,da,0),a.layout.measuredHeight=M(a,fa,0);else{var sa=a.style.measure(ba,l,ca,O);a.layout.measuredWidth=M(a,da,l===ua||l===wa?sa.width+S:d-W),a.layout.measuredHeight=M(a,fa,O===ua||O===wa?sa.height+U:e-X)}}else{var Aa=a.children.length;if(0===Aa)return a.layout.measuredWidth=M(a,da,l===ua||l===wa?S:d-W),void(a.layout.measuredHeight=M(a,fa,O===ua||O===wa?U:e-X));if(!R){if(l===wa&&0>=d&&O===wa&&0>=e)return a.layout.measuredWidth=M(a,da,0),void(a.layout.measuredHeight=M(a,fa,0));if(l===wa&&0>=d)return a.layout.measuredWidth=M(a,da,0),void(a.layout.measuredHeight=M(a,fa,b(e)?0:e-X));if(O===wa&&0>=e)return a.layout.measuredWidth=M(a,da,b(d)?0:d-W),void(a.layout.measuredHeight=M(a,fa,0));if(l===va&&O===va)return a.layout.measuredWidth=M(a,da,d-W),void(a.layout.measuredHeight=M(a,fa,e-X))}var Ca,Da,Ea,Fa,Ga,Ha,Ia=v(x(a),aa),Ja=y(Ia,aa),Ka=c(Ia),La=s(a),Ma=C(a),Na=void 0,Oa=void 0,Pa=o(a,Ia),Qa=p(a,Ia),Ra=o(a,Ja),Sa=r(a,Ia),Ta=r(a,Ja),Ua=Ka?l:O,Va=Ka?O:l,Wa=d-W-S,Xa=e-X-U,Ya=Ka?Wa:Xa,Za=Ka?Xa:Wa;for(Da=0;Aa>Da;Da++){if(Ca=a.children[Da],R){var $a=w(Ca,aa);P(Ca,$a)}z(Ca)===ra?(void 0===Na&&(Na=Ca),void 0!==Oa&&(Oa.nextChild=Ca),Oa=Ca,Ca.nextChild=void 0):Ka&&E(Ca,da)?Ca.layout.flexBasis=L(Ca.style.width,r(Ca,da)):!Ka&&E(Ca,fa)?Ca.layout.flexBasis=L(Ca.style.height,r(Ca,fa)):f(Ca)||b(Ya)?(Ea=V,Fa=V,Ga=ua,Ha=ua,E(Ca,da)&&(Ea=Ca.style.width+q(Ca,da),Ga=va),E(Ca,fa)&&(Fa=Ca.style.height+q(Ca,fa),Ha=va),Ka||!b(Ea)||b(Wa)||(Ea=Wa,Ga=wa),A(a)===ta&&Ka&&b(Fa)&&!b(Xa)&&(Fa=Xa,Ha=wa),T(Ca,Ea,Fa,aa,Ga,Ha,!1,"measure"),Ca.layout.flexBasis=L(Ka?Ca.layout.measuredWidth:Ca.layout.measuredHeight,r(Ca,Ia))):Ca.layout.flexBasis=L(0,r(Ca,Ia))}for(var _a=0,ab=0,bb=0,cb=0,db=0;Aa>ab;){var eb=0,fb=0,gb=0,hb=0;Da=_a;for(var ib=void 0,jb=void 0;Aa>Da;){if(Ca=a.children[Da],Ca.lineIndex=bb,z(Ca)!==ra){var kb=Ca.layout.flexBasis+q(Ca,Ia);if(fb+kb>Ya&&Ma&&eb>0)break;fb+=kb,eb++,B(Ca)&&(gb+=g(Ca),hb+=h(Ca)*Ca.layout.flexBasis),void 0===ib&&(ib=Ca),void 0!==jb&&(jb.nextChild=Ca),jb=Ca,Ca.nextChild=void 0}Da++,ab++}var lb=!R&&Va===va,mb=0,nb=0,ob=0;b(Ya)?0>fb&&(ob=-fb):ob=Ya-fb;var pb=ob,qb=0;if(!lb){var rb,sb,tb,ub,vb,wb=0,xb=0;for(jb=ib;void 0!==jb;)rb=jb.layout.flexBasis,0>ob?(sb=h(jb)*rb,0!==sb&&(ub=rb+ob/hb*sb,vb=M(jb,Ia,ub),ub!==vb&&(qb-=vb-rb,wb-=sb))):ob>0&&(tb=g(jb),0!==tb&&(ub=rb+ob/gb*tb,vb=M(jb,Ia,ub),ub!==vb&&(qb-=vb-rb,xb-=tb))),jb=jb.nextChild;for(hb+=wb,gb+=xb,ob+=qb,qb=0,jb=ib;void 0!==jb;){rb=jb.layout.flexBasis;var yb=rb;0>ob?(sb=h(jb)*rb,0!==sb&&(yb=M(jb,Ia,rb+ob/hb*sb))):ob>0&&(tb=g(jb),0!==tb&&(yb=M(jb,Ia,rb+ob/gb*tb))),qb-=yb-rb,Ka?(Ea=yb+q(jb,da),Ga=va,E(jb,fa)?(Fa=jb.style.height+q(jb,fa),Ha=va):(Fa=Za,Ha=b(Fa)?ua:wa)):(Fa=yb+q(jb,fa),Ha=va,E(jb,da)?(Ea=jb.style.width+q(jb,da),Ga=va):(Ea=Za,Ga=b(Ea)?ua:wa));var zb=!E(jb,Ja)&&u(a,jb)===pa;T(jb,Ea,Fa,aa,Ga,Ha,R&&!zb,"flex"),jb=jb.nextChild}}ob=pb+qb,Ua===wa&&(ob=0),La!==ha&&(La===ia?mb=ob/2:La===ja?mb=ob:La===ka?(ob=L(ob,0),nb=eb>1?ob/(eb-1):0):La===la&&(nb=ob/eb,mb=nb/2));var Ab=Pa+mb,Bb=0;for(Da=_a;ab>Da;++Da)Ca=a.children[Da],z(Ca)===ra&&G(Ca,xa[Ia])?R&&(Ca.layout[za[Ia]]=I(Ca,xa[Ia])+m(a,Ia)+i(Ca,Ia)):(R&&(Ca.layout[za[Ia]]+=Ab),z(Ca)===qa&&(lb?(Ab+=nb+q(Ca,Ia)+Ca.layout.flexBasis,Bb=Za):(Ab+=nb+D(Ca,Ia),Bb=L(Bb,D(Ca,Ja)))));Ab+=Qa;var Cb=Za;if(Va!==ua&&Va!==wa||(Cb=M(a,Ja,Bb+Ta)-Ta,Va===wa&&(Cb=K(Cb,Za))),Ma||Va!==va||(Bb=Za),Bb=M(a,Ja,Bb+Ta)-Ta,R)for(Da=_a;ab>Da;++Da)if(Ca=a.children[Da],z(Ca)===ra)G(Ca,xa[Ja])?Ca.layout[za[Ja]]=I(Ca,xa[Ja])+m(a,Ja)+i(Ca,Ja):Ca.layout[za[Ja]]=Ra+i(Ca,Ja);else{var Db=Ra,Eb=u(a,Ca);if(Eb===pa){Ea=Ca.layout.measuredWidth+q(Ca,da),Fa=Ca.layout.measuredHeight+q(Ca,fa);var Fb=!1;Ka?(Fb=E(Ca,fa),Fa=Bb):(Fb=E(Ca,da),Ea=Bb),Fb||(Ga=b(Ea)?ua:va,Ha=b(Fa)?ua:va,T(Ca,Ea,Fa,aa,Ga,Ha,!0,"stretch"))}else if(Eb!==ma){var Gb=Cb-D(Ca,Ja);Db+=Eb===na?Gb/2:Gb}Ca.layout[za[Ja]]+=cb+Db}cb+=Bb,db=L(db,Ab),bb++,_a=ab,ab=_a}if(bb>1&&R&&!b(Za)){var Hb=Za-cb,Ib=0,Jb=Ra,Kb=t(a);Kb===oa?Jb+=Hb:Kb===na?Jb+=Hb/2:Kb===pa&&Za>cb&&(Ib=Hb/bb);var Lb=0;for(Da=0;bb>Da;++Da){var Mb,Nb=Lb,Ob=0;for(Mb=Nb;Aa>Mb;++Mb)if(Ca=a.children[Mb],z(Ca)===qa){if(Ca.lineIndex!==Da)break;F(Ca,Ja)&&(Ob=L(Ob,Ca.layout[Ba[Ja]]+q(Ca,Ja)))}if(Lb=Mb,Ob+=Ib,R)for(Mb=Nb;Lb>Mb;++Mb)if(Ca=a.children[Mb],z(Ca)===qa){var Pb=u(a,Ca);Pb===ma?Ca.layout[za[Ja]]=Jb+i(Ca,Ja):Pb===oa?Ca.layout[za[Ja]]=Jb+Ob-j(Ca,Ja)-Ca.layout[Ba[Ja]]:Pb===na?(Fa=Ca.layout[Ba[Ja]],Ca.layout[za[Ja]]=Jb+(Ob-Fa)/2):Pb===pa&&(Ca.layout[za[Ja]]=Jb+i(Ca,Ja))}Jb+=Ob}}if(a.layout.measuredWidth=M(a,da,d-W),a.layout.measuredHeight=M(a,fa,e-X),Ua===ua?a.layout[Ba[Ia]]=M(a,Ia,db):Ua===wa&&(a.layout[Ba[Ia]]=L(K(Ya+Sa,J(a,Ia,db)),Sa)),Va===ua?a.layout[Ba[Ja]]=M(a,Ja,cb+Ta):Va===wa&&(a.layout[Ba[Ja]]=L(K(Za+Ta,J(a,Ja,cb+Ta)),Ta)),R){var Qb=!1,Rb=!1;if(Ia!==ea&&Ia!==ga||(Qb=!0),Ja!==ea&&Ja!==ga||(Rb=!0),Qb||Rb)for(Da=0;Aa>Da;++Da)Ca=a.children[Da],Qb&&N(a,Ca,Ia),Rb&&N(a,Ca,Ja)}for(Oa=Na;void 0!==Oa;)R&&(Ea=V,Fa=V,E(Oa,da)?Ea=Oa.style.width+q(Oa,da):G(Oa,Y)&&G(Oa,$)&&(Ea=a.layout.measuredWidth-(m(a,da)+n(a,da))-(Oa.style[Y]+Oa.style[$]),Ea=M(Oa,da,Ea)),E(Oa,fa)?Fa=Oa.style.height+q(Oa,fa):G(Oa,Z)&&G(Oa,_)&&(Fa=a.layout.measuredHeight-(m(a,fa)+n(a,fa))-(Oa.style[Z]+Oa.style[_]),Fa=M(Oa,fa,Fa)),(b(Ea)||b(Fa))&&(Ga=b(Ea)?ua:va,Ha=b(Fa)?ua:va,Ka||!b(Ea)||b(Wa)||(Ea=Wa,Ga=wa),A(a)===ta&&Ka&&b(Fa)&&!b(Xa)&&(Fa=Xa,Ha=wa),T(Oa,Ea,Fa,aa,Ga,Ha,!1,"abs-measure"),Ea=Oa.layout.measuredWidth+q(Oa,da),Fa=Oa.layout.measuredHeight+q(Oa,fa)),T(Oa,Ea,Fa,aa,va,va,!0,"abs-layout"),G(Oa,ya[da])&&!G(Oa,xa[da])&&(Oa.layout[xa[da]]=a.layout[Ba[da]]-Oa.layout[Ba[da]]-I(Oa,ya[da])),G(Oa,ya[fa])&&!G(Oa,xa[fa])&&(Oa.layout[xa[fa]]=a.layout[Ba[fa]]-Oa.layout[Ba[fa]]-I(Oa,ya[fa]))),Oa=Oa.nextChild}}function S(a,b,c,d,e,f,g){return g.availableWidth===a&&g.availableHeight===b&&g.widthMeasureMode===e&&g.heightMeasureMode===f?!0:g.availableWidth===a&&g.widthMeasureMode===e&&f===va&&b-d===g.computedHeight?!0:g.availableHeight===b&&g.heightMeasureMode===f&&e===va&&a-c===g.computedWidth}function T(a,b,c,d,e,f,g,h){var i=a.layout,j=a.isDirty&&i.generationCount!==X||i.lastParentDirection!==d;j&&(void 0!==i.cachedMeasurements&&(i.cachedMeasurements=[]),void 0!==i.cachedLayout&&(i.cachedLayout.widthMeasureMode=void 0,i.cachedLayout.heightMeasureMode=void 0));var k,l,m;if(H(a)){var n=q(a,da),o=q(a,fa);if(i.cachedLayout&&S(b,c,n,o,e,f,i.cachedLayout))m=i.cachedLayout;else if(i.cachedMeasurements)for(k=0,l=i.cachedMeasurements.length;l>k;k++)if(S(b,c,n,o,e,f,i.cachedMeasurements[k])){m=i.cachedMeasurements[k];break}}else if(g)i.cachedLayout&&i.cachedLayout.availableWidth===b&&i.cachedLayout.availableHeight===c&&i.cachedLayout.widthMeasureMode===e&&i.cachedLayout.heightMeasureMode===f&&(m=i.cachedLayout);else if(i.cachedMeasurements)for(k=0,l=i.cachedMeasurements.length;l>k;k++)if(i.cachedMeasurements[k].availableWidth===b&&i.cachedMeasurements[k].availableHeight===c&&i.cachedMeasurements[k].widthMeasureMode===e&&i.cachedMeasurements[k].heightMeasureMode===f){m=i.cachedMeasurements[k];break}if(j||void 0===m){if(R(a,b,c,d,e,f,g),i.lastParentDirection=d,void 0===m){var p;g?(void 0===i.cachedLayout&&(i.cachedLayout={}),p=i.cachedLayout):(void 0===i.cachedMeasurements&&(i.cachedMeasurements=[]),p={},i.cachedMeasurements.push(p)),p.availableWidth=b,p.availableHeight=c,p.widthMeasureMode=e,p.heightMeasureMode=f,p.computedWidth=i.measuredWidth,p.computedHeight=i.measuredHeight}}else i.measureWidth=m.computedWidth,i.measureHeight=m.computedHeight;return g&&(a.layout.width=a.layout.measuredWidth,a.layout.height=a.layout.measuredHeight,i.shouldUpdate=!0),i.generationCount=X,j||void 0===m}function U(a,c,d,e){X++,b(c)&&E(a,da)&&(c=a.style.width+q(a,da)),b(d)&&E(a,fa)&&(d=a.style.height+q(a,fa));var f=b(c)?ua:va,g=b(d)?ua:va;T(a,c,d,e,f,g,!0,"initial")&&P(a,a.layout.direction)}var V,W=!1,X=0,Y="left",Z="top",$="right",_="bottom",aa="inherit",ba="ltr",ca="rtl",da="row",ea="row-reverse",fa="column",ga="column-reverse",ha="flex-start",ia="center",ja="flex-end",ka="space-between",la="space-around",ma="flex-start",na="center",oa="flex-end",pa="stretch",qa="relative",ra="absolute",sa="visible",ta="hidden",ua="undefined",va="exactly",wa="at-most",xa={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},ya={row:"right","row-reverse":"left",column:"bottom","column-reverse":"top"},za={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},Aa={row:"width","row-reverse":"width",column:"height","column-reverse":"height"},Ba={row:"measuredWidth","row-reverse":"measuredWidth",column:"measuredHeight","column-reverse":"measuredHeight"};return{layoutNodeImpl:R,computeLayout:U,fillNodes:a,canUseCachedMeasurement:S}}();return"object"==typeof exports&&(module.exports=a),function(b){a.fillNodes(b),a.computeLayout(b)}});
+!function(a,b){"function"==typeof define&&define.amd?define([],b):"object"==typeof exports?module.exports=b():a.computeLayout=b()}(this,function(){var a=function(){function a(b){if((!b.layout||b.isDirty)&&(b.layout={width:void 0,height:void 0,top:0,left:0,right:0,bottom:0}),b.style||(b.style={}),b.children||(b.children=[]),b.style.measure&&b.children&&b.children.length)throw new Error("Using custom measure function is supported only for leaf nodes.");return b.children.forEach(a),b}function b(a){return void 0===a||Number.isNaN(a)}function c(a){return a===da||a===ea}function d(a){return a===fa||a===ga}function e(a){return void 0===a.style.flex?0:a.style.flex}function f(a){return W?!0:e(a)<=0}function g(a){return e(a)>0?e(a):0}function h(a){if(W){if(0!==e(a))return 1}else if(e(a)<0)return 1;return 0}function i(a,b){if(void 0!==a.style.marginStart&&c(b))return a.style.marginStart;var d=null;switch(b){case"row":d=a.style.marginLeft;break;case"row-reverse":d=a.style.marginRight;break;case"column":d=a.style.marginTop;break;case"column-reverse":d=a.style.marginBottom}return void 0!==d?d:void 0!==a.style.margin?a.style.margin:0}function j(a,b){if(void 0!==a.style.marginEnd&&c(b))return a.style.marginEnd;var d=null;switch(b){case"row":d=a.style.marginRight;break;case"row-reverse":d=a.style.marginLeft;break;case"column":d=a.style.marginBottom;break;case"column-reverse":d=a.style.marginTop}return null!=d?d:void 0!==a.style.margin?a.style.margin:0}function k(a,b){if(void 0!==a.style.paddingStart&&a.style.paddingStart>=0&&c(b))return a.style.paddingStart;var d=null;switch(b){case"row":d=a.style.paddingLeft;break;case"row-reverse":d=a.style.paddingRight;break;case"column":d=a.style.paddingTop;break;case"column-reverse":d=a.style.paddingBottom}return null!=d&&d>=0?d:void 0!==a.style.padding&&a.style.padding>=0?a.style.padding:0}function l(a,b){if(void 0!==a.style.paddingEnd&&a.style.paddingEnd>=0&&c(b))return a.style.paddingEnd;var d=null;switch(b){case"row":d=a.style.paddingRight;break;case"row-reverse":d=a.style.paddingLeft;break;case"column":d=a.style.paddingBottom;break;case"column-reverse":d=a.style.paddingTop}return null!=d&&d>=0?d:void 0!==a.style.padding&&a.style.padding>=0?a.style.padding:0}function m(a,b){if(void 0!==a.style.borderStartWidth&&a.style.borderStartWidth>=0&&c(b))return a.style.borderStartWidth;var d=null;switch(b){case"row":d=a.style.borderLeftWidth;break;case"row-reverse":d=a.style.borderRightWidth;break;case"column":d=a.style.borderTopWidth;break;case"column-reverse":d=a.style.borderBottomWidth}return null!=d&&d>=0?d:void 0!==a.style.borderWidth&&a.style.borderWidth>=0?a.style.borderWidth:0}function n(a,b){if(void 0!==a.style.borderEndWidth&&a.style.borderEndWidth>=0&&c(b))return a.style.borderEndWidth;var d=null;switch(b){case"row":d=a.style.borderRightWidth;break;case"row-reverse":d=a.style.borderLeftWidth;break;case"column":d=a.style.borderBottomWidth;break;case"column-reverse":d=a.style.borderTopWidth}return null!=d&&d>=0?d:void 0!==a.style.borderWidth&&a.style.borderWidth>=0?a.style.borderWidth:0}function o(a,b){return k(a,b)+m(a,b)}function p(a,b){return l(a,b)+n(a,b)}function q(a,b){return i(a,b)+j(a,b)}function r(a,b){return o(a,b)+p(a,b)}function s(a){return a.style.justifyContent?a.style.justifyContent:"flex-start"}function t(a){return a.style.alignContent?a.style.alignContent:"flex-start"}function u(a,b){return b.style.alignSelf?b.style.alignSelf:a.style.alignItems?a.style.alignItems:"stretch"}function v(a,b){if(b===ca){if(a===da)return ea;if(a===ea)return da}return a}function w(a,b){var c;return c=a.style.direction?a.style.direction:aa,c===aa&&(c=void 0===b?ba:b),c}function x(a){return a.style.flexDirection?a.style.flexDirection:fa}function y(a,b){return d(a)?v(da,b):fa}function z(a){return a.style.position?a.style.position:qa}function A(a){return a.style.overflow?a.style.overflow:sa}function B(a){return z(a)===qa&&void 0!==a.style.flex&&0!==a.style.flex}function C(a){return"wrap"===a.style.flexWrap}function D(a,b){return a.layout[Ba[b]]+q(a,b)}function E(a,b){return void 0!==a.style[Aa[b]]&&a.style[Aa[b]]>=0}function F(a,b){return void 0!==a.layout[Ba[b]]&&a.layout[Ba[b]]>=0}function G(a,b){return void 0!==a.style[b]}function H(a){return void 0!==a.style.measure}function I(a,b){return void 0!==a.style[b]?a.style[b]:0}function J(a,b,c){var d={row:a.style.minWidth,"row-reverse":a.style.minWidth,column:a.style.minHeight,"column-reverse":a.style.minHeight}[b],e={row:a.style.maxWidth,"row-reverse":a.style.maxWidth,column:a.style.maxHeight,"column-reverse":a.style.maxHeight}[b],f=c;return void 0!==e&&e>=0&&f>e&&(f=e),void 0!==d&&d>=0&&d>f&&(f=d),f}function K(a,b){return b>a?a:b}function L(a,b){return a>b?a:b}function M(a,b,c){return L(J(a,b,c),r(a,b))}function N(a,b,c){var d=z(b)===ra?0:b.layout[Ba[c]];b.layout[ya[c]]=a.layout[Ba[c]]-d-b.layout[za[c]]}function O(a,b){return void 0!==a.style[xa[b]]?I(a,xa[b]):-I(a,ya[b])}function P(a,b){var c=v(x(a),b),d=y(c,b);a.layout[xa[c]]=i(a,c)+O(a,c),a.layout[ya[c]]=j(a,c)+O(a,c),a.layout[xa[d]]=i(a,d)+O(a,d),a.layout[ya[d]]=j(a,d)+O(a,d)}function Q(a,b){if(!a)throw new Error(b)}function R(a,d,e,k,l,O,R){Q(b(d)?l===ua:!0,"availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED"),Q(b(e)?O===ua:!0,"availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED");var S=r(a,da),U=r(a,fa),W=q(a,da),X=q(a,fa),aa=w(a,k);if(a.layout.direction=aa,H(a)){var ba=d-W-S,ca=e-X-U;if(l===va&&O===va)a.layout.measuredWidth=M(a,da,d-W),a.layout.measuredHeight=M(a,fa,e-X);else if(0>=ba||0>=ca)a.layout.measuredWidth=M(a,da,0),a.layout.measuredHeight=M(a,fa,0);else{var sa=a.style.measure(ba,l,ca,O);a.layout.measuredWidth=M(a,da,l===ua||l===wa?sa.width+S:d-W),a.layout.measuredHeight=M(a,fa,O===ua||O===wa?sa.height+U:e-X)}}else{var Aa=a.children.length;if(0===Aa)return a.layout.measuredWidth=M(a,da,l===ua||l===wa?S:d-W),void(a.layout.measuredHeight=M(a,fa,O===ua||O===wa?U:e-X));if(!R){if(l===wa&&0>=d&&O===wa&&0>=e)return a.layout.measuredWidth=M(a,da,0),void(a.layout.measuredHeight=M(a,fa,0));if(l===wa&&0>=d)return a.layout.measuredWidth=M(a,da,0),void(a.layout.measuredHeight=M(a,fa,b(e)?0:e-X));if(O===wa&&0>=e)return a.layout.measuredWidth=M(a,da,b(d)?0:d-W),void(a.layout.measuredHeight=M(a,fa,0));if(l===va&&O===va)return a.layout.measuredWidth=M(a,da,d-W),void(a.layout.measuredHeight=M(a,fa,e-X))}var Ca,Da,Ea,Fa,Ga,Ha,Ia=v(x(a),aa),Ja=y(Ia,aa),Ka=c(Ia),La=s(a),Ma=C(a),Na=void 0,Oa=void 0,Pa=o(a,Ia),Qa=p(a,Ia),Ra=o(a,Ja),Sa=r(a,Ia),Ta=r(a,Ja),Ua=Ka?l:O,Va=Ka?O:l,Wa=d-W-S,Xa=e-X-U,Ya=Ka?Wa:Xa,Za=Ka?Xa:Wa;for(Da=0;Aa>Da;Da++){if(Ca=a.children[Da],R){var $a=w(Ca,aa);P(Ca,$a)}z(Ca)===ra?(void 0===Na&&(Na=Ca),void 0!==Oa&&(Oa.nextChild=Ca),Oa=Ca,Ca.nextChild=void 0):Ka&&E(Ca,da)?Ca.layout.flexBasis=L(Ca.style.width,r(Ca,da)):!Ka&&E(Ca,fa)?Ca.layout.flexBasis=L(Ca.style.height,r(Ca,fa)):f(Ca)||b(Ya)?(Ea=V,Fa=V,Ga=ua,Ha=ua,E(Ca,da)&&(Ea=Ca.style.width+q(Ca,da),Ga=va),E(Ca,fa)&&(Fa=Ca.style.height+q(Ca,fa),Ha=va),Ka||!b(Ea)||b(Wa)||(Ea=Wa,Ga=wa),A(a)===ta&&Ka&&b(Fa)&&!b(Xa)&&(Fa=Xa,Ha=wa),T(Ca,Ea,Fa,aa,Ga,Ha,!1,"measure"),Ca.layout.flexBasis=L(Ka?Ca.layout.measuredWidth:Ca.layout.measuredHeight,r(Ca,Ia))):Ca.layout.flexBasis=L(0,r(Ca,Ia))}for(var _a=0,ab=0,bb=0,cb=0,db=0;Aa>ab;){var eb=0,fb=0,gb=0,hb=0;Da=_a;for(var ib=void 0,jb=void 0;Aa>Da;){if(Ca=a.children[Da],Ca.lineIndex=bb,z(Ca)!==ra){var kb=Ca.layout.flexBasis+q(Ca,Ia);if(fb+kb>Ya&&Ma&&eb>0)break;fb+=kb,eb++,B(Ca)&&(gb+=g(Ca),hb+=h(Ca)*Ca.layout.flexBasis),void 0===ib&&(ib=Ca),void 0!==jb&&(jb.nextChild=Ca),jb=Ca,Ca.nextChild=void 0}Da++,ab++}var lb=!R&&Va===va,mb=0,nb=0,ob=0;b(Ya)?0>fb&&(ob=-fb):ob=Ya-fb;var pb=ob,qb=0;if(!lb){var rb,sb,tb,ub,vb,wb=0,xb=0;for(jb=ib;void 0!==jb;)rb=jb.layout.flexBasis,0>ob?(sb=h(jb)*rb,0!==sb&&(ub=rb+ob/hb*sb,vb=M(jb,Ia,ub),ub!==vb&&(qb-=vb-rb,wb-=sb))):ob>0&&(tb=g(jb),0!==tb&&(ub=rb+ob/gb*tb,vb=M(jb,Ia,ub),ub!==vb&&(qb-=vb-rb,xb-=tb))),jb=jb.nextChild;for(hb+=wb,gb+=xb,ob+=qb,qb=0,jb=ib;void 0!==jb;){rb=jb.layout.flexBasis;var yb=rb;0>ob?(sb=h(jb)*rb,0!==sb&&(yb=M(jb,Ia,rb+ob/hb*sb))):ob>0&&(tb=g(jb),0!==tb&&(yb=M(jb,Ia,rb+ob/gb*tb))),qb-=yb-rb,Ka?(Ea=yb+q(jb,da),Ga=va,E(jb,fa)?(Fa=jb.style.height+q(jb,fa),Ha=va):(Fa=Za,Ha=b(Fa)?ua:wa)):(Fa=yb+q(jb,fa),Ha=va,E(jb,da)?(Ea=jb.style.width+q(jb,da),Ga=va):(Ea=Za,Ga=b(Ea)?ua:wa));var zb=!E(jb,Ja)&&u(a,jb)===pa;T(jb,Ea,Fa,aa,Ga,Ha,R&&!zb,"flex"),jb=jb.nextChild}}ob=pb+qb,Ua===wa&&(ob=0),La!==ha&&(La===ia?mb=ob/2:La===ja?mb=ob:La===ka?(ob=L(ob,0),nb=eb>1?ob/(eb-1):0):La===la&&(nb=ob/eb,mb=nb/2));var Ab=Pa+mb,Bb=0;for(Da=_a;ab>Da;++Da)Ca=a.children[Da],z(Ca)===ra&&G(Ca,xa[Ia])?R&&(Ca.layout[za[Ia]]=I(Ca,xa[Ia])+m(a,Ia)+i(Ca,Ia)):(R&&(Ca.layout[za[Ia]]+=Ab),z(Ca)===qa&&(lb?(Ab+=nb+q(Ca,Ia)+Ca.layout.flexBasis,Bb=Za):(Ab+=nb+D(Ca,Ia),Bb=L(Bb,D(Ca,Ja)))));Ab+=Qa;var Cb=Za;if((Va===ua||Va===wa)&&(Cb=M(a,Ja,Bb+Ta)-Ta,Va===wa&&(Cb=K(Cb,Za))),Ma||Va!==va||(Bb=Za),Bb=M(a,Ja,Bb+Ta)-Ta,R)for(Da=_a;ab>Da;++Da)if(Ca=a.children[Da],z(Ca)===ra)G(Ca,xa[Ja])?Ca.layout[za[Ja]]=I(Ca,xa[Ja])+m(a,Ja)+i(Ca,Ja):Ca.layout[za[Ja]]=Ra+i(Ca,Ja);else{var Db=Ra,Eb=u(a,Ca);if(Eb===pa){Ea=Ca.layout.measuredWidth+q(Ca,da),Fa=Ca.layout.measuredHeight+q(Ca,fa);var Fb=!1;Ka?(Fb=E(Ca,fa),Fa=Bb):(Fb=E(Ca,da),Ea=Bb),Fb||(Ga=b(Ea)?ua:va,Ha=b(Fa)?ua:va,T(Ca,Ea,Fa,aa,Ga,Ha,!0,"stretch"))}else if(Eb!==ma){var Gb=Cb-D(Ca,Ja);Db+=Eb===na?Gb/2:Gb}Ca.layout[za[Ja]]+=cb+Db}cb+=Bb,db=L(db,Ab),bb++,_a=ab,ab=_a}if(bb>1&&R&&!b(Za)){var Hb=Za-cb,Ib=0,Jb=Ra,Kb=t(a);Kb===oa?Jb+=Hb:Kb===na?Jb+=Hb/2:Kb===pa&&Za>cb&&(Ib=Hb/bb);var Lb=0;for(Da=0;bb>Da;++Da){var Mb,Nb=Lb,Ob=0;for(Mb=Nb;Aa>Mb;++Mb)if(Ca=a.children[Mb],z(Ca)===qa){if(Ca.lineIndex!==Da)break;F(Ca,Ja)&&(Ob=L(Ob,Ca.layout[Ba[Ja]]+q(Ca,Ja)))}if(Lb=Mb,Ob+=Ib,R)for(Mb=Nb;Lb>Mb;++Mb)if(Ca=a.children[Mb],z(Ca)===qa){var Pb=u(a,Ca);Pb===ma?Ca.layout[za[Ja]]=Jb+i(Ca,Ja):Pb===oa?Ca.layout[za[Ja]]=Jb+Ob-j(Ca,Ja)-Ca.layout[Ba[Ja]]:Pb===na?(Fa=Ca.layout[Ba[Ja]],Ca.layout[za[Ja]]=Jb+(Ob-Fa)/2):Pb===pa&&(Ca.layout[za[Ja]]=Jb+i(Ca,Ja))}Jb+=Ob}}if(a.layout.measuredWidth=M(a,da,d-W),a.layout.measuredHeight=M(a,fa,e-X),Ua===ua?a.layout[Ba[Ia]]=M(a,Ia,db):Ua===wa&&(a.layout[Ba[Ia]]=L(K(Ya+Sa,J(a,Ia,db)),Sa)),Va===ua?a.layout[Ba[Ja]]=M(a,Ja,cb+Ta):Va===wa&&(a.layout[Ba[Ja]]=L(K(Za+Ta,J(a,Ja,cb+Ta)),Ta)),R){var Qb=!1,Rb=!1;if((Ia===ea||Ia===ga)&&(Qb=!0),(Ja===ea||Ja===ga)&&(Rb=!0),Qb||Rb)for(Da=0;Aa>Da;++Da)Ca=a.children[Da],Qb&&N(a,Ca,Ia),Rb&&N(a,Ca,Ja)}for(Oa=Na;void 0!==Oa;)R&&(Ea=V,Fa=V,E(Oa,da)?Ea=Oa.style.width+q(Oa,da):G(Oa,Y)&&G(Oa,$)&&(Ea=a.layout.measuredWidth-(m(a,da)+n(a,da))-(Oa.style[Y]+Oa.style[$]),Ea=M(Oa,da,Ea)),E(Oa,fa)?Fa=Oa.style.height+q(Oa,fa):G(Oa,Z)&&G(Oa,_)&&(Fa=a.layout.measuredHeight-(m(a,fa)+n(a,fa))-(Oa.style[Z]+Oa.style[_]),Fa=M(Oa,fa,Fa)),(b(Ea)||b(Fa))&&(Ga=b(Ea)?ua:va,Ha=b(Fa)?ua:va,Ka||!b(Ea)||b(Wa)||(Ea=Wa,Ga=wa),A(a)===ta&&Ka&&b(Fa)&&!b(Xa)&&(Fa=Xa,Ha=wa),T(Oa,Ea,Fa,aa,Ga,Ha,!1,"abs-measure"),Ea=Oa.layout.measuredWidth+q(Oa,da),Fa=Oa.layout.measuredHeight+q(Oa,fa)),T(Oa,Ea,Fa,aa,va,va,!0,"abs-layout"),G(Oa,ya[da])&&!G(Oa,xa[da])&&(Oa.layout[xa[da]]=a.layout[Ba[da]]-Oa.layout[Ba[da]]-I(Oa,ya[da])),G(Oa,ya[fa])&&!G(Oa,xa[fa])&&(Oa.layout[xa[fa]]=a.layout[Ba[fa]]-Oa.layout[Ba[fa]]-I(Oa,ya[fa]))),Oa=Oa.nextChild}}function S(a,b,c,d,e,f,g){return g.availableWidth===a&&g.availableHeight===b&&g.widthMeasureMode===e&&g.heightMeasureMode===f?!0:g.availableWidth===a&&g.widthMeasureMode===e&&f===va&&b-d===g.computedHeight?!0:g.availableHeight===b&&g.heightMeasureMode===f&&e===va&&a-c===g.computedWidth?!0:!1}function T(a,b,c,d,e,f,g,h){var i=a.layout,j=a.isDirty&&i.generationCount!==X||i.lastParentDirection!==d;j&&(void 0!==i.cachedMeasurements&&(i.cachedMeasurements=[]),void 0!==i.cachedLayout&&(i.cachedLayout.widthMeasureMode=void 0,i.cachedLayout.heightMeasureMode=void 0));var k,l,m;if(H(a)){var n=q(a,da),o=q(a,fa);if(i.cachedLayout&&S(b,c,n,o,e,f,i.cachedLayout))m=i.cachedLayout;else if(i.cachedMeasurements)for(k=0,l=i.cachedMeasurements.length;l>k;k++)if(S(b,c,n,o,e,f,i.cachedMeasurements[k])){m=i.cachedMeasurements[k];break}}else if(g)i.cachedLayout&&i.cachedLayout.availableWidth===b&&i.cachedLayout.availableHeight===c&&i.cachedLayout.widthMeasureMode===e&&i.cachedLayout.heightMeasureMode===f&&(m=i.cachedLayout);else if(i.cachedMeasurements)for(k=0,l=i.cachedMeasurements.length;l>k;k++)if(i.cachedMeasurements[k].availableWidth===b&&i.cachedMeasurements[k].availableHeight===c&&i.cachedMeasurements[k].widthMeasureMode===e&&i.cachedMeasurements[k].heightMeasureMode===f){m=i.cachedMeasurements[k];break}if(j||void 0===m){if(R(a,b,c,d,e,f,g),i.lastParentDirection=d,void 0===m){var p;g?(void 0===i.cachedLayout&&(i.cachedLayout={}),p=i.cachedLayout):(void 0===i.cachedMeasurements&&(i.cachedMeasurements=[]),p={},i.cachedMeasurements.push(p)),p.availableWidth=b,p.availableHeight=c,p.widthMeasureMode=e,p.heightMeasureMode=f,p.computedWidth=i.measuredWidth,p.computedHeight=i.measuredHeight}}else i.measureWidth=m.computedWidth,i.measureHeight=m.computedHeight;return g&&(a.layout.width=a.layout.measuredWidth,a.layout.height=a.layout.measuredHeight,i.shouldUpdate=!0),i.generationCount=X,j||void 0===m}function U(a,c,d,e){X++,b(c)&&E(a,da)&&(c=a.style.width+q(a,da)),b(d)&&E(a,fa)&&(d=a.style.height+q(a,fa));var f=b(c)?ua:va,g=b(d)?ua:va;T(a,c,d,e,f,g,!0,"initial")&&P(a,a.layout.direction)}var V,W=!1,X=0,Y="left",Z="top",$="right",_="bottom",aa="inherit",ba="ltr",ca="rtl",da="row",ea="row-reverse",fa="column",ga="column-reverse",ha="flex-start",ia="center",ja="flex-end",ka="space-between",la="space-around",ma="flex-start",na="center",oa="flex-end",pa="stretch",qa="relative",ra="absolute",sa="visible",ta="hidden",ua="undefined",va="exactly",wa="at-most",xa={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},ya={row:"right","row-reverse":"left",column:"bottom","column-reverse":"top"},za={row:"left","row-reverse":"right",column:"top","column-reverse":"bottom"},Aa={row:"width","row-reverse":"width",column:"height","column-reverse":"height"},Ba={row:"measuredWidth","row-reverse":"measuredWidth",column:"measuredHeight","column-reverse":"measuredHeight"};return{layoutNodeImpl:R,computeLayout:U,fillNodes:a,canUseCachedMeasurement:S}}();return"object"==typeof exports&&(module.exports=a),function(b){a.fillNodes(b),a.computeLayout(b)}});
//# sourceMappingURL=css-layout.min.js.map
\ No newline at end of file
diff --git a/dist/css-layout.min.js.map b/dist/css-layout.min.js.map
index e73d0ca2..5f6eb9aa 100644
--- a/dist/css-layout.min.js.map
+++ b/dist/css-layout.min.js.map
@@ -1 +1 @@
-{"version":3,"sources":["css-layout.js"],"names":["root","factory","define","amd","exports","module","computeLayout","this","fillNodes","node","layout","isDirty","width","undefined","height","top","left","right","bottom","style","children","measure","length","Error","forEach","isUndefined","value","Number","isNaN","isRowDirection","flexDirection","CSS_FLEX_DIRECTION_ROW","CSS_FLEX_DIRECTION_ROW_REVERSE","isColumnDirection","CSS_FLEX_DIRECTION_COLUMN","CSS_FLEX_DIRECTION_COLUMN_REVERSE","getFlex","flex","isFlexBasisAuto","POSITIVE_FLEX_IS_AUTO","getFlexGrowFactor","getFlexShrinkFactor","getLeadingMargin","axis","marginStart","marginLeft","marginRight","marginTop","marginBottom","margin","getTrailingMargin","marginEnd","getLeadingPadding","paddingStart","paddingLeft","paddingRight","paddingTop","paddingBottom","padding","getTrailingPadding","paddingEnd","getLeadingBorder","borderStartWidth","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth","borderWidth","getTrailingBorder","borderEndWidth","getLeadingPaddingAndBorder","getTrailingPaddingAndBorder","getMarginAxis","getPaddingAndBorderAxis","getJustifyContent","justifyContent","getAlignContent","alignContent","getAlignItem","child","alignSelf","alignItems","resolveAxis","direction","CSS_DIRECTION_RTL","resolveDirection","parentDirection","CSS_DIRECTION_INHERIT","CSS_DIRECTION_LTR","getFlexDirection","getCrossFlexDirection","getPositionType","position","CSS_POSITION_RELATIVE","getOverflow","overflow","CSS_OVERFLOW_VISIBLE","isFlex","isFlexWrap","flexWrap","getDimWithMargin","measuredDim","isStyleDimDefined","dim","isLayoutDimDefined","isPosDefined","pos","isMeasureDefined","getPosition","boundAxisWithinMinAndMax","min","row","minWidth","row-reverse","column","minHeight","column-reverse","max","maxWidth","maxHeight","boundValue","fminf","a","b","fmaxf","boundAxis","setTrailingPosition","size","CSS_POSITION_ABSOLUTE","trailing","getRelativePosition","leading","setPosition","mainAxis","crossAxis","assert","condition","message","layoutNodeImpl","availableWidth","availableHeight","widthMeasureMode","heightMeasureMode","performLayout","CSS_MEASURE_MODE_UNDEFINED","paddingAndBorderAxisRow","paddingAndBorderAxisColumn","marginAxisRow","marginAxisColumn","innerWidth","innerHeight","CSS_MEASURE_MODE_EXACTLY","measuredWidth","measuredHeight","measureDim","CSS_MEASURE_MODE_AT_MOST","childCount","i","childWidth","childHeight","childWidthMeasureMode","childHeightMeasureMode","isMainAxisRow","isNodeFlexWrap","firstAbsoluteChild","currentAbsoluteChild","leadingPaddingAndBorderMain","trailingPaddingAndBorderMain","leadingPaddingAndBorderCross","paddingAndBorderAxisMain","paddingAndBorderAxisCross","measureModeMainDim","measureModeCrossDim","availableInnerWidth","availableInnerHeight","availableInnerMainDim","availableInnerCrossDim","childDirection","nextChild","flexBasis","CSS_UNDEFINED","CSS_OVERFLOW_HIDDEN","layoutNodeInternal","startOfLineIndex","endOfLineIndex","lineCount","totalLineCrossDim","maxLineMainDim","itemsOnLine","sizeConsumedOnCurrentLine","totalFlexGrowFactors","totalFlexShrinkScaledFactors","firstRelativeChild","currentRelativeChild","lineIndex","outerFlexBasis","canSkipFlex","leadingMainDim","betweenMainDim","remainingFreeSpace","originalRemainingFreeSpace","deltaFreeSpace","childFlexBasis","flexShrinkScaledFactor","flexGrowFactor","baseMainSize","boundMainSize","deltaFlexShrinkScaledFactors","deltaFlexGrowFactors","updatedMainSize","requiresStretchLayout","CSS_ALIGN_STRETCH","CSS_JUSTIFY_FLEX_START","CSS_JUSTIFY_CENTER","CSS_JUSTIFY_FLEX_END","CSS_JUSTIFY_SPACE_BETWEEN","CSS_JUSTIFY_SPACE_AROUND","mainDim","crossDim","containerCrossAxis","leadingCrossDim","alignItem","isCrossSizeDefinite","CSS_ALIGN_FLEX_START","remainingCrossDim","CSS_ALIGN_CENTER","remainingAlignContentDim","crossDimLead","currentLead","CSS_ALIGN_FLEX_END","endIndex","j","startIndex","lineHeight","alignContentAlignItem","needsMainTrailingPos","needsCrossTrailingPos","CSS_LEFT","CSS_RIGHT","CSS_TOP","CSS_BOTTOM","canUseCachedMeasurement","marginRow","marginColumn","cachedLayout","computedHeight","computedWidth","reason","needToVisitNode","generationCount","gCurrentGenerationCount","lastParentDirection","cachedMeasurements","len","cachedResults","newCacheEntry","push","measureWidth","measureHeight","shouldUpdate","layoutNode"],"mappings":"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","file":"css-layout.min.js","sourcesContent":["// UMD (Universal Module Definition)\n// See https://github.com/umdjs/umd for reference\n//\n// This file uses the following specific UMD implementation:\n// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define([], factory);\n } else if (typeof exports === 'object') {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory();\n } else {\n // Browser globals (root is window)\n root.computeLayout = factory();\n }\n}(this, function() {\n /**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nvar computeLayout = (function() {\n \n var POSITIVE_FLEX_IS_AUTO = false;\n \n var gCurrentGenerationCount = 0;\n \n var CSS_UNDEFINED;\n \n var CSS_LEFT = 'left';\n var CSS_TOP = 'top';\n var CSS_RIGHT = 'right';\n var CSS_BOTTOM = 'bottom';\n \n var CSS_DIRECTION_INHERIT = 'inherit';\n var CSS_DIRECTION_LTR = 'ltr';\n var CSS_DIRECTION_RTL = 'rtl';\n\n var CSS_FLEX_DIRECTION_ROW = 'row';\n var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';\n var CSS_FLEX_DIRECTION_COLUMN = 'column';\n var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';\n\n var CSS_JUSTIFY_FLEX_START = 'flex-start';\n var CSS_JUSTIFY_CENTER = 'center';\n var CSS_JUSTIFY_FLEX_END = 'flex-end';\n var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';\n var CSS_JUSTIFY_SPACE_AROUND = 'space-around';\n\n var CSS_ALIGN_FLEX_START = 'flex-start';\n var CSS_ALIGN_CENTER = 'center';\n var CSS_ALIGN_FLEX_END = 'flex-end';\n var CSS_ALIGN_STRETCH = 'stretch';\n\n var CSS_POSITION_RELATIVE = 'relative';\n var CSS_POSITION_ABSOLUTE = 'absolute';\n \n var CSS_OVERFLOW_VISIBLE = 'visible';\n var CSS_OVERFLOW_HIDDEN = 'hidden';\n \n var CSS_MEASURE_MODE_UNDEFINED = 'undefined';\n var CSS_MEASURE_MODE_EXACTLY = 'exactly';\n var CSS_MEASURE_MODE_AT_MOST = 'at-most';\n\n var leading = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var trailing = {\n 'row': 'right',\n 'row-reverse': 'left',\n 'column': 'bottom',\n 'column-reverse': 'top'\n };\n var pos = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var dim = {\n 'row': 'width',\n 'row-reverse': 'width',\n 'column': 'height',\n 'column-reverse': 'height'\n };\n var measuredDim = {\n 'row': 'measuredWidth',\n 'row-reverse': 'measuredWidth',\n 'column': 'measuredHeight',\n 'column-reverse': 'measuredHeight'\n };\n\n // When transpiled to Java / C the node type has layout, children and style\n // properties. For the JavaScript version this function adds these properties\n // if they don't already exist.\n function fillNodes(node) {\n if (!node.layout || node.isDirty) {\n node.layout = {\n width: undefined,\n height: undefined,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n }\n\n if (!node.style) {\n node.style = {};\n }\n\n if (!node.children) {\n node.children = [];\n }\n\n if (node.style.measure && node.children && node.children.length) {\n throw new Error('Using custom measure function is supported only for leaf nodes.');\n }\n\n node.children.forEach(fillNodes);\n return node;\n }\n\n function isUndefined(value) {\n return value === undefined || Number.isNaN(value);\n }\n\n function isRowDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_ROW ||\n flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;\n }\n\n function isColumnDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||\n flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;\n }\n \n function getFlex(node) {\n if (node.style.flex === undefined) {\n return 0;\n }\n return node.style.flex;\n }\n \n function isFlexBasisAuto(node) {\n if (POSITIVE_FLEX_IS_AUTO) {\n // All flex values are auto.\n return true;\n } else {\n // A flex value > 0 implies a basis of zero.\n return getFlex(node) <= 0;\n }\n }\n \n function getFlexGrowFactor(node) {\n // Flex grow is implied by positive values for flex.\n if (getFlex(node) > 0) {\n return getFlex(node);\n }\n return 0;\n }\n \n function getFlexShrinkFactor(node) {\n if (POSITIVE_FLEX_IS_AUTO) {\n // A flex shrink factor of 1 is implied by non-zero values for flex.\n if (getFlex(node) !== 0) {\n return 1;\n }\n } else {\n // A flex shrink factor of 1 is implied by negative values for flex.\n if (getFlex(node) < 0) {\n return 1;\n }\n }\n return 0;\n }\n\n function getLeadingMargin(node, axis) {\n if (node.style.marginStart !== undefined && isRowDirection(axis)) {\n return node.style.marginStart;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.marginLeft; break;\n case 'row-reverse': value = node.style.marginRight; break;\n case 'column': value = node.style.marginTop; break;\n case 'column-reverse': value = node.style.marginBottom; break;\n }\n\n if (value !== undefined) {\n return value;\n }\n\n if (node.style.margin !== undefined) {\n return node.style.margin;\n }\n\n return 0;\n }\n\n function getTrailingMargin(node, axis) {\n if (node.style.marginEnd !== undefined && isRowDirection(axis)) {\n return node.style.marginEnd;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.marginRight; break;\n case 'row-reverse': value = node.style.marginLeft; break;\n case 'column': value = node.style.marginBottom; break;\n case 'column-reverse': value = node.style.marginTop; break;\n }\n\n if (value != null) {\n return value;\n }\n\n if (node.style.margin !== undefined) {\n return node.style.margin;\n }\n\n return 0;\n }\n\n function getLeadingPadding(node, axis) {\n if (node.style.paddingStart !== undefined && node.style.paddingStart >= 0\n && isRowDirection(axis)) {\n return node.style.paddingStart;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.paddingLeft; break;\n case 'row-reverse': value = node.style.paddingRight; break;\n case 'column': value = node.style.paddingTop; break;\n case 'column-reverse': value = node.style.paddingBottom; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.padding !== undefined && node.style.padding >= 0) {\n return node.style.padding;\n }\n\n return 0;\n }\n\n function getTrailingPadding(node, axis) {\n if (node.style.paddingEnd !== undefined && node.style.paddingEnd >= 0\n && isRowDirection(axis)) {\n return node.style.paddingEnd;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.paddingRight; break;\n case 'row-reverse': value = node.style.paddingLeft; break;\n case 'column': value = node.style.paddingBottom; break;\n case 'column-reverse': value = node.style.paddingTop; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.padding !== undefined && node.style.padding >= 0) {\n return node.style.padding;\n }\n\n return 0;\n }\n\n function getLeadingBorder(node, axis) {\n if (node.style.borderStartWidth !== undefined && node.style.borderStartWidth >= 0\n && isRowDirection(axis)) {\n return node.style.borderStartWidth;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.borderLeftWidth; break;\n case 'row-reverse': value = node.style.borderRightWidth; break;\n case 'column': value = node.style.borderTopWidth; break;\n case 'column-reverse': value = node.style.borderBottomWidth; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {\n return node.style.borderWidth;\n }\n\n return 0;\n }\n\n function getTrailingBorder(node, axis) {\n if (node.style.borderEndWidth !== undefined && node.style.borderEndWidth >= 0\n && isRowDirection(axis)) {\n return node.style.borderEndWidth;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.borderRightWidth; break;\n case 'row-reverse': value = node.style.borderLeftWidth; break;\n case 'column': value = node.style.borderBottomWidth; break;\n case 'column-reverse': value = node.style.borderTopWidth; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {\n return node.style.borderWidth;\n }\n\n return 0;\n }\n\n function getLeadingPaddingAndBorder(node, axis) {\n return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);\n }\n\n function getTrailingPaddingAndBorder(node, axis) {\n return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getMarginAxis(node, axis) {\n return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);\n }\n\n function getPaddingAndBorderAxis(node, axis) {\n return getLeadingPaddingAndBorder(node, axis) +\n getTrailingPaddingAndBorder(node, axis);\n }\n\n function getJustifyContent(node) {\n if (node.style.justifyContent) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if (node.style.alignContent) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if (child.style.alignSelf) {\n return child.style.alignSelf;\n }\n if (node.style.alignItems) {\n return node.style.alignItems;\n }\n return 'stretch';\n }\n\n function resolveAxis(axis, direction) {\n if (direction === CSS_DIRECTION_RTL) {\n if (axis === CSS_FLEX_DIRECTION_ROW) {\n return CSS_FLEX_DIRECTION_ROW_REVERSE;\n } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {\n return CSS_FLEX_DIRECTION_ROW;\n }\n }\n\n return axis;\n }\n\n function resolveDirection(node, parentDirection) {\n var direction;\n if (node.style.direction) {\n direction = node.style.direction;\n } else {\n direction = CSS_DIRECTION_INHERIT;\n }\n\n if (direction === CSS_DIRECTION_INHERIT) {\n direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);\n }\n\n return direction;\n }\n\n function getFlexDirection(node) {\n if (node.style.flexDirection) {\n return node.style.flexDirection;\n }\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n\n function getCrossFlexDirection(flexDirection, direction) {\n if (isColumnDirection(flexDirection)) {\n return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n } else {\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n }\n\n function getPositionType(node) {\n if (node.style.position) {\n return node.style.position;\n }\n return CSS_POSITION_RELATIVE;\n }\n \n function getOverflow(node) {\n if (node.style.overflow) {\n return node.style.overflow;\n }\n return CSS_OVERFLOW_VISIBLE;\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n node.style.flex !== undefined && node.style.flex !== 0\n );\n }\n\n function isFlexWrap(node) {\n return node.style.flexWrap === 'wrap';\n }\n\n function getDimWithMargin(node, axis) {\n return node.layout[measuredDim[axis]] + getMarginAxis(node, axis);\n }\n \n function isStyleDimDefined(node, axis) { \n return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;\n }\n \n function isLayoutDimDefined(node, axis) { \n return node.layout[measuredDim[axis]] !== undefined && node.layout[measuredDim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return node.style[pos] !== undefined;\n }\n\n function isMeasureDefined(node) {\n return node.style.measure !== undefined;\n }\n\n function getPosition(node, pos) {\n if (node.style[pos] !== undefined) {\n return node.style[pos];\n }\n return 0;\n }\n \n function boundAxisWithinMinAndMax(node, axis, value) {\n var min = {\n 'row': node.style.minWidth,\n 'row-reverse': node.style.minWidth,\n 'column': node.style.minHeight,\n 'column-reverse': node.style.minHeight\n }[axis];\n\n var max = {\n 'row': node.style.maxWidth,\n 'row-reverse': node.style.maxWidth,\n 'column': node.style.maxHeight,\n 'column-reverse': node.style.maxHeight\n }[axis];\n\n var boundValue = value;\n if (max !== undefined && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (min !== undefined && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n \n function fminf(a, b) {\n if (a < b) {\n return a;\n }\n return b;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n \n // Like boundAxisWithinMinAndMax but also ensures that the value doesn't go below the\n // padding and border amount.\n function boundAxis(node, axis, value) {\n return fmaxf(boundAxisWithinMinAndMax(node, axis, value), getPaddingAndBorderAxis(node, axis));\n }\n\n function setTrailingPosition(node, child, axis) {\n var size = (getPositionType(child) === CSS_POSITION_ABSOLUTE) ?\n 0 :\n child.layout[measuredDim[axis]];\n child.layout[trailing[axis]] = node.layout[measuredDim[axis]] - size - child.layout[pos[axis]];\n }\n\n // If both left and right are defined, then use left. Otherwise return\n // +left or -right depending on which is defined.\n function getRelativePosition(node, axis) {\n if (node.style[leading[axis]] !== undefined) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n \n function setPosition(node, direction) {\n var mainAxis = resolveAxis(getFlexDirection(node), direction);\n var crossAxis = getCrossFlexDirection(mainAxis, direction);\n \n node.layout[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[leading[crossAxis]] = getLeadingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n node.layout[trailing[crossAxis]] = getTrailingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n }\n \n function assert(condition, message) {\n if (!condition) {\n throw new Error(message);\n }\n }\n \n //\n // This is the main routine that implements a subset of the flexbox layout algorithm\n // described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.\n //\n // Limitations of this algorithm, compared to the full standard:\n // * Display property is always assumed to be 'flex' except for Text nodes, which\n // are assumed to be 'inline-flex'.\n // * The 'zIndex' property (or any form of z ordering) is not supported. Nodes are\n // stacked in document order.\n // * The 'order' property is not supported. The order of flex items is always defined\n // by document order.\n // * The 'visibility' property is always assumed to be 'visible'. Values of 'collapse'\n // and 'hidden' are not supported.\n // * The 'wrap' property supports only 'nowrap' (which is the default) or 'wrap'. The\n // rarely-used 'wrap-reverse' is not supported.\n // * Rather than allowing arbitrary combinations of flexGrow, flexShrink and\n // flexBasis, this algorithm supports only the three most common combinations:\n // flex: 0 is equiavlent to flex: 0 0 auto\n // flex: n (where n is a positive value) is equivalent to flex: n 1 auto\n // If POSITIVE_FLEX_IS_AUTO is 0, then it is equivalent to flex: n 0 0\n // This is faster because the content doesn't need to be measured, but it's\n // less flexible because the basis is always 0 and can't be overriden with\n // the width/height attributes.\n // flex: -1 (or any negative value) is equivalent to flex: 0 1 auto\n // * Margins cannot be specified as 'auto'. They must be specified in terms of pixel\n // values, and the default value is 0.\n // * The 'baseline' value is not supported for alignItems and alignSelf properties.\n // * Values of width, maxWidth, minWidth, height, maxHeight and minHeight must be\n // specified as pixel values, not as percentages.\n // * There is no support for calculation of dimensions based on intrinsic aspect ratios\n // (e.g. images).\n // * There is no support for forced breaks.\n // * It does not support vertical inline directions (top-to-bottom or bottom-to-top text).\n //\n // Deviations from standard:\n // * Section 4.5 of the spec indicates that all flex items have a default minimum\n // main size. For text blocks, for example, this is the width of the widest word. \n // Calculating the minimum width is expensive, so we forego it and assume a default \n // minimum main size of 0.\n // * Min/Max sizes in the main axis are not honored when resolving flexible lengths.\n // * The spec indicates that the default value for 'flexDirection' is 'row', but\n // the algorithm below assumes a default of 'column'.\n //\n // Input parameters:\n // - node: current node to be sized and layed out\n // - availableWidth & availableHeight: available size to be used for sizing the node\n // or CSS_UNDEFINED if the size is not available; interpretation depends on layout\n // flags\n // - parentDirection: the inline (text) direction within the parent (left-to-right or\n // right-to-left)\n // - widthMeasureMode: indicates the sizing rules for the width (see below for explanation)\n // - heightMeasureMode: indicates the sizing rules for the height (see below for explanation)\n // - performLayout: specifies whether the caller is interested in just the dimensions\n // of the node or it requires the entire node and its subtree to be layed out\n // (with final positions)\n //\n // Details:\n // This routine is called recursively to lay out subtrees of flexbox elements. It uses the\n // information in node.style, which is treated as a read-only input. It is responsible for\n // setting the layout.direction and layout.measured_dimensions fields for the input node as well\n // as the layout.position and layout.line_index fields for its child nodes. The\n // layout.measured_dimensions field includes any border or padding for the node but does\n // not include margins.\n //\n // The spec describes four different layout modes: \"fill available\", \"max content\", \"min content\",\n // and \"fit content\". Of these, we don't use \"min content\" because we don't support default\n // minimum main sizes (see above for details). Each of our measure modes maps to a layout mode\n // from the spec (https://www.w3.org/TR/css3-sizing/#terms):\n // - CSS_MEASURE_MODE_UNDEFINED: max content\n // - CSS_MEASURE_MODE_EXACTLY: fill available\n // - CSS_MEASURE_MODE_AT_MOST: fit content\n // \n // When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of\n // undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.\n //\n function layoutNodeImpl(node, availableWidth, availableHeight, /*css_direction_t*/parentDirection, widthMeasureMode, heightMeasureMode, performLayout) {\n assert(isUndefined(availableWidth) ? widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');\n assert(isUndefined(availableHeight) ? heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');\n \n var/*float*/ paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);\n var/*float*/ paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n var/*float*/ marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n var/*float*/ marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n\n // Set the resolved resolution in the node's layout.\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\n node.layout.direction = direction;\n\n // For content (text) nodes, determine the dimensions based on the text contents.\n if (isMeasureDefined(node)) {\n var/*float*/ innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;\n var/*float*/ innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;\n \n if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {\n\n // Don't bother sizing the text if both dimensions are already defined.\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n } else if (innerWidth <= 0 || innerHeight <= 0) {\n\n // Don't bother sizing the text if there's no horizontal or vertical space.\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n } else {\n\n // Measure the text under the current constraints.\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n innerWidth,\n widthMeasureMode,\n innerHeight,\n heightMeasureMode\n );\n\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW,\n (widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n measureDim.width + paddingAndBorderAxisRow :\n availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN,\n (heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n measureDim.height + paddingAndBorderAxisColumn :\n availableHeight - marginAxisColumn);\n }\n \n return;\n }\n\n // For nodes with no children, use the available values if they were provided, or\n // the minimum size as indicated by the padding and border sizes.\n var/*int*/ childCount = node.children.length;\n if (childCount === 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW,\n (widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n paddingAndBorderAxisRow :\n availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN,\n (heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n paddingAndBorderAxisColumn :\n availableHeight - marginAxisColumn);\n return;\n }\n\n // If we're not being asked to perform a full layout, we can handle a number of common\n // cases here without incurring the cost of the remaining function.\n if (!performLayout) {\n // If we're being asked to size the content with an at most constraint but there is no available width,\n // the measurement will always be zero.\n if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0 &&\n heightMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n return;\n }\n \n if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));\n return;\n }\n\n if (heightMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, isUndefined(availableWidth) ? 0 : (availableWidth - marginAxisRow));\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n return;\n }\n \n // If we're being asked to use an exact width/height, there's no need to measure the children.\n if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n return;\n }\n }\n\n // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM\n var/*(c)!css_flex_direction_t*//*(java)!int*/ mainAxis = resolveAxis(getFlexDirection(node), direction);\n var/*(c)!css_flex_direction_t*//*(java)!int*/ crossAxis = getCrossFlexDirection(mainAxis, direction);\n var/*bool*/ isMainAxisRow = isRowDirection(mainAxis);\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n var/*bool*/ isNodeFlexWrap = isFlexWrap(node);\n\n var/*css_node_t**/ firstAbsoluteChild = undefined;\n var/*css_node_t**/ currentAbsoluteChild = undefined;\n\n var/*float*/ leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);\n var/*float*/ trailingPaddingAndBorderMain = getTrailingPaddingAndBorder(node, mainAxis);\n var/*float*/ leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);\n var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);\n var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);\n \n var/*css_measure_mode_t*/ measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;\n var/*css_measure_mode_t*/ measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;\n\n // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS\n var/*float*/ availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;\n var/*float*/ availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;\n var/*float*/ availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;\n var/*float*/ availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;\n\n // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM\n var/*css_node_t**/ child;\n var/*int*/ i;\n var/*float*/ childWidth;\n var/*float*/ childHeight;\n var/*css_measure_mode_t*/ childWidthMeasureMode;\n var/*css_measure_mode_t*/ childHeightMeasureMode;\n for (i = 0; i < childCount; i++) {\n child = node.children[i];\n\n if (performLayout) {\n // Set the initial position (relative to the parent).\n var/*css_direction_t*/ childDirection = resolveDirection(child, direction);\n setPosition(child, childDirection);\n }\n \n // Absolute-positioned children don't participate in flex layout. Add them\n // to a list that we can process later.\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n\n // Store a private linked list of absolutely positioned children\n // so that we can efficiently traverse them later.\n if (firstAbsoluteChild === undefined) {\n firstAbsoluteChild = child;\n }\n if (currentAbsoluteChild !== undefined) {\n currentAbsoluteChild.nextChild = child;\n }\n currentAbsoluteChild = child;\n child.nextChild = undefined;\n } else {\n \n if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {\n \n // The width is definite, so use that as the flex basis.\n child.layout.flexBasis = fmaxf(child.style.width, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));\n } else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {\n \n // The height is definite, so use that as the flex basis.\n child.layout.flexBasis = fmaxf(child.style.height, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));\n } else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {\n \n // If the basis isn't 'auto', it is assumed to be zero.\n child.layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));\n } else {\n \n // Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).\n childWidth = CSS_UNDEFINED;\n childHeight = CSS_UNDEFINED;\n childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;\n childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;\n \n if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = child.style.width + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = child.style.height + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n \n // According to the spec, if the main size is not definite and the\n // child's inline axis is parallel to the main axis (i.e. it's\n // horizontal), the child should be sized using \"UNDEFINED\" in\n // the main size. Otherwise use \"AT_MOST\" in the cross axis.\n if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) {\n childWidth = availableInnerWidth;\n childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n\n // The W3C spec doesn't say anything about the 'overflow' property,\n // but all major browsers appear to implement the following logic.\n if (getOverflow(node) === CSS_OVERFLOW_HIDDEN) {\n if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) {\n childHeight = availableInnerHeight;\n childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n }\n\n // Measure the child\n layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'measure');\n \n child.layout.flexBasis = fmaxf(isMainAxisRow ? child.layout.measuredWidth : child.layout.measuredHeight, getPaddingAndBorderAxis(child, mainAxis));\n }\n }\n }\n\n // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES\n \n // Indexes of children that represent the first and last items in the line.\n var/*int*/ startOfLineIndex = 0;\n var/*int*/ endOfLineIndex = 0;\n \n // Number of lines.\n var/*int*/ lineCount = 0;\n \n // Accumulated cross dimensions of all lines so far.\n var/*float*/ totalLineCrossDim = 0;\n\n // Max main dimension of all the lines.\n var/*float*/ maxLineMainDim = 0;\n\n while (endOfLineIndex < childCount) {\n \n // Number of items on the currently line. May be different than the difference\n // between start and end indicates because we skip over absolute-positioned items.\n var/*int*/ itemsOnLine = 0;\n\n // sizeConsumedOnCurrentLine is accumulation of the dimensions and margin\n // of all the children on the current line. This will be used in order to\n // either set the dimensions of the node if none already exist or to compute\n // the remaining space left for the flexible children.\n var/*float*/ sizeConsumedOnCurrentLine = 0;\n\n var/*float*/ totalFlexGrowFactors = 0;\n var/*float*/ totalFlexShrinkScaledFactors = 0;\n\n i = startOfLineIndex;\n\n // Maintain a linked list of the child nodes that can shrink and/or grow.\n var/*css_node_t**/ firstRelativeChild = undefined;\n var/*css_node_t**/ currentRelativeChild = undefined;\n\n // Add items to the current line until it's full or we run out of items.\n while (i < childCount) {\n child = node.children[i];\n child.lineIndex = lineCount;\n\n if (getPositionType(child) !== CSS_POSITION_ABSOLUTE) {\n var/*float*/ outerFlexBasis = child.layout.flexBasis + getMarginAxis(child, mainAxis);\n \n // If this is a multi-line flow and this item pushes us over the available size, we've\n // hit the end of the current line. Break out of the loop and lay out the current line.\n if (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {\n break;\n }\n\n sizeConsumedOnCurrentLine += outerFlexBasis;\n itemsOnLine++;\n\n if (isFlex(child)) {\n totalFlexGrowFactors += getFlexGrowFactor(child);\n \n // Unlike the grow factor, the shrink factor is scaled relative to the child\n // dimension.\n totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;\n }\n\n // Store a private linked list of children that need to be layed out.\n if (firstRelativeChild === undefined) {\n firstRelativeChild = child;\n }\n if (currentRelativeChild !== undefined) {\n currentRelativeChild.nextChild = child;\n }\n currentRelativeChild = child;\n child.nextChild = undefined;\n }\n \n i++;\n endOfLineIndex++;\n }\n \n // If we don't need to measure the cross axis, we can skip the entire flex step.\n var/*bool*/ canSkipFlex = !performLayout && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY;\n\n // In order to position the elements in the main axis, we have two\n // controls. The space between the beginning and the first element\n // and the space between each two elements.\n var/*float*/ leadingMainDim = 0;\n var/*float*/ betweenMainDim = 0;\n\n // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS\n // Calculate the remaining available space that needs to be allocated.\n // If the main dimension size isn't known, it is computed based on\n // the line length, so there's no more space left to distribute.\n var/*float*/ remainingFreeSpace = 0;\n if (!isUndefined(availableInnerMainDim)) {\n remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine;\n } else if (sizeConsumedOnCurrentLine < 0) {\n // availableInnerMainDim is indefinite which means the node is being sized based on its content.\n // sizeConsumedOnCurrentLine is negative which means the node will allocate 0 pixels for\n // its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.\n remainingFreeSpace = -sizeConsumedOnCurrentLine;\n }\n \n var/*float*/ originalRemainingFreeSpace = remainingFreeSpace;\n var/*float*/ deltaFreeSpace = 0;\n\n if (!canSkipFlex) {\n var/*float*/ childFlexBasis;\n var/*float*/ flexShrinkScaledFactor;\n var/*float*/ flexGrowFactor;\n var/*float*/ baseMainSize;\n var/*float*/ boundMainSize;\n \n // Do two passes over the flex items to figure out how to distribute the remaining space.\n // The first pass finds the items whose min/max constraints trigger, freezes them at those\n // sizes, and excludes those sizes from the remaining space. The second pass sets the size\n // of each flexible item. It distributes the remaining space amongst the items whose min/max\n // constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing\n // their min/max constraints to trigger again. \n //\n // This two pass approach for resolving min/max constraints deviates from the spec. The\n // spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process\n // that needs to be repeated a variable number of times. The algorithm implemented here\n // won't handle all cases but it was simpler to implement and it mitigates performance\n // concerns because we know exactly how many passes it'll do.\n \n // First pass: detect the flex items whose min/max constraints trigger\n var/*float*/ deltaFlexShrinkScaledFactors = 0;\n var/*float*/ deltaFlexGrowFactors = 0;\n currentRelativeChild = firstRelativeChild;\n while (currentRelativeChild !== undefined) {\n childFlexBasis = currentRelativeChild.layout.flexBasis;\n\n if (remainingFreeSpace < 0) {\n flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;\n \n // Is this child able to shrink?\n if (flexShrinkScaledFactor !== 0) {\n baseMainSize = childFlexBasis +\n remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor;\n boundMainSize = boundAxis(currentRelativeChild, mainAxis, baseMainSize);\n if (baseMainSize !== boundMainSize) {\n // By excluding this item's size and flex factor from remaining, this item's\n // min/max constraints should also trigger in the second pass resulting in the\n // item's size calculation being identical in the first and second passes.\n deltaFreeSpace -= boundMainSize - childFlexBasis;\n deltaFlexShrinkScaledFactors -= flexShrinkScaledFactor;\n }\n }\n } else if (remainingFreeSpace > 0) {\n flexGrowFactor = getFlexGrowFactor(currentRelativeChild);\n\n // Is this child able to grow?\n if (flexGrowFactor !== 0) {\n baseMainSize = childFlexBasis +\n remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor;\n boundMainSize = boundAxis(currentRelativeChild, mainAxis, baseMainSize);\n if (baseMainSize !== boundMainSize) {\n // By excluding this item's size and flex factor from remaining, this item's\n // min/max constraints should also trigger in the second pass resulting in the\n // item's size calculation being identical in the first and second passes.\n deltaFreeSpace -= boundMainSize - childFlexBasis;\n deltaFlexGrowFactors -= flexGrowFactor;\n }\n }\n }\n \n currentRelativeChild = currentRelativeChild.nextChild;\n }\n \n totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;\n totalFlexGrowFactors += deltaFlexGrowFactors;\n remainingFreeSpace += deltaFreeSpace;\n \n // Second pass: resolve the sizes of the flexible items\n deltaFreeSpace = 0;\n currentRelativeChild = firstRelativeChild;\n while (currentRelativeChild !== undefined) {\n childFlexBasis = currentRelativeChild.layout.flexBasis;\n var/*float*/ updatedMainSize = childFlexBasis;\n\n if (remainingFreeSpace < 0) {\n flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;\n \n // Is this child able to shrink?\n if (flexShrinkScaledFactor !== 0) {\n updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +\n remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor);\n }\n } else if (remainingFreeSpace > 0) {\n flexGrowFactor = getFlexGrowFactor(currentRelativeChild);\n\n // Is this child able to grow?\n if (flexGrowFactor !== 0) {\n updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +\n remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);\n }\n }\n \n deltaFreeSpace -= updatedMainSize - childFlexBasis;\n \n if (isMainAxisRow) {\n childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n \n if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = availableInnerCrossDim;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;\n } else {\n childHeight = currentRelativeChild.style.height + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n } else {\n childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n \n if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = availableInnerCrossDim;\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;\n } else {\n childWidth = currentRelativeChild.style.width + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n }\n \n var/*bool*/ requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&\n getAlignItem(node, currentRelativeChild) === CSS_ALIGN_STRETCH;\n\n // Recursively call the layout algorithm for this child with the updated main size.\n layoutNodeInternal(currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, 'flex');\n\n currentRelativeChild = currentRelativeChild.nextChild;\n }\n }\n \n remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;\n\n // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION\n\n // At this point, all the children have their dimensions set in the main axis.\n // Their dimensions are also set in the cross axis with the exception of items\n // that are aligned 'stretch'. We need to compute these stretch values and\n // set the final positions.\n\n // If we are using \"at most\" rules in the main axis, we won't distribute\n // any remaining space at this point.\n if (measureModeMainDim === CSS_MEASURE_MODE_AT_MOST) {\n remainingFreeSpace = 0;\n }\n\n // Use justifyContent to figure out how to allocate the remaining space\n // available in the main axis.\n if (justifyContent !== CSS_JUSTIFY_FLEX_START) {\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingFreeSpace / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingFreeSpace;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingFreeSpace = fmaxf(remainingFreeSpace, 0);\n if (itemsOnLine > 1) {\n betweenMainDim = remainingFreeSpace / (itemsOnLine - 1);\n } else {\n betweenMainDim = 0;\n }\n } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {\n // Space on the edges is half of the space between elements\n betweenMainDim = remainingFreeSpace / itemsOnLine;\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n var/*float*/ mainDim = leadingPaddingAndBorderMain + leadingMainDim;\n var/*float*/ crossDim = 0;\n\n for (i = startOfLineIndex; i < endOfLineIndex; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\n if (performLayout) {\n // In case the child is position absolute and has left/top being\n // defined, we override the position to whatever the user said\n // (and margin/border).\n child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +\n getLeadingBorder(node, mainAxis) +\n getLeadingMargin(child, mainAxis);\n }\n } else {\n if (performLayout) {\n // If the child is position absolute (without top/left) or relative,\n // we put it at the current accumulated offset.\n child.layout[pos[mainAxis]] += mainDim;\n }\n \n // Now that we placed the element, we need to update the variables.\n // We need to do that only for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n if (canSkipFlex) {\n // If we skipped the flex step, then we can't rely on the measuredDims because\n // they weren't computed. This means we can't call getDimWithMargin.\n mainDim += betweenMainDim + getMarginAxis(child, mainAxis) + child.layout.flexBasis;\n crossDim = availableInnerCrossDim;\n } else {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\n \n // The cross dimension is the max of the elements dimension since there\n // can only be one element in that cross dimension.\n crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));\n }\n }\n }\n }\n\n mainDim += trailingPaddingAndBorderMain;\n \n var/*float*/ containerCrossAxis = availableInnerCrossDim;\n if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n // Compute the cross axis from the max cross dimension of the children.\n containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;\n \n if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);\n }\n }\n\n // If there's no flex wrap, the cross dimension is defined by the container.\n if (!isNodeFlexWrap && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY) {\n crossDim = availableInnerCrossDim;\n }\n\n // Clamp to the min/max size specified on the container.\n crossDim = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;\n\n // STEP 7: CROSS-AXIS ALIGNMENT\n // We can skip child alignment if we're just measuring the container.\n if (performLayout) {\n for (i = startOfLineIndex; i < endOfLineIndex; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // If the child is absolutely positioned and has a top/left/bottom/right\n // set, override all the previously computed positions to set it correctly.\n if (isPosDefined(child, leading[crossAxis])) {\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\n getLeadingMargin(child, crossAxis);\n } else {\n child.layout[pos[crossAxis]] = leadingPaddingAndBorderCross +\n getLeadingMargin(child, crossAxis);\n }\n } else {\n var/*float*/ leadingCrossDim = leadingPaddingAndBorderCross;\n\n // For a relative children, we're either using alignItems (parent) or\n // alignSelf (child) in order to determine the position in the cross axis\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n \n // If the child uses align stretch, we need to lay it out one more time, this time\n // forcing the cross-axis size to be the computed cross size for the current line.\n if (alignItem === CSS_ALIGN_STRETCH) {\n childWidth = child.layout.measuredWidth + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);\n childHeight = child.layout.measuredHeight + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);\n var/*bool*/ isCrossSizeDefinite = false;\n \n if (isMainAxisRow) {\n isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);\n childHeight = crossDim;\n } else {\n isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);\n childWidth = crossDim;\n }\n \n // If the child defines a definite size for its cross axis, there's no need to stretch.\n if (!isCrossSizeDefinite) {\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, true, 'stretch');\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n var/*float*/ remainingCrossDim = containerCrossAxis - getDimWithMargin(child, crossAxis);\n\n if (alignItem === CSS_ALIGN_CENTER) {\n leadingCrossDim += remainingCrossDim / 2;\n } else { // CSS_ALIGN_FLEX_END\n leadingCrossDim += remainingCrossDim;\n }\n }\n\n // And we apply the position\n child.layout[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim;\n }\n }\n }\n\n totalLineCrossDim += crossDim;\n maxLineMainDim = fmaxf(maxLineMainDim, mainDim);\n\n // Reset variables for new line.\n lineCount++;\n startOfLineIndex = endOfLineIndex;\n endOfLineIndex = startOfLineIndex;\n }\n\n // STEP 8: MULTI-LINE CONTENT ALIGNMENT\n if (lineCount > 1 && performLayout && !isUndefined(availableInnerCrossDim)) {\n var/*float*/ remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;\n\n var/*float*/ crossDimLead = 0;\n var/*float*/ currentLead = leadingPaddingAndBorderCross;\n\n var/*css_align_t*/ alignContent = getAlignContent(node);\n if (alignContent === CSS_ALIGN_FLEX_END) {\n currentLead += remainingAlignContentDim;\n } else if (alignContent === CSS_ALIGN_CENTER) {\n currentLead += remainingAlignContentDim / 2;\n } else if (alignContent === CSS_ALIGN_STRETCH) {\n if (availableInnerCrossDim > totalLineCrossDim) {\n crossDimLead = (remainingAlignContentDim / lineCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < lineCount; ++i) {\n var/*int*/ startIndex = endIndex;\n var/*int*/ j;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (j = startIndex; j < childCount; ++j) {\n child = node.children[j];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (isLayoutDimDefined(child, crossAxis)) {\n lineHeight = fmaxf(lineHeight,\n child.layout[measuredDim[crossAxis]] + getMarginAxis(child, crossAxis));\n }\n }\n endIndex = j;\n lineHeight += crossDimLead;\n\n if (performLayout) {\n for (j = startIndex; j < endIndex; ++j) {\n child = node.children[j];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n\n var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child);\n if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {\n child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[measuredDim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n childHeight = child.layout[measuredDim[crossAxis]];\n child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;\n } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n // TODO(prenaux): Correctly set the height of items with indefinite\n // (auto) crossAxis dimension.\n }\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n // STEP 9: COMPUTING FINAL DIMENSIONS\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n\n // If the user didn't specify a width or height for the node, set the\n // dimensions based on the children.\n if (measureModeMainDim === CSS_MEASURE_MODE_UNDEFINED) {\n // Clamp the size to the min/max size, if specified, and make sure it\n // doesn't go below the padding and border amount.\n node.layout[measuredDim[mainAxis]] = boundAxis(node, mainAxis, maxLineMainDim);\n } else if (measureModeMainDim === CSS_MEASURE_MODE_AT_MOST) {\n node.layout[measuredDim[mainAxis]] = fmaxf(\n fminf(availableInnerMainDim + paddingAndBorderAxisMain,\n boundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)),\n paddingAndBorderAxisMain);\n }\n\n if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED) {\n // Clamp the size to the min/max size, if specified, and make sure it\n // doesn't go below the padding and border amount.\n node.layout[measuredDim[crossAxis]] = boundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross);\n } else if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n node.layout[measuredDim[crossAxis]] = fmaxf(\n fminf(availableInnerCrossDim + paddingAndBorderAxisCross,\n boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),\n paddingAndBorderAxisCross);\n }\n \n // STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN\n if (performLayout) {\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n if (mainAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||\n mainAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsMainTrailingPos = true;\n }\n\n if (crossAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||\n crossAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsCrossTrailingPos = true;\n }\n\n // Set trailing position if necessary.\n if (needsMainTrailingPos || needsCrossTrailingPos) {\n for (i = 0; i < childCount; ++i) {\n child = node.children[i];\n\n if (needsMainTrailingPos) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n if (needsCrossTrailingPos) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n }\n \n // STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN\n currentAbsoluteChild = firstAbsoluteChild;\n while (currentAbsoluteChild !== undefined) {\n // Now that we know the bounds of the container, perform layout again on the\n // absolutely-positioned children.\n if (performLayout) {\n\n childWidth = CSS_UNDEFINED;\n childHeight = CSS_UNDEFINED;\n\n if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = currentAbsoluteChild.style.width + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);\n } else {\n // If the child doesn't have a specified width, compute the width based on the left/right offsets if they're defined.\n if (isPosDefined(currentAbsoluteChild, CSS_LEFT) && isPosDefined(currentAbsoluteChild, CSS_RIGHT)) {\n childWidth = node.layout.measuredWidth -\n (getLeadingBorder(node, CSS_FLEX_DIRECTION_ROW) + getTrailingBorder(node, CSS_FLEX_DIRECTION_ROW)) -\n (currentAbsoluteChild.style[CSS_LEFT] + currentAbsoluteChild.style[CSS_RIGHT]);\n childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);\n }\n }\n \n if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = currentAbsoluteChild.style.height + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);\n } else {\n // If the child doesn't have a specified height, compute the height based on the top/bottom offsets if they're defined.\n if (isPosDefined(currentAbsoluteChild, CSS_TOP) && isPosDefined(currentAbsoluteChild, CSS_BOTTOM)) {\n childHeight = node.layout.measuredHeight -\n (getLeadingBorder(node, CSS_FLEX_DIRECTION_COLUMN) + getTrailingBorder(node, CSS_FLEX_DIRECTION_COLUMN)) -\n (currentAbsoluteChild.style[CSS_TOP] + currentAbsoluteChild.style[CSS_BOTTOM]);\n childHeight = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN, childHeight);\n }\n }\n\n // If we're still missing one or the other dimension, measure the content.\n if (isUndefined(childWidth) || isUndefined(childHeight)) {\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n \n // According to the spec, if the main size is not definite and the\n // child's inline axis is parallel to the main axis (i.e. it's\n // horizontal), the child should be sized using \"UNDEFINED\" in\n // the main size. Otherwise use \"AT_MOST\" in the cross axis.\n if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) {\n childWidth = availableInnerWidth;\n childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n\n // The W3C spec doesn't say anything about the 'overflow' property,\n // but all major browsers appear to implement the following logic.\n if (getOverflow(node) === CSS_OVERFLOW_HIDDEN) {\n if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) {\n childHeight = availableInnerHeight;\n childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n }\n\n layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'abs-measure');\n childWidth = currentAbsoluteChild.layout.measuredWidth + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);\n childHeight = currentAbsoluteChild.layout.measuredHeight + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);\n }\n \n layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, 'abs-layout');\n \n if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&\n !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {\n currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_ROW]] =\n node.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -\n currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -\n getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);\n }\n \n if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&\n !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {\n currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_COLUMN]] =\n node.layout[measuredDim[CSS_FLEX_DIRECTION_COLUMN]] -\n currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_COLUMN]] -\n getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]);\n }\n }\n\n currentAbsoluteChild = currentAbsoluteChild.nextChild;\n }\n }\n \n function canUseCachedMeasurement(availableWidth, availableHeight,\n marginRow, marginColumn,\n widthMeasureMode, heightMeasureMode,\n cachedLayout) {\n\n // Is it an exact match?\n if (cachedLayout.availableWidth === availableWidth &&\n cachedLayout.availableHeight === availableHeight &&\n cachedLayout.widthMeasureMode === widthMeasureMode &&\n cachedLayout.heightMeasureMode === heightMeasureMode) {\n return true;\n }\n \n // If the width is an exact match, try a fuzzy match on the height.\n if (cachedLayout.availableWidth === availableWidth &&\n cachedLayout.widthMeasureMode === widthMeasureMode &&\n heightMeasureMode === CSS_MEASURE_MODE_EXACTLY &&\n availableHeight - marginColumn === cachedLayout.computedHeight) {\n return true;\n }\n \n // If the height is an exact match, try a fuzzy match on the width.\n if (cachedLayout.availableHeight === availableHeight &&\n cachedLayout.heightMeasureMode === heightMeasureMode &&\n widthMeasureMode === CSS_MEASURE_MODE_EXACTLY &&\n availableWidth - marginRow === cachedLayout.computedWidth) {\n return true;\n }\n\n return false;\n }\n \n //\n // This is a wrapper around the layoutNodeImpl function. It determines\n // whether the layout request is redundant and can be skipped.\n //\n // Parameters:\n // Input parameters are the same as layoutNodeImpl (see above)\n // Return parameter is true if layout was performed, false if skipped\n //\n function layoutNodeInternal(node, availableWidth, availableHeight, parentDirection,\n widthMeasureMode, heightMeasureMode, performLayout, reason) {\n var layout = node.layout;\n\n var needToVisitNode = (node.isDirty && layout.generationCount !== gCurrentGenerationCount) ||\n layout.lastParentDirection !== parentDirection;\n\n if (needToVisitNode) {\n // Invalidate the cached results.\n if (layout.cachedMeasurements !== undefined) {\n layout.cachedMeasurements = []; \n }\n if (layout.cachedLayout !== undefined) {\n layout.cachedLayout.widthMeasureMode = undefined;\n layout.cachedLayout.heightMeasureMode = undefined;\n }\n }\n \n var i;\n var len;\n var cachedResults;\n \n // Determine whether the results are already cached. We maintain a separate\n // cache for layouts and measurements. A layout operation modifies the positions\n // and dimensions for nodes in the subtree. The algorithm assumes that each node\n // gets layed out a maximum of one time per tree layout, but multiple measurements\n // may be required to resolve all of the flex dimensions.\n // We handle nodes with measure functions specially here because they are the most\n // expensive to measure, so it's worth avoiding redundant measurements if at all possible.\n if (isMeasureDefined(node)) {\n var marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n var marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n \n // First, try to use the layout cache.\n if (layout.cachedLayout &&\n canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,\n widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {\n cachedResults = layout.cachedLayout;\n } else if (layout.cachedMeasurements) {\n // Try to use the measurement cache.\n for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {\n if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,\n widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {\n cachedResults = layout.cachedMeasurements[i];\n break;\n }\n }\n }\n } else if (performLayout) {\n if (layout.cachedLayout &&\n layout.cachedLayout.availableWidth === availableWidth &&\n layout.cachedLayout.availableHeight === availableHeight &&\n layout.cachedLayout.widthMeasureMode === widthMeasureMode &&\n layout.cachedLayout.heightMeasureMode === heightMeasureMode) {\n cachedResults = layout.cachedLayout;\n }\n } else if (layout.cachedMeasurements) {\n for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {\n if (layout.cachedMeasurements[i].availableWidth === availableWidth &&\n layout.cachedMeasurements[i].availableHeight === availableHeight &&\n layout.cachedMeasurements[i].widthMeasureMode === widthMeasureMode &&\n layout.cachedMeasurements[i].heightMeasureMode === heightMeasureMode) {\n cachedResults = layout.cachedMeasurements[i];\n break;\n }\n }\n }\n \n if (!needToVisitNode && cachedResults !== undefined) {\n layout.measureWidth = cachedResults.computedWidth;\n layout.measureHeight = cachedResults.computedHeight;\n } else {\n layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);\n layout.lastParentDirection = parentDirection;\n \n if (cachedResults === undefined) {\n var newCacheEntry;\n if (performLayout) {\n // Use the single layout cache entry.\n if (layout.cachedLayout === undefined) {\n layout.cachedLayout = {};\n }\n newCacheEntry = layout.cachedLayout;\n } else {\n // Allocate a new measurement cache entry.\n if (layout.cachedMeasurements === undefined) {\n layout.cachedMeasurements = [];\n }\n newCacheEntry = {};\n layout.cachedMeasurements.push(newCacheEntry);\n }\n \n newCacheEntry.availableWidth = availableWidth;\n newCacheEntry.availableHeight = availableHeight;\n newCacheEntry.widthMeasureMode = widthMeasureMode;\n newCacheEntry.heightMeasureMode = heightMeasureMode;\n newCacheEntry.computedWidth = layout.measuredWidth;\n newCacheEntry.computedHeight = layout.measuredHeight;\n }\n }\n \n if (performLayout) {\n node.layout.width = node.layout.measuredWidth;\n node.layout.height = node.layout.measuredHeight;\n layout.shouldUpdate = true;\n }\n \n layout.generationCount = gCurrentGenerationCount;\n return (needToVisitNode || cachedResults === undefined);\n }\n \n function layoutNode(node, availableWidth, availableHeight, parentDirection) {\n // Increment the generation count. This will force the recursive routine to visit\n // all dirty nodes at least once. Subsequent visits will be skipped if the input\n // parameters don't change.\n gCurrentGenerationCount++;\n \n // If the caller didn't specify a height/width, use the dimensions\n // specified in the style.\n if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {\n availableWidth = node.style.width + getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n }\n if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {\n availableHeight = node.style.height + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n \n var widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n var heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n \n if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, 'initial')) {\n setPosition(node, node.layout.direction);\n }\n }\n\n return {\n layoutNodeImpl: layoutNodeImpl,\n computeLayout: layoutNode,\n fillNodes: fillNodes,\n canUseCachedMeasurement: canUseCachedMeasurement\n };\n})();\n\n// This module export is only used for the purposes of unit testing this file. When\n// the library is packaged this file is included within css-layout.js which forms\n// the public API.\nif (typeof exports === 'object') {\n module.exports = computeLayout;\n}\n\n\n return function(node) {\n /*eslint-disable */\n // disabling ESLint because this code relies on the above include\n computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n /*eslint-enable */\n };\n}));\n"]}
\ No newline at end of file
+{"version":3,"sources":["css-layout.js"],"names":["root","factory","define","amd","exports","module","computeLayout","this","fillNodes","node","layout","isDirty","width","undefined","height","top","left","right","bottom","style","children","measure","length","Error","forEach","isUndefined","value","Number","isNaN","isRowDirection","flexDirection","CSS_FLEX_DIRECTION_ROW","CSS_FLEX_DIRECTION_ROW_REVERSE","isColumnDirection","CSS_FLEX_DIRECTION_COLUMN","CSS_FLEX_DIRECTION_COLUMN_REVERSE","getFlex","flex","isFlexBasisAuto","POSITIVE_FLEX_IS_AUTO","getFlexGrowFactor","getFlexShrinkFactor","getLeadingMargin","axis","marginStart","marginLeft","marginRight","marginTop","marginBottom","margin","getTrailingMargin","marginEnd","getLeadingPadding","paddingStart","paddingLeft","paddingRight","paddingTop","paddingBottom","padding","getTrailingPadding","paddingEnd","getLeadingBorder","borderStartWidth","borderLeftWidth","borderRightWidth","borderTopWidth","borderBottomWidth","borderWidth","getTrailingBorder","borderEndWidth","getLeadingPaddingAndBorder","getTrailingPaddingAndBorder","getMarginAxis","getPaddingAndBorderAxis","getJustifyContent","justifyContent","getAlignContent","alignContent","getAlignItem","child","alignSelf","alignItems","resolveAxis","direction","CSS_DIRECTION_RTL","resolveDirection","parentDirection","CSS_DIRECTION_INHERIT","CSS_DIRECTION_LTR","getFlexDirection","getCrossFlexDirection","getPositionType","position","CSS_POSITION_RELATIVE","getOverflow","overflow","CSS_OVERFLOW_VISIBLE","isFlex","isFlexWrap","flexWrap","getDimWithMargin","measuredDim","isStyleDimDefined","dim","isLayoutDimDefined","isPosDefined","pos","isMeasureDefined","getPosition","boundAxisWithinMinAndMax","min","row","minWidth","row-reverse","column","minHeight","column-reverse","max","maxWidth","maxHeight","boundValue","fminf","a","b","fmaxf","boundAxis","setTrailingPosition","size","CSS_POSITION_ABSOLUTE","trailing","getRelativePosition","leading","setPosition","mainAxis","crossAxis","assert","condition","message","layoutNodeImpl","availableWidth","availableHeight","widthMeasureMode","heightMeasureMode","performLayout","CSS_MEASURE_MODE_UNDEFINED","paddingAndBorderAxisRow","paddingAndBorderAxisColumn","marginAxisRow","marginAxisColumn","innerWidth","innerHeight","CSS_MEASURE_MODE_EXACTLY","measuredWidth","measuredHeight","measureDim","CSS_MEASURE_MODE_AT_MOST","childCount","i","childWidth","childHeight","childWidthMeasureMode","childHeightMeasureMode","isMainAxisRow","isNodeFlexWrap","firstAbsoluteChild","currentAbsoluteChild","leadingPaddingAndBorderMain","trailingPaddingAndBorderMain","leadingPaddingAndBorderCross","paddingAndBorderAxisMain","paddingAndBorderAxisCross","measureModeMainDim","measureModeCrossDim","availableInnerWidth","availableInnerHeight","availableInnerMainDim","availableInnerCrossDim","childDirection","nextChild","flexBasis","CSS_UNDEFINED","CSS_OVERFLOW_HIDDEN","layoutNodeInternal","startOfLineIndex","endOfLineIndex","lineCount","totalLineCrossDim","maxLineMainDim","itemsOnLine","sizeConsumedOnCurrentLine","totalFlexGrowFactors","totalFlexShrinkScaledFactors","firstRelativeChild","currentRelativeChild","lineIndex","outerFlexBasis","canSkipFlex","leadingMainDim","betweenMainDim","remainingFreeSpace","originalRemainingFreeSpace","deltaFreeSpace","childFlexBasis","flexShrinkScaledFactor","flexGrowFactor","baseMainSize","boundMainSize","deltaFlexShrinkScaledFactors","deltaFlexGrowFactors","updatedMainSize","requiresStretchLayout","CSS_ALIGN_STRETCH","CSS_JUSTIFY_FLEX_START","CSS_JUSTIFY_CENTER","CSS_JUSTIFY_FLEX_END","CSS_JUSTIFY_SPACE_BETWEEN","CSS_JUSTIFY_SPACE_AROUND","mainDim","crossDim","containerCrossAxis","leadingCrossDim","alignItem","isCrossSizeDefinite","CSS_ALIGN_FLEX_START","remainingCrossDim","CSS_ALIGN_CENTER","remainingAlignContentDim","crossDimLead","currentLead","CSS_ALIGN_FLEX_END","endIndex","j","startIndex","lineHeight","alignContentAlignItem","needsMainTrailingPos","needsCrossTrailingPos","CSS_LEFT","CSS_RIGHT","CSS_TOP","CSS_BOTTOM","canUseCachedMeasurement","marginRow","marginColumn","cachedLayout","computedHeight","computedWidth","reason","needToVisitNode","generationCount","gCurrentGenerationCount","lastParentDirection","cachedMeasurements","len","cachedResults","newCacheEntry","push","measureWidth","measureHeight","shouldUpdate","layoutNode"],"mappings":"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","file":"css-layout.min.js","sourcesContent":["// UMD (Universal Module Definition)\n// See https://github.com/umdjs/umd for reference\n//\n// This file uses the following specific UMD implementation:\n// https://github.com/umdjs/umd/blob/master/templates/returnExports.js\n(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n // AMD. Register as an anonymous module.\n define([], factory);\n } else if (typeof exports === 'object') {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory();\n } else {\n // Browser globals (root is window)\n root.computeLayout = factory();\n }\n}(this, function() {\n /**\n * Copyright (c) 2014, Facebook, Inc.\n * All rights reserved.\n *\n * This source code is licensed under the BSD-style license found in the\n * LICENSE file in the root directory of this source tree. An additional grant\n * of patent rights can be found in the PATENTS file in the same directory.\n */\n\nvar computeLayout = (function() {\n\n var POSITIVE_FLEX_IS_AUTO = false;\n\n var gCurrentGenerationCount = 0;\n\n var CSS_UNDEFINED;\n\n var CSS_LEFT = 'left';\n var CSS_TOP = 'top';\n var CSS_RIGHT = 'right';\n var CSS_BOTTOM = 'bottom';\n\n var CSS_DIRECTION_INHERIT = 'inherit';\n var CSS_DIRECTION_LTR = 'ltr';\n var CSS_DIRECTION_RTL = 'rtl';\n\n var CSS_FLEX_DIRECTION_ROW = 'row';\n var CSS_FLEX_DIRECTION_ROW_REVERSE = 'row-reverse';\n var CSS_FLEX_DIRECTION_COLUMN = 'column';\n var CSS_FLEX_DIRECTION_COLUMN_REVERSE = 'column-reverse';\n\n var CSS_JUSTIFY_FLEX_START = 'flex-start';\n var CSS_JUSTIFY_CENTER = 'center';\n var CSS_JUSTIFY_FLEX_END = 'flex-end';\n var CSS_JUSTIFY_SPACE_BETWEEN = 'space-between';\n var CSS_JUSTIFY_SPACE_AROUND = 'space-around';\n\n var CSS_ALIGN_FLEX_START = 'flex-start';\n var CSS_ALIGN_CENTER = 'center';\n var CSS_ALIGN_FLEX_END = 'flex-end';\n var CSS_ALIGN_STRETCH = 'stretch';\n\n var CSS_POSITION_RELATIVE = 'relative';\n var CSS_POSITION_ABSOLUTE = 'absolute';\n\n var CSS_OVERFLOW_VISIBLE = 'visible';\n var CSS_OVERFLOW_HIDDEN = 'hidden';\n\n var CSS_MEASURE_MODE_UNDEFINED = 'undefined';\n var CSS_MEASURE_MODE_EXACTLY = 'exactly';\n var CSS_MEASURE_MODE_AT_MOST = 'at-most';\n\n var leading = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var trailing = {\n 'row': 'right',\n 'row-reverse': 'left',\n 'column': 'bottom',\n 'column-reverse': 'top'\n };\n var pos = {\n 'row': 'left',\n 'row-reverse': 'right',\n 'column': 'top',\n 'column-reverse': 'bottom'\n };\n var dim = {\n 'row': 'width',\n 'row-reverse': 'width',\n 'column': 'height',\n 'column-reverse': 'height'\n };\n var measuredDim = {\n 'row': 'measuredWidth',\n 'row-reverse': 'measuredWidth',\n 'column': 'measuredHeight',\n 'column-reverse': 'measuredHeight'\n };\n\n // When transpiled to Java / C the node type has layout, children and style\n // properties. For the JavaScript version this function adds these properties\n // if they don't already exist.\n function fillNodes(node) {\n if (!node.layout || node.isDirty) {\n node.layout = {\n width: undefined,\n height: undefined,\n top: 0,\n left: 0,\n right: 0,\n bottom: 0\n };\n }\n\n if (!node.style) {\n node.style = {};\n }\n\n if (!node.children) {\n node.children = [];\n }\n\n if (node.style.measure && node.children && node.children.length) {\n throw new Error('Using custom measure function is supported only for leaf nodes.');\n }\n\n node.children.forEach(fillNodes);\n return node;\n }\n\n function isUndefined(value) {\n return value === undefined || Number.isNaN(value);\n }\n\n function isRowDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_ROW ||\n flexDirection === CSS_FLEX_DIRECTION_ROW_REVERSE;\n }\n\n function isColumnDirection(flexDirection) {\n return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||\n flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;\n }\n\n function getFlex(node) {\n if (node.style.flex === undefined) {\n return 0;\n }\n return node.style.flex;\n }\n\n function isFlexBasisAuto(node) {\n if (POSITIVE_FLEX_IS_AUTO) {\n // All flex values are auto.\n return true;\n } else {\n // A flex value > 0 implies a basis of zero.\n return getFlex(node) <= 0;\n }\n }\n\n function getFlexGrowFactor(node) {\n // Flex grow is implied by positive values for flex.\n if (getFlex(node) > 0) {\n return getFlex(node);\n }\n return 0;\n }\n\n function getFlexShrinkFactor(node) {\n if (POSITIVE_FLEX_IS_AUTO) {\n // A flex shrink factor of 1 is implied by non-zero values for flex.\n if (getFlex(node) !== 0) {\n return 1;\n }\n } else {\n // A flex shrink factor of 1 is implied by negative values for flex.\n if (getFlex(node) < 0) {\n return 1;\n }\n }\n return 0;\n }\n\n function getLeadingMargin(node, axis) {\n if (node.style.marginStart !== undefined && isRowDirection(axis)) {\n return node.style.marginStart;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.marginLeft; break;\n case 'row-reverse': value = node.style.marginRight; break;\n case 'column': value = node.style.marginTop; break;\n case 'column-reverse': value = node.style.marginBottom; break;\n }\n\n if (value !== undefined) {\n return value;\n }\n\n if (node.style.margin !== undefined) {\n return node.style.margin;\n }\n\n return 0;\n }\n\n function getTrailingMargin(node, axis) {\n if (node.style.marginEnd !== undefined && isRowDirection(axis)) {\n return node.style.marginEnd;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.marginRight; break;\n case 'row-reverse': value = node.style.marginLeft; break;\n case 'column': value = node.style.marginBottom; break;\n case 'column-reverse': value = node.style.marginTop; break;\n }\n\n if (value != null) {\n return value;\n }\n\n if (node.style.margin !== undefined) {\n return node.style.margin;\n }\n\n return 0;\n }\n\n function getLeadingPadding(node, axis) {\n if (node.style.paddingStart !== undefined && node.style.paddingStart >= 0\n && isRowDirection(axis)) {\n return node.style.paddingStart;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.paddingLeft; break;\n case 'row-reverse': value = node.style.paddingRight; break;\n case 'column': value = node.style.paddingTop; break;\n case 'column-reverse': value = node.style.paddingBottom; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.padding !== undefined && node.style.padding >= 0) {\n return node.style.padding;\n }\n\n return 0;\n }\n\n function getTrailingPadding(node, axis) {\n if (node.style.paddingEnd !== undefined && node.style.paddingEnd >= 0\n && isRowDirection(axis)) {\n return node.style.paddingEnd;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.paddingRight; break;\n case 'row-reverse': value = node.style.paddingLeft; break;\n case 'column': value = node.style.paddingBottom; break;\n case 'column-reverse': value = node.style.paddingTop; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.padding !== undefined && node.style.padding >= 0) {\n return node.style.padding;\n }\n\n return 0;\n }\n\n function getLeadingBorder(node, axis) {\n if (node.style.borderStartWidth !== undefined && node.style.borderStartWidth >= 0\n && isRowDirection(axis)) {\n return node.style.borderStartWidth;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.borderLeftWidth; break;\n case 'row-reverse': value = node.style.borderRightWidth; break;\n case 'column': value = node.style.borderTopWidth; break;\n case 'column-reverse': value = node.style.borderBottomWidth; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {\n return node.style.borderWidth;\n }\n\n return 0;\n }\n\n function getTrailingBorder(node, axis) {\n if (node.style.borderEndWidth !== undefined && node.style.borderEndWidth >= 0\n && isRowDirection(axis)) {\n return node.style.borderEndWidth;\n }\n\n var value = null;\n switch (axis) {\n case 'row': value = node.style.borderRightWidth; break;\n case 'row-reverse': value = node.style.borderLeftWidth; break;\n case 'column': value = node.style.borderBottomWidth; break;\n case 'column-reverse': value = node.style.borderTopWidth; break;\n }\n\n if (value != null && value >= 0) {\n return value;\n }\n\n if (node.style.borderWidth !== undefined && node.style.borderWidth >= 0) {\n return node.style.borderWidth;\n }\n\n return 0;\n }\n\n function getLeadingPaddingAndBorder(node, axis) {\n return getLeadingPadding(node, axis) + getLeadingBorder(node, axis);\n }\n\n function getTrailingPaddingAndBorder(node, axis) {\n return getTrailingPadding(node, axis) + getTrailingBorder(node, axis);\n }\n\n function getMarginAxis(node, axis) {\n return getLeadingMargin(node, axis) + getTrailingMargin(node, axis);\n }\n\n function getPaddingAndBorderAxis(node, axis) {\n return getLeadingPaddingAndBorder(node, axis) +\n getTrailingPaddingAndBorder(node, axis);\n }\n\n function getJustifyContent(node) {\n if (node.style.justifyContent) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if (node.style.alignContent) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if (child.style.alignSelf) {\n return child.style.alignSelf;\n }\n if (node.style.alignItems) {\n return node.style.alignItems;\n }\n return 'stretch';\n }\n\n function resolveAxis(axis, direction) {\n if (direction === CSS_DIRECTION_RTL) {\n if (axis === CSS_FLEX_DIRECTION_ROW) {\n return CSS_FLEX_DIRECTION_ROW_REVERSE;\n } else if (axis === CSS_FLEX_DIRECTION_ROW_REVERSE) {\n return CSS_FLEX_DIRECTION_ROW;\n }\n }\n\n return axis;\n }\n\n function resolveDirection(node, parentDirection) {\n var direction;\n if (node.style.direction) {\n direction = node.style.direction;\n } else {\n direction = CSS_DIRECTION_INHERIT;\n }\n\n if (direction === CSS_DIRECTION_INHERIT) {\n direction = (parentDirection === undefined ? CSS_DIRECTION_LTR : parentDirection);\n }\n\n return direction;\n }\n\n function getFlexDirection(node) {\n if (node.style.flexDirection) {\n return node.style.flexDirection;\n }\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n\n function getCrossFlexDirection(flexDirection, direction) {\n if (isColumnDirection(flexDirection)) {\n return resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n } else {\n return CSS_FLEX_DIRECTION_COLUMN;\n }\n }\n\n function getPositionType(node) {\n if (node.style.position) {\n return node.style.position;\n }\n return CSS_POSITION_RELATIVE;\n }\n\n function getOverflow(node) {\n if (node.style.overflow) {\n return node.style.overflow;\n }\n return CSS_OVERFLOW_VISIBLE;\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n node.style.flex !== undefined && node.style.flex !== 0\n );\n }\n\n function isFlexWrap(node) {\n return node.style.flexWrap === 'wrap';\n }\n\n function getDimWithMargin(node, axis) {\n return node.layout[measuredDim[axis]] + getMarginAxis(node, axis);\n }\n\n function isStyleDimDefined(node, axis) {\n return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;\n }\n\n function isLayoutDimDefined(node, axis) {\n return node.layout[measuredDim[axis]] !== undefined && node.layout[measuredDim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return node.style[pos] !== undefined;\n }\n\n function isMeasureDefined(node) {\n return node.style.measure !== undefined;\n }\n\n function getPosition(node, pos) {\n if (node.style[pos] !== undefined) {\n return node.style[pos];\n }\n return 0;\n }\n\n function boundAxisWithinMinAndMax(node, axis, value) {\n var min = {\n 'row': node.style.minWidth,\n 'row-reverse': node.style.minWidth,\n 'column': node.style.minHeight,\n 'column-reverse': node.style.minHeight\n }[axis];\n\n var max = {\n 'row': node.style.maxWidth,\n 'row-reverse': node.style.maxWidth,\n 'column': node.style.maxHeight,\n 'column-reverse': node.style.maxHeight\n }[axis];\n\n var boundValue = value;\n if (max !== undefined && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (min !== undefined && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n\n function fminf(a, b) {\n if (a < b) {\n return a;\n }\n return b;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n\n // Like boundAxisWithinMinAndMax but also ensures that the value doesn't go below the\n // padding and border amount.\n function boundAxis(node, axis, value) {\n return fmaxf(boundAxisWithinMinAndMax(node, axis, value), getPaddingAndBorderAxis(node, axis));\n }\n\n function setTrailingPosition(node, child, axis) {\n var size = (getPositionType(child) === CSS_POSITION_ABSOLUTE) ?\n 0 :\n child.layout[measuredDim[axis]];\n child.layout[trailing[axis]] = node.layout[measuredDim[axis]] - size - child.layout[pos[axis]];\n }\n\n // If both left and right are defined, then use left. Otherwise return\n // +left or -right depending on which is defined.\n function getRelativePosition(node, axis) {\n if (node.style[leading[axis]] !== undefined) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n\n function setPosition(node, direction) {\n var mainAxis = resolveAxis(getFlexDirection(node), direction);\n var crossAxis = getCrossFlexDirection(mainAxis, direction);\n\n node.layout[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +\n getRelativePosition(node, mainAxis);\n node.layout[leading[crossAxis]] = getLeadingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n node.layout[trailing[crossAxis]] = getTrailingMargin(node, crossAxis) +\n getRelativePosition(node, crossAxis);\n }\n\n function assert(condition, message) {\n if (!condition) {\n throw new Error(message);\n }\n }\n\n //\n // This is the main routine that implements a subset of the flexbox layout algorithm\n // described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.\n //\n // Limitations of this algorithm, compared to the full standard:\n // * Display property is always assumed to be 'flex' except for Text nodes, which\n // are assumed to be 'inline-flex'.\n // * The 'zIndex' property (or any form of z ordering) is not supported. Nodes are\n // stacked in document order.\n // * The 'order' property is not supported. The order of flex items is always defined\n // by document order.\n // * The 'visibility' property is always assumed to be 'visible'. Values of 'collapse'\n // and 'hidden' are not supported.\n // * The 'wrap' property supports only 'nowrap' (which is the default) or 'wrap'. The\n // rarely-used 'wrap-reverse' is not supported.\n // * Rather than allowing arbitrary combinations of flexGrow, flexShrink and\n // flexBasis, this algorithm supports only the three most common combinations:\n // flex: 0 is equiavlent to flex: 0 0 auto\n // flex: n (where n is a positive value) is equivalent to flex: n 1 auto\n // If POSITIVE_FLEX_IS_AUTO is 0, then it is equivalent to flex: n 0 0\n // This is faster because the content doesn't need to be measured, but it's\n // less flexible because the basis is always 0 and can't be overriden with\n // the width/height attributes.\n // flex: -1 (or any negative value) is equivalent to flex: 0 1 auto\n // * Margins cannot be specified as 'auto'. They must be specified in terms of pixel\n // values, and the default value is 0.\n // * The 'baseline' value is not supported for alignItems and alignSelf properties.\n // * Values of width, maxWidth, minWidth, height, maxHeight and minHeight must be\n // specified as pixel values, not as percentages.\n // * There is no support for calculation of dimensions based on intrinsic aspect ratios\n // (e.g. images).\n // * There is no support for forced breaks.\n // * It does not support vertical inline directions (top-to-bottom or bottom-to-top text).\n //\n // Deviations from standard:\n // * Section 4.5 of the spec indicates that all flex items have a default minimum\n // main size. For text blocks, for example, this is the width of the widest word.\n // Calculating the minimum width is expensive, so we forego it and assume a default\n // minimum main size of 0.\n // * Min/Max sizes in the main axis are not honored when resolving flexible lengths.\n // * The spec indicates that the default value for 'flexDirection' is 'row', but\n // the algorithm below assumes a default of 'column'.\n //\n // Input parameters:\n // - node: current node to be sized and layed out\n // - availableWidth & availableHeight: available size to be used for sizing the node\n // or CSS_UNDEFINED if the size is not available; interpretation depends on layout\n // flags\n // - parentDirection: the inline (text) direction within the parent (left-to-right or\n // right-to-left)\n // - widthMeasureMode: indicates the sizing rules for the width (see below for explanation)\n // - heightMeasureMode: indicates the sizing rules for the height (see below for explanation)\n // - performLayout: specifies whether the caller is interested in just the dimensions\n // of the node or it requires the entire node and its subtree to be layed out\n // (with final positions)\n //\n // Details:\n // This routine is called recursively to lay out subtrees of flexbox elements. It uses the\n // information in node.style, which is treated as a read-only input. It is responsible for\n // setting the layout.direction and layout.measured_dimensions fields for the input node as well\n // as the layout.position and layout.line_index fields for its child nodes. The\n // layout.measured_dimensions field includes any border or padding for the node but does\n // not include margins.\n //\n // The spec describes four different layout modes: \"fill available\", \"max content\", \"min content\",\n // and \"fit content\". Of these, we don't use \"min content\" because we don't support default\n // minimum main sizes (see above for details). Each of our measure modes maps to a layout mode\n // from the spec (https://www.w3.org/TR/css3-sizing/#terms):\n // - CSS_MEASURE_MODE_UNDEFINED: max content\n // - CSS_MEASURE_MODE_EXACTLY: fill available\n // - CSS_MEASURE_MODE_AT_MOST: fit content\n //\n // When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of\n // undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.\n //\n function layoutNodeImpl(node, availableWidth, availableHeight, /*css_direction_t*/parentDirection, widthMeasureMode, heightMeasureMode, performLayout) {\n assert(isUndefined(availableWidth) ? widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');\n assert(isUndefined(availableHeight) ? heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');\n\n var/*float*/ paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);\n var/*float*/ paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n var/*float*/ marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n var/*float*/ marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n\n // Set the resolved resolution in the node's layout.\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\n node.layout.direction = direction;\n\n // For content (text) nodes, determine the dimensions based on the text contents.\n if (isMeasureDefined(node)) {\n var/*float*/ innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;\n var/*float*/ innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;\n\n if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {\n\n // Don't bother sizing the text if both dimensions are already defined.\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n } else if (innerWidth <= 0 || innerHeight <= 0) {\n\n // Don't bother sizing the text if there's no horizontal or vertical space.\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n } else {\n\n // Measure the text under the current constraints.\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n innerWidth,\n widthMeasureMode,\n innerHeight,\n heightMeasureMode\n );\n\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW,\n (widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n measureDim.width + paddingAndBorderAxisRow :\n availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN,\n (heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n measureDim.height + paddingAndBorderAxisColumn :\n availableHeight - marginAxisColumn);\n }\n\n return;\n }\n\n // For nodes with no children, use the available values if they were provided, or\n // the minimum size as indicated by the padding and border sizes.\n var/*int*/ childCount = node.children.length;\n if (childCount === 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW,\n (widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED || widthMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n paddingAndBorderAxisRow :\n availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN,\n (heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED || heightMeasureMode === CSS_MEASURE_MODE_AT_MOST) ?\n paddingAndBorderAxisColumn :\n availableHeight - marginAxisColumn);\n return;\n }\n\n // If we're not being asked to perform a full layout, we can handle a number of common\n // cases here without incurring the cost of the remaining function.\n if (!performLayout) {\n // If we're being asked to size the content with an at most constraint but there is no available width,\n // the measurement will always be zero.\n if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0 &&\n heightMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n return;\n }\n\n if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));\n return;\n }\n\n if (heightMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableHeight <= 0) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, isUndefined(availableWidth) ? 0 : (availableWidth - marginAxisRow));\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);\n return;\n }\n\n // If we're being asked to use an exact width/height, there's no need to measure the children.\n if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n return;\n }\n }\n\n // STEP 1: CALCULATE VALUES FOR REMAINDER OF ALGORITHM\n var/*(c)!css_flex_direction_t*//*(java)!int*/ mainAxis = resolveAxis(getFlexDirection(node), direction);\n var/*(c)!css_flex_direction_t*//*(java)!int*/ crossAxis = getCrossFlexDirection(mainAxis, direction);\n var/*bool*/ isMainAxisRow = isRowDirection(mainAxis);\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n var/*bool*/ isNodeFlexWrap = isFlexWrap(node);\n\n var/*css_node_t**/ firstAbsoluteChild = undefined;\n var/*css_node_t**/ currentAbsoluteChild = undefined;\n\n var/*float*/ leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(node, mainAxis);\n var/*float*/ trailingPaddingAndBorderMain = getTrailingPaddingAndBorder(node, mainAxis);\n var/*float*/ leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);\n var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);\n var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);\n\n var/*css_measure_mode_t*/ measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;\n var/*css_measure_mode_t*/ measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;\n\n // STEP 2: DETERMINE AVAILABLE SIZE IN MAIN AND CROSS DIRECTIONS\n var/*float*/ availableInnerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;\n var/*float*/ availableInnerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;\n var/*float*/ availableInnerMainDim = isMainAxisRow ? availableInnerWidth : availableInnerHeight;\n var/*float*/ availableInnerCrossDim = isMainAxisRow ? availableInnerHeight : availableInnerWidth;\n\n // STEP 3: DETERMINE FLEX BASIS FOR EACH ITEM\n var/*css_node_t**/ child;\n var/*int*/ i;\n var/*float*/ childWidth;\n var/*float*/ childHeight;\n var/*css_measure_mode_t*/ childWidthMeasureMode;\n var/*css_measure_mode_t*/ childHeightMeasureMode;\n for (i = 0; i < childCount; i++) {\n child = node.children[i];\n\n if (performLayout) {\n // Set the initial position (relative to the parent).\n var/*css_direction_t*/ childDirection = resolveDirection(child, direction);\n setPosition(child, childDirection);\n }\n\n // Absolute-positioned children don't participate in flex layout. Add them\n // to a list that we can process later.\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n\n // Store a private linked list of absolutely positioned children\n // so that we can efficiently traverse them later.\n if (firstAbsoluteChild === undefined) {\n firstAbsoluteChild = child;\n }\n if (currentAbsoluteChild !== undefined) {\n currentAbsoluteChild.nextChild = child;\n }\n currentAbsoluteChild = child;\n child.nextChild = undefined;\n } else {\n\n if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {\n\n // The width is definite, so use that as the flex basis.\n child.layout.flexBasis = fmaxf(child.style.width, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));\n } else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {\n\n // The height is definite, so use that as the flex basis.\n child.layout.flexBasis = fmaxf(child.style.height, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));\n } else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {\n\n // If the basis isn't 'auto', it is assumed to be zero.\n child.layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));\n } else {\n\n // Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).\n childWidth = CSS_UNDEFINED;\n childHeight = CSS_UNDEFINED;\n childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;\n childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;\n\n if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = child.style.width + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = child.style.height + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n\n // According to the spec, if the main size is not definite and the\n // child's inline axis is parallel to the main axis (i.e. it's\n // horizontal), the child should be sized using \"UNDEFINED\" in\n // the main size. Otherwise use \"AT_MOST\" in the cross axis.\n if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) {\n childWidth = availableInnerWidth;\n childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n\n // The W3C spec doesn't say anything about the 'overflow' property,\n // but all major browsers appear to implement the following logic.\n if (getOverflow(node) === CSS_OVERFLOW_HIDDEN) {\n if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) {\n childHeight = availableInnerHeight;\n childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n }\n\n // Measure the child\n layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'measure');\n\n child.layout.flexBasis = fmaxf(isMainAxisRow ? child.layout.measuredWidth : child.layout.measuredHeight, getPaddingAndBorderAxis(child, mainAxis));\n }\n }\n }\n\n // STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES\n\n // Indexes of children that represent the first and last items in the line.\n var/*int*/ startOfLineIndex = 0;\n var/*int*/ endOfLineIndex = 0;\n\n // Number of lines.\n var/*int*/ lineCount = 0;\n\n // Accumulated cross dimensions of all lines so far.\n var/*float*/ totalLineCrossDim = 0;\n\n // Max main dimension of all the lines.\n var/*float*/ maxLineMainDim = 0;\n\n while (endOfLineIndex < childCount) {\n\n // Number of items on the currently line. May be different than the difference\n // between start and end indicates because we skip over absolute-positioned items.\n var/*int*/ itemsOnLine = 0;\n\n // sizeConsumedOnCurrentLine is accumulation of the dimensions and margin\n // of all the children on the current line. This will be used in order to\n // either set the dimensions of the node if none already exist or to compute\n // the remaining space left for the flexible children.\n var/*float*/ sizeConsumedOnCurrentLine = 0;\n\n var/*float*/ totalFlexGrowFactors = 0;\n var/*float*/ totalFlexShrinkScaledFactors = 0;\n\n i = startOfLineIndex;\n\n // Maintain a linked list of the child nodes that can shrink and/or grow.\n var/*css_node_t**/ firstRelativeChild = undefined;\n var/*css_node_t**/ currentRelativeChild = undefined;\n\n // Add items to the current line until it's full or we run out of items.\n while (i < childCount) {\n child = node.children[i];\n child.lineIndex = lineCount;\n\n if (getPositionType(child) !== CSS_POSITION_ABSOLUTE) {\n var/*float*/ outerFlexBasis = child.layout.flexBasis + getMarginAxis(child, mainAxis);\n\n // If this is a multi-line flow and this item pushes us over the available size, we've\n // hit the end of the current line. Break out of the loop and lay out the current line.\n if (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {\n break;\n }\n\n sizeConsumedOnCurrentLine += outerFlexBasis;\n itemsOnLine++;\n\n if (isFlex(child)) {\n totalFlexGrowFactors += getFlexGrowFactor(child);\n\n // Unlike the grow factor, the shrink factor is scaled relative to the child\n // dimension.\n totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;\n }\n\n // Store a private linked list of children that need to be layed out.\n if (firstRelativeChild === undefined) {\n firstRelativeChild = child;\n }\n if (currentRelativeChild !== undefined) {\n currentRelativeChild.nextChild = child;\n }\n currentRelativeChild = child;\n child.nextChild = undefined;\n }\n\n i++;\n endOfLineIndex++;\n }\n\n // If we don't need to measure the cross axis, we can skip the entire flex step.\n var/*bool*/ canSkipFlex = !performLayout && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY;\n\n // In order to position the elements in the main axis, we have two\n // controls. The space between the beginning and the first element\n // and the space between each two elements.\n var/*float*/ leadingMainDim = 0;\n var/*float*/ betweenMainDim = 0;\n\n // STEP 5: RESOLVING FLEXIBLE LENGTHS ON MAIN AXIS\n // Calculate the remaining available space that needs to be allocated.\n // If the main dimension size isn't known, it is computed based on\n // the line length, so there's no more space left to distribute.\n var/*float*/ remainingFreeSpace = 0;\n if (!isUndefined(availableInnerMainDim)) {\n remainingFreeSpace = availableInnerMainDim - sizeConsumedOnCurrentLine;\n } else if (sizeConsumedOnCurrentLine < 0) {\n // availableInnerMainDim is indefinite which means the node is being sized based on its content.\n // sizeConsumedOnCurrentLine is negative which means the node will allocate 0 pixels for\n // its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.\n remainingFreeSpace = -sizeConsumedOnCurrentLine;\n }\n\n var/*float*/ originalRemainingFreeSpace = remainingFreeSpace;\n var/*float*/ deltaFreeSpace = 0;\n\n if (!canSkipFlex) {\n var/*float*/ childFlexBasis;\n var/*float*/ flexShrinkScaledFactor;\n var/*float*/ flexGrowFactor;\n var/*float*/ baseMainSize;\n var/*float*/ boundMainSize;\n\n // Do two passes over the flex items to figure out how to distribute the remaining space.\n // The first pass finds the items whose min/max constraints trigger, freezes them at those\n // sizes, and excludes those sizes from the remaining space. The second pass sets the size\n // of each flexible item. It distributes the remaining space amongst the items whose min/max\n // constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing\n // their min/max constraints to trigger again.\n //\n // This two pass approach for resolving min/max constraints deviates from the spec. The\n // spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process\n // that needs to be repeated a variable number of times. The algorithm implemented here\n // won't handle all cases but it was simpler to implement and it mitigates performance\n // concerns because we know exactly how many passes it'll do.\n\n // First pass: detect the flex items whose min/max constraints trigger\n var/*float*/ deltaFlexShrinkScaledFactors = 0;\n var/*float*/ deltaFlexGrowFactors = 0;\n currentRelativeChild = firstRelativeChild;\n while (currentRelativeChild !== undefined) {\n childFlexBasis = currentRelativeChild.layout.flexBasis;\n\n if (remainingFreeSpace < 0) {\n flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;\n\n // Is this child able to shrink?\n if (flexShrinkScaledFactor !== 0) {\n baseMainSize = childFlexBasis +\n remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor;\n boundMainSize = boundAxis(currentRelativeChild, mainAxis, baseMainSize);\n if (baseMainSize !== boundMainSize) {\n // By excluding this item's size and flex factor from remaining, this item's\n // min/max constraints should also trigger in the second pass resulting in the\n // item's size calculation being identical in the first and second passes.\n deltaFreeSpace -= boundMainSize - childFlexBasis;\n deltaFlexShrinkScaledFactors -= flexShrinkScaledFactor;\n }\n }\n } else if (remainingFreeSpace > 0) {\n flexGrowFactor = getFlexGrowFactor(currentRelativeChild);\n\n // Is this child able to grow?\n if (flexGrowFactor !== 0) {\n baseMainSize = childFlexBasis +\n remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor;\n boundMainSize = boundAxis(currentRelativeChild, mainAxis, baseMainSize);\n if (baseMainSize !== boundMainSize) {\n // By excluding this item's size and flex factor from remaining, this item's\n // min/max constraints should also trigger in the second pass resulting in the\n // item's size calculation being identical in the first and second passes.\n deltaFreeSpace -= boundMainSize - childFlexBasis;\n deltaFlexGrowFactors -= flexGrowFactor;\n }\n }\n }\n\n currentRelativeChild = currentRelativeChild.nextChild;\n }\n\n totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;\n totalFlexGrowFactors += deltaFlexGrowFactors;\n remainingFreeSpace += deltaFreeSpace;\n\n // Second pass: resolve the sizes of the flexible items\n deltaFreeSpace = 0;\n currentRelativeChild = firstRelativeChild;\n while (currentRelativeChild !== undefined) {\n childFlexBasis = currentRelativeChild.layout.flexBasis;\n var/*float*/ updatedMainSize = childFlexBasis;\n\n if (remainingFreeSpace < 0) {\n flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;\n\n // Is this child able to shrink?\n if (flexShrinkScaledFactor !== 0) {\n updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +\n remainingFreeSpace / totalFlexShrinkScaledFactors * flexShrinkScaledFactor);\n }\n } else if (remainingFreeSpace > 0) {\n flexGrowFactor = getFlexGrowFactor(currentRelativeChild);\n\n // Is this child able to grow?\n if (flexGrowFactor !== 0) {\n updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +\n remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);\n }\n }\n\n deltaFreeSpace -= updatedMainSize - childFlexBasis;\n\n if (isMainAxisRow) {\n childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n\n if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = availableInnerCrossDim;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;\n } else {\n childHeight = currentRelativeChild.style.height + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n } else {\n childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);\n childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n\n if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = availableInnerCrossDim;\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;\n } else {\n childWidth = currentRelativeChild.style.width + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);\n childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;\n }\n }\n\n var/*bool*/ requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&\n getAlignItem(node, currentRelativeChild) === CSS_ALIGN_STRETCH;\n\n // Recursively call the layout algorithm for this child with the updated main size.\n layoutNodeInternal(currentRelativeChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, performLayout && !requiresStretchLayout, 'flex');\n\n currentRelativeChild = currentRelativeChild.nextChild;\n }\n }\n\n remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;\n\n // STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION\n\n // At this point, all the children have their dimensions set in the main axis.\n // Their dimensions are also set in the cross axis with the exception of items\n // that are aligned 'stretch'. We need to compute these stretch values and\n // set the final positions.\n\n // If we are using \"at most\" rules in the main axis, we won't distribute\n // any remaining space at this point.\n if (measureModeMainDim === CSS_MEASURE_MODE_AT_MOST) {\n remainingFreeSpace = 0;\n }\n\n // Use justifyContent to figure out how to allocate the remaining space\n // available in the main axis.\n if (justifyContent !== CSS_JUSTIFY_FLEX_START) {\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingFreeSpace / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingFreeSpace;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingFreeSpace = fmaxf(remainingFreeSpace, 0);\n if (itemsOnLine > 1) {\n betweenMainDim = remainingFreeSpace / (itemsOnLine - 1);\n } else {\n betweenMainDim = 0;\n }\n } else if (justifyContent === CSS_JUSTIFY_SPACE_AROUND) {\n // Space on the edges is half of the space between elements\n betweenMainDim = remainingFreeSpace / itemsOnLine;\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n var/*float*/ mainDim = leadingPaddingAndBorderMain + leadingMainDim;\n var/*float*/ crossDim = 0;\n\n for (i = startOfLineIndex; i < endOfLineIndex; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\n if (performLayout) {\n // In case the child is position absolute and has left/top being\n // defined, we override the position to whatever the user said\n // (and margin/border).\n child.layout[pos[mainAxis]] = getPosition(child, leading[mainAxis]) +\n getLeadingBorder(node, mainAxis) +\n getLeadingMargin(child, mainAxis);\n }\n } else {\n if (performLayout) {\n // If the child is position absolute (without top/left) or relative,\n // we put it at the current accumulated offset.\n child.layout[pos[mainAxis]] += mainDim;\n }\n\n // Now that we placed the element, we need to update the variables.\n // We need to do that only for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n if (canSkipFlex) {\n // If we skipped the flex step, then we can't rely on the measuredDims because\n // they weren't computed. This means we can't call getDimWithMargin.\n mainDim += betweenMainDim + getMarginAxis(child, mainAxis) + child.layout.flexBasis;\n crossDim = availableInnerCrossDim;\n } else {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\n\n // The cross dimension is the max of the elements dimension since there\n // can only be one element in that cross dimension.\n crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));\n }\n }\n }\n }\n\n mainDim += trailingPaddingAndBorderMain;\n\n var/*float*/ containerCrossAxis = availableInnerCrossDim;\n if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n // Compute the cross axis from the max cross dimension of the children.\n containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;\n\n if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);\n }\n }\n\n // If there's no flex wrap, the cross dimension is defined by the container.\n if (!isNodeFlexWrap && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY) {\n crossDim = availableInnerCrossDim;\n }\n\n // Clamp to the min/max size specified on the container.\n crossDim = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;\n\n // STEP 7: CROSS-AXIS ALIGNMENT\n // We can skip child alignment if we're just measuring the container.\n if (performLayout) {\n for (i = startOfLineIndex; i < endOfLineIndex; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // If the child is absolutely positioned and has a top/left/bottom/right\n // set, override all the previously computed positions to set it correctly.\n if (isPosDefined(child, leading[crossAxis])) {\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\n getLeadingMargin(child, crossAxis);\n } else {\n child.layout[pos[crossAxis]] = leadingPaddingAndBorderCross +\n getLeadingMargin(child, crossAxis);\n }\n } else {\n var/*float*/ leadingCrossDim = leadingPaddingAndBorderCross;\n\n // For a relative children, we're either using alignItems (parent) or\n // alignSelf (child) in order to determine the position in the cross axis\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n\n // If the child uses align stretch, we need to lay it out one more time, this time\n // forcing the cross-axis size to be the computed cross size for the current line.\n if (alignItem === CSS_ALIGN_STRETCH) {\n childWidth = child.layout.measuredWidth + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);\n childHeight = child.layout.measuredHeight + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);\n var/*bool*/ isCrossSizeDefinite = false;\n\n if (isMainAxisRow) {\n isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);\n childHeight = crossDim;\n } else {\n isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);\n childWidth = crossDim;\n }\n\n // If the child defines a definite size for its cross axis, there's no need to stretch.\n if (!isCrossSizeDefinite) {\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, true, 'stretch');\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n var/*float*/ remainingCrossDim = containerCrossAxis - getDimWithMargin(child, crossAxis);\n\n if (alignItem === CSS_ALIGN_CENTER) {\n leadingCrossDim += remainingCrossDim / 2;\n } else { // CSS_ALIGN_FLEX_END\n leadingCrossDim += remainingCrossDim;\n }\n }\n\n // And we apply the position\n child.layout[pos[crossAxis]] += totalLineCrossDim + leadingCrossDim;\n }\n }\n }\n\n totalLineCrossDim += crossDim;\n maxLineMainDim = fmaxf(maxLineMainDim, mainDim);\n\n // Reset variables for new line.\n lineCount++;\n startOfLineIndex = endOfLineIndex;\n endOfLineIndex = startOfLineIndex;\n }\n\n // STEP 8: MULTI-LINE CONTENT ALIGNMENT\n if (lineCount > 1 && performLayout && !isUndefined(availableInnerCrossDim)) {\n var/*float*/ remainingAlignContentDim = availableInnerCrossDim - totalLineCrossDim;\n\n var/*float*/ crossDimLead = 0;\n var/*float*/ currentLead = leadingPaddingAndBorderCross;\n\n var/*css_align_t*/ alignContent = getAlignContent(node);\n if (alignContent === CSS_ALIGN_FLEX_END) {\n currentLead += remainingAlignContentDim;\n } else if (alignContent === CSS_ALIGN_CENTER) {\n currentLead += remainingAlignContentDim / 2;\n } else if (alignContent === CSS_ALIGN_STRETCH) {\n if (availableInnerCrossDim > totalLineCrossDim) {\n crossDimLead = (remainingAlignContentDim / lineCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < lineCount; ++i) {\n var/*int*/ startIndex = endIndex;\n var/*int*/ j;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (j = startIndex; j < childCount; ++j) {\n child = node.children[j];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (isLayoutDimDefined(child, crossAxis)) {\n lineHeight = fmaxf(lineHeight,\n child.layout[measuredDim[crossAxis]] + getMarginAxis(child, crossAxis));\n }\n }\n endIndex = j;\n lineHeight += crossDimLead;\n\n if (performLayout) {\n for (j = startIndex; j < endIndex; ++j) {\n child = node.children[j];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n\n var/*css_align_t*/ alignContentAlignItem = getAlignItem(node, child);\n if (alignContentAlignItem === CSS_ALIGN_FLEX_START) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n } else if (alignContentAlignItem === CSS_ALIGN_FLEX_END) {\n child.layout[pos[crossAxis]] = currentLead + lineHeight - getTrailingMargin(child, crossAxis) - child.layout[measuredDim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n childHeight = child.layout[measuredDim[crossAxis]];\n child.layout[pos[crossAxis]] = currentLead + (lineHeight - childHeight) / 2;\n } else if (alignContentAlignItem === CSS_ALIGN_STRETCH) {\n child.layout[pos[crossAxis]] = currentLead + getLeadingMargin(child, crossAxis);\n // TODO(prenaux): Correctly set the height of items with indefinite\n // (auto) crossAxis dimension.\n }\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n // STEP 9: COMPUTING FINAL DIMENSIONS\n node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);\n node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, availableHeight - marginAxisColumn);\n\n // If the user didn't specify a width or height for the node, set the\n // dimensions based on the children.\n if (measureModeMainDim === CSS_MEASURE_MODE_UNDEFINED) {\n // Clamp the size to the min/max size, if specified, and make sure it\n // doesn't go below the padding and border amount.\n node.layout[measuredDim[mainAxis]] = boundAxis(node, mainAxis, maxLineMainDim);\n } else if (measureModeMainDim === CSS_MEASURE_MODE_AT_MOST) {\n node.layout[measuredDim[mainAxis]] = fmaxf(\n fminf(availableInnerMainDim + paddingAndBorderAxisMain,\n boundAxisWithinMinAndMax(node, mainAxis, maxLineMainDim)),\n paddingAndBorderAxisMain);\n }\n\n if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED) {\n // Clamp the size to the min/max size, if specified, and make sure it\n // doesn't go below the padding and border amount.\n node.layout[measuredDim[crossAxis]] = boundAxis(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross);\n } else if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {\n node.layout[measuredDim[crossAxis]] = fmaxf(\n fminf(availableInnerCrossDim + paddingAndBorderAxisCross,\n boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),\n paddingAndBorderAxisCross);\n }\n\n // STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN\n if (performLayout) {\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n if (mainAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||\n mainAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsMainTrailingPos = true;\n }\n\n if (crossAxis === CSS_FLEX_DIRECTION_ROW_REVERSE ||\n crossAxis === CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsCrossTrailingPos = true;\n }\n\n // Set trailing position if necessary.\n if (needsMainTrailingPos || needsCrossTrailingPos) {\n for (i = 0; i < childCount; ++i) {\n child = node.children[i];\n\n if (needsMainTrailingPos) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n if (needsCrossTrailingPos) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n }\n\n // STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN\n currentAbsoluteChild = firstAbsoluteChild;\n while (currentAbsoluteChild !== undefined) {\n // Now that we know the bounds of the container, perform layout again on the\n // absolutely-positioned children.\n if (performLayout) {\n\n childWidth = CSS_UNDEFINED;\n childHeight = CSS_UNDEFINED;\n\n if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW)) {\n childWidth = currentAbsoluteChild.style.width + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);\n } else {\n // If the child doesn't have a specified width, compute the width based on the left/right offsets if they're defined.\n if (isPosDefined(currentAbsoluteChild, CSS_LEFT) && isPosDefined(currentAbsoluteChild, CSS_RIGHT)) {\n childWidth = node.layout.measuredWidth -\n (getLeadingBorder(node, CSS_FLEX_DIRECTION_ROW) + getTrailingBorder(node, CSS_FLEX_DIRECTION_ROW)) -\n (currentAbsoluteChild.style[CSS_LEFT] + currentAbsoluteChild.style[CSS_RIGHT]);\n childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);\n }\n }\n\n if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {\n childHeight = currentAbsoluteChild.style.height + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);\n } else {\n // If the child doesn't have a specified height, compute the height based on the top/bottom offsets if they're defined.\n if (isPosDefined(currentAbsoluteChild, CSS_TOP) && isPosDefined(currentAbsoluteChild, CSS_BOTTOM)) {\n childHeight = node.layout.measuredHeight -\n (getLeadingBorder(node, CSS_FLEX_DIRECTION_COLUMN) + getTrailingBorder(node, CSS_FLEX_DIRECTION_COLUMN)) -\n (currentAbsoluteChild.style[CSS_TOP] + currentAbsoluteChild.style[CSS_BOTTOM]);\n childHeight = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN, childHeight);\n }\n }\n\n // If we're still missing one or the other dimension, measure the content.\n if (isUndefined(childWidth) || isUndefined(childHeight)) {\n childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n\n // According to the spec, if the main size is not definite and the\n // child's inline axis is parallel to the main axis (i.e. it's\n // horizontal), the child should be sized using \"UNDEFINED\" in\n // the main size. Otherwise use \"AT_MOST\" in the cross axis.\n if (!isMainAxisRow && isUndefined(childWidth) && !isUndefined(availableInnerWidth)) {\n childWidth = availableInnerWidth;\n childWidthMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n\n // The W3C spec doesn't say anything about the 'overflow' property,\n // but all major browsers appear to implement the following logic.\n if (getOverflow(node) === CSS_OVERFLOW_HIDDEN) {\n if (isMainAxisRow && isUndefined(childHeight) && !isUndefined(availableInnerHeight)) {\n childHeight = availableInnerHeight;\n childHeightMeasureMode = CSS_MEASURE_MODE_AT_MOST;\n }\n }\n\n layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'abs-measure');\n childWidth = currentAbsoluteChild.layout.measuredWidth + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);\n childHeight = currentAbsoluteChild.layout.measuredHeight + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);\n }\n\n layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, 'abs-layout');\n\n if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&\n !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {\n currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_ROW]] =\n node.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -\n currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -\n getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);\n }\n\n if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&\n !isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {\n currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_COLUMN]] =\n node.layout[measuredDim[CSS_FLEX_DIRECTION_COLUMN]] -\n currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_COLUMN]] -\n getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]);\n }\n }\n\n currentAbsoluteChild = currentAbsoluteChild.nextChild;\n }\n }\n\n function canUseCachedMeasurement(availableWidth, availableHeight,\n marginRow, marginColumn,\n widthMeasureMode, heightMeasureMode,\n cachedLayout) {\n\n // Is it an exact match?\n if (cachedLayout.availableWidth === availableWidth &&\n cachedLayout.availableHeight === availableHeight &&\n cachedLayout.widthMeasureMode === widthMeasureMode &&\n cachedLayout.heightMeasureMode === heightMeasureMode) {\n return true;\n }\n\n // If the width is an exact match, try a fuzzy match on the height.\n if (cachedLayout.availableWidth === availableWidth &&\n cachedLayout.widthMeasureMode === widthMeasureMode &&\n heightMeasureMode === CSS_MEASURE_MODE_EXACTLY &&\n availableHeight - marginColumn === cachedLayout.computedHeight) {\n return true;\n }\n\n // If the height is an exact match, try a fuzzy match on the width.\n if (cachedLayout.availableHeight === availableHeight &&\n cachedLayout.heightMeasureMode === heightMeasureMode &&\n widthMeasureMode === CSS_MEASURE_MODE_EXACTLY &&\n availableWidth - marginRow === cachedLayout.computedWidth) {\n return true;\n }\n\n return false;\n }\n\n //\n // This is a wrapper around the layoutNodeImpl function. It determines\n // whether the layout request is redundant and can be skipped.\n //\n // Parameters:\n // Input parameters are the same as layoutNodeImpl (see above)\n // Return parameter is true if layout was performed, false if skipped\n //\n function layoutNodeInternal(node, availableWidth, availableHeight, parentDirection,\n widthMeasureMode, heightMeasureMode, performLayout, reason) {\n var layout = node.layout;\n\n var needToVisitNode = (node.isDirty && layout.generationCount !== gCurrentGenerationCount) ||\n layout.lastParentDirection !== parentDirection;\n\n if (needToVisitNode) {\n // Invalidate the cached results.\n if (layout.cachedMeasurements !== undefined) {\n layout.cachedMeasurements = [];\n }\n if (layout.cachedLayout !== undefined) {\n layout.cachedLayout.widthMeasureMode = undefined;\n layout.cachedLayout.heightMeasureMode = undefined;\n }\n }\n\n var i;\n var len;\n var cachedResults;\n\n // Determine whether the results are already cached. We maintain a separate\n // cache for layouts and measurements. A layout operation modifies the positions\n // and dimensions for nodes in the subtree. The algorithm assumes that each node\n // gets layed out a maximum of one time per tree layout, but multiple measurements\n // may be required to resolve all of the flex dimensions.\n // We handle nodes with measure functions specially here because they are the most\n // expensive to measure, so it's worth avoiding redundant measurements if at all possible.\n if (isMeasureDefined(node)) {\n var marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n var marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n\n // First, try to use the layout cache.\n if (layout.cachedLayout &&\n canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,\n widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {\n cachedResults = layout.cachedLayout;\n } else if (layout.cachedMeasurements) {\n // Try to use the measurement cache.\n for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {\n if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,\n widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {\n cachedResults = layout.cachedMeasurements[i];\n break;\n }\n }\n }\n } else if (performLayout) {\n if (layout.cachedLayout &&\n layout.cachedLayout.availableWidth === availableWidth &&\n layout.cachedLayout.availableHeight === availableHeight &&\n layout.cachedLayout.widthMeasureMode === widthMeasureMode &&\n layout.cachedLayout.heightMeasureMode === heightMeasureMode) {\n cachedResults = layout.cachedLayout;\n }\n } else if (layout.cachedMeasurements) {\n for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {\n if (layout.cachedMeasurements[i].availableWidth === availableWidth &&\n layout.cachedMeasurements[i].availableHeight === availableHeight &&\n layout.cachedMeasurements[i].widthMeasureMode === widthMeasureMode &&\n layout.cachedMeasurements[i].heightMeasureMode === heightMeasureMode) {\n cachedResults = layout.cachedMeasurements[i];\n break;\n }\n }\n }\n\n if (!needToVisitNode && cachedResults !== undefined) {\n layout.measureWidth = cachedResults.computedWidth;\n layout.measureHeight = cachedResults.computedHeight;\n } else {\n layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);\n layout.lastParentDirection = parentDirection;\n\n if (cachedResults === undefined) {\n var newCacheEntry;\n if (performLayout) {\n // Use the single layout cache entry.\n if (layout.cachedLayout === undefined) {\n layout.cachedLayout = {};\n }\n newCacheEntry = layout.cachedLayout;\n } else {\n // Allocate a new measurement cache entry.\n if (layout.cachedMeasurements === undefined) {\n layout.cachedMeasurements = [];\n }\n newCacheEntry = {};\n layout.cachedMeasurements.push(newCacheEntry);\n }\n\n newCacheEntry.availableWidth = availableWidth;\n newCacheEntry.availableHeight = availableHeight;\n newCacheEntry.widthMeasureMode = widthMeasureMode;\n newCacheEntry.heightMeasureMode = heightMeasureMode;\n newCacheEntry.computedWidth = layout.measuredWidth;\n newCacheEntry.computedHeight = layout.measuredHeight;\n }\n }\n\n if (performLayout) {\n node.layout.width = node.layout.measuredWidth;\n node.layout.height = node.layout.measuredHeight;\n layout.shouldUpdate = true;\n }\n\n layout.generationCount = gCurrentGenerationCount;\n return (needToVisitNode || cachedResults === undefined);\n }\n\n function layoutNode(node, availableWidth, availableHeight, parentDirection) {\n // Increment the generation count. This will force the recursive routine to visit\n // all dirty nodes at least once. Subsequent visits will be skipped if the input\n // parameters don't change.\n gCurrentGenerationCount++;\n\n // If the caller didn't specify a height/width, use the dimensions\n // specified in the style.\n if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {\n availableWidth = node.style.width + getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);\n }\n if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {\n availableHeight = node.style.height + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n\n var widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n var heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;\n\n if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, 'initial')) {\n setPosition(node, node.layout.direction);\n }\n }\n\n return {\n layoutNodeImpl: layoutNodeImpl,\n computeLayout: layoutNode,\n fillNodes: fillNodes,\n canUseCachedMeasurement: canUseCachedMeasurement\n };\n})();\n\n// This module export is only used for the purposes of unit testing this file. When\n// the library is packaged this file is included within css-layout.js which forms\n// the public API.\nif (typeof exports === 'object') {\n module.exports = computeLayout;\n}\n\n\n return function(node) {\n /*eslint-disable */\n // disabling ESLint because this code relies on the above include\n computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n /*eslint-enable */\n };\n}));\n"]}
\ No newline at end of file
diff --git a/src/Layout-test-utils.js b/src/Layout-test-utils.js
index f33665d3..6d9e6b1e 100644
--- a/src/Layout-test-utils.js
+++ b/src/Layout-test-utils.js
@@ -130,13 +130,13 @@ var layoutTestUtils = (function() {
keysToCopy.forEach(function(key) {
layout[key] = node.layout[key];
});
-
+
if (node.children && node.children.length > 0) {
layout.children = node.children.map(extractNodes);
} else {
delete node.children;
}
-
+
delete node.layout;
return layout;
@@ -192,13 +192,13 @@ var layoutTestUtils = (function() {
function computeDOMLayout(node) {
var body = getIframe().contentDocument.body;
-
+
function setStyle(div, name, value) {
div.style['-webkit-' + name] = value;
div.style['webkit' + capitalizeFirst(name)] = value;
div.style[name] = value;
}
-
+
function transfer(div, node, name, ext) {
if (name in node.style) {
var value = node.style[name] + (ext || '');
@@ -215,7 +215,7 @@ var layoutTestUtils = (function() {
transfer(div, node, type + 'Start' + suffix, 'px');
transfer(div, node, type + 'End' + suffix, 'px');
}
-
+
function transferFlex(div, node) {
if ('flex' in node.style) {
var flex = node.style.flex;
@@ -227,7 +227,7 @@ var layoutTestUtils = (function() {
setStyle(div, 'flex', resolvedFlex);
}
}
-
+
function renderNode(parent, node) {
var div = document.createElement('div');
transfer(div, node, 'width', 'px');
@@ -325,13 +325,13 @@ var layoutTestUtils = (function() {
function testExtractNodes(node, extractedNode) {
expect(extractNodes(node)).toEqual(extractedNode);
}
-
+
function testCanUseCachedMeasurement(canReuse, spec, cacheEntry) {
var availableWidth = spec.availableWidth;
var availableHeight = spec.availableHeight;
var widthMeasureMode = spec.widthMeasureMode;
var heightMeasureMode = spec.heightMeasureMode;
-
+
expect(
canUseCachedMeasurement(
availableWidth, availableHeight,
diff --git a/src/Layout.c b/src/Layout.c
index f43b38da..2e0918a3 100644
--- a/src/Layout.c
+++ b/src/Layout.c
@@ -54,7 +54,7 @@ void init_css_node(css_node_t* node) {
node->style.direction = CSS_DIRECTION_INHERIT;
node->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN;
-
+
node->style.overflow = CSS_OVERFLOW_VISIBLE;
// Some of the fields default to undefined and not 0
@@ -86,7 +86,7 @@ void init_css_node(css_node_t* node) {
node->layout.last_parent_direction = (css_direction_t)-1;
node->layout.should_update = true;
node->layout.next_cached_measurements_index = 0;
-
+
node->layout.measured_dimensions[CSS_WIDTH] = CSS_UNDEFINED;
node->layout.measured_dimensions[CSS_HEIGHT] = CSS_UNDEFINED;
node->layout.cached_layout.width_measure_mode = (css_measure_mode_t)-1;
@@ -566,7 +566,7 @@ static float getRelativePosition(css_node_t* node, css_flex_direction_t axis) {
static void setPosition(css_node_t* node, css_direction_t direction) {
css_flex_direction_t mainAxis = resolveAxis(getFlexDirection(node), direction);
css_flex_direction_t crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node->layout.position[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node->layout.position[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +
@@ -613,8 +613,8 @@ static void setPosition(css_node_t* node, css_direction_t direction) {
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
-// main size. For text blocks, for example, this is the width of the widest word.
-// Calculating the minimum width is expensive, so we forego it and assume a default
+// main size. For text blocks, for example, this is the width of the widest word.
+// Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -648,7 +648,7 @@ static void setPosition(css_node_t* node, css_direction_t direction) {
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
-//
+//
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
@@ -658,7 +658,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
assert(isUndefined(availableWidth) ? widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED
assert(isUndefined(availableHeight) ? heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED : true); // availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED
-
+
float paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
@@ -672,7 +672,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isMeasureDefined(node)) {
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -704,7 +704,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
measureDim.dimensions[CSS_HEIGHT] + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -734,7 +734,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {
node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -746,7 +746,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
node->layout.measured_dimensions[CSS_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && heightMeasureMode == CSS_MEASURE_MODE_EXACTLY) {
node->layout.measured_dimensions[CSS_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -770,7 +770,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
-
+
css_measure_mode_t measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
css_measure_mode_t measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -795,7 +795,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
css_direction_t childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (child->style.position_type == CSS_POSITION_ABSOLUTE) {
@@ -811,27 +811,27 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentAbsoluteChild = child;
child->next_child = NULL;
} else {
-
+
if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
-
+
// The width is definite, so use that as the flex basis.
child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_WIDTH], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {
-
+
// The height is definite, so use that as the flex basis.
child->layout.flex_basis = fmaxf(child->style.dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));
} else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child->layout.flex_basis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSS_UNDEFINED;
childHeight = CSS_UNDEFINED;
childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
-
+
if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
childWidth = child->style.dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
@@ -840,7 +840,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childHeight = child->style.dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -861,21 +861,21 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// Measure the child
layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
-
+
child->layout.flex_basis = fmaxf(isMainAxisRow ? child->layout.measured_dimensions[CSS_WIDTH] : child->layout.measured_dimensions[CSS_HEIGHT], getPaddingAndBorderAxis(child, mainAxis));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
int startOfLineIndex = 0;
int endOfLineIndex = 0;
-
+
// Number of lines.
int lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
float totalLineCrossDim = 0;
@@ -883,7 +883,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
int itemsOnLine = 0;
@@ -910,7 +910,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (child->style.position_type != CSS_POSITION_ABSOLUTE) {
float outerFlexBasis = child->layout.flex_basis + getMarginAxis(child, mainAxis);
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -922,7 +922,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isFlex(child)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child->layout.flex_basis;
@@ -938,11 +938,11 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentRelativeChild = child;
child->next_child = NULL;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
bool canSkipFlex = !performLayout && measureModeCrossDim == CSS_MEASURE_MODE_EXACTLY;
@@ -965,7 +965,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
float originalRemainingFreeSpace = remainingFreeSpace;
float deltaFreeSpace = 0;
@@ -975,20 +975,20 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
float flexGrowFactor;
float baseMainSize;
float boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
float deltaFlexShrinkScaledFactors = 0;
float deltaFlexGrowFactors = 0;
@@ -998,7 +998,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
baseMainSize = childFlexBasis +
@@ -1029,14 +1029,14 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
}
}
-
+
currentRelativeChild = currentRelativeChild->next_child;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -1046,7 +1046,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -1061,13 +1061,13 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1078,7 +1078,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
} else {
childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1087,7 +1087,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
}
-
+
bool requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&
getAlignItem(node, currentRelativeChild) == CSS_ALIGN_STRETCH;
@@ -1097,7 +1097,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentRelativeChild = currentRelativeChild->next_child;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -1156,7 +1156,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// we put it at the current accumulated offset.
child->layout.position[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1170,7 +1170,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));
@@ -1180,12 +1180,12 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
mainDim += trailingPaddingAndBorderMain;
-
+
float containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim == CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim == CSS_MEASURE_MODE_AT_MOST) {
containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);
}
@@ -1222,14 +1222,14 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
css_align_t alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem == CSS_ALIGN_STRETCH) {
childWidth = child->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childHeight = child->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
bool isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);
childHeight = crossDim;
@@ -1237,7 +1237,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
@@ -1364,7 +1364,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
bool needsMainTrailingPos = false;
@@ -1395,7 +1395,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild != NULL) {
@@ -1417,7 +1417,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = currentAbsoluteChild->style.dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
} else {
@@ -1434,7 +1434,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
if (isUndefined(childWidth) || isUndefined(childHeight)) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1457,9 +1457,9 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
childWidth = currentAbsoluteChild->layout.measured_dimensions[CSS_WIDTH] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);
childHeight = currentAbsoluteChild->layout.measured_dimensions[CSS_HEIGHT] + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, "abs-layout");
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {
currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1467,7 +1467,7 @@ static void layoutNodeImpl(css_node_t* node, float availableWidth, float availab
currentAbsoluteChild->layout.measured_dimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);
}
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {
currentAbsoluteChild->layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
@@ -1508,11 +1508,11 @@ static const char* getModeName(css_measure_mode_t mode, bool performLayout) {
"LAY_EXACTLY",
"LAY_AT_MOST"
};
-
+
if (mode >= CSS_MEASURE_MODE_COUNT) {
return "";
}
-
+
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
}
@@ -1528,7 +1528,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
cachedLayout.height_measure_mode == heightMeasureMode) {
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (cachedLayout.width_measure_mode == widthMeasureMode &&
eq(cachedLayout.available_width, availableWidth) &&
@@ -1536,7 +1536,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
eq(availableHeight - marginColumn, cachedLayout.computed_height)) {
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (cachedLayout.height_measure_mode == heightMeasureMode &&
eq(cachedLayout.available_height, availableHeight) &&
@@ -1559,7 +1559,7 @@ static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableHeight,
css_direction_t parentDirection, css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode, bool performLayout, char* reason) {
css_layout_t* layout = &node->layout;
-
+
gDepth++;
bool needToVisitNode = (node->is_dirty(node->context) && layout->generation_count != gCurrentGenerationCount) ||
@@ -1573,7 +1573,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
css_cached_measurement_t* cachedResults = NULL;
-
+
// Determine whether the results are already cached. We maintain a separate
// cache for layouts and measurements. A layout operation modifies the positions
// and dimensions for nodes in the subtree. The algorithm assumes that each node
@@ -1584,7 +1584,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
if (isMeasureDefined(node)) {
float marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-
+
// First, try to use the layout cache.
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
@@ -1604,7 +1604,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
eq(layout->cached_layout.available_height, availableHeight) &&
layout->cached_layout.width_measure_mode == widthMeasureMode &&
layout->cached_layout.height_measure_mode == heightMeasureMode) {
-
+
cachedResults = &layout->cached_layout;
}
} else {
@@ -1649,7 +1649,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);
-
+
if (gPrintChanges) {
printf("%s%d.}%s", getSpacer(gDepth), gDepth, needToVisitNode ? "*" : "");
if (node->print) {
@@ -1662,7 +1662,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
}
layout->last_parent_direction = parentDirection;
-
+
if (cachedResults == NULL) {
if (layout->next_cached_measurements_index == CSS_MAX_CACHED_RESULT_COUNT) {
if (gPrintChanges) {
@@ -1680,7 +1680,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
newCacheEntry = &layout->cached_measurements[layout->next_cached_measurements_index];
layout->next_cached_measurements_index++;
}
-
+
newCacheEntry->available_width = availableWidth;
newCacheEntry->available_height = availableHeight;
newCacheEntry->width_measure_mode = widthMeasureMode;
@@ -1689,7 +1689,7 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
newCacheEntry->computed_height = layout->measured_dimensions[CSS_HEIGHT];
}
}
-
+
if (performLayout) {
node->layout.dimensions[CSS_WIDTH] = node->layout.measured_dimensions[CSS_WIDTH];
node->layout.dimensions[CSS_HEIGHT] = node->layout.measured_dimensions[CSS_HEIGHT];
@@ -1706,7 +1706,7 @@ void layoutNode(css_node_t* node, float availableWidth, float availableHeight, c
// all dirty nodes at least once. Subsequent visits will be skipped if the input
// parameters don't change.
gCurrentGenerationCount++;
-
+
// If the caller didn't specify a height/width, use the dimensions
// specified in the style.
if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
@@ -1715,10 +1715,10 @@ void layoutNode(css_node_t* node, float availableWidth, float availableHeight, c
if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
availableHeight = node->style.dimensions[CSS_HEIGHT] + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
css_measure_mode_t widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
css_measure_mode_t heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, "initial")) {
setPosition(node, node->layout.direction);
diff --git a/src/Layout.js b/src/Layout.js
index bb40f609..b1e4e7d7 100755
--- a/src/Layout.js
+++ b/src/Layout.js
@@ -8,18 +8,18 @@
*/
var computeLayout = (function() {
-
+
var POSITIVE_FLEX_IS_AUTO = false;
-
+
var gCurrentGenerationCount = 0;
-
+
var CSS_UNDEFINED;
-
+
var CSS_LEFT = 'left';
var CSS_TOP = 'top';
var CSS_RIGHT = 'right';
var CSS_BOTTOM = 'bottom';
-
+
var CSS_DIRECTION_INHERIT = 'inherit';
var CSS_DIRECTION_LTR = 'ltr';
var CSS_DIRECTION_RTL = 'rtl';
@@ -42,10 +42,10 @@ var computeLayout = (function() {
var CSS_POSITION_RELATIVE = 'relative';
var CSS_POSITION_ABSOLUTE = 'absolute';
-
+
var CSS_OVERFLOW_VISIBLE = 'visible';
var CSS_OVERFLOW_HIDDEN = 'hidden';
-
+
var CSS_MEASURE_MODE_UNDEFINED = 'undefined';
var CSS_MEASURE_MODE_EXACTLY = 'exactly';
var CSS_MEASURE_MODE_AT_MOST = 'at-most';
@@ -125,14 +125,14 @@ var computeLayout = (function() {
return flexDirection === CSS_FLEX_DIRECTION_COLUMN ||
flexDirection === CSS_FLEX_DIRECTION_COLUMN_REVERSE;
}
-
+
function getFlex(node) {
if (node.style.flex === undefined) {
return 0;
}
return node.style.flex;
}
-
+
function isFlexBasisAuto(node) {
if (POSITIVE_FLEX_IS_AUTO) {
// All flex values are auto.
@@ -142,7 +142,7 @@ var computeLayout = (function() {
return getFlex(node) <= 0;
}
}
-
+
function getFlexGrowFactor(node) {
// Flex grow is implied by positive values for flex.
if (getFlex(node) > 0) {
@@ -150,7 +150,7 @@ var computeLayout = (function() {
}
return 0;
}
-
+
function getFlexShrinkFactor(node) {
if (POSITIVE_FLEX_IS_AUTO) {
// A flex shrink factor of 1 is implied by non-zero values for flex.
@@ -403,7 +403,7 @@ var computeLayout = (function() {
}
return CSS_POSITION_RELATIVE;
}
-
+
function getOverflow(node) {
if (node.style.overflow) {
return node.style.overflow;
@@ -425,12 +425,12 @@ var computeLayout = (function() {
function getDimWithMargin(node, axis) {
return node.layout[measuredDim[axis]] + getMarginAxis(node, axis);
}
-
- function isStyleDimDefined(node, axis) {
+
+ function isStyleDimDefined(node, axis) {
return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0;
}
-
- function isLayoutDimDefined(node, axis) {
+
+ function isLayoutDimDefined(node, axis) {
return node.layout[measuredDim[axis]] !== undefined && node.layout[measuredDim[axis]] >= 0;
}
@@ -448,7 +448,7 @@ var computeLayout = (function() {
}
return 0;
}
-
+
function boundAxisWithinMinAndMax(node, axis, value) {
var min = {
'row': node.style.minWidth,
@@ -473,7 +473,7 @@ var computeLayout = (function() {
}
return boundValue;
}
-
+
function fminf(a, b) {
if (a < b) {
return a;
@@ -487,7 +487,7 @@ var computeLayout = (function() {
}
return b;
}
-
+
// Like boundAxisWithinMinAndMax but also ensures that the value doesn't go below the
// padding and border amount.
function boundAxis(node, axis, value) {
@@ -509,11 +509,11 @@ var computeLayout = (function() {
}
return -getPosition(node, trailing[axis]);
}
-
+
function setPosition(node, direction) {
var mainAxis = resolveAxis(getFlexDirection(node), direction);
var crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node.layout[leading[mainAxis]] = getLeadingMargin(node, mainAxis) +
getRelativePosition(node, mainAxis);
node.layout[trailing[mainAxis]] = getTrailingMargin(node, mainAxis) +
@@ -523,13 +523,13 @@ var computeLayout = (function() {
node.layout[trailing[crossAxis]] = getTrailingMargin(node, crossAxis) +
getRelativePosition(node, crossAxis);
}
-
+
function assert(condition, message) {
if (!condition) {
throw new Error(message);
}
}
-
+
//
// This is the main routine that implements a subset of the flexbox layout algorithm
// described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.
@@ -566,8 +566,8 @@ var computeLayout = (function() {
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
- // main size. For text blocks, for example, this is the width of the widest word.
- // Calculating the minimum width is expensive, so we forego it and assume a default
+ // main size. For text blocks, for example, this is the width of the widest word.
+ // Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -601,14 +601,14 @@ var computeLayout = (function() {
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
- //
+ //
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
function layoutNodeImpl(node, availableWidth, availableHeight, /*css_direction_t*/parentDirection, widthMeasureMode, heightMeasureMode, performLayout) {
assert(isUndefined(availableWidth) ? widthMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableWidth is indefinite so widthMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');
assert(isUndefined(availableHeight) ? heightMeasureMode === CSS_MEASURE_MODE_UNDEFINED : true, 'availableHeight is indefinite so heightMeasureMode must be CSS_MEASURE_MODE_UNDEFINED');
-
+
var/*float*/ paddingAndBorderAxisRow = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_ROW);
var/*float*/ paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
var/*float*/ marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
@@ -622,7 +622,7 @@ var computeLayout = (function() {
if (isMeasureDefined(node)) {
var/*float*/ innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
var/*float*/ innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -654,7 +654,7 @@ var computeLayout = (function() {
measureDim.height + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -684,7 +684,7 @@ var computeLayout = (function() {
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode === CSS_MEASURE_MODE_AT_MOST && availableWidth <= 0) {
node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, isUndefined(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -696,7 +696,7 @@ var computeLayout = (function() {
node.layout.measuredHeight = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode === CSS_MEASURE_MODE_EXACTLY && heightMeasureMode === CSS_MEASURE_MODE_EXACTLY) {
node.layout.measuredWidth = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -720,7 +720,7 @@ var computeLayout = (function() {
var/*float*/ leadingPaddingAndBorderCross = getLeadingPaddingAndBorder(node, crossAxis);
var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis);
var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis);
-
+
var/*css_measure_mode_t*/ measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
var/*css_measure_mode_t*/ measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -745,7 +745,7 @@ var computeLayout = (function() {
var/*css_direction_t*/ childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {
@@ -761,27 +761,27 @@ var computeLayout = (function() {
currentAbsoluteChild = child;
child.nextChild = undefined;
} else {
-
+
if (isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
-
+
// The width is definite, so use that as the flex basis.
child.layout.flexBasis = fmaxf(child.style.width, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_ROW));
} else if (!isMainAxisRow && isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN)) {
-
+
// The height is definite, so use that as the flex basis.
child.layout.flexBasis = fmaxf(child.style.height, getPaddingAndBorderAxis(child, CSS_FLEX_DIRECTION_COLUMN));
} else if (!isFlexBasisAuto(child) && !isUndefined(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child.layout.flexBasis = fmaxf(0, getPaddingAndBorderAxis(child, mainAxis));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSS_UNDEFINED;
childHeight = CSS_UNDEFINED;
childWidthMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
childHeightMeasureMode = CSS_MEASURE_MODE_UNDEFINED;
-
+
if (isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW)) {
childWidth = child.style.width + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
@@ -790,7 +790,7 @@ var computeLayout = (function() {
childHeight = child.style.height + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -811,21 +811,21 @@ var computeLayout = (function() {
// Measure the child
layoutNodeInternal(child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, 'measure');
-
+
child.layout.flexBasis = fmaxf(isMainAxisRow ? child.layout.measuredWidth : child.layout.measuredHeight, getPaddingAndBorderAxis(child, mainAxis));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
var/*int*/ startOfLineIndex = 0;
var/*int*/ endOfLineIndex = 0;
-
+
// Number of lines.
var/*int*/ lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
var/*float*/ totalLineCrossDim = 0;
@@ -833,7 +833,7 @@ var computeLayout = (function() {
var/*float*/ maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
var/*int*/ itemsOnLine = 0;
@@ -860,7 +860,7 @@ var computeLayout = (function() {
if (getPositionType(child) !== CSS_POSITION_ABSOLUTE) {
var/*float*/ outerFlexBasis = child.layout.flexBasis + getMarginAxis(child, mainAxis);
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -872,7 +872,7 @@ var computeLayout = (function() {
if (isFlex(child)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
@@ -888,11 +888,11 @@ var computeLayout = (function() {
currentRelativeChild = child;
child.nextChild = undefined;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
var/*bool*/ canSkipFlex = !performLayout && measureModeCrossDim === CSS_MEASURE_MODE_EXACTLY;
@@ -915,7 +915,7 @@ var computeLayout = (function() {
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
var/*float*/ originalRemainingFreeSpace = remainingFreeSpace;
var/*float*/ deltaFreeSpace = 0;
@@ -925,20 +925,20 @@ var computeLayout = (function() {
var/*float*/ flexGrowFactor;
var/*float*/ baseMainSize;
var/*float*/ boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
var/*float*/ deltaFlexShrinkScaledFactors = 0;
var/*float*/ deltaFlexGrowFactors = 0;
@@ -948,7 +948,7 @@ var computeLayout = (function() {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor !== 0) {
baseMainSize = childFlexBasis +
@@ -979,14 +979,14 @@ var computeLayout = (function() {
}
}
}
-
+
currentRelativeChild = currentRelativeChild.nextChild;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -996,7 +996,7 @@ var computeLayout = (function() {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor !== 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -1011,13 +1011,13 @@ var computeLayout = (function() {
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_ROW);
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1028,7 +1028,7 @@ var computeLayout = (function() {
} else {
childHeight = updatedMainSize + getMarginAxis(currentRelativeChild, CSS_FLEX_DIRECTION_COLUMN);
childHeightMeasureMode = CSS_MEASURE_MODE_EXACTLY;
-
+
if (!isStyleDimDefined(currentRelativeChild, CSS_FLEX_DIRECTION_ROW)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_AT_MOST;
@@ -1037,7 +1037,7 @@ var computeLayout = (function() {
childWidthMeasureMode = CSS_MEASURE_MODE_EXACTLY;
}
}
-
+
var/*bool*/ requiresStretchLayout = !isStyleDimDefined(currentRelativeChild, crossAxis) &&
getAlignItem(node, currentRelativeChild) === CSS_ALIGN_STRETCH;
@@ -1047,7 +1047,7 @@ var computeLayout = (function() {
currentRelativeChild = currentRelativeChild.nextChild;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -1106,7 +1106,7 @@ var computeLayout = (function() {
// we put it at the current accumulated offset.
child.layout[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1120,7 +1120,7 @@ var computeLayout = (function() {
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = fmaxf(crossDim, getDimWithMargin(child, crossAxis));
@@ -1130,12 +1130,12 @@ var computeLayout = (function() {
}
mainDim += trailingPaddingAndBorderMain;
-
+
var/*float*/ containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim === CSS_MEASURE_MODE_UNDEFINED || measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim === CSS_MEASURE_MODE_AT_MOST) {
containerCrossAxis = fminf(containerCrossAxis, availableInnerCrossDim);
}
@@ -1172,14 +1172,14 @@ var computeLayout = (function() {
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
var/*css_align_t*/ alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem === CSS_ALIGN_STRETCH) {
childWidth = child.layout.measuredWidth + getMarginAxis(child, CSS_FLEX_DIRECTION_ROW);
childHeight = child.layout.measuredHeight + getMarginAxis(child, CSS_FLEX_DIRECTION_COLUMN);
var/*bool*/ isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_COLUMN);
childHeight = crossDim;
@@ -1187,7 +1187,7 @@ var computeLayout = (function() {
isCrossSizeDefinite = isStyleDimDefined(child, CSS_FLEX_DIRECTION_ROW);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
@@ -1314,7 +1314,7 @@ var computeLayout = (function() {
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
var/*bool*/ needsMainTrailingPos = false;
@@ -1345,7 +1345,7 @@ var computeLayout = (function() {
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild !== undefined) {
@@ -1367,7 +1367,7 @@ var computeLayout = (function() {
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if (isStyleDimDefined(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN)) {
childHeight = currentAbsoluteChild.style.height + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
} else {
@@ -1384,7 +1384,7 @@ var computeLayout = (function() {
if (isUndefined(childWidth) || isUndefined(childHeight)) {
childWidthMeasureMode = isUndefined(childWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
childHeightMeasureMode = isUndefined(childHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1407,9 +1407,9 @@ var computeLayout = (function() {
childWidth = currentAbsoluteChild.layout.measuredWidth + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW);
childHeight = currentAbsoluteChild.layout.measuredHeight + getMarginAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
layoutNodeInternal(currentAbsoluteChild, childWidth, childHeight, direction, CSS_MEASURE_MODE_EXACTLY, CSS_MEASURE_MODE_EXACTLY, true, 'abs-layout');
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_ROW])) {
currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1417,7 +1417,7 @@ var computeLayout = (function() {
currentAbsoluteChild.layout[measuredDim[CSS_FLEX_DIRECTION_ROW]] -
getPosition(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_ROW]);
}
-
+
if (isPosDefined(currentAbsoluteChild, trailing[CSS_FLEX_DIRECTION_COLUMN]) &&
!isPosDefined(currentAbsoluteChild, leading[CSS_FLEX_DIRECTION_COLUMN])) {
currentAbsoluteChild.layout[leading[CSS_FLEX_DIRECTION_COLUMN]] =
@@ -1430,7 +1430,7 @@ var computeLayout = (function() {
currentAbsoluteChild = currentAbsoluteChild.nextChild;
}
}
-
+
function canUseCachedMeasurement(availableWidth, availableHeight,
marginRow, marginColumn,
widthMeasureMode, heightMeasureMode,
@@ -1443,7 +1443,7 @@ var computeLayout = (function() {
cachedLayout.heightMeasureMode === heightMeasureMode) {
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (cachedLayout.availableWidth === availableWidth &&
cachedLayout.widthMeasureMode === widthMeasureMode &&
@@ -1451,7 +1451,7 @@ var computeLayout = (function() {
availableHeight - marginColumn === cachedLayout.computedHeight) {
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (cachedLayout.availableHeight === availableHeight &&
cachedLayout.heightMeasureMode === heightMeasureMode &&
@@ -1462,7 +1462,7 @@ var computeLayout = (function() {
return false;
}
-
+
//
// This is a wrapper around the layoutNodeImpl function. It determines
// whether the layout request is redundant and can be skipped.
@@ -1481,18 +1481,18 @@ var computeLayout = (function() {
if (needToVisitNode) {
// Invalidate the cached results.
if (layout.cachedMeasurements !== undefined) {
- layout.cachedMeasurements = [];
+ layout.cachedMeasurements = [];
}
if (layout.cachedLayout !== undefined) {
layout.cachedLayout.widthMeasureMode = undefined;
layout.cachedLayout.heightMeasureMode = undefined;
}
}
-
+
var i;
var len;
var cachedResults;
-
+
// Determine whether the results are already cached. We maintain a separate
// cache for layouts and measurements. A layout operation modifies the positions
// and dimensions for nodes in the subtree. The algorithm assumes that each node
@@ -1503,7 +1503,7 @@ var computeLayout = (function() {
if (isMeasureDefined(node)) {
var marginAxisRow = getMarginAxis(node, CSS_FLEX_DIRECTION_ROW);
var marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
-
+
// First, try to use the layout cache.
if (layout.cachedLayout &&
canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
@@ -1538,14 +1538,14 @@ var computeLayout = (function() {
}
}
}
-
+
if (!needToVisitNode && cachedResults !== undefined) {
layout.measureWidth = cachedResults.computedWidth;
layout.measureHeight = cachedResults.computedHeight;
} else {
layoutNodeImpl(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);
layout.lastParentDirection = parentDirection;
-
+
if (cachedResults === undefined) {
var newCacheEntry;
if (performLayout) {
@@ -1562,7 +1562,7 @@ var computeLayout = (function() {
newCacheEntry = {};
layout.cachedMeasurements.push(newCacheEntry);
}
-
+
newCacheEntry.availableWidth = availableWidth;
newCacheEntry.availableHeight = availableHeight;
newCacheEntry.widthMeasureMode = widthMeasureMode;
@@ -1571,23 +1571,23 @@ var computeLayout = (function() {
newCacheEntry.computedHeight = layout.measuredHeight;
}
}
-
+
if (performLayout) {
node.layout.width = node.layout.measuredWidth;
node.layout.height = node.layout.measuredHeight;
layout.shouldUpdate = true;
}
-
+
layout.generationCount = gCurrentGenerationCount;
return (needToVisitNode || cachedResults === undefined);
}
-
+
function layoutNode(node, availableWidth, availableHeight, parentDirection) {
// Increment the generation count. This will force the recursive routine to visit
// all dirty nodes at least once. Subsequent visits will be skipped if the input
// parameters don't change.
gCurrentGenerationCount++;
-
+
// If the caller didn't specify a height/width, use the dimensions
// specified in the style.
if (isUndefined(availableWidth) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_ROW)) {
@@ -1596,10 +1596,10 @@ var computeLayout = (function() {
if (isUndefined(availableHeight) && isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
availableHeight = node.style.height + getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
}
-
+
var widthMeasureMode = isUndefined(availableWidth) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
var heightMeasureMode = isUndefined(availableHeight) ? CSS_MEASURE_MODE_UNDEFINED : CSS_MEASURE_MODE_EXACTLY;
-
+
if (layoutNodeInternal(node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, 'initial')) {
setPosition(node, node.layout.direction);
}
diff --git a/src/__tests__/Layout-test.js b/src/__tests__/Layout-test.js
index 391c518c..7599fd36 100755
--- a/src/__tests__/Layout-test.js
+++ b/src/__tests__/Layout-test.js
@@ -39,14 +39,14 @@ describe('Javascript Only', function() {
{layout: {width: 200}},
{layout: {width: 200}, style: {}, children: []}
);
- });
+ });
it('should only invoke measure function one time in simple layout', function() {
var measureInvocations = 0;
function measure(width, widthMode, height, heightMode) {
measureInvocations++;
return { width: 25, height: 25 };
}
-
+
testLayoutAgainstExpectedOnly(
{style: {width: 100, height: 100}, children: [
{style: {measure: measure}}
@@ -55,17 +55,17 @@ describe('Javascript Only', function() {
{width: 100, height: 25, top: 0, left: 0}
]}
);
-
+
expect(measureInvocations).toEqual(1);
});
});
describe('JavaScript Only: canUseCachedTextMeasurement', function() {
var measureModes = ['undefined', 'exactly', 'at-most'];
-
+
var assertCanReuse = testCanUseCachedMeasurement.bind(null, true);
var assertCannotReuse = testCanUseCachedMeasurement.bind(null, false);
-
+
it('should not reuse when width mode is "exactly" and available width != measurement', function() {
measureModes.forEach(function(widthMeasureMode) {
measureModes.forEach(function(heightMeasureMode) {
@@ -73,12 +73,12 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
var computedHeight = 200;
var availableWidth = widthMeasureMode === 'undefined' ? undefined : computedWidth;
var availableHeight = heightMeasureMode === 'undefined' ? undefined : computedHeight;
-
+
var cacheEntry = {
availableWidth: availableWidth, widthMeasureMode: widthMeasureMode, computedWidth: computedWidth,
availableHeight: availableHeight, heightMeasureMode: heightMeasureMode, computedHeight: computedHeight
};
-
+
assertCannotReuse(
{
availableWidth: computedWidth - 1, widthMeasureMode: 'exactly',
@@ -86,7 +86,7 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
},
cacheEntry
);
-
+
assertCannotReuse(
{
availableWidth: computedWidth + 1, widthMeasureMode: 'exactly',
@@ -97,7 +97,7 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
});
});
});
-
+
it('should not reuse when height mode is "exactly" and available height != measurement', function() {
measureModes.forEach(function(widthMeasureMode) {
measureModes.forEach(function(heightMeasureMode) {
@@ -105,12 +105,12 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
var computedHeight = 200;
var availableWidth = widthMeasureMode === 'undefined' ? undefined : computedWidth;
var availableHeight = heightMeasureMode === 'undefined' ? undefined : computedHeight;
-
+
var cacheEntry = {
availableWidth: availableWidth, widthMeasureMode: widthMeasureMode, computedWidth: computedWidth,
availableHeight: availableHeight, heightMeasureMode: heightMeasureMode, computedHeight: computedHeight
};
-
+
assertCannotReuse(
{
availableWidth: availableWidth, widthMeasureMode: widthMeasureMode,
@@ -118,7 +118,7 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
},
cacheEntry
);
-
+
assertCannotReuse(
{
availableWidth: availableWidth, widthMeasureMode: widthMeasureMode,
@@ -129,7 +129,7 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
});
});
});
-
+
it('should reuse exact matches', function() {
measureModes.forEach(function(widthMeasureMode) {
measureModes.forEach(function(heightMeasureMode) {
@@ -148,13 +148,13 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
});
});
});
-
+
it('should reuse cache entry with unconstrained width when width mode is "exactly" and available width == measurement', function() {
measureModes.forEach(function(heightMeasureMode) {
var computedWidth = 100;
var computedHeight = 200;
var availableHeight = heightMeasureMode === 'undefined' ? undefined : computedHeight;
-
+
assertCanReuse(
{
availableWidth: computedWidth, widthMeasureMode: 'exactly',
@@ -167,13 +167,13 @@ describe('JavaScript Only: canUseCachedTextMeasurement', function() {
);
});
});
-
+
it('should reuse cache entry with unconstrained height when height mode is "exactly" and height == measurement', function() {
measureModes.forEach(function(widthMeasureMode) {
var computedWidth = 100;
var computedHeight = 200;
var availableWidth = widthMeasureMode === 'undefined' ? undefined : computedWidth;
-
+
assertCanReuse(
{
availableWidth: availableWidth, widthMeasureMode: widthMeasureMode,
@@ -2298,7 +2298,7 @@ describe('Layout', function() {
]}
);
});
-
+
it('should center flexible item with max size', function() {
testLayout(
{style: {width: 1000, height: 1000, flexDirection: 'row', justifyContent: 'center'}, children: [
@@ -2309,7 +2309,7 @@ describe('Layout', function() {
]}
);
});
-
+
it('should correctly size flexible items with flex basis and a max width', function() {
testLayout(
{style: {width: 1000, height: 1000, flexDirection: 'row'}, children: [
@@ -2660,7 +2660,7 @@ describe('Layout', function() {
describe('Layout flex:-1', function() {
// Tests for items with flex:-1 in a container with flexDirection:column
-
+
it('should not shrink column node when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100}, children: [
@@ -2675,7 +2675,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink column node when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100}, children: [
@@ -2690,7 +2690,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should not shrink column node with siblings when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100}, children: [
@@ -2709,7 +2709,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink column node with siblings when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100}, children: [
@@ -2728,7 +2728,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink column nodes proportional to their main size when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100}, children: [
@@ -2743,9 +2743,9 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
// Tests for items with flex:-1 and overflow:visible in a container with flexDirection:row
-
+
it('should not shrink visible row node when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2760,7 +2760,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink visible row node when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2776,7 +2776,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should not shrink visible row node with siblings when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2795,7 +2795,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink visible row node with siblings when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2815,7 +2815,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink visible row nodes when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2832,9 +2832,9 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
// Tests for items with flex:-1 and overflow:hidden in a container with flexDirection:row
-
+
it('should not shrink hidden row node when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2864,7 +2864,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should not shrink hidden row node with siblings when there is space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2883,7 +2883,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink hidden row node with siblings when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2902,7 +2902,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink hidden row nodes proportional to their main size when there is not any space left over', function() {
testLayout(
{style: {width: 100, height: 100, flexDirection: 'row'}, children: [
@@ -2917,9 +2917,9 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
// Tests for items with flex:-1 containing a text node
-
+
it('should not shrink text node with siblings when there is space left over', function() {
testLayoutAgainstExpectedOnly(
{style: {width: 213, height: 100, flexDirection: 'row'}, children: [
@@ -2938,7 +2938,7 @@ describe('Layout flex:-1', function() {
]}
);
});
-
+
it('should shrink text node with siblings when there is not any space left over', function() {
testLayout(
{style: {width: 140, height: 100, flexDirection: 'row'}, children: [
diff --git a/src/csharp/Facebook.CSSLayout.Tests/Facebook.CSSLayout.Tests.csproj b/src/csharp/Facebook.CSSLayout.Tests/Facebook.CSSLayout.Tests.csproj
index e1d78dca..2aac63d0 100755
--- a/src/csharp/Facebook.CSSLayout.Tests/Facebook.CSSLayout.Tests.csproj
+++ b/src/csharp/Facebook.CSSLayout.Tests/Facebook.CSSLayout.Tests.csproj
@@ -60,7 +60,7 @@
-
-
\ No newline at end of file
+
diff --git a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs
index c6cc7c18..8a7e9189 100644
--- a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs
+++ b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs
@@ -156,7 +156,7 @@ namespace Facebook.CSSLayout
return boundValue;
}
-
+
private static float boundAxis(CSSNode node, int axis, float value)
{
float paddingAndBorderAxis =
@@ -178,12 +178,12 @@ namespace Facebook.CSSLayout
float trailingPos = node.style.position[trailing[axis]];
return float.IsNaN(trailingPos) ? 0 : -trailingPos;
}
-
+
private static void setPosition(CSSNode node, CSSDirection direction)
{
int mainAxis = resolveAxis(getFlexDirection(node), direction);
int crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node.layout.position[leading[mainAxis]] = node.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) +
getRelativePosition(node, mainAxis);
node.layout.position[trailing[mainAxis]] = node.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) +
@@ -272,7 +272,7 @@ namespace Facebook.CSSLayout
float marginAxisColumn = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
availableHeight = node.style.dimensions[DIMENSION_HEIGHT] + marginAxisColumn;
}
-
+
CSSMeasureMode widthMeasureMode = float.IsNaN(availableWidth) ? CSSMeasureMode.Undefined : CSSMeasureMode.Exactly;
CSSMeasureMode heightMeasureMode = float.IsNaN(availableHeight) ? CSSMeasureMode.Undefined : CSSMeasureMode.Exactly;
@@ -281,7 +281,7 @@ namespace Facebook.CSSLayout
setPosition(node, node.layout.direction);
}
}
-
+
internal static boolean canUseCachedMeasurement(float availableWidth, float availableHeight,
float marginRow, float marginColumn,
CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode,
@@ -295,7 +295,7 @@ namespace Facebook.CSSLayout
{
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
cachedLayout.widthMeasureMode == widthMeasureMode &&
@@ -304,7 +304,7 @@ namespace Facebook.CSSLayout
{
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
cachedLayout.heightMeasureMode == heightMeasureMode &&
@@ -316,7 +316,7 @@ namespace Facebook.CSSLayout
return false;
}
-
+
//
// This is a wrapper around the layoutNodeImpl function. It determines
// whether the layout request is redundant and can be skipped.
@@ -356,8 +356,8 @@ namespace Facebook.CSSLayout
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]);
float marginAxisColumn =
node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) +
- node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
-
+ node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
+
// First, try to use the layout cache.
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
widthMeasureMode, heightMeasureMode, layout.cachedLayout))
@@ -460,7 +460,7 @@ namespace Facebook.CSSLayout
layout.generationCount = layoutContext.currentGenerationCount;
return (needToVisitNode || cachedResults == null);
}
-
+
//
// This is the main routine that implements a subset of the flexbox layout algorithm
// described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.
@@ -497,8 +497,8 @@ namespace Facebook.CSSLayout
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
- // main size. For text blocks, for example, this is the width of the widest word.
- // Calculating the minimum width is expensive, so we forego it and assume a default
+ // main size. For text blocks, for example, this is the width of the widest word.
+ // Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -532,7 +532,7 @@ namespace Facebook.CSSLayout
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
- //
+ //
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
@@ -542,7 +542,7 @@ namespace Facebook.CSSLayout
Assertions.assertCondition(float.IsNaN(availableWidth) ? widthMeasureMode == CSSMeasureMode.Undefined : true, "availableWidth is indefinite so widthMeasureMode must be CSSMeasureMode.Undefined");
Assertions.assertCondition(float.IsNaN(availableHeight) ? heightMeasureMode == CSSMeasureMode.Undefined : true, "availableHeight is indefinite so heightMeasureMode must be CSSMeasureMode.Undefined");
-
+
float paddingAndBorderAxisRow = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW])));
float paddingAndBorderAxisColumn = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
float marginAxisRow = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
@@ -556,7 +556,7 @@ namespace Facebook.CSSLayout
if (isMeasureDefined(node)) {
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode == CSSMeasureMode.Exactly && heightMeasureMode == CSSMeasureMode.Exactly) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -588,7 +588,7 @@ namespace Facebook.CSSLayout
measureDim.height + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -618,7 +618,7 @@ namespace Facebook.CSSLayout
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode == CSSMeasureMode.AtMost && availableWidth <= 0) {
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, float.IsNaN(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -630,7 +630,7 @@ namespace Facebook.CSSLayout
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode == CSSMeasureMode.Exactly && heightMeasureMode == CSSMeasureMode.Exactly) {
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -654,7 +654,7 @@ namespace Facebook.CSSLayout
float leadingPaddingAndBorderCross = (node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]));
float paddingAndBorderAxisMain = ((node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
float paddingAndBorderAxisCross = ((node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (node.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + node.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
-
+
CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -679,7 +679,7 @@ namespace Facebook.CSSLayout
CSSDirection childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (child.style.positionType == CSSPositionType.Absolute) {
@@ -695,27 +695,27 @@ namespace Facebook.CSSLayout
currentAbsoluteChild = child;
child.nextChild = null;
} else {
-
+
if (isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
-
+
// The width is definite, so use that as the flex basis.
child.layout.flexBasis = Math.Max(child.style.dimensions[DIMENSION_WIDTH], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]))));
} else if (!isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
-
+
// The height is definite, so use that as the flex basis.
child.layout.flexBasis = Math.Max(child.style.dimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]))));
} else if (!isFlexBasisAuto(child) && !float.IsNaN(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child.layout.flexBasis = Math.Max(0, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSSConstants.Undefined;
childHeight = CSSConstants.Undefined;
childWidthMeasureMode = CSSMeasureMode.Undefined;
childHeightMeasureMode = CSSMeasureMode.Undefined;
-
+
if ((child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
childWidth = child.style.dimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childWidthMeasureMode = CSSMeasureMode.Exactly;
@@ -724,7 +724,7 @@ namespace Facebook.CSSLayout
childHeight = child.style.dimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
childHeightMeasureMode = CSSMeasureMode.Exactly;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -745,21 +745,21 @@ namespace Facebook.CSSLayout
// Measure the child
layoutNodeInternal(layoutContext, child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
-
+
child.layout.flexBasis = Math.Max(isMainAxisRow ? child.layout.measuredDimensions[DIMENSION_WIDTH] : child.layout.measuredDimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
int startOfLineIndex = 0;
int endOfLineIndex = 0;
-
+
// Number of lines.
int lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
float totalLineCrossDim = 0;
@@ -767,7 +767,7 @@ namespace Facebook.CSSLayout
float maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
int itemsOnLine = 0;
@@ -794,7 +794,7 @@ namespace Facebook.CSSLayout
if (child.style.positionType != CSSPositionType.Absolute) {
float outerFlexBasis = child.layout.flexBasis + (child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -806,7 +806,7 @@ namespace Facebook.CSSLayout
if ((child.style.positionType == CSSPositionType.Relative && child.style.flex != 0)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
@@ -822,11 +822,11 @@ namespace Facebook.CSSLayout
currentRelativeChild = child;
child.nextChild = null;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
boolean canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureMode.Exactly;
@@ -849,7 +849,7 @@ namespace Facebook.CSSLayout
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
float originalRemainingFreeSpace = remainingFreeSpace;
float deltaFreeSpace = 0;
@@ -859,20 +859,20 @@ namespace Facebook.CSSLayout
float flexGrowFactor;
float baseMainSize;
float boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
float deltaFlexShrinkScaledFactors = 0;
float deltaFlexGrowFactors = 0;
@@ -882,7 +882,7 @@ namespace Facebook.CSSLayout
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
baseMainSize = childFlexBasis +
@@ -913,14 +913,14 @@ namespace Facebook.CSSLayout
}
}
}
-
+
currentRelativeChild = currentRelativeChild.nextChild;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -930,7 +930,7 @@ namespace Facebook.CSSLayout
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -945,13 +945,13 @@ namespace Facebook.CSSLayout
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childWidthMeasureMode = CSSMeasureMode.Exactly;
-
+
if (!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = float.IsNaN(childHeight) ? CSSMeasureMode.Undefined : CSSMeasureMode.AtMost;
@@ -962,7 +962,7 @@ namespace Facebook.CSSLayout
} else {
childHeight = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
childHeightMeasureMode = CSSMeasureMode.Exactly;
-
+
if (!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = float.IsNaN(childWidth) ? CSSMeasureMode.Undefined : CSSMeasureMode.AtMost;
@@ -971,7 +971,7 @@ namespace Facebook.CSSLayout
childWidthMeasureMode = CSSMeasureMode.Exactly;
}
}
-
+
boolean requiresStretchLayout = !(currentRelativeChild.style.dimensions[dim[crossAxis]] >= 0.0) &&
getAlignItem(node, currentRelativeChild) == CSSAlign.Stretch;
@@ -981,7 +981,7 @@ namespace Facebook.CSSLayout
currentRelativeChild = currentRelativeChild.nextChild;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -1040,7 +1040,7 @@ namespace Facebook.CSSLayout
// we put it at the current accumulated offset.
child.layout.position[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1054,7 +1054,7 @@ namespace Facebook.CSSLayout
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + (child.layout.measuredDimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = Math.Max(crossDim, (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
@@ -1064,12 +1064,12 @@ namespace Facebook.CSSLayout
}
mainDim += trailingPaddingAndBorderMain;
-
+
float containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim == CSSMeasureMode.Undefined || measureModeCrossDim == CSSMeasureMode.AtMost) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim == CSSMeasureMode.AtMost) {
containerCrossAxis = Math.Min(containerCrossAxis, availableInnerCrossDim);
}
@@ -1106,14 +1106,14 @@ namespace Facebook.CSSLayout
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
CSSAlign alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem == CSSAlign.Stretch) {
childWidth = child.layout.measuredDimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childHeight = child.layout.measuredDimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
boolean isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0);
childHeight = crossDim;
@@ -1121,7 +1121,7 @@ namespace Facebook.CSSLayout
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = float.IsNaN(childWidth) ? CSSMeasureMode.Undefined : CSSMeasureMode.Exactly;
@@ -1248,7 +1248,7 @@ namespace Facebook.CSSLayout
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
boolean needsMainTrailingPos = false;
@@ -1279,7 +1279,7 @@ namespace Facebook.CSSLayout
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild != null) {
@@ -1301,7 +1301,7 @@ namespace Facebook.CSSLayout
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
childHeight = currentAbsoluteChild.style.dimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
} else {
@@ -1318,7 +1318,7 @@ namespace Facebook.CSSLayout
if (float.IsNaN(childWidth) || float.IsNaN(childHeight)) {
childWidthMeasureMode = float.IsNaN(childWidth) ? CSSMeasureMode.Undefined : CSSMeasureMode.Exactly;
childHeightMeasureMode = float.IsNaN(childHeight) ? CSSMeasureMode.Undefined : CSSMeasureMode.Exactly;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1341,9 +1341,9 @@ namespace Facebook.CSSLayout
childWidth = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childHeight = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
}
-
+
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, CSSMeasureMode.Exactly, CSSMeasureMode.Exactly, true, "abs-layout");
-
+
if (!float.IsNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) &&
!!float.IsNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_ROW]])) {
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1351,7 +1351,7 @@ namespace Facebook.CSSLayout
currentAbsoluteChild.layout.measuredDimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
(float.IsNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]);
}
-
+
if (!float.IsNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) &&
!!float.IsNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_COLUMN]])) {
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
diff --git a/src/csharp/Facebook.CSSLayout/MeasureOutput.cs b/src/csharp/Facebook.CSSLayout/MeasureOutput.cs
index 1d2bb1ce..4462cd75 100644
--- a/src/csharp/Facebook.CSSLayout/MeasureOutput.cs
+++ b/src/csharp/Facebook.CSSLayout/MeasureOutput.cs
@@ -33,4 +33,4 @@ namespace Facebook.CSSLayout
get { return Height; }
}
}
-}
\ No newline at end of file
+}
diff --git a/src/csharp/Facebook.CSSLayout/Spacing.cs b/src/csharp/Facebook.CSSLayout/Spacing.cs
index 6ca1f28d..8c718e25 100644
--- a/src/csharp/Facebook.CSSLayout/Spacing.cs
+++ b/src/csharp/Facebook.CSSLayout/Spacing.cs
@@ -137,7 +137,7 @@ namespace Facebook.CSSLayout
internal float get(int spacingType)
{
- float defaultValue =
+ float defaultValue =
(mDefaultSpacing != null)
? mDefaultSpacing[spacingType]
: (spacingType == START || spacingType == END ? CSSConstants.Undefined : 0);
diff --git a/src/csharp/Makefile b/src/csharp/Makefile
index f879150c..3bc1dc47 100644
--- a/src/csharp/Makefile
+++ b/src/csharp/Makefile
@@ -35,4 +35,3 @@ build-release: build
.PHONY: build
build:
${MSB} ${NAME}.sln /p:Configuration=${conf} /t:"Facebook_CSSLayout:Rebuild;Facebook_CSSLayout_Tests:Rebuild"
-
diff --git a/src/java/src/com/facebook/csslayout/CSSCachedMeasurement.java b/src/java/src/com/facebook/csslayout/CSSCachedMeasurement.java
index 92b3f77b..2ada4cf8 100644
--- a/src/java/src/com/facebook/csslayout/CSSCachedMeasurement.java
+++ b/src/java/src/com/facebook/csslayout/CSSCachedMeasurement.java
@@ -13,7 +13,7 @@ public class CSSCachedMeasurement {
public float availableHeight;
public CSSMeasureMode widthMeasureMode = null;
public CSSMeasureMode heightMeasureMode = null;
-
+
public float computedWidth;
public float computedHeight;
}
diff --git a/src/java/src/com/facebook/csslayout/CSSLayout.java b/src/java/src/com/facebook/csslayout/CSSLayout.java
index a484bd94..18e55d2c 100644
--- a/src/java/src/com/facebook/csslayout/CSSLayout.java
+++ b/src/java/src/com/facebook/csslayout/CSSLayout.java
@@ -17,7 +17,7 @@ public class CSSLayout {
// This value was chosen based on empiracle data. Even the most complicated
// layouts should not require more than 16 entries to fit within the cache.
public static final int MAX_CACHED_RESULT_COUNT = 16;
-
+
public static final int POSITION_LEFT = 0;
public static final int POSITION_TOP = 1;
public static final int POSITION_RIGHT = 2;
@@ -29,36 +29,36 @@ public class CSSLayout {
public float[] position = new float[4];
public float[] dimensions = new float[2];
public CSSDirection direction = CSSDirection.LTR;
-
+
public float flexBasis;
-
+
public int generationCount;
public CSSDirection lastParentDirection;
-
+
public int nextCachedMeasurementsIndex;
public CSSCachedMeasurement[] cachedMeasurements = new CSSCachedMeasurement[MAX_CACHED_RESULT_COUNT];
public float[] measuredDimensions = new float[2];
-
+
public CSSCachedMeasurement cachedLayout = new CSSCachedMeasurement();
-
+
CSSLayout() {
resetResult();
}
-
+
public void resetResult() {
Arrays.fill(position, 0);
Arrays.fill(dimensions, CSSConstants.UNDEFINED);
direction = CSSDirection.LTR;
-
+
flexBasis = 0;
-
+
generationCount = 0;
lastParentDirection = null;
-
+
nextCachedMeasurementsIndex = 0;
measuredDimensions[DIMENSION_WIDTH] = CSSConstants.UNDEFINED;
measuredDimensions[DIMENSION_HEIGHT] = CSSConstants.UNDEFINED;
-
+
cachedLayout.widthMeasureMode = null;
cachedLayout.heightMeasureMode = null;
}
diff --git a/src/java/src/com/facebook/csslayout/CSSNode.java b/src/java/src/com/facebook/csslayout/CSSNode.java
index d8b5243d..b6be7216 100644
--- a/src/java/src/com/facebook/csslayout/CSSNode.java
+++ b/src/java/src/com/facebook/csslayout/CSSNode.java
@@ -64,7 +64,7 @@ public class CSSNode {
public int lineIndex = 0;
/*package*/ CSSNode nextChild;
-
+
private @Nullable ArrayList mChildren;
private @Nullable CSSNode mParent;
private @Nullable MeasureFunction mMeasureFunction = null;
diff --git a/src/java/src/com/facebook/csslayout/LayoutEngine.java b/src/java/src/com/facebook/csslayout/LayoutEngine.java
index 1b888497..9da1af06 100644
--- a/src/java/src/com/facebook/csslayout/LayoutEngine.java
+++ b/src/java/src/com/facebook/csslayout/LayoutEngine.java
@@ -21,9 +21,9 @@ import static com.facebook.csslayout.CSSLayout.POSITION_TOP;
* Calculates layouts based on CSS style. See {@link #layoutNode(CSSNode, float, float)}.
*/
public class LayoutEngine {
-
+
private static final boolean POSITIVE_FLEX_IS_AUTO = false;
-
+
private static final int CSS_FLEX_DIRECTION_COLUMN =
CSSFlexDirection.COLUMN.ordinal();
private static final int CSS_FLEX_DIRECTION_COLUMN_REVERSE =
@@ -77,7 +77,7 @@ public class LayoutEngine {
Spacing.END,
Spacing.END
};
-
+
private static boolean isFlexBasisAuto(CSSNode node) {
if (POSITIVE_FLEX_IS_AUTO) {
// All flex values are auto.
@@ -87,7 +87,7 @@ public class LayoutEngine {
return node.style.flex <= 0;
}
}
-
+
private static float getFlexGrowFactor(CSSNode node) {
// Flex grow is implied by positive values for flex.
if (node.style.flex > 0) {
@@ -95,7 +95,7 @@ public class LayoutEngine {
}
return 0;
}
-
+
private static float getFlexShrinkFactor(CSSNode node) {
if (POSITIVE_FLEX_IS_AUTO) {
// A flex shrink factor of 1 is implied by non-zero values for flex.
@@ -137,7 +137,7 @@ public class LayoutEngine {
return boundValue;
}
-
+
private static float boundAxis(CSSNode node, int axis, float value) {
float paddingAndBorderAxis =
node.style.padding.getWithFallback(leadingSpacing[axis], leading[axis]) +
@@ -156,11 +156,11 @@ public class LayoutEngine {
float trailingPos = node.style.position[trailing[axis]];
return Float.isNaN(trailingPos) ? 0 : -trailingPos;
}
-
+
private static void setPosition(CSSNode node, CSSDirection direction) {
int mainAxis = resolveAxis(getFlexDirection(node), direction);
int crossAxis = getCrossFlexDirection(mainAxis, direction);
-
+
node.layout.position[leading[mainAxis]] = node.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) +
getRelativePosition(node, mainAxis);
node.layout.position[trailing[mainAxis]] = node.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) +
@@ -230,7 +230,7 @@ public class LayoutEngine {
// all dirty nodes at least once. Subsequent visits will be skipped if the input
// parameters don't change.
layoutContext.currentGenerationCount++;
-
+
// If the caller didn't specify a height/width, use the dimensions
// specified in the style.
if (Float.isNaN(availableWidth) && node.style.dimensions[DIMENSION_WIDTH] >= 0.0) {
@@ -241,15 +241,15 @@ public class LayoutEngine {
float marginAxisColumn = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
availableHeight = node.style.dimensions[DIMENSION_HEIGHT] + marginAxisColumn;
}
-
+
CSSMeasureMode widthMeasureMode = Float.isNaN(availableWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
CSSMeasureMode heightMeasureMode = Float.isNaN(availableHeight) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
-
+
if (layoutNodeInternal(layoutContext, node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, true, "initial")) {
setPosition(node, node.layout.direction);
}
}
-
+
/*package*/ static boolean canUseCachedMeasurement(float availableWidth, float availableHeight,
float marginRow, float marginColumn,
CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode,
@@ -261,7 +261,7 @@ public class LayoutEngine {
cachedLayout.heightMeasureMode == heightMeasureMode) {
return true;
}
-
+
// If the width is an exact match, try a fuzzy match on the height.
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
cachedLayout.widthMeasureMode == widthMeasureMode &&
@@ -269,7 +269,7 @@ public class LayoutEngine {
FloatUtil.floatsEqual(availableHeight - marginColumn, cachedLayout.computedHeight)) {
return true;
}
-
+
// If the height is an exact match, try a fuzzy match on the width.
if (FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
cachedLayout.heightMeasureMode == heightMeasureMode &&
@@ -277,10 +277,10 @@ public class LayoutEngine {
FloatUtil.floatsEqual(availableWidth - marginRow, cachedLayout.computedWidth)) {
return true;
}
-
+
return false;
}
-
+
//
// This is a wrapper around the layoutNodeImpl function. It determines
// whether the layout request is redundant and can be skipped.
@@ -300,19 +300,19 @@ public class LayoutEngine {
boolean performLayout,
String reason) {
CSSLayout layout = node.layout;
-
+
boolean needToVisitNode = (node.isDirty() && layout.generationCount != layoutContext.currentGenerationCount) ||
layout.lastParentDirection != parentDirection;
-
+
if (needToVisitNode) {
// Invalidate the cached results.
layout.nextCachedMeasurementsIndex = 0;
layout.cachedLayout.widthMeasureMode = null;
layout.cachedLayout.heightMeasureMode = null;
}
-
+
CSSCachedMeasurement cachedResults = null;
-
+
// Determine whether the results are already cached. We maintain a separate
// cache for layouts and measurements. A layout operation modifies the positions
// and dimensions for nodes in the subtree. The algorithm assumes that each node
@@ -326,8 +326,8 @@ public class LayoutEngine {
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]);
float marginAxisColumn =
node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) +
- node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
-
+ node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
+
// First, try to use the layout cache.
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
@@ -347,7 +347,7 @@ public class LayoutEngine {
FloatUtil.floatsEqual(layout.cachedLayout.availableHeight, availableHeight) &&
layout.cachedLayout.widthMeasureMode == widthMeasureMode &&
layout.cachedLayout.heightMeasureMode == heightMeasureMode) {
-
+
cachedResults = layout.cachedLayout;
}
} else {
@@ -362,15 +362,15 @@ public class LayoutEngine {
}
}
}
-
+
if (!needToVisitNode && cachedResults != null) {
layout.measuredDimensions[DIMENSION_WIDTH] = cachedResults.computedWidth;
layout.measuredDimensions[DIMENSION_HEIGHT] = cachedResults.computedHeight;
} else {
layoutNodeImpl(layoutContext, node, availableWidth, availableHeight, parentDirection, widthMeasureMode, heightMeasureMode, performLayout);
-
+
layout.lastParentDirection = parentDirection;
-
+
if (cachedResults == null) {
if (layout.nextCachedMeasurementsIndex == CSSLayout.MAX_CACHED_RESULT_COUNT) {
layout.nextCachedMeasurementsIndex = 0;
@@ -389,7 +389,7 @@ public class LayoutEngine {
}
layout.nextCachedMeasurementsIndex++;
}
-
+
newCacheEntry.availableWidth = availableWidth;
newCacheEntry.availableHeight = availableHeight;
newCacheEntry.widthMeasureMode = widthMeasureMode;
@@ -398,18 +398,18 @@ public class LayoutEngine {
newCacheEntry.computedHeight = layout.measuredDimensions[DIMENSION_HEIGHT];
}
}
-
+
if (performLayout) {
node.layout.dimensions[DIMENSION_WIDTH] = node.layout.measuredDimensions[DIMENSION_WIDTH];
node.layout.dimensions[DIMENSION_HEIGHT] = node.layout.measuredDimensions[DIMENSION_HEIGHT];
node.markHasNewLayout();
}
-
+
layout.generationCount = layoutContext.currentGenerationCount;
return (needToVisitNode || cachedResults == null);
}
-
-
+
+
//
// This is the main routine that implements a subset of the flexbox layout algorithm
// described in the W3C CSS documentation: https://www.w3.org/TR/css3-flexbox/.
@@ -446,8 +446,8 @@ public class LayoutEngine {
//
// Deviations from standard:
// * Section 4.5 of the spec indicates that all flex items have a default minimum
- // main size. For text blocks, for example, this is the width of the widest word.
- // Calculating the minimum width is expensive, so we forego it and assume a default
+ // main size. For text blocks, for example, this is the width of the widest word.
+ // Calculating the minimum width is expensive, so we forego it and assume a default
// minimum main size of 0.
// * Min/Max sizes in the main axis are not honored when resolving flexible lengths.
// * The spec indicates that the default value for 'flexDirection' is 'row', but
@@ -481,7 +481,7 @@ public class LayoutEngine {
// - CSS_MEASURE_MODE_UNDEFINED: max content
// - CSS_MEASURE_MODE_EXACTLY: fill available
// - CSS_MEASURE_MODE_AT_MOST: fit content
- //
+ //
// When calling layoutNodeImpl and layoutNodeInternal, if the caller passes an available size of
// undefined then it must also pass a measure mode of CSS_MEASURE_MODE_UNDEFINED in that dimension.
//
@@ -498,7 +498,7 @@ public class LayoutEngine {
Assertions.assertCondition(Float.isNaN(availableWidth) ? widthMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableWidth is indefinite so widthMeasureMode must be CSSMeasureMode.UNDEFINED");
Assertions.assertCondition(Float.isNaN(availableHeight) ? heightMeasureMode == CSSMeasureMode.UNDEFINED : true, "availableHeight is indefinite so heightMeasureMode must be CSSMeasureMode.UNDEFINED");
-
+
float paddingAndBorderAxisRow = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW])));
float paddingAndBorderAxisColumn = ((node.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (node.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + node.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN])));
float marginAxisRow = (node.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
@@ -512,7 +512,7 @@ public class LayoutEngine {
if (isMeasureDefined(node)) {
float innerWidth = availableWidth - marginAxisRow - paddingAndBorderAxisRow;
float innerHeight = availableHeight - marginAxisColumn - paddingAndBorderAxisColumn;
-
+
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
// Don't bother sizing the text if both dimensions are already defined.
@@ -544,7 +544,7 @@ public class LayoutEngine {
measureDim.height + paddingAndBorderAxisColumn :
availableHeight - marginAxisColumn);
}
-
+
return;
}
@@ -574,7 +574,7 @@ public class LayoutEngine {
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
if (widthMeasureMode == CSSMeasureMode.AT_MOST && availableWidth <= 0) {
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, 0);
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, Float.isNaN(availableHeight) ? 0 : (availableHeight - marginAxisColumn));
@@ -586,7 +586,7 @@ public class LayoutEngine {
node.layout.measuredDimensions[DIMENSION_HEIGHT] = boundAxis(node, CSS_FLEX_DIRECTION_COLUMN, 0);
return;
}
-
+
// If we're being asked to use an exact width/height, there's no need to measure the children.
if (widthMeasureMode == CSSMeasureMode.EXACTLY && heightMeasureMode == CSSMeasureMode.EXACTLY) {
node.layout.measuredDimensions[DIMENSION_WIDTH] = boundAxis(node, CSS_FLEX_DIRECTION_ROW, availableWidth - marginAxisRow);
@@ -610,7 +610,7 @@ public class LayoutEngine {
float leadingPaddingAndBorderCross = (node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]));
float paddingAndBorderAxisMain = ((node.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + node.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (node.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + node.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis])));
float paddingAndBorderAxisCross = ((node.style.padding.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + node.style.border.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis])) + (node.style.padding.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]) + node.style.border.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
-
+
CSSMeasureMode measureModeMainDim = isMainAxisRow ? widthMeasureMode : heightMeasureMode;
CSSMeasureMode measureModeCrossDim = isMainAxisRow ? heightMeasureMode : widthMeasureMode;
@@ -635,7 +635,7 @@ public class LayoutEngine {
CSSDirection childDirection = resolveDirection(child, direction);
setPosition(child, childDirection);
}
-
+
// Absolute-positioned children don't participate in flex layout. Add them
// to a list that we can process later.
if (child.style.positionType == CSSPositionType.ABSOLUTE) {
@@ -651,27 +651,27 @@ public class LayoutEngine {
currentAbsoluteChild = child;
child.nextChild = null;
} else {
-
+
if (isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
-
+
// The width is definite, so use that as the flex basis.
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_WIDTH], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]))));
} else if (!isMainAxisRow && (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
-
+
// The height is definite, so use that as the flex basis.
child.layout.flexBasis = Math.max(child.style.dimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN])) + (child.style.padding.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]) + child.style.border.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]))));
} else if (!isFlexBasisAuto(child) && !Float.isNaN(availableInnerMainDim)) {
-
+
// If the basis isn't 'auto', it is assumed to be zero.
child.layout.flexBasis = Math.max(0, ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
} else {
-
+
// Compute the flex basis and hypothetical main size (i.e. the clamped flex basis).
childWidth = CSSConstants.UNDEFINED;
childHeight = CSSConstants.UNDEFINED;
childWidthMeasureMode = CSSMeasureMode.UNDEFINED;
childHeightMeasureMode = CSSMeasureMode.UNDEFINED;
-
+
if ((child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
childWidth = child.style.dimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
@@ -680,7 +680,7 @@ public class LayoutEngine {
childHeight = child.style.dimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
}
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -701,21 +701,21 @@ public class LayoutEngine {
// Measure the child
layoutNodeInternal(layoutContext, child, childWidth, childHeight, direction, childWidthMeasureMode, childHeightMeasureMode, false, "measure");
-
+
child.layout.flexBasis = Math.max(isMainAxisRow ? child.layout.measuredDimensions[DIMENSION_WIDTH] : child.layout.measuredDimensions[DIMENSION_HEIGHT], ((child.style.padding.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.border.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis])) + (child.style.padding.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]) + child.style.border.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]))));
}
}
}
// STEP 4: COLLECT FLEX ITEMS INTO FLEX LINES
-
+
// Indexes of children that represent the first and last items in the line.
int startOfLineIndex = 0;
int endOfLineIndex = 0;
-
+
// Number of lines.
int lineCount = 0;
-
+
// Accumulated cross dimensions of all lines so far.
float totalLineCrossDim = 0;
@@ -723,7 +723,7 @@ public class LayoutEngine {
float maxLineMainDim = 0;
while (endOfLineIndex < childCount) {
-
+
// Number of items on the currently line. May be different than the difference
// between start and end indicates because we skip over absolute-positioned items.
int itemsOnLine = 0;
@@ -750,7 +750,7 @@ public class LayoutEngine {
if (child.style.positionType != CSSPositionType.ABSOLUTE) {
float outerFlexBasis = child.layout.flexBasis + (child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
-
+
// 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 (sizeConsumedOnCurrentLine + outerFlexBasis > availableInnerMainDim && isNodeFlexWrap && itemsOnLine > 0) {
@@ -762,7 +762,7 @@ public class LayoutEngine {
if ((child.style.positionType == CSSPositionType.RELATIVE && child.style.flex != 0)) {
totalFlexGrowFactors += getFlexGrowFactor(child);
-
+
// Unlike the grow factor, the shrink factor is scaled relative to the child
// dimension.
totalFlexShrinkScaledFactors += getFlexShrinkFactor(child) * child.layout.flexBasis;
@@ -778,11 +778,11 @@ public class LayoutEngine {
currentRelativeChild = child;
child.nextChild = null;
}
-
+
i++;
endOfLineIndex++;
}
-
+
// If we don't need to measure the cross axis, we can skip the entire flex step.
boolean canSkipFlex = !performLayout && measureModeCrossDim == CSSMeasureMode.EXACTLY;
@@ -805,7 +805,7 @@ public class LayoutEngine {
// its content. Consequently, remainingFreeSpace is 0 - sizeConsumedOnCurrentLine.
remainingFreeSpace = -sizeConsumedOnCurrentLine;
}
-
+
float originalRemainingFreeSpace = remainingFreeSpace;
float deltaFreeSpace = 0;
@@ -815,20 +815,20 @@ public class LayoutEngine {
float flexGrowFactor;
float baseMainSize;
float boundMainSize;
-
+
// Do two passes over the flex items to figure out how to distribute the remaining space.
// The first pass finds the items whose min/max constraints trigger, freezes them at those
// sizes, and excludes those sizes from the remaining space. The second pass sets the size
// of each flexible item. It distributes the remaining space amongst the items whose min/max
// constraints didn't trigger in pass 1. For the other items, it sets their sizes by forcing
- // their min/max constraints to trigger again.
+ // their min/max constraints to trigger again.
//
// This two pass approach for resolving min/max constraints deviates from the spec. The
// spec (https://www.w3.org/TR/css-flexbox-1/#resolve-flexible-lengths) describes a process
// that needs to be repeated a variable number of times. The algorithm implemented here
// won't handle all cases but it was simpler to implement and it mitigates performance
// concerns because we know exactly how many passes it'll do.
-
+
// First pass: detect the flex items whose min/max constraints trigger
float deltaFlexShrinkScaledFactors = 0;
float deltaFlexGrowFactors = 0;
@@ -838,7 +838,7 @@ public class LayoutEngine {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
baseMainSize = childFlexBasis +
@@ -869,14 +869,14 @@ public class LayoutEngine {
}
}
}
-
+
currentRelativeChild = currentRelativeChild.nextChild;
}
-
+
totalFlexShrinkScaledFactors += deltaFlexShrinkScaledFactors;
totalFlexGrowFactors += deltaFlexGrowFactors;
remainingFreeSpace += deltaFreeSpace;
-
+
// Second pass: resolve the sizes of the flexible items
deltaFreeSpace = 0;
currentRelativeChild = firstRelativeChild;
@@ -886,7 +886,7 @@ public class LayoutEngine {
if (remainingFreeSpace < 0) {
flexShrinkScaledFactor = getFlexShrinkFactor(currentRelativeChild) * childFlexBasis;
-
+
// Is this child able to shrink?
if (flexShrinkScaledFactor != 0) {
updatedMainSize = boundAxis(currentRelativeChild, mainAxis, childFlexBasis +
@@ -901,13 +901,13 @@ public class LayoutEngine {
remainingFreeSpace / totalFlexGrowFactors * flexGrowFactor);
}
}
-
+
deltaFreeSpace -= updatedMainSize - childFlexBasis;
-
+
if (isMainAxisRow) {
childWidth = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
-
+
if (!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
childHeight = availableInnerCrossDim;
childHeightMeasureMode = Float.isNaN(childHeight) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.AT_MOST;
@@ -918,7 +918,7 @@ public class LayoutEngine {
} else {
childHeight = updatedMainSize + (currentRelativeChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentRelativeChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
childHeightMeasureMode = CSSMeasureMode.EXACTLY;
-
+
if (!(currentRelativeChild.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0)) {
childWidth = availableInnerCrossDim;
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.AT_MOST;
@@ -927,7 +927,7 @@ public class LayoutEngine {
childWidthMeasureMode = CSSMeasureMode.EXACTLY;
}
}
-
+
boolean requiresStretchLayout = !(currentRelativeChild.style.dimensions[dim[crossAxis]] >= 0.0) &&
getAlignItem(node, currentRelativeChild) == CSSAlign.STRETCH;
@@ -937,7 +937,7 @@ public class LayoutEngine {
currentRelativeChild = currentRelativeChild.nextChild;
}
}
-
+
remainingFreeSpace = originalRemainingFreeSpace + deltaFreeSpace;
// STEP 6: MAIN-AXIS JUSTIFICATION & CROSS-AXIS SIZE DETERMINATION
@@ -996,7 +996,7 @@ public class LayoutEngine {
// we put it at the current accumulated offset.
child.layout.position[pos[mainAxis]] += mainDim;
}
-
+
// Now that we placed the element, we need to update the variables.
// We need to do that only for relative elements. Absolute elements
// do not take part in that phase.
@@ -1010,7 +1010,7 @@ public class LayoutEngine {
// The main dimension is the sum of all the elements dimension plus
// the spacing.
mainDim += betweenMainDim + (child.layout.measuredDimensions[dim[mainAxis]] + child.style.margin.getWithFallback(leadingSpacing[mainAxis], leading[mainAxis]) + child.style.margin.getWithFallback(trailingSpacing[mainAxis], trailing[mainAxis]));
-
+
// The cross dimension is the max of the elements dimension since there
// can only be one element in that cross dimension.
crossDim = Math.max(crossDim, (child.layout.measuredDimensions[dim[crossAxis]] + child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])));
@@ -1020,12 +1020,12 @@ public class LayoutEngine {
}
mainDim += trailingPaddingAndBorderMain;
-
+
float containerCrossAxis = availableInnerCrossDim;
if (measureModeCrossDim == CSSMeasureMode.UNDEFINED || measureModeCrossDim == CSSMeasureMode.AT_MOST) {
// Compute the cross axis from the max cross dimension of the children.
containerCrossAxis = boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross) - paddingAndBorderAxisCross;
-
+
if (measureModeCrossDim == CSSMeasureMode.AT_MOST) {
containerCrossAxis = Math.min(containerCrossAxis, availableInnerCrossDim);
}
@@ -1062,14 +1062,14 @@ public class LayoutEngine {
// For a relative children, we're either using alignItems (parent) or
// alignSelf (child) in order to determine the position in the cross axis
CSSAlign alignItem = getAlignItem(node, child);
-
+
// If the child uses align stretch, we need to lay it out one more time, this time
// forcing the cross-axis size to be the computed cross size for the current line.
if (alignItem == CSSAlign.STRETCH) {
childWidth = child.layout.measuredDimensions[DIMENSION_WIDTH] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childHeight = child.layout.measuredDimensions[DIMENSION_HEIGHT] + (child.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + child.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
boolean isCrossSizeDefinite = false;
-
+
if (isMainAxisRow) {
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0);
childHeight = crossDim;
@@ -1077,7 +1077,7 @@ public class LayoutEngine {
isCrossSizeDefinite = (child.style.dimensions[dim[CSS_FLEX_DIRECTION_ROW]] >= 0.0);
childWidth = crossDim;
}
-
+
// If the child defines a definite size for its cross axis, there's no need to stretch.
if (!isCrossSizeDefinite) {
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
@@ -1204,7 +1204,7 @@ public class LayoutEngine {
boundAxisWithinMinAndMax(node, crossAxis, totalLineCrossDim + paddingAndBorderAxisCross)),
paddingAndBorderAxisCross);
}
-
+
// STEP 10: SETTING TRAILING POSITIONS FOR CHILDREN
if (performLayout) {
boolean needsMainTrailingPos = false;
@@ -1235,7 +1235,7 @@ public class LayoutEngine {
}
}
}
-
+
// STEP 11: SIZING AND POSITIONING ABSOLUTE CHILDREN
currentAbsoluteChild = firstAbsoluteChild;
while (currentAbsoluteChild != null) {
@@ -1257,7 +1257,7 @@ public class LayoutEngine {
childWidth = boundAxis(currentAbsoluteChild, CSS_FLEX_DIRECTION_ROW, childWidth);
}
}
-
+
if ((currentAbsoluteChild.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
childHeight = currentAbsoluteChild.style.dimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
} else {
@@ -1274,7 +1274,7 @@ public class LayoutEngine {
if (Float.isNaN(childWidth) || Float.isNaN(childHeight)) {
childWidthMeasureMode = Float.isNaN(childWidth) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
childHeightMeasureMode = Float.isNaN(childHeight) ? CSSMeasureMode.UNDEFINED : CSSMeasureMode.EXACTLY;
-
+
// According to the spec, if the main size is not definite and the
// child's inline axis is parallel to the main axis (i.e. it's
// horizontal), the child should be sized using "UNDEFINED" in
@@ -1297,9 +1297,9 @@ public class LayoutEngine {
childWidth = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_WIDTH] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_ROW], leading[CSS_FLEX_DIRECTION_ROW]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_ROW], trailing[CSS_FLEX_DIRECTION_ROW]));
childHeight = currentAbsoluteChild.layout.measuredDimensions[DIMENSION_HEIGHT] + (currentAbsoluteChild.style.margin.getWithFallback(leadingSpacing[CSS_FLEX_DIRECTION_COLUMN], leading[CSS_FLEX_DIRECTION_COLUMN]) + currentAbsoluteChild.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]));
}
-
+
layoutNodeInternal(layoutContext, currentAbsoluteChild, childWidth, childHeight, direction, CSSMeasureMode.EXACTLY, CSSMeasureMode.EXACTLY, true, "abs-layout");
-
+
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) &&
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_ROW]])) {
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_ROW]] =
@@ -1307,7 +1307,7 @@ public class LayoutEngine {
currentAbsoluteChild.layout.measuredDimensions[dim[CSS_FLEX_DIRECTION_ROW]] -
(Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]) ? 0 : currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_ROW]]);
}
-
+
if (!Float.isNaN(currentAbsoluteChild.style.position[trailing[CSS_FLEX_DIRECTION_COLUMN]]) &&
!!Float.isNaN(currentAbsoluteChild.style.position[leading[CSS_FLEX_DIRECTION_COLUMN]])) {
currentAbsoluteChild.layout.position[leading[CSS_FLEX_DIRECTION_COLUMN]] =
diff --git a/src/java/tests/com/facebook/csslayout/LayoutCachingTest.java b/src/java/tests/com/facebook/csslayout/LayoutCachingTest.java
index 0fa61088..492571cf 100644
--- a/src/java/tests/com/facebook/csslayout/LayoutCachingTest.java
+++ b/src/java/tests/com/facebook/csslayout/LayoutCachingTest.java
@@ -43,7 +43,7 @@ public class LayoutCachingTest {
root.addChildAt(c0, 0);
root.addChildAt(c1, 1);
c0.addChildAt(c0c0, 0);
-
+
root.calculateLayout(layoutContext);
assertTreeHasNewLayout(true, root);
markLayoutAppliedForTree(root);