diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-10-20 14:07:21 +0200 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-10-28 16:18:39 +0200 |
commit | cc3bbe49ce3fa0c99dafd4d762b8da0ecd281ff2 (patch) | |
tree | 71637e49c05fd145e39636bb44605e8bbc062cde /source/html | |
parent | 8a07b7fb14f11204a0d840792ab9f4bd54b066e5 (diff) | |
download | mupdf-cc3bbe49ce3fa0c99dafd4d762b8da0ecd281ff2.tar.xz |
epub: Add 'id' attribute to all HTML elements, not just <a> tags.
Allows id anchoring to block elements as well as inline elements.
Fix for bug 697123.
Diffstat (limited to 'source/html')
-rw-r--r-- | source/html/epub-doc.c | 42 | ||||
-rw-r--r-- | source/html/html-layout.c | 39 |
2 files changed, 47 insertions, 34 deletions
diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index 0616bb70..f9d9e6aa 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -35,32 +35,40 @@ struct epub_page_s }; static int -find_anchor_flow(fz_html_flow *flow, const char *anchor, float page_h, int *page) +find_anchor_flow(fz_html_flow *flow, const char *anchor, float page_h) { while (flow) { - if (flow->type == FLOW_ANCHOR && !strcmp(anchor, flow->content.text)) - { - *page += (int)(flow->y / page_h); - return 1; - } + if (flow->box->id && !strcmp(anchor, flow->box->id)) + return flow->y / page_h; flow = flow->next; } - return 0; + return -1; } static int -find_anchor_box(fz_html_box *box, const char *anchor, float page_h, int *page) +find_anchor_box(fz_html_box *box, const char *anchor, float page_h) { + int page; while (box) { - if (box->flow_head && find_anchor_flow(box->flow_head, anchor, page_h, page)) - return 1; - if (box->down && find_anchor_box(box->down, anchor, page_h, page)) - return 1; + if (box->id && !strcmp(anchor, box->id)) + return box->y / page_h; + if (box->type == BOX_FLOW) + { + page = find_anchor_flow(box->flow_head, anchor, page_h); + if (page >= 0) + return page; + } + else + { + page = find_anchor_box(box->down, anchor, page_h); + if (page >= 0) + return page; + } box = box->next; } - return 0; + return -1; } static int @@ -79,16 +87,18 @@ epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest) { if (!strncmp(ch->path, dest, n) && ch->path[n] == 0) { - page = ch->start; if (s) { /* Search for a matching fragment */ - find_anchor_box(ch->html->root, s+1, ch->page_h, &page); + page = find_anchor_box(ch->html->root, s+1, ch->page_h); + if (page >= 0) + return ch->start + page; } + return ch->start; } } - return page; + return -1; } static void diff --git a/source/html/html-layout.c b/source/html/html-layout.c index b700b59b..fc0874ae 100644 --- a/source/html/html-layout.c +++ b/source/html/html-layout.c @@ -198,12 +198,9 @@ static void add_flow_image(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_ flow->content.image = fz_keep_image(ctx, img); } -static void add_flow_anchor(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_html_box *inline_box, const char *anchor) +static void add_flow_anchor(fz_context *ctx, fz_pool *pool, fz_html_box *top, fz_html_box *inline_box) { - fz_html_flow *flow = add_flow(ctx, pool, top, inline_box, FLOW_ANCHOR); - size_t len = strlen(anchor)+1; - flow->content.text = fz_pool_alloc(ctx, pool, len); - memcpy(flow->content.text, anchor, len); + (void)add_flow(ctx, pool, top, inline_box, FLOW_ANCHOR); } static fz_html_flow *split_flow(fz_context *ctx, fz_pool *pool, fz_html_flow *flow, size_t offset) @@ -425,13 +422,13 @@ static fz_image *load_html_image(fz_context *ctx, fz_archive *zip, const char *b return img; } -static void generate_anchor(fz_context *ctx, fz_html_box *box, const char *id, struct genstate *g) +static void generate_anchor(fz_context *ctx, fz_html_box *box, struct genstate *g) { fz_pool *pool = g->pool; fz_html_box *flow = box; while (flow->type != BOX_FLOW) flow = flow->up; - add_flow_anchor(ctx, pool, flow, box, id); + add_flow_anchor(ctx, pool, flow, box); } static void generate_image(fz_context *ctx, fz_html_box *box, fz_image *img, struct genstate *g) @@ -704,6 +701,10 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html_box *top, box = new_box(ctx, g->pool, child_dir); fz_apply_css_style(ctx, g->set, &box->style, &match); + id = fz_xml_att(node, "id"); + if (id) + box->id = fz_pool_strdup(ctx, g->pool, id); + if (display == DIS_BLOCK || display == DIS_INLINE_BLOCK) { top = insert_block_box(ctx, box, top); @@ -716,14 +717,13 @@ static void generate_boxes(fz_context *ctx, fz_xml *node, fz_html_box *top, else if (display == DIS_INLINE) { insert_inline_box(ctx, box, top, child_dir, g); + if (id) + generate_anchor(ctx, box, g); if (tag[0]=='a' && tag[1]==0) { - id = fz_xml_att(node, "id"); - if (id) - generate_anchor(ctx, box, id, g); href = fz_xml_att(node, "href"); if (href) - box->a_href = fz_pool_strdup(ctx, g->pool, href); + box->href = fz_pool_strdup(ctx, g->pool, href); } } @@ -1206,6 +1206,7 @@ static void layout_flow_inline(fz_context *ctx, fz_html_box *box, fz_html_box *t { while (box) { + box->y = top->y; box->em = fz_from_css_number(box->style.font_size, top->em, top->em); if (box->down) layout_flow_inline(ctx, box->down, box); @@ -1908,7 +1909,7 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea while (flow) { - href = flow->box->a_href; + href = flow->box->href; next = flow->next; if (href && (int)(flow->y / page_h) == page) { @@ -1917,8 +1918,8 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea while (next && next->y == flow->y && next->h == flow->h && - next->box->a_href && - !strcmp(href, next->box->a_href)) + next->box->href && + !strcmp(href, next->box->href)) { end = next->x + next->w; next = next->next; @@ -2187,9 +2188,10 @@ fz_print_html_box(fz_context *ctx, fz_html_box *box, int pstyle, int level) if (box->list_item) printf(" list=%d", box->list_item); - - if (box->a_href) - printf(" href='%s'", box->a_href); + if (box->id) + printf(" id='%s'", box->id); + if (box->href) + printf(" href='%s'", box->href); if (box->down || box->flow_head) printf(" {\n"); @@ -2301,7 +2303,8 @@ static void fragment_cb(const uint32_t *fragment, len = 1; } - else if (data->flow->type == FLOW_BREAK || data->flow->type == FLOW_SBREAK || data->flow->type == FLOW_SHYPHEN) + else if (data->flow->type == FLOW_BREAK || data->flow->type == FLOW_SBREAK || + data->flow->type == FLOW_SHYPHEN || data->flow->type == FLOW_ANCHOR) { len = 0; } |