[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:
parent
91300f840f
commit
600f3ad557
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
@ -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>
|
||||
|
|
Loading…
Reference in New Issue