summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--apps/pdfapp.c3
-rw-r--r--xps/muxps.h7
-rw-r--r--xps/xps_doc.c68
-rw-r--r--xps/xps_glyphs.c5
-rw-r--r--xps/xps_path.c5
-rw-r--r--xps/xps_tile.c5
-rw-r--r--xps/xps_util.c4
7 files changed, 95 insertions, 2 deletions
diff --git a/apps/pdfapp.c b/apps/pdfapp.c
index 48e9fe93..aa529220 100644
--- a/apps/pdfapp.c
+++ b/apps/pdfapp.c
@@ -367,7 +367,6 @@ static void pdfapp_loadpage_xps(pdfapp_t *app)
}
app->page_bbox = xps_bound_page(app->xps, page);
- app->page_links = NULL;
/* Create display list */
app->page_list = fz_new_display_list(app->ctx);
@@ -375,6 +374,8 @@ static void pdfapp_loadpage_xps(pdfapp_t *app)
xps_run_page(app->xps, page, mdev, fz_identity, NULL);
fz_free_device(mdev);
+ app->page_links = page->links;
+
xps_free_page(app->xps, page);
}
diff --git a/xps/muxps.h b/xps/muxps.h
index fe0e5de1..2f87edc6 100644
--- a/xps/muxps.h
+++ b/xps/muxps.h
@@ -89,6 +89,8 @@ struct xps_page_s
int width;
int height;
xml_element *root;
+ int links_resolved;
+ fz_link *links;
xps_page *next;
};
@@ -111,7 +113,7 @@ void xps_free_page(xps_document *doc, xps_page *page);
fz_outline *xps_load_outline(xps_document *doc);
int xps_find_link_target(xps_document *doc, char *target_uri);
-
+void xps_add_link(xps_document *doc, fz_rect area, char *base_uri, char *target_uri);
/*
* Images, fonts, and colorspaces.
*/
@@ -245,6 +247,9 @@ struct xps_document_s
/* Current device */
fz_cookie *cookie;
fz_device *dev;
+
+ /* Current page we are loading */
+ xps_page *current_page;
};
xps_document *xps_open_document(fz_context *ctx, char *filename);
diff --git a/xps/xps_doc.c b/xps/xps_doc.c
index 36903266..d1943fc0 100644
--- a/xps/xps_doc.c
+++ b/xps/xps_doc.c
@@ -69,6 +69,69 @@ xps_add_fixed_document(xps_document *doc, char *name)
}
}
+void
+xps_add_link(xps_document *doc, fz_rect area, char *base_uri, char *target_uri)
+{
+ int len;
+ char *buffer = NULL;
+ char *uri;
+ xps_target *target;
+ fz_link_dest dest;
+ fz_link *link;
+ fz_context *ctx = doc->ctx;
+
+ fz_var(buffer);
+
+ if (doc->current_page == NULL || doc->current_page->links_resolved)
+ return;
+
+ fz_try(ctx)
+ {
+ len = 2 + (base_uri ? strlen(base_uri) : 0) +
+ (target_uri ? strlen(target_uri) : 0);
+ buffer = fz_malloc(doc->ctx, len);
+ xps_absolute_path(buffer, base_uri, target_uri, len);
+ uri = buffer;
+
+ /* FIXME: This won't work for remote docs */
+ /* Skip until we find the fragment marker */
+ while (*uri && *uri != '#')
+ uri++;
+ if (*uri == '#')
+ uri++;
+
+ for (target = doc->target; target; target = target->next)
+ if (!strcmp(target->name, uri))
+ break;
+
+ if (target == NULL)
+ break;
+
+ dest.kind = FZ_LINK_GOTO;
+ dest.ld.gotor.flags = fz_link_flag_l_valid | fz_link_flag_t_valid | fz_link_flag_r_valid | fz_link_flag_b_valid;
+ dest.ld.gotor.lt.x = area.x0;
+ dest.ld.gotor.lt.y = area.y0;
+ dest.ld.gotor.rb.x = area.x1;
+ dest.ld.gotor.rb.y = area.y1;
+ dest.ld.gotor.page = target->page;
+ dest.ld.gotor.file_spec = NULL;
+ dest.ld.gotor.new_window = 0;
+
+ link = fz_new_link(doc->ctx, area, dest);
+ link->next = doc->current_page->links;
+ doc->current_page->links = link;
+ }
+ fz_always(ctx)
+ {
+ fz_free(doc->ctx, buffer);
+ }
+ fz_catch(ctx)
+ {
+ fz_rethrow(ctx);
+ }
+}
+
+
static void
xps_add_fixed_page(xps_document *doc, char *name, int width, int height)
{
@@ -84,6 +147,8 @@ xps_add_fixed_page(xps_document *doc, char *name, int width, int height)
page->number = doc->page_count++;
page->width = width;
page->height = height;
+ page->links = NULL;
+ page->links_resolved = 0;
page->root = NULL;
page->next = NULL;
@@ -353,8 +418,10 @@ xps_load_page(xps_document *doc, int number)
{
if (n == number)
{
+ doc->current_page = page;
if (!page->root)
xps_load_fixed_page(doc, page);
+ page->links_resolved = 1;
return page;
}
n ++;
@@ -380,5 +447,6 @@ xps_free_page(xps_document *doc, xps_page *page)
/* only free the XML contents */
if (page->root)
xml_free_element(doc->ctx, page->root);
+ fz_free_link(doc->ctx, page->links);
page->root = NULL;
}
diff --git a/xps/xps_glyphs.c b/xps/xps_glyphs.c
index bbc49af1..0cc4af5d 100644
--- a/xps/xps_glyphs.c
+++ b/xps/xps_glyphs.c
@@ -387,6 +387,7 @@ xps_parse_glyphs(xps_document *doc, fz_matrix ctm,
char *clip_att;
char *opacity_att;
char *opacity_mask_att;
+ char *navigate_uri_att;
xml_element *transform_tag = NULL;
xml_element *clip_tag = NULL;
@@ -428,6 +429,7 @@ xps_parse_glyphs(xps_document *doc, fz_matrix ctm,
clip_att = xml_att(root, "Clip");
opacity_att = xml_att(root, "Opacity");
opacity_mask_att = xml_att(root, "OpacityMask");
+ navigate_uri_att = xml_att(root, "FixedPage.NavigateUri");
for (node = xml_down(root); node; node = xml_next(node))
{
@@ -545,6 +547,9 @@ xps_parse_glyphs(xps_document *doc, fz_matrix ctm,
area = fz_bound_text(doc->ctx, text, ctm);
+ if (navigate_uri_att)
+ xps_add_link(doc, area, base_uri, navigate_uri_att);
+
xps_begin_opacity(doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
/* If it's a solid color brush fill/stroke do a simple fill */
diff --git a/xps/xps_path.c b/xps/xps_path.c
index c49a55a6..77bb6a36 100644
--- a/xps/xps_path.c
+++ b/xps/xps_path.c
@@ -837,6 +837,7 @@ xps_parse_path(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *d
char *stroke_line_join_att;
char *stroke_miter_limit_att;
char *stroke_thickness_att;
+ char *navigate_uri_att;
fz_stroke_state stroke;
fz_matrix transform;
@@ -866,6 +867,7 @@ xps_parse_path(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *d
stroke_line_join_att = xml_att(root, "StrokeLineJoin");
stroke_miter_limit_att = xml_att(root, "StrokeMiterLimit");
stroke_thickness_att = xml_att(root, "StrokeThickness");
+ navigate_uri_att = xml_att(root, "FixedPage.NavigateUri");
for (node = xml_down(root); node; node = xml_next(node))
{
@@ -976,6 +978,9 @@ xps_parse_path(xps_document *doc, fz_matrix ctm, char *base_uri, xps_resource *d
else
area = fz_bound_path(path, NULL, ctm);
+ if (navigate_uri_att)
+ xps_add_link(doc, area, base_uri, navigate_uri_att);
+
xps_begin_opacity(doc, ctm, area, opacity_mask_uri, dict, opacity_att, opacity_mask_tag);
if (fill_att)
diff --git a/xps/xps_tile.c b/xps/xps_tile.c
index b672724b..fe4d2350 100644
--- a/xps/xps_tile.c
+++ b/xps/xps_tile.c
@@ -255,6 +255,7 @@ xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri,
char *clip_att;
char *opacity_att;
char *opacity_mask_att;
+ char *navigate_uri_att;
xml_element *transform_tag = NULL;
xml_element *clip_tag = NULL;
@@ -266,6 +267,7 @@ xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri,
clip_att = xml_att(root, "Clip");
opacity_att = xml_att(root, "Opacity");
opacity_mask_att = xml_att(root, "OpacityMask");
+ navigate_uri_att = xml_att(root, "FixedPage.NavigateUri");
for (node = xml_down(root); node; node = xml_next(node))
{
@@ -301,6 +303,9 @@ xps_parse_canvas(xps_document *doc, fz_matrix ctm, fz_rect area, char *base_uri,
xps_parse_matrix_transform(doc, transform_tag, &transform);
ctm = fz_concat(transform, ctm);
+ if (navigate_uri_att)
+ xps_add_link(doc, area, base_uri, navigate_uri_att);
+
if (clip_att || clip_tag)
xps_clip(doc, ctm, dict, clip_att, clip_tag);
diff --git a/xps/xps_util.c b/xps/xps_util.c
index d6e226b5..6af4da91 100644
--- a/xps/xps_util.c
+++ b/xps/xps_util.c
@@ -77,6 +77,10 @@ xps_clean_path(char *name)
return name;
}
+/* RJW: Possible problems here:
+ * "/foo" + "../../bar" = "/bar" not "../bar"
+ * "http://something/" + ... doesn't work.
+ */
void
xps_absolute_path(char *output, char *base_uri, char *path, int output_size)
{