Fix viewport height handling not to obliterate calculation

of root element height from children's dimensions.
Improve handling of percentage heights on HTML and BODY.

svn path=/trunk/netsurf/; revision=7429
This commit is contained in:
Michael Drake 2009-05-07 16:22:38 +00:00
parent 40d27d1152
commit c2ecbebd3d

View File

@ -56,11 +56,13 @@
#define AUTO INT_MIN
static bool layout_block_context(struct box *block, struct content *content);
static bool layout_block_context(struct box *block, int viewport_height,
struct content *content);
static void layout_minmax_block(struct box *block,
const struct font_functions *font_func);
static bool layout_block_object(struct box *block);
static void layout_block_find_dimensions(int available_width, int lm, int rm,
static void layout_block_find_dimensions(int available_width,
int viewport_height, int lm, int rm,
struct box *box);
static bool layout_apply_minmax_height(struct box *box, struct box *container);
static void layout_block_add_scrollbar(struct box *box, int which);
@ -69,7 +71,7 @@ static int layout_solve_width(int available_width, int width, int lm, int rm,
int margin[4], int padding[4], int border[4]);
static void layout_float_find_dimensions(int available_width,
struct css_style *style, struct box *box);
static void layout_find_dimensions(int available_width,
static void layout_find_dimensions(int available_width, int viewport_height,
struct box *box, struct css_style *style,
int *width, int *height, int *max_width, int *min_width,
int margin[4], int padding[4], int border[4]);
@ -133,7 +135,7 @@ bool layout_document(struct content *content, int width, int height)
layout_minmax_block(doc, font_func);
layout_block_find_dimensions(width, 0, 0, doc);
layout_block_find_dimensions(width, height, 0, 0, doc);
doc->x = doc->margin[LEFT] + doc->border[LEFT];
doc->y = doc->margin[TOP] + doc->border[TOP];
width -= doc->margin[LEFT] + doc->border[LEFT] + doc->padding[LEFT] +
@ -142,10 +144,8 @@ bool layout_document(struct content *content, int width, int height)
if (width < 0)
width = 0;
doc->width = width;
if (doc->height == AUTO)
doc->height = height;
ret = layout_block_context(doc, content);
ret = layout_block_context(doc, height, content);
/* make <html> and <body> fill available height */
if (doc->y + doc->padding[TOP] + doc->height + doc->padding[BOTTOM] +
@ -177,15 +177,17 @@ bool layout_document(struct content *content, int width, int height)
/**
* Layout a block formatting context.
*
* \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
* \param content memory pool for any new boxes
* \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout
* \param viewport_height Height of viewport in pixels or -ve if unknown
* \param content Memory pool for any new boxes
* \return true on success, false on memory exhaustion
*
* This function carries out layout of a block and its children, as described
* in CSS 2.1 9.4.1.
*/
bool layout_block_context(struct box *block, struct content *content)
bool layout_block_context(struct box *block, int viewport_height,
struct content *content)
{
struct box *box;
int cx, cy; /**< current coordinates */
@ -317,8 +319,9 @@ bool layout_block_context(struct box *block, struct content *content)
(box->style->position == CSS_POSITION_ABSOLUTE||
box->style->position == CSS_POSITION_FIXED)) {
box->x = box->parent->padding[LEFT];
layout_find_dimensions(box->parent->width, box,
box->style, NULL, &(box->height), NULL,
layout_find_dimensions(box->parent->width,
viewport_height, box, box->style,
NULL, &(box->height), NULL,
NULL, NULL, NULL, NULL);
/* absolute positioned; this element will establish
* its own block context when it gets laid out later,
@ -334,8 +337,9 @@ bool layout_block_context(struct box *block, struct content *content)
/* Get top margin */
if (box->style) {
layout_find_dimensions(box->parent->width, box,
box->style, NULL, NULL, NULL, NULL,
layout_find_dimensions(box->parent->width,
viewport_height, box, box->style,
NULL, NULL, NULL, NULL,
box->margin, NULL, NULL);
}
@ -374,7 +378,7 @@ bool layout_block_context(struct box *block, struct content *content)
x1;
}
layout_block_find_dimensions(box->parent->width,
lm, rm, box);
viewport_height, lm, rm, box);
layout_block_add_scrollbar(box, RIGHT);
layout_block_add_scrollbar(box, BOTTOM);
} else if (box->type == BOX_TABLE) {
@ -434,7 +438,7 @@ bool layout_block_context(struct box *block, struct content *content)
cy += max_pos_margin - max_neg_margin;
box->y += max_pos_margin - max_neg_margin;
layout_block_context(box, content);
layout_block_context(box, viewport_height, content);
if (box->type == BOX_BLOCK || box->object)
cy += box->padding[TOP];
@ -760,6 +764,7 @@ bool layout_block_object(struct box *block)
* element.
*
* \param available_width Max width available in pixels
* \param viewport_height Height of viewport in pixels or -ve if unknown
* \param lm min left margin required to avoid floats in px.
* zero if not applicable
* \param rm min right margin required to avoid floats in px.
@ -770,8 +775,8 @@ bool layout_block_object(struct box *block)
* See CSS 2.1 10.3.3, 10.3.4, 10.6.2, and 10.6.3.
*/
void layout_block_find_dimensions(int available_width, int lm, int rm,
struct box *box)
void layout_block_find_dimensions(int available_width, int viewport_height,
int lm, int rm, struct box *box)
{
int width, max_width, min_width;
int height;
@ -780,8 +785,9 @@ void layout_block_find_dimensions(int available_width, int lm, int rm,
int *border = box->border;
struct css_style *style = box->style;
layout_find_dimensions(available_width, box, style, &width, &height,
&max_width, &min_width, margin, padding, border);
layout_find_dimensions(available_width, viewport_height, box, style,
&width, &height, &max_width, &min_width,
margin, padding, border);
if (box->object && box->object->type != CONTENT_HTML) {
/* block-level replaced element, see 10.3.4 and 10.6.2 */
@ -1054,7 +1060,7 @@ void layout_float_find_dimensions(int available_width,
style->overflow == CSS_OVERFLOW_AUTO) ?
SCROLLBAR_WIDTH : 0;
layout_find_dimensions(available_width, box, style, &width, &height,
layout_find_dimensions(available_width, -1, box, style, &width, &height,
&max_width, &min_width, margin, padding, border);
if (margin[LEFT] == AUTO)
@ -1143,6 +1149,7 @@ void layout_float_find_dimensions(int available_width,
* Calculate width, height, and thickness of margins, paddings, and borders.
*
* \param available_width width of containing block
* \param viewport_height height of viewport in pixels or -ve if unknown
* \param box current box
* \param style style giving width, height, margins, paddings,
* and borders
@ -1155,7 +1162,7 @@ void layout_float_find_dimensions(int available_width,
* \param border[4] filled with border widths, may be NULL
*/
void layout_find_dimensions(int available_width,
void layout_find_dimensions(int available_width, int viewport_height,
struct box *box, struct css_style *style,
int *width, int *height, int *max_width, int *min_width,
int margin[4], int padding[4], int border[4])
@ -1233,6 +1240,12 @@ void layout_find_dimensions(int available_width,
* height. (CSS 2.1 Section 10.5) */
*height = style->height.value.percent *
containing_block->height / 100;
} else if ((!box->parent || !box->parent->parent) &&
viewport_height >= 0) {
/* If root element or it's child
* (HTML or BODY) */
*height = style->height.value.percent *
viewport_height / 100;
} else {
/* precentage height not permissible
* treat height as auto */
@ -1708,7 +1721,7 @@ bool layout_line(struct box *first, int *width, int *y,
if (b->type == BOX_INLINE) {
/* calculate borders, margins, and padding */
layout_find_dimensions(*width, b, b->style, 0, 0,
layout_find_dimensions(*width, -1, b, b->style, 0, 0,
0, 0, b->margin, b->padding, b->border);
for (i = 0; i != 4; i++)
if (b->margin[i] == AUTO)
@ -2503,7 +2516,7 @@ bool layout_float(struct box *b, int width, struct content *content)
if (b->margin[BOTTOM] == AUTO)
b->margin[BOTTOM] = 0;
} else
return layout_block_context(b, content);
return layout_block_context(b, -1, content);
return true;
}
@ -2609,14 +2622,14 @@ bool layout_table(struct box *table, int available_width,
memcpy(col, table->col, sizeof(col[0]) * columns);
/* find margins, paddings, and borders for table and cells */
layout_find_dimensions(available_width, table, style, 0, 0, 0, 0,
layout_find_dimensions(available_width, -1, table, style, 0, 0, 0, 0,
table->margin, table->padding, table->border);
for (row_group = table->children; row_group;
row_group = row_group->next) {
for (row = row_group->children; row; row = row->next) {
for (c = row->children; c; c = c->next) {
assert(c->style);
layout_find_dimensions(available_width,
layout_find_dimensions(available_width, -1,
c, c->style, 0, 0, 0, 0, 0,
c->padding, c->border);
if (c->style->overflow ==
@ -2861,7 +2874,7 @@ bool layout_table(struct box *table, int available_width,
c->float_children = 0;
c->height = AUTO;
if (!layout_block_context(c, content)) {
if (!layout_block_context(c, -1, content)) {
free(col);
free(excess_y);
free(row_span);
@ -3559,7 +3572,7 @@ bool layout_absolute(struct box *box, struct box *containing_block,
* containing block box member. This is unused for absolutely positioned
* boxes because a box can't be floated and absolutely positioned. */
box->float_container = containing_block;
layout_find_dimensions(available_width, box, box->style,
layout_find_dimensions(available_width, -1, box, box->style,
&width, &height, &max_width, &min_width,
margin, padding, border);
box->float_container = NULL;
@ -3739,7 +3752,7 @@ bool layout_absolute(struct box *box, struct box *containing_block,
if (box->type == BOX_BLOCK || box->type == BOX_INLINE_BLOCK ||
box->object) {
if (!layout_block_context(box, content))
if (!layout_block_context(box, -1, content))
return false;
} else if (box->type == BOX_TABLE) {
/* \todo layout_table considers margins etc. again */