From b5606d8f61d3da51302c7acd81ceaa1c236a04b6 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sun, 6 Jul 2003 21:10:12 +0000 Subject: [project @ 2003-07-06 21:10:12 by bursa] Implement rowspan. svn path=/import/netsurf/; revision=207 --- render/box.c | 62 +++++++++++++++++++++++++++++++++++++++++++------------- render/box.h | 1 + render/layout.c | 63 +++++++++++++++++++++++++++++++++++++++++++++------------ 3 files changed, 99 insertions(+), 27 deletions(-) (limited to 'render') diff --git a/render/box.c b/render/box.c index 253cb112b..a829d84f5 100644 --- a/render/box.c +++ b/render/box.c @@ -68,8 +68,10 @@ struct result box_input(xmlNode *n, struct status *status, static void add_option(xmlNode* n, struct gui_gadget* current_select, char *text); static void box_normalise_block(struct box *block); static void box_normalise_table(struct box *table); -static void box_normalise_table_row_group(struct box *row_group); -static void box_normalise_table_row(struct box *row); +void box_normalise_table_row_group(struct box *row_group, + unsigned int **row_span, unsigned int *table_columns); +void box_normalise_table_row(struct box *row, + unsigned int **row_span, unsigned int *table_columns); static void box_normalise_inline_container(struct box *cont); static void gadget_free(struct gui_gadget* g); static void box_free_box(struct box *box); @@ -139,6 +141,7 @@ struct box * box_create(struct css_style * style, box->text = 0; box->space = 0; box->length = 0; + box->start_column = 0; box->next = 0; box->prev = 0; box->children = 0; @@ -947,17 +950,21 @@ void box_normalise_table(struct box *table) struct box *next_child; struct box *row_group; struct css_style *style; + unsigned int *row_span = xcalloc(2, sizeof(row_span[0])); + unsigned int table_columns = 0; assert(table != 0); assert(table->type == BOX_TABLE); LOG(("table %p", table)); + row_span[0] = row_span[1] = 0; for (child = table->children; child != 0; child = next_child) { next_child = child->next; switch (child->type) { case BOX_TABLE_ROW_GROUP: /* ok */ - box_normalise_table_row_group(child); + box_normalise_table_row_group(child, &row_span, + &table_columns); break; case BOX_BLOCK: case BOX_INLINE_CONTAINER: @@ -965,7 +972,6 @@ void box_normalise_table(struct box *table) case BOX_TABLE_ROW: case BOX_TABLE_CELL: /* insert implied table row group */ -/* fprintf(stderr, "inserting implied table row group\n"); */ style = xcalloc(1, sizeof(struct css_style)); memcpy(style, table->style, sizeof(struct css_style)); css_cascade(style, &css_blank_style); @@ -988,7 +994,8 @@ void box_normalise_table(struct box *table) row_group->last->next = 0; row_group->next = next_child = child; row_group->parent = table; - box_normalise_table_row_group(row_group); + box_normalise_table_row_group(row_group, &row_span, + &table_columns); break; case BOX_INLINE: case BOX_FLOAT_LEFT: @@ -1003,6 +1010,9 @@ void box_normalise_table(struct box *table) } } + table->columns = table_columns; + xfree(row_span); + if (table->children == 0) { LOG(("table->children == 0, removing")); if (table->prev == 0) @@ -1018,7 +1028,8 @@ void box_normalise_table(struct box *table) } -void box_normalise_table_row_group(struct box *row_group) +void box_normalise_table_row_group(struct box *row_group, + unsigned int **row_span, unsigned int *table_columns) { struct box *child; struct box *next_child; @@ -1034,7 +1045,7 @@ void box_normalise_table_row_group(struct box *row_group) switch (child->type) { case BOX_TABLE_ROW: /* ok */ - box_normalise_table_row(child); + box_normalise_table_row(child, row_span, table_columns); break; case BOX_BLOCK: case BOX_INLINE_CONTAINER: @@ -1064,7 +1075,7 @@ void box_normalise_table_row_group(struct box *row_group) row->last->next = 0; row->next = next_child = child; row->parent = row_group; - box_normalise_table_row(row); + box_normalise_table_row(row, row_span, table_columns); break; case BOX_INLINE: case BOX_FLOAT_LEFT: @@ -1093,13 +1104,14 @@ void box_normalise_table_row_group(struct box *row_group) } -void box_normalise_table_row(struct box *row) +void box_normalise_table_row(struct box *row, + unsigned int **row_span, unsigned int *table_columns) { struct box *child; struct box *next_child; struct box *cell; struct css_style *style; - unsigned int columns = 0; + unsigned int columns = 0, i, min; assert(row != 0); assert(row->type == BOX_TABLE_ROW); @@ -1111,7 +1123,7 @@ void box_normalise_table_row(struct box *row) case BOX_TABLE_CELL: /* ok */ box_normalise_block(child); - columns += child->columns; + cell = child; break; case BOX_BLOCK: case BOX_INLINE_CONTAINER: @@ -1142,7 +1154,6 @@ void box_normalise_table_row(struct box *row) cell->next = next_child = child; cell->parent = row; box_normalise_block(cell); - columns++; break; case BOX_INLINE: case BOX_FLOAT_LEFT: @@ -1154,9 +1165,32 @@ void box_normalise_table_row(struct box *row) default: assert(0); } + + /* skip columns with cells spanning from above */ + while ((*row_span)[columns] != 0) { + (*row_span)[columns]--; + columns++; + } + cell->start_column = columns; + if (*table_columns < columns + cell->columns) { + *table_columns = columns + cell->columns; + *row_span = xrealloc(*row_span, + sizeof((*row_span)[0]) * + (*table_columns + 1)); + (*row_span)[*table_columns] = 0; /* sentinel */ + } + for (i = 0; i != cell->columns; i++) + (*row_span)[columns + i] = cell->rows - 1; + columns += cell->columns; } - if (row->parent->parent->columns < columns) - row->parent->parent->columns = columns; + + /* if all columns have a rowspan, shrink it to the lowest equivalent */ + min = (*row_span)[0]; + for (i = 1; i != *table_columns; i++) + if ((*row_span)[i] < min) + min = (*row_span)[i]; + for (i = 0; i != *table_columns; i++) + (*row_span)[i] -= min; if (row->children == 0) { LOG(("row->children == 0, removing")); diff --git a/render/box.h b/render/box.h index 6ee732567..5a16ecd9c 100644 --- a/render/box.h +++ b/render/box.h @@ -93,6 +93,7 @@ struct box { unsigned int length; unsigned int columns; unsigned int rows; + unsigned int start_column; /* start column of table cell */ struct box * next; struct box * prev; struct box * children; diff --git a/render/layout.c b/render/layout.c index f2bd019c9..4a8bcd386 100644 --- a/render/layout.c +++ b/render/layout.c @@ -590,9 +590,11 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, unsigned long table_height = 0; unsigned long *xs; /* array of column x positions */ unsigned int i; + unsigned int *row_span, *excess_y, min; struct box *c; struct box *row; struct box *row_group; + struct box **row_span_cell; assert(table->type == BOX_TABLE); assert(table->style != 0); @@ -661,20 +663,26 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, } xs = xcalloc(columns + 1, sizeof(*xs)); + row_span = xcalloc(columns, sizeof(row_span[0])); + excess_y = xcalloc(columns, sizeof(excess_y[0])); + row_span_cell = xcalloc(columns, sizeof(row_span_cell[0])); xs[0] = x = 0; - for (i = 0; i < table->columns; i++) { + for (i = 0; i != columns; i++) { x += table->col[i].width; xs[i + 1] = x; + row_span[i] = 0; + excess_y[i] = 0; + row_span_cell[i] = 0; } - + /* position cells */ for (row_group = table->children; row_group != 0; row_group = row_group->next) { unsigned long row_group_height = 0; for (row = row_group->children; row != 0; row = row->next) { unsigned long row_height = 0; - for (i = 0, c = row->children; c != 0; i += c->columns, c = c->next) { + for (c = row->children; c != 0; c = c->next) { assert(c->style != 0); - c->width = xs[i + c->columns] - xs[i]; + c->width = xs[c->start_column + c->columns] - xs[c->start_column]; c->float_children = 0; c->height = layout_block_children(c, c->width, c, 0, 0); if (c->style->height.height == CSS_HEIGHT_LENGTH) { @@ -685,12 +693,37 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, if (c->height < h) c->height = h; } - c->x = xs[i]; + c->x = xs[c->start_column]; c->y = 0; - if (c->height > row_height) row_height = c->height; + for (i = 0; i != c->columns; i++) { + row_span[c->start_column + i] = c->rows; + excess_y[c->start_column + i] = c->height; + row_span_cell[c->start_column + i] = 0; + } + row_span_cell[c->start_column] = c; + c->height = 0; + } + for (i = 0; i != columns; i++) + row_span[i]--; + /* if all columns have a row span, shrink it to the lowest equivalent */ + min = row_span[0]; + for (i = 1; i != columns; i++) + if (row_span[i] < min) + min = row_span[i]; + for (i = 0; i != columns; i++) + row_span[i] -= min; + /* row height is greatest excess of a cell which ends in this row */ + for (i = 0; i != columns; i++) + if (row_span[i] == 0 && row_height < excess_y[i]) + row_height = excess_y[i]; + for (i = 0; i != columns; i++) { + excess_y[i] -= row_height; + if (row_span_cell[i] != 0) + row_span_cell[i]->height += row_height; } - for (c = row->children; c != 0; c = c->next) - c->height = row_height; + + /*for (c = row->children; c != 0; c = c->next) + c->height = row_height;*/ row->x = 0; row->y = row_group_height; row->width = table_width; @@ -704,7 +737,10 @@ void layout_table(struct box * table, unsigned long width, struct box * cont, table_height += row_group_height; } - free(xs); + xfree(row_span_cell); + xfree(excess_y); + xfree(row_span); + xfree(xs); table->width = table_width; table->height = table_height; @@ -848,25 +884,26 @@ void calculate_table_widths(struct box *table) LOG(("table %p, columns %u", table, table->columns)); assert(table->children != 0 && table->children->children != 0); - for (pass = 1; pass != 3; pass++) { + for (pass = 0; pass != 2; pass++) { for (row_group = table->children; row_group != 0; row_group = row_group->next) { assert(row_group->type == BOX_TABLE_ROW_GROUP); for (row = row_group->children; row != 0; row = row->next) { assert(row->type == BOX_TABLE_ROW); - for (i = 0, cell = row->children; cell != 0; - i += cell->columns, cell = cell->next) { + for (cell = row->children; cell != 0; cell = cell->next) { unsigned int j, flexible_columns = 0; unsigned long min = 0, max = 0, extra; /* consider cells with colspan 1 in 1st pass, rest * in 2nd pass */ - if (pass != cell->columns) + if ((pass == 0 && cell->columns != 1) || + (pass == 1 && cell->columns == 1)) continue; assert(cell->type == BOX_TABLE_CELL); assert(cell->style != 0); calculate_widths(cell); + i = cell->start_column; /* find min, max width so far of spanned columns */ for (j = 0; j != cell->columns; j++) { -- cgit v1.2.3