summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
Diffstat (limited to 'source')
-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
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;