From 064b36eb743b6844c35c20e2d202a5ec81074878 Mon Sep 17 00:00:00 2001 From: Sebastian Rasmussen Date: Thu, 6 Apr 2017 19:53:16 +0800 Subject: Bug 697662: Support named actions to first/last/next/previous page. --- include/mupdf/pdf/annot.h | 4 ++-- resources/pdf/names.txt | 4 ++++ source/pdf/pdf-annot.c | 33 ++++++++++++++++++++++++++++----- source/pdf/pdf-outline.c | 2 +- source/pdf/pdf-page.c | 2 +- 5 files changed, 36 insertions(+), 9 deletions(-) diff --git a/include/mupdf/pdf/annot.h b/include/mupdf/pdf/annot.h index f8806728..866e5ba5 100644 --- a/include/mupdf/pdf/annot.h +++ b/include/mupdf/pdf/annot.h @@ -104,13 +104,13 @@ struct pdf_annot_s char *pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_obj *dest); char *pdf_parse_link_dest(fz_context *ctx, pdf_document *doc, pdf_obj *obj); -char *pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *obj); +char *pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *obj, int pagenum); pdf_obj *pdf_lookup_dest(fz_context *ctx, pdf_document *doc, pdf_obj *needle); pdf_obj *pdf_lookup_name(fz_context *ctx, pdf_document *doc, pdf_obj *which, pdf_obj *needle); pdf_obj *pdf_load_name_tree(fz_context *ctx, pdf_document *doc, pdf_obj *which); int pdf_resolve_link(fz_context *ctx, pdf_document *doc, const char *uri, float *xp, float *yp); -fz_link *pdf_load_link_annots(fz_context *ctx, pdf_document *, pdf_obj *annots, const fz_matrix *page_ctm); +fz_link *pdf_load_link_annots(fz_context *ctx, pdf_document *, pdf_obj *annots, int pagenum, const fz_matrix *page_ctm); void pdf_annot_transform(fz_context *ctx, pdf_annot *annot, fz_matrix *annot_ctm); void pdf_load_annots(fz_context *ctx, pdf_page *page, pdf_obj *annots); diff --git a/resources/pdf/names.txt b/resources/pdf/names.txt index 071e7f2e..cfe83ed2 100644 --- a/resources/pdf/names.txt +++ b/resources/pdf/names.txt @@ -144,6 +144,7 @@ Filespec Filter First FirstChar +FirstPage Fit FitB FitBH @@ -214,6 +215,7 @@ LZWDecode Lab Last LastChar +LastPage Launch Length Length1 @@ -244,6 +246,7 @@ Named Names NewWindow Next +NextPage None Normal O @@ -279,6 +282,7 @@ Polygon Popup Predictor Prev +PrevPage Print PrinterMark ProcSet diff --git a/source/pdf/pdf-annot.c b/source/pdf/pdf-annot.c index 539c4882..b90b5e86 100644 --- a/source/pdf/pdf-annot.c +++ b/source/pdf/pdf-annot.c @@ -169,7 +169,7 @@ pdf_parse_file_spec(fz_context *ctx, pdf_document *doc, pdf_obj *file_spec, pdf_ } char * -pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action) +pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action, int pagenum) { pdf_obj *obj, *dest, *file_spec; @@ -208,12 +208,35 @@ pdf_parse_link_action(fz_context *ctx, pdf_document *doc, pdf_obj *action) file_spec = pdf_dict_get(ctx, action, PDF_NAME_F); return pdf_parse_file_spec(ctx, doc, file_spec, dest); } + else if (pdf_name_eq(ctx, PDF_NAME_Named, obj)) + { + dest = pdf_dict_get(ctx, action, PDF_NAME_N); + + if (pdf_name_eq(ctx, PDF_NAME_FirstPage, dest)) + pagenum = 0; + else if (pdf_name_eq(ctx, PDF_NAME_LastPage, dest)) + pagenum = pdf_count_pages(ctx, doc) - 1; + else if (pdf_name_eq(ctx, PDF_NAME_PrevPage, dest) && pagenum >= 0) + { + if (pagenum > 0) + pagenum--; + } + else if (pdf_name_eq(ctx, PDF_NAME_NextPage, dest) && pagenum >= 0) + { + if (pagenum < pdf_count_pages(ctx, doc) - 1) + pagenum++; + } + else + return NULL; + + return fz_asprintf(ctx, "#%d", pagenum + 1); + } return NULL; } static fz_link * -pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, const fz_matrix *page_ctm) +pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, int pagenum, const fz_matrix *page_ctm) { pdf_obj *action; pdf_obj *obj; @@ -241,7 +264,7 @@ pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, const fz_matrix /* 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); - uri = pdf_parse_link_action(ctx, doc, action); + uri = pdf_parse_link_action(ctx, doc, action, pagenum); } if (!uri) @@ -253,7 +276,7 @@ pdf_load_link(fz_context *ctx, pdf_document *doc, pdf_obj *dict, const fz_matrix } fz_link * -pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, const fz_matrix *page_ctm) +pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, int pagenum, const fz_matrix *page_ctm) { fz_link *link, *head, *tail; pdf_obj *obj; @@ -269,7 +292,7 @@ pdf_load_link_annots(fz_context *ctx, pdf_document *doc, pdf_obj *annots, const fz_try(ctx) { obj = pdf_array_get(ctx, annots, i); - link = pdf_load_link(ctx, doc, obj, page_ctm); + link = pdf_load_link(ctx, doc, obj, pagenum, page_ctm); } fz_catch(ctx) { diff --git a/source/pdf/pdf-outline.c b/source/pdf/pdf-outline.c index 7c8cfdaa..708f7087 100644 --- a/source/pdf/pdf-outline.c +++ b/source/pdf/pdf-outline.c @@ -29,7 +29,7 @@ pdf_load_outline_imp(fz_context *ctx, pdf_document *doc, pdf_obj *dict) if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_Dest)) != NULL) node->uri = pdf_parse_link_dest(ctx, doc, obj); else if ((obj = pdf_dict_get(ctx, dict, PDF_NAME_A)) != NULL) - node->uri = pdf_parse_link_action(ctx, doc, obj); + node->uri = pdf_parse_link_action(ctx, doc, obj, -1); else node->uri = NULL; diff --git a/source/pdf/pdf-page.c b/source/pdf/pdf-page.c index dc907798..f3860e52 100644 --- a/source/pdf/pdf-page.c +++ b/source/pdf/pdf-page.c @@ -699,7 +699,7 @@ pdf_load_page(fz_context *ctx, pdf_document *doc, int number) fz_rect page_mediabox; fz_matrix page_ctm; pdf_page_transform(ctx, page, &page_mediabox, &page_ctm); - page->links = pdf_load_link_annots(ctx, doc, obj, &page_ctm); + page->links = pdf_load_link_annots(ctx, doc, obj, number, &page_ctm); pdf_load_annots(ctx, page, obj); } } -- cgit v1.2.3