summaryrefslogtreecommitdiff
path: root/render/layout.c
diff options
context:
space:
mode:
Diffstat (limited to 'render/layout.c')
-rw-r--r--render/layout.c205
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