diff options
author | John Mark Bell <jmb@netsurf-browser.org> | 2006-11-04 19:53:22 +0000 |
---|---|---|
committer | John Mark Bell <jmb@netsurf-browser.org> | 2006-11-04 19:53:22 +0000 |
commit | 7bd710a71c3233bc44ec66350a9c8d2b7a29c41c (patch) | |
tree | 2ff2e9e69383b87c1333cfb21252ccc5d38b5444 /render/layout.c | |
parent | 2d4276ee41f51e3b897539e716968907e9c75f70 (diff) | |
download | netsurf-7bd710a71c3233bc44ec66350a9c8d2b7a29c41c.tar.gz netsurf-7bd710a71c3233bc44ec66350a9c8d2b7a29c41c.tar.bz2 |
Initial work for display: list-item support
svn path=/trunk/netsurf/; revision=3028
Diffstat (limited to 'render/layout.c')
-rw-r--r-- | render/layout.c | 205 |
1 files changed, 199 insertions, 6 deletions
diff --git a/render/layout.c b/render/layout.c index 58693e254..2822c5239 100644 --- a/render/layout.c +++ b/render/layout.c @@ -48,6 +48,7 @@ static void layout_minmax_block(struct box *block); static bool layout_block_object(struct box *block); static void layout_block_find_dimensions(int available_width, struct box *box); +static void layout_list_find_dimensions(int available_width, struct box *box); static int layout_solve_width(int available_width, int width, int margin[4], int padding[4], int border[4]); static void layout_float_find_dimensions(int available_width, @@ -59,6 +60,9 @@ static void layout_find_dimensions(int available_width, static int layout_clear(struct box *fl, css_clear clear); static void find_sides(struct box *fl, int y0, int y1, int *x0, int *x1, struct box **left, struct box **right); +static void layout_minmax_list(struct box *box); +static void layout_minmax_list_item(struct box *box); +static bool layout_list(struct box *box, struct content *content); static void layout_minmax_inline_container(struct box *inline_container); static int line_height(struct css_style *style); static bool layout_line(struct box *first, int *width, int *y, @@ -149,7 +153,7 @@ bool layout_document(struct content *content, int width, int height) /** * Layout a block formatting context. * - * \param block BLOCK, INLINE_BLOCK, or TABLE_CELL to layout + * \param block BLOCK, INLINE_BLOCK, TABLE_CELL or LIST_PRINCIPAL to layout * \param content memory pool for any new boxes * \return true on success, false on memory exhaustion * @@ -168,7 +172,8 @@ bool layout_block_context(struct box *block, struct content *content) assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK || - block->type == BOX_TABLE_CELL); + block->type == BOX_TABLE_CELL || + block->type == BOX_LIST_PRINCIPAL); gui_multitask(); @@ -210,7 +215,8 @@ bool layout_block_context(struct box *block, struct content *content) * to each in the order shown. */ while (box) { assert(box->type == BOX_BLOCK || box->type == BOX_TABLE || - box->type == BOX_INLINE_CONTAINER); + box->type == BOX_INLINE_CONTAINER || + box->type == BOX_LIST); assert(margin_box); /* Tables are laid out before being positioned, because the @@ -235,7 +241,8 @@ bool layout_block_context(struct box *block, struct content *content) return false; layout_solve_width(box->parent->width, box->width, box->margin, box->padding, box->border); - } + } else if (box->type == BOX_LIST) + layout_list_find_dimensions(box->parent->width, box); /* Position box: horizontal. */ box->x = box->parent->padding[LEFT] + box->margin[LEFT] + @@ -308,6 +315,9 @@ bool layout_block_context(struct box *block, struct content *content) cx = x0; box->y += y - cy; cy = y; + } else if (box->type == BOX_LIST) { + if (!layout_list(box, content)) + return false; } /* Advance to next box. */ @@ -386,7 +396,7 @@ bool layout_block_context(struct box *block, struct content *content) /** * Calculate minimum and maximum width of a block. * - * \param block box of type BLOCK, INLINE_BLOCK, or TABLE_CELL + * \param block box of type BLOCK, INLINE_BLOCK, TABLE_CELL, or LIST_PRINCIPAL * \post block->min_width and block->max_width filled in, * 0 <= block->min_width <= block->max_width */ @@ -400,7 +410,8 @@ void layout_minmax_block(struct box *block) assert(block->type == BOX_BLOCK || block->type == BOX_INLINE_BLOCK || - block->type == BOX_TABLE_CELL); + block->type == BOX_TABLE_CELL || + block->type == BOX_LIST_PRINCIPAL); /* check if the widths have already been calculated */ if (block->max_width != UNKNOWN_MAX_WIDTH) @@ -427,6 +438,9 @@ void layout_minmax_block(struct box *block) case BOX_TABLE: layout_minmax_table(child); break; + case BOX_LIST: + layout_minmax_list(child); + break; default: assert(0); } @@ -563,6 +577,64 @@ void layout_block_find_dimensions(int available_width, struct box *box) /** + * Compute dimensions of box, margins, paddings, and borders for a list. + * + * Similar to layout_block_find_dimensions() + */ + +void layout_list_find_dimensions(int available_width, struct box *box) +{ + int width, height; + int *margin = box->margin; + int *padding = box->padding; + int *border = box->border; + struct css_style *style = box->style; + struct box *c; + + layout_find_dimensions(available_width, style, + &width, &height, margin, padding, border); + + for (c = box->children; c; c = c->next) { + struct box *marker, *principal; + + marker = c->children; + principal = marker->next; + + /** \todo handle marker */ + marker->width = marker->height = 0; + + layout_block_find_dimensions(available_width, principal); + + if (width < principal->x + principal->width + + principal->padding[RIGHT] + + principal->border[RIGHT] + + principal->margin[RIGHT]) + width = principal->x + principal->width + + principal->padding[RIGHT] + + principal->border[RIGHT] + + principal->margin[RIGHT]; + + if (height < principal->y + principal->height + + principal->padding[BOTTOM] + + principal->border[BOTTOM] + + principal->margin[BOTTOM]) + height = principal->y + principal->height + + principal->padding[BOTTOM] + + principal->border[BOTTOM] + + principal->margin[BOTTOM]; + } + + box->width = layout_solve_width(available_width, width, margin, + padding, border); + box->height = height; + + if (margin[TOP] == AUTO) + margin[TOP] = 0; + if (margin[BOTTOM] == AUTO) + margin[BOTTOM] = 0; +} + +/** * Solve the width constraint as given in CSS 2.1 section 10.3.3. */ @@ -818,6 +890,127 @@ void find_sides(struct box *fl, int y0, int y1, /** + * Calculate minimum and maximum widths of a list + */ + +void layout_minmax_list(struct box *box) +{ + int min = 0, max = 0; + struct box *c; + + assert(box->type == BOX_LIST); + + /* check if we've already calculated the width */ + if (box->max_width != UNKNOWN_MAX_WIDTH) + return; + + for (c = box->children; c; c = c->next) { + layout_minmax_list_item(c); + if (min < c->min_width) + min = c->min_width; + if (max < c->max_width) + max = c->max_width; + } + + box->min_width = min; + box->max_width = max; +} + + +/** + * Calculate minimum and maximum widths of a list item + */ + +void layout_minmax_list_item(struct box *box) +{ + struct box *marker, *principal; + + assert(box->type == BOX_LIST_ITEM); + + /* check if we've already calculated the width */ + if (box->max_width != UNKNOWN_MAX_WIDTH) + return; + + marker = box->children; + principal = marker->next; + + layout_minmax_block(principal); + + /** \todo what on earth are we expected to do with the marker? + * AFAICS, none of Opera, Firefox nor Konqueror support + * display: list-item with list-style-position: outside + * In Opera/Firefox's case, they don't appear to bother to + * generate the marker box (probably following the "optional" + * wording of the spec - 12.5). Konqueror turns it into + * list-style-position: inside. */ + marker->min_width = marker->max_width = 0; + + box->min_width = principal->min_width + marker->min_width; + box->max_width = principal->max_width + marker->max_width; +} + + +/** + * Layout a list + * + * \param box list box + * \param content memory pool for any new boxes + * \return true on success, false on memory exhaustion + */ + +bool layout_list(struct box *box, struct content *content) +{ + struct box *c; + int cy = 0; + + assert(box->type == BOX_LIST); + + for (c = box->children; c; c = c->next) { + struct box *marker, *principal; + + assert(c->type == BOX_LIST_ITEM); + + marker = c->children; + principal = marker->next; + + c->x = 0; + c->y = cy; + + /** \todo handle marker */ + marker->x = marker->y = 0; + + principal->x = 0; + principal->y = 0; + /* manipulate principal box's parent pointer so + * layout_block_context has a parent style to play with */ + /** \todo is this sane? */ + principal->parent = box; + layout_block_context(principal, content); + principal->parent = c; + + if (c->width == UNKNOWN_WIDTH) + c->width = principal->x + principal->width + + principal->padding[RIGHT] + + principal->border[RIGHT] + + principal->margin[RIGHT]; + +// if (c->height == AUTO) + c->height = principal->y + principal->height + + principal->padding[BOTTOM] + + principal->border[BOTTOM] + + principal->margin[BOTTOM]; + + cy += c->height; + } + +// if (box->height == AUTO) + box->height = cy - box->padding[TOP]; + + return true; +} + + +/** * Layout lines of text or inline boxes with floats. * * \param box inline container |