summaryrefslogtreecommitdiff
path: root/source
diff options
context:
space:
mode:
authorTor Andersson <tor.andersson@artifex.com>2016-10-17 17:13:32 +0200
committerTor Andersson <tor.andersson@artifex.com>2016-10-28 16:18:38 +0200
commit8a07b7fb14f11204a0d840792ab9f4bd54b066e5 (patch)
treee617a898c17aeb353f35d7b362ca2de290cf2b82 /source
parent4029b45e494634361a4205f8896ec429d11e990a (diff)
downloadmupdf-8a07b7fb14f11204a0d840792ab9f4bd54b066e5.tar.xz
Clean up link destination handling.
All link destinations should be URIs, and a document specific function can be called to resolve them to actual page numbers. Outlines have cached page numbers as well as string URIs.
Diffstat (limited to 'source')
-rw-r--r--source/fitz/document.c9
-rw-r--r--source/fitz/link.c58
-rw-r--r--source/fitz/outline.c6
-rw-r--r--source/html/epub-doc.c48
-rw-r--r--source/html/html-layout.c14
-rw-r--r--source/pdf/pdf-annot.c272
-rw-r--r--source/pdf/pdf-outline.c8
-rw-r--r--source/pdf/pdf-page.c6
-rw-r--r--source/pdf/pdf-xref.c1
-rw-r--r--source/tools/murun.c29
-rw-r--r--source/xps/xps-link.c18
-rw-r--r--source/xps/xps-outline.c5
-rw-r--r--source/xps/xps-zip.c1
13 files changed, 162 insertions, 313 deletions
diff --git a/source/fitz/document.c b/source/fitz/document.c
index 43fcb133..87ad3884 100644
--- a/source/fitz/document.c
+++ b/source/fitz/document.c
@@ -215,6 +215,15 @@ fz_load_outline(fz_context *ctx, fz_document *doc)
return NULL;
}
+int
+fz_resolve_link(fz_context *ctx, fz_document *doc, const char *uri)
+{
+ fz_ensure_layout(ctx, doc);
+ if (doc && doc->resolve_link)
+ return doc->resolve_link(ctx, doc, uri);
+ return -1;
+}
+
void
fz_layout_document(fz_context *ctx, fz_document *doc, float w, float h, float em)
{
diff --git a/source/fitz/link.c b/source/fitz/link.c
index eaed1402..430c9bfe 100644
--- a/source/fitz/link.c
+++ b/source/fitz/link.c
@@ -1,51 +1,25 @@
#include "mupdf/fitz.h"
-void
-fz_drop_link_dest(fz_context *ctx, fz_link_dest *dest)
-{
- if (!dest)
- return;
-
- switch (dest->kind)
- {
- case FZ_LINK_NONE:
- break;
- case FZ_LINK_GOTO:
- fz_free(ctx, dest->ld.gotor.dest);
- break;
- case FZ_LINK_URI:
- fz_free(ctx, dest->ld.uri.uri);
- break;
- case FZ_LINK_LAUNCH:
- fz_free(ctx, dest->ld.launch.file_spec);
- break;
- case FZ_LINK_NAMED:
- fz_free(ctx, dest->ld.named.named);
- break;
- case FZ_LINK_GOTOR:
- fz_free(ctx, dest->ld.gotor.file_spec);
- break;
- }
-}
-
fz_link *
-fz_new_link(fz_context *ctx, const fz_rect *bbox, fz_link_dest dest)
+fz_new_link(fz_context *ctx, const fz_rect *bbox, void *doc, const char *uri)
{
fz_link *link;
+ link = fz_malloc_struct(ctx, fz_link);
+ link->refs = 1;
+ link->rect = *bbox;
+ link->next = NULL;
+ link->doc = doc; /* don't take reference */
+ link->uri = NULL;
+
fz_try(ctx)
- {
- link = fz_malloc_struct(ctx, fz_link);
- link->refs = 1;
- }
+ link->uri = fz_strdup(ctx, uri);
fz_catch(ctx)
{
- fz_drop_link_dest(ctx, &dest);
+ fz_drop_link(ctx, link);
fz_rethrow(ctx);
}
- link->dest = dest;
- link->rect = *bbox;
- link->next = NULL;
+
return link;
}
@@ -61,8 +35,16 @@ fz_drop_link(fz_context *ctx, fz_link *link)
while (fz_drop_imp(ctx, link, &link->refs))
{
fz_link *next = link->next;
- fz_drop_link_dest(ctx, &link->dest);
+ fz_free(ctx, link->uri);
fz_free(ctx, link);
link = next;
}
}
+
+int
+fz_is_external_link(fz_context *ctx, const char *uri)
+{
+ while (*uri >= 'a' && *uri <= 'z')
+ ++uri;
+ return uri[0] == ':' && uri[1] == '/' && uri[2] == '/';
+}
diff --git a/source/fitz/outline.c b/source/fitz/outline.c
index 257c44c1..888212bc 100644
--- a/source/fitz/outline.c
+++ b/source/fitz/outline.c
@@ -22,7 +22,7 @@ fz_drop_outline(fz_context *ctx, fz_outline *outline)
fz_outline *next = outline->next;
fz_drop_outline(ctx, outline->down);
fz_free(ctx, outline->title);
- fz_drop_link_dest(ctx, &outline->dest);
+ fz_free(ctx, outline->uri);
fz_free(ctx, outline);
outline = next;
}
@@ -33,7 +33,7 @@ fz_debug_outline_xml_imp(fz_context *ctx, fz_output *out, fz_outline *outline, i
{
while (outline)
{
- fz_printf(ctx, out, "<outline title=%q page=\"%d\"", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
+ fz_printf(ctx, out, "<outline title=%q uri=\"%s\"", outline->title, outline->uri);
if (outline->down)
{
fz_printf(ctx, out, ">\n");
@@ -62,7 +62,7 @@ fz_print_outline_imp(fz_context *ctx, fz_output *out, fz_outline *outline, int l
{
for (i = 0; i < level; i++)
fz_printf(ctx, out, "\t");
- fz_printf(ctx, out, "%s\t%d\n", outline->title, outline->dest.kind == FZ_LINK_GOTO ? outline->dest.ld.gotor.page + 1 : 0);
+ fz_printf(ctx, out, "%s\t%s\n", outline->title, outline->uri);
if (outline->down)
fz_print_outline_imp(ctx, out, outline->down, level + 1);
outline = outline->next;
diff --git a/source/html/epub-doc.c b/source/html/epub-doc.c
index efc4ac18..0616bb70 100644
--- a/source/html/epub-doc.c
+++ b/source/html/epub-doc.c
@@ -63,41 +63,40 @@ find_anchor_box(fz_html_box *box, const char *anchor, float page_h, int *page)
return 0;
}
-static void
-resolve_link_dest(fz_context *ctx, epub_document *doc, fz_link_dest *ld)
+static int
+epub_resolve_link(fz_context *ctx, fz_document *doc_, const char *dest)
{
+ epub_document *doc = (epub_document*)doc_;
epub_chapter *ch;
+ int page = -1;
- if (ld->kind == FZ_LINK_GOTO)
- {
- const char *dest = ld->ld.gotor.dest;
- const char *s = strchr(dest, '#');
- int n = s ? s - dest : strlen(dest);
- if (s && s[1] == 0)
- s = NULL;
+ 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)
+ for (ch = doc->spine; ch; ch = ch->next)
+ {
+ if (!strncmp(ch->path, dest, n) && ch->path[n] == 0)
{
- if (strncmp(ch->path, dest, n) || ch->path[n] != 0)
- continue;
- ld->ld.gotor.page = ch->start;
+ page = ch->start;
if (s)
{
/* Search for a matching fragment */
- if (find_anchor_box(ch->html->root, s+1, ch->page_h, &ld->ld.gotor.page))
- continue;
+ find_anchor_box(ch->html->root, s+1, ch->page_h, &page);
}
- break;
}
}
+
+ return page;
}
static void
-epub_update_outline(fz_context *ctx, epub_document *doc, fz_outline *node)
+epub_update_outline(fz_context *ctx, fz_document *doc, fz_outline *node)
{
while (node)
{
- resolve_link_dest(ctx, doc, &node->dest);
+ node->page = epub_resolve_link(ctx, doc, node->uri);
epub_update_outline(ctx, doc, node->down);
node = node->next;
}
@@ -124,7 +123,7 @@ epub_layout(fz_context *ctx, fz_document *doc_, float w, float h, float em)
count += ceilf(ch->html->root->h / ch->page_h);
}
- epub_update_outline(ctx, doc, doc->outline);
+ epub_update_outline(ctx, doc_, doc->outline);
}
static int
@@ -211,14 +210,13 @@ epub_load_links(fz_context *ctx, fz_page *page_)
head = fz_load_html_links(ctx, ch->html, n - count, ch->page_h, ch->path);
for (link = head; link; link = link->next)
{
+ link->doc = doc;
+
/* Adjust for page margins */
link->rect.x0 += ch->page_margin[L];
link->rect.x1 += ch->page_margin[L];
link->rect.y0 += ch->page_margin[T];
link->rect.y1 += ch->page_margin[T];
-
- /* Resolve local links */
- resolve_link_dest(ctx, doc, &link->dest);
}
return head;
}
@@ -343,9 +341,8 @@ epub_parse_ncx_imp(fz_context *ctx, epub_document *doc, fz_xml *node, char *base
*tailp = outline = fz_new_outline(ctx);
tailp = &(*tailp)->next;
outline->title = fz_strdup(ctx, text);
- outline->dest.kind = FZ_LINK_GOTO;
- outline->dest.ld.gotor.dest = fz_strdup(ctx, path);
- outline->dest.ld.gotor.page = 0; /* computed in epub_layout */
+ outline->uri = fz_strdup(ctx, path);
+ outline->page = -1;
outline->down = epub_parse_ncx_imp(ctx, doc, node, base_uri);
}
node = fz_xml_find_next(node, "navPoint");
@@ -494,6 +491,7 @@ epub_init(fz_context *ctx, fz_archive *zip)
doc->super.drop_document = epub_drop_document;
doc->super.layout = epub_layout;
doc->super.load_outline = epub_load_outline;
+ doc->super.resolve_link = epub_resolve_link;
doc->super.count_pages = epub_count_pages;
doc->super.load_page = epub_load_page;
doc->super.lookup_metadata = epub_lookup_metadata;
diff --git a/source/html/html-layout.c b/source/html/html-layout.c
index 54a96c1d..b700b59b 100644
--- a/source/html/html-layout.c
+++ b/source/html/html-layout.c
@@ -1902,7 +1902,7 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea
fz_html_flow *next;
char path[2048];
fz_rect bbox;
- fz_link_dest dest;
+ char *dest;
char *href;
float end;
@@ -1951,20 +1951,14 @@ static fz_link *load_link_flow(fz_context *ctx, fz_html_flow *flow, fz_link *hea
fz_urldecode(path);
fz_cleanname(path);
- memset(&dest, 0, sizeof dest);
- dest.kind = FZ_LINK_GOTO;
- dest.ld.gotor.dest = fz_strdup(ctx, path);
- dest.ld.gotor.page = 0; /* computed in epub_load_links */
+ dest = path;
}
else
{
- memset(&dest, 0, sizeof dest);
- dest.kind = FZ_LINK_URI;
- dest.ld.uri.uri = fz_strdup(ctx, href);
- dest.ld.uri.is_map = 0;
+ dest = href;
}
- link = fz_new_link(ctx, &bbox, dest);
+ link = fz_new_link(ctx, &bbox, NULL, dest);
link->next = head;
head = link;
}
diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c
index a0220099..44c30fe9 100644
--- a/source/pdf/pdf-annot.c
+++ b/source/pdf/pdf-annot.c
@@ -1,19 +1,15 @@
#include "mupdf/pdf.h"
static pdf_obj *
-resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind kind, int depth)
+resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, int depth)
{
if (depth > 10) /* Arbitrary to avoid infinite recursion */
return NULL;
if (pdf_is_name(ctx, dest) || pdf_is_string(ctx, dest))
{
- if (kind == FZ_LINK_GOTO)
- {
- dest = pdf_lookup_dest(ctx, doc, dest);
- dest = resolve_dest_rec(ctx, doc, dest, kind, depth+1);
- }
-
+ dest = pdf_lookup_dest(ctx, doc, dest);
+ dest = resolve_dest_rec(ctx, doc, dest, depth+1);
return dest;
}
@@ -25,7 +21,7 @@ resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind
else if (pdf_is_dict(ctx, dest))
{
dest = pdf_dict_get(ctx, dest, PDF_NAME_D);
- return resolve_dest_rec(ctx, doc, dest, kind, depth+1);
+ return resolve_dest_rec(ctx, doc, dest, depth+1);
}
else if (pdf_is_indirect(ctx, dest))
@@ -35,193 +31,63 @@ resolve_dest_rec(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind
}
static pdf_obj *
-resolve_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest, fz_link_kind kind)
+resolve_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest)
{
- return resolve_dest_rec(ctx, doc, dest, kind, 0);
+ return resolve_dest_rec(ctx, doc, dest, 0);
}
-fz_link_dest
-pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, fz_link_kind kind, pdf_obj *dest)
+char *
+pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *dest)
{
- fz_link_dest ld;
pdf_obj *obj;
+ char buf[40];
+ char *ld;
- int l_from_2 = 0;
- int b_from_3 = 0;
- int r_from_4 = 0;
- int t_from_5 = 0;
- int t_from_3 = 0;
- int t_from_2 = 0;
- int z_from_4 = 0;
-
- ld.kind = kind;
- ld.ld.gotor.flags = 0;
- ld.ld.gotor.lt.x = 0;
- ld.ld.gotor.lt.y = 0;
- ld.ld.gotor.rb.x = 0;
- ld.ld.gotor.rb.y = 0;
- ld.ld.gotor.page = -1;
- ld.ld.gotor.dest = NULL;
-
- dest = resolve_dest(ctx, doc, dest, kind);
+ dest = resolve_dest(ctx, doc, dest);
if (dest == NULL)
{
fz_warn(ctx, "undefined link destination");
- return ld;
+ return NULL;
}
if (pdf_is_name(ctx, dest))
{
- ld.ld.gotor.dest = pdf_to_name(ctx, dest);
- return ld;
+ ld = pdf_to_name(ctx, dest);
+ return fz_strdup(ctx, ld);
}
else if (pdf_is_string(ctx, dest))
{
- ld.ld.gotor.dest = pdf_to_str_buf(ctx, dest);
- return ld;
+ ld = pdf_to_str_buf(ctx, dest);
+ return fz_strdup(ctx, ld);
}
obj = pdf_array_get(ctx, dest, 0);
if (pdf_is_int(ctx, obj))
- ld.ld.gotor.page = pdf_to_int(ctx, obj);
- else
- {
- fz_try(ctx)
- {
- ld.ld.gotor.page = pdf_lookup_page_number(ctx, doc, obj);
- }
- fz_catch(ctx)
- {
- ld.kind = FZ_LINK_NONE;
- return ld;
- }
- }
-
- obj = pdf_array_get(ctx, dest, 1);
- if (!pdf_is_name(ctx, obj))
- return ld;
-
- if (pdf_name_eq(ctx, PDF_NAME_XYZ, obj))
- {
- l_from_2 = t_from_3 = z_from_4 = 1;
- ld.ld.gotor.flags |= fz_link_flag_r_is_zoom;
- }
- else if ((pdf_name_eq(ctx, PDF_NAME_Fit, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitB, obj)))
{
- ld.ld.gotor.flags |= fz_link_flag_fit_h;
- ld.ld.gotor.flags |= fz_link_flag_fit_v;
+ sprintf(buf, "#%d", pdf_to_int(ctx, obj) + 1);
+ return fz_strdup(ctx, buf);
}
- else if ((pdf_name_eq(ctx, PDF_NAME_FitH, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitBH, obj)))
- {
- t_from_2 = 1;
- ld.ld.gotor.flags |= fz_link_flag_fit_h;
- }
- else if ((pdf_name_eq(ctx, PDF_NAME_FitV, obj)) || (pdf_name_eq(ctx, PDF_NAME_FitBV, obj)))
- {
- l_from_2 = 1;
- ld.ld.gotor.flags |= fz_link_flag_fit_v;
- }
- else if (pdf_name_eq(ctx, PDF_NAME_FitR, obj))
- {
- l_from_2 = b_from_3 = r_from_4 = t_from_5 = 1;
- ld.ld.gotor.flags |= fz_link_flag_fit_h;
- ld.ld.gotor.flags |= fz_link_flag_fit_v;
- }
-
- if (l_from_2)
- {
- obj = pdf_array_get(ctx, dest, 2);
- if (pdf_is_int(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_l_valid;
- ld.ld.gotor.lt.x = pdf_to_int(ctx, obj);
- }
- else if (pdf_is_real(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_l_valid;
- ld.ld.gotor.lt.x = pdf_to_real(ctx, obj);
- }
- }
- if (b_from_3)
- {
- obj = pdf_array_get(ctx, dest, 3);
- if (pdf_is_int(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_b_valid;
- ld.ld.gotor.rb.y = pdf_to_int(ctx, obj);
- }
- else if (pdf_is_real(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_b_valid;
- ld.ld.gotor.rb.y = pdf_to_real(ctx, obj);
- }
- }
- if (r_from_4)
- {
- obj = pdf_array_get(ctx, dest, 4);
- if (pdf_is_int(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_r_valid;
- ld.ld.gotor.rb.x = pdf_to_int(ctx, obj);
- }
- else if (pdf_is_real(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_r_valid;
- ld.ld.gotor.rb.x = pdf_to_real(ctx, obj);
- }
- }
- if (t_from_5 || t_from_3 || t_from_2)
- {
- if (t_from_5)
- obj = pdf_array_get(ctx, dest, 5);
- else if (t_from_3)
- obj = pdf_array_get(ctx, dest, 3);
- else
- obj = pdf_array_get(ctx, dest, 2);
- if (pdf_is_int(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_t_valid;
- ld.ld.gotor.lt.y = pdf_to_int(ctx, obj);
- }
- else if (pdf_is_real(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_t_valid;
- ld.ld.gotor.lt.y = pdf_to_real(ctx, obj);
- }
- }
- if (z_from_4)
+ else
{
- obj = pdf_array_get(ctx, dest, 4);
- if (pdf_is_int(ctx, obj))
+ int page = pdf_lookup_page_number(ctx, doc, obj);
+ if (page >= 0)
{
- ld.ld.gotor.flags |= fz_link_flag_r_valid;
- ld.ld.gotor.rb.x = pdf_to_int(ctx, obj);
- }
- else if (pdf_is_real(ctx, obj))
- {
- ld.ld.gotor.flags |= fz_link_flag_r_valid;
- ld.ld.gotor.rb.x = pdf_to_real(ctx, obj);
+ sprintf(buf, "#%d", page + 1);
+ return fz_strdup(ctx, buf);
}
}
- /* Duplicate the values out for the sake of stupid clients */
- if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid)) == fz_link_flag_l_valid)
- ld.ld.gotor.rb.x = ld.ld.gotor.lt.x;
- if ((ld.ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid | fz_link_flag_r_is_zoom)) == fz_link_flag_r_valid)
- ld.ld.gotor.lt.x = ld.ld.gotor.rb.x;
- if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_t_valid)
- ld.ld.gotor.rb.y = ld.ld.gotor.lt.y;
- if ((ld.ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_b_valid)
- ld.ld.gotor.lt.y = ld.ld.gotor.rb.y;
-
- return ld;
+ return NULL;
}
char *
-pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec)
+pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_obj *dest)
{
pdf_obj *filename=NULL;
char *path = NULL;
+ char *uri = NULL;
+ char buf[256];
+ size_t n;
if (pdf_is_string(ctx, file_spec))
filename = file_spec;
@@ -260,54 +126,56 @@ pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec)
}
}
#endif
- return path;
+
+ if (pdf_is_array(ctx, dest))
+ fz_snprintf(buf, sizeof buf, "#%d", pdf_to_int(ctx, pdf_array_get(ctx, dest, 0)) + 1);
+ else if (pdf_is_name(ctx, dest))
+ fz_snprintf(buf, sizeof buf, "#%s", pdf_to_name(ctx, dest));
+ else if (pdf_is_stream(ctx, dest))
+ fz_snprintf(buf, sizeof buf, "#%s", pdf_to_str_buf(ctx, dest));
+ else
+ buf[0] = 0;
+
+ n = 7 + strlen(path) + strlen(buf) + 1;
+ uri = fz_malloc(ctx, n);
+ fz_strlcpy(uri, "file://", n);
+ fz_strlcat(uri, path, n);
+ fz_strlcat(uri, buf, n);
+ fz_free(ctx, path);
+ return uri;
}
-fz_link_dest
-pdf_parse_action(fz_context *ctx, pdf_document *doc, pdf_obj *action)
+char *
+pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action)
{
- fz_link_dest ld;
pdf_obj *obj, *dest, *file_spec;
- ld.kind = FZ_LINK_NONE;
-
if (!action)
- return ld;
+ return NULL;
obj = pdf_dict_get(ctx, action, PDF_NAME_S);
if (pdf_name_eq(ctx, PDF_NAME_GoTo, obj))
{
dest = pdf_dict_get(ctx, action, PDF_NAME_D);
- ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, dest);
+ return pdf_parse_link_dest(ctx, doc, dest);
}
else if (pdf_name_eq(ctx, PDF_NAME_URI, obj))
{
- ld.kind = FZ_LINK_URI;
- ld.ld.uri.is_map = pdf_to_bool(ctx, pdf_dict_get(ctx, action, PDF_NAME_IsMap));
- ld.ld.uri.uri = pdf_to_utf8(ctx, pdf_dict_get(ctx, action, PDF_NAME_URI));
+ return pdf_to_utf8(ctx, pdf_dict_get(ctx, action, PDF_NAME_URI));
}
else if (pdf_name_eq(ctx, PDF_NAME_Launch, obj))
{
- ld.kind = FZ_LINK_LAUNCH;
file_spec = pdf_dict_get(ctx, action, PDF_NAME_F);
- ld.ld.launch.file_spec = pdf_parse_file_spec(ctx, doc, file_spec);
- ld.ld.launch.new_window = pdf_to_int(ctx, pdf_dict_get(ctx, action, PDF_NAME_NewWindow));
- ld.ld.launch.is_uri = pdf_name_eq(ctx, PDF_NAME_URL, pdf_dict_get(ctx, file_spec, PDF_NAME_FS));
- }
- else if (pdf_name_eq(ctx, PDF_NAME_Named, obj))
- {
- ld.kind = FZ_LINK_NAMED;
- ld.ld.named.named = fz_strdup(ctx, pdf_to_name(ctx, pdf_dict_get(ctx, action, PDF_NAME_N)));
+ return pdf_parse_file_spec(ctx, doc, file_spec, NULL);
}
else if (pdf_name_eq(ctx, PDF_NAME_GoToR, obj))
{
dest = pdf_dict_get(ctx, action, PDF_NAME_D);
file_spec = pdf_dict_get(ctx, action, PDF_NAME_F);
- ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTOR, dest);
- ld.ld.gotor.file_spec = pdf_parse_file_spec(ctx, doc, file_spec);
- ld.ld.gotor.new_window = pdf_to_int(ctx, pdf_dict_get(ctx, action, PDF_NAME_NewWindow));
+ return pdf_parse_file_spec(ctx, doc, file_spec, dest);
}
- return ld;
+
+ return NULL;
}
static fz_link *
@@ -316,31 +184,34 @@ pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, const fz_matrix
pdf_obj *action;
pdf_obj *obj;
fz_rect bbox;
- fz_link_dest ld;
+ char *uri;
+ fz_link *link;
obj = pdf_dict_get(ctx, dict, PDF_NAME_Rect);
- if (obj)
- pdf_to_rect(ctx, obj, &bbox);
- else
- bbox = fz_empty_rect;
+ if (!obj)
+ return NULL;
+ pdf_to_rect(ctx, obj, &bbox);
fz_transform_rect(&bbox, page_ctm);
obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest);
if (obj)
- ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, obj);
+ uri = pdf_parse_link_dest(ctx, doc, obj);
else
{
action = pdf_dict_get(ctx, dict, PDF_NAME_A);
/* fall back to additional action button's down/up action */
if (!action)
action = pdf_dict_geta(ctx, pdf_dict_get(ctx, dict, PDF_NAME_AA), PDF_NAME_U, PDF_NAME_D);
-
- ld = pdf_parse_action(ctx, doc, action);
+ uri = pdf_parse_link_action(ctx, doc, action);
}
- if (ld.kind == FZ_LINK_NONE)
+
+ if (!uri)
return NULL;
- return fz_new_link(ctx, &bbox, ld);
+
+ link = fz_new_link(ctx, &bbox, doc, uri);
+ fz_free(ctx, uri);
+ return link;
}
fz_link *
@@ -383,6 +254,15 @@ pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, const
return head;
}
+int
+pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri)
+{
+ if (uri && uri[0] == '#')
+ return fz_atoi(uri + 1) - 1;
+ fz_warn(ctx, "unknown link uri '%s'", uri);
+ return -1;
+}
+
static void
pdf_drop_annot_imp(fz_context *ctx, pdf_annot *annot)
{
diff --git a/source/pdf/pdf-outline.c b/source/pdf/pdf-outline.c
index c9fd35fe..d82db02c 100644
--- a/source/pdf/pdf-outline.c
+++ b/source/pdf/pdf-outline.c
@@ -27,9 +27,13 @@ pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict)
node->title = pdf_to_utf8(ctx, obj);
if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest)) != NULL)
- node->dest = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, obj);
+ node->uri = pdf_parse_link_dest(ctx, doc, obj);
else if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_A)) != NULL)
- node->dest = pdf_parse_action(ctx, doc, obj);
+ node->uri = pdf_parse_link_action(ctx, doc, obj);
+ else
+ node->uri = NULL;
+
+ node->page = pdf_resolve_link(ctx, doc, node->uri);
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 0cfb5dae..7c7005e3 100644
--- a/source/pdf/pdf-page.c
+++ b/source/pdf/pdf-page.c
@@ -204,7 +204,7 @@ int
pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name)
{
pdf_obj *needle, *dest;
- fz_link_dest ld;
+ char *uri;
needle = pdf_new_string(ctx, doc, name, strlen(name));
fz_try(ctx)
@@ -214,8 +214,8 @@ pdf_lookup_anchor(fz_context *ctx, pdf_document *doc, const char *name)
fz_catch(ctx)
fz_rethrow(ctx);
- ld = pdf_parse_link_dest(ctx, doc, FZ_LINK_GOTO, dest);
- return ld.ld.gotor.page;
+ uri = pdf_parse_link_dest(ctx, doc, dest);
+ return pdf_resolve_link(ctx, doc, uri);
}
static pdf_obj *
diff --git a/source/pdf/pdf-xref.c b/source/pdf/pdf-xref.c
index c46d9f52..070e0946 100644
--- a/source/pdf/pdf-xref.c
+++ b/source/pdf/pdf-xref.c
@@ -2343,6 +2343,7 @@ pdf_new_document(fz_context *ctx, fz_stream *file)
doc->super.authenticate_password = (fz_document_authenticate_password_fn *)pdf_authenticate_password;
doc->super.has_permission = (fz_document_has_permission_fn *)pdf_has_permission;
doc->super.load_outline = (fz_document_load_outline_fn *)pdf_load_outline;
+ doc->super.resolve_link = (fz_document_resolve_link_fn *)pdf_resolve_link;
doc->super.count_pages = (fz_document_count_pages_fn *)pdf_count_pages;
doc->super.load_page = (fz_document_load_page_fn *)pdf_load_page;
doc->super.lookup_metadata = (fz_document_lookup_metadata_fn *)pdf_lookup_metadata;
diff --git a/source/tools/murun.c b/source/tools/murun.c
index fc887105..079a8c3c 100644
--- a/source/tools/murun.c
+++ b/source/tools/murun.c
@@ -1601,14 +1601,17 @@ static void to_outline(js_State *J, fz_outline *outline)
js_pushundefined(J);
js_setproperty(J, -2, "title");
- if (outline->dest.kind == FZ_LINK_GOTO) {
- js_pushnumber(J, outline->dest.ld.gotor.page);
- js_setproperty(J, -2, "page");
- }
- if (outline->dest.kind == FZ_LINK_URI) {
- js_pushstring(J, outline->dest.ld.uri.uri);
- js_setproperty(J, -2, "uri");
- }
+ if (outline->uri)
+ js_pushstring(J, outline->uri);
+ else
+ js_pushundefined(J);
+ js_setproperty(J, -2, "uri");
+
+ if (outline->page >= 0)
+ js_pushnumber(J, outline->page);
+ else
+ js_pushundefined(J);
+ js_setproperty(J, -2, "page");
if (outline->down) {
to_outline(J, outline->down);
@@ -1821,14 +1824,8 @@ static void ffi_Page_getLinks(js_State *J)
ffi_pushrect(J, link->rect);
js_setproperty(J, -2, "bounds");
- if (link->dest.kind == FZ_LINK_GOTO) {
- js_pushnumber(J, link->dest.ld.gotor.page);
- js_setproperty(J, -2, "page");
- }
- if (link->dest.kind == FZ_LINK_URI) {
- js_pushstring(J, link->dest.ld.uri.uri);
- js_setproperty(J, -2, "uri");
- }
+ js_pushstring(J, link->uri);
+ js_setproperty(J, -2, "uri");
js_setindex(J, -2, i++);
}
diff --git a/source/xps/xps-link.c b/source/xps/xps-link.c
index 9986d25f..1b2423ad 100644
--- a/source/xps/xps-link.c
+++ b/source/xps/xps-link.c
@@ -10,23 +10,7 @@ xps_load_links_in_element(fz_context *ctx, xps_document *doc, const fz_matrix *c
static void
xps_add_link(fz_context *ctx, xps_document *doc, const fz_rect *area, char *base_uri, char *target_uri, fz_link **head)
{
- fz_link_dest dest;
- fz_link *link;
-
- memset(&dest, 0, sizeof dest);
-
- if (xps_url_is_remote(ctx, doc, target_uri))
- {
- dest.kind = FZ_LINK_URI;
- dest.ld.uri.uri = fz_strdup(ctx, target_uri);
- }
- else
- {
- dest.kind = FZ_LINK_GOTO;
- dest.ld.gotor.page = xps_lookup_link_target(ctx, doc, target_uri);
- }
-
- link = fz_new_link(ctx, area, dest);
+ fz_link *link = fz_new_link(ctx, area, doc, target_uri);
link->next = *head;
*head = link;
}
diff --git a/source/xps/xps-outline.c b/source/xps/xps-outline.c
index 50eaf960..1fe294fb 100644
--- a/source/xps/xps-outline.c
+++ b/source/xps/xps-outline.c
@@ -33,9 +33,8 @@ 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->dest.kind = FZ_LINK_GOTO;
- entry->dest.ld.gotor.flags = 0;
- entry->dest.ld.gotor.page = xps_lookup_link_target(ctx, doc, target);
+ entry->uri = fz_strdup(ctx, target);
+ entry->page = xps_lookup_link_target(ctx, doc, target);
entry->down = NULL;
entry->next = NULL;
diff --git a/source/xps/xps-zip.c b/source/xps/xps-zip.c
index b2cc9e77..ba9947c7 100644
--- a/source/xps/xps-zip.c
+++ b/source/xps/xps-zip.c
@@ -231,6 +231,7 @@ xps_init_document(fz_context *ctx, xps_document *doc)
doc->super.refs = 1;
doc->super.drop_document = (fz_document_drop_fn *)xps_drop_document;
doc->super.load_outline = (fz_document_load_outline_fn *)xps_load_outline;
+ doc->super.resolve_link = (fz_document_resolve_link_fn *)xps_lookup_link_target;
doc->super.count_pages = (fz_document_count_pages_fn *)xps_count_pages;
doc->super.load_page = (fz_document_load_page_fn *)xps_load_page;
doc->super.lookup_metadata = (fz_document_lookup_metadata_fn *)xps_lookup_metadata;