From 57b68bd9332f4c1636073ab8dd10a3ce50a173cf Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 5 Jun 2005 20:54:37 +0000 Subject: [project @ 2005-06-05 20:54:37 by bursa] More work on borders / padding / margins on inline elements. Add BOX_INLINE_END to hold the right border / padding / margin (left is in the BOX_INLINE). svn path=/import/netsurf/; revision=1742 --- render/box.c | 11 +++++++---- render/box.h | 11 +++++------ render/box_construct.c | 24 +++++++++++++++++------ render/box_normalise.c | 9 +++++---- render/html_redraw.c | 38 +++++++++++++++++++----------------- render/layout.c | 52 ++++++++++++++++++++++++++++++++++++++++---------- 6 files changed, 98 insertions(+), 47 deletions(-) diff --git a/render/box.c b/render/box.c index b53ae2b2b..c6e1702d5 100644 --- a/render/box.c +++ b/render/box.c @@ -76,7 +76,7 @@ struct box * box_create(struct css_style *style, box->last = NULL; box->parent = NULL; box->fallback = NULL; - box->end_inline_children = NULL; + box->inline_end = NULL; box->float_children = NULL; box->next_float = NULL; box->col = NULL; @@ -100,6 +100,9 @@ struct box * box_create(struct css_style *style, void box_add_child(struct box *parent, struct box *child) { + assert(parent); + assert(child); + if (parent->children != 0) { /* has children already */ parent->last->next = child; child->prev = parent->last; @@ -447,6 +450,7 @@ void box_dump(struct box *box, unsigned int depth) case BOX_BLOCK: fprintf(stderr, "BLOCK "); break; case BOX_INLINE_CONTAINER: fprintf(stderr, "INLINE_CONTAINER "); break; case BOX_INLINE: fprintf(stderr, "INLINE "); break; + case BOX_INLINE_END: fprintf(stderr, "INLINE_END "); break; case BOX_INLINE_BLOCK: fprintf(stderr, "INLINE_BLOCK "); break; case BOX_TABLE: fprintf(stderr, "TABLE [columns %i] ", box->columns); break; @@ -476,9 +480,8 @@ void box_dump(struct box *box, unsigned int depth) fprintf(stderr, " [%s]", box->title); if (box->id != 0) fprintf(stderr, " <%s>", box->id); - if (box->type == BOX_INLINE) - fprintf(stderr, " end_inline_children %p", - box->end_inline_children); + if (box->type == BOX_INLINE || box->type == BOX_INLINE_END) + fprintf(stderr, " inline_end %p", box->inline_end); if (box->float_children) fprintf(stderr, " float_children %p", box->float_children); if (box->next_float) diff --git a/render/box.h b/render/box.h index b377cd91a..f8fe0db90 100644 --- a/render/box.h +++ b/render/box.h @@ -91,7 +91,8 @@ typedef enum { BOX_TABLE, BOX_TABLE_ROW, BOX_TABLE_CELL, BOX_TABLE_ROW_GROUP, BOX_FLOAT_LEFT, BOX_FLOAT_RIGHT, - BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT + BOX_INLINE_BLOCK, BOX_BR, BOX_TEXT, + BOX_INLINE_END } box_type; /** Node in box tree. All dimensions are in pixels. */ @@ -166,11 +167,9 @@ struct box { struct box *last; /**< Last child box, or 0. */ struct box *parent; /**< Parent box, or 0. */ struct box *fallback; /**< Fallback children for object, or 0. */ - /** Sibling box after the last sibling box which was a child of this box - * in the document tree (the box after is used so that splitting boxes - * for line wrapping doesn't change it), or 0 if continues to end of - * inline container (only valid for INLINE boxes). */ - struct box *end_inline_children; + /** INLINE_END box corresponding to this INLINE box, or INLINE box + * corresponding to this INLINE_END box. */ + struct box *inline_end; /** First float child box, or 0. Float boxes are in the tree twice, in * this list for the block box which defines the area for floats, and diff --git a/render/box_construct.c b/render/box_construct.c index c3dc1e7bc..961fc7f17 100644 --- a/render/box_construct.c +++ b/render/box_construct.c @@ -263,6 +263,7 @@ bool box_construct_element(xmlNode *n, struct content *content, char *s; struct box *box = 0; struct box *inline_container_c; + struct box *inline_end; struct css_style *style = 0; struct element_entry *element; colour border_color; @@ -336,13 +337,24 @@ bool box_construct_element(xmlNode *n, struct content *content, if (box->type == BOX_INLINE || box->type == BOX_BR) { /* inline box: add to tree and recurse */ box_add_child(*inline_container, box); - for (c = n->children; convert_children && c; c = c->next) - if (!convert_xml_to_box(c, content, style, parent, - inline_container, href, title)) + if (convert_children) { + for (c = n->children; c; c = c->next) + if (!convert_xml_to_box(c, content, style, + parent, inline_container, + href, title)) + return false; + inline_end = box_create(style, href, title, id, + content); + if (!inline_end) return false; - /* corrected to next box (which doesn't exist yet) in - * box_normalise_inline_container() */ - box->end_inline_children = (*inline_container)->last; + inline_end->type = BOX_INLINE_END; + if (*inline_container) + box_add_child(*inline_container, inline_end); + else + box_add_child(box->parent, inline_end); + box->inline_end = inline_end; + inline_end->inline_end = box; + } } else if (box->type == BOX_INLINE_BLOCK) { /* inline block box: add to tree and recurse */ box_add_child(*inline_container, box); diff --git a/render/box_normalise.c b/render/box_normalise.c index c67fe285d..22971af8c 100644 --- a/render/box_normalise.c +++ b/render/box_normalise.c @@ -110,6 +110,7 @@ bool box_normalise_block(struct box *block, struct content *c) return false; break; case BOX_INLINE: + case BOX_INLINE_END: case BOX_INLINE_BLOCK: case BOX_FLOAT_LEFT: case BOX_FLOAT_RIGHT: @@ -246,6 +247,7 @@ bool box_normalise_table(struct box *table, struct content * c) } break; case BOX_INLINE: + case BOX_INLINE_END: case BOX_INLINE_BLOCK: case BOX_FLOAT_LEFT: case BOX_FLOAT_RIGHT: @@ -409,6 +411,7 @@ bool box_normalise_table_row_group(struct box *row_group, return false; break; case BOX_INLINE: + case BOX_INLINE_END: case BOX_INLINE_BLOCK: case BOX_FLOAT_LEFT: case BOX_FLOAT_RIGHT: @@ -506,6 +509,7 @@ bool box_normalise_table_row(struct box *row, return false; break; case BOX_INLINE: + case BOX_INLINE_END: case BOX_INLINE_BLOCK: case BOX_FLOAT_LEFT: case BOX_FLOAT_RIGHT: @@ -643,10 +647,7 @@ bool box_normalise_inline_container(struct box *cont, struct content * c) next_child = child->next; switch (child->type) { case BOX_INLINE: - /* correct end_inline_children to the box after the - * last inline child (see box_construct_element()) */ - child->end_inline_children = - child->end_inline_children->next; + case BOX_INLINE_END: case BOX_BR: case BOX_TEXT: /* ok */ diff --git a/render/html_redraw.c b/render/html_redraw.c index d6b255de2..cc946f17c 100644 --- a/render/html_redraw.c +++ b/render/html_redraw.c @@ -460,17 +460,22 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent, if (box->type == BOX_INLINE && !box->object && !box->gadget && !box->text) { - /* draw from next sibling to the sibling which has the same - * inline parent as this box (which must mean it was the next - * sibling of this inline in the HTML tree) */ - for (struct box *c = box->next; - c && c != box->end_inline_children; - c = c->next) { + int padding_height = (box->padding[TOP] + box->height + + box->padding[BOTTOM]) * scale; + for (struct box *c = box; c; c = c->next) { int x = (x_parent + c->x) * scale; - int y = (y_parent + c->y - box->padding[TOP]) * scale; - int padding_width = c->width * scale; - int padding_height = (box->padding[TOP] + c->height + - box->padding[BOTTOM]) * scale; + int y = y_parent + c->y; + int padding_width = c->width; + if (c != box) + y -= box->padding[TOP]; + if (c == box) + padding_width += box->padding[LEFT]; + if (!box->inline_end || c == box->inline_end) + padding_width += box->padding[RIGHT]; + if (scale != 1) { + y *= scale; + padding_width *= scale; + } int p[20] = { x, y, x - left, y - top, @@ -484,7 +489,7 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent, x, y, x - left, y - top }; - if (box->border[LEFT] && c == box->next) + if (box->border[LEFT] && c == box) html_redraw_border_plot(LEFT, p, box->style->border[LEFT].color, box->style->border[LEFT].style, @@ -501,12 +506,14 @@ bool html_redraw_borders(struct box *box, int x_parent, int y_parent, box->style->border[BOTTOM]. style, box->border[BOTTOM] * scale); - if (box->border[RIGHT] && (!c->next || - c->next == box->end_inline_children)) + if (box->border[RIGHT] && (!box->inline_end || + c == box->inline_end)) html_redraw_border_plot(RIGHT, p, box->style->border[RIGHT].color, box->style->border[RIGHT].style, box->border[RIGHT] * scale); + if (!box->inline_end || c == box->inline_end) + break; } } else { int x = (x_parent + box->x) * scale; @@ -1033,11 +1040,8 @@ bool html_redraw_text_decoration(struct box *box, bool html_redraw_text_decoration_inline(struct box *box, int x, int y, float scale, colour colour, float ratio) { - /* draw from next sibling to the sibling which has the same inline - * parent as this box (which must mean it was the next sibling of this - * inline in the HTML tree) */ for (struct box *c = box->next; - c && c != box->end_inline_children; + c && c != box->inline_end; c = c->next) { if (!plot.line((x + c->x) * scale, (y + c->y + c->height * ratio) * scale, diff --git a/render/layout.c b/render/layout.c index 90bdc8c3c..c8633d8f6 100644 --- a/render/layout.c +++ b/render/layout.c @@ -689,12 +689,13 @@ int line_height(struct css_style *style) /* take account of minimum font size option */ if ((font_len = css_len2px(&style->font_size.value.length, 0)) < - ((float)(option_font_min_size * 9.0 / 72.0))) - font_len = (float)(option_font_min_size * 9.0 / 72.0); + option_font_min_size * 9.0 / 72.0) + font_len = option_font_min_size * 9.0 / 72.0; switch (style->line_height.size) { case CSS_LINE_HEIGHT_LENGTH: - return (int)css_len2px(&style->line_height.value.length, style); + return css_len2px(&style->line_height.value.length, + style); case CSS_LINE_HEIGHT_ABSOLUTE: return style->line_height.value.absolute * font_len; @@ -762,7 +763,8 @@ bool layout_line(struct box *first, int width, int *y, assert(b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK || b->type == BOX_FLOAT_LEFT || b->type == BOX_FLOAT_RIGHT || - b->type == BOX_BR || b->type == BOX_TEXT); + b->type == BOX_BR || b->type == BOX_TEXT || + b->type == BOX_INLINE_END); x += space_after; @@ -785,7 +787,8 @@ bool layout_line(struct box *first, int width, int *y, if (b->type == BOX_BR) break; - if (b->type != BOX_INLINE && b->type != BOX_TEXT) + if (b->type != BOX_INLINE && b->type != BOX_TEXT && + b->type != BOX_INLINE_END) continue; if (b->type == BOX_INLINE) { @@ -795,6 +798,22 @@ bool layout_line(struct box *first, int width, int *y, for (i = 0; i != 4; i++) if (b->margin[i] == AUTO) b->margin[i] = 0; + if (b->inline_end) { + b->inline_end->margin[RIGHT] = b->margin[RIGHT]; + b->inline_end->padding[RIGHT] = + b->padding[RIGHT]; + b->inline_end->border[RIGHT] = + b->border[RIGHT]; + } + } else if (b->type == BOX_INLINE_END) { + b->width = 0; + if (b->space) { + /** \todo optimize out */ + nsfont_width(b->style, " ", 1, &space_after); + } else { + space_after = 0; + } + continue; } if (!b->object && !b->gadget) { @@ -919,26 +938,35 @@ bool layout_line(struct box *first, int width, int *y, /* pass 2: place boxes in line: loop body executed at least once */ for (x = x_previous = 0, b = first; x <= x1 - x0 && b; b = b->next) { if (b->type == BOX_INLINE || b->type == BOX_INLINE_BLOCK || - b->type == BOX_TEXT) { + b->type == BOX_TEXT || + b->type == BOX_INLINE_END) { assert(b->width != UNKNOWN_WIDTH); x_previous = x; x += space_after; b->x = x; - if (b->type == BOX_INLINE_BLOCK) { + if ((b->type == BOX_INLINE && !b->inline_end) || + b->type == BOX_INLINE_BLOCK) { b->x += b->margin[LEFT] + b->border[LEFT]; x = b->x + b->padding[LEFT] + b->width + b->padding[RIGHT] + b->border[RIGHT] + b->margin[RIGHT]; - } else + } else if (b->type == BOX_INLINE) { + b->x += b->margin[LEFT] + b->border[LEFT]; + x = b->x + b->padding[LEFT] + b->width; + } else if (b->type == BOX_INLINE_END) { + x += b->padding[RIGHT] + b->border[RIGHT] + + b->margin[RIGHT]; + } else { x += b->width; + } space_before = space_after; if (b->object) space_after = 0; - else if (b->text) { + else if (b->text || b->type == BOX_INLINE_END) { space_after = 0; if (b->space) /** \todo handle errors, optimize */ @@ -1129,7 +1157,8 @@ bool layout_line(struct box *first, int width, int *y, for (d = first; d != b; d = d->next) { if (d->type == BOX_INLINE || d->type == BOX_INLINE_BLOCK || - d->type == BOX_BR || d->type == BOX_TEXT) { + d->type == BOX_BR || d->type == BOX_TEXT || + d->type == BOX_INLINE_END) { d->x += x0; d->y = *y - d->padding[TOP]; } @@ -1827,6 +1856,9 @@ bool calculate_inline_container_widths(struct box *box) child->width = 0; break; + case BOX_INLINE_END: + break; + case BOX_INLINE_BLOCK: if (!calculate_block_widths(child, &min, &max, &line_max)) -- cgit v1.2.3