diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2014-10-21 16:37:29 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2014-12-03 12:25:51 +0100 |
commit | 4ce5833ca8e6e6f0156125a572fbc3b376e41d36 (patch) | |
tree | 60272e5114ee62f11f27cf58be45efeb79d2ea61 /source/html/layout.c | |
parent | 1ce69ac127c823463204ad522bb7c71ac7fad27a (diff) | |
download | mupdf-4ce5833ca8e6e6f0156125a572fbc3b376e41d36.tar.xz |
html: Box generation.
Diffstat (limited to 'source/html/layout.c')
-rw-r--r-- | source/html/layout.c | 255 |
1 files changed, 201 insertions, 54 deletions
diff --git a/source/html/layout.c b/source/html/layout.c index 372a495d..340b8c58 100644 --- a/source/html/layout.c +++ b/source/html/layout.c @@ -30,10 +30,195 @@ static const char *default_css = "center{text-align:center}" "svg{display:none}"; -char dirname[2048]; -char filename[2048]; +enum +{ + BOX_BLOCK, /* block-level: contains other block and anonymous boxes */ + BOX_ANONYMOUS, /* block-level: contains only inline boxes */ + BOX_INLINE, /* inline-level: contains only inline boxes */ +}; + +struct box +{ + int type; + + float x, y, w, h; + float padding[4]; + float border[4]; + float margin[4]; + + fz_xml *node; + const char *text; + + struct box *up, *down, *last, *next; +}; + +struct box *new_box(fz_context *ctx, struct box *root, int type, struct computed_style *cstyle, fz_xml *node) +{ + struct box *box; + int i; + + box = fz_malloc_struct(ctx, struct box); + box->type = type; + box->x = box->y = 0; + box->w = box->h = 0; + for (i = 0; i < 4; ++i) + { + box->padding[i] = cstyle->padding[i]; + box->margin[i] = cstyle->margin[i]; + box->border[i] = cstyle->border_width[i]; + } + + box->node = node; + + box->up = root; + box->last = NULL; + box->down = NULL; + box->next = NULL; + + if (root) + { + if (!root->last) + { + root->down = root->last = box; + } + else + { + root->last->next = box; + root->last = box; + } + } + + return box; +} + +static struct box *new_block_box(fz_context *ctx, struct box *box, struct computed_style *cstyle, fz_xml *node) +{ + if (box->type == BOX_BLOCK) + { + box = new_box(ctx, box, BOX_BLOCK, cstyle, node); + } + else if (box->type == BOX_ANONYMOUS) + { + fz_warn(ctx, "block-level box inside anonymous box"); + while (box->type != BOX_BLOCK) + box = box->up; + box = new_box(ctx, box, BOX_BLOCK, cstyle, node); + } + else if (box->type == BOX_INLINE) + { + fz_warn(ctx, "block-level box inside inline box"); + while (box->type != BOX_BLOCK) + box = box->up; + box = new_box(ctx, box, BOX_BLOCK, cstyle, node); + } + return box; +} + +static struct box *new_inline_box(fz_context *ctx, struct box *box, struct computed_style *cstyle, fz_xml *node) +{ + if (box->type == BOX_BLOCK) + { + if (box->last && box->last->type == BOX_ANONYMOUS) + box = box->last; + else + box = new_box(ctx, box, BOX_ANONYMOUS, cstyle, NULL); + box = new_box(ctx, box, BOX_INLINE, cstyle, node); + } + else if (box->type == BOX_ANONYMOUS) + { + box = new_box(ctx, box, BOX_INLINE, cstyle, node); + } + else if (box->type == BOX_INLINE) + { + box = new_box(ctx, box, BOX_INLINE, cstyle, node); + } + return box; +} + +static void layout_tree(fz_context *ctx, fz_xml *node, struct box *box, struct style *up_style, struct rule *rule) +{ + struct style style; + struct computed_style cstyle; + struct box *save_box; + + while (node) + { + style.up = up_style; + style.count = 0; + + if (fz_xml_tag(node)) + { + apply_styles(ctx, &style, rule, node); + compute_style(&cstyle, &style); + // print_style(&cstyle); + + // TOOD: <br> + // TODO: <img> + + if (cstyle.display != NONE) + { + save_box = box; + + if (cstyle.display == BLOCK) + { + box = new_block_box(ctx, box, &cstyle, node); + } + else if (cstyle.display == INLINE) + { + box = new_inline_box(ctx, box, &cstyle, node); + } + else + { + fz_warn(ctx, "unknown box display type"); + box = new_box(ctx, box, BOX_BLOCK, &cstyle, node); + } + + if (fz_xml_down(node)) + layout_tree(ctx, fz_xml_down(node), box, &style, rule); + + box = save_box; + } + } + else + { + compute_style(&cstyle, &style); + new_inline_box(ctx, box, &cstyle, node); + } + + node = fz_xml_next(node); + } +} + +static void indent(int level) +{ + while (level--) printf(" "); +} + +static void print_box(fz_context *ctx, struct box *box, int level) +{ + while (box) + { + indent(level); + switch (box->type) + { + case BOX_BLOCK: printf("block"); break; + case BOX_ANONYMOUS: printf("anonymous"); break; + case BOX_INLINE: printf("inline"); break; + } + if (box->node) { + const char *tag = fz_xml_tag(box->node); + const char *text = fz_xml_text(box->node); + if (tag) printf(" <%s>", tag); + if (text) printf(" \"%s\"", text); + } + printf("\n"); + if (box->down) + print_box(ctx, box->down, level + 1); + box = box->next; + } +} -static char *concat_text(fz_xml *root) +static char *concat_text(fz_context *ctx, fz_xml *root) { fz_xml *node; int i = 0, n = 1; @@ -43,7 +228,7 @@ static char *concat_text(fz_xml *root) const char *text = fz_xml_text(node); n += text ? strlen(text) : 0; } - s = malloc(n); + s = fz_malloc(ctx, n); for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { const char *text = fz_xml_text(node); @@ -77,10 +262,9 @@ static struct rule *load_css(fz_context *ctx, struct rule *css, fz_xml *root) } #endif if (tag && !strcmp(tag, "style")) { -printf("found inline style sheet!\n"); - char *s = concat_text(node); -printf("'%s'\n", s); + char *s = concat_text(ctx, node); css = fz_parse_css(ctx, css, s); + fz_free(ctx, s); } if (fz_xml_down(node)) css = load_css(ctx, css, fz_xml_down(node)); @@ -88,56 +272,13 @@ printf("'%s'\n", s); return css; } -static void layout_text(struct rule *rule, struct style *style, fz_xml *node) -{ - printf("%s\n", fz_xml_text(node)); -} - -static void layout_tree(fz_context *ctx, struct rule *rule, struct style *up, fz_xml *node) -{ - while (node) - { - struct style style; - style.up = up; - style.count = 0; - - if (fz_xml_tag(node)) - { - struct computed_style cstyle; - const char *s; - - printf("open '%s'\n", fz_xml_tag(node)); - apply_styles(&style, rule, node); - - s = fz_xml_att(node, "style"); - if (s) - { - struct property *props = fz_parse_css_properties(ctx, s); - apply_inline_style(&style, props); - // free props - } - - compute_style(&cstyle, &style); - print_style(&cstyle); - } - else - layout_text(rule, &style, node); - - // TOOD: <br> - // TODO: <img> - - if (fz_xml_down(node)) - layout_tree(ctx, rule, &style, fz_xml_down(node)); - - printf("end\n"); - node = fz_xml_next(node); - } -} - void html_layout_document(html_document *doc, float w, float h) { struct rule *css = NULL; + struct box *root_box; + struct style style; + struct computed_style cstyle; #if 0 strcpy(dirname, argv[i]); @@ -152,5 +293,11 @@ html_layout_document(html_document *doc, float w, float h) print_rules(css); - layout_tree(doc->ctx, css, NULL, doc->root); + style.up = NULL; + style.count = 0; + compute_style(&cstyle, &style); + root_box = new_box(doc->ctx, NULL, BOX_BLOCK, &cstyle, NULL); + + layout_tree(doc->ctx, doc->root, root_box, NULL, css); + print_box(doc->ctx, root_box, 0); } |