Improve heuristic for cache re-use #195
88
dist/css-layout.h
vendored
88
dist/css-layout.h
vendored
@@ -180,6 +180,7 @@ struct css_node {
|
|||||||
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);
|
||||||
|
bool (*is_text_node)(void *context);
|
||||||
void *context;
|
void *context;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1752,35 +1753,80 @@ static const char* getModeName(css_measure_mode_t mode, bool performLayout) {
|
|||||||
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
|
static bool canUseCachedMeasurement(
|
||||||
float marginRow, float marginColumn,
|
bool is_text_node,
|
||||||
css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode,
|
float available_width,
|
||||||
css_cached_measurement_t cachedLayout) {
|
float available_height,
|
||||||
|
float margin_row,
|
||||||
|
float margin_column,
|
||||||
|
css_measure_mode_t width_measure_mode,
|
||||||
|
css_measure_mode_t height_measure_mode,
|
||||||
|
css_cached_measurement_t cached_layout) {
|
||||||
|
|
||||||
// Is it an exact match?
|
bool is_height_same =
|
||||||
if (eq(cachedLayout.available_width, availableWidth) &&
|
(cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
eq(cachedLayout.available_height, availableHeight) &&
|
(cached_layout.height_measure_mode == height_measure_mode && eq(cached_layout.available_height, available_height));
|
||||||
cachedLayout.width_measure_mode == widthMeasureMode &&
|
|
||||||
cachedLayout.height_measure_mode == heightMeasureMode) {
|
bool is_width_same =
|
||||||
|
(cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
|
(cached_layout.width_measure_mode == width_measure_mode && eq(cached_layout.available_width, available_width));
|
||||||
|
|
||||||
|
if (is_height_same && is_width_same) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
bool is_height_valid =
|
||||||
if (cachedLayout.width_measure_mode == widthMeasureMode &&
|
(cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_height <= (available_height - margin_column)) ||
|
||||||
eq(cachedLayout.available_width, availableWidth) &&
|
(height_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_height, available_height - margin_column));
|
||||||
heightMeasureMode == CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
eq(availableHeight - marginColumn, cachedLayout.computed_height)) {
|
if (is_width_same && is_height_valid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
bool is_width_valid =
|
||||||
if (cachedLayout.height_measure_mode == heightMeasureMode &&
|
(cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_width <= (available_width - margin_row)) ||
|
||||||
eq(cachedLayout.available_height, availableHeight) &&
|
(width_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_width, available_width - margin_row));
|
||||||
widthMeasureMode == CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
eq(availableWidth - marginRow, cachedLayout.computed_width)) {
|
if (is_height_same && is_width_valid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_height_valid && is_width_valid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (is_text_node) {
|
||||||
|
if (is_width_same) {
|
||||||
|
if (height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height_measure_mode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cached_layout.computed_height < (available_height - margin_column)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cached_layout.computed_height = available_height - margin_column;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
if (width_measure_mode == CSS_MEASURE_MODE_UNDEFINED ||
|
||||||
|
(width_measure_mode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cached_layout.computed_width <= (available_width - margin_row))) {
|
||||||
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1822,13 +1868,13 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
|
|||||||
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
|
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
|
||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
|
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
|
||||||
cachedResults = &layout->cached_layout;
|
cachedResults = &layout->cached_layout;
|
||||||
} else {
|
} else {
|
||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (int i = 0; i < layout->next_cached_measurements_index; i++) {
|
for (int i = 0; i < layout->next_cached_measurements_index; i++) {
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout->cached_measurements[i])) {
|
widthMeasureMode, heightMeasureMode, layout->cached_measurements[i])) {
|
||||||
cachedResults = &layout->cached_measurements[i];
|
cachedResults = &layout->cached_measurements[i];
|
||||||
break;
|
break;
|
||||||
|
BIN
dist/css-layout.jar
vendored
BIN
dist/css-layout.jar
vendored
Binary file not shown.
87
dist/css-layout.js
vendored
87
dist/css-layout.js
vendored
@@ -1481,35 +1481,80 @@ var computeLayout = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function canUseCachedMeasurement(availableWidth, availableHeight,
|
function canUseCachedMeasurement(
|
||||||
marginRow, marginColumn,
|
isTextNode,
|
||||||
widthMeasureMode, heightMeasureMode,
|
availableWidth,
|
||||||
cachedLayout) {
|
availableHeight,
|
||||||
|
marginRow,
|
||||||
|
marginColumn,
|
||||||
|
widthMeasureMode,
|
||||||
|
heightMeasureMode,
|
||||||
|
cachedLayout) {
|
||||||
|
|
||||||
// Is it an exact match?
|
var isHeightSame =
|
||||||
if (cachedLayout.availableWidth === availableWidth &&
|
(cachedLayout.heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED && heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
cachedLayout.availableHeight === availableHeight &&
|
(cachedLayout.heightMeasureMode == heightMeasureMode && cachedLayout.availableHeight == availableHeight);
|
||||||
cachedLayout.widthMeasureMode === widthMeasureMode &&
|
|
||||||
cachedLayout.heightMeasureMode === heightMeasureMode) {
|
var isWidthSame =
|
||||||
|
(cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED && widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
|
(cachedLayout.widthMeasureMode == widthMeasureMode && cachedLayout.availableWidth == availableWidth);
|
||||||
|
|
||||||
|
if (isHeightSame && isWidthSame) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
var isHeightValid =
|
||||||
if (cachedLayout.availableWidth === availableWidth &&
|
(cachedLayout.heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED && heightMeasureMode == CSS_MEASURE_MODE_AT_MOST && cachedLayout.computedHeight <= (availableHeight - marginColumn)) ||
|
||||||
cachedLayout.widthMeasureMode === widthMeasureMode &&
|
(heightMeasureMode == CSS_MEASURE_MODE_EXACTLY && cachedLayout.computedHeight == (availableHeight - marginColumn));
|
||||||
heightMeasureMode === CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
availableHeight - marginColumn === cachedLayout.computedHeight) {
|
if (isWidthSame && isHeightValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
var isWidthValid =
|
||||||
if (cachedLayout.availableHeight === availableHeight &&
|
(cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED && widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && cachedLayout.computedWidth <= (availableWidth - marginRow)) ||
|
||||||
cachedLayout.heightMeasureMode === heightMeasureMode &&
|
(widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && cachedLayout.computedWidth == (availableWidth - marginRow));
|
||||||
widthMeasureMode === CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
availableWidth - marginRow === cachedLayout.computedWidth) {
|
if (isHeightSame && isWidthValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isHeightValid && isWidthValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (isTextNode) {
|
||||||
|
if (isWidthSame) {
|
||||||
|
if (heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightMeasureMode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cachedLayout.computedHeight < (availableHeight - marginColumn)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cachedLayout.computedHeight = availableHeight - marginColumn;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
if (widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED ||
|
||||||
|
(widthMeasureMode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cachedLayout.computedWidth <= (availableWidth - marginRow))) {
|
||||||
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1556,13 +1601,13 @@ var computeLayout = (function() {
|
|||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (layout.cachedLayout &&
|
if (layout.cachedLayout &&
|
||||||
canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
canUseCachedMeasurement(node.isTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
||||||
cachedResults = layout.cachedLayout;
|
cachedResults = layout.cachedLayout;
|
||||||
} else if (layout.cachedMeasurements) {
|
} else if (layout.cachedMeasurements) {
|
||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {
|
for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.isTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
||||||
cachedResults = layout.cachedMeasurements[i];
|
cachedResults = layout.cachedMeasurements[i];
|
||||||
break;
|
break;
|
||||||
|
2
dist/css-layout.min.js
vendored
2
dist/css-layout.min.js
vendored
File diff suppressed because one or more lines are too long
2
dist/css-layout.min.js.map
vendored
2
dist/css-layout.min.js.map
vendored
File diff suppressed because one or more lines are too long
87
src/Layout.c
87
src/Layout.c
@@ -1547,35 +1547,80 @@ static const char* getModeName(css_measure_mode_t mode, bool performLayout) {
|
|||||||
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
return performLayout? kLayoutModeNames[mode] : kMeasureModeNames[mode];
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool canUseCachedMeasurement(float availableWidth, float availableHeight,
|
static bool canUseCachedMeasurement(
|
||||||
float marginRow, float marginColumn,
|
bool is_text_node,
|
||||||
css_measure_mode_t widthMeasureMode, css_measure_mode_t heightMeasureMode,
|
float available_width,
|
||||||
css_cached_measurement_t cachedLayout) {
|
float available_height,
|
||||||
|
float margin_row,
|
||||||
|
float margin_column,
|
||||||
|
css_measure_mode_t width_measure_mode,
|
||||||
|
css_measure_mode_t height_measure_mode,
|
||||||
|
css_cached_measurement_t cached_layout) {
|
||||||
|
|
||||||
// Is it an exact match?
|
bool is_height_same =
|
||||||
if (eq(cachedLayout.available_width, availableWidth) &&
|
(cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
eq(cachedLayout.available_height, availableHeight) &&
|
(cached_layout.height_measure_mode == height_measure_mode && eq(cached_layout.available_height, available_height));
|
||||||
cachedLayout.width_measure_mode == widthMeasureMode &&
|
|
||||||
cachedLayout.height_measure_mode == heightMeasureMode) {
|
bool is_width_same =
|
||||||
|
(cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
|
(cached_layout.width_measure_mode == width_measure_mode && eq(cached_layout.available_width, available_width));
|
||||||
|
|
||||||
|
if (is_height_same && is_width_same) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
bool is_height_valid =
|
||||||
if (cachedLayout.width_measure_mode == widthMeasureMode &&
|
(cached_layout.height_measure_mode == CSS_MEASURE_MODE_UNDEFINED && height_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_height <= (available_height - margin_column)) ||
|
||||||
eq(cachedLayout.available_width, availableWidth) &&
|
(height_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_height, available_height - margin_column));
|
||||||
heightMeasureMode == CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
eq(availableHeight - marginColumn, cachedLayout.computed_height)) {
|
if (is_width_same && is_height_valid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
bool is_width_valid =
|
||||||
if (cachedLayout.height_measure_mode == heightMeasureMode &&
|
(cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED && width_measure_mode == CSS_MEASURE_MODE_AT_MOST && cached_layout.computed_width <= (available_width - margin_row)) ||
|
||||||
eq(cachedLayout.available_height, availableHeight) &&
|
(width_measure_mode == CSS_MEASURE_MODE_EXACTLY && eq(cached_layout.computed_width, available_width - margin_row));
|
||||||
widthMeasureMode == CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
eq(availableWidth - marginRow, cachedLayout.computed_width)) {
|
if (is_height_same && is_width_valid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (is_height_valid && is_width_valid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (is_text_node) {
|
||||||
|
if (is_width_same) {
|
||||||
|
if (height_measure_mode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (height_measure_mode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cached_layout.computed_height < (available_height - margin_column)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cached_layout.computed_height = available_height - margin_column;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cached_layout.width_measure_mode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
if (width_measure_mode == CSS_MEASURE_MODE_UNDEFINED ||
|
||||||
|
(width_measure_mode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cached_layout.computed_width <= (available_width - margin_row))) {
|
||||||
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1617,13 +1662,13 @@ bool layoutNodeInternal(css_node_t* node, float availableWidth, float availableH
|
|||||||
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
|
float marginAxisColumn = getMarginAxis(node, CSS_FLEX_DIRECTION_COLUMN);
|
||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
|
widthMeasureMode, heightMeasureMode, layout->cached_layout)) {
|
||||||
cachedResults = &layout->cached_layout;
|
cachedResults = &layout->cached_layout;
|
||||||
} else {
|
} else {
|
||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (int i = 0; i < layout->next_cached_measurements_index; i++) {
|
for (int i = 0; i < layout->next_cached_measurements_index; i++) {
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node->is_text_node && node->is_text_node(node->context), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout->cached_measurements[i])) {
|
widthMeasureMode, heightMeasureMode, layout->cached_measurements[i])) {
|
||||||
cachedResults = &layout->cached_measurements[i];
|
cachedResults = &layout->cached_measurements[i];
|
||||||
break;
|
break;
|
||||||
|
@@ -176,6 +176,7 @@ struct css_node {
|
|||||||
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);
|
||||||
|
bool (*is_text_node)(void *context);
|
||||||
void *context;
|
void *context;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -1462,35 +1462,80 @@ var computeLayout = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function canUseCachedMeasurement(availableWidth, availableHeight,
|
function canUseCachedMeasurement(
|
||||||
marginRow, marginColumn,
|
isTextNode,
|
||||||
widthMeasureMode, heightMeasureMode,
|
availableWidth,
|
||||||
cachedLayout) {
|
availableHeight,
|
||||||
|
marginRow,
|
||||||
|
marginColumn,
|
||||||
|
widthMeasureMode,
|
||||||
|
heightMeasureMode,
|
||||||
|
cachedLayout) {
|
||||||
|
|
||||||
// Is it an exact match?
|
var isHeightSame =
|
||||||
if (cachedLayout.availableWidth === availableWidth &&
|
(cachedLayout.heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED && heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
cachedLayout.availableHeight === availableHeight &&
|
(cachedLayout.heightMeasureMode == heightMeasureMode && cachedLayout.availableHeight == availableHeight);
|
||||||
cachedLayout.widthMeasureMode === widthMeasureMode &&
|
|
||||||
cachedLayout.heightMeasureMode === heightMeasureMode) {
|
var isWidthSame =
|
||||||
|
(cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED && widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED) ||
|
||||||
|
(cachedLayout.widthMeasureMode == widthMeasureMode && cachedLayout.availableWidth == availableWidth);
|
||||||
|
|
||||||
|
if (isHeightSame && isWidthSame) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
var isHeightValid =
|
||||||
if (cachedLayout.availableWidth === availableWidth &&
|
(cachedLayout.heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED && heightMeasureMode == CSS_MEASURE_MODE_AT_MOST && cachedLayout.computedHeight <= (availableHeight - marginColumn)) ||
|
||||||
cachedLayout.widthMeasureMode === widthMeasureMode &&
|
(heightMeasureMode == CSS_MEASURE_MODE_EXACTLY && cachedLayout.computedHeight == (availableHeight - marginColumn));
|
||||||
heightMeasureMode === CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
availableHeight - marginColumn === cachedLayout.computedHeight) {
|
if (isWidthSame && isHeightValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
var isWidthValid =
|
||||||
if (cachedLayout.availableHeight === availableHeight &&
|
(cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED && widthMeasureMode == CSS_MEASURE_MODE_AT_MOST && cachedLayout.computedWidth <= (availableWidth - marginRow)) ||
|
||||||
cachedLayout.heightMeasureMode === heightMeasureMode &&
|
(widthMeasureMode == CSS_MEASURE_MODE_EXACTLY && cachedLayout.computedWidth == (availableWidth - marginRow));
|
||||||
widthMeasureMode === CSS_MEASURE_MODE_EXACTLY &&
|
|
||||||
availableWidth - marginRow === cachedLayout.computedWidth) {
|
if (isHeightSame && isWidthValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isHeightValid && isWidthValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (isTextNode) {
|
||||||
|
if (isWidthSame) {
|
||||||
|
if (heightMeasureMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightMeasureMode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cachedLayout.computedHeight < (availableHeight - marginColumn)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cachedLayout.computedHeight = availableHeight - marginColumn;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedLayout.widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED) {
|
||||||
|
if (widthMeasureMode == CSS_MEASURE_MODE_UNDEFINED ||
|
||||||
|
(widthMeasureMode == CSS_MEASURE_MODE_AT_MOST &&
|
||||||
|
cachedLayout.computedWidth <= (availableWidth - marginRow))) {
|
||||||
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1537,13 +1582,13 @@ var computeLayout = (function() {
|
|||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (layout.cachedLayout &&
|
if (layout.cachedLayout &&
|
||||||
canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
canUseCachedMeasurement(node.isTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
||||||
cachedResults = layout.cachedLayout;
|
cachedResults = layout.cachedLayout;
|
||||||
} else if (layout.cachedMeasurements) {
|
} else if (layout.cachedMeasurements) {
|
||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {
|
for (i = 0, len = layout.cachedMeasurements.length; i < len; i++) {
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.isTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
||||||
cachedResults = layout.cachedMeasurements[i];
|
cachedResults = layout.cachedMeasurements[i];
|
||||||
break;
|
break;
|
||||||
|
@@ -65,6 +65,7 @@ namespace Facebook.CSSLayout
|
|||||||
[Nullable] CSSNode mParent;
|
[Nullable] CSSNode mParent;
|
||||||
[Nullable] MeasureFunction mMeasureFunction = null;
|
[Nullable] MeasureFunction mMeasureFunction = null;
|
||||||
LayoutState mLayoutState = LayoutState.DIRTY;
|
LayoutState mLayoutState = LayoutState.DIRTY;
|
||||||
|
bool mIsTextNode = false;
|
||||||
|
|
||||||
public int ChildCount
|
public int ChildCount
|
||||||
{
|
{
|
||||||
@@ -134,6 +135,12 @@ namespace Facebook.CSSLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsTextNode
|
||||||
|
{
|
||||||
|
get { return mIsTextNode; }
|
||||||
|
set { mIsTextNode = value; }
|
||||||
|
}
|
||||||
|
|
||||||
public bool IsMeasureDefined
|
public bool IsMeasureDefined
|
||||||
{
|
{
|
||||||
get { return mMeasureFunction != null; }
|
get { return mMeasureFunction != null; }
|
||||||
@@ -518,6 +525,11 @@ namespace Facebook.CSSLayout
|
|||||||
node.MeasureFunction = measureFunction;
|
node.MeasureFunction = measureFunction;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setIsTextNode(this CSSNode node, bool isTextNode)
|
||||||
|
{
|
||||||
|
node.IsTextNode = isTextNode;
|
||||||
|
}
|
||||||
|
|
||||||
public static void calculateLayout(this CSSNode node)
|
public static void calculateLayout(this CSSNode node)
|
||||||
{
|
{
|
||||||
node.CalculateLayout();
|
node.CalculateLayout();
|
||||||
|
@@ -282,39 +282,82 @@ namespace Facebook.CSSLayout
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
internal static boolean canUseCachedMeasurement(float availableWidth, float availableHeight,
|
internal static boolean canUseCachedMeasurement(
|
||||||
float marginRow, float marginColumn,
|
boolean isTextNode,
|
||||||
CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode,
|
float availableWidth,
|
||||||
|
float availableHeight,
|
||||||
|
float marginRow,
|
||||||
|
float marginColumn,
|
||||||
|
CSSMeasureMode widthMeasureMode,
|
||||||
|
CSSMeasureMode heightMeasureMode,
|
||||||
CSSCachedMeasurement cachedLayout)
|
CSSCachedMeasurement cachedLayout)
|
||||||
{
|
{
|
||||||
// Is it an exact match?
|
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
|
boolean isHeightSame =
|
||||||
FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
|
(cachedLayout.heightMeasureMode == CSSMeasureMode.Undefined && heightMeasureMode == CSSMeasureMode.Undefined) ||
|
||||||
cachedLayout.widthMeasureMode == widthMeasureMode &&
|
(cachedLayout.heightMeasureMode == heightMeasureMode && FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight));
|
||||||
cachedLayout.heightMeasureMode == heightMeasureMode)
|
|
||||||
{
|
boolean isWidthSame =
|
||||||
|
(cachedLayout.widthMeasureMode == CSSMeasureMode.Undefined && widthMeasureMode == CSSMeasureMode.Undefined) ||
|
||||||
|
(cachedLayout.widthMeasureMode == widthMeasureMode && FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth));
|
||||||
|
|
||||||
|
if (isHeightSame && isWidthSame) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isHeightValid =
|
||||||
|
(cachedLayout.heightMeasureMode == CSSMeasureMode.Undefined && heightMeasureMode == CSSMeasureMode.AtMost && cachedLayout.computedHeight <= (availableHeight - marginColumn)) ||
|
||||||
|
(heightMeasureMode == CSSMeasureMode.Exactly && FloatUtil.floatsEqual(cachedLayout.computedHeight, availableHeight - marginColumn));
|
||||||
|
|
||||||
|
if (isWidthSame && isHeightValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boolean isWidthValid =
|
||||||
|
(cachedLayout.widthMeasureMode == CSSMeasureMode.Undefined && widthMeasureMode == CSSMeasureMode.AtMost && cachedLayout.computedWidth <= (availableWidth - marginRow)) ||
|
||||||
|
(widthMeasureMode == CSSMeasureMode.Exactly && FloatUtil.floatsEqual(cachedLayout.computedWidth, availableWidth - marginRow));
|
||||||
|
|
||||||
|
if (isHeightSame && isWidthValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isHeightValid && isWidthValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (isTextNode) {
|
||||||
|
if (isWidthSame) {
|
||||||
|
if (heightMeasureMode == CSSMeasureMode.Undefined) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightMeasureMode == CSSMeasureMode.AtMost &&
|
||||||
|
cachedLayout.computedHeight < (availableHeight - marginColumn)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cachedLayout.computedHeight = availableHeight - marginColumn;
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
if (cachedLayout.widthMeasureMode == CSSMeasureMode.Undefined) {
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
|
if (widthMeasureMode == CSSMeasureMode.Undefined ||
|
||||||
cachedLayout.widthMeasureMode == widthMeasureMode &&
|
(widthMeasureMode == CSSMeasureMode.AtMost &&
|
||||||
heightMeasureMode == CSSMeasureMode.Exactly &&
|
cachedLayout.computedWidth <= (availableWidth - marginRow))) {
|
||||||
FloatUtil.floatsEqual(availableHeight - marginColumn, cachedLayout.computedHeight))
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
{
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
return true;
|
return true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
return false;
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
|
|
||||||
cachedLayout.heightMeasureMode == heightMeasureMode &&
|
|
||||||
widthMeasureMode == CSSMeasureMode.Exactly &&
|
|
||||||
FloatUtil.floatsEqual(availableWidth - marginRow, cachedLayout.computedWidth))
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//
|
//
|
||||||
@@ -359,7 +402,7 @@ namespace Facebook.CSSLayout
|
|||||||
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
|
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
|
||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.IsTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedLayout))
|
widthMeasureMode, heightMeasureMode, layout.cachedLayout))
|
||||||
{
|
{
|
||||||
cachedResults = layout.cachedLayout;
|
cachedResults = layout.cachedLayout;
|
||||||
@@ -369,7 +412,7 @@ namespace Facebook.CSSLayout
|
|||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (int i = 0; i < layout.nextCachedMeasurementsIndex; i++)
|
for (int i = 0; i < layout.nextCachedMeasurementsIndex; i++)
|
||||||
{
|
{
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.IsTextNode, availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i]))
|
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i]))
|
||||||
{
|
{
|
||||||
cachedResults = layout.cachedMeasurements[i];
|
cachedResults = layout.cachedMeasurements[i];
|
||||||
|
@@ -69,6 +69,7 @@ public class CSSNode {
|
|||||||
private @Nullable CSSNode mParent;
|
private @Nullable CSSNode mParent;
|
||||||
private @Nullable MeasureFunction mMeasureFunction = null;
|
private @Nullable MeasureFunction mMeasureFunction = null;
|
||||||
private LayoutState mLayoutState = LayoutState.DIRTY;
|
private LayoutState mLayoutState = LayoutState.DIRTY;
|
||||||
|
private boolean mIsTextNode = false;
|
||||||
|
|
||||||
public int getChildCount() {
|
public int getChildCount() {
|
||||||
return mChildren == null ? 0 : mChildren.size();
|
return mChildren == null ? 0 : mChildren.size();
|
||||||
@@ -124,6 +125,14 @@ public class CSSNode {
|
|||||||
return mMeasureFunction != null;
|
return mMeasureFunction != null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void setIsTextNode(boolean isTextNode) {
|
||||||
|
mIsTextNode = isTextNode;
|
||||||
|
}
|
||||||
|
|
||||||
|
public boolean isTextNode() {
|
||||||
|
return mIsTextNode;
|
||||||
|
}
|
||||||
|
|
||||||
/*package*/ MeasureOutput measure(MeasureOutput measureOutput, float width, CSSMeasureMode widthMode, float height, CSSMeasureMode heightMode) {
|
/*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!");
|
||||||
|
@@ -250,34 +250,80 @@ public class LayoutEngine {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*package*/ static boolean canUseCachedMeasurement(float availableWidth, float availableHeight,
|
/*package*/ static boolean canUseCachedMeasurement(
|
||||||
float marginRow, float marginColumn,
|
boolean isTextNode,
|
||||||
CSSMeasureMode widthMeasureMode, CSSMeasureMode heightMeasureMode,
|
float availableWidth,
|
||||||
|
float availableHeight,
|
||||||
|
float marginRow,
|
||||||
|
float marginColumn,
|
||||||
|
CSSMeasureMode widthMeasureMode,
|
||||||
|
CSSMeasureMode heightMeasureMode,
|
||||||
CSSCachedMeasurement cachedLayout) {
|
CSSCachedMeasurement cachedLayout) {
|
||||||
// Is it an exact match?
|
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
|
boolean isHeightSame =
|
||||||
FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
|
(cachedLayout.heightMeasureMode == CSSMeasureMode.UNDEFINED && heightMeasureMode == CSSMeasureMode.UNDEFINED) ||
|
||||||
cachedLayout.widthMeasureMode == widthMeasureMode &&
|
(cachedLayout.heightMeasureMode == heightMeasureMode && FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight));
|
||||||
cachedLayout.heightMeasureMode == heightMeasureMode) {
|
|
||||||
|
boolean isWidthSame =
|
||||||
|
(cachedLayout.widthMeasureMode == CSSMeasureMode.UNDEFINED && widthMeasureMode == CSSMeasureMode.UNDEFINED) ||
|
||||||
|
(cachedLayout.widthMeasureMode == widthMeasureMode && FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth));
|
||||||
|
|
||||||
|
if (isHeightSame && isWidthSame) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the width is an exact match, try a fuzzy match on the height.
|
boolean isHeightValid =
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableWidth, availableWidth) &&
|
(cachedLayout.heightMeasureMode == CSSMeasureMode.UNDEFINED && heightMeasureMode == CSSMeasureMode.AT_MOST && cachedLayout.computedHeight <= (availableHeight - marginColumn)) ||
|
||||||
cachedLayout.widthMeasureMode == widthMeasureMode &&
|
(heightMeasureMode == CSSMeasureMode.EXACTLY && FloatUtil.floatsEqual(cachedLayout.computedHeight, availableHeight - marginColumn));
|
||||||
heightMeasureMode == CSSMeasureMode.EXACTLY &&
|
|
||||||
FloatUtil.floatsEqual(availableHeight - marginColumn, cachedLayout.computedHeight)) {
|
if (isWidthSame && isHeightValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the height is an exact match, try a fuzzy match on the width.
|
boolean isWidthValid =
|
||||||
if (FloatUtil.floatsEqual(cachedLayout.availableHeight, availableHeight) &&
|
(cachedLayout.widthMeasureMode == CSSMeasureMode.UNDEFINED && widthMeasureMode == CSSMeasureMode.AT_MOST && cachedLayout.computedWidth <= (availableWidth - marginRow)) ||
|
||||||
cachedLayout.heightMeasureMode == heightMeasureMode &&
|
(widthMeasureMode == CSSMeasureMode.EXACTLY && FloatUtil.floatsEqual(cachedLayout.computedWidth, availableWidth - marginRow));
|
||||||
widthMeasureMode == CSSMeasureMode.EXACTLY &&
|
|
||||||
FloatUtil.floatsEqual(availableWidth - marginRow, cachedLayout.computedWidth)) {
|
if (isHeightSame && isWidthValid) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (isHeightValid && isWidthValid) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// We know this to be text so we can apply some more specialized heuristics.
|
||||||
|
if (isTextNode) {
|
||||||
|
if (isWidthSame) {
|
||||||
|
if (heightMeasureMode == CSSMeasureMode.UNDEFINED) {
|
||||||
|
// Width is the same and height is not restricted. Re-use cahced value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (heightMeasureMode == CSSMeasureMode.AT_MOST &&
|
||||||
|
cachedLayout.computedHeight < (availableHeight - marginColumn)) {
|
||||||
|
// Width is the same and height restriction is greater than the cached height. Re-use cached value.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Width is the same but height restriction imposes smaller height than previously measured.
|
||||||
|
// Update the cached value to respect the new height restriction.
|
||||||
|
cachedLayout.computedHeight = availableHeight - marginColumn;
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cachedLayout.widthMeasureMode == CSSMeasureMode.UNDEFINED) {
|
||||||
|
if (widthMeasureMode == CSSMeasureMode.UNDEFINED ||
|
||||||
|
(widthMeasureMode == CSSMeasureMode.AT_MOST &&
|
||||||
|
cachedLayout.computedWidth <= (availableWidth - marginRow))) {
|
||||||
|
// Previsouly this text was measured with no width restriction, if width is now restricted
|
||||||
|
// but to a larger value than the previsouly measured width we can re-use the measurement
|
||||||
|
// as we know it will fit.
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -329,13 +375,13 @@ public class LayoutEngine {
|
|||||||
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
|
node.style.margin.getWithFallback(trailingSpacing[CSS_FLEX_DIRECTION_COLUMN], trailing[CSS_FLEX_DIRECTION_COLUMN]);
|
||||||
|
|
||||||
// First, try to use the layout cache.
|
// First, try to use the layout cache.
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.isTextNode(), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
widthMeasureMode, heightMeasureMode, layout.cachedLayout)) {
|
||||||
cachedResults = layout.cachedLayout;
|
cachedResults = layout.cachedLayout;
|
||||||
} else {
|
} else {
|
||||||
// Try to use the measurement cache.
|
// Try to use the measurement cache.
|
||||||
for (int i = 0; i < layout.nextCachedMeasurementsIndex; i++) {
|
for (int i = 0; i < layout.nextCachedMeasurementsIndex; i++) {
|
||||||
if (canUseCachedMeasurement(availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
if (canUseCachedMeasurement(node.isTextNode(), availableWidth, availableHeight, marginAxisRow, marginAxisColumn,
|
||||||
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
widthMeasureMode, heightMeasureMode, layout.cachedMeasurements[i])) {
|
||||||
cachedResults = layout.cachedMeasurements[i];
|
cachedResults = layout.cachedMeasurements[i];
|
||||||
break;
|
break;
|
||||||
|
Reference in New Issue
Block a user