diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-04-06 00:37:33 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-04-06 00:58:04 +0200 |
commit | 3939a49a37b5c05002e9aa8e9526d3de9307f423 (patch) | |
tree | 0c1176078758b1c238b89bd191ea65469f2a3489 | |
parent | 935f1ba5c2a4c67d98658d72322ae11402d380d0 (diff) | |
download | mupdf-3939a49a37b5c05002e9aa8e9526d3de9307f423.tar.xz |
epub: Handle font-size in nested inline elements.
Point to the box struct rather than its style, so we can look at its
resolved em size. Also make sure to resolve em sizes for inline boxes.
-rw-r--r-- | include/mupdf/html.h | 4 | ||||
-rw-r--r-- | source/html/html-layout.c | 124 |
2 files changed, 71 insertions, 57 deletions
diff --git a/include/mupdf/html.h b/include/mupdf/html.h index 106fb155..3adbf8e0 100644 --- a/include/mupdf/html.h +++ b/include/mupdf/html.h @@ -222,8 +222,8 @@ struct fz_html_flow_s /* The script detected by the bidi code. */ unsigned int script : 8; - float x, y, w, h, em; - fz_css_style *style; + float x, y, w, h; + fz_html *box; /* for style and em */ union { char *text; fz_image *image; diff --git a/source/html/html-layout.c b/source/html/html-layout.c index f9fcacce..d76dd2a8 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -104,51 +104,51 @@ static void fz_drop_html_flow(fz_context *ctx, fz_html_flow *flow) } } -static fz_html_flow *add_flow(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, int type) +static fz_html_flow *add_flow(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, int type) { fz_html_flow *flow = fz_pool_alloc(ctx, pool, sizeof *flow); flow->type = type; flow->expand = 0; flow->bidi_level = 0; flow->breaks_line = 0; - flow->style = style; + flow->box = inline_box; *top->flow_tail = flow; top->flow_tail = &flow->next; return flow; } -static void add_flow_space(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style) +static void add_flow_space(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box) { - fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_SPACE); + fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_SPACE); flow->expand = 1; } -static void add_flow_break(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style) +static void add_flow_break(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box) { - (void)add_flow(ctx, pool, top, style, FLOW_BREAK); + (void)add_flow(ctx, pool, top, inline_box, FLOW_BREAK); } -static void add_flow_sbreak(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style) +static void add_flow_sbreak(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box) { - (void)add_flow(ctx, pool, top, style, FLOW_SBREAK); + (void)add_flow(ctx, pool, top, inline_box, FLOW_SBREAK); } -static void add_flow_shyphen(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style) +static void add_flow_shyphen(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box) { - (void)add_flow(ctx, pool, top, style, FLOW_SHYPHEN); + (void)add_flow(ctx, pool, top, inline_box, FLOW_SHYPHEN); } -static void add_flow_word(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, const char *a, const char *b) +static void add_flow_word(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, const char *a, const char *b) { - fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_WORD); + fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_WORD); flow->content.text = fz_pool_alloc(ctx, pool, b - a + 1); memcpy(flow->content.text, a, b - a); flow->content.text[b - a] = 0; } -static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html *top, fz_css_style *style, fz_image *img) +static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html *top, fz_html *inline_box, fz_image *img) { - fz_html_flow *flow = add_flow(ctx, pool, top, style, FLOW_IMAGE); + fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_IMAGE); flow->content.image = fz_keep_image(ctx, img); } @@ -179,18 +179,18 @@ static fz_html_flow *split_flow(fz_context *ctx, fz_pool *pool, fz_html_flow *fl return new_flow; } -static void flush_space(fz_context *ctx, fz_pool *pool, fz_html *flow, fz_css_style *style, struct genstate *g) +static void flush_space(fz_context *ctx, fz_pool *pool, fz_html *flow, fz_html *inline_box, struct genstate *g) { static const char *space = " "; - int bsp = style->white_space & WS_ALLOW_BREAK_SPACE; + int bsp = inline_box->style.white_space & WS_ALLOW_BREAK_SPACE; if (g->emit_white) { if (!g->at_bol) { if (bsp) - add_flow_space(ctx, pool, flow, style); + add_flow_space(ctx, pool, flow, inline_box); else - add_flow_word(ctx, pool, flow, style, space, space+1); + add_flow_word(ctx, pool, flow, inline_box, space, space+1); } g->emit_white = 0; } @@ -254,7 +254,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch text += 2; else text += 1; - add_flow_break(ctx, pool, flow, &box->style); + add_flow_break(ctx, pool, flow, box); g->at_bol = 1; } else if (iswhite(*text)) @@ -273,9 +273,9 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch { // TODO: tabs if (bsp) - add_flow_space(ctx, pool, flow, &box->style); + add_flow_space(ctx, pool, flow, box); else - add_flow_word(ctx, pool, flow, &box->style, space, space+1); + add_flow_word(ctx, pool, flow, box, space, space+1); ++text; } g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ; /* don't add sbreaks after a space */ @@ -285,7 +285,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch const char *prev, *mark = text; int c; - flush_space(ctx, pool, flow, &box->style, g); + flush_space(ctx, pool, flow, box, g); if (g->at_bol) g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ; @@ -297,8 +297,8 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch if (c == 0xAD) /* soft hyphen */ { if (mark != prev) - add_flow_word(ctx, pool, flow, &box->style, mark, prev); - add_flow_shyphen(ctx, pool, flow, &box->style); + add_flow_word(ctx, pool, flow, box, mark, prev); + add_flow_shyphen(ctx, pool, flow, box); mark = text; g->last_brk_cls = UCDN_LINEBREAK_CLASS_WJ; /* don't add sbreaks after a soft hyphen */ } @@ -317,8 +317,8 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch if (brk == '_') { if (mark != prev) - add_flow_word(ctx, pool, flow, &box->style, mark, prev); - add_flow_sbreak(ctx, pool, flow, &box->style); + add_flow_word(ctx, pool, flow, box, mark, prev); + add_flow_sbreak(ctx, pool, flow, box); mark = prev; } @@ -327,7 +327,7 @@ static void generate_text(fz_context *ctx, fz_pool *pool, fz_html *box, const ch } } if (mark != text) - add_flow_word(ctx, pool, flow, &box->style, mark, text); + add_flow_word(ctx, pool, flow, box, mark, text); g->at_bol = 0; } @@ -353,15 +353,15 @@ static void generate_image(fz_context *ctx, fz_pool *pool, fz_archive *zip, cons fz_var(buf); fz_var(img); - flush_space(ctx, pool, flow, &box->style, g); + flush_space(ctx, pool, flow, box, g); fz_try(ctx) { buf = fz_read_archive_entry(ctx, zip, path); img = fz_new_image_from_buffer(ctx, buf); - add_flow_sbreak(ctx, pool, flow, &box->style); - add_flow_image(ctx, pool, flow, &box->style, img); - add_flow_sbreak(ctx, pool, flow, &box->style); + add_flow_sbreak(ctx, pool, flow, box); + add_flow_image(ctx, pool, flow, box, img); + add_flow_sbreak(ctx, pool, flow, box); } fz_always(ctx) { @@ -372,7 +372,7 @@ static void generate_image(fz_context *ctx, fz_pool *pool, fz_archive *zip, cons { const char *alt = "[image]"; fz_warn(ctx, "html: cannot add image src='%s'", src); - add_flow_word(ctx, pool, flow, &box->style, alt, alt + 7); + add_flow_word(ctx, pool, flow, box, alt, alt + 7); } g->at_bol = 0; @@ -536,7 +536,7 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html *top, fz_html *flow = top; while (flow->type != BOX_FLOW) flow = flow->up; - add_flow_break(ctx, g->pool, flow, &top->style); + add_flow_break(ctx, g->pool, flow, top); } else { @@ -847,14 +847,14 @@ static void measure_string(fz_context *ctx, fz_html_flow *node, float em, hb_buf string_walker walker; const char *s; - em = fz_from_css_number(node->style->font_size, em, em); + em = node->box->em; node->x = 0; node->y = 0; node->w = 0; - node->h = fz_from_css_number_scale(node->style->line_height, em, em, em); + node->h = fz_from_css_number_scale(node->box->style.line_height, em, em, em); s = get_node_text(ctx, node); - init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->style->font, node->script, s); + init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->box->style.font, node->script, s); while (walk_string(&walker)) { int x = 0; @@ -862,8 +862,6 @@ static void measure_string(fz_context *ctx, fz_html_flow *node, float em, hb_buf x += walker.glyph_pos[i].x_advance; node->w += x * em / walker.scale; } - - node->em = em; } static float measure_line(fz_html_flow *node, fz_html_flow *end, float *baseline) @@ -878,8 +876,8 @@ static float measure_line(fz_html_flow *node, fz_html_flow *end, float *baseline } else { - float a = node->em * 0.8; - float d = node->em * 0.2; + float a = node->box->em * 0.8; + float d = node->box->em * 0.2; if (a > max_a) max_a = a; if (d > max_d) max_d = d; } @@ -991,25 +989,25 @@ static void layout_line(fz_context *ctx, float indent, float page_w, float line_ node->x = x; x += w; - switch (node->style->vertical_align) + switch (node->box->style.vertical_align) { default: case VA_BASELINE: va = 0; break; case VA_SUB: - va = node->em * 0.2f; + va = node->box->em * 0.2f; break; case VA_SUPER: - va = node->em * -0.3f; + va = node->box->em * -0.3f; break; case VA_TOP: case VA_TEXT_TOP: - va = -baseline + node->em * 0.8; + va = -baseline + node->box->em * 0.8; break; case VA_BOTTOM: case VA_TEXT_BOTTOM: - va = -baseline + line_h - node->em * 0.2; + va = -baseline + line_h - node->box->em * 0.2; break; } @@ -1046,13 +1044,24 @@ static void flush_line(fz_context *ctx, fz_html *box, float page_h, float page_w box->h += line_h; } +static void layout_flow_inline(fz_context *ctx, fz_html *box, fz_html *top, float em) +{ + while (box) + { + box->em = fz_from_css_number(box->style.font_size, em, em); + if (box->down) + layout_flow_inline(ctx, box->down, box, box->em); + box = box->next; + } +} + static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, float page_h, hb_buffer_t *hb_buf) { fz_html_flow *node, *line, *candidate; float line_w, candidate_w, indent, break_w, nonbreak_w; int line_align, align; - em = fz_from_css_number(box->style.font_size, em, em); + em = box->em = fz_from_css_number(box->style.font_size, em, em); indent = box->is_first_flow ? fz_from_css_number(top->style.text_indent, em, top->w) : 0; align = top->style.text_align; @@ -1072,6 +1081,9 @@ static void layout_flow(fz_context *ctx, fz_html *box, fz_html *top, float em, f if (!box->flow_head) return; + if (box->down) + layout_flow_inline(ctx, box->down, box, em); + for (node = box->flow_head; node; node = node->next) { if (node->type == FLOW_IMAGE) @@ -1283,6 +1295,8 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p for (node = box->flow_head; node; node = node->next) { + fz_css_style *style = &node->box->style; + if (node->type == FLOW_IMAGE) { if (node->y >= page_bot || node->y + node->h <= page_top) @@ -1306,12 +1320,12 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p continue; if (node->type == FLOW_SHYPHEN && !node->breaks_line) continue; - if (node->style->visibility != V_VISIBLE) + if (style->visibility != V_VISIBLE) continue; - color[0] = node->style->color.r / 255.0f; - color[1] = node->style->color.g / 255.0f; - color[2] = node->style->color.b / 255.0f; + color[0] = style->color.r / 255.0f; + color[1] = style->color.g / 255.0f; + color[2] = style->color.b / 255.0f; if (color[0] != prev_color[0] || color[1] != prev_color[1] || color[2] != prev_color[2]) { @@ -1335,18 +1349,18 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p x = node->x; y = node->y; - trm.a = node->em; + trm.a = node->box->em; trm.b = 0; trm.c = 0; - trm.d = -node->em; + trm.d = -node->box->em; trm.e = x; trm.f = y; s = get_node_text(ctx, node); - init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, node->style->font, node->script, s); + init_string_walker(ctx, &walker, hb_buf, node->bidi_level & 1, style->font, node->script, s); while (walk_string(&walker)) { - float node_scale = node->em / walker.scale; + float node_scale = node->box->em / walker.scale; unsigned int i; int c, k, n; @@ -1408,7 +1422,7 @@ static void draw_flow_box(fz_context *ctx, fz_html *box, float page_top, float p fz_drop_text(ctx, text); text = NULL; } - if (node->style->visibility == V_VISIBLE) + if (style->visibility == V_VISIBLE) { fz_matrix local_ctm = *ctm; fz_pre_translate(&local_ctm, node->x, node->y); |