diff options
author | Tor Andersson <tor.andersson@artifex.com> | 2016-11-14 13:03:07 +0100 |
---|---|---|
committer | Tor Andersson <tor.andersson@artifex.com> | 2016-11-14 13:23:57 +0100 |
commit | 2216f9402a9ddf232e15fdd508b9123011af8bd3 (patch) | |
tree | 3b4e44be0e332bb9d957864fcde41057ed0fcb79 /source | |
parent | 018253cfc8a34805c4fc1e0f955e3696db60886a (diff) | |
download | mupdf-2216f9402a9ddf232e15fdd508b9123011af8bd3.tar.xz |
Add/fix page coordinates to link targets.
Correctly transformed target coordinates for PDF.
Target coordinates for EPUB and HTML.
Diffstat (limited to 'source')
-rw-r--r-- | source/fitz/document.c | 6 | ||||
-rw-r--r-- | source/html/epub-doc.c | 10 | ||||
-rw-r--r-- | source/html/html-doc.c | 9 | ||||
-rw-r--r-- | source/pdf/pdf-annot.c | 65 | ||||
-rw-r--r-- | source/pdf/pdf-outline.c | 2 | ||||
-rw-r--r-- | source/pdf/pdf-page.c | 11 | ||||
-rw-r--r-- | source/xps/xps-doc.c | 2 | ||||
-rw-r--r-- | source/xps/xps-imp.h | 2 | ||||
-rw-r--r-- | source/xps/xps-outline.c | 2 |
9 files changed, 82 insertions, 27 deletions
diff --git a/source/fitz/document.c b/source/fitz/document.c index 87ad3884..684c8523 100644 --- a/source/fitz/document.c +++ b/source/fitz/document.c @@ -216,11 +216,13 @@ fz_load_outline(fz_context *ctx, fz_document *doc) } int -fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri) +fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri, float *xp, float *yp) { fz_ensure_layout(ctx, doc); + if (xp) *xp = 0; + if (yp) *yp = 0; if (doc && doc->resolve_link) - return doc->resolve_link(ctx, doc, uri); + return doc->resolve_link(ctx, doc, uri, xp, yp); return -1; } diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c index a30fbcd3..f5f3ca67 100644 --- a/source/html/epub-doc.c +++ b/source/html/epub-doc.c @@ -35,7 +35,7 @@ struct epub_page_s }; static int -epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest) +epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest, float *xp, float *yp) { epub_document *doc = (epub_document*)doc_; epub_chapter *ch; @@ -54,7 +54,11 @@ epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest) /* Search for a matching fragment */ float y = fz_find_html_target(ctx, ch->html, s+1); if (y >= 0) - return ch->start + y / ch->page_h; + { + int page = y / ch->page_h; + if (yp) *yp = y - page * ch->page_h; + return ch->start + page; + } } return ch->start; } @@ -68,7 +72,7 @@ epub_update_outline(fz_context *ctx, fz_document *doc, fz_outline *node) { while (node) { - node->page = epub_resolve_link(ctx, doc, node->uri); + node->page = epub_resolve_link(ctx, doc, node->uri, NULL, NULL); epub_update_outline(ctx, doc, node->down); node = node->next; } diff --git a/source/html/html-doc.c b/source/html/html-doc.c index 810b92c1..8d602030 100644 --- a/source/html/html-doc.c +++ b/source/html/html-doc.c @@ -32,16 +32,19 @@ htdoc_drop_document(fz_context *ctx, fz_document *doc_) } static int -htdoc_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest) +htdoc_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest, float *xp, float *yp) { html_document *doc = (html_document*)doc_; - const char *s = strchr(dest, '#'); if (s && s[1] != 0) { float y = fz_find_html_target(ctx, doc->html, s+1); if (y >= 0) - return y / doc->page_h; + { + int page = y / doc->page_h; + if (yp) *yp = y - page * doc->page_h; + return page; + } } return -1; diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index 44c30fe9..ec19f27a 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -40,8 +40,10 @@ char * pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest) { pdf_obj *obj; - char buf[40]; + char buf[256]; char *ld; + int page; + int x, y; dest = resolve_dest(ctx, doc, dest); if (dest == NULL) @@ -63,18 +65,34 @@ pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest) obj = pdf_array_get(ctx, dest, 0); if (pdf_is_int(ctx, obj)) + page = pdf_to_int(ctx, obj); + else + page = pdf_lookup_page_number(ctx, doc, obj); + + x = y = 0; + obj = pdf_array_get(ctx, dest, 1); + if (pdf_name_eq(ctx, obj, PDF_NAME_XYZ)) { - sprintf(buf, "#%d", pdf_to_int(ctx, obj) + 1); - return fz_strdup(ctx, buf); + x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2)); + y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 3)); } - else + else if (pdf_name_eq(ctx, obj, PDF_NAME_FitR)) { - int page = pdf_lookup_page_number(ctx, doc, obj); - if (page >= 0) - { - sprintf(buf, "#%d", page + 1); - return fz_strdup(ctx, buf); - } + x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2)); + y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 5)); + } + else if (pdf_name_eq(ctx, obj, PDF_NAME_FitH) || pdf_name_eq(ctx, obj, PDF_NAME_FitBH)) + y = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2)); + else if (pdf_name_eq(ctx, obj, PDF_NAME_FitV) || pdf_name_eq(ctx, obj, PDF_NAME_FitBV)) + x = pdf_to_int(ctx, pdf_array_get(ctx, dest, 2)); + + if (page >= 0) + { + if (x != 0 || y != 0) + fz_snprintf(buf, sizeof buf, "#%d,%d,%d", page + 1, x, y); + else + fz_snprintf(buf, sizeof buf, "#%d", page + 1); + return fz_strdup(ctx, buf); } return NULL; @@ -255,10 +273,33 @@ pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, const } int -pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri) +pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri, float *xp, float *yp) { if (uri && uri[0] == '#') - return fz_atoi(uri + 1) - 1; + { + int page = fz_atoi(uri + 1) - 1; + if (xp || yp) + { + const char *x = strchr(uri, ','); + const char *y = strrchr(uri, ','); + if (x && y) + { + pdf_obj *obj; + fz_matrix ctm; + fz_point p; + + p.x = x ? fz_atoi(x + 1) : 0; + p.y = y ? fz_atoi(y + 1) : 0; + obj = pdf_lookup_page_obj(ctx, doc, page); + pdf_page_obj_transform(ctx, obj, NULL, &ctm); + fz_transform_point(&p, &ctm); + + if (xp) *xp = p.x; + if (yp) *yp = p.y; + } + } + return page; + } fz_warn(ctx, "unknown link uri '%s'", uri); return -1; } diff --git a/source/pdf/pdf-outline.c b/source/pdf/pdf-outline.c index d82db02c..7db65153 100644 --- a/source/pdf/pdf-outline.c +++ b/source/pdf/pdf-outline.c @@ -33,7 +33,7 @@ pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict) else node->uri = NULL; - node->page = pdf_resolve_link(ctx, doc, node->uri); + node->page = pdf_resolve_link(ctx, doc, node->uri, NULL, NULL); obj = pdf_dict_get(ctx, dict, PDF_NAME_First); if (obj) diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index e3c78877..89b62005 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -215,7 +215,7 @@ pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name) fz_rethrow(ctx); uri = pdf_parse_link_dest(ctx, doc, dest); - return pdf_resolve_link(ctx, doc, uri); + return pdf_resolve_link(ctx, doc, uri, NULL, NULL); } static pdf_obj * @@ -443,9 +443,8 @@ pdf_page_contents(fz_context *ctx, pdf_page *page) } void -pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *page_mediabox, fz_matrix *page_ctm) +pdf_page_obj_transform(fz_context *ctx, pdf_obj *pageobj, fz_rect *page_mediabox, fz_matrix *page_ctm) { - pdf_obj *pageobj = page->obj; pdf_obj *obj; fz_rect mediabox, cropbox, realbox, pagebox; fz_matrix tmp; @@ -507,6 +506,12 @@ pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *page_mediabox, fz_m fz_concat(page_ctm, page_ctm, &tmp); } +void +pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *page_mediabox, fz_matrix *page_ctm) +{ + return pdf_page_obj_transform(ctx, page->obj, page_mediabox, page_ctm); +} + static void pdf_drop_page_imp(fz_context *ctx, pdf_page *page) { diff --git a/source/xps/xps-doc.c b/source/xps/xps-doc.c index d530bdbd..8197f505 100644 --- a/source/xps/xps-doc.c +++ b/source/xps/xps-doc.c @@ -124,7 +124,7 @@ xps_add_link_target(fz_context *ctx, xps_document *doc, char *name) } int -xps_lookup_link_target(fz_context *ctx, xps_document *doc, char *target_uri) +xps_lookup_link_target(fz_context *ctx, xps_document *doc, char *target_uri, float *xp, float *yp) { xps_target *target; char *needle = strrchr(target_uri, '#'); diff --git a/source/xps/xps-imp.h b/source/xps/xps-imp.h index 4f21fb95..2ba78a50 100644 --- a/source/xps/xps-imp.h +++ b/source/xps/xps-imp.h @@ -105,7 +105,7 @@ void xps_read_page_list(fz_context *ctx, xps_document *doc); void xps_print_page_list(fz_context *ctx, xps_document *doc); void xps_drop_page_list(fz_context *ctx, xps_document *doc); -int xps_lookup_link_target(fz_context *ctx, xps_document *doc, char *target_uri); +int xps_lookup_link_target(fz_context *ctx, xps_document *doc, char *target_uri, float *xp, float *yp); /* * Images, fonts, and colorspaces. diff --git a/source/xps/xps-outline.c b/source/xps/xps-outline.c index 1fe294fb..bcb16509 100644 --- a/source/xps/xps-outline.c +++ b/source/xps/xps-outline.c @@ -34,7 +34,7 @@ xps_parse_document_outline(fz_context *ctx, xps_document *doc, fz_xml *root) entry = fz_new_outline(ctx); entry->title = fz_strdup(ctx, description); entry->uri = fz_strdup(ctx, target); - entry->page = xps_lookup_link_target(ctx, doc, target); + entry->page = xps_lookup_link_target(ctx, doc, target, NULL, NULL); entry->down = NULL; entry->next = NULL; |