diff options
-rw-r--r-- | android/jni/Core.mk | 1 | ||||
-rw-r--r-- | apps/pdfapp.c | 32 | ||||
-rw-r--r-- | apps/pdfapp.h | 2 | ||||
-rw-r--r-- | fitz/base_link.c | 57 | ||||
-rw-r--r-- | fitz/fitz.h | 60 | ||||
-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 | ||||
-rw-r--r-- | win32/libmupdf.vcproj | 4 |
10 files changed, 317 insertions, 99 deletions
diff --git a/android/jni/Core.mk b/android/jni/Core.mk index 259f0398..0ed43751 100644 --- a/android/jni/Core.mk +++ b/android/jni/Core.mk @@ -25,6 +25,7 @@ LOCAL_SRC_FILES := \ $(MY_ROOT)/fitz/base_geometry.c \ $(MY_ROOT)/fitz/base_getopt.c \ $(MY_ROOT)/fitz/base_hash.c \ + $(MY_ROOT)/fitz/base_link.c \ $(MY_ROOT)/fitz/base_memory.c \ $(MY_ROOT)/fitz/base_object.c \ $(MY_ROOT)/fitz/base_string.c \ diff --git a/apps/pdfapp.c b/apps/pdfapp.c index 849b0d18..cf136261 100644 --- a/apps/pdfapp.c +++ b/apps/pdfapp.c @@ -238,7 +238,7 @@ void pdfapp_close(pdfapp_t *app) app->page_text = NULL; if (app->page_links) - pdf_free_link(app->ctx, app->page_links); + fz_free_link(app->ctx, app->page_links); app->page_links = NULL; if (app->doctitle) @@ -394,7 +394,7 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai if (app->page_text) fz_free_text_span(app->ctx, app->page_text); if (app->page_links) - pdf_free_link(app->ctx, app->page_links); + fz_free_link(app->ctx, app->page_links); if (app->xref) pdfapp_loadpage_pdf(app); @@ -467,25 +467,13 @@ static void pdfapp_showpage(pdfapp_t *app, int loadpage, int drawpage, int repai fz_flush_warnings(app->ctx); } -static void pdfapp_gotouri(pdfapp_t *app, fz_obj *uri) +static void pdfapp_gotouri(pdfapp_t *app, char *uri) { - char *buf; - int n = fz_to_str_len(uri); - buf = fz_malloc(app->ctx, n + 1); - memcpy(buf, fz_to_str_buf(uri), n); - buf[n] = 0; - winopenuri(app, buf); - fz_free(app->ctx, buf); + winopenuri(app, uri); } -static void pdfapp_gotopage(pdfapp_t *app, fz_obj *obj) +static void pdfapp_gotopage(pdfapp_t *app, int number) { - int number; - - number = pdf_find_page_number(app->xref, obj); - if (number < 0) - return; - if (app->histlen + 1 == 256) { memmove(app->hist, app->hist + 1, sizeof(int) * 255); @@ -1025,7 +1013,7 @@ void pdfapp_onkey(pdfapp_t *app, int c) void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int state) { - pdf_link *link; + fz_link *link; fz_matrix ctm; fz_point p; @@ -1049,10 +1037,10 @@ void pdfapp_onmouse(pdfapp_t *app, int x, int y, int btn, int modifiers, int sta wincursor(app, HAND); if (btn == 1 && state == 1) { - if (link->kind == PDF_LINK_URI) - pdfapp_gotouri(app, link->dest); - else if (link->kind == PDF_LINK_GOTO) - pdfapp_gotopage(app, fz_array_get(link->dest, 0)); /* [ pageobj ... ] */ + if (link->kind == FZ_LINK_URI) + pdfapp_gotouri(app, link->dest.uri.uri); + else if (link->kind == FZ_LINK_GOTO) + pdfapp_gotopage(app, link->dest.gotor.page); return; } } diff --git a/apps/pdfapp.h b/apps/pdfapp.h index c9fe1d4f..22b6ad0d 100644 --- a/apps/pdfapp.h +++ b/apps/pdfapp.h @@ -49,7 +49,7 @@ struct pdfapp_s float page_rotate; fz_display_list *page_list; fz_text_span *page_text; - pdf_link *page_links; + fz_link *page_links; /* snapback history */ int hist[256]; diff --git a/fitz/base_link.c b/fitz/base_link.c new file mode 100644 index 00000000..d8d7e3ab --- /dev/null +++ b/fitz/base_link.c @@ -0,0 +1,57 @@ +#include "fitz.h" + +static void +free_link_dest(fz_context *ctx, fz_link_kind kind, fz_link_dest *dest) +{ + switch(kind) + { + case FZ_LINK_GOTO: + break; + case FZ_LINK_URI: + fz_free(ctx, dest->uri.uri); + break; + case FZ_LINK_LAUNCH: + fz_free(ctx, dest->launch.file_spec); + break; + case FZ_LINK_NAMED: + fz_free(ctx, dest->named.named); + break; + case FZ_LINK_GOTOR: + fz_free(ctx, dest->gotor.file_spec); + break; + } +} + +fz_link * +fz_new_link(fz_context *ctx, fz_link_kind kind, fz_rect bbox, fz_link_dest dest) +{ + fz_link *link; + + fz_try(ctx) + { + link = fz_malloc_struct(ctx, fz_link); + } + fz_catch(ctx) + { + free_link_dest(ctx, kind, &dest); + fz_rethrow(ctx); + } + link->kind = kind; + link->rect = bbox; + link->next = NULL; + return link; +} + +void +fz_free_link(fz_context *ctx, fz_link *link) +{ + fz_link *next; + + while (link) + { + next = link->next; + free_link_dest(ctx, link->kind, &link->dest); + fz_free(ctx, link); + link = next; + } +} diff --git a/fitz/fitz.h b/fitz/fitz.h index 589f22ee..9ac43d48 100644 --- a/fitz/fitz.h +++ b/fitz/fitz.h @@ -1233,4 +1233,64 @@ enum FZ_BLEND_KNOCKOUT = 32 }; +/* Links */ + +typedef struct fz_link_s fz_link; + +typedef union fz_link_dest_s fz_link_dest; + +typedef enum fz_link_kind_e +{ + FZ_LINK_GOTO = 0, + FZ_LINK_URI, + FZ_LINK_LAUNCH, + FZ_LINK_NAMED, + FZ_LINK_GOTOR +} fz_link_kind; + +enum { + fz_link_flag_l_valid = 1, /* lt.x is valid */ + fz_link_flag_t_valid = 2, /* lt.y is valid */ + fz_link_flag_r_valid = 4, /* rb.x is valid */ + fz_link_flag_b_valid = 8, /* rb.y is valid */ + fz_link_flag_fit_h = 16, /* Fit horizontally */ + fz_link_flag_fit_v = 32, /* Fit vertically */ + fz_link_flag_r_is_zoom = 64 /* rb.x is actually a zoom figure */ +}; + +union fz_link_dest_s +{ + struct { + int page; + int flags; + fz_point lt; + fz_point rb; + char *file_spec; + int new_window; + } gotor; + struct { + char *uri; + int is_map; + } uri; + struct { + char *file_spec; + int new_window; + } launch; + struct { + char *named; + } named; +}; + + +struct fz_link_s +{ + fz_link_kind kind; + fz_rect rect; + fz_link_dest dest; + fz_link *next; +}; + +fz_link *fz_new_link(fz_context *ctx, fz_link_kind, fz_rect bbox, fz_link_dest dest); +void fz_free_link(fz_context *ctx, fz_link *); + #endif 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); diff --git a/win32/libmupdf.vcproj b/win32/libmupdf.vcproj index 663f0268..bd24cb54 100644 --- a/win32/libmupdf.vcproj +++ b/win32/libmupdf.vcproj @@ -355,6 +355,10 @@ > </File> <File + RelativePath="..\fitz\base_link.c" + > + </File> + <File RelativePath="..\fitz\base_memory.c" > </File> |