From 71f37228cee5f32ec378d216f927c0b0164e291d Mon Sep 17 00:00:00 2001 From: John Whitington Date: Wed, 2 Oct 2013 15:29:53 +0100 Subject: [PATCH] Added support for open actions --- cpdf.ml | 27 +++++++++++++++++++++++++++ cpdf.mli | 5 +++-- cpdfcommand.ml | 29 ++++++++++++++++++++++++----- cpdfmanual.tex | 4 ++++ 4 files changed, 58 insertions(+), 7 deletions(-) diff --git a/cpdf.ml b/cpdf.ml index fce62ba..fc512b8 100644 --- a/cpdf.ml +++ b/cpdf.ml @@ -827,6 +827,33 @@ let set_page_mode pdf s = end | _ -> error "Unknown page mode" +(* Set open action *) +let set_open_action pdf fit pagenumber = + if pagenumber > Pdfpage.endpage pdf || pagenumber < 0 then + raise (error "set_open_action: invalid page number") + else + let pageobjectnumber = select pagenumber (Pdf.page_reference_numbers pdf) in + let destination = + if fit then + Pdf.Array [Pdf.Indirect pageobjectnumber; Pdf.Name "/Fit"] + else + Pdf.Array [Pdf.Indirect pageobjectnumber; Pdf.Name "/XYZ"; Pdf.Null; Pdf.Null; Pdf.Null] + in + let open_action = + Pdf.Dictionary [("/D", destination); ("/S", Pdf.Name "/GoTo")] + in + match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with + | Some catalog -> + let catalog' = + Pdf.add_dict_entry catalog "/OpenAction" open_action + in + let catalognum = Pdf.addobj pdf catalog' in + let trailerdict' = + Pdf.add_dict_entry pdf.Pdf.trailerdict "/Root" (Pdf.Indirect catalognum) + in + {pdf with Pdf.root = catalognum; Pdf.trailerdict = trailerdict'} + | None -> error "bad root" + (* \section{Set viewer preferences} *) let set_viewer_preference (key, value, version) pdf = match Pdf.lookup_direct pdf "/Root" pdf.Pdf.trailerdict with diff --git a/cpdf.mli b/cpdf.mli index 0aeaef3..b08dbb7 100644 --- a/cpdf.mli +++ b/cpdf.mli @@ -105,6 +105,9 @@ val set_page_layout : Pdf.t -> string -> Pdf.t (** Set the page layout to the given name (sans slash) e.g SinglePage *) val set_page_mode : Pdf.t -> string -> Pdf.t +(** Set the open action. If the boolean is true, /Fit will be used, otherwise /XYZ *) +val set_open_action : Pdf.t -> bool -> int -> Pdf.t + (** Set the PDF version number *) val set_version : int -> Pdf.t -> unit @@ -248,8 +251,6 @@ val calculate_position : float * float * float * float -> orientation -> position -> float * float * float - - (** Call [add_texts metrics linewidth outline fast fontname font bates colour position linespacing fontsize underneath text pages orientation relative_to_cropbox midline_adjust filename pdf]. For details see cpdfmanual.pdf *) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index 7a45abf..23488ed 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -1,9 +1,9 @@ -(* cpdf command line tools} *) +(* cpdf command line tools *) let demo = false and noncomp = true and major_version = 1 -and minor_version = 7 -and version_date = "(7th August 2013)" +and minor_version = 8 +and version_date = "(unreleased)" open Pdfutil open Pdfio @@ -150,6 +150,8 @@ type op = | ExtractFontFile | ExtractText | PrintLinearization + | OpenAtPage of int + | OpenAtPageFit of int (* Inputs: filename, pagespec. *) type input_kind = @@ -399,7 +401,8 @@ let reset_arguments () = args.makenewid <- false; args.ismulti <- false; args.uprightstamp <- false - (* We don't reset args.do_ask and args.verbose, because they operate on all parts of the AND-ed command line sent from cpdftk. *) + (* We don't reset args.do_ask and args.verbose, because they operate on all + parts of the AND-ed command line sent from cpdftk. *) let banlist_of_args () = let l = ref [] in @@ -1178,6 +1181,12 @@ let setstdinowner o = | (StdIn, x, y, u, _)::t -> args.inputs <- (StdIn, x, y, u, o)::t | _ -> error "-stdin-user: must follow -stdin" +let setopenatpage n = + args.op <- Some (OpenAtPage n) + +let setopenatpagefit n = + args.op <- Some (OpenAtPageFit n) + (* Parse a control file, make an argv, and then make Arg parse it. *) let rec make_control_argv_and_parse filename = control_args := !control_args @ parse_control_file filename @@ -1539,6 +1548,12 @@ and specs = ("-set-page-mode", Arg.String setpagemode, " Set page mode upon document opening"); + ("-open-at-page", + Arg.Int setopenatpage, + " Set initial page"); + ("-open-at-page-fit", + Arg.Int setopenatpagefit, + " Set inital page, scaling to fit"); ("-set-metadata", Arg.String setmetadata, " Set metadata to the contents of a file"); @@ -2621,7 +2636,7 @@ let addrectangle (w, h) color position relative_to_cropbox underneath range pdf in Cpdf.process_pages addrectangle_page pdf range -(* \section{Main function} *) +(* Main function *) let go () = match args.op with | Some Version -> @@ -2938,6 +2953,10 @@ let go () = let version = if args.keepversion then pdf.Pdf.minor else version in write_pdf false (Cpdf.set_viewer_preference (key, value, version) pdf) end + | Some (OpenAtPage n) -> + write_pdf false (Cpdf.set_open_action (get_single_pdf args.op false) false n) + | Some (OpenAtPageFit n) -> + write_pdf false (Cpdf.set_open_action (get_single_pdf args.op true) false n) | Some (SetMetadata metadata_file) -> write_pdf false (Cpdf.set_metadata args.keepversion metadata_file (get_single_pdf args.op false)) | Some (SetVersion v) -> diff --git a/cpdfmanual.tex b/cpdfmanual.tex index e773c89..e5e2433 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -1,3 +1,7 @@ +%To document for next version: +% Anil's changes to output format of -list-annotations +% The new -open-at-page, -open-at-page-fit options + \documentclass[a4paper,makeidx]{memoir} \usepackage{palatino} \usepackage{microtype}