Improve min/max-height handling on replaced elements.

This commit is contained in:
Michael Drake 2014-01-04 14:00:16 +00:00
parent 845923adfc
commit 8b253a2151

View File

@ -75,7 +75,8 @@ static struct box* layout_next_margin_block(struct box *box, struct box *block,
int viewport_height, int *max_pos_margin, int *max_neg_margin); int viewport_height, int *max_pos_margin, int *max_neg_margin);
static bool layout_block_object(struct box *block); static bool layout_block_object(struct box *block);
static void layout_get_object_dimensions(struct box *box, static void layout_get_object_dimensions(struct box *box,
int *width, int *height, int min_width, int max_width); int *width, int *height, int min_width, int max_width,
int min_height, int max_height);
static void layout_block_find_dimensions(int available_width, static void layout_block_find_dimensions(int available_width,
int viewport_height, int lm, int rm, int viewport_height, int lm, int rm,
struct box *box); struct box *box);
@ -88,7 +89,8 @@ static void layout_float_find_dimensions(int available_width,
static void layout_find_dimensions(int available_width, int viewport_height, static void layout_find_dimensions(int available_width, int viewport_height,
struct box *box, const css_computed_style *style, struct box *box, const css_computed_style *style,
int *width, int *height, int *max_width, int *min_width, int *width, int *height, int *max_width, int *min_width,
int margin[4], int padding[4], struct box_border border[4]); int *max_height, int *min_height, int margin[4], int padding[4],
struct box_border border[4]);
static void layout_tweak_form_dimensions(struct box *box, bool percentage, static void layout_tweak_form_dimensions(struct box *box, bool percentage,
int available_width, bool setwidth, int *dimension); int available_width, bool setwidth, int *dimension);
static int layout_clear(struct box *fl, enum css_clear_e clear); static int layout_clear(struct box *fl, enum css_clear_e clear);
@ -229,7 +231,8 @@ bool layout_block_context(struct box *block, int viewport_height,
if (!layout_block_object(block)) if (!layout_block_object(block))
return false; return false;
layout_get_object_dimensions(block, &temp_width, layout_get_object_dimensions(block, &temp_width,
&block->height, INT_MIN, INT_MAX); &block->height, INT_MIN, INT_MAX,
INT_MIN, INT_MAX);
return true; return true;
} else if (block->flags & REPLACE_DIM) { } else if (block->flags & REPLACE_DIM) {
return true; return true;
@ -903,8 +906,8 @@ struct box* layout_next_margin_block(struct box *box, struct box *block,
viewport_height, box, viewport_height, box,
box->style, box->style,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
box->margin, box->padding, NULL, NULL, box->margin,
box->border); box->padding, box->border);
/* Apply top margin */ /* Apply top margin */
if (*max_pos_margin < box->margin[TOP]) if (*max_pos_margin < box->margin[TOP])
@ -977,8 +980,8 @@ struct box* layout_next_margin_block(struct box *box, struct box *block,
viewport_height, box, viewport_height, box,
box->style, box->style,
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
box->margin, box->padding, NULL, NULL, box->margin,
box->border); box->padding, box->border);
} }
} }
} }
@ -1029,12 +1032,14 @@ bool layout_block_object(struct box *block)
* \param height Height value in px or AUTO. If AUTO, updated to value in px. * \param height Height value in px or AUTO. If AUTO, updated to value in px.
* \param min_width Box's min width, as given by layout_find_dimensions. * \param min_width Box's min width, as given by layout_find_dimensions.
* \param max_width Box's max width, as given by layout_find_dimensions. * \param max_width Box's max width, as given by layout_find_dimensions.
* \param min_height Box's min height, as given by layout_find_dimensions.
* \param max_height Box's max height, as given by layout_find_dimensions.
* *
* See CSS 2.1 sections 10.3 and 10.6. * See CSS 2.1 sections 10.3 and 10.6.
*/ */
void layout_get_object_dimensions(struct box *box, int *width, int *height, void layout_get_object_dimensions(struct box *box, int *width, int *height,
int min_width, int max_width) int min_width, int max_width, int min_height, int max_height)
{ {
assert(box->object != NULL); assert(box->object != NULL);
assert(width != NULL && height != NULL); assert(width != NULL && height != NULL);
@ -1050,6 +1055,7 @@ void layout_get_object_dimensions(struct box *box, int *width, int *height,
*width = intrinsic_width; *width = intrinsic_width;
*height = intrinsic_height; *height = intrinsic_height;
/* Deal with min/max-width first */
if (min_width > 0 && min_width > *width) { if (min_width > 0 && min_width > *width) {
*width = min_width; *width = min_width;
scaled = true; scaled = true;
@ -1060,10 +1066,28 @@ void layout_get_object_dimensions(struct box *box, int *width, int *height,
} }
if (scaled && (intrinsic_width != 0)) { if (scaled && (intrinsic_width != 0)) {
/* Update height */
*height = (*width * intrinsic_height) / *height = (*width * intrinsic_height) /
intrinsic_width; intrinsic_width;
} }
scaled = false;
/* Deal with min/max-height */
if (min_height > 0 && min_height > *height) {
*height = min_height;
scaled = true;
}
if (max_height >= 0 && max_height < *height) {
*height = max_height;
scaled = true;
}
if (scaled && (intrinsic_height != 0)) {
/* Update width */
*width = (*height * intrinsic_width) /
intrinsic_height;
}
} else if (*width == AUTO) { } else if (*width == AUTO) {
/* Have given height; width is calculated from the given height /* Have given height; width is calculated from the given height
* and ratio of intrinsic dimensions */ * and ratio of intrinsic dimensions */
@ -1116,7 +1140,7 @@ void layout_block_find_dimensions(int available_width, int viewport_height,
int lm, int rm, struct box *box) int lm, int rm, struct box *box)
{ {
int width, max_width, min_width; int width, max_width, min_width;
int height; int height, max_height, min_height;
int *margin = box->margin; int *margin = box->margin;
int *padding = box->padding; int *padding = box->padding;
struct box_border *border = box->border; struct box_border *border = box->border;
@ -1124,13 +1148,13 @@ void layout_block_find_dimensions(int available_width, int viewport_height,
layout_find_dimensions(available_width, viewport_height, box, style, layout_find_dimensions(available_width, viewport_height, box, style,
&width, &height, &max_width, &min_width, &width, &height, &max_width, &min_width,
margin, padding, border); &max_height, &min_height, margin, padding, border);
if (box->object && !(box->flags & REPLACE_DIM) && if (box->object && !(box->flags & REPLACE_DIM) &&
content_get_type(box->object) != CONTENT_HTML) { content_get_type(box->object) != CONTENT_HTML) {
/* block-level replaced element, see 10.3.4 and 10.6.2 */ /* block-level replaced element, see 10.3.4 and 10.6.2 */
layout_get_object_dimensions(box, &width, &height, layout_get_object_dimensions(box, &width, &height,
min_width, max_width); min_width, max_width, min_height, max_height);
} }
box->width = layout_solve_width(box, available_width, width, lm, rm, box->width = layout_solve_width(box, available_width, width, lm, rm,
@ -1430,7 +1454,7 @@ int layout_solve_width(struct box *box, int available_width, int width,
void layout_float_find_dimensions(int available_width, void layout_float_find_dimensions(int available_width,
const css_computed_style *style, struct box *box) const css_computed_style *style, struct box *box)
{ {
int width, height, max_width, min_width; int width, height, max_width, min_width, max_height, min_height;
int *margin = box->margin; int *margin = box->margin;
int *padding = box->padding; int *padding = box->padding;
struct box_border *border = box->border; struct box_border *border = box->border;
@ -1440,7 +1464,8 @@ void layout_float_find_dimensions(int available_width,
SCROLLBAR_WIDTH : 0; SCROLLBAR_WIDTH : 0;
layout_find_dimensions(available_width, -1, box, style, &width, &height, layout_find_dimensions(available_width, -1, box, style, &width, &height,
&max_width, &min_width, margin, padding, border); &max_width, &min_width, &max_height, &min_height,
margin, padding, border);
if (margin[LEFT] == AUTO) if (margin[LEFT] == AUTO)
margin[LEFT] = 0; margin[LEFT] = 0;
@ -1457,7 +1482,7 @@ void layout_float_find_dimensions(int available_width,
/* Floating replaced element, with intrinsic width or height. /* Floating replaced element, with intrinsic width or height.
* See 10.3.6 and 10.6.2 */ * See 10.3.6 and 10.6.2 */
layout_get_object_dimensions(box, &width, &height, layout_get_object_dimensions(box, &width, &height,
min_width, max_width); min_width, max_width, min_height, max_height);
} else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX || } else if (box->gadget && (box->gadget->type == GADGET_TEXTBOX ||
box->gadget->type == GADGET_PASSWORD || box->gadget->type == GADGET_PASSWORD ||
box->gadget->type == GADGET_FILE || box->gadget->type == GADGET_FILE ||
@ -1555,6 +1580,8 @@ void layout_float_find_dimensions(int available_width,
* \param height updated to height, may be NULL * \param height updated to height, may be NULL
* \param max_width updated to max-width, may be NULL * \param max_width updated to max-width, may be NULL
* \param min_width updated to min-width, may be NULL * \param min_width updated to min-width, may be NULL
* \param max_height updated to max-height, may be NULL
* \param min_height updated to min-height, may be NULL
* \param margin[4] filled with margins, may be NULL * \param margin[4] filled with margins, may be NULL
* \param padding[4] filled with paddings, may be NULL * \param padding[4] filled with paddings, may be NULL
* \param border[4] filled with border widths, may be NULL * \param border[4] filled with border widths, may be NULL
@ -1563,7 +1590,8 @@ void layout_float_find_dimensions(int available_width,
void layout_find_dimensions(int available_width, int viewport_height, void layout_find_dimensions(int available_width, int viewport_height,
struct box *box, const css_computed_style *style, struct box *box, const css_computed_style *style,
int *width, int *height, int *max_width, int *min_width, int *width, int *height, int *max_width, int *min_width,
int margin[4], int padding[4], struct box_border border[4]) int *max_height, int *min_height, int margin[4], int padding[4],
struct box_border border[4])
{ {
struct box *containing_block = NULL; struct box *containing_block = NULL;
unsigned int i; unsigned int i;
@ -1750,6 +1778,48 @@ void layout_find_dimensions(int available_width, int viewport_height,
} }
} }
if (max_height) {
enum css_max_height_e type;
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
type = css_computed_max_height(style, &value, &unit);
if (type == CSS_MAX_HEIGHT_SET) {
if (unit == CSS_UNIT_PCT) {
/* TODO: handle percentage */
*max_height = -1;
} else {
*max_height = FIXTOINT(nscss_len2px(value, unit,
style));
}
} else {
/* Inadmissible */
*max_height = -1;
}
}
if (min_height) {
enum css_min_height_e type;
css_fixed value = 0;
css_unit unit = CSS_UNIT_PX;
type = css_computed_min_height(style, &value, &unit);
if (type == CSS_MIN_HEIGHT_SET) {
if (unit == CSS_UNIT_PCT) {
/* TODO: handle percentage */
*min_height = 0;
} else {
*min_height = FIXTOINT(nscss_len2px(value, unit,
style));
}
} else {
/* Inadmissible */
*min_height = 0;
}
}
for (i = 0; i != 4; i++) { for (i = 0; i != 4; i++) {
if (margin) { if (margin) {
enum css_margin_e type = CSS_MARGIN_AUTO; enum css_margin_e type = CSS_MARGIN_AUTO;
@ -2297,7 +2367,7 @@ bool layout_line(struct box *first, int *width, int *y,
#endif #endif
for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) { for (x = 0, b = first; x <= x1 - x0 && b != 0; b = b->next) {
int min_width, max_width; int min_width, max_width, min_height, max_height;
assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK || assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK ||
b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_LEFT ||
@ -2347,7 +2417,8 @@ bool layout_line(struct box *first, int *width, int *y,
if (b->type == BOX_INLINE) { if (b->type == BOX_INLINE) {
/* calculate borders, margins, and padding */ /* calculate borders, margins, and padding */
layout_find_dimensions(*width, -1, b, b->style, 0, 0, layout_find_dimensions(*width, -1, b, b->style, 0, 0,
0, 0, b->margin, b->padding, b->border); 0, 0, 0, 0, b->margin, b->padding,
b->border);
for (i = 0; i != 4; i++) for (i = 0; i != 4; i++)
if (b->margin[i] == AUTO) if (b->margin[i] == AUTO)
b->margin[i] = 0; b->margin[i] = 0;
@ -2454,11 +2525,12 @@ bool layout_line(struct box *first, int *width, int *y,
layout_find_dimensions(*width, -1, b, b->style, layout_find_dimensions(*width, -1, b, b->style,
&b->width, &b->height, &max_width, &min_width, &b->width, &b->height, &max_width, &min_width,
NULL, NULL, NULL); &max_height, &min_height, NULL, NULL, NULL);
if (b->object && !(b->flags & REPLACE_DIM)) { if (b->object && !(b->flags & REPLACE_DIM)) {
layout_get_object_dimensions(b, &b->width, &b->height, layout_get_object_dimensions(b, &b->width, &b->height,
min_width, max_width); min_width, max_width,
min_height, max_height);
} else if (b->flags & IFRAME) { } else if (b->flags & IFRAME) {
/* TODO: should we look at the content dimensions? */ /* TODO: should we look at the content dimensions? */
if (b->width == AUTO) if (b->width == AUTO)
@ -3185,6 +3257,7 @@ struct box *layout_minmax_line(struct box *first,
int temp_height = height; int temp_height = height;
layout_get_object_dimensions(b, layout_get_object_dimensions(b,
&width, &temp_height, &width, &temp_height,
INT_MIN, INT_MAX,
INT_MIN, INT_MAX); INT_MIN, INT_MAX);
} }
@ -3412,7 +3485,7 @@ bool layout_table(struct box *table, int available_width,
/* find margins, paddings, and borders for table and cells */ /* find margins, paddings, and borders for table and cells */
layout_find_dimensions(available_width, -1, table, style, 0, 0, 0, 0, layout_find_dimensions(available_width, -1, table, style, 0, 0, 0, 0,
table->margin, table->padding, table->border); 0, 0, table->margin, table->padding, table->border);
for (row_group = table->children; row_group; for (row_group = table->children; row_group;
row_group = row_group->next) { row_group = row_group->next) {
for (row = row_group->children; row; row = row->next) { for (row = row_group->children; row; row = row->next) {
@ -3420,8 +3493,8 @@ bool layout_table(struct box *table, int available_width,
assert(c->style); assert(c->style);
table_used_border_for_cell(c); table_used_border_for_cell(c);
layout_find_dimensions(available_width, -1, layout_find_dimensions(available_width, -1,
c, c->style, 0, 0, 0, 0, 0, c, c->style, 0, 0, 0, 0, 0, 0,
c->padding, c->border); 0, c->padding, c->border);
if (css_computed_overflow(c->style) == if (css_computed_overflow(c->style) ==
CSS_OVERFLOW_SCROLL || CSS_OVERFLOW_SCROLL ||
css_computed_overflow(c->style) == css_computed_overflow(c->style) ==
@ -4518,7 +4591,7 @@ bool layout_absolute(struct box *box, struct box *containing_block,
box->float_container = containing_block; box->float_container = containing_block;
layout_find_dimensions(available_width, -1, box, box->style, layout_find_dimensions(available_width, -1, box, box->style,
&width, &height, &max_width, &min_width, &width, &height, &max_width, &min_width,
margin, padding, border); 0, 0, margin, padding, border);
box->float_container = NULL; box->float_container = NULL;
/* 10.3.7 */ /* 10.3.7 */