From a785bc25f7d34a7121739219ccdc063e4ac8ba33 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 8 Oct 2006 22:46:25 +0000 Subject: Modify implementation of absolute positioning to support "static positions". Absolutely positioned boxes are now in their original place in the tree instead of linked from absolute_children. svn path=/trunk/netsurf/; revision=2984 --- render/box.c | 46 --------------- render/box.h | 5 -- render/box_construct.c | 13 ----- render/box_normalise.c | 38 ------------- render/html_redraw.c | 8 --- render/layout.c | 148 ++++++++++++++++++++----------------------------- 6 files changed, 59 insertions(+), 199 deletions(-) (limited to 'render') diff --git a/render/box.c b/render/box.c index f31b636ec..506d94215 100644 --- a/render/box.c +++ b/render/box.c @@ -84,7 +84,6 @@ struct box * box_create(struct css_style *style, box->inline_end = NULL; box->float_children = NULL; box->next_float = NULL; - box->absolute_children = NULL; box->col = NULL; box->gadget = NULL; box->usemap = NULL; @@ -122,30 +121,6 @@ void box_add_child(struct box *parent, struct box *child) } -/** - * Add an absolutely positioned child to a box tree node. - * - * \param parent box giving birth - * \param child box to link as last child of parent - */ - -void box_add_absolute_child(struct box *parent, struct box *child) -{ - assert(parent); - assert(child); - - if (parent->absolute_children != 0) { /* has children already */ - child->next = parent->absolute_children; - parent->absolute_children->prev = child; - } else { /* this is the first child */ - child->next = 0; - } - - parent->absolute_children = child; - child->parent = parent; -} - - /** * Insert a new box as a sibling to a box in a tree. * @@ -212,11 +187,6 @@ void box_free(struct box *box) box_free(child); } - for (child = box->absolute_children; child; child = next) { - next = child->next; - box_free(child); - } - /* last this box */ box_free_box(box); } @@ -331,15 +301,6 @@ struct box *box_at_point(struct box *box, int x, int y, } } - /* consider absolute children first */ - for (child = box->absolute_children; child; child = child->next) { - if (box_contains_point(child, x - bx, y - by)) { - *box_x = bx + child->x - child->scroll_x; - *box_y = by + child->y - child->scroll_y; - return child; - } - } - /* consider floats second, since they will often overlap other boxes */ for (child = box->float_children; child; child = child->next_float) { if (box_contains_point(child, x - bx, y - by)) { @@ -596,11 +557,4 @@ void box_dump(struct box *box, unsigned int depth) for (c = box->fallback; c; c = c->next) box_dump(c, depth + 1); } - if (box->absolute_children) { - for (i = 0; i != depth; i++) - fprintf(stderr, " "); - fprintf(stderr, "absolute_children:\n"); - for (c = box->absolute_children; c; c = c->next) - box_dump(c, depth + 1); - } } diff --git a/render/box.h b/render/box.h index 90d011486..a0c43ef1e 100644 --- a/render/box.h +++ b/render/box.h @@ -193,10 +193,6 @@ struct box { /** Next sibling float box. */ struct box *next_float; - /** First absolutely positioned child box, or 0. Absolutely positioned - * boxes are linked by next / prev and do not appear under children. */ - struct box *absolute_children; - struct column *col; /**< Array of table column data for TABLE only. */ /** Form control data, or 0 if not a form control. */ @@ -264,7 +260,6 @@ struct box * box_create(struct css_style *style, char *href, const char *target, char *title, char *id, void *context); void box_add_child(struct box *parent, struct box *child); -void box_add_absolute_child(struct box *parent, struct box *child); void box_insert_sibling(struct box *box, struct box *new_box); void box_unlink_and_free(struct box *box); void box_free(struct box *box); diff --git a/render/box_construct.c b/render/box_construct.c index 025781ce5..bfaf104b9 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -174,7 +174,6 @@ bool xml_to_box(xmlNode *n, struct content *c) root.parent = NULL; root.float_children = NULL; root.next_float = NULL; - root.absolute_children = NULL; c->data.html.style = talloc_memdup(c, &css_base_style, sizeof css_base_style); @@ -415,18 +414,6 @@ bool box_construct_element(xmlNode *n, struct content *content, containing_block_c, href, target, title)) return false; - } else if ((style->position == CSS_POSITION_ABSOLUTE || - style->position == CSS_POSITION_FIXED) && - containing_block) { - /* absolutely positioned */ - box_add_absolute_child(containing_block, box); - inline_container_c = 0; - for (c = n->children; convert_children && c; c = c->next) - if (!convert_xml_to_box(c, content, style, box, - &inline_container_c, - containing_block_c, - href, target, title)) - return false; } else { if (style->float_ == CSS_FLOAT_LEFT || style->float_ == CSS_FLOAT_RIGHT) { diff --git a/render/box_normalise.c b/render/box_normalise.c index e9d482d8c..e241f447f 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -45,7 +45,6 @@ struct columns { }; -static bool box_normalise_absolute_children(struct box *box, struct content *c); static bool box_normalise_table(struct box *table, struct content *c); static void box_normalise_table_spans(struct box *table); static bool box_normalise_table_row_group(struct box *row_group, @@ -164,34 +163,6 @@ bool box_normalise_block(struct box *block, struct content *c) } } - if (!box_normalise_absolute_children(block, c)) - return false; - - return true; -} - - -bool box_normalise_absolute_children(struct box *box, struct content *c) -{ - struct box *child; - struct box *next_child; - - for (child = box->absolute_children; child != 0; child = next_child) { - next_child = child->next; /* child may be destroyed */ - switch (child->type) { - case BOX_BLOCK: - if (!box_normalise_block(child, c)) - return false; - break; - case BOX_TABLE: - if (!box_normalise_table(child, c)) - return false; - break; - default: - assert(0); - } - } - return true; } @@ -300,9 +271,6 @@ bool box_normalise_table(struct box *table, struct content * c) table->rows = col_info.num_rows; free(col_info.spans); - if (!box_normalise_absolute_children(table, c)) - return false; - if (table->children == 0) { LOG(("table->children == 0, removing")); if (table->prev == 0) @@ -467,9 +435,6 @@ bool box_normalise_table_row_group(struct box *row_group, } } - if (!box_normalise_absolute_children(row_group, c)) - return false; - if (row_group->children == 0) { LOG(("row_group->children == 0, removing")); if (row_group->prev == 0) @@ -583,9 +548,6 @@ bool box_normalise_table_row(struct box *row, col_info->current_column = 0; col_info->extra = false; - if (!box_normalise_absolute_children(row, c)) - return false; - if (row->children == 0) { LOG(("row->children == 0, removing")); if (row->prev == 0) diff --git a/render/html_redraw.c b/render/html_redraw.c index f70e9eefa..9cf8a2927 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -390,14 +390,6 @@ bool html_redraw_box_children(struct box *box, scale, current_background_color)) return false; - for (c = box->absolute_children; c; c = c->next) - if (!html_redraw_box(c, - x_parent + box->x - box->scroll_x, - y_parent + box->y - box->scroll_y, - clip_x0, clip_y0, clip_x1, clip_y1, - scale, current_background_color)) - return false; - return true; } 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; - } } -- cgit v1.2.3