From 600f3ad557dd0ac4e1fea316fe36251363988401 Mon Sep 17 00:00:00 2001 From: James Bursa Date: Sat, 11 May 2002 15:22:24 +0000 Subject: [project @ 2002-05-11 15:22:24 by bursa] Better inline layout algorithm, simple tcl/tk gui. svn path=/import/netsurf/; revision=15 --- render/box.c | 4 +-- render/font.c | 34 +++++++++++------- render/font.h | 11 ++++-- render/layout.c | 96 ++++++++++++++++++++++++++------------------------ render/render.c | 44 ++++++++++++++++++++--- render/show.tcl | 19 ++++++++++ render/test/test1.html | 2 +- 7 files changed, 141 insertions(+), 69 deletions(-) create mode 100644 render/show.tcl (limited to 'render') diff --git a/render/box.c b/render/box.c index 2966e70af..f857a3461 100644 --- a/render/box.c +++ b/render/box.c @@ -1,5 +1,5 @@ /** - * $Id: box.c,v 1.2 2002/05/04 21:17:06 bursa Exp $ + * $Id: box.c,v 1.3 2002/05/11 15:22:24 bursa Exp $ */ #include @@ -72,7 +72,7 @@ struct box * xml_to_box(xmlNode * n, struct css_style * parent_style, struct css memcpy(style, parent_style, sizeof(struct css_style)); css_get_style(stylesheet, *selector, depth + 1, style); - if (s = xmlGetProp(n, "style")) { + if ((s = xmlGetProp(n, "style"))) { struct css_style * astyle = xcalloc(1, sizeof(struct css_style)); memcpy(astyle, &css_empty_style, sizeof(struct css_style)); css_parse_property_list(astyle, s); diff --git a/render/font.c b/render/font.c index 068687431..6ac3a656a 100644 --- a/render/font.c +++ b/render/font.c @@ -1,5 +1,5 @@ /** - * $Id: font.c,v 1.1 2002/04/25 15:52:26 bursa Exp $ + * $Id: font.c,v 1.2 2002/05/11 15:22:24 bursa Exp $ */ #include @@ -39,21 +39,31 @@ void font_set_free(struct font_set * font_set) * find where to split some text to fit it in width */ -unsigned long font_split(struct font_set * font_set, font_id id, const char * text, - unsigned long width, const char ** end) +struct font_split font_split(struct font_set * font_set, font_id id, const char * text, + unsigned long width, int force) { size_t len = strlen(text); unsigned int i; - assert(width >= 1); - if (len <= width) { - *end = text + len; - return len; + struct font_split split; + + split.height = 30; + + if (len * 20 <= width) { + split.width = len * 20; + split.end = text + len; + } else { + for (i = width / 20; i != 0 && text[i] != ' '; i--) + ; + if (force && i == 0) { + i = width / 20; + if (i == 0) i = 1; + } + split.width = i * 20; + if (text[i] == ' ') i++; + split.end = text + i; } - /* invariant: no space in text[i+1..width) */ - for (i = width - 1; i != 0 && text[i] != ' '; i--) - ; - *end = text + i; - return i; + + return split; } diff --git a/render/font.h b/render/font.h index db10b20b2..4d789a208 100644 --- a/render/font.h +++ b/render/font.h @@ -1,5 +1,5 @@ /** - * $Id: font.h,v 1.1 2002/04/25 15:52:26 bursa Exp $ + * $Id: font.h,v 1.2 2002/05/11 15:22:24 bursa Exp $ */ /** @@ -8,6 +8,11 @@ struct font_set; typedef unsigned int font_id; +struct font_split { + unsigned long width; + unsigned long height; + const char * end; +}; /** * interface @@ -17,6 +22,6 @@ struct font_set * font_set_create(void); font_id font_add(struct font_set * font_set, const char * name, unsigned int weight, unsigned int size); void font_set_free(struct font_set * font_set); -unsigned long font_split(struct font_set * font_set, font_id id, const char * text, - unsigned long width, const char ** end); +struct font_split font_split(struct font_set * font_set, font_id id, const char * text, + unsigned long width, int force); diff --git a/render/layout.c b/render/layout.c index af0760362..8e386736f 100644 --- a/render/layout.c +++ b/render/layout.c @@ -1,5 +1,5 @@ /** - * $Id: layout.c,v 1.1 2002/05/04 19:57:18 bursa Exp $ + * $Id: layout.c,v 1.2 2002/05/11 15:22:24 bursa Exp $ */ #include @@ -56,7 +56,7 @@ void layout_block(struct box * box, unsigned long width) box->width = width; break; case CSS_WIDTH_LENGTH: - box->width = len(&style->width.value.length, 10); + box->width = len(&style->width.value.length, 20); break; case CSS_WIDTH_PERCENT: box->width = width * style->width.value.percent / 100; @@ -67,7 +67,7 @@ void layout_block(struct box * box, unsigned long width) case CSS_HEIGHT_AUTO: break; case CSS_HEIGHT_LENGTH: - box->height = len(&style->height.length, 10); + box->height = len(&style->height.length, 20); break; } } @@ -75,27 +75,27 @@ void layout_block(struct box * box, unsigned long width) unsigned long layout_block_children(struct box * box, unsigned long width) { struct box * c; - unsigned long y = 1; + unsigned long y = 0; for (c = box->children; c != 0; c = c->next) { switch (c->type) { case BOX_BLOCK: - layout_block(c, width-4); - c->x = 2; + layout_block(c, width); + c->x = 0; c->y = y; - y += c->height + 1; + y += c->height; break; case BOX_INLINE_CONTAINER: - layout_inline_container(c, width-4); - c->x = 2; + layout_inline_container(c, width); + c->x = 0; c->y = y; - y += c->height + 1; + y += c->height; break; case BOX_TABLE: - layout_table(c, width-4); - c->x = 2; + layout_table(c, width); + c->x = 0; c->y = y; - y += c->height + 1; + y += c->height; break; default: die("block child not block, table, or inline container"); @@ -108,45 +108,49 @@ void layout_inline_container(struct box * box, unsigned long width) { /* TODO: write this */ struct box * c; - unsigned long y = 1; - unsigned long x = 2; + unsigned long y = 0; + unsigned long x = 0; const char * end; - struct box * new; + struct box * c2; + struct font_split split; for (c = box->children; c != 0; ) { - c->width = font_split(0, c->font, c->text, width-2-x, &end)+1; - if (*end == 0) { + split = font_split(0, c->font, c->text, width - x, x == 0); + if (*(split.end) == 0) { /* fits into this line */ c->x = x; c->y = y; - c->height = 2; + c->width = split.width; + c->height = split.height; + c->length = split.end - c->text; x += c->width; c = c->next; - continue; - } - if (end == c->text) { + } else if (split.end == c->text) { /* doesn't fit at all: move down a line */ - x = 2; - y += 3; - c->width = font_split(0, c->font, c->text, width-2-x, &end)+1; + x = 0; + y += 30; + /*c->width = font_split(0, c->font, c->text, (width-x)/20+1, &end)*20; if (end == c->text) end = strchr(c->text, ' '); - if (end == 0) end = c->text + 1; + if (end == 0) end = c->text + 1;*/ + } else { + /* split into two lines */ + c->x = x; + c->y = y; + c->width = split.width; + c->height = split.height; + c->length = split.end - c->text; + x = 0; + y += 30; + c2 = memcpy(xcalloc(1, sizeof(struct box)), c, sizeof(struct box)); + c2->text = split.end; + c2->next = c->next; + c->next = c2; + c = c2; } - /* split into two lines */ - c->x = x; - c->y = y; - c->height = 2; - x = 2; - y += 3; - new = memcpy(xcalloc(1, sizeof(struct box)), c, sizeof(struct box)); - new->text = end + 1; - new->next = c->next; - c->next = new; - c = new; } box->width = width; - box->height = y + 3; + box->height = y + 30; } /** @@ -165,7 +169,7 @@ void layout_table(struct box * table, unsigned long width) unsigned long auto_width; /* width of each auto column (all equal) */ unsigned long extra_width = 0; /* extra width for each column if table is wider than columns */ unsigned long x; - unsigned long y = 1; + unsigned long y = 0; unsigned long * xs; unsigned int i; struct box * c; @@ -176,7 +180,7 @@ void layout_table(struct box * table, unsigned long width) /* find table width */ switch (table->style->width.width) { case CSS_WIDTH_LENGTH: - table_width = len(&table->style->width.value.length, 10); + table_width = len(&table->style->width.value.length, 20); break; case CSS_WIDTH_PERCENT: table_width = width * table->style->width.value.percent / 100; @@ -193,7 +197,7 @@ void layout_table(struct box * table, unsigned long width) assert(c->type == BOX_TABLE_CELL); switch (c->style->width.width) { case CSS_WIDTH_LENGTH: - used_width += len(&c->style->width.value.length, 10); + used_width += len(&c->style->width.value.length, 20); break; case CSS_WIDTH_PERCENT: used_width += table_width * c->style->width.value.percent / 100; @@ -228,9 +232,9 @@ void layout_table(struct box * table, unsigned long width) break; } xs[i] = x; - printf("%i ", x); + /*printf("%i ", x);*/ } - printf("\n"); + /*printf("\n");*/ if (auto_columns == 0 && table->style->width.width == CSS_WIDTH_AUTO) table_width = used_width; @@ -249,14 +253,14 @@ void layout_table(struct box * table, unsigned long width) break; } c->x = xs[i]; - c->y = 1; + c->y = 0; if (c->height > height) height = c->height; } r->x = 0; r->y = y; r->width = table_width; - r->height = height + 2; - y += height + 3; + r->height = height; + y += height; } free(xs); diff --git a/render/render.c b/render/render.c index 6ada1da3e..2e3eb9c12 100644 --- a/render/render.c +++ b/render/render.c @@ -1,5 +1,5 @@ /** - * $Id: render.c,v 1.8 2002/05/04 21:17:06 bursa Exp $ + * $Id: render.c,v 1.9 2002/05/11 15:22:24 bursa Exp $ */ #include @@ -87,6 +87,38 @@ void render_plain(struct box * box) } +void render_dump(struct box * box, unsigned long x, unsigned long y) +{ + struct box * c; + const char * const noname = ""; + const char * name = noname; + + switch (box->type) { + case BOX_TABLE: + case BOX_TABLE_ROW: + case BOX_TABLE_CELL: + case BOX_BLOCK: name = box->node->name; + break; + case BOX_INLINE: + case BOX_INLINE_CONTAINER: + default: + } + + printf("rect %li %li %li %li \"%s\" \"%.*s\" ", x + box->x, y + box->y, + box->width, box->height, name, + box->type == BOX_INLINE ? box->length : 0, + box->type == BOX_INLINE ? box->text : ""); + if (name == noname) + printf("\"\"\n"); + else + printf("#%.6x\n", 0xffffff - ((name[0] << 16) | (name[1] << 8) | name[0])); + fflush(stdout); + + for (c = box->children; c != 0; c = c->next) + render_dump(c, x + box->x, y + box->y); +} + + int main(int argc, char *argv[]) { struct css_stylesheet * stylesheet; @@ -115,11 +147,13 @@ int main(int argc, char *argv[]) doc_box->node = c; xml_to_box(c, style, stylesheet, &selector, 0, doc_box, 0); html_box = doc_box->children; - box_dump(html_box, 0); +/* box_dump(html_box, 0);*/ - layout_block(html_box, 79); - box_dump(html_box, 0); - render_plain(html_box); + layout_block(html_box, 600); +/* box_dump(html_box, 0);*/ +/* render_plain(html_box);*/ + printf("%li %li\n", html_box->width, html_box->height); + render_dump(html_box, 0, 0); return 0; } diff --git a/render/show.tcl b/render/show.tcl new file mode 100644 index 000000000..4adc48287 --- /dev/null +++ b/render/show.tcl @@ -0,0 +1,19 @@ +#!/usr/bin/wish + +gets stdin size +scan $size "%i %i" x y +canvas .can -width [expr $x+16] -height [expr $y+16] -borderwidth 0 -highlightthickness 0 -bg white +pack .can + +proc rect {x y w h n t c} { + set x [expr $x+8] + set y [expr $y+8] + .can create rectangle $x $y [expr $x+$w] [expr $y+$h] -fill $c + .can create text $x $y -anchor nw -text $n -fill red -font "arial 18 bold" + .can create text $x [expr $y+$h] -anchor sw -text $t -font "courier 32" +} + +while {-1 != [gets stdin line]} { + eval $line +} + diff --git a/render/test/test1.html b/render/test/test1.html index 757c51cb6..901d13c67 100644 --- a/render/test/test1.html +++ b/render/test/test1.html @@ -9,7 +9,7 @@

Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant Morbi tristique Senectus et Metus et malesuada Fames ac turpis Egestas. (This paragraph has no closing tag.)

Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque habitant Morbi tristique Senectus et Metus et malesuada Fames ac turpis Egestas.

- +
Cell 1Cell 2

More cell 2

Cell 1Cell 2

More cell 2

Cell 3Cell 4

Inline text

containing a block
and more text.

-- cgit v1.2.3