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
This commit is contained in:
James Bursa 2006-10-08 22:46:25 +00:00
parent d2469b806c
commit a785bc25f7
6 changed files with 59 additions and 199 deletions

View File

@ -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);
}
}

View File

@ -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);

View File

@ -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) {

View File

@ -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)

View File

@ -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;
}

View File

@ -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,6 +216,12 @@ bool layout_block_context(struct box *block, struct content *content)
* correct handling of floats.
*/
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) {
@ -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)
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;
}
}