summaryrefslogtreecommitdiff
path: root/render
diff options
context:
space:
mode:
authorJames Bursa <james@netsurf-browser.org>2003-07-06 21:10:12 +0000
committerJames Bursa <james@netsurf-browser.org>2003-07-06 21:10:12 +0000
commitb5606d8f61d3da51302c7acd81ceaa1c236a04b6 (patch)
tree3c73b7713f035c34dd0b4e9413e03774a1541f6c /render
parent210a18e39d5858c86b3a7bfc1562b1ad569e5900 (diff)
downloadnetsurf-b5606d8f61d3da51302c7acd81ceaa1c236a04b6.tar.gz
netsurf-b5606d8f61d3da51302c7acd81ceaa1c236a04b6.tar.bz2
[project @ 2003-07-06 21:10:12 by bursa]
Implement rowspan. svn path=/import/netsurf/; revision=207
Diffstat (limited to 'render')
-rw-r--r--render/box.c62
-rw-r--r--render/box.h1
-rw-r--r--render/layout.c63
3 files changed, 99 insertions, 27 deletions
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++) {