Add support for measure mode

This commit is contained in:
Emil Sjolander
2016-01-06 16:56:56 +00:00
parent 68e0b0cc58
commit 7bd6b2b7dd
26 changed files with 237 additions and 45 deletions

9
TestResult.xml Normal file
View File

@@ -0,0 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="no"?>
<!--This file represents the results of running a test suite-->
<test-results name="src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll" total="0" failures="0" not-run="0" date="2016-04-01" time="11:01:04">
<environment nunit-version="2.4.8.0" clr-version="4.0.30319.17020" os-version="Unix 15.4.0.0" platform="Unix" cwd="/Users/emilsj/css-layout" machine-name="emilsj-pro" user="emilsj" user-domain="emilsj-pro" />
<culture-info current-culture="en-US" current-uiculture="en-US" />
<test-suite name="src/csharp/Facebook.CSSLayout.Tests/bin/Release/Facebook.CSSLayout.Tests.dll" success="True" time="0.001" asserts="0">
<results />
</test-suite>
</test-results>

30
dist/css-layout.h vendored
View File

@@ -80,6 +80,12 @@ typedef enum {
CSS_POSITION_COUNT CSS_POSITION_COUNT
} css_position_t; } css_position_t;
typedef enum {
CSS_MEASURE_MODE_UNDEFINED = 0,
CSS_MEASURE_MODE_EXACTLY,
CSS_MEASURE_MODE_AT_MOST
} css_measure_mode_t;
typedef enum { typedef enum {
CSS_WIDTH = 0, CSS_WIDTH = 0,
CSS_HEIGHT CSS_HEIGHT
@@ -144,7 +150,7 @@ struct css_node {
css_node_t *next_absolute_child; css_node_t *next_absolute_child;
css_node_t *next_flex_child; css_node_t *next_flex_child;
css_dim_t (*measure)(void *context, float width, float height); css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
void (*print)(void *context); void (*print)(void *context);
struct css_node* (*get_child)(void *context, int i); struct css_node* (*get_child)(void *context, int i);
bool (*is_dirty)(void *context); bool (*is_dirty)(void *context);
@@ -734,26 +740,40 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM
bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
float width = CSS_UNDEFINED; float width = CSS_UNDEFINED;
css_measure_mode_t widthMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, resolvedRowAxis)) { if (isStyleDimDefined(node, resolvedRowAxis)) {
width = node->style.dimensions[CSS_WIDTH]; width = node->style.dimensions[CSS_WIDTH];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node->layout.dimensions[dim[resolvedRowAxis]]; width = node->layout.dimensions[dim[resolvedRowAxis]];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
widthMode = CSS_MEASURE_MODE_AT_MOST;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (isUndefined(width)) {
widthMode = CSS_MEASURE_MODE_UNDEFINED;
}
float height = CSS_UNDEFINED; float height = CSS_UNDEFINED;
css_measure_mode_t heightMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node->style.dimensions[CSS_HEIGHT]; height = node->style.dimensions[CSS_HEIGHT];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]; height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
heightMode = CSS_MEASURE_MODE_AT_MOST;
} }
height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
if (isUndefined(height)) {
heightMode = CSS_MEASURE_MODE_UNDEFINED;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -768,7 +788,9 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM
node->context, node->context,
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] + node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +
@@ -1447,8 +1469,8 @@ void layoutNode(css_node_t *node, float parentMaxWidth, float parentMaxHeight, c
!node->is_dirty(node->context) && !node->is_dirty(node->context) &&
eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) && eq(layout->last_requested_dimensions[CSS_WIDTH], layout->dimensions[CSS_WIDTH]) &&
eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) && eq(layout->last_requested_dimensions[CSS_HEIGHT], layout->dimensions[CSS_HEIGHT]) &&
eq(layout->last_parent_max_width, parentMaxWidth); eq(layout->last_parent_max_width, parentMaxWidth) &&
eq(layout->last_parent_max_height, parentMaxHeight); eq(layout->last_parent_max_height, parentMaxHeight) &&
eq(layout->last_direction, direction); eq(layout->last_direction, direction);
if (skipLayout) { if (skipLayout) {

BIN
dist/css-layout.jar vendored

Binary file not shown.

24
dist/css-layout.js vendored
View File

@@ -53,6 +53,10 @@ var computeLayout = (function() {
var CSS_POSITION_RELATIVE = 'relative'; var CSS_POSITION_RELATIVE = 'relative';
var CSS_POSITION_ABSOLUTE = 'absolute'; var CSS_POSITION_ABSOLUTE = 'absolute';
var CSS_MEASURE_MODE_UNDEFINED = 'undefined';
var CSS_MEASURE_MODE_EXACTLY = 'exactly';
var CSS_MEASURE_MODE_AT_MOST = 'at-most';
var leading = { var leading = {
'row': 'left', 'row': 'left',
'row-reverse': 'right', 'row-reverse': 'right',
@@ -110,7 +114,7 @@ var computeLayout = (function() {
} }
function isUndefined(value) { function isUndefined(value) {
return value === undefined; return value === undefined || isNaN(value);
} }
function isRowDirection(flexDirection) { function isRowDirection(flexDirection) {
@@ -501,26 +505,40 @@ var computeLayout = (function() {
var/*bool*/ isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); var/*bool*/ isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
var/*float*/ width = CSS_UNDEFINED; var/*float*/ width = CSS_UNDEFINED;
var/*css_measure_mode_t*/ widthMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, resolvedRowAxis)) { if (isStyleDimDefined(node, resolvedRowAxis)) {
width = node.style.width; width = node.style.width;
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node.layout[dim[resolvedRowAxis]]; width = node.layout[dim[resolvedRowAxis]];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
widthMode = CSS_MEASURE_MODE_AT_MOST;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (isUndefined(width)) {
widthMode = CSS_MEASURE_MODE_UNDEFINED;
}
var/*float*/ height = CSS_UNDEFINED; var/*float*/ height = CSS_UNDEFINED;
var/*css_measure_mode_t*/ heightMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node.style.height; height = node.style.height;
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]; height = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
heightMode = CSS_MEASURE_MODE_AT_MOST;
} }
height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
if (isUndefined(height)) {
heightMode = CSS_MEASURE_MODE_UNDEFINED;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -535,7 +553,9 @@ var computeLayout = (function() {
/*(c)!node->context,*/ /*(c)!node->context,*/
/*(java)!layoutContext.measureOutput,*/ /*(java)!layoutContext.measureOutput,*/
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node.layout.width = measureDim.width + node.layout.width = measureDim.width +

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@@ -11,12 +11,14 @@ function __transpileToCSharpCommon(code) {
return code return code
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED') .replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.') .replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
.replace(/CSS_ALIGN_/g, 'CSSAlign.') .replace(/CSS_ALIGN_/g, 'CSSAlign.')
.replace(/CSS_POSITION_/g, 'CSSPositionType.') .replace(/CSS_POSITION_/g, 'CSSPositionType.')
.replace(/css_flex_direction_t/g, 'CSSFlexDirection') .replace(/css_flex_direction_t/g, 'CSSFlexDirection')
.replace(/css_direction_t/g, 'CSSDirection') .replace(/css_direction_t/g, 'CSSDirection')
.replace(/css_align_t/g, 'CSSAlign') .replace(/css_align_t/g, 'CSSAlign')
.replace(/css_justify_t/g, 'CSSJustify') .replace(/css_justify_t/g, 'CSSJustify')
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
.replace(/css_dim_t/g, 'MeasureOutput') .replace(/css_dim_t/g, 'MeasureOutput')
.replace(/bool/g, 'boolean') .replace(/bool/g, 'boolean')
.replace(/style\[dim/g, 'style.dimensions[dim') .replace(/style\[dim/g, 'style.dimensions[dim')
@@ -56,7 +58,7 @@ function __transpileToCSharpCommon(code) {
// additional case conversions // additional case conversions
.replace(/(CSSConstants|CSSWrap|CSSJustify|CSSAlign|CSSPositionType)\.([_A-Z]+)/g, .replace(/(CSSConstants|CSSWrap|CSSJustify|CSSMeasureMode|CSSAlign|CSSPositionType)\.([_A-Z]+)/g,
function(str, match1, match2) { function(str, match1, match2) {
return match1 + '.' + constantToPascalCase(match2); return match1 + '.' + constantToPascalCase(match2);
}); });

View File

@@ -11,12 +11,14 @@ function __transpileToJavaCommon(code) {
return code return code
.replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED') .replace(/CSS_UNDEFINED/g, 'CSSConstants.UNDEFINED')
.replace(/CSS_JUSTIFY_/g, 'CSSJustify.') .replace(/CSS_JUSTIFY_/g, 'CSSJustify.')
.replace(/CSS_MEASURE_MODE_/g, 'CSSMeasureMode.')
.replace(/CSS_ALIGN_/g, 'CSSAlign.') .replace(/CSS_ALIGN_/g, 'CSSAlign.')
.replace(/CSS_POSITION_/g, 'CSSPositionType.') .replace(/CSS_POSITION_/g, 'CSSPositionType.')
.replace(/css_flex_direction_t/g, 'CSSFlexDirection') .replace(/css_flex_direction_t/g, 'CSSFlexDirection')
.replace(/css_direction_t/g, 'CSSDirection') .replace(/css_direction_t/g, 'CSSDirection')
.replace(/css_align_t/g, 'CSSAlign') .replace(/css_align_t/g, 'CSSAlign')
.replace(/css_justify_t/g, 'CSSJustify') .replace(/css_justify_t/g, 'CSSJustify')
.replace(/css_measure_mode_t/g, 'CSSMeasureMode')
.replace(/css_dim_t/g, 'MeasureOutput') .replace(/css_dim_t/g, 'MeasureOutput')
.replace(/bool/g, 'boolean') .replace(/bool/g, 'boolean')
.replace(/style\[dim/g, 'style.dimensions[dim') .replace(/style\[dim/g, 'style.dimensions[dim')

View File

@@ -82,11 +82,11 @@ static bool are_layout_equal(css_node_t *a, css_node_t *b) {
return true; return true;
} }
css_dim_t measure(void *context, float width, float height) { css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode) {
const char *text = (const char *)context; const char *text = (const char *)context;
css_dim_t dim; css_dim_t dim;
if (strcmp(text, SMALL_TEXT) == 0) { if (strcmp(text, SMALL_TEXT) == 0) {
if (width != width) { if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
width = 1000000; width = 1000000;
} }
dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width); dim.dimensions[CSS_WIDTH] = fminf(SMALL_WIDTH, width);
@@ -94,7 +94,7 @@ css_dim_t measure(void *context, float width, float height) {
return dim; return dim;
} }
if (strcmp(text, LONG_TEXT) == 0) { if (strcmp(text, LONG_TEXT) == 0) {
if (width != width) { if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
width = 1000000; width = 1000000;
} }
dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width); dim.dimensions[CSS_WIDTH] = width >= BIG_WIDTH ? BIG_WIDTH : fmaxf(BIG_MIN_WIDTH, width);
@@ -103,10 +103,10 @@ css_dim_t measure(void *context, float width, float height) {
} }
if (strcmp(text, MEASURE_WITH_RATIO_2) == 0) { if (strcmp(text, MEASURE_WITH_RATIO_2) == 0) {
if (width > 0) { if (widthMode != CSS_MEASURE_MODE_UNDEFINED) {
dim.dimensions[CSS_WIDTH] = width; dim.dimensions[CSS_WIDTH] = width;
dim.dimensions[CSS_HEIGHT] = width * 2; dim.dimensions[CSS_HEIGHT] = width * 2;
} else if (height > 0) { } else if (heightMode != CSS_MEASURE_MODE_UNDEFINED) {
dim.dimensions[CSS_WIDTH] = height * 2; dim.dimensions[CSS_WIDTH] = height * 2;
dim.dimensions[CSS_HEIGHT] = height; dim.dimensions[CSS_HEIGHT] = height;
} else { } else {
@@ -117,6 +117,12 @@ css_dim_t measure(void *context, float width, float height) {
} }
if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) { if (strcmp(text, MEASURE_WITH_MATCH_PARENT) == 0) {
if (widthMode == CSS_MEASURE_MODE_UNDEFINED) {
width = 99999;
}
if (heightMode == CSS_MEASURE_MODE_UNDEFINED) {
height = 99999;
}
dim.dimensions[CSS_WIDTH] = width; dim.dimensions[CSS_WIDTH] = width;
dim.dimensions[CSS_HEIGHT] = height; dim.dimensions[CSS_HEIGHT] = height;
return dim; return dim;

View File

@@ -13,6 +13,6 @@
void test(const char *name, css_node_t *style, css_node_t *expected_layout); void test(const char *name, css_node_t *style, css_node_t *expected_layout);
int tests_finished(void); int tests_finished(void);
css_dim_t measure(void *context, float width, float height); css_dim_t measure(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
void init_css_node_children(css_node_t *node, int children_count); void init_css_node_children(css_node_t *node, int children_count);
css_node_t *new_test_css_node(void); css_node_t *new_test_css_node(void);

View File

@@ -494,8 +494,8 @@ var layoutTestUtils = (function() {
computeDOMLayout: computeDOMLayout, computeDOMLayout: computeDOMLayout,
reduceTest: reduceTest, reduceTest: reduceTest,
text: function(text) { text: function(text) {
var fn = function(width, height) { var fn = function(width, widthMode, height, heightMode) {
if (width === undefined || isNaN(width)) { if (widthMode === 'undefined') {
width = Infinity; width = Infinity;
} }
@@ -522,10 +522,10 @@ var layoutTestUtils = (function() {
return fn; return fn;
}, },
measureWithRatio2: function() { measureWithRatio2: function() {
var fn = function(width, height) { var fn = function(width, widthMode, height, heightMode) {
if (width > 0) { if (widthMode !== 'undefined') {
height = width * 2; height = width * 2;
} else if (height > 0) { } else if (heightMode !== 'undefined') {
width = height * 2; width = height * 2;
} else { } else {
// This should be Infinity, but it would be pain to transpile, // This should be Infinity, but it would be pain to transpile,
@@ -540,7 +540,13 @@ var layoutTestUtils = (function() {
return fn; return fn;
}, },
measureWithMatchParent: function() { measureWithMatchParent: function() {
var fn = function(width, height) { var fn = function(width, widthMode, height, heightMode) {
if (widthMode === 'undefined') {
width = 99999;
}
if (heightMode === 'undefined') {
height = 99999;
}
return {width: width, height: height}; return {width: width, height: height};
}; };
// This is necessary for transpiled tests, see previous comment // This is necessary for transpiled tests, see previous comment

View File

@@ -557,26 +557,40 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM
bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); bool isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
float width = CSS_UNDEFINED; float width = CSS_UNDEFINED;
css_measure_mode_t widthMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, resolvedRowAxis)) { if (isStyleDimDefined(node, resolvedRowAxis)) {
width = node->style.dimensions[CSS_WIDTH]; width = node->style.dimensions[CSS_WIDTH];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node->layout.dimensions[dim[resolvedRowAxis]]; width = node->layout.dimensions[dim[resolvedRowAxis]];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
widthMode = CSS_MEASURE_MODE_AT_MOST;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (isUndefined(width)) {
widthMode = CSS_MEASURE_MODE_UNDEFINED;
}
float height = CSS_UNDEFINED; float height = CSS_UNDEFINED;
css_measure_mode_t heightMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node->style.dimensions[CSS_HEIGHT]; height = node->style.dimensions[CSS_HEIGHT];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]; height = node->layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
heightMode = CSS_MEASURE_MODE_AT_MOST;
} }
height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
if (isUndefined(height)) {
heightMode = CSS_MEASURE_MODE_UNDEFINED;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -591,7 +605,9 @@ static void layoutNodeImpl(css_node_t *node, float parentMaxWidth, float parentM
node->context, node->context,
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] + node->layout.dimensions[CSS_WIDTH] = measureDim.dimensions[CSS_WIDTH] +

View File

@@ -76,6 +76,12 @@ typedef enum {
CSS_POSITION_COUNT CSS_POSITION_COUNT
} css_position_t; } css_position_t;
typedef enum {
CSS_MEASURE_MODE_UNDEFINED = 0,
CSS_MEASURE_MODE_EXACTLY,
CSS_MEASURE_MODE_AT_MOST
} css_measure_mode_t;
typedef enum { typedef enum {
CSS_WIDTH = 0, CSS_WIDTH = 0,
CSS_HEIGHT CSS_HEIGHT
@@ -140,7 +146,7 @@ struct css_node {
css_node_t *next_absolute_child; css_node_t *next_absolute_child;
css_node_t *next_flex_child; css_node_t *next_flex_child;
css_dim_t (*measure)(void *context, float width, float height); css_dim_t (*measure)(void *context, float width, css_measure_mode_t widthMode, float height, css_measure_mode_t heightMode);
void (*print)(void *context); void (*print)(void *context);
struct css_node* (*get_child)(void *context, int i); struct css_node* (*get_child)(void *context, int i);
bool (*is_dirty)(void *context); bool (*is_dirty)(void *context);

View File

@@ -34,6 +34,10 @@ var computeLayout = (function() {
var CSS_POSITION_RELATIVE = 'relative'; var CSS_POSITION_RELATIVE = 'relative';
var CSS_POSITION_ABSOLUTE = 'absolute'; var CSS_POSITION_ABSOLUTE = 'absolute';
var CSS_MEASURE_MODE_UNDEFINED = 'undefined';
var CSS_MEASURE_MODE_EXACTLY = 'exactly';
var CSS_MEASURE_MODE_AT_MOST = 'at-most';
var leading = { var leading = {
'row': 'left', 'row': 'left',
'row-reverse': 'right', 'row-reverse': 'right',
@@ -91,7 +95,7 @@ var computeLayout = (function() {
} }
function isUndefined(value) { function isUndefined(value) {
return value === undefined; return value === undefined || isNaN(value);
} }
function isRowDirection(flexDirection) { function isRowDirection(flexDirection) {
@@ -482,26 +486,40 @@ var computeLayout = (function() {
var/*bool*/ isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis); var/*bool*/ isResolvedRowDimDefined = isLayoutDimDefined(node, resolvedRowAxis);
var/*float*/ width = CSS_UNDEFINED; var/*float*/ width = CSS_UNDEFINED;
var/*css_measure_mode_t*/ widthMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, resolvedRowAxis)) { if (isStyleDimDefined(node, resolvedRowAxis)) {
width = node.style.width; width = node.style.width;
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node.layout[dim[resolvedRowAxis]]; width = node.layout[dim[resolvedRowAxis]];
widthMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
widthMode = CSS_MEASURE_MODE_AT_MOST;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (isUndefined(width)) {
widthMode = CSS_MEASURE_MODE_UNDEFINED;
}
var/*float*/ height = CSS_UNDEFINED; var/*float*/ height = CSS_UNDEFINED;
var/*css_measure_mode_t*/ heightMode = CSS_MEASURE_MODE_UNDEFINED;
if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { if (isStyleDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node.style.height; height = node.style.height;
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) { } else if (isLayoutDimDefined(node, CSS_FLEX_DIRECTION_COLUMN)) {
height = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]]; height = node.layout[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSS_MEASURE_MODE_EXACTLY;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
getMarginAxis(node, resolvedRowAxis); getMarginAxis(node, resolvedRowAxis);
heightMode = CSS_MEASURE_MODE_AT_MOST;
} }
height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN); height -= getPaddingAndBorderAxis(node, CSS_FLEX_DIRECTION_COLUMN);
if (isUndefined(height)) {
heightMode = CSS_MEASURE_MODE_UNDEFINED;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -516,7 +534,9 @@ var computeLayout = (function() {
/*(c)!node->context,*/ /*(c)!node->context,*/
/*(java)!layoutContext.measureOutput,*/ /*(java)!layoutContext.measureOutput,*/
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node.layout.width = measureDim.width + node.layout.width = measureDim.width +

View File

@@ -226,7 +226,7 @@ namespace Facebook.CSSLayout.Tests
root.calculateLayout(); root.calculateLayout();
markLayoutAppliedForTree(root); markLayoutAppliedForTree(root);
c1.setMeasureFunction((node, width, height) => new MeasureOutput(100, 20)); c1.setMeasureFunction((node, width, widthMode, height, heightMode) => new MeasureOutput(100, 20));
root.calculateLayout(); root.calculateLayout();

View File

@@ -25,11 +25,11 @@ public class LayoutEngineTest
const int DIMENSION_HEIGHT = CSSLayout.DIMENSION_HEIGHT; const int DIMENSION_HEIGHT = CSSLayout.DIMENSION_HEIGHT;
const int DIMENSION_WIDTH = CSSLayout.DIMENSION_WIDTH; const int DIMENSION_WIDTH = CSSLayout.DIMENSION_WIDTH;
static readonly MeasureFunction sTestMeasureFunction = (node, width, height) => static readonly MeasureFunction sTestMeasureFunction = (node, width, widthMode, height, heightMode) =>
{ {
TestCSSNode testNode = (TestCSSNode) node; TestCSSNode testNode = (TestCSSNode) node;
if (testNode.context.Equals(TestConstants.SMALL_TEXT)) { if (testNode.context.Equals(TestConstants.SMALL_TEXT)) {
if (CSSConstants.IsUndefined(width)) { if (widthMode == CSSMeasureMode.Undefined) {
width = 10000000; width = 10000000;
} }
return new MeasureOutput( return new MeasureOutput(
@@ -46,14 +46,20 @@ public class LayoutEngineTest
? TestConstants.SMALL_HEIGHT ? TestConstants.SMALL_HEIGHT
: TestConstants.BIG_HEIGHT); : TestConstants.BIG_HEIGHT);
} else if (testNode.context.Equals(TestConstants.MEASURE_WITH_RATIO_2)) { } else if (testNode.context.Equals(TestConstants.MEASURE_WITH_RATIO_2)) {
if (width > 0) { if (widthMode != CSSMeasureMode.Undefined) {
return new MeasureOutput(width, width * 2); return new MeasureOutput(width, width * 2);
} else if (height > 0) { } else if (heightMode != CSSMeasureMode.Undefined) {
return new MeasureOutput(height * 2, height); return new MeasureOutput(height * 2, height);
} else { } else {
return new MeasureOutput(99999, 99999); return new MeasureOutput(99999, 99999);
} }
} else if (testNode.context.Equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) { } else if (testNode.context.Equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) {
if (widthMode == CSSMeasureMode.Undefined) {
width = 99999;
}
if (heightMode == CSSMeasureMode.Undefined) {
height = 99999;
}
return new MeasureOutput(width, height); return new MeasureOutput(width, height);
} else { } else {
throw new Exception("Got unknown test: " + testNode.context); throw new Exception("Got unknown test: " + testNode.context);

View File

@@ -0,0 +1,18 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
namespace Facebook.CSSLayout
{
public enum CSSMeasureMode
{
Undefined,
Exactly,
AtMost,
}
}

View File

@@ -17,7 +17,7 @@ namespace Facebook.CSSLayout
* Should measure the given node and put the result in the given MeasureOutput. * Should measure the given node and put the result in the given MeasureOutput.
*/ */
public delegate MeasureOutput MeasureFunction(CSSNode node, float width, float height); public delegate MeasureOutput MeasureFunction(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode);
/** /**
* A CSS Node. It has a style object you can manipulate at {@link #style}. After calling * A CSS Node. It has a style object you can manipulate at {@link #style}. After calling
@@ -140,13 +140,13 @@ namespace Facebook.CSSLayout
get { return mMeasureFunction != null; } get { return mMeasureFunction != null; }
} }
internal MeasureOutput measure(MeasureOutput measureOutput, float width, float height) internal MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode)
{ {
if (!IsMeasureDefined) if (!IsMeasureDefined)
{ {
throw new Exception("Measure function isn't defined!"); throw new Exception("Measure function isn't defined!");
} }
return Assertions.assertNotNull(mMeasureFunction)(this, width, height); return Assertions.assertNotNull(mMeasureFunction)(this, width, widthMode, height, heightMode);
} }
/** /**

View File

@@ -45,6 +45,7 @@
<Compile Include="CSSDirection.cs" /> <Compile Include="CSSDirection.cs" />
<Compile Include="CSSFlexDirection.cs" /> <Compile Include="CSSFlexDirection.cs" />
<Compile Include="CSSJustify.cs" /> <Compile Include="CSSJustify.cs" />
<Compile Include="CSSMeasureMode.cs" />
<Compile Include="CSSLayout.cs" /> <Compile Include="CSSLayout.cs" />
<Compile Include="CSSLayoutContext.cs" /> <Compile Include="CSSLayoutContext.cs" />
<Compile Include="CSSNode.cs" /> <Compile Include="CSSNode.cs" />
@@ -67,4 +68,4 @@
<Target Name="AfterBuild"> <Target Name="AfterBuild">
</Target> </Target>
--> -->
</Project> </Project>

View File

@@ -282,26 +282,40 @@ namespace Facebook.CSSLayout
boolean isResolvedRowDimDefined = (!float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0); boolean isResolvedRowDimDefined = (!float.IsNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0);
float width = CSSConstants.Undefined; float width = CSSConstants.Undefined;
CSSMeasureMode widthMode = CSSMeasureMode.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]; width = node.style.dimensions[DIMENSION_WIDTH];
widthMode = CSSMeasureMode.Exactly;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node.layout.dimensions[dim[resolvedRowAxis]]; width = node.layout.dimensions[dim[resolvedRowAxis]];
widthMode = CSSMeasureMode.Exactly;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
(node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])); (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
widthMode = CSSMeasureMode.AtMost;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (float.IsNaN(width)) {
widthMode = CSSMeasureMode.Undefined;
}
float height = CSSConstants.Undefined; float height = CSSConstants.Undefined;
CSSMeasureMode heightMode = CSSMeasureMode.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.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
height = node.style.dimensions[DIMENSION_HEIGHT]; height = node.style.dimensions[DIMENSION_HEIGHT];
heightMode = CSSMeasureMode.Exactly;
} else if ((!float.IsNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { } 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]]; height = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSSMeasureMode.Exactly;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
(node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])); (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
heightMode = CSSMeasureMode.AtMost;
} }
height -= ((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]))); height -= ((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 (float.IsNaN(height)) {
heightMode = CSSMeasureMode.Undefined;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -316,7 +330,9 @@ namespace Facebook.CSSLayout
layoutContext.measureOutput, layoutContext.measureOutput,
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node.layout.dimensions[DIMENSION_WIDTH] = measureDim.width + node.layout.dimensions[DIMENSION_WIDTH] = measureDim.width +

View File

@@ -0,0 +1,15 @@
/**
* Copyright (c) 2014, Facebook, Inc.
* All rights reserved.
*
* This source code is licensed under the BSD-style license found in the
* LICENSE file in the root directory of this source tree. An additional grant
* of patent rights can be found in the PATENTS file in the same directory.
*/
package com.facebook.csslayout;
public enum CSSMeasureMode {
UNDEFINED,
EXACTLY,
AT_MOST,
}

View File

@@ -53,7 +53,7 @@ public class CSSNode {
* *
* NB: measure is NOT guaranteed to be threadsafe/re-entrant safe! * NB: measure is NOT guaranteed to be threadsafe/re-entrant safe!
*/ */
public void measure(CSSNode node, float width, float height, MeasureOutput measureOutput); public void measure(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode, MeasureOutput measureOutput);
} }
// VisibleForTesting // VisibleForTesting
@@ -125,13 +125,13 @@ public class CSSNode {
return mMeasureFunction != null; return mMeasureFunction != null;
} }
/*package*/ MeasureOutput measure(MeasureOutput measureOutput, float width, float height) { /*package*/ MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode) {
if (!isMeasureDefined()) { if (!isMeasureDefined()) {
throw new RuntimeException("Measure function isn't defined!"); throw new RuntimeException("Measure function isn't defined!");
} }
measureOutput.height = CSSConstants.UNDEFINED; measureOutput.height = CSSConstants.UNDEFINED;
measureOutput.width = CSSConstants.UNDEFINED; measureOutput.width = CSSConstants.UNDEFINED;
Assertions.assertNotNull(mMeasureFunction).measure(this, width, height, measureOutput); Assertions.assertNotNull(mMeasureFunction).measure(this, width, widthMode, height, heightMode, measureOutput);
return measureOutput; return measureOutput;
} }

View File

@@ -258,26 +258,40 @@ public class LayoutEngine {
boolean isResolvedRowDimDefined = (!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0); boolean isResolvedRowDimDefined = (!Float.isNaN(node.layout.dimensions[dim[resolvedRowAxis]]) && node.layout.dimensions[dim[resolvedRowAxis]] >= 0.0);
float width = CSSConstants.UNDEFINED; float width = CSSConstants.UNDEFINED;
CSSMeasureMode widthMode = CSSMeasureMode.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]; width = node.style.dimensions[DIMENSION_WIDTH];
widthMode = CSSMeasureMode.EXACTLY;
} else if (isResolvedRowDimDefined) { } else if (isResolvedRowDimDefined) {
width = node.layout.dimensions[dim[resolvedRowAxis]]; width = node.layout.dimensions[dim[resolvedRowAxis]];
widthMode = CSSMeasureMode.EXACTLY;
} else { } else {
width = parentMaxWidth - width = parentMaxWidth -
(node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])); (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
widthMode = CSSMeasureMode.AT_MOST;
} }
width -= paddingAndBorderAxisResolvedRow; width -= paddingAndBorderAxisResolvedRow;
if (Float.isNaN(width)) {
widthMode = CSSMeasureMode.UNDEFINED;
}
float height = CSSConstants.UNDEFINED; float height = CSSConstants.UNDEFINED;
CSSMeasureMode heightMode = CSSMeasureMode.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.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.style.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) {
height = node.style.dimensions[DIMENSION_HEIGHT]; height = node.style.dimensions[DIMENSION_HEIGHT];
heightMode = CSSMeasureMode.EXACTLY;
} else if ((!Float.isNaN(node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]]) && node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]] >= 0.0)) { } 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]]; height = node.layout.dimensions[dim[CSS_FLEX_DIRECTION_COLUMN]];
heightMode = CSSMeasureMode.EXACTLY;
} else { } else {
height = parentMaxHeight - height = parentMaxHeight -
(node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis])); (node.style.margin.getWithFallback(leadingSpacing[resolvedRowAxis], leading[resolvedRowAxis]) + node.style.margin.getWithFallback(trailingSpacing[resolvedRowAxis], trailing[resolvedRowAxis]));
heightMode = CSSMeasureMode.AT_MOST;
} }
height -= ((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]))); height -= ((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 (Float.isNaN(height)) {
heightMode = CSSMeasureMode.UNDEFINED;
}
// We only need to give a dimension for the text if we haven't got any // 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 // for it computed yet. It can either be from the style attribute or because
@@ -292,7 +306,9 @@ public class LayoutEngine {
layoutContext.measureOutput, layoutContext.measureOutput,
width, width,
height widthMode,
height,
heightMode
); );
if (isRowUndefined) { if (isRowUndefined) {
node.layout.dimensions[DIMENSION_WIDTH] = measureDim.width + node.layout.dimensions[DIMENSION_WIDTH] = measureDim.width +

View File

@@ -223,7 +223,7 @@ public class LayoutCachingTest {
c1.setMeasureFunction(new CSSNode.MeasureFunction() { c1.setMeasureFunction(new CSSNode.MeasureFunction() {
@Override @Override
public void measure(CSSNode node, float width, float height, MeasureOutput measureOutput) { public void measure(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode, MeasureOutput measureOutput) {
measureOutput.width = 100; measureOutput.width = 100;
measureOutput.height = 20; measureOutput.height = 20;
} }

View File

@@ -27,16 +27,16 @@ public class LayoutEngineTest {
new CSSNode.MeasureFunction() { new CSSNode.MeasureFunction() {
@Override @Override
public void measure(CSSNode node, float width, float height, MeasureOutput measureOutput) { public void measure(CSSNode node, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode, MeasureOutput measureOutput) {
TestCSSNode testNode = (TestCSSNode) node; TestCSSNode testNode = (TestCSSNode) node;
if (testNode.context.equals(TestConstants.SMALL_TEXT)) { if (testNode.context.equals(TestConstants.SMALL_TEXT)) {
if (CSSConstants.isUndefined(width)) { if (widthMode == CSSMeasureMode.UNDEFINED) {
width = 10000000; width = 10000000;
} }
measureOutput.width = Math.min(width, TestConstants.SMALL_WIDTH); measureOutput.width = Math.min(width, TestConstants.SMALL_WIDTH);
measureOutput.height = TestConstants.SMALL_HEIGHT; measureOutput.height = TestConstants.SMALL_HEIGHT;
} else if (testNode.context.equals(TestConstants.LONG_TEXT)) { } else if (testNode.context.equals(TestConstants.LONG_TEXT)) {
if (CSSConstants.isUndefined(width)) { if (widthMode == CSSMeasureMode.UNDEFINED) {
width = 10000000; width = 10000000;
} }
measureOutput.width = width >= TestConstants.BIG_WIDTH ? measureOutput.width = width >= TestConstants.BIG_WIDTH ?
@@ -44,10 +44,10 @@ public class LayoutEngineTest {
measureOutput.height = width >= TestConstants.BIG_WIDTH ? measureOutput.height = width >= TestConstants.BIG_WIDTH ?
TestConstants.SMALL_HEIGHT : TestConstants.BIG_HEIGHT; TestConstants.SMALL_HEIGHT : TestConstants.BIG_HEIGHT;
} else if (testNode.context.equals(TestConstants.MEASURE_WITH_RATIO_2)) { } else if (testNode.context.equals(TestConstants.MEASURE_WITH_RATIO_2)) {
if (width > 0) { if (widthMode != CSSMeasureMode.UNDEFINED) {
measureOutput.width = width; measureOutput.width = width;
measureOutput.height = width * 2; measureOutput.height = width * 2;
} else if (height > 0) { } else if (heightMode != CSSMeasureMode.UNDEFINED) {
measureOutput.width = height * 2; measureOutput.width = height * 2;
measureOutput.height = height; measureOutput.height = height;
} else { } else {
@@ -55,6 +55,12 @@ public class LayoutEngineTest {
measureOutput.height = 99999; measureOutput.height = 99999;
} }
} else if (testNode.context.equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) { } else if (testNode.context.equals(TestConstants.MEASURE_WITH_MATCH_PARENT)) {
if (widthMode == CSSMeasureMode.UNDEFINED) {
width = 99999;
}
if (heightMode == CSSMeasureMode.UNDEFINED) {
height = 99999;
}
measureOutput.width = width; measureOutput.width = width;
measureOutput.height = height; measureOutput.height = height;
} else { } else {

View File

@@ -170,6 +170,11 @@ function printLayout(test) {
'nowrap': 'CSS_NOWRAP', 'nowrap': 'CSS_NOWRAP',
'wrap': 'CSS_WRAP' 'wrap': 'CSS_WRAP'
}); });
addEnum(node, 'measureMode', 'measure_mode', {
'undefined': 'CSS_MEASURE_MODE_UNDEFINED',
'exactly': 'CSS_MEASURE_MODE_EXACTLY',
'at-most': 'CSS_MEASURE_MODE_AT_MOST'
});
addFloat(node, 'flex', 'flex'); addFloat(node, 'flex', 'flex');
addFloat(node, 'width', 'dimensions[CSS_WIDTH]'); addFloat(node, 'width', 'dimensions[CSS_WIDTH]');
addFloat(node, 'height', 'dimensions[CSS_HEIGHT]'); addFloat(node, 'height', 'dimensions[CSS_HEIGHT]');