From c9094f94d00ab0a9c9869cdfbc44aed39fef0d91 Mon Sep 17 00:00:00 2001 From: Emil Sjolander Date: Tue, 5 Jan 2016 19:33:04 +0000 Subject: [PATCH] Check layout instead of style before setting height and width to whatever is set in layout --- src/CSharpTranspiler.js | 3 +- src/JavaTranspiler.js | 3 +- src/Layout-test-utils.c | 7 ++ src/Layout-test-utils.js | 8 +++ src/Layout.c | 51 +++++++------ src/Layout.js | 50 +++++++------ src/__tests__/Layout-test.c | 66 +++++++++++++++++ src/__tests__/Layout-test.js | 18 +++++ .../LayoutEngineTest.cs | 70 ++++++++++++++++++ .../Facebook.CSSLayout.Tests/TestConstants.cs | 1 + src/csharp/Facebook.CSSLayout/LayoutEngine.cs | 26 +++---- .../com/facebook/csslayout/LayoutEngine.java | 26 +++---- .../facebook/csslayout/LayoutEngineTest.java | 71 +++++++++++++++++++ .../com/facebook/csslayout/TestConstants.java | 1 + src/transpile.js | 6 +- 15 files changed, 331 insertions(+), 76 deletions(-) diff --git a/src/CSharpTranspiler.js b/src/CSharpTranspiler.js index fdc9ce47..5fbe5b76 100644 --- a/src/CSharpTranspiler.js +++ b/src/CSharpTranspiler.js @@ -30,7 +30,8 @@ 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(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] >= 0.0\)') + .replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.layout.dimensions[dim[$2]]\) && $1.layout.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 f7244fe9..60b26e9c 100644 --- a/src/JavaTranspiler.js +++ b/src/JavaTranspiler.js @@ -30,7 +30,8 @@ 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(/isStyleDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.style.dimensions[dim[$2]]\) && $1.style.dimensions[dim[$2]] >= 0.0\)') + .replace(/isLayoutDimDefined\((.+?),\s*(.+?)\)/g, '\(!isUndefined\($1.layout.dimensions[dim[$2]]\) && $1.layout.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-test-utils.c b/src/Layout-test-utils.c index 95922e3f..8b66e263 100644 --- a/src/Layout-test-utils.c +++ b/src/Layout-test-utils.c @@ -34,6 +34,7 @@ __forceinline const float fminf(const float a, const float b) { #define SMALL_TEXT "small" #define LONG_TEXT "loooooooooong with space" #define MEASURE_WITH_RATIO_2 "measureWithRatio2" +#define MEASURE_WITH_MATCH_PARENT "measureWithMatchParent" /** END_GENERATED **/ typedef struct failed_test_t { @@ -115,6 +116,12 @@ css_dim_t measure(void *context, float width, float height) { return dim; } + if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) { + dim.dimensions[CSS_WIDTH] = width; + dim.dimensions[CSS_HEIGHT] = height; + return dim; + } + // Should not go here dim.dimensions[CSS_WIDTH] = CSS_UNDEFINED; dim.dimensions[CSS_HEIGHT] = CSS_UNDEFINED; diff --git a/src/Layout-test-utils.js b/src/Layout-test-utils.js index 4108e67f..799393ac 100644 --- a/src/Layout-test-utils.js +++ b/src/Layout-test-utils.js @@ -538,6 +538,14 @@ var layoutTestUtils = (function() { // This is necessary for transpiled tests, see previous comment fn.toString = function() { return 'measureWithRatio2'; }; return fn; + }, + measureWithMatchParent: function() { + var fn = function(width, height) { + return {width: width, height: height}; + }; + // This is necessary for transpiled tests, see previous comment + fn.toString = function() { return 'measureWithMatchParent'; }; + return fn; } }; })(); diff --git a/src/Layout.c b/src/Layout.c index 40f723a6..2440041f 100644 --- a/src/Layout.c +++ b/src/Layout.c @@ -439,11 +439,16 @@ static float getDimWithMargin(css_node_t *node, css_flex_direction_t axis) { getTrailingMargin(node, axis); } -static bool isDimDefined(css_node_t *node, css_flex_direction_t axis) { +static bool isStyleDimDefined(css_node_t *node, css_flex_direction_t axis) { float value = node->style.dimensions[dim[axis]]; return !isUndefined(value) && value >= 0.0; } +static bool isLayoutDimDefined(css_node_t *node, css_flex_direction_t axis) { + float value = node->layout.dimensions[dim[axis]]; + return !isUndefined(value) && value >= 0.0; +} + static bool isPosDefined(css_node_t *node, css_position_t position) { return !isUndefined(node->style.position[position]); } @@ -487,11 +492,11 @@ static float boundAxis(css_node_t *node, css_flex_direction_t axis, float value) // When the user specifically sets a value for width or height static void setDimensionFromStyle(css_node_t *node, css_flex_direction_t axis) { // The parent already computed us a width or height. We just skip it - if (!isUndefined(node->layout.dimensions[dim[axis]])) { + if (isLayoutDimDefined(node, axis)) { return; } // We only run if there's a width or height defined - if (!isDimDefined(node, axis)) { + if (!isStyleDimDefined(node, axis)) { return; } @@ -549,10 +554,10 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM float paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); if (isMeasureDefined(node)) { - bool isResolvedRowDimDefined = !isUndefined(node->layout.dimensions[dim[resolvedRowAxis]]); + bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); float width = CSS_UNDEFINED; - if (isDimDefined(node, resolvedRowAxis)) { + if (isStyleDimDefined(node, resolvedRowAxis)) { width = node->style.dimensions[CSS_WIDTH]; } else if (isResolvedRowDimDefined) { width = node->layout.dimensions[dim[resolvedRowAxis]]; @@ -563,9 +568,9 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM width -= paddingAndBorderAxisResolvedRow; float height = CSS_UNDEFINED; - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { height = node->style.dimensions[CSS_HEIGHT]; - } else if (!isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]])) { + } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]; } else { height = parentMaxHeight - @@ -576,8 +581,8 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM // 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. - bool isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined; - bool isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && + bool isRowUndefined = !isStyleDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined; + bool isColumnUndefined = !isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && isUndefined(node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]); // Let's not measure the text if we already know both dimensions @@ -611,8 +616,8 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM float paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis); float paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis); - bool isMainDimDefined = !isUndefined(node->layout.dimensions[dim[mainAxis]]); - bool isCrossDimDefined = !isUndefined(node->layout.dimensions[dim[crossAxis]]); + bool isMainDimDefined = isLayoutDimDefined(node, mainAxis); + bool isCrossDimDefined = isLayoutDimDefined(node, crossAxis); bool isMainRowDirection = isRowDirection(mainAxis); int i; @@ -690,7 +695,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM if (alignItem == CSS_ALIGN_STRETCH && child->style.position_type == CSS_POSITION_RELATIVE && isCrossDimDefined && - !isDimDefined(child, crossAxis)) { + !isStyleDimDefined(child, crossAxis)) { child->layout.dimensions[dim[crossAxis]] = fmaxf( boundAxis(child, crossAxis, node->layout.dimensions[dim[crossAxis]] - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)), @@ -712,8 +717,8 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM // left and right or top and bottom). for (ii = 0; ii < 2; ii++) { axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node->layout.dimensions[dim[axis]]) && - !isDimDefined(child, axis) && + if (isLayoutDimDefined(node, axis) && + !isStyleDimDefined(child, axis) && isPosDefined(child, leading[axis]) && isPosDefined(child, trailing[axis])) { child->layout.dimensions[dim[axis]] = fmaxf( @@ -759,7 +764,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM maxHeight = CSS_UNDEFINED; if (!isMainRowDirection) { - if (isDimDefined(node, resolvedRowAxis)) { + if (isLayoutDimDefined(node, resolvedRowAxis)) { maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -768,7 +773,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM paddingAndBorderAxisResolvedRow; } } else { - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else { @@ -819,7 +824,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM if (isSimpleStackCross && (child->style.position_type != CSS_POSITION_RELATIVE || (alignItem != CSS_ALIGN_STRETCH && alignItem != CSS_ALIGN_FLEX_START) || - isUndefined(child->layout.dimensions[dim[crossAxis]]))) { + !isLayoutDimDefined(child, crossAxis))) { isSimpleStackCross = false; firstComplexCross = i; } @@ -902,7 +907,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM ); maxWidth = CSS_UNDEFINED; - if (isDimDefined(node, resolvedRowAxis)) { + if (isLayoutDimDefined(node, resolvedRowAxis)) { maxWidth = node->layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -911,7 +916,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM paddingAndBorderAxisResolvedRow; } maxHeight = CSS_UNDEFINED; - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { maxHeight = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else if (isMainRowDirection) { @@ -1031,7 +1036,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM if (alignItem == CSS_ALIGN_STRETCH) { // You can only stretch if the dimension has not already been set // previously. - if (isUndefined(child->layout.dimensions[dim[crossAxis]])) { + if (!isLayoutDimDefined(child, crossAxis)) { child->layout.dimensions[dim[crossAxis]] = fmaxf( boundAxis(child, crossAxis, containerCrossAxis - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)), @@ -1115,7 +1120,7 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM if (child->line_index != i) { break; } - if (!isUndefined(child->layout.dimensions[dim[crossAxis]])) { + if (isLayoutDimDefined(child, crossAxis)) { lineHeight = fmaxf( lineHeight, child->layout.dimensions[dim[crossAxis]] + getMarginAxis(child, crossAxis) @@ -1208,8 +1213,8 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM for (ii = 0; ii < 2; ii++) { axis = (ii != 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node->layout.dimensions[dim[axis]]) && - !isDimDefined(currentAbsoluteChild, axis) && + if (isLayoutDimDefined(node, axis) && + !isStyleDimDefined(currentAbsoluteChild, axis) && isPosDefined(currentAbsoluteChild, leading[axis]) && isPosDefined(currentAbsoluteChild, trailing[axis])) { currentAbsoluteChild->layout.dimensions[dim[axis]] = fmaxf( diff --git a/src/Layout.js b/src/Layout.js index 525bab7f..ec8f0521 100755 --- a/src/Layout.js +++ b/src/Layout.js @@ -361,10 +361,14 @@ var computeLayout = (function() { return node.layout[dim[axis]] + getMarginAxis(node, axis); } - function isDimDefined(node, axis) { + function isStyleDimDefined(node, axis) { return node.style[dim[axis]] !== undefined && node.style[dim[axis]] >= 0; } + function isLayoutDimDefined(node, axis) { + return node.layout[dim[axis]] !== undefined && node.layout[dim[axis]] >= 0; + } + function isPosDefined(node, pos) { return node.style[pos] !== undefined; } @@ -415,11 +419,11 @@ var computeLayout = (function() { // When the user specifically sets a value for width or height function setDimensionFromStyle(node, axis) { // The parent already computed us a width or height. We just skip it - if (node.layout[dim[axis]] !== undefined) { + if (isLayoutDimDefined(node, axis)) { return; } // We only run if there's a width or height defined - if (!isDimDefined(node, axis)) { + if (!isStyleDimDefined(node, axis)) { return; } @@ -475,10 +479,10 @@ var computeLayout = (function() { var/*float*/ paddingAndBorderAxisColumn = getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); if (isMeasureDefined(node)) { - var/*bool*/ isResolvedRowDimDefined = !isUndefined(node.layout[dim[resolvedRowAxis]]); + var/*bool*/ isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); var/*float*/ width = CSS_UNDEFINED; - if (isDimDefined(node, resolvedRowAxis)) { + if (isStyleDimDefined(node, resolvedRowAxis)) { width = node.style.width; } else if (isResolvedRowDimDefined) { width = node.layout[dim[resolvedRowAxis]]; @@ -489,9 +493,9 @@ var computeLayout = (function() { width -= paddingAndBorderAxisResolvedRow; var/*float*/ height = CSS_UNDEFINED; - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { height = node.style.height; - } else if (!isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]])) { + } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { height = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]; } else { height = parentMaxHeight - @@ -502,8 +506,8 @@ var computeLayout = (function() { // 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. - var/*bool*/ isRowUndefined = !isDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined; - var/*bool*/ isColumnUndefined = !isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && + var/*bool*/ isRowUndefined = !isStyleDimDefined(node, resolvedRowAxis) && !isResolvedRowDimDefined; + var/*bool*/ isColumnUndefined = !isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN) && isUndefined(node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]); // Let's not measure the text if we already know both dimensions @@ -537,8 +541,8 @@ var computeLayout = (function() { var/*float*/ paddingAndBorderAxisMain = getPaddingAndBorderAxis(node, mainAxis); var/*float*/ paddingAndBorderAxisCross = getPaddingAndBorderAxis(node, crossAxis); - var/*bool*/ isMainDimDefined = !isUndefined(node.layout[dim[mainAxis]]); - var/*bool*/ isCrossDimDefined = !isUndefined(node.layout[dim[crossAxis]]); + var/*bool*/ isMainDimDefined = isLayoutDimDefined(node, mainAxis); + var/*bool*/ isCrossDimDefined = isLayoutDimDefined(node, crossAxis); var/*bool*/ isMainRowDirection = isRowDirection(mainAxis); var/*int*/ i; @@ -616,7 +620,7 @@ var computeLayout = (function() { if (alignItem === CSS_ALIGN_STRETCH && getPositionType(child) === CSS_POSITION_RELATIVE && isCrossDimDefined && - !isDimDefined(child, crossAxis)) { + !isStyleDimDefined(child, crossAxis)) { child.layout[dim[crossAxis]] = fmaxf( boundAxis(child, crossAxis, node.layout[dim[crossAxis]] - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)), @@ -638,8 +642,8 @@ var computeLayout = (function() { // left and right or top and bottom). for (ii = 0; ii < 2; ii++) { axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node.layout[dim[axis]]) && - !isDimDefined(child, axis) && + if (isLayoutDimDefined(node, axis) && + !isStyleDimDefined(child, axis) && isPosDefined(child, leading[axis]) && isPosDefined(child, trailing[axis])) { child.layout[dim[axis]] = fmaxf( @@ -685,7 +689,7 @@ var computeLayout = (function() { maxHeight = CSS_UNDEFINED; if (!isMainRowDirection) { - if (isDimDefined(node, resolvedRowAxis)) { + if (isLayoutDimDefined(node, resolvedRowAxis)) { maxWidth = node.layout[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -694,7 +698,7 @@ var computeLayout = (function() { paddingAndBorderAxisResolvedRow; } } else { - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { maxHeight = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else { @@ -745,7 +749,7 @@ var computeLayout = (function() { if (isSimpleStackCross && (getPositionType(child) !== CSS_POSITION_RELATIVE || (alignItem !== CSS_ALIGN_STRETCH && alignItem !== CSS_ALIGN_FLEX_START) || - isUndefined(child.layout[dim[crossAxis]]))) { + !isLayoutDimDefined(child, crossAxis))) { isSimpleStackCross = false; firstComplexCross = i; } @@ -828,7 +832,7 @@ var computeLayout = (function() { ); maxWidth = CSS_UNDEFINED; - if (isDimDefined(node, resolvedRowAxis)) { + if (isLayoutDimDefined(node, resolvedRowAxis)) { maxWidth = node.layout[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -837,7 +841,7 @@ var computeLayout = (function() { paddingAndBorderAxisResolvedRow; } maxHeight = CSS_UNDEFINED; - if (isDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { + if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { maxHeight = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else if (isMainRowDirection) { @@ -957,7 +961,7 @@ var computeLayout = (function() { if (alignItem === CSS_ALIGN_STRETCH) { // You can only stretch if the dimension has not already been set // previously. - if (isUndefined(child.layout[dim[crossAxis]])) { + if (!isLayoutDimDefined(child, crossAxis)) { child.layout[dim[crossAxis]] = fmaxf( boundAxis(child, crossAxis, containerCrossAxis - paddingAndBorderAxisCross - getMarginAxis(child, crossAxis)), @@ -1041,7 +1045,7 @@ var computeLayout = (function() { if (child.lineIndex !== i) { break; } - if (!isUndefined(child.layout[dim[crossAxis]])) { + if (isLayoutDimDefined(child, crossAxis)) { lineHeight = fmaxf( lineHeight, child.layout[dim[crossAxis]] + getMarginAxis(child, crossAxis) @@ -1134,8 +1138,8 @@ var computeLayout = (function() { for (ii = 0; ii < 2; ii++) { axis = (ii !== 0) ? CSS_FLEX_DIRECTION_ROW : CSS_FLEX_DIRECTION_COLUMN; - if (!isUndefined(node.layout[dim[axis]]) && - !isDimDefined(currentAbsoluteChild, axis) && + if (isLayoutDimDefined(node, axis) && + !isStyleDimDefined(currentAbsoluteChild, axis) && isPosDefined(currentAbsoluteChild, leading[axis]) && isPosDefined(currentAbsoluteChild, trailing[axis])) { currentAbsoluteChild.layout[dim[axis]] = fmaxf( diff --git a/src/__tests__/Layout-test.c b/src/__tests__/Layout-test.c index ef0db773..0d462881 100644 --- a/src/__tests__/Layout-test.c +++ b/src/__tests__/Layout-test.c @@ -7654,6 +7654,72 @@ int main() test("should layout node with a 0 width", root_node, root_layout); } + { + css_node_t *root_node = new_test_css_node(); + { + css_node_t *node_0 = root_node; + node_0->style.flex_direction = CSS_FLEX_DIRECTION_ROW; + node_0->style.align_items = CSS_ALIGN_FLEX_START; + node_0->style.dimensions[CSS_WIDTH] = 100; + node_0->style.dimensions[CSS_HEIGHT] = 10; + init_css_node_children(node_0, 2); + { + css_node_t *node_1; + node_1 = node_0->get_child(node_0->context, 0); + node_1->style.dimensions[CSS_WIDTH] = 50; + node_1->style.dimensions[CSS_HEIGHT] = 10; + node_1 = node_0->get_child(node_0->context, 1); + node_1->style.flex_direction = CSS_FLEX_DIRECTION_COLUMN; + node_1->style.align_items = CSS_ALIGN_FLEX_START; + node_1->style.flex = 1; + node_1->style.dimensions[CSS_HEIGHT] = 10; + init_css_node_children(node_1, 1); + { + css_node_t *node_2; + node_2 = node_1->get_child(node_1->context, 0); + node_2->style.flex = 1; + node_2->style.dimensions[CSS_HEIGHT] = 10; + node_2->measure = measure; + node_2->context = "measureWithMatchParent"; + } + } + } + + 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] = 100; + node_0->layout.dimensions[CSS_HEIGHT] = 10; + init_css_node_children(node_0, 2); + { + 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] = 50; + node_1->layout.dimensions[CSS_HEIGHT] = 10; + node_1 = node_0->get_child(node_0->context, 1); + node_1->layout.position[CSS_TOP] = 0; + node_1->layout.position[CSS_LEFT] = 50; + node_1->layout.dimensions[CSS_WIDTH] = 50; + node_1->layout.dimensions[CSS_HEIGHT] = 10; + init_css_node_children(node_1, 1); + { + css_node_t *node_2; + node_2 = node_1->get_child(node_1->context, 0); + node_2->layout.position[CSS_TOP] = 0; + node_2->layout.position[CSS_LEFT] = 0; + node_2->layout.dimensions[CSS_WIDTH] = 50; + node_2->layout.dimensions[CSS_HEIGHT] = 10; + } + } + } + + test("should correctly progagate size contraints from flexible parents", 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 31d39551..38399ce1 100755 --- a/src/__tests__/Layout-test.js +++ b/src/__tests__/Layout-test.js @@ -16,6 +16,7 @@ var text = layoutTestUtils.text; var texts = layoutTestUtils.texts; var textSizes = layoutTestUtils.textSizes; var measureWithRatio2 = layoutTestUtils.measureWithRatio2(); +var measureWithMatchParent = layoutTestUtils.measureWithMatchParent(); describe('Javascript Only', function() { it('should fill root node with layout, style, and children', function() { @@ -2383,6 +2384,23 @@ describe('Layout', function() { ]} ); }); + + it('should correctly progagate size contraints from flexible parents', function() { + testLayoutAgainstExpectedOnly( + {style:{flexDirection: 'row', alignItems: 'flex-start', width: 100, height: 10}, children: [ + {style: {width: 50, height: 10}}, + {style:{flexDirection: 'column', alignItems: 'flex-start', flex: 1, height: 10}, children: [ + {style: {measure: measureWithMatchParent, flex: 1, height: 10}} + ]} + ]}, + {width: 100, height: 10, top: 0, left: 0, children: [ + {width: 50, height: 10, top: 0, left: 0}, + {width: 50, height: 10, top: 0, left:50, children: [ + {width: 50, height: 10, top: 0, left: 0} + ]}, + ]} + ); + }); }); describe('Layout alignContent', function() { diff --git a/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs b/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs index 6ef73899..0aa3d16f 100644 --- a/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs +++ b/src/csharp/Facebook.CSSLayout.Tests/LayoutEngineTest.cs @@ -53,6 +53,8 @@ public class LayoutEngineTest } else { return new MeasureOutput(99999, 99999); } + } else if (testNode.context.Equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) { + return new MeasureOutput(width, height); } else { throw new Exception("Got unknown test: " + testNode.context); } @@ -8115,6 +8117,74 @@ public class LayoutEngineTest [Test] public void TestCase183() + { + TestCSSNode root_node = new TestCSSNode(); + { + TestCSSNode node_0 = root_node; + node_0.style.flexDirection = CSSFlexDirection.Row; + node_0.style.alignItems = CSSAlign.FlexStart; + node_0.style.dimensions[DIMENSION_WIDTH] = 100; + node_0.style.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_0, 2); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.style.dimensions[DIMENSION_WIDTH] = 50; + node_1.style.dimensions[DIMENSION_HEIGHT] = 10; + node_1 = node_0.getChildAt(1); + node_1.style.flexDirection = CSSFlexDirection.Column; + node_1.style.alignItems = CSSAlign.FlexStart; + node_1.style.flex = 1; + node_1.style.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_1, 1); + { + TestCSSNode node_2; + node_2 = node_1.getChildAt(0); + node_2.style.flex = 1; + node_2.style.dimensions[DIMENSION_HEIGHT] = 10; + node_2.setMeasureFunction(sTestMeasureFunction); + node_2.context = "measureWithMatchParent"; + } + } + } + + 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] = 100; + node_0.layout.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_0, 2); + { + 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] = 50; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 10; + node_1 = node_0.getChildAt(1); + node_1.layout.position[POSITION_TOP] = 0; + node_1.layout.position[POSITION_LEFT] = 50; + node_1.layout.dimensions[DIMENSION_WIDTH] = 50; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_1, 1); + { + TestCSSNode node_2; + node_2 = node_1.getChildAt(0); + node_2.layout.position[POSITION_TOP] = 0; + node_2.layout.position[POSITION_LEFT] = 0; + node_2.layout.dimensions[DIMENSION_WIDTH] = 50; + node_2.layout.dimensions[DIMENSION_HEIGHT] = 10; + } + } + } + + test("should correctly progagate size contraints from flexible parents", root_node, root_layout); + } + + [Test] + public void TestCase184() { TestCSSNode root_node = new TestCSSNode(); { diff --git a/src/csharp/Facebook.CSSLayout.Tests/TestConstants.cs b/src/csharp/Facebook.CSSLayout.Tests/TestConstants.cs index 03c660b4..b139e02c 100644 --- a/src/csharp/Facebook.CSSLayout.Tests/TestConstants.cs +++ b/src/csharp/Facebook.CSSLayout.Tests/TestConstants.cs @@ -24,6 +24,7 @@ namespace Facebook.CSSLayout.Tests public static readonly string SMALL_TEXT = "small"; public static readonly string LONG_TEXT = "loooooooooong with space"; public static readonly string MEASURE_WITH_RATIO_2 = "measureWithRatio2"; + public static readonly string MEASURE_WITH_MATCH_PARENT = "measureWithMatchParent"; /** END_GENERATED **/ } } diff --git a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs index 87b682fc..4d5543d8 100644 --- a/src/csharp/Facebook.CSSLayout/LayoutEngine.cs +++ b/src/csharp/Facebook.CSSLayout/LayoutEngine.cs @@ -279,7 +279,7 @@ namespace Facebook.CSSLayout 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]))); if (isMeasureDefined(node)) { - boolean isResolvedRowDimDefined = !float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]); + boolean isResolvedRowDimDefined = (!float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0); float width = CSSConstants.Undefined; if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { @@ -295,7 +295,7 @@ namespace Facebook.CSSLayout float height = CSSConstants.Undefined; if ((!float.IsNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { height = node.style.dimensions[DIMENSION_HEIGHT]; - } else if (!float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]])) { + } else if ((!float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { height = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]; } else { height = parentMaxHeight - @@ -341,8 +341,8 @@ namespace Facebook.CSSLayout 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]))); - boolean isMainDimDefined = !float.IsNaN(node.layout.dimensions[dim[mainAxis]]); - boolean isCrossDimDefined = !float.IsNaN(node.layout.dimensions[dim[crossAxis]]); + boolean isMainDimDefined = (!float.IsNaN(node.layout.dimensions[dim[mainAxis]]) && node.layout.dimensions[dim[mainAxis]] >= 0.0); + boolean isCrossDimDefined = (!float.IsNaN(node.layout.dimensions[dim[crossAxis]]) && node.layout.dimensions[dim[crossAxis]] >= 0.0); boolean isMainRowDirection = (mainAxis == CSS_FLEX_DIRECTION_ROW || mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE); int i; @@ -442,7 +442,7 @@ namespace Facebook.CSSLayout // left and right or top and bottom). 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]]) && + if ((!float.IsNaN(node.layout.dimensions[dim[axis]]) && node.layout.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]])) { @@ -489,7 +489,7 @@ namespace Facebook.CSSLayout maxHeight = CSSConstants.Undefined; if (!isMainRowDirection) { - if ((!float.IsNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { + if ((!float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -498,7 +498,7 @@ namespace Facebook.CSSLayout paddingAndBorderAxisResolvedRow; } } else { - if ((!float.IsNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { + if ((!float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else { @@ -549,7 +549,7 @@ namespace Facebook.CSSLayout if (isSimpleStackCross && (child.style.positionType != CSSPositionType.Relative || (alignItem != CSSAlign.Stretch && alignItem != CSSAlign.FlexStart) || - float.IsNaN(child.layout.dimensions[dim[crossAxis]]))) { + !(!float.IsNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0))) { isSimpleStackCross = false; firstComplexCross = i; } @@ -632,7 +632,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.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -641,7 +641,7 @@ namespace Facebook.CSSLayout paddingAndBorderAxisResolvedRow; } maxHeight = CSSConstants.Undefined; - if ((!float.IsNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { + if ((!float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else if (isMainRowDirection) { @@ -761,7 +761,7 @@ namespace Facebook.CSSLayout if (alignItem == CSSAlign.Stretch) { // You can only stretch if the dimension has not already been set // previously. - if (float.IsNaN(child.layout.dimensions[dim[crossAxis]])) { + if (!(!float.IsNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) { child.layout.dimensions[dim[crossAxis]] = Math.Max( boundAxis(child, crossAxis, containerCrossAxis - paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))), @@ -845,7 +845,7 @@ namespace Facebook.CSSLayout if (child.lineIndex != i) { break; } - if (!float.IsNaN(child.layout.dimensions[dim[crossAxis]])) { + if ((!float.IsNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) { lineHeight = Math.Max( lineHeight, child.layout.dimensions[dim[crossAxis]] + (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])) @@ -938,7 +938,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]]) && + if ((!float.IsNaN(node.layout.dimensions[dim[axis]]) && node.layout.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]])) { diff --git a/src/java/src/com/facebook/csslayout/LayoutEngine.java b/src/java/src/com/facebook/csslayout/LayoutEngine.java index 76e057ff..f4743291 100644 --- a/src/java/src/com/facebook/csslayout/LayoutEngine.java +++ b/src/java/src/com/facebook/csslayout/LayoutEngine.java @@ -255,7 +255,7 @@ public class LayoutEngine { 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]))); if (isMeasureDefined(node)) { - boolean isResolvedRowDimDefined = !Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]); + boolean isResolvedRowDimDefined = (!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0); float width = CSSConstants.UNDEFINED; if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { @@ -271,7 +271,7 @@ public class LayoutEngine { float height = CSSConstants.UNDEFINED; if ((!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { height = node.style.dimensions[DIMENSION_HEIGHT]; - } else if (!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]])) { + } else if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { height = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]; } else { height = parentMaxHeight - @@ -317,8 +317,8 @@ public class LayoutEngine { 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]))); - boolean isMainDimDefined = !Float.isNaN(node.layout.dimensions[dim[mainAxis]]); - boolean isCrossDimDefined = !Float.isNaN(node.layout.dimensions[dim[crossAxis]]); + boolean isMainDimDefined = (!Float.isNaN(node.layout.dimensions[dim[mainAxis]]) && node.layout.dimensions[dim[mainAxis]] >= 0.0); + boolean isCrossDimDefined = (!Float.isNaN(node.layout.dimensions[dim[crossAxis]]) && node.layout.dimensions[dim[crossAxis]] >= 0.0); boolean isMainRowDirection = (mainAxis == CSS_FLEX_DIRECTION_ROW || mainAxis == CSS_FLEX_DIRECTION_ROW_REVERSE); int i; @@ -418,7 +418,7 @@ public class LayoutEngine { // left and right or top and bottom). 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]]) && + if ((!Float.isNaN(node.layout.dimensions[dim[axis]]) && node.layout.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]])) { @@ -465,7 +465,7 @@ public class LayoutEngine { maxHeight = CSSConstants.UNDEFINED; if (!isMainRowDirection) { - if ((!Float.isNaN(node.style.dimensions[dim[resolvedRowAxis]]) && node.style.dimensions[dim[resolvedRowAxis]] >= 0.0)) { + if ((!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else { @@ -474,7 +474,7 @@ public class LayoutEngine { paddingAndBorderAxisResolvedRow; } } else { - if ((!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { + if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else { @@ -525,7 +525,7 @@ public class LayoutEngine { if (isSimpleStackCross && (child.style.positionType != CSSPositionType.RELATIVE || (alignItem != CSSAlign.STRETCH && alignItem != CSSAlign.FLEX_START) || - Float.isNaN(child.layout.dimensions[dim[crossAxis]]))) { + !(!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0))) { isSimpleStackCross = false; firstComplexCross = i; } @@ -608,7 +608,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.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0)) { maxWidth = node.layout.dimensions[dim[resolvedRowAxis]] - paddingAndBorderAxisResolvedRow; } else if (!isMainRowDirection) { @@ -617,7 +617,7 @@ public class LayoutEngine { paddingAndBorderAxisResolvedRow; } maxHeight = CSSConstants.UNDEFINED; - if ((!Float.isNaN(node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { + if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { maxHeight = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] - paddingAndBorderAxisColumn; } else if (isMainRowDirection) { @@ -737,7 +737,7 @@ public class LayoutEngine { if (alignItem == CSSAlign.STRETCH) { // You can only stretch if the dimension has not already been set // previously. - if (Float.isNaN(child.layout.dimensions[dim[crossAxis]])) { + if (!(!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) { child.layout.dimensions[dim[crossAxis]] = Math.max( boundAxis(child, crossAxis, containerCrossAxis - paddingAndBorderAxisCross - (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis]))), @@ -821,7 +821,7 @@ public class LayoutEngine { if (child.lineIndex != i) { break; } - if (!Float.isNaN(child.layout.dimensions[dim[crossAxis]])) { + if ((!Float.isNaN(child.layout.dimensions[dim[crossAxis]]) && child.layout.dimensions[dim[crossAxis]] >= 0.0)) { lineHeight = Math.max( lineHeight, child.layout.dimensions[dim[crossAxis]] + (child.style.margin.getWithFallback(leadingSpacing[crossAxis], leading[crossAxis]) + child.style.margin.getWithFallback(trailingSpacing[crossAxis], trailing[crossAxis])) @@ -914,7 +914,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]]) && + if ((!Float.isNaN(node.layout.dimensions[dim[axis]]) && node.layout.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]])) { diff --git a/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java b/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java index 3e1b35cd..b18859ec 100644 --- a/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java +++ b/src/java/tests/com/facebook/csslayout/LayoutEngineTest.java @@ -54,6 +54,9 @@ public class LayoutEngineTest { measureOutput.width = 99999; measureOutput.height = 99999; } + } else if (testNode.context.equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) { + measureOutput.width = width; + measureOutput.height = height; } else { throw new RuntimeException("Got unknown test: " + testNode.context); } @@ -8117,6 +8120,74 @@ public class LayoutEngineTest { @Test public void testCase183() + { + TestCSSNode root_node = new TestCSSNode(); + { + TestCSSNode node_0 = root_node; + node_0.style.flexDirection = CSSFlexDirection.ROW; + node_0.style.alignItems = CSSAlign.FLEX_START; + node_0.style.dimensions[DIMENSION_WIDTH] = 100; + node_0.style.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_0, 2); + { + TestCSSNode node_1; + node_1 = node_0.getChildAt(0); + node_1.style.dimensions[DIMENSION_WIDTH] = 50; + node_1.style.dimensions[DIMENSION_HEIGHT] = 10; + node_1 = node_0.getChildAt(1); + node_1.style.flexDirection = CSSFlexDirection.COLUMN; + node_1.style.alignItems = CSSAlign.FLEX_START; + node_1.style.flex = 1; + node_1.style.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_1, 1); + { + TestCSSNode node_2; + node_2 = node_1.getChildAt(0); + node_2.style.flex = 1; + node_2.style.dimensions[DIMENSION_HEIGHT] = 10; + node_2.setMeasureFunction(sTestMeasureFunction); + node_2.context = "measureWithMatchParent"; + } + } + } + + 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] = 100; + node_0.layout.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_0, 2); + { + 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] = 50; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 10; + node_1 = node_0.getChildAt(1); + node_1.layout.position[POSITION_TOP] = 0; + node_1.layout.position[POSITION_LEFT] = 50; + node_1.layout.dimensions[DIMENSION_WIDTH] = 50; + node_1.layout.dimensions[DIMENSION_HEIGHT] = 10; + addChildren(node_1, 1); + { + TestCSSNode node_2; + node_2 = node_1.getChildAt(0); + node_2.layout.position[POSITION_TOP] = 0; + node_2.layout.position[POSITION_LEFT] = 0; + node_2.layout.dimensions[DIMENSION_WIDTH] = 50; + node_2.layout.dimensions[DIMENSION_HEIGHT] = 10; + } + } + } + + test("should correctly progagate size contraints from flexible parents", root_node, root_layout); + } + + @Test + public void testCase184() { TestCSSNode root_node = new TestCSSNode(); { diff --git a/src/java/tests/com/facebook/csslayout/TestConstants.java b/src/java/tests/com/facebook/csslayout/TestConstants.java index e9049383..41cce209 100644 --- a/src/java/tests/com/facebook/csslayout/TestConstants.java +++ b/src/java/tests/com/facebook/csslayout/TestConstants.java @@ -22,5 +22,6 @@ public class TestConstants { public static final String SMALL_TEXT = "small"; public static final String LONG_TEXT = "loooooooooong with space"; public static final String MEASURE_WITH_RATIO_2 = "measureWithRatio2"; + public static final String MEASURE_WITH_MATCH_PARENT = "measureWithMatchParent"; /** END_GENERATED **/ } diff --git a/src/transpile.js b/src/transpile.js index afe96af6..01f9821c 100644 --- a/src/transpile.js +++ b/src/transpile.js @@ -34,7 +34,8 @@ global.layoutTestUtils = { text: layoutTestUtils.text, texts: layoutTestUtils.texts, textSizes: layoutTestUtils.textSizes, - measureWithRatio2: layoutTestUtils.measureWithRatio2 + measureWithRatio2: layoutTestUtils.measureWithRatio2, + measureWithMatchParent: layoutTestUtils.measureWithMatchParent }; global.describe = function(name, cb) { @@ -297,7 +298,8 @@ function makeConstDefs() { '#define BIG_MIN_WIDTH ' + layoutTestUtils.textSizes.bigMinWidth, '#define SMALL_TEXT "' + layoutTestUtils.texts.small + '"', '#define LONG_TEXT "' + layoutTestUtils.texts.big + '"', - '#define MEASURE_WITH_RATIO_2 "' + layoutTestUtils.measureWithRatio2() + '"' + '#define MEASURE_WITH_RATIO_2 "' + layoutTestUtils.measureWithRatio2() + '"', + '#define MEASURE_WITH_MATCH_PARENT "' + layoutTestUtils.measureWithMatchParent() + '"' ]; return lines.join('\n'); }