[project @ 2002-05-11 15:22:24 by bursa]

Better inline layout algorithm, simple tcl/tk gui.

svn path=/import/netsurf/; revision=15
This commit is contained in:
James Bursa 2002-05-11 15:22:24 +00:00
parent 91300f840f
commit 600f3ad557
7 changed files with 141 additions and 69 deletions

View File

@ -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 <assert.h>
@ -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);

View File

@ -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 <assert.h>
@ -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;
}

View File

@ -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);

View File

@ -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 <assert.h>
@ -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);

View File

@ -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 <assert.h>
@ -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;
}

19
render/show.tcl Normal file
View File

@ -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
}

View File

@ -9,7 +9,7 @@
<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque <b>habitant <i>Morbi</i></b> tristique Senectus et Metus et malesuada Fames ac turpis Egestas. (This paragraph has no closing tag.)<p>Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; <b>Pellentesque</b> habitant Morbi tristique Senectus et Metus et malesuada Fames ac turpis Egestas.</p>
<table><tr><td style="width: 30%; height: 1em">Cell 1</td><td style="width: 50%;">Cell 2<p>More cell 2</p></td></tr>
<table><tr><td style="width: 30%; height: 4em">Cell 1</td><td style="width: 50%;">Cell 2<p>More cell 2</p></td></tr>
<tr><td>Cell 3</td><td>Cell 4</td></tr></table>
<p>Inline text <div>containing a block</div> and more text.</p>