summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-11-14 13:03:07 +0100
committerTor Andersson <tor.andersson@artifex.com>2016-11-14 13:23:57 +0100
commit2216f9402a9ddf232e15fdd508b9123011af8bd3 (patch)
tree3b4e44be0e332bb9d957864fcde41057ed0fcb79
parent018253cfc8a34805c4fc1e0f955e3696db60886a (diff)
downloadmupdf-2216f9402a9ddf232e15fdd508b9123011af8bd3.tar.xz
Add/fix page coordinates to link targets.
Correctly transformed target coordinates for PDF. Target coordinates for EPUB and HTML.
-rw-r--r--include/mupdf/fitz/document.h6
-rw-r--r--include/mupdf/pdf/annot.h2
-rw-r--r--include/mupdf/pdf/page.h1
-rw-r--r--platform/android/viewer/jni/mupdf.c2
-rw-r--r--platform/gl/gl-main.c2
-rw-r--r--platform/java/mupdf_native.c4
-rw-r--r--platform/x11/pdfapp.c2
-rw-r--r--source/fitz/document.c6
-rw-r--r--source/html/epub-doc.c10
-rw-r--r--source/html/html-doc.c9
-rw-r--r--source/pdf/pdf-annot.c65
-rw-r--r--source/pdf/pdf-outline.c2
-rw-r--r--source/pdf/pdf-page.c11
-rw-r--r--source/xps/xps-doc.c2
-rw-r--r--source/xps/xps-imp.h2
-rw-r--r--source/xps/xps-outline.c2
16 files changed, 93 insertions, 35 deletions
diff --git a/include/mupdf/fitz/document.h b/include/mupdf/fitz/document.h
index d8123a00..105692e6 100644
--- a/include/mupdf/fitz/document.h
+++ b/include/mupdf/fitz/document.h
@@ -32,7 +32,7 @@ typedef int (fz_document_authenticate_password_fn)(fz_context *ctx, fz_document
typedef int (fz_document_has_permission_fn)(fz_context *ctx, fz_document *doc, fz_permission permission);
typedef fz_outline *(fz_document_load_outline_fn)(fz_context *ctx, fz_document *doc);
typedef void (fz_document_layout_fn)(fz_context *ctx, fz_document *doc, float w, float h, float em);
-typedef int (fz_document_resolve_link_fn)(fz_context *ctx, fz_document *doc, const char *uri);
+typedef int (fz_document_resolve_link_fn)(fz_context *ctx, fz_document *doc, const char *uri, float *xp, float *yp);
typedef int (fz_document_count_pages_fn)(fz_context *ctx, fz_document *doc);
typedef fz_page *(fz_document_load_page_fn)(fz_context *ctx, fz_document *doc, int number);
typedef int (fz_document_lookup_metadata_fn)(fz_context *ctx, fz_document *doc, const char *key, char *buf, int size);
@@ -214,9 +214,11 @@ int fz_count_pages(fz_context *ctx, fz_document *doc);
/*
fz_resolve_link: Resolve an internal link to a page number.
+ xp, yp: Pointer to store coordinate of destination on the page.
+
Returns -1 if the URI cannot be resolved.
*/
-int fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri);
+int fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri, float *xp, float *yp);
/*
fz_load_page: Load a page.
diff --git a/include/mupdf/pdf/annot.h b/include/mupdf/pdf/annot.h
index caaa9047..49ae9246 100644
--- a/include/mupdf/pdf/annot.h
+++ b/include/mupdf/pdf/annot.h
@@ -108,7 +108,7 @@ pdf_obj *pdf_lookup_dest(fz_context *ctx, pdf_document *doc, pdf_obj *needle);
pdf_obj *pdf_lookup_name(fz_context *ctx, pdf_document *doc, pdf_obj *which, pdf_obj *needle);
pdf_obj *pdf_load_name_tree(fz_context *ctx, pdf_document *doc, pdf_obj *which);
-int pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri);
+int pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri, float *xp, float *yp);
fz_link *pdf_load_link_annots(fz_context *ctx, pdf_document *, pdf_obj *annots, const fz_matrix *page_ctm);
void pdf_annot_transform(fz_context *ctx, pdf_annot *annot, fz_matrix *annot_ctm);
diff --git a/include/mupdf/pdf/page.h b/include/mupdf/pdf/page.h
index 407fcc09..bae9193f 100644
--- a/include/mupdf/pdf/page.h
+++ b/include/mupdf/pdf/page.h
@@ -34,6 +34,7 @@ void pdf_flatten_inheritable_page_items(fz_context *ctx, pdf_obj *page);
pdf_page *pdf_load_page(fz_context *ctx, pdf_document *doc, int number);
void pdf_drop_page(fz_context *ctx, pdf_page *page);
+void pdf_page_obj_transform(fz_context *ctx, pdf_obj *pageobj, fz_rect *page_mediabox, fz_matrix *page_ctm);
void pdf_page_transform(fz_context *ctx, pdf_page *page, fz_rect *mediabox, fz_matrix *ctm);
pdf_obj *pdf_page_resources(fz_context *ctx, pdf_page *page);
pdf_obj *pdf_page_contents(fz_context *ctx, pdf_page *page);
diff --git a/platform/android/viewer/jni/mupdf.c b/platform/android/viewer/jni/mupdf.c
index 895f6912..236efbf2 100644
--- a/platform/android/viewer/jni/mupdf.c
+++ b/platform/android/viewer/jni/mupdf.c
@@ -1903,7 +1903,7 @@ JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumbe
{
linkInfo = (*env)->NewObject(env, linkInfoInternalClass, ctorInternal,
(float)rect.x0, (float)rect.y0, (float)rect.x1, (float)rect.y1,
- fz_resolve_link(glo->ctx, link->doc, link->uri));
+ fz_resolve_link(glo->ctx, link->doc, link->uri, NULL, NULL));
}
else
{
diff --git a/platform/gl/gl-main.c b/platform/gl/gl-main.c
index 2a46e1b1..557d616a 100644
--- a/platform/gl/gl-main.c
+++ b/platform/gl/gl-main.c
@@ -589,7 +589,7 @@ static void do_links(fz_link *link, int xofs, int yofs)
if (fz_is_external_link(ctx, link->uri))
open_browser(link->uri);
else
- jump_to_page(fz_resolve_link(ctx, doc, link->uri));
+ jump_to_page(fz_resolve_link(ctx, doc, link->uri, NULL, NULL));
}
ui_needs_update = 1;
}
diff --git a/platform/java/mupdf_native.c b/platform/java/mupdf_native.c
index 537646a6..843a79dc 100644
--- a/platform/java/mupdf_native.c
+++ b/platform/java/mupdf_native.c
@@ -1031,7 +1031,7 @@ static inline jobject to_Outline_safe(fz_context *ctx, JNIEnv *env, fz_document
if (!juri) return NULL;
}
else
- jpage = fz_resolve_link(ctx, doc, outline->uri);
+ jpage = fz_resolve_link(ctx, doc, outline->uri, NULL, NULL);
if (outline->down)
{
@@ -4564,7 +4564,7 @@ FUN(Page_getLinks)(JNIEnv *env, jobject self)
if (!juri) return NULL;
}
else
- page = fz_resolve_link(ctx, link->doc, link->uri);
+ page = fz_resolve_link(ctx, link->doc, link->uri, NULL, NULL);
jlink = (*env)->NewObject(env, cls_Link, mid_Link_init, jbounds, page, juri);
(*env)->DeleteLocalRef(env, jbounds);
diff --git a/platform/x11/pdfapp.c b/platform/x11/pdfapp.c
index 19983ee9..58a50db5 100644
--- a/platform/x11/pdfapp.c
+++ b/platform/x11/pdfapp.c
@@ -1740,7 +1740,7 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta
if (fz_is_external_link(ctx, link->uri))
pdfapp_gotouri(app, link->uri);
else
- pdfapp_gotopage(app, fz_resolve_link(ctx, app->doc, link->uri) + 1);
+ pdfapp_gotopage(app, fz_resolve_link(ctx, app->doc, link->uri, NULL, NULL) + 1);
return;
}
}
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;