diff options
author | Robin Watts <robin.watts@artifex.com> | 2011-12-23 12:59:24 +0000 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2011-12-23 13:18:42 +0000 |
commit | 73e548cdd564c6c2099ceafaa4019a7dbb188a30 (patch) | |
tree | e2d0b498abf0f0057d7d565d6b465226e6491d60 /pdf | |
parent | cc4dd0f8358d3de1594cc530b8f2691bccf194f0 (diff) | |
download | mupdf-73e548cdd564c6c2099ceafaa4019a7dbb188a30.tar.xz |
Generalise pdf_links to be fz_links.
Move to a non-pdf specific type for links. PDF specific parsing is
done in pdf_annots.c as before, but the essential type (and handling
functions for that type) are in a new file fitz/base_link.c.
The new type is more expressive than before; specifically all the
possible PDF modes are expressable in it. Hopefully this should
allow XPS links to be represented too.
Diffstat (limited to 'pdf')
-rw-r--r-- | pdf/mupdf.h | 27 | ||||
-rw-r--r-- | pdf/pdf_annot.c | 224 | ||||
-rw-r--r-- | pdf/pdf_outline.c | 7 | ||||
-rw-r--r-- | pdf/pdf_page.c | 2 |
4 files changed, 184 insertions, 76 deletions
diff --git a/pdf/mupdf.h b/pdf/mupdf.h index 7db1ca36..ca173b12 100644 --- a/pdf/mupdf.h +++ b/pdf/mupdf.h @@ -409,26 +409,8 @@ void pdf_debug_font(pdf_font_desc *fontdesc); * Interactive features */ -typedef struct pdf_link_s pdf_link; typedef struct pdf_annot_s pdf_annot; -typedef enum pdf_link_kind_e -{ - PDF_LINK_GOTO = 0, - PDF_LINK_URI, - PDF_LINK_LAUNCH, - PDF_LINK_NAMED, - PDF_LINK_ACTION, -} pdf_link_kind; - -struct pdf_link_s -{ - pdf_link_kind kind; - fz_rect rect; - fz_obj *dest; - pdf_link *next; -}; - struct pdf_annot_s { fz_obj *obj; @@ -438,15 +420,16 @@ struct pdf_annot_s pdf_annot *next; }; +fz_link_dest pdf_parse_link_dest(pdf_xref *xref, fz_obj *dest); + fz_obj *pdf_lookup_dest(pdf_xref *xref, fz_obj *needle); fz_obj *pdf_lookup_name(pdf_xref *xref, char *which, fz_obj *needle); fz_obj *pdf_load_name_tree(pdf_xref *xref, char *which); fz_outline *pdf_load_outline(pdf_xref *xref); -pdf_link *pdf_load_link(pdf_xref *xref, fz_obj *dict); -void pdf_load_links(pdf_link **, pdf_xref *, fz_obj *annots); -void pdf_free_link(fz_context *ctx, pdf_link *link); +fz_link *pdf_load_link(pdf_xref *xref, fz_obj *dict); +void pdf_load_links(fz_link **, pdf_xref *, fz_obj *annots); void pdf_load_annots(pdf_annot **, pdf_xref *, fz_obj *annots); void pdf_free_annot(fz_context *ctx, pdf_annot *link); @@ -464,7 +447,7 @@ struct pdf_page_s int transparency; fz_obj *resources; fz_buffer *contents; - pdf_link *links; + fz_link *links; pdf_annot *annots; }; diff --git a/pdf/pdf_annot.c b/pdf/pdf_annot.c index 79bdb4ff..ba4d509d 100644 --- a/pdf/pdf_annot.c +++ b/pdf/pdf_annot.c @@ -1,21 +1,6 @@ #include "fitz.h" #include "mupdf.h" -void -pdf_free_link(fz_context *ctx, pdf_link *link) -{ - pdf_link *next; - - while (link) - { - next = link->next; - if (link->dest) - fz_drop_obj(link->dest); - fz_free(ctx, link); - link = next; - } -} - static fz_obj * resolve_dest(pdf_xref *xref, fz_obj *dest) { @@ -42,14 +27,155 @@ resolve_dest(pdf_xref *xref, fz_obj *dest) return NULL; } -pdf_link * +fz_link_dest +pdf_parse_link_dest(pdf_xref *xref, fz_obj *dest) +{ + fz_link_dest ld; + fz_obj *obj; + int read = 0; + + obj = fz_array_get(dest, 0); + if (fz_is_int(obj)) + ld.gotor.page = fz_to_int(obj)-1; + else + ld.gotor.page = pdf_find_page_number(xref, obj); + + ld.gotor.flags = 0; + ld.gotor.lt.x = 0; + ld.gotor.lt.y = 0; + ld.gotor.rb.x = 0; + ld.gotor.rb.y = 0; + ld.gotor.file_spec = NULL; + ld.gotor.new_window = 0; + + obj = fz_array_get(dest, 1); + if (!fz_is_name(obj)) + return ld; + + if (!strcmp("XYZ", fz_to_name(obj))) + { + read = 1+16; + ld.gotor.flags |= fz_link_flag_r_is_zoom; + } + else if ((!strcmp("Fit", fz_to_name(obj))) || (!strcmp("FitB", fz_to_name(obj)))) + { + read = 0; + ld.gotor.flags |= fz_link_flag_fit_h; + ld.gotor.flags |= fz_link_flag_fit_v; + } + else if ((!strcmp("FitH", fz_to_name(obj))) || (!strcmp("FitBH", fz_to_name(obj)))) + { + read = 32; + ld.gotor.flags |= fz_link_flag_fit_h; + } + else if ((!strcmp("FitV", fz_to_name(obj))) || (!strcmp("FitBV", fz_to_name(obj)))) + { + read = 1; + ld.gotor.flags |= fz_link_flag_fit_v; + } + else if (!strcmp("FitR", fz_to_name(obj))) + { + read = 1+2+4+8; + ld.gotor.flags |= fz_link_flag_fit_h; + ld.gotor.flags |= fz_link_flag_fit_v; + } + + if (read & 1) + { + obj = fz_array_get(dest, 2); + if (fz_is_int(obj)) + { + ld.gotor.flags |= fz_link_flag_l_valid; + ld.gotor.lt.x = fz_to_int(obj); + } + else if (fz_is_real(obj)) + { + ld.gotor.flags |= fz_link_flag_l_valid; + ld.gotor.lt.x = fz_to_real(obj); + } + } + if (read & 2) + { + obj = fz_array_get(dest, 3); + if (fz_is_int(obj)) + { + ld.gotor.flags |= fz_link_flag_b_valid; + ld.gotor.rb.y = fz_to_int(obj); + } + else if (fz_is_real(obj)) + { + ld.gotor.flags |= fz_link_flag_b_valid; + ld.gotor.rb.y = fz_to_real(obj); + } + } + if (read & 4) + { + obj = fz_array_get(dest, 4); + if (fz_is_int(obj)) + { + ld.gotor.flags |= fz_link_flag_r_valid; + ld.gotor.rb.x = fz_to_int(obj); + } + else if (fz_is_real(obj)) + { + ld.gotor.flags |= fz_link_flag_r_valid; + ld.gotor.rb.x = fz_to_real(obj); + } + } + if (read & (8+16+32)) + { + if (read & 8) + obj = fz_array_get(dest, 5); + else if (read & 16) + obj = fz_array_get(dest, 3); + else + obj = fz_array_get(dest, 2); + if (fz_is_int(obj)) + { + ld.gotor.flags |= fz_link_flag_t_valid; + ld.gotor.lt.x = fz_to_int(obj); + } + else if (fz_is_real(obj)) + { + ld.gotor.flags |= fz_link_flag_t_valid; + ld.gotor.lt.x = fz_to_real(obj); + } + } + if (read & 16) + { + obj = fz_array_get(dest, 4); + if (fz_is_int(obj)) + { + ld.gotor.flags |= fz_link_flag_r_valid; + ld.gotor.rb.x = fz_to_int(obj); + } + else if (fz_is_real(obj)) + { + ld.gotor.flags |= fz_link_flag_r_valid; + ld.gotor.rb.x = fz_to_real(obj); + } + } + + /* Duplicate the values out for the sake of stupid clients */ + if ((ld.gotor.flags & (fz_link_flag_l_valid | fz_link_flag_r_valid)) == fz_link_flag_l_valid) + ld.gotor.rb.x = ld.gotor.lt.x; + if ((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.gotor.lt.x = ld.gotor.rb.x; + if ((ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_t_valid) + ld.gotor.rb.y = ld.gotor.lt.y; + if ((ld.gotor.flags & (fz_link_flag_t_valid | fz_link_flag_b_valid)) == fz_link_flag_b_valid) + ld.gotor.lt.y = ld.gotor.rb.y; + + return ld; +} + +fz_link * pdf_load_link(pdf_xref *xref, fz_obj *dict) { - fz_obj *dest; + fz_obj *dest = NULL; fz_obj *action; fz_obj *obj; fz_rect bbox; - pdf_link_kind kind; fz_context *ctx = xref->ctx; dest = NULL; @@ -63,8 +189,10 @@ pdf_load_link(pdf_xref *xref, fz_obj *dict) obj = fz_dict_gets(dict, "Dest"); if (obj) { - kind = PDF_LINK_GOTO; + fz_link_dest ld; dest = resolve_dest(xref, obj); + ld = pdf_parse_link_dest(xref, dest); + return fz_new_link(ctx, FZ_LINK_GOTO, bbox, ld); } action = fz_dict_gets(dict, "A"); @@ -76,54 +204,54 @@ pdf_load_link(pdf_xref *xref, fz_obj *dict) if (action) { obj = fz_dict_gets(action, "S"); - if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "GoTo")) + if (!fz_is_name(obj)) { - kind = PDF_LINK_GOTO; - dest = resolve_dest(xref, fz_dict_gets(action, "D")); } - else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "URI")) + else if (!strcmp(fz_to_name(obj), "GoTo")) { - kind = PDF_LINK_URI; - dest = fz_dict_gets(action, "URI"); + fz_link_dest ld; + dest = resolve_dest(xref, fz_dict_gets(action, "D")); + ld = pdf_parse_link_dest(xref, dest); + return fz_new_link(ctx, FZ_LINK_GOTO, bbox, ld); } - else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Launch")) + else if (!strcmp(fz_to_name(obj), "URI")) { - kind = PDF_LINK_LAUNCH; - dest = fz_dict_gets(action, "F"); + fz_link_dest ld; + ld.uri.is_map = fz_to_int(fz_dict_gets(action, "IsMap")); + ld.uri.uri = pdf_to_utf8(ctx, fz_dict_gets(action, "URI")); + return fz_new_link(ctx, FZ_LINK_URI, bbox, ld); } - else if (fz_is_name(obj) && !strcmp(fz_to_name(obj), "Named")) + else if (!strcmp(fz_to_name(obj), "Launch")) { - kind = PDF_LINK_NAMED; - dest = fz_dict_gets(action, "N"); + fz_link_dest ld; + ld.launch.file_spec = pdf_to_utf8(ctx, fz_dict_gets(action, "F")); + ld.launch.new_window = fz_to_int(fz_dict_gets(action, "NewWindow")); + return fz_new_link(ctx, FZ_LINK_LAUNCH, bbox, ld); } - else if (fz_is_name(obj) && (!strcmp(fz_to_name(obj), "GoToR"))) + else if (!strcmp(fz_to_name(obj), "Named")) { - kind = PDF_LINK_ACTION; - dest = action; + fz_link_dest ld; + ld.named.named = pdf_to_utf8(ctx, fz_dict_gets(action, "N")); + return fz_new_link(ctx, FZ_LINK_NAMED, bbox, ld); } - else + else if (!strcmp(fz_to_name(obj), "GoToR")) { - dest = NULL; + fz_link_dest ld; + dest = resolve_dest(xref, fz_dict_gets(action, "D")); + ld = pdf_parse_link_dest(xref, dest); + ld.gotor.file_spec = pdf_to_utf8(ctx, fz_dict_gets(action, "F")); + ld.gotor.new_window = fz_to_int(fz_dict_gets(action, "NewWindow")); + return fz_new_link(ctx, FZ_LINK_GOTOR, bbox, ld); } } - if (dest) - { - pdf_link *link = fz_malloc_struct(ctx, pdf_link); - link->kind = kind; - link->rect = bbox; - link->dest = fz_keep_obj(dest); - link->next = NULL; - return link; - } - return NULL; } void -pdf_load_links(pdf_link **linkp, pdf_xref *xref, fz_obj *annots) +pdf_load_links(fz_link **linkp, pdf_xref *xref, fz_obj *annots) { - pdf_link *link, *head, *tail; + fz_link *link, *head, *tail; fz_obj *obj; int i, n; diff --git a/pdf/pdf_outline.c b/pdf/pdf_outline.c index 8a33d8e2..3f6b745b 100644 --- a/pdf/pdf_outline.c +++ b/pdf/pdf_outline.c @@ -5,7 +5,6 @@ static fz_outline * pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict) { fz_context *ctx = xref->ctx; - pdf_link *link; fz_outline *node; fz_obj *obj; @@ -25,10 +24,8 @@ pdf_load_outline_imp(pdf_xref *xref, fz_obj *dict) if (fz_dict_gets(dict, "Dest") || fz_dict_gets(dict, "A")) { - link = pdf_load_link(xref, dict); - if (link && link->kind == PDF_LINK_GOTO) - node->page = pdf_find_page_number(xref, fz_array_get(link->dest, 0)); - pdf_free_link(xref->ctx, link); + fz_link_dest ld = pdf_parse_link_dest(xref, dict); + node->page = ld.gotor.page; } obj = fz_dict_gets(dict, "First"); diff --git a/pdf/pdf_page.c b/pdf/pdf_page.c index a9e99e52..05af3b60 100644 --- a/pdf/pdf_page.c +++ b/pdf/pdf_page.c @@ -363,7 +363,7 @@ pdf_free_page(fz_context *ctx, pdf_page *page) if (page->contents) fz_drop_buffer(ctx, page->contents); if (page->links) - pdf_free_link(ctx, page->links); + fz_free_link(ctx, page->links); if (page->annots) pdf_free_annot(ctx, page->annots); fz_free(ctx, page); |