From e280a577ae2cdc7fb53b0d3feed8be4c5a438c74 Mon Sep 17 00:00:00 2001 From: Christopher Chedeau Date: Fri, 25 Sep 2015 13:09:58 -0700 Subject: [PATCH] Fix width being ignored when has a value of 0 https://github.com/facebook/css-layout/commit/8f6a96adbcb2b0389f948b8113d8b7cb8991bb2d added a test in isDimDefined that checks if `value > 0.0`, but unfortunately, it did not faithfully port the JavaScript version which is `value >= 0.0`. Sadly, no test covered this so it went unnoticed. --- dist/css-layout.h | 2 +- dist/css-layout.jar | Bin 13819 -> 13871 bytes dist/css-layout.js | 2 +- dist/css-layout.min.js.map | 2 +- src/CSharpTranspiler.js | 2 +- src/JavaTranspiler.js | 2 +- src/Layout.c | 2 +- src/Layout.js | 2 +- src/__tests__/Layout-test.c | 34 +++++++++++++++++ src/__tests__/Layout-test.js | 11 ++++++ .../LayoutEngineTest.cs | 36 ++++++++++++++++++ src/csharp/Facebook.CSSLayout/LayoutEngine.cs | 16 ++++---- .../com/facebook/csslayout/LayoutEngine.java | 16 ++++---- .../facebook/csslayout/LayoutEngineTest.java | 36 ++++++++++++++++++ 14 files changed, 140 insertions(+), 23 deletions(-) diff --git a/dist/css-layout.h b/dist/css-layout.h index c0293f75..4f85096a 100644 --- a/dist/css-layout.h +++ b/dist/css-layout.h @@ -613,7 +613,7 @@ static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) { static bool isDimDefined(css_node_t *node, css_flex_direction_t axis) { float value = node->style.dimensions[dim[axis]]; - return !isUndefined(value) && value > 0.0; + return !isUndefined(value) && value >= 0.0; } static bool isPosDefined(css_node_t *node, css_position_t position) { diff --git a/dist/css-layout.jar b/dist/css-layout.jar index 79c83dd640b2b1c517dffaeb121eee3b5ff38dc4..d983bc0e41054a12dc21030a392f807c3bc487e6 100644 GIT binary patch delta 10987 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≷WcoX7(0$4-@5#wdosP~=E@JWFFq*Fdr2&> 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 KKg{`G= 0) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n\n function isUndefined(value) {\n return value === undefined;\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 getLeadingLocations(axis) {\n var locations = [leading[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('start');\n }\n\n return locations;\n }\n\n function getTrailingLocations(axis) {\n var locations = [trailing[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('end');\n }\n\n return locations;\n }\n\n function getMargin(node, locations) {\n return getSpacing(node, 'margin', '', locations);\n }\n\n function getLeadingMargin(node, axis) {\n return getMargin(node, getLeadingLocations(axis));\n }\n\n function getTrailingMargin(node, axis) {\n return getMargin(node, getTrailingLocations(axis));\n }\n\n function getPadding(node, locations) {\n return getPositiveSpacing(node, 'padding', '', locations);\n }\n\n function getLeadingPadding(node, axis) {\n return getPadding(node, getLeadingLocations(axis));\n }\n\n function getTrailingPadding(node, axis) {\n return getPadding(node, getTrailingLocations(axis));\n }\n\n function getBorder(node, locations) {\n return getPositiveSpacing(node, 'border', 'Width', locations);\n }\n\n function getLeadingBorder(node, axis) {\n return getBorder(node, getLeadingLocations(axis));\n }\n\n function getTrailingBorder(node, axis) {\n return getBorder(node, getTrailingLocations(axis));\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 getBorderAxis(node, axis) {\n return getLeadingBorder(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 ('justifyContent' in node.style) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if ('alignContent' in node.style) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if ('alignSelf' in child.style) {\n return child.style.alignSelf;\n }\n if ('alignItems' in node.style) {\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 ('direction' in node.style) {\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 ('flexDirection' in node.style) {\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 ('position' in node.style) {\n return node.style.position;\n }\n return 'relative';\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n 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[dim[axis]] + getMarginAxis(node, axis);\n }\n\n function isDimDefined(node, axis) {\n return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return !isUndefined(node.style[pos]);\n }\n\n function isMeasureDefined(node) {\n return 'measure' in node.style;\n }\n\n function getPosition(node, pos) {\n if (pos in node.style) {\n return node.style[pos];\n }\n return 0;\n }\n\n function boundAxis(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 (!isUndefined(max) && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (!isUndefined(min) && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n\n // When the user specifically sets a value for width or height\n function setDimensionFromStyle(node, axis) {\n // The parent already computed us a width or height. We just skip it\n if (!isUndefined(node.layout[dim[axis]])) {\n return;\n }\n // We only run if there's a width or height defined\n if (!isDimDefined(node, axis)) {\n return;\n }\n\n // The dimensions can never be smaller than the padding and border\n node.layout[dim[axis]] = fmaxf(\n boundAxis(node, axis, node.style[dim[axis]]),\n getPaddingAndBorderAxis(node, axis)\n );\n }\n\n function setTrailingPosition(node, child, axis) {\n child.layout[trailing[axis]] = node.layout[dim[axis]] -\n child.layout[dim[axis]] - 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 (leading[axis] in node.style) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n\n function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) {\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\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/*(c)!css_flex_direction_t*//*(java)!int*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n\n // Handle width and height style attributes\n setDimensionFromStyle(node, mainAxis);\n setDimensionFromStyle(node, crossAxis);\n\n // Set the resolved resolution in the node's layout\n node.layout.direction = direction;\n\n // The position is set by the parent, but we need to complete it with a\n // delta composed of the margin and left/top/right/bottom\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 // Inline immutable values from the target node to avoid excessive method\n // invocations during the layout calculation.\n var/*int*/ childCount = node.children.length;\n var/*float*/ paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n if (isMeasureDefined(node)) {\n var/*bool*/ isResolvedRowDimDefined = !isUndefined(node.layout[dim[resolvedRowAxis]]);\n\n var/*float*/ width = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n width = node.style.width;\n } else if (isResolvedRowDimDefined) {\n width = node.layout[dim[resolvedRowAxis]];\n } else {\n width = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis);\n }\n width -= paddingAndBorderAxisResolvedRow;\n\n // We only need to give a dimension for the text if we haven't got any\n // for it computed yet. It can either be from the style attribute or because\n // the element is flexible.\n var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;\n var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&\n isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);\n\n // Let's not measure the text if we already know both dimensions\n if (isRowUndefined || isColumnUndefined) {\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n width\n );\n if (isRowUndefined) {\n node.layout.width = measureDim.width +\n paddingAndBorderAxisResolvedRow;\n }\n if (isColumnUndefined) {\n node.layout.height = measureDim.height +\n getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n }\n if (childCount === 0) {\n return;\n }\n }\n\n var/*bool*/ isNodeFlexWrap = isFlexWrap(node);\n\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n\n var/*float*/ leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(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/*bool*/ isMainDimDefined = !isUndefined(node.layout[dim[mainAxis]]);\n var/*bool*/ isCrossDimDefined = !isUndefined(node.layout[dim[crossAxis]]);\n var/*bool*/ isMainRowDirection = isRowDirection(mainAxis);\n\n var/*int*/ i;\n var/*int*/ ii;\n var/*css_node_t**/ child;\n var/*(c)!css_flex_direction_t*//*(java)!int*/ axis;\n\n var/*css_node_t**/ firstAbsoluteChild = null;\n var/*css_node_t**/ currentAbsoluteChild = null;\n\n var/*float*/ definedMainDim = CSS_UNDEFINED;\n if (isMainDimDefined) {\n definedMainDim = node.layout[dim[mainAxis]] - paddingAndBorderAxisMain;\n }\n\n // We want to execute the next two loops one per line with flex-wrap\n var/*int*/ startLine = 0;\n var/*int*/ endLine = 0;\n // var/*int*/ nextOffset = 0;\n var/*int*/ alreadyComputedNextLayout = 0;\n // We aggregate the total dimensions of the container in those two variables\n var/*float*/ linesCrossDim = 0;\n var/*float*/ linesMainDim = 0;\n var/*int*/ linesCount = 0;\n while (endLine < childCount) {\n // Layout non flexible children and count children by type\n\n // mainContentDim is accumulation of the dimensions and margin of all the\n // non flexible children. This will be used in order to either set the\n // dimensions of the node if none already exist, or to compute the\n // remaining space left for the flexible children.\n var/*float*/ mainContentDim = 0;\n\n // There are three kind of children, non flexible, flexible and absolute.\n // We need to know how many there are in order to distribute the space.\n var/*int*/ flexibleChildrenCount = 0;\n var/*float*/ totalFlexible = 0;\n var/*int*/ nonFlexibleChildrenCount = 0;\n\n // Use the line loop to position children in the main axis for as long\n // as they are using a simple stacking behaviour. Children that are\n // immediately stacked in the initial loop will not be touched again\n // in .\n var/*bool*/ isSimpleStackMain =\n (isMainDimDefined && justifyContent == CSS_JUSTIFY_FLEX_START) ||\n (!isMainDimDefined && justifyContent != CSS_JUSTIFY_CENTER);\n var/*int*/ firstComplexMain = (isSimpleStackMain ? childCount : startLine);\n\n // Use the initial line loop to position children in the cross axis for\n // as long as they are relatively positioned with alignment STRETCH or\n // FLEX_START. Children that are immediately stacked in the initial loop\n // will not be touched again in .\n var/*bool*/ isSimpleStackCross = true;\n var/*int*/ firstComplexCross = childCount;\n\n var/*css_node_t**/ firstFlexChild = null;\n var/*css_node_t**/ currentFlexChild = null;\n\n var/*float*/ mainDim = leadingPaddingAndBorderMain;\n var/*float*/ crossDim = 0;\n\n var/*float*/ maxWidth;\n for (i = startLine; i < childCount; ++i) {\n child = node.children[i];\n child.lineIndex = linesCount;\n\n child.nextAbsoluteChild = null;\n child.nextFlexChild = null;\n\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n\n // Pre-fill cross axis dimensions when the child is using stretch before\n // we call the recursive layout pass\n if (alignItem === CSS_ALIGN_STRETCH &&\n getPositionType(child) === CSS_POSITION_RELATIVE &&\n isCrossDimDefined &&\n !isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, node.layout[dim[crossAxis]] -\n paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Store a private linked list of absolutely positioned children\n // so that we can efficiently traverse them later.\n if (firstAbsoluteChild === null) {\n firstAbsoluteChild = child;\n }\n if (currentAbsoluteChild !== null) {\n currentAbsoluteChild.nextAbsoluteChild = child;\n }\n currentAbsoluteChild = child;\n\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getPaddingAndBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n }\n\n var/*float*/ nextContentDim = 0;\n\n // It only makes sense to consider a child flexible if we have a computed\n // dimension for the node.\n if (isMainDimDefined && isFlex(child)) {\n flexibleChildrenCount++;\n totalFlexible += child.style.flex;\n\n // Store a private linked list of flexible children so that we can\n // efficiently traverse them later.\n if (firstFlexChild === null) {\n firstFlexChild = child;\n }\n if (currentFlexChild !== null) {\n currentFlexChild.nextFlexChild = child;\n }\n currentFlexChild = child;\n\n // Even if we don't know its exact size yet, we already know the padding,\n // border and margin. We'll use this partial information, which represents\n // the smallest possible size for the child, to compute the remaining\n // available space.\n nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +\n getMarginAxis(child, mainAxis);\n\n } else {\n maxWidth = CSS_UNDEFINED;\n if (!isMainRowDirection) {\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n paddingAndBorderAxisResolvedRow;\n } else {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n paddingAndBorderAxisResolvedRow;\n }\n }\n\n // This is the main recursive call. We layout non flexible children.\n if (alreadyComputedNextLayout === 0) {\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n\n // Absolute positioned elements do not take part of the layout, so we\n // don't use them to compute mainContentDim\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n nonFlexibleChildrenCount++;\n // At this point we know the final size and margin of the element.\n nextContentDim = getDimWithMargin(child, mainAxis);\n }\n }\n\n // The element we are about to add would make us go to the next line\n if (isNodeFlexWrap &&\n isMainDimDefined &&\n mainContentDim + nextContentDim > definedMainDim &&\n // If there's only one element, then it's bigger than the content\n // and needs its own line\n i !== startLine) {\n nonFlexibleChildrenCount--;\n alreadyComputedNextLayout = 1;\n break;\n }\n\n // Disable simple stacking in the main axis for the current line as\n // we found a non-trivial child. The remaining children will be laid out\n // in .\n if (isSimpleStackMain &&\n (getPositionType(child) != CSS_POSITION_RELATIVE || isFlex(child))) {\n isSimpleStackMain = false;\n firstComplexMain = i;\n }\n\n // Disable simple stacking in the cross axis for the current line as\n // we found a non-trivial child. The remaining children will be laid out\n // in .\n if (isSimpleStackCross &&\n (getPositionType(child) != CSS_POSITION_RELATIVE ||\n (alignItem !== CSS_ALIGN_STRETCH && alignItem != CSS_ALIGN_FLEX_START) ||\n isUndefined(child.layout[dim[crossAxis]]))) {\n isSimpleStackCross = false;\n firstComplexCross = i;\n }\n\n if (isSimpleStackMain) {\n child.layout[pos[mainAxis]] += mainDim;\n if (isMainDimDefined) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n mainDim += getDimWithMargin(child, mainAxis);\n crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n\n if (isSimpleStackCross) {\n child.layout[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;\n if (isCrossDimDefined) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n\n alreadyComputedNextLayout = 0;\n mainContentDim += nextContentDim;\n endLine = i + 1;\n }\n\n // Layout flexible children and allocate empty space\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 // The remaining available space that needs to be allocated\n var/*float*/ remainingMainDim = 0;\n if (isMainDimDefined) {\n remainingMainDim = definedMainDim - mainContentDim;\n } else {\n remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;\n }\n\n // If there are flexible children in the mix, they are going to fill the\n // remaining space\n if (flexibleChildrenCount !== 0) {\n var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible;\n var/*float*/ baseMainDim;\n var/*float*/ boundMainDim;\n\n // If the flex share of remaining space doesn't meet min/max bounds,\n // remove this child from flex calculations.\n currentFlexChild = firstFlexChild;\n while (currentFlexChild !== null) {\n baseMainDim = flexibleMainDim * currentFlexChild.style.flex +\n getPaddingAndBorderAxis(currentFlexChild, mainAxis);\n boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);\n\n if (baseMainDim !== boundMainDim) {\n remainingMainDim -= boundMainDim;\n totalFlexible -= currentFlexChild.style.flex;\n }\n\n currentFlexChild = currentFlexChild.nextFlexChild;\n }\n flexibleMainDim = remainingMainDim / totalFlexible;\n\n // The non flexible children can overflow the container, in this case\n // we should just assume that there is no space available.\n if (flexibleMainDim < 0) {\n flexibleMainDim = 0;\n }\n\n currentFlexChild = firstFlexChild;\n while (currentFlexChild !== null) {\n // At this point we know the final size of the element in the main\n // dimension\n currentFlexChild.layout[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,\n flexibleMainDim * currentFlexChild.style.flex +\n getPaddingAndBorderAxis(currentFlexChild, mainAxis)\n );\n\n maxWidth = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n paddingAndBorderAxisResolvedRow;\n } else if (!isMainRowDirection) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n paddingAndBorderAxisResolvedRow;\n }\n\n // And we recursively call the layout algorithm for this child\n layoutNode(/*(java)!layoutContext, */currentFlexChild, maxWidth, direction);\n\n child = currentFlexChild;\n currentFlexChild = currentFlexChild.nextFlexChild;\n child.nextFlexChild = null;\n }\n\n // We use justifyContent to figure out how to allocate the remaining\n // space available\n } else if (justifyContent !== CSS_JUSTIFY_FLEX_START) {\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingMainDim / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingMainDim;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingMainDim = fmaxf(remainingMainDim, 0);\n if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount - 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 = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount);\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n // Position elements in the main axis and compute dimensions\n\n // At this point, all the children have their dimensions set. We need to\n // find their position. In order to do that, we accumulate data in\n // variables that are also useful to compute the total dimensions of the\n // container!\n mainDim += leadingMainDim;\n\n for (i = firstComplexMain; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\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 } else {\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 // Define the trailing position accordingly.\n if (isMainDimDefined) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n // Now that we placed the element, we need to update the variables\n // We only need to do that for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\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, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n }\n }\n\n var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]];\n if (!isCrossDimDefined) {\n containerCrossAxis = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),\n paddingAndBorderAxisCross\n );\n }\n\n // Position elements in the cross axis\n for (i = firstComplexCross; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[crossAxis])) {\n // In case the child is absolutely positionned and has a\n // top/left/bottom/right being set, we override all the previously\n // computed positions to set it correctly.\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\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 if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n if (alignItem === CSS_ALIGN_STRETCH) {\n // You can only stretch if the dimension has not already been set\n // previously.\n if (isUndefined(child.layout[dim[crossAxis]])) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, containerCrossAxis -\n paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n // The remaining space between the parent dimensions+padding and child\n // dimensions+margin.\n var/*float*/ remainingCrossDim = containerCrossAxis -\n paddingAndBorderAxisCross - 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\n // And we apply the position\n child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;\n\n // Define the trailing position accordingly.\n if (isCrossDimDefined) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n linesCrossDim += crossDim;\n linesMainDim = fmaxf(linesMainDim, mainDim);\n linesCount += 1;\n startLine = endLine;\n }\n\n // \n //\n // Note(prenaux): More than one line, we need to layout the crossAxis\n // according to alignContent.\n //\n // Note that we could probably remove and handle the one line case\n // here too, but for the moment this is safer since it won't interfere with\n // previously working code.\n //\n // See specs:\n // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm\n // section 9.4\n //\n if (linesCount > 1 && isCrossDimDefined) {\n var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] -\n paddingAndBorderAxisCross;\n var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;\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 (nodeCrossAxisInnerSize > linesCrossDim) {\n crossDimLead = (remainingAlignContentDim / linesCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < linesCount; ++i) {\n var/*int*/ startIndex = endIndex;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (ii = startIndex; ii < childCount; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (!isUndefined(child.layout[dim[crossAxis]])) {\n lineHeight = fmaxf(\n lineHeight,\n child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis)\n );\n }\n }\n endIndex = ii;\n lineHeight += crossDimLead;\n\n for (ii = startIndex; ii < endIndex; ++ii) {\n child = node.children[ii];\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[dim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n var/*float*/ childHeight = child.layout[dim[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 undefined\n // (auto) crossAxis dimension.\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n // If the user didn't specify a width or height, and it has not been set\n // by the container, then we set it via the children.\n if (!isMainDimDefined) {\n node.layout[dim[mainAxis]] = fmaxf(\n // We're missing the last padding at this point to get the final\n // dimension\n boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),\n // We can never assign a width smaller than the padding and borders\n paddingAndBorderAxisMain\n );\n\n if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||\n mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsMainTrailingPos = true;\n }\n }\n\n if (!isCrossDimDefined) {\n node.layout[dim[crossAxis]] = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),\n paddingAndBorderAxisCross\n );\n\n if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||\n crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsCrossTrailingPos = true;\n }\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 // Calculate dimensions for absolutely positioned elements\n currentAbsoluteChild = firstAbsoluteChild;\n while (currentAbsoluteChild !== null) {\n // Pre-fill dimensions when using absolute position and both offsets for\n // the axis are defined (either both left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(currentAbsoluteChild, axis) &&\n isPosDefined(currentAbsoluteChild, leading[axis]) &&\n isPosDefined(currentAbsoluteChild, trailing[axis])) {\n currentAbsoluteChild.layout[dim[axis]] = fmaxf(\n boundAxis(currentAbsoluteChild, axis, node.layout[dim[axis]] -\n getBorderAxis(node, axis) -\n getMarginAxis(currentAbsoluteChild, axis) -\n getPosition(currentAbsoluteChild, leading[axis]) -\n getPosition(currentAbsoluteChild, trailing[axis])\n ),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(currentAbsoluteChild, axis)\n );\n }\n\n if (isPosDefined(currentAbsoluteChild, trailing[axis]) &&\n !isPosDefined(currentAbsoluteChild, leading[axis])) {\n currentAbsoluteChild.layout[leading[axis]] =\n node.layout[dim[axis]] -\n currentAbsoluteChild.layout[dim[axis]] -\n getPosition(currentAbsoluteChild, trailing[axis]);\n }\n }\n\n child = currentAbsoluteChild;\n currentAbsoluteChild = currentAbsoluteChild.nextAbsoluteChild;\n child.nextAbsoluteChild = null;\n }\n }\n\n return {\n computeLayout: layoutNode,\n fillNodes: fillNodes\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 computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n };\n}));\n"]} \ No newline at end of file +{"version":3,"file":"css-layout.min.js","sources":["css-layout.js"],"names":["root","factory","define","amd","exports","module","computeLayout","this","capitalizeFirst","str","charAt","toUpperCase","slice","getSpacing","node","type","suffix","locations","i","length","location","key","style","fillNodes","layout","width","undefined","height","top","left","right","bottom","children","forEach","getPositiveSpacing","isUndefined","value","isRowDirection","flexDirection","CSS_FLEX_DIRECTION_ROW","CSS_FLEX_DIRECTION_ROW_REVERSE","isColumnDirection","CSS_FLEX_DIRECTION_COLUMN","CSS_FLEX_DIRECTION_COLUMN_REVERSE","getLeadingLocations","axis","leading","unshift","getTrailingLocations","trailing","getMargin","getLeadingMargin","getTrailingMargin","getPadding","getLeadingPadding","getTrailingPadding","getBorder","getLeadingBorder","getTrailingBorder","getLeadingPaddingAndBorder","getTrailingPaddingAndBorder","getBorderAxis","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","isFlex","CSS_POSITION_RELATIVE","flex","isFlexWrap","flexWrap","getDimWithMargin","dim","isDimDefined","isPosDefined","pos","isMeasureDefined","getPosition","boundAxis","min","row","minWidth","row-reverse","column","minHeight","column-reverse","max","maxWidth","maxHeight","boundValue","fmaxf","a","b","setDimensionFromStyle","setTrailingPosition","getRelativePosition","layoutNode","parentMaxWidth","mainAxis","crossAxis","resolvedRowAxis","childCount","paddingAndBorderAxisResolvedRow","isResolvedRowDimDefined","CSS_UNDEFINED","isRowUndefined","isColumnUndefined","measureDim","measure","ii","isNodeFlexWrap","leadingPaddingAndBorderMain","leadingPaddingAndBorderCross","paddingAndBorderAxisMain","paddingAndBorderAxisCross","isMainDimDefined","isCrossDimDefined","isMainRowDirection","firstAbsoluteChild","currentAbsoluteChild","definedMainDim","startLine","endLine","alreadyComputedNextLayout","linesCrossDim","linesMainDim","linesCount","mainContentDim","flexibleChildrenCount","totalFlexible","nonFlexibleChildrenCount","isSimpleStackMain","CSS_JUSTIFY_FLEX_START","CSS_JUSTIFY_CENTER","firstComplexMain","isSimpleStackCross","firstComplexCross","firstFlexChild","currentFlexChild","mainDim","crossDim","lineIndex","nextAbsoluteChild","nextFlexChild","alignItem","CSS_ALIGN_STRETCH","CSS_POSITION_ABSOLUTE","nextContentDim","CSS_ALIGN_FLEX_START","leadingMainDim","betweenMainDim","remainingMainDim","baseMainDim","boundMainDim","flexibleMainDim","CSS_JUSTIFY_FLEX_END","CSS_JUSTIFY_SPACE_BETWEEN","CSS_JUSTIFY_SPACE_AROUND","containerCrossAxis","leadingCrossDim","remainingCrossDim","CSS_ALIGN_CENTER","nodeCrossAxisInnerSize","remainingAlignContentDim","crossDimLead","currentLead","CSS_ALIGN_FLEX_END","endIndex","startIndex","lineHeight","alignContentAlignItem","childHeight","needsMainTrailingPos","needsCrossTrailingPos"],"mappings":"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","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/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 CSS_UNDEFINED;\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 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\n function capitalizeFirst(str) {\n return str.charAt(0).toUpperCase() + str.slice(1);\n }\n\n function getSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style) {\n return node.style[key];\n }\n }\n\n return 0;\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) {\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 node.children.forEach(fillNodes);\n return node;\n }\n\n function getPositiveSpacing(node, type, suffix, locations) {\n for (var i = 0; i < locations.length; ++i) {\n var location = locations[i];\n\n var key = type + capitalizeFirst(location) + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n\n key = type + suffix;\n if (key in node.style && node.style[key] >= 0) {\n return node.style[key];\n }\n }\n\n return 0;\n }\n\n function isUndefined(value) {\n return value === undefined;\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 getLeadingLocations(axis) {\n var locations = [leading[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('start');\n }\n\n return locations;\n }\n\n function getTrailingLocations(axis) {\n var locations = [trailing[axis]];\n if (isRowDirection(axis)) {\n locations.unshift('end');\n }\n\n return locations;\n }\n\n function getMargin(node, locations) {\n return getSpacing(node, 'margin', '', locations);\n }\n\n function getLeadingMargin(node, axis) {\n return getMargin(node, getLeadingLocations(axis));\n }\n\n function getTrailingMargin(node, axis) {\n return getMargin(node, getTrailingLocations(axis));\n }\n\n function getPadding(node, locations) {\n return getPositiveSpacing(node, 'padding', '', locations);\n }\n\n function getLeadingPadding(node, axis) {\n return getPadding(node, getLeadingLocations(axis));\n }\n\n function getTrailingPadding(node, axis) {\n return getPadding(node, getTrailingLocations(axis));\n }\n\n function getBorder(node, locations) {\n return getPositiveSpacing(node, 'border', 'Width', locations);\n }\n\n function getLeadingBorder(node, axis) {\n return getBorder(node, getLeadingLocations(axis));\n }\n\n function getTrailingBorder(node, axis) {\n return getBorder(node, getTrailingLocations(axis));\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 getBorderAxis(node, axis) {\n return getLeadingBorder(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 ('justifyContent' in node.style) {\n return node.style.justifyContent;\n }\n return 'flex-start';\n }\n\n function getAlignContent(node) {\n if ('alignContent' in node.style) {\n return node.style.alignContent;\n }\n return 'flex-start';\n }\n\n function getAlignItem(node, child) {\n if ('alignSelf' in child.style) {\n return child.style.alignSelf;\n }\n if ('alignItems' in node.style) {\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 ('direction' in node.style) {\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 ('flexDirection' in node.style) {\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 ('position' in node.style) {\n return node.style.position;\n }\n return 'relative';\n }\n\n function isFlex(node) {\n return (\n getPositionType(node) === CSS_POSITION_RELATIVE &&\n 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[dim[axis]] + getMarginAxis(node, axis);\n }\n\n function isDimDefined(node, axis) {\n return !isUndefined(node.style[dim[axis]]) && node.style[dim[axis]] >= 0;\n }\n\n function isPosDefined(node, pos) {\n return !isUndefined(node.style[pos]);\n }\n\n function isMeasureDefined(node) {\n return 'measure' in node.style;\n }\n\n function getPosition(node, pos) {\n if (pos in node.style) {\n return node.style[pos];\n }\n return 0;\n }\n\n function boundAxis(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 (!isUndefined(max) && max >= 0 && boundValue > max) {\n boundValue = max;\n }\n if (!isUndefined(min) && min >= 0 && boundValue < min) {\n boundValue = min;\n }\n return boundValue;\n }\n\n function fmaxf(a, b) {\n if (a > b) {\n return a;\n }\n return b;\n }\n\n // When the user specifically sets a value for width or height\n function setDimensionFromStyle(node, axis) {\n // The parent already computed us a width or height. We just skip it\n if (!isUndefined(node.layout[dim[axis]])) {\n return;\n }\n // We only run if there's a width or height defined\n if (!isDimDefined(node, axis)) {\n return;\n }\n\n // The dimensions can never be smaller than the padding and border\n node.layout[dim[axis]] = fmaxf(\n boundAxis(node, axis, node.style[dim[axis]]),\n getPaddingAndBorderAxis(node, axis)\n );\n }\n\n function setTrailingPosition(node, child, axis) {\n child.layout[trailing[axis]] = node.layout[dim[axis]] -\n child.layout[dim[axis]] - 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 (leading[axis] in node.style) {\n return getPosition(node, leading[axis]);\n }\n return -getPosition(node, trailing[axis]);\n }\n\n function layoutNode(node, parentMaxWidth, /*css_direction_t*/parentDirection) {\n var/*css_direction_t*/ direction = resolveDirection(node, parentDirection);\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/*(c)!css_flex_direction_t*//*(java)!int*/ resolvedRowAxis = resolveAxis(CSS_FLEX_DIRECTION_ROW, direction);\n\n // Handle width and height style attributes\n setDimensionFromStyle(node, mainAxis);\n setDimensionFromStyle(node, crossAxis);\n\n // Set the resolved resolution in the node's layout\n node.layout.direction = direction;\n\n // The position is set by the parent, but we need to complete it with a\n // delta composed of the margin and left/top/right/bottom\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 // Inline immutable values from the target node to avoid excessive method\n // invocations during the layout calculation.\n var/*int*/ childCount = node.children.length;\n var/*float*/ paddingAndBorderAxisResolvedRow = getPaddingAndBorderAxis(node, resolvedRowAxis);\n\n if (isMeasureDefined(node)) {\n var/*bool*/ isResolvedRowDimDefined = !isUndefined(node.layout[dim[resolvedRowAxis]]);\n\n var/*float*/ width = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n width = node.style.width;\n } else if (isResolvedRowDimDefined) {\n width = node.layout[dim[resolvedRowAxis]];\n } else {\n width = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis);\n }\n width -= paddingAndBorderAxisResolvedRow;\n\n // We only need to give a dimension for the text if we haven't got any\n // for it computed yet. It can either be from the style attribute or because\n // the element is flexible.\n var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined;\n var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) &&\n isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]);\n\n // Let's not measure the text if we already know both dimensions\n if (isRowUndefined || isColumnUndefined) {\n var/*css_dim_t*/ measureDim = node.style.measure(\n /*(c)!node->context,*/\n /*(java)!layoutContext.measureOutput,*/\n width\n );\n if (isRowUndefined) {\n node.layout.width = measureDim.width +\n paddingAndBorderAxisResolvedRow;\n }\n if (isColumnUndefined) {\n node.layout.height = measureDim.height +\n getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);\n }\n }\n if (childCount === 0) {\n return;\n }\n }\n\n var/*bool*/ isNodeFlexWrap = isFlexWrap(node);\n\n var/*css_justify_t*/ justifyContent = getJustifyContent(node);\n\n var/*float*/ leadingPaddingAndBorderMain = getLeadingPaddingAndBorder(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/*bool*/ isMainDimDefined = !isUndefined(node.layout[dim[mainAxis]]);\n var/*bool*/ isCrossDimDefined = !isUndefined(node.layout[dim[crossAxis]]);\n var/*bool*/ isMainRowDirection = isRowDirection(mainAxis);\n\n var/*int*/ i;\n var/*int*/ ii;\n var/*css_node_t**/ child;\n var/*(c)!css_flex_direction_t*//*(java)!int*/ axis;\n\n var/*css_node_t**/ firstAbsoluteChild = null;\n var/*css_node_t**/ currentAbsoluteChild = null;\n\n var/*float*/ definedMainDim = CSS_UNDEFINED;\n if (isMainDimDefined) {\n definedMainDim = node.layout[dim[mainAxis]] - paddingAndBorderAxisMain;\n }\n\n // We want to execute the next two loops one per line with flex-wrap\n var/*int*/ startLine = 0;\n var/*int*/ endLine = 0;\n // var/*int*/ nextOffset = 0;\n var/*int*/ alreadyComputedNextLayout = 0;\n // We aggregate the total dimensions of the container in those two variables\n var/*float*/ linesCrossDim = 0;\n var/*float*/ linesMainDim = 0;\n var/*int*/ linesCount = 0;\n while (endLine < childCount) {\n // Layout non flexible children and count children by type\n\n // mainContentDim is accumulation of the dimensions and margin of all the\n // non flexible children. This will be used in order to either set the\n // dimensions of the node if none already exist, or to compute the\n // remaining space left for the flexible children.\n var/*float*/ mainContentDim = 0;\n\n // There are three kind of children, non flexible, flexible and absolute.\n // We need to know how many there are in order to distribute the space.\n var/*int*/ flexibleChildrenCount = 0;\n var/*float*/ totalFlexible = 0;\n var/*int*/ nonFlexibleChildrenCount = 0;\n\n // Use the line loop to position children in the main axis for as long\n // as they are using a simple stacking behaviour. Children that are\n // immediately stacked in the initial loop will not be touched again\n // in .\n var/*bool*/ isSimpleStackMain =\n (isMainDimDefined && justifyContent == CSS_JUSTIFY_FLEX_START) ||\n (!isMainDimDefined && justifyContent != CSS_JUSTIFY_CENTER);\n var/*int*/ firstComplexMain = (isSimpleStackMain ? childCount : startLine);\n\n // Use the initial line loop to position children in the cross axis for\n // as long as they are relatively positioned with alignment STRETCH or\n // FLEX_START. Children that are immediately stacked in the initial loop\n // will not be touched again in .\n var/*bool*/ isSimpleStackCross = true;\n var/*int*/ firstComplexCross = childCount;\n\n var/*css_node_t**/ firstFlexChild = null;\n var/*css_node_t**/ currentFlexChild = null;\n\n var/*float*/ mainDim = leadingPaddingAndBorderMain;\n var/*float*/ crossDim = 0;\n\n var/*float*/ maxWidth;\n for (i = startLine; i < childCount; ++i) {\n child = node.children[i];\n child.lineIndex = linesCount;\n\n child.nextAbsoluteChild = null;\n child.nextFlexChild = null;\n\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n\n // Pre-fill cross axis dimensions when the child is using stretch before\n // we call the recursive layout pass\n if (alignItem === CSS_ALIGN_STRETCH &&\n getPositionType(child) === CSS_POSITION_RELATIVE &&\n isCrossDimDefined &&\n !isDimDefined(child, crossAxis)) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, node.layout[dim[crossAxis]] -\n paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n } else if (getPositionType(child) === CSS_POSITION_ABSOLUTE) {\n // Store a private linked list of absolutely positioned children\n // so that we can efficiently traverse them later.\n if (firstAbsoluteChild === null) {\n firstAbsoluteChild = child;\n }\n if (currentAbsoluteChild !== null) {\n currentAbsoluteChild.nextAbsoluteChild = child;\n }\n currentAbsoluteChild = child;\n\n // Pre-fill dimensions when using absolute position and both offsets for the axis are defined (either both\n // left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(child, axis) &&\n isPosDefined(child, leading[axis]) &&\n isPosDefined(child, trailing[axis])) {\n child.layout[dim[axis]] = fmaxf(\n boundAxis(child, axis, node.layout[dim[axis]] -\n getPaddingAndBorderAxis(node, axis) -\n getMarginAxis(child, axis) -\n getPosition(child, leading[axis]) -\n getPosition(child, trailing[axis])),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, axis)\n );\n }\n }\n }\n\n var/*float*/ nextContentDim = 0;\n\n // It only makes sense to consider a child flexible if we have a computed\n // dimension for the node.\n if (isMainDimDefined && isFlex(child)) {\n flexibleChildrenCount++;\n totalFlexible += child.style.flex;\n\n // Store a private linked list of flexible children so that we can\n // efficiently traverse them later.\n if (firstFlexChild === null) {\n firstFlexChild = child;\n }\n if (currentFlexChild !== null) {\n currentFlexChild.nextFlexChild = child;\n }\n currentFlexChild = child;\n\n // Even if we don't know its exact size yet, we already know the padding,\n // border and margin. We'll use this partial information, which represents\n // the smallest possible size for the child, to compute the remaining\n // available space.\n nextContentDim = getPaddingAndBorderAxis(child, mainAxis) +\n getMarginAxis(child, mainAxis);\n\n } else {\n maxWidth = CSS_UNDEFINED;\n if (!isMainRowDirection) {\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n paddingAndBorderAxisResolvedRow;\n } else {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n paddingAndBorderAxisResolvedRow;\n }\n }\n\n // This is the main recursive call. We layout non flexible children.\n if (alreadyComputedNextLayout === 0) {\n layoutNode(/*(java)!layoutContext, */child, maxWidth, direction);\n }\n\n // Absolute positioned elements do not take part of the layout, so we\n // don't use them to compute mainContentDim\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n nonFlexibleChildrenCount++;\n // At this point we know the final size and margin of the element.\n nextContentDim = getDimWithMargin(child, mainAxis);\n }\n }\n\n // The element we are about to add would make us go to the next line\n if (isNodeFlexWrap &&\n isMainDimDefined &&\n mainContentDim + nextContentDim > definedMainDim &&\n // If there's only one element, then it's bigger than the content\n // and needs its own line\n i !== startLine) {\n nonFlexibleChildrenCount--;\n alreadyComputedNextLayout = 1;\n break;\n }\n\n // Disable simple stacking in the main axis for the current line as\n // we found a non-trivial child. The remaining children will be laid out\n // in .\n if (isSimpleStackMain &&\n (getPositionType(child) != CSS_POSITION_RELATIVE || isFlex(child))) {\n isSimpleStackMain = false;\n firstComplexMain = i;\n }\n\n // Disable simple stacking in the cross axis for the current line as\n // we found a non-trivial child. The remaining children will be laid out\n // in .\n if (isSimpleStackCross &&\n (getPositionType(child) != CSS_POSITION_RELATIVE ||\n (alignItem !== CSS_ALIGN_STRETCH && alignItem != CSS_ALIGN_FLEX_START) ||\n isUndefined(child.layout[dim[crossAxis]]))) {\n isSimpleStackCross = false;\n firstComplexCross = i;\n }\n\n if (isSimpleStackMain) {\n child.layout[pos[mainAxis]] += mainDim;\n if (isMainDimDefined) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n mainDim += getDimWithMargin(child, mainAxis);\n crossDim = fmaxf(crossDim, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n\n if (isSimpleStackCross) {\n child.layout[pos[crossAxis]] += linesCrossDim + leadingPaddingAndBorderCross;\n if (isCrossDimDefined) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n\n alreadyComputedNextLayout = 0;\n mainContentDim += nextContentDim;\n endLine = i + 1;\n }\n\n // Layout flexible children and allocate empty space\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 // The remaining available space that needs to be allocated\n var/*float*/ remainingMainDim = 0;\n if (isMainDimDefined) {\n remainingMainDim = definedMainDim - mainContentDim;\n } else {\n remainingMainDim = fmaxf(mainContentDim, 0) - mainContentDim;\n }\n\n // If there are flexible children in the mix, they are going to fill the\n // remaining space\n if (flexibleChildrenCount !== 0) {\n var/*float*/ flexibleMainDim = remainingMainDim / totalFlexible;\n var/*float*/ baseMainDim;\n var/*float*/ boundMainDim;\n\n // If the flex share of remaining space doesn't meet min/max bounds,\n // remove this child from flex calculations.\n currentFlexChild = firstFlexChild;\n while (currentFlexChild !== null) {\n baseMainDim = flexibleMainDim * currentFlexChild.style.flex +\n getPaddingAndBorderAxis(currentFlexChild, mainAxis);\n boundMainDim = boundAxis(currentFlexChild, mainAxis, baseMainDim);\n\n if (baseMainDim !== boundMainDim) {\n remainingMainDim -= boundMainDim;\n totalFlexible -= currentFlexChild.style.flex;\n }\n\n currentFlexChild = currentFlexChild.nextFlexChild;\n }\n flexibleMainDim = remainingMainDim / totalFlexible;\n\n // The non flexible children can overflow the container, in this case\n // we should just assume that there is no space available.\n if (flexibleMainDim < 0) {\n flexibleMainDim = 0;\n }\n\n currentFlexChild = firstFlexChild;\n while (currentFlexChild !== null) {\n // At this point we know the final size of the element in the main\n // dimension\n currentFlexChild.layout[dim[mainAxis]] = boundAxis(currentFlexChild, mainAxis,\n flexibleMainDim * currentFlexChild.style.flex +\n getPaddingAndBorderAxis(currentFlexChild, mainAxis)\n );\n\n maxWidth = CSS_UNDEFINED;\n if (isDimDefined(node, resolvedRowAxis)) {\n maxWidth = node.layout[dim[resolvedRowAxis]] -\n paddingAndBorderAxisResolvedRow;\n } else if (!isMainRowDirection) {\n maxWidth = parentMaxWidth -\n getMarginAxis(node, resolvedRowAxis) -\n paddingAndBorderAxisResolvedRow;\n }\n\n // And we recursively call the layout algorithm for this child\n layoutNode(/*(java)!layoutContext, */currentFlexChild, maxWidth, direction);\n\n child = currentFlexChild;\n currentFlexChild = currentFlexChild.nextFlexChild;\n child.nextFlexChild = null;\n }\n\n // We use justifyContent to figure out how to allocate the remaining\n // space available\n } else if (justifyContent !== CSS_JUSTIFY_FLEX_START) {\n if (justifyContent === CSS_JUSTIFY_CENTER) {\n leadingMainDim = remainingMainDim / 2;\n } else if (justifyContent === CSS_JUSTIFY_FLEX_END) {\n leadingMainDim = remainingMainDim;\n } else if (justifyContent === CSS_JUSTIFY_SPACE_BETWEEN) {\n remainingMainDim = fmaxf(remainingMainDim, 0);\n if (flexibleChildrenCount + nonFlexibleChildrenCount - 1 !== 0) {\n betweenMainDim = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount - 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 = remainingMainDim /\n (flexibleChildrenCount + nonFlexibleChildrenCount);\n leadingMainDim = betweenMainDim / 2;\n }\n }\n\n // Position elements in the main axis and compute dimensions\n\n // At this point, all the children have their dimensions set. We need to\n // find their position. In order to do that, we accumulate data in\n // variables that are also useful to compute the total dimensions of the\n // container!\n mainDim += leadingMainDim;\n\n for (i = firstComplexMain; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[mainAxis])) {\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 } else {\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 // Define the trailing position accordingly.\n if (isMainDimDefined) {\n setTrailingPosition(node, child, mainAxis);\n }\n\n // Now that we placed the element, we need to update the variables\n // We only need to do that for relative elements. Absolute elements\n // do not take part in that phase.\n if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n // The main dimension is the sum of all the elements dimension plus\n // the spacing.\n mainDim += betweenMainDim + getDimWithMargin(child, mainAxis);\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, boundAxis(child, crossAxis, getDimWithMargin(child, crossAxis)));\n }\n }\n }\n\n var/*float*/ containerCrossAxis = node.layout[dim[crossAxis]];\n if (!isCrossDimDefined) {\n containerCrossAxis = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, crossDim + paddingAndBorderAxisCross),\n paddingAndBorderAxisCross\n );\n }\n\n // Position elements in the cross axis\n for (i = firstComplexCross; i < endLine; ++i) {\n child = node.children[i];\n\n if (getPositionType(child) === CSS_POSITION_ABSOLUTE &&\n isPosDefined(child, leading[crossAxis])) {\n // In case the child is absolutely positionned and has a\n // top/left/bottom/right being set, we override all the previously\n // computed positions to set it correctly.\n child.layout[pos[crossAxis]] = getPosition(child, leading[crossAxis]) +\n getLeadingBorder(node, crossAxis) +\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 if (getPositionType(child) === CSS_POSITION_RELATIVE) {\n var/*css_align_t*/ alignItem = getAlignItem(node, child);\n if (alignItem === CSS_ALIGN_STRETCH) {\n // You can only stretch if the dimension has not already been set\n // previously.\n if (isUndefined(child.layout[dim[crossAxis]])) {\n child.layout[dim[crossAxis]] = fmaxf(\n boundAxis(child, crossAxis, containerCrossAxis -\n paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(child, crossAxis)\n );\n }\n } else if (alignItem !== CSS_ALIGN_FLEX_START) {\n // The remaining space between the parent dimensions+padding and child\n // dimensions+margin.\n var/*float*/ remainingCrossDim = containerCrossAxis -\n paddingAndBorderAxisCross - 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\n // And we apply the position\n child.layout[pos[crossAxis]] += linesCrossDim + leadingCrossDim;\n\n // Define the trailing position accordingly.\n if (isCrossDimDefined) {\n setTrailingPosition(node, child, crossAxis);\n }\n }\n }\n\n linesCrossDim += crossDim;\n linesMainDim = fmaxf(linesMainDim, mainDim);\n linesCount += 1;\n startLine = endLine;\n }\n\n // \n //\n // Note(prenaux): More than one line, we need to layout the crossAxis\n // according to alignContent.\n //\n // Note that we could probably remove and handle the one line case\n // here too, but for the moment this is safer since it won't interfere with\n // previously working code.\n //\n // See specs:\n // http://www.w3.org/TR/2012/CR-css3-flexbox-20120918/#layout-algorithm\n // section 9.4\n //\n if (linesCount > 1 && isCrossDimDefined) {\n var/*float*/ nodeCrossAxisInnerSize = node.layout[dim[crossAxis]] -\n paddingAndBorderAxisCross;\n var/*float*/ remainingAlignContentDim = nodeCrossAxisInnerSize - linesCrossDim;\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 (nodeCrossAxisInnerSize > linesCrossDim) {\n crossDimLead = (remainingAlignContentDim / linesCount);\n }\n }\n\n var/*int*/ endIndex = 0;\n for (i = 0; i < linesCount; ++i) {\n var/*int*/ startIndex = endIndex;\n\n // compute the line's height and find the endIndex\n var/*float*/ lineHeight = 0;\n for (ii = startIndex; ii < childCount; ++ii) {\n child = node.children[ii];\n if (getPositionType(child) !== CSS_POSITION_RELATIVE) {\n continue;\n }\n if (child.lineIndex !== i) {\n break;\n }\n if (!isUndefined(child.layout[dim[crossAxis]])) {\n lineHeight = fmaxf(\n lineHeight,\n child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis)\n );\n }\n }\n endIndex = ii;\n lineHeight += crossDimLead;\n\n for (ii = startIndex; ii < endIndex; ++ii) {\n child = node.children[ii];\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[dim[crossAxis]];\n } else if (alignContentAlignItem === CSS_ALIGN_CENTER) {\n var/*float*/ childHeight = child.layout[dim[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 undefined\n // (auto) crossAxis dimension.\n }\n }\n\n currentLead += lineHeight;\n }\n }\n\n var/*bool*/ needsMainTrailingPos = false;\n var/*bool*/ needsCrossTrailingPos = false;\n\n // If the user didn't specify a width or height, and it has not been set\n // by the container, then we set it via the children.\n if (!isMainDimDefined) {\n node.layout[dim[mainAxis]] = fmaxf(\n // We're missing the last padding at this point to get the final\n // dimension\n boundAxis(node, mainAxis, linesMainDim + getTrailingPaddingAndBorder(node, mainAxis)),\n // We can never assign a width smaller than the padding and borders\n paddingAndBorderAxisMain\n );\n\n if (mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||\n mainAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsMainTrailingPos = true;\n }\n }\n\n if (!isCrossDimDefined) {\n node.layout[dim[crossAxis]] = fmaxf(\n // For the cross dim, we add both sides at the end because the value\n // is aggregate via a max function. Intermediate negative values\n // can mess this computation otherwise\n boundAxis(node, crossAxis, linesCrossDim + paddingAndBorderAxisCross),\n paddingAndBorderAxisCross\n );\n\n if (crossAxis == CSS_FLEX_DIRECTION_ROW_REVERSE ||\n crossAxis == CSS_FLEX_DIRECTION_COLUMN_REVERSE) {\n needsCrossTrailingPos = true;\n }\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 // Calculate dimensions for absolutely positioned elements\n currentAbsoluteChild = firstAbsoluteChild;\n while (currentAbsoluteChild !== null) {\n // Pre-fill dimensions when using absolute position and both offsets for\n // the axis are defined (either both left and right or top and bottom).\n for (ii = 0; ii < 2; ii++) {\n axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN;\n\n if (!isUndefined(node.layout[dim[axis]]) &&\n !isDimDefined(currentAbsoluteChild, axis) &&\n isPosDefined(currentAbsoluteChild, leading[axis]) &&\n isPosDefined(currentAbsoluteChild, trailing[axis])) {\n currentAbsoluteChild.layout[dim[axis]] = fmaxf(\n boundAxis(currentAbsoluteChild, axis, node.layout[dim[axis]] -\n getBorderAxis(node, axis) -\n getMarginAxis(currentAbsoluteChild, axis) -\n getPosition(currentAbsoluteChild, leading[axis]) -\n getPosition(currentAbsoluteChild, trailing[axis])\n ),\n // You never want to go smaller than padding\n getPaddingAndBorderAxis(currentAbsoluteChild, axis)\n );\n }\n\n if (isPosDefined(currentAbsoluteChild, trailing[axis]) &&\n !isPosDefined(currentAbsoluteChild, leading[axis])) {\n currentAbsoluteChild.layout[leading[axis]] =\n node.layout[dim[axis]] -\n currentAbsoluteChild.layout[dim[axis]] -\n getPosition(currentAbsoluteChild, trailing[axis]);\n }\n }\n\n child = currentAbsoluteChild;\n currentAbsoluteChild = currentAbsoluteChild.nextAbsoluteChild;\n child.nextAbsoluteChild = null;\n }\n }\n\n return {\n computeLayout: layoutNode,\n fillNodes: fillNodes\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 computeLayout.fillNodes(node);\n computeLayout.computeLayout(node);\n };\n}));\n"]} \ No newline at end of file diff --git a/src/CSharpTranspiler.js b/src/CSharpTranspiler.js index a0f4ad18..7aa3e0a7 100644 --- a/src/CSharpTranspiler.js +++ b/src/CSharpTranspiler.js @@ -30,7 +30,7 @@ function __transpileToCSharpCommon(code) { .replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent') .replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent') .replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)') - .replace(/isDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] > 0.0\)') + .replace(/isDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] >= 0.0\)') .replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)') .replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.dimensions[dim[$3]] - $2.layout.dimensions[dim[$3]] - $2.layout.position[pos[$3]]') .replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex > 0\)') diff --git a/src/JavaTranspiler.js b/src/JavaTranspiler.js index 6aca0d79..bf528424 100644 --- a/src/JavaTranspiler.js +++ b/src/JavaTranspiler.js @@ -30,7 +30,7 @@ function __transpileToJavaCommon(code) { .replace(/getJustifyContent\((.+?)\)/g, '$1.style.justifyContent') .replace(/getAlignContent\((.+?)\)/g, '$1.style.alignContent') .replace(/isPosDefined\((.+?),\s*(.+?)\)/g, '!isUndefined\($1.style.position[$2]\)') - .replace(/isDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] > 0.0\)') + .replace(/isDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] >= 0.0\)') .replace(/getPosition\((.+?),\s*(.+?)\)/g, '\(isUndefined\($1.style.position[$2]\) ? 0 : $1.style.position[$2]\)') .replace(/setTrailingPosition\((.+?),\s*(.+?),\s*(.+?)\)/g, '$2.layout.position[trailing[$3]] = $1.layout.dimensions[dim[$3]] - $2.layout.dimensions[dim[$3]] - $2.layout.position[pos[$3]]') .replace(/isFlex\((.+?)\)/g, '\($1.style.positionType == CSSPositionType.RELATIVE && $1.style.flex > 0\)') diff --git a/src/Layout.c b/src/Layout.c index bab98467..fa031f20 100644 --- a/src/Layout.c +++ b/src/Layout.c @@ -440,7 +440,7 @@ static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) { static bool isDimDefined(css_node_t *node, css_flex_direction_t axis) { float value = node->style.dimensions[dim[axis]]; - return !isUndefined(value) && value > 0.0; + return !isUndefined(value) && value >= 0.0; } static bool isPosDefined(css_node_t *node, css_position_t position) { diff --git a/src/Layout.js b/src/Layout.js index e97258e9..0e98bdc6 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -1076,7 +1076,7 @@ var computeLayout = (function() { })(); // This module export is only used for the purposes of unit testing this file. When -// the library is packaged this file is included within css-layout.js which forms +// the library is packaged this file is included within css-layout.js which forms // the public API. if (typeof exports === 'object') { module.exports = computeLayout; diff --git a/src/__tests__/Layout-test.c b/src/__tests__/Layout-test.c index e2b54bc9..85079d44 100644 --- a/src/__tests__/Layout-test.c +++ b/src/__tests__/Layout-test.c @@ -7468,6 +7468,40 @@ int main() test("should layout node with correct start/end border in rtl", root_node, root_layout); } + { + css_node_t *root_node = new_test_css_node(); + { + css_node_t *node_0 = root_node; + node_0->style.dimensions[CSS_WIDTH] = 200; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->style.dimensions[CSS_WIDTH] = 0; + } + } + + css_node_t *root_layout = new_test_css_node(); + { + css_node_t *node_0 = root_layout; + node_0->layout.position[CSS_TOP] = 0; + node_0->layout.position[CSS_LEFT] = 0; + node_0->layout.dimensions[CSS_WIDTH] = 200; + node_0->layout.dimensions[CSS_HEIGHT] = 0; + init_css_node_children(node_0, 1); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->layout.position[CSS_TOP] = 0; + node_1->layout.position[CSS_LEFT] = 0; + node_1->layout.dimensions[CSS_WIDTH] = 0; + node_1->layout.dimensions[CSS_HEIGHT] = 0; + } + } + + test("should layout node with a 0 width", root_node, root_layout); + } + { css_node_t *root_node = new_test_css_node(); { diff --git a/src/__tests__/Layout-test.js b/src/__tests__/Layout-test.js index 45d4a2a0..3db4e72f 100755 --- a/src/__tests__/Layout-test.js +++ b/src/__tests__/Layout-test.js @@ -2298,6 +2298,17 @@ describe('Layout', function() { ); }); + it('should layout node with a 0 width', function() { + testLayout( + {style: {width: 200}, children: [ + {style: {width: 0}} + ]}, + {width: 200, height: 0, top: 0, left: 0, children: [ + {width: 0, height: 0, top: 0, left: 0} + ]} + ); + }); + xit('should stretch a nested child', function() { testLayout( {children: [ diff --git a/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs b/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs index 0f1529a2..2331433c 100644 --- a/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs +++ b/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs @@ -7903,6 +7903,42 @@ public class LayoutEngineTest [Test] public void TestCase177() + { + TestCSSNode root_node = new TestCSSNode(); + { + TestCSSNode node_0 = root_node; + node_0.style.dimensions[DIMENSION_WIDTH] = 200; + addChildren(node_0, 1); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.style.dimensions[DIMENSION_WIDTH] = 0; + } + } + + TestCSSNode root_layout = new TestCSSNode(); + { + TestCSSNode node_0 = root_layout; + node_0.layout.position[POSITION_TOP] = 0; + node_0.layout.position[POSITION_LEFT] = 0; + node_0.layout.dimensions[DIMENSION_WIDTH] = 200; + node_0.layout.dimensions[DIMENSION_HEIGHT] = 0; + addChildren(node_0, 1); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.layout.position[POSITION_TOP] = 0; + node_1.layout.position[POSITION_LEFT] = 0; + node_1.layout.dimensions[DIMENSION_WIDTH] = 0; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 0; + } + } + + test("should layout node with a 0 width", root_node, root_layout); + } + + [Test] + public void TestCase178() { TestCSSNode root_node = new TestCSSNode(); { diff --git a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs index c0008b83..819ea4c3 100644 --- a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs +++ b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs @@ -273,7 +273,7 @@ namespace Facebook.CSSLayout boolean isResolvedRowDimDefined = !float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]); float width = CSSConstants.Undefined; - if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { width = node.style.dimensions[DIMENSION_WIDTH]; } else if (isResolvedRowDimDefined) { width = node.layout.dimensions[dim[resolvedRowAxis]]; @@ -286,8 +286,8 @@ namespace Facebook.CSSLayout // We only need to give a dimension for the text if we haven't got any // for it computed yet. It can either be from the style attribute or because // the element is flexible. - boolean isRowUndefined = !(!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0) && !isResolvedRowDimDefined; - boolean isColumnUndefined = !(!float.IsNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] > 0.0) && + boolean isRowUndefined = !(!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0) && !isResolvedRowDimDefined; + boolean isColumnUndefined = !(!float.IsNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0) && float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]); // Let's not measure the text if we already know both dimensions @@ -398,7 +398,7 @@ namespace Facebook.CSSLayout if (alignItem == CSSAlign.Stretch && child.style.positionType == CSSPositionType.Relative && isCrossDimDefined && - !(!float.IsNaN(child.style.dimensions[dim[crossAxis]]) && child.style.dimensions[dim[crossAxis]] > 0.0)) { + !(!float.IsNaN(child.style.dimensions[dim[crossAxis]]) && child.style.dimensions[dim[crossAxis]] >= 0.0)) { child.layout.dimensions[dim[crossAxis]] = Math.Max( boundAxis(child, crossAxis, node.layout.dimensions[dim[crossAxis]] - paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))), @@ -421,7 +421,7 @@ namespace Facebook.CSSLayout for (ii = 0; ii < 2; ii++) { axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; if (!float.IsNaN(node.layout.dimensions[dim[axis]]) && - !(!float.IsNaN(child.style.dimensions[dim[axis]]) && child.style.dimensions[dim[axis]] > 0.0) && + !(!float.IsNaN(child.style.dimensions[dim[axis]]) && child.style.dimensions[dim[axis]] >= 0.0) && !float.IsNaN(child.style.position[leading[axis]]) && !float.IsNaN(child.style.position[trailing[axis]])) { child.layout.dimensions[dim[axis]] = Math.Max( @@ -465,7 +465,7 @@ namespace Facebook.CSSLayout } else { maxWidth = CSSConstants.Undefined; if (!isMainRowDirection) { - if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -599,7 +599,7 @@ namespace Facebook.CSSLayout ); maxWidth = CSSConstants.Undefined; - if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -894,7 +894,7 @@ namespace Facebook.CSSLayout axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; if (!float.IsNaN(node.layout.dimensions[dim[axis]]) && - !(!float.IsNaN(currentAbsoluteChild.style.dimensions[dim[axis]]) && currentAbsoluteChild.style.dimensions[dim[axis]] > 0.0) && + !(!float.IsNaN(currentAbsoluteChild.style.dimensions[dim[axis]]) && currentAbsoluteChild.style.dimensions[dim[axis]] >= 0.0) && !float.IsNaN(currentAbsoluteChild.style.position[leading[axis]]) && !float.IsNaN(currentAbsoluteChild.style.position[trailing[axis]])) { currentAbsoluteChild.layout.dimensions[dim[axis]] = Math.Max( diff --git a/src/java/src/com/facebook/csslayout/LayoutEngine.java b/src/java/src/com/facebook/csslayout/LayoutEngine.java index 7e114ad3..c88a9295 100644 --- a/src/java/src/com/facebook/csslayout/LayoutEngine.java +++ b/src/java/src/com/facebook/csslayout/LayoutEngine.java @@ -253,7 +253,7 @@ public class LayoutEngine { boolean isResolvedRowDimDefined = !Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]); float width = CSSConstants.UNDEFINED; - if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { width = node.style.dimensions[DIMENSION_WIDTH]; } else if (isResolvedRowDimDefined) { width = node.layout.dimensions[dim[resolvedRowAxis]]; @@ -266,8 +266,8 @@ public class LayoutEngine { // We only need to give a dimension for the text if we haven't got any // for it computed yet. It can either be from the style attribute or because // the element is flexible. - boolean isRowUndefined = !(!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0) && !isResolvedRowDimDefined; - boolean isColumnUndefined = !(!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] > 0.0) && + boolean isRowUndefined = !(!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0) && !isResolvedRowDimDefined; + boolean isColumnUndefined = !(!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0) && Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]); // Let's not measure the text if we already know both dimensions @@ -378,7 +378,7 @@ public class LayoutEngine { if (alignItem == CSSAlign.STRETCH && child.style.positionType == CSSPositionType.RELATIVE && isCrossDimDefined && - !(!Float.isNaN(child.style.dimensions[dim[crossAxis]]) && child.style.dimensions[dim[crossAxis]] > 0.0)) { + !(!Float.isNaN(child.style.dimensions[dim[crossAxis]]) && child.style.dimensions[dim[crossAxis]] >= 0.0)) { child.layout.dimensions[dim[crossAxis]] = Math.max( boundAxis(child, crossAxis, node.layout.dimensions[dim[crossAxis]] - paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))), @@ -401,7 +401,7 @@ public class LayoutEngine { for (ii = 0; ii < 2; ii++) { axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; if (!Float.isNaN(node.layout.dimensions[dim[axis]]) && - !(!Float.isNaN(child.style.dimensions[dim[axis]]) && child.style.dimensions[dim[axis]] > 0.0) && + !(!Float.isNaN(child.style.dimensions[dim[axis]]) && child.style.dimensions[dim[axis]] >= 0.0) && !Float.isNaN(child.style.position[leading[axis]]) && !Float.isNaN(child.style.position[trailing[axis]])) { child.layout.dimensions[dim[axis]] = Math.max( @@ -445,7 +445,7 @@ public class LayoutEngine { } else { maxWidth = CSSConstants.UNDEFINED; if (!isMainRowDirection) { - if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -579,7 +579,7 @@ public class LayoutEngine { ); maxWidth = CSSConstants.UNDEFINED; - if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] > 0.0)) { + if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -874,7 +874,7 @@ public class LayoutEngine { axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; if (!Float.isNaN(node.layout.dimensions[dim[axis]]) && - !(!Float.isNaN(currentAbsoluteChild.style.dimensions[dim[axis]]) && currentAbsoluteChild.style.dimensions[dim[axis]] > 0.0) && + !(!Float.isNaN(currentAbsoluteChild.style.dimensions[dim[axis]]) && currentAbsoluteChild.style.dimensions[dim[axis]] >= 0.0) && !Float.isNaN(currentAbsoluteChild.style.position[leading[axis]]) && !Float.isNaN(currentAbsoluteChild.style.position[trailing[axis]])) { currentAbsoluteChild.layout.dimensions[dim[axis]] = Math.max( diff --git a/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java b/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java index 0610728f..971a9fe1 100644 --- a/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java +++ b/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java @@ -7906,6 +7906,42 @@ public class LayoutEngineTest { @Test public void testCase177() + { + TestCSSNode root_node = new TestCSSNode(); + { + TestCSSNode node_0 = root_node; + node_0.style.dimensions[DIMENSION_WIDTH] = 200; + addChildren(node_0, 1); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.style.dimensions[DIMENSION_WIDTH] = 0; + } + } + + TestCSSNode root_layout = new TestCSSNode(); + { + TestCSSNode node_0 = root_layout; + node_0.layout.position[POSITION_TOP] = 0; + node_0.layout.position[POSITION_LEFT] = 0; + node_0.layout.dimensions[DIMENSION_WIDTH] = 200; + node_0.layout.dimensions[DIMENSION_HEIGHT] = 0; + addChildren(node_0, 1); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.layout.position[POSITION_TOP] = 0; + node_1.layout.position[POSITION_LEFT] = 0; + node_1.layout.dimensions[DIMENSION_WIDTH] = 0; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 0; + } + } + + test("should layout node with a 0 width", root_node, root_layout); + } + + @Test + public void testCase178() { TestCSSNode root_node = new TestCSSNode(); {