diff options
Diffstat (limited to 'render/layout.c')
-rw-r--r-- | render/layout.c | 148 |
1 files changed, 59 insertions, 89 deletions
diff --git a/render/layout.c b/render/layout.c index 3ac988656..dfd4ab321 100644 --- a/render/layout.c +++ b/render/layout.c @@ -158,7 +158,7 @@ bool layout_block_context(struct box *block, struct content *content) int cx, cy; /**< current coordinates */ int max_pos_margin = 0; int max_neg_margin = 0; - int y; + int y = 0; struct box *margin_box; assert(block->type == BOX_BLOCK || @@ -216,7 +216,13 @@ bool layout_block_context(struct box *block, struct content *content) * correct handling of floats. */ - if (box->type == BOX_BLOCK || box->object) + if (box->style->position == CSS_POSITION_ABSOLUTE || + box->style->position == CSS_POSITION_FIXED) { + box->x = box->parent->padding[LEFT]; + goto advance_to_next_box; + } + + if (box->type == BOX_BLOCK || box->object) layout_block_find_dimensions(box->parent->width, box); else if (box->type == BOX_TABLE) { if (!layout_table(box, box->parent->width, content)) @@ -314,23 +320,20 @@ bool layout_block_context(struct box *block, struct content *content) cy += box->padding[TOP]; if (box->type == BOX_BLOCK && box->height == AUTO) box->height = 0; - /* Absolutely positioned children. */ - if (!layout_absolute_children(box, content)) - return false; cy += box->height + box->padding[BOTTOM] + box->border[BOTTOM]; max_pos_margin = max_neg_margin = 0; if (max_pos_margin < box->margin[BOTTOM]) max_pos_margin = box->margin[BOTTOM]; else if (max_neg_margin < -box->margin[BOTTOM]) max_neg_margin = -box->margin[BOTTOM]; + cx -= box->x; + y = box->y + box->padding[TOP] + box->height + + box->padding[BOTTOM] + box->border[BOTTOM]; + advance_to_next_box: if (!box->next) { /* No more siblings: up to first ancestor with a sibling. */ do { - cx -= box->x; - y = box->y + box->padding[TOP] + box->height + - box->padding[BOTTOM] + - box->border[BOTTOM]; box = box->parent; if (box == block) break; @@ -339,22 +342,20 @@ bool layout_block_context(struct box *block, struct content *content) else cy += box->height - (y - box->padding[TOP]); - /* Absolutely positioned children. */ - if (!layout_absolute_children(box, content)) - return false; cy += box->padding[BOTTOM] + box->border[BOTTOM]; if (max_pos_margin < box->margin[BOTTOM]) max_pos_margin = box->margin[BOTTOM]; else if (max_neg_margin < -box->margin[BOTTOM]) max_neg_margin = -box->margin[BOTTOM]; + cx -= box->x; + y = box->y + box->padding[TOP] + box->height + + box->padding[BOTTOM] + + box->border[BOTTOM]; } while (box != block && !box->next); if (box == block) break; } - cx -= box->x; - y = box->y + box->padding[TOP] + box->height + - box->padding[BOTTOM] + box->border[BOTTOM]; /* To next sibling. */ box = box->next; box->y = y; @@ -440,21 +441,6 @@ void layout_minmax_block(struct box *block) assert(0); } - /* absolutely positioned children */ - for (child = block->absolute_children; child; child = child->next) { - switch (child->type) { - case BOX_BLOCK: - layout_minmax_block(child); - break; - case BOX_TABLE: - layout_minmax_table(child); - break; - default: - assert(0); - } - assert(child->max_width != UNKNOWN_MAX_WIDTH); - } - /* fixed width takes priority */ if (block->type != BOX_TABLE_CELL && block->style->width.width == CSS_WIDTH_LENGTH) @@ -2167,9 +2153,6 @@ bool layout_table(struct box *table, int available_width, table->width = table_width; table->height = table_height; - if (!layout_absolute_children(table, content)) - return false; - return true; } @@ -2422,39 +2405,6 @@ void layout_position_relative(struct box *root) } } } - - /* Absolute children */ - for (box = root->absolute_children; box; box = box->next) { - int x, y; - - if (box->type == BOX_TEXT) - continue; - - /* recurse first */ - layout_position_relative(box); - - /* Ignore things we're not interested in. */ - if (!box->style || (box->style && - box->style->position != CSS_POSITION_RELATIVE)) - continue; - - layout_compute_relative_offset(box, &x, &y); - - box->x += x; - box->y += y; - - /* Handle INLINEs - their "children" are in fact - * the sibling boxes between the INLINE and - * INLINE_END boxes */ - if (box->type == BOX_INLINE && box->inline_end) { - struct box *b; - for (b = box->next; b && b != box->inline_end; - b = b->next) { - b->x += x; - b->y += y; - } - } - } } @@ -2517,7 +2467,7 @@ void layout_compute_relative_offset(struct box *box, int *x, int *y) /** - * Layout absolutely positioned children of a box. + * Layout absolutely positioned boxes in a block context. * * \param block box to layout children of * \param content memory pool for any new boxes @@ -2529,9 +2479,17 @@ bool layout_absolute_children(struct box *block, { struct box *box; - for (box = block->absolute_children; box; box = box->next) - if (!layout_absolute(box, content)) - return false; + for (box = block->children; box; box = box->next) { + if ((box->type == BOX_BLOCK || box->type == BOX_TABLE) && + (box->style->position == CSS_POSITION_ABSOLUTE|| + box->style->position == CSS_POSITION_FIXED)) { + if (!layout_absolute(box, content)) + return false; + } else if (box->type == BOX_BLOCK) { + if (!layout_absolute_children(box, content)) + return false; + } + } return true; } @@ -2548,6 +2506,8 @@ bool layout_absolute_children(struct box *block, bool layout_absolute(struct box *box, struct content *content) { struct box *containing_block = box->parent; + int cx, cy; /* position of box parent relative to containing block */ + int static_left, static_top; /* static position */ int top, right, bottom, left; int width, height; int *margin = box->margin; @@ -2558,6 +2518,29 @@ bool layout_absolute(struct box *box, struct content *content) assert(box->type == BOX_BLOCK || box->type == BOX_TABLE); + /* Determine containing block and compute offset of box parent from + * the containing block. The absolute box is positioned relative to the + * containing block, but coordinates are relative to parent, so the + * offset is required to set the position. */ + cx = 0; + cy = 0; + for (containing_block = box->parent; + containing_block->parent; + containing_block = containing_block->parent) { + if (containing_block->style->position == CSS_POSITION_ABSOLUTE|| + containing_block->style->position == CSS_POSITION_RELATIVE|| + containing_block->style->position == CSS_POSITION_FIXED) + break; + cx += containing_block->x; + cy += containing_block->y; + } + + /* The static position is where the box would be if it was not + * absolutely positioned. The x and y are filled in by + * layout_block_context(). */ + static_left = cx + box->x; + static_top = cy + box->y; + if (containing_block->type == BOX_BLOCK || containing_block->type == BOX_INLINE_BLOCK || containing_block->type == BOX_TABLE_CELL) { @@ -2588,7 +2571,7 @@ bool layout_absolute(struct box *box, struct content *content) margin[LEFT] = 0; if (margin[RIGHT] == AUTO) margin[RIGHT] = 0; - left = 0; + left = static_left; width = min(max(box->min_width, available_width), box->max_width); width -= box->margin[LEFT] + box->border[LEFT] + @@ -2655,7 +2638,7 @@ bool layout_absolute(struct box *box, struct content *content) padding[RIGHT] - border[RIGHT] - margin[RIGHT] - right; } else if (left == AUTO && width != AUTO && right == AUTO) { - left = 0; + left = static_left; right = containing_block->width - left - margin[LEFT] - border[LEFT] - padding[LEFT] - @@ -2699,7 +2682,7 @@ bool layout_absolute(struct box *box, struct content *content) padding[RIGHT], border[RIGHT], margin[RIGHT], right, containing_block->width)); - box->x = left + margin[LEFT] + border[LEFT]; + box->x = left + margin[LEFT] + border[LEFT] - cx; if (containing_block->type == BOX_BLOCK || containing_block->type == BOX_INLINE_BLOCK || containing_block->type == BOX_TABLE_CELL) { @@ -2729,7 +2712,7 @@ bool layout_absolute(struct box *box, struct content *content) padding[BOTTOM], border[BOTTOM], margin[BOTTOM], bottom, containing_block->height)); if (top == AUTO && height == AUTO && bottom == AUTO) { - top = 0; + top = static_top; height = box->height; if (margin[TOP] == AUTO) margin[TOP] = 0; @@ -2783,7 +2766,7 @@ bool layout_absolute(struct box *box, struct content *content) padding[BOTTOM] - border[BOTTOM] - margin[BOTTOM] - bottom; } else if (top == AUTO && height != AUTO && bottom == AUTO) { - top = 0; + top = static_top; bottom = containing_block->height - top - margin[TOP] - border[TOP] - padding[TOP] - @@ -2821,7 +2804,7 @@ bool layout_absolute(struct box *box, struct content *content) padding[BOTTOM], border[BOTTOM], margin[BOTTOM], bottom, containing_block->height)); - box->y = top + margin[TOP] + border[TOP]; + box->y = top + margin[TOP] + border[TOP] - cy; if (containing_block->type == BOX_BLOCK || containing_block->type == BOX_INLINE_BLOCK || containing_block->type == BOX_TABLE_CELL) { @@ -3006,17 +2989,4 @@ void layout_calculate_descendant_bboxes(struct box *box) if (box->descendant_y1 < child->y + child->descendant_y1) box->descendant_y1 = child->y + child->descendant_y1; } - - for (child = box->absolute_children; child; child = child->next) { - layout_calculate_descendant_bboxes(child); - - if (child->x + child->descendant_x0 < box->descendant_x0) - box->descendant_x0 = child->x + child->descendant_x0; - if (box->descendant_x1 < child->x + child->descendant_x1) - box->descendant_x1 = child->x + child->descendant_x1; - if (child->y + child->descendant_y0 < box->descendant_y0) - box->descendant_y0 = child->y + child->descendant_y0; - if (box->descendant_y1 < child->y + child->descendant_y1) - box->descendant_y1 = child->y + child->descendant_y1; - } } |