mirror of
https://github.com/netsurf-browser/netsurf
synced 2024-12-23 12:36:51 +03:00
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:
parent
d2469b806c
commit
a785bc25f7
46
render/box.c
46
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);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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) {
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
148
render/layout.c
148
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;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user