summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--render/box.c46
-rw-r--r--render/box.h5
-rw-r--r--render/box_construct.c13
-rw-r--r--render/box_normalise.c38
-rw-r--r--render/html_redraw.c8
-rw-r--r--render/layout.c148
6 files changed, 59 insertions, 199 deletions
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;
@@ -123,30 +122,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.
*
* \param box box already in 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;
- }
}