diff options
author | Robin Watts <robin.watts@artifex.com> | 2016-10-07 19:56:00 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2016-10-10 15:57:46 +0100 |
commit | f22be2b82fe1afe733dd0e6c3ab9d26a39acd39b (patch) | |
tree | a56e46b0dc3d44f844e82ba03d6aba9dac1319c7 /source/html | |
parent | b2a895f639c3f98925a0ad1913bf81dc44fe221f (diff) | |
download | mupdf-f22be2b82fe1afe733dd0e6c3ab9d26a39acd39b.tar.xz |
Bug 697123: epub: Adjust anchor positions using fragments.
Diffstat (limited to 'source/html')
-rw-r--r-- | source/html/epub-doc.c | 51 |
1 files changed, 44 insertions, 7 deletions
diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index 19b8c0a8..fbcc1a86 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -34,6 +34,35 @@ struct epub_page_s int number; }; +static int +find_anchor_flow(fz_html_flow *flow, const char *anchor, float page_h, int *page) +{ + while (flow) + { + if (flow->type == FLOW_ANCHOR && !strcmp(anchor, flow->content.text)) + { + *page += (int)(flow->y / page_h); + return 1; + } + flow = flow->next; + } + return 0; +} + +static int +find_anchor(fz_html *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->down, anchor, page_h, page)) + return 1; + box = box->next; + } + return 0; +} + static void epub_update_link_dests(fz_context *ctx, epub_document *doc, fz_outline *node) { @@ -43,13 +72,24 @@ epub_update_link_dests(fz_context *ctx, epub_document *doc, fz_outline *node) { if (node->dest.kind == FZ_LINK_GOTO) { + const char *dest = node->dest.ld.gotor.dest; + const char *s = strchr(dest, '#'); + int n = s ? s - dest : strlen(dest); + if (s && s[1] == 0) + s = NULL; + for (ch = doc->spine; ch; ch = ch->next) { - if (!strcmp(ch->path, node->dest.ld.gotor.dest)) + if (strncmp(ch->path, dest, n) || ch->path[n] != 0) + continue; + node->dest.ld.gotor.page = ch->start; + if (s) { - node->dest.ld.gotor.page = ch->start; - break; + /* Search for a matching fragment */ + if (find_anchor(ch->box, s+1, ch->page_h, &node->dest.ld.gotor.page)) + continue; } + break; } } epub_update_link_dests(ctx, doc, node->down); @@ -240,7 +280,7 @@ epub_parse_chapter(fz_context *ctx, epub_document *doc, const char *path) static fz_outline * epub_parse_ncx_imp(fz_context *ctx, epub_document *doc, fz_xml *node, char *base_uri) { - char path[2048], *s; + char path[2048]; fz_outline *outline, *head, **tailp; head = NULL; @@ -258,9 +298,6 @@ epub_parse_ncx_imp(fz_context *ctx, epub_document *doc, fz_xml *node, char *base fz_strlcat(path, content, sizeof path); fz_urldecode(path); fz_cleanname(path); - s = strchr(path, '#'); - if (s) - *s = 0; *tailp = outline = fz_new_outline(ctx); tailp = &(*tailp)->next; |