mirror of
https://github.com/netsurf-browser/netsurf
synced 2025-03-30 10:53:00 +03:00
[project @ 2004-12-01 21:48:11 by bursa]
Implement table cell padding and separated borders model for tables. Min/max width calculations still need implementing. svn path=/import/netsurf/; revision=1378
This commit is contained in:
parent
e5fb9a08b4
commit
37d7353f43
@ -1363,22 +1363,30 @@ void parse_border_spacing(struct css_style * const s, const struct css_node * v)
|
||||
if (!v->next) {
|
||||
/* one node */
|
||||
if (v->type == CSS_NODE_IDENT && v->data_length == 7 &&
|
||||
strncasecmp(v->data, "inherit", 7) == 0)
|
||||
s->border_spacing.border_spacing = CSS_BORDER_SPACING_INHERIT;
|
||||
strncasecmp(v->data, "inherit", 7) == 0)
|
||||
s->border_spacing.border_spacing =
|
||||
CSS_BORDER_SPACING_INHERIT;
|
||||
else if (v->type == CSS_NODE_DIMENSION ||
|
||||
v->type == CSS_NODE_NUMBER) {
|
||||
if (parse_length(&s->border_spacing.horz, v, true) == 0 && parse_length(&s->border_spacing.vert, v, true == 0))
|
||||
s->border_spacing.border_spacing = CSS_BORDER_SPACING_LENGTH;
|
||||
if (parse_length(&s->border_spacing.horz,
|
||||
v, true) == 0 &&
|
||||
parse_length(&s->border_spacing.vert,
|
||||
v, true) == 0)
|
||||
s->border_spacing.border_spacing =
|
||||
CSS_BORDER_SPACING_LENGTH;
|
||||
}
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
/* two nodes */
|
||||
if ((v->type == CSS_NODE_DIMENSION ||
|
||||
v->type == CSS_NODE_NUMBER) &&
|
||||
(v->next->type == CSS_NODE_DIMENSION ||
|
||||
v->type == CSS_NODE_NUMBER) &&
|
||||
(v->next->type == CSS_NODE_DIMENSION ||
|
||||
v->next->type == CSS_NODE_NUMBER)) {
|
||||
if (parse_length(&s->border_spacing.horz, v, true) == 0 && parse_length(&s->border_spacing.vert, v->next, true == 0))
|
||||
s->border_spacing.border_spacing = CSS_BORDER_SPACING_LENGTH;
|
||||
if (parse_length(&s->border_spacing.horz,
|
||||
v, true) == 0 &&
|
||||
parse_length(&s->border_spacing.vert,
|
||||
v->next, true) == 0)
|
||||
s->border_spacing.border_spacing =
|
||||
CSS_BORDER_SPACING_LENGTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
189
render/layout.c
189
render/layout.c
@ -253,7 +253,9 @@ bool layout_block_context(struct box *block, pool box_pool)
|
||||
box->padding[BOTTOM] +
|
||||
box->border[BOTTOM];
|
||||
box = box->parent;
|
||||
if (box != block && box->height == AUTO)
|
||||
if (box == block)
|
||||
break;
|
||||
if (box->height == AUTO)
|
||||
box->height = y - box->padding[TOP];
|
||||
cy += box->padding[BOTTOM] +
|
||||
box->border[BOTTOM];
|
||||
@ -501,6 +503,12 @@ void layout_float_find_dimensions(int available_width,
|
||||
|
||||
/**
|
||||
* Calculate size of margins, paddings, and borders.
|
||||
*
|
||||
* \param available_width width of containing block
|
||||
* \param style style giving margins, paddings, and borders
|
||||
* \param margin[4] filled with margins, may be NULL
|
||||
* \param padding[4] filled with paddings
|
||||
* \param border[4] filled with border widths
|
||||
*/
|
||||
|
||||
void layout_find_dimensions(int available_width,
|
||||
@ -509,37 +517,42 @@ void layout_find_dimensions(int available_width,
|
||||
{
|
||||
unsigned int i;
|
||||
for (i = 0; i != 4; i++) {
|
||||
switch (style->margin[i].margin) {
|
||||
if (margin) {
|
||||
switch (style->margin[i].margin) {
|
||||
case CSS_MARGIN_LENGTH:
|
||||
margin[i] = (int)css_len2px(&style->margin[i].value.length, style);
|
||||
margin[i] = (int) css_len2px(&style->margin[i].
|
||||
value.length, style);
|
||||
break;
|
||||
case CSS_MARGIN_PERCENT:
|
||||
margin[i] = available_width *
|
||||
style->margin[i].value.percent / 100;
|
||||
style->margin[i].value.percent / 100;
|
||||
break;
|
||||
case CSS_MARGIN_AUTO:
|
||||
default:
|
||||
margin[i] = AUTO;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
switch (style->padding[i].padding) {
|
||||
case CSS_PADDING_PERCENT:
|
||||
padding[i] = available_width *
|
||||
style->padding[i].value.percent / 100;
|
||||
break;
|
||||
case CSS_PADDING_LENGTH:
|
||||
default:
|
||||
padding[i] = (int)css_len2px(&style->padding[i].value.length, style);
|
||||
break;
|
||||
case CSS_PADDING_PERCENT:
|
||||
padding[i] = available_width *
|
||||
style->padding[i].value.percent / 100;
|
||||
break;
|
||||
case CSS_PADDING_LENGTH:
|
||||
default:
|
||||
padding[i] = (int) css_len2px(&style->padding[i].
|
||||
value.length, style);
|
||||
break;
|
||||
}
|
||||
|
||||
if (style->border[i].style == CSS_BORDER_STYLE_NONE ||
|
||||
style->border[i].style == CSS_BORDER_STYLE_HIDDEN)
|
||||
if (style->border[i].style == CSS_BORDER_STYLE_HIDDEN ||
|
||||
style->border[i].style == CSS_BORDER_STYLE_NONE)
|
||||
/* spec unclear: following Mozilla */
|
||||
border[i] = 0;
|
||||
else
|
||||
border[i] = (int)css_len2px(&style->border[i].width.value, style);
|
||||
border[i] = (int) css_len2px(&style->border[i].
|
||||
width.value, style);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1169,7 +1182,9 @@ void place_float_below(struct box *c, int width, int cx, int y,
|
||||
/**
|
||||
* Layout a table.
|
||||
*
|
||||
* \param box_pool memory pool for any new boxes
|
||||
* \param table table to layout
|
||||
* \param available_width width of containing block
|
||||
* \param box_pool memory pool for any new boxes
|
||||
* \return true on success, false on memory exhaustion
|
||||
*/
|
||||
|
||||
@ -1188,6 +1203,7 @@ bool layout_table(struct box *table, int available_width,
|
||||
int auto_width;
|
||||
int spare_width;
|
||||
int relative_sum = 0;
|
||||
int border_spacing_h = 0, border_spacing_v = 0;
|
||||
struct box *c;
|
||||
struct box *row;
|
||||
struct box *row_group;
|
||||
@ -1200,6 +1216,7 @@ bool layout_table(struct box *table, int available_width,
|
||||
assert(table->children && table->children->children);
|
||||
assert(columns);
|
||||
|
||||
/* allocate working buffers */
|
||||
col = malloc(columns * sizeof col[0]);
|
||||
excess_y = malloc(columns * sizeof excess_y[0]);
|
||||
row_span = malloc(columns * sizeof row_span[0]);
|
||||
@ -1216,34 +1233,57 @@ bool layout_table(struct box *table, int available_width,
|
||||
|
||||
memcpy(col, table->col, sizeof(col[0]) * columns);
|
||||
|
||||
/* find margins, paddings, and borders for table and cells */
|
||||
layout_find_dimensions(available_width, style, table->margin,
|
||||
table->padding, table->border);
|
||||
|
||||
switch (style->width.width) {
|
||||
case CSS_WIDTH_LENGTH:
|
||||
table_width = (int)css_len2px(&style->width.value.length, style);
|
||||
auto_width = table_width;
|
||||
break;
|
||||
case CSS_WIDTH_PERCENT:
|
||||
table_width = available_width *
|
||||
style->width.value.percent / 100;
|
||||
auto_width = table_width;
|
||||
break;
|
||||
case CSS_WIDTH_AUTO:
|
||||
default:
|
||||
table_width = AUTO;
|
||||
auto_width = available_width -
|
||||
((table->margin[LEFT] == AUTO ?
|
||||
0 : table->margin[LEFT]) +
|
||||
table->border[LEFT] +
|
||||
table->padding[LEFT] +
|
||||
table->padding[RIGHT] +
|
||||
table->border[RIGHT] +
|
||||
(table->margin[RIGHT] == AUTO ?
|
||||
0 : table->margin[RIGHT]));
|
||||
break;
|
||||
for (row_group = table->children; row_group;
|
||||
row_group = row_group->next) {
|
||||
for (row = row_group->children; row; row = row->next) {
|
||||
for (c = row->children; c; c = c->next) {
|
||||
assert(c->style);
|
||||
layout_find_dimensions(available_width,
|
||||
c->style, 0,
|
||||
c->padding, c->border);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* border-spacing is used in the separated borders model */
|
||||
if (style->border_collapse == CSS_BORDER_COLLAPSE_SEPARATE) {
|
||||
border_spacing_h = (int) css_len2px(&style->border_spacing.horz,
|
||||
style);
|
||||
border_spacing_v = (int) css_len2px(&style->border_spacing.vert,
|
||||
style);
|
||||
}
|
||||
|
||||
/* find specified table width, or available width if auto-width */
|
||||
switch (style->width.width) {
|
||||
case CSS_WIDTH_LENGTH:
|
||||
table_width = (int) css_len2px(&style->width.value.length,
|
||||
style);
|
||||
auto_width = table_width;
|
||||
break;
|
||||
case CSS_WIDTH_PERCENT:
|
||||
table_width = available_width *
|
||||
style->width.value.percent / 100;
|
||||
auto_width = table_width;
|
||||
break;
|
||||
case CSS_WIDTH_AUTO:
|
||||
default:
|
||||
table_width = AUTO;
|
||||
auto_width = available_width -
|
||||
((table->margin[LEFT] == AUTO ? 0 :
|
||||
table->margin[LEFT]) +
|
||||
table->border[LEFT] +
|
||||
table->padding[LEFT] +
|
||||
table->padding[RIGHT] +
|
||||
table->border[RIGHT] +
|
||||
(table->margin[RIGHT] == AUTO ? 0 :
|
||||
table->margin[RIGHT]));
|
||||
break;
|
||||
}
|
||||
|
||||
/* calculate width required by cells */
|
||||
for (i = 0; i != columns; i++) {
|
||||
if (col[i].type == COLUMN_WIDTH_FIXED) {
|
||||
if (col[i].width < col[i].min)
|
||||
@ -1253,10 +1293,12 @@ bool layout_table(struct box *table, int available_width,
|
||||
required_width += col[i].width;
|
||||
} else if (col[i].type == COLUMN_WIDTH_PERCENT) {
|
||||
int width = col[i].width * auto_width / 100;
|
||||
required_width += col[i].min < width ? width : col[i].min;
|
||||
required_width += col[i].min < width ? width :
|
||||
col[i].min;
|
||||
} else
|
||||
required_width += col[i].min;
|
||||
}
|
||||
required_width += (columns + 1) * border_spacing_h;
|
||||
|
||||
LOG(("width %i, min %i, max %i, auto %i, required %i",
|
||||
table_width, table->min_width, table->max_width,
|
||||
@ -1303,6 +1345,7 @@ bool layout_table(struct box *table, int available_width,
|
||||
else
|
||||
spare_width -= col[i].min;
|
||||
}
|
||||
spare_width -= (columns + 1) * border_spacing_h;
|
||||
if (relative_sum != 0) {
|
||||
if (spare_width < 0)
|
||||
spare_width = 0;
|
||||
@ -1316,6 +1359,8 @@ bool layout_table(struct box *table, int available_width,
|
||||
}
|
||||
}
|
||||
}
|
||||
min_width += (columns + 1) * border_spacing_h;
|
||||
max_width += (columns + 1) * border_spacing_h;
|
||||
|
||||
if (auto_width <= min_width) {
|
||||
/* not enough space: minimise column widths */
|
||||
@ -1360,9 +1405,9 @@ bool layout_table(struct box *table, int available_width,
|
||||
table_width = auto_width;
|
||||
}
|
||||
|
||||
xs[0] = x = 0;
|
||||
xs[0] = x = border_spacing_h;
|
||||
for (i = 0; i != columns; i++) {
|
||||
x += col[i].width;
|
||||
x += col[i].width + border_spacing_h;
|
||||
xs[i + 1] = x;
|
||||
row_span[i] = 0;
|
||||
excess_y[i] = 0;
|
||||
@ -1370,13 +1415,21 @@ bool layout_table(struct box *table, int available_width,
|
||||
}
|
||||
|
||||
/* position cells */
|
||||
for (row_group = table->children; row_group != 0; row_group = row_group->next) {
|
||||
table_height = border_spacing_v;
|
||||
for (row_group = table->children; row_group;
|
||||
row_group = row_group->next) {
|
||||
int row_group_height = 0;
|
||||
for (row = row_group->children; row != 0; row = row->next) {
|
||||
for (row = row_group->children; row; row = row->next) {
|
||||
int row_height = 0;
|
||||
for (c = row->children; c != 0; c = c->next) {
|
||||
assert(c->style != 0);
|
||||
c->width = xs[c->start_column + c->columns] - xs[c->start_column];
|
||||
for (c = row->children; c; c = c->next) {
|
||||
assert(c->style);
|
||||
c->width = xs[c->start_column + c->columns] -
|
||||
xs[c->start_column] -
|
||||
border_spacing_h -
|
||||
c->border[LEFT] -
|
||||
c->padding[LEFT] -
|
||||
c->padding[RIGHT] -
|
||||
c->border[RIGHT];
|
||||
c->float_children = 0;
|
||||
|
||||
c->height = AUTO;
|
||||
@ -1388,23 +1441,34 @@ bool layout_table(struct box *table, int available_width,
|
||||
free(xs);
|
||||
return false;
|
||||
}
|
||||
if (c->style->height.height == CSS_HEIGHT_LENGTH) {
|
||||
/* some sites use height="1" or similar to attempt
|
||||
* to make cells as small as possible, so treat
|
||||
* it as a minimum */
|
||||
int h = (int)css_len2px(&c->style->height.length, c->style);
|
||||
if (c->style->height.height ==
|
||||
CSS_HEIGHT_LENGTH) {
|
||||
/* some sites use height="1" or similar
|
||||
* to attempt to make cells as small as
|
||||
* possible, so treat it as a minimum */
|
||||
int h = (int) css_len2px(&c->style->
|
||||
height.length, c->style);
|
||||
if (c->height < h)
|
||||
c->height = h;
|
||||
}
|
||||
c->x = xs[c->start_column];
|
||||
c->y = 0;
|
||||
c->x = xs[c->start_column] + c->border[LEFT];
|
||||
c->y = c->border[TOP];
|
||||
for (i = 0; i != c->columns; i++) {
|
||||
row_span[c->start_column + i] = c->rows;
|
||||
excess_y[c->start_column + i] = c->height;
|
||||
excess_y[c->start_column + i] =
|
||||
c->border[TOP] +
|
||||
c->padding[TOP] +
|
||||
c->height +
|
||||
c->padding[BOTTOM] +
|
||||
c->border[BOTTOM];
|
||||
row_span_cell[c->start_column + i] = 0;
|
||||
}
|
||||
row_span_cell[c->start_column] = c;
|
||||
c->height = 0;
|
||||
c->height = -border_spacing_v -
|
||||
c->border[TOP] -
|
||||
c->padding[TOP] -
|
||||
c->padding[BOTTOM] -
|
||||
c->border[BOTTOM];
|
||||
}
|
||||
for (i = 0; i != columns; i++)
|
||||
if (row_span[i] != 0)
|
||||
@ -1412,9 +1476,11 @@ bool layout_table(struct box *table, int available_width,
|
||||
else
|
||||
row_span_cell[i] = 0;
|
||||
if (row->next || row_group->next) {
|
||||
/* row height is greatest excess of a cell which ends in this row */
|
||||
/* 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])
|
||||
if (row_span[i] == 0 && row_height <
|
||||
excess_y[i])
|
||||
row_height = excess_y[i];
|
||||
} else {
|
||||
/* except in the last row */
|
||||
@ -1428,14 +1494,15 @@ bool layout_table(struct box *table, int available_width,
|
||||
else
|
||||
excess_y[i] = 0;
|
||||
if (row_span_cell[i] != 0)
|
||||
row_span_cell[i]->height += row_height;
|
||||
row_span_cell[i]->height += row_height +
|
||||
border_spacing_v;
|
||||
}
|
||||
|
||||
row->x = 0;
|
||||
row->y = row_group_height;
|
||||
row->width = table_width;
|
||||
row->height = row_height;
|
||||
row_group_height += row_height;
|
||||
row_group_height += row_height + border_spacing_v;
|
||||
}
|
||||
row_group->x = 0;
|
||||
row_group->y = table_height;
|
||||
|
Loading…
x
Reference in New Issue
Block a user