diff options
-rw-r--r-- | apps/pdfapp.c | 3 | ||||
-rw-r--r-- | xps/muxps.h | 7 | ||||
-rw-r--r-- | xps/xps_doc.c | 68 | ||||
-rw-r--r-- | xps/xps_glyphs.c | 5 | ||||
-rw-r--r-- | xps/xps_path.c | 5 | ||||
-rw-r--r-- | xps/xps_tile.c | 5 | ||||
-rw-r--r-- | xps/xps_util.c | 4 |
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) { |