diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2014-10-22 21:20:42 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2014-12-03 12:25:51 +0100 |
commit | d79203b42621257aed8e4c02e4e6c95ec82d9243 (patch) | |
tree | 4ebd4fc7a39f55ad1a4ec7cad157f0d9a90a64e3 /source/html/layout.c | |
parent | 9890cc2bd3c6b81ebaf5f7ce236117dc08c03cee (diff) | |
download | mupdf-d79203b42621257aed8e4c02e4e6c95ec82d9243.tar.xz |
html: Don't compute full styles during box generation.
Apply the style sheet rules and save the raw properties in each box.
Only resolve the 'display' property that is needed for box generation.
Diffstat (limited to 'source/html/layout.c')
-rw-r--r-- | source/html/layout.c | 167 |
1 files changed, 82 insertions, 85 deletions
diff --git a/source/html/layout.c b/source/html/layout.c index c8ba17e2..1d92b502 100644 --- a/source/html/layout.c +++ b/source/html/layout.c @@ -40,159 +40,156 @@ enum struct box { int type; - float x, y, w, h; - float padding[4]; - float border[4]; - float margin[4]; - - int bold, italic; - - fz_xml *node; - const char *text; - struct box *up, *down, *last, *next; + fz_xml *node; + struct style style; }; -struct box *new_box(fz_context *ctx, struct box *root, int type, struct computed_style *cstyle, fz_xml *node) +struct box *new_box(fz_context *ctx, fz_xml *node, struct style *up_style) { struct box *box; - int i; box = fz_malloc_struct(ctx, struct box); - box->type = type; + + box->type = BOX_BLOCK; 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->bold = cstyle->bold; - box->italic = cstyle->italic; - } - - box->node = node; - - box->up = root; + box->up = NULL; box->last = NULL; box->down = NULL; box->next = NULL; - if (root) + box->node = node; + + box->style.up = up_style; + box->style.count = 0; + + return box; +} + +void insert_box(fz_context *ctx, struct box *box, int type, struct box *top) +{ + box->type = type; + + box->up = top; + + if (top) { - if (!root->last) + if (!top->last) { - root->down = root->last = box; + top->down = top->last = box; } else { - root->last->next = box; - root->last = box; + top->last->next = box; + top->last = box; } } - - return box; } -static struct box *new_block_box(fz_context *ctx, struct box **topp, struct computed_style *cstyle, fz_xml *node) +static struct box *insert_block_box(fz_context *ctx, struct box *box, struct box *top) { - struct box *top = *topp; - struct box *box; - if (top->type == BOX_BLOCK) { - box = new_box(ctx, top, BOX_BLOCK, cstyle, node); + insert_box(ctx, box, BOX_BLOCK, top); } else if (top->type == BOX_ANONYMOUS) { while (top->type != BOX_BLOCK) top = top->up; - *topp = top; - box = new_box(ctx, top, BOX_BLOCK, cstyle, node); + insert_box(ctx, box, BOX_BLOCK, top); } else if (top->type == BOX_INLINE) { while (top->type != BOX_BLOCK) top = top->up; - *topp = top; - box = new_box(ctx, top, BOX_BLOCK, cstyle, node); + insert_box(ctx, box, BOX_BLOCK, top); } - return box; + return top; } -static struct box *new_inline_box(fz_context *ctx, struct box *box, struct computed_style *cstyle, fz_xml *node) +static void insert_inline_box(fz_context *ctx, struct box *box, struct box *top) { - if (box->type == BOX_BLOCK) + if (top->type == BOX_BLOCK) { - if (box->last && box->last->type == BOX_ANONYMOUS) - box = box->last; + if (top->last && top->last->type == BOX_ANONYMOUS) + { + insert_box(ctx, box, BOX_INLINE, top->last); + } else - box = new_box(ctx, box, BOX_ANONYMOUS, cstyle, NULL); - box = new_box(ctx, box, BOX_INLINE, cstyle, node); + { + struct box *anon = new_box(ctx, NULL, &top->style); + insert_box(ctx, anon, BOX_ANONYMOUS, top); + insert_box(ctx, box, BOX_INLINE, anon); + } } else if (box->type == BOX_ANONYMOUS) { - box = new_box(ctx, box, BOX_INLINE, cstyle, node); + insert_box(ctx, box, BOX_INLINE, top); } else if (box->type == BOX_INLINE) { - box = new_box(ctx, box, BOX_INLINE, cstyle, node); + insert_box(ctx, box, BOX_INLINE, top); } - return box; } -static void layout_tree(fz_context *ctx, fz_xml *node, struct box *top, struct style *up_style, struct rule *rule) +static void generate_boxes(fz_context *ctx, fz_xml *node, struct box *top, struct rule *rule) { - struct style style; - struct computed_style cstyle; + struct style *up_style; struct box *box; + int display; + + /* link styles separately because splitting inline blocks breaks the style/box tree symmetry */ + up_style = &top->style; while (node) { - style.up = up_style; - style.count = 0; + box = new_box(ctx, node, up_style); if (fz_xml_tag(node)) { - apply_styles(ctx, &style, rule, node); - compute_style(&cstyle, &style); - // print_style(&cstyle); + apply_styles(ctx, &box->style, rule, node); + + display = get_style_property_display(&box->style); // TOOD: <br> // TODO: <img> - if (cstyle.display != NONE) + if (display != NONE) { - if (cstyle.display == BLOCK) + if (display == BLOCK) { - box = new_block_box(ctx, &top, &cstyle, node); + top = insert_block_box(ctx, box, top); } - else if (cstyle.display == INLINE) + else if (display == INLINE) { - box = new_inline_box(ctx, top, &cstyle, node); + insert_inline_box(ctx, box, top); } else { fz_warn(ctx, "unknown box display type"); - box = new_box(ctx, top, BOX_BLOCK, &cstyle, node); + insert_box(ctx, box, BOX_BLOCK, top); } if (fz_xml_down(node)) - layout_tree(ctx, fz_xml_down(node), box, &style, rule); + generate_boxes(ctx, fz_xml_down(node), box, rule); } } else { - compute_style(&cstyle, &style); - new_inline_box(ctx, top, &cstyle, node); + insert_inline_box(ctx, box, top); } node = fz_xml_next(node); } } +static void layout_boxes(fz_context *ctx, struct box *top, float w, float h) +{ +} + static void indent(int level) { while (level--) printf(" "); @@ -209,13 +206,12 @@ static void print_box(fz_context *ctx, struct box *box, int level) case BOX_ANONYMOUS: printf("anonymous"); break; case BOX_INLINE: printf("inline"); break; } - if (box->node) { + 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); - if (box->bold) printf(" bold"); - if (box->italic) printf(" italic"); } printf("\n"); if (box->down) @@ -238,7 +234,8 @@ static char *concat_text(fz_context *ctx, fz_xml *root) for (node = fz_xml_down(root); node; node = fz_xml_next(node)) { const char *text = fz_xml_text(node); - if (text) { + if (text) + { n = strlen(text); memcpy(s+i, text, n); i += n; @@ -251,14 +248,18 @@ static char *concat_text(fz_context *ctx, fz_xml *root) static struct rule *load_css(fz_context *ctx, struct rule *css, fz_xml *root) { fz_xml *node; - for (node = root; node; node = fz_xml_next(node)) { + for (node = root; node; node = fz_xml_next(node)) + { const char *tag = fz_xml_tag(node); #if 0 - if (tag && !strcmp(tag, "link")) { + if (tag && !strcmp(tag, "link")) + { char *rel = fz_xml_att(node, "rel"); - if (rel && !strcasecmp(rel, "stylesheet")) { + if (rel && !strcasecmp(rel, "stylesheet")) + { char *type = fz_xml_att(node, "type"); - if ((type && !strcmp(type, "text/css")) || !type) { + if ((type && !strcmp(type, "text/css")) || !type) + { char *href = fz_xml_att(node, "href"); strcpy(filename, dirname); strcat(filename, href); @@ -267,7 +268,8 @@ static struct rule *load_css(fz_context *ctx, struct rule *css, fz_xml *root) } } #endif - if (tag && !strcmp(tag, "style")) { + if (tag && !strcmp(tag, "style")) + { char *s = concat_text(ctx, node); css = fz_parse_css(ctx, css, s); fz_free(ctx, s); @@ -283,8 +285,6 @@ 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]); @@ -299,11 +299,8 @@ html_layout_document(html_document *doc, float w, float h) // print_rules(css); - 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); + root_box = new_box(doc->ctx, NULL, NULL); + generate_boxes(doc->ctx, doc->root, root_box, css); + layout_boxes(doc->ctx, root_box, w, h); print_box(doc->ctx, root_box, 0); } |