From 3bc02d71ec0397118b97a60d48d3927e6bfdde41 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Fri, 10 Dec 2021 12:58:30 +0000 Subject: [PATCH] toc-bookmark --- cpdfcommand.ml | 19 ++++++++++++++----- cpdftoc.ml | 15 +++++++++++++-- cpdftoc.mli | 2 +- 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index a40aeb8..9f2b1e9 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -476,7 +476,8 @@ type args = mutable format_json : bool; mutable replace_dict_entry_value : Pdf.pdfobject; mutable dict_entry_search : Pdf.pdfobject option; - mutable toc_title : string} + mutable toc_title : string; + mutable toc_bookmark : bool} let args = {op = None; @@ -593,7 +594,8 @@ let args = format_json = false; replace_dict_entry_value = Pdf.Null; dict_entry_search = None; - toc_title = "Table of Contents"} + toc_title = "Table of Contents"; + toc_bookmark = true} let reset_arguments () = args.op <- None; @@ -695,7 +697,8 @@ let reset_arguments () = args.format_json <- false; args.replace_dict_entry_value <- Pdf.Null; args.dict_entry_search <- None; - args.toc_title <- "Table of Contents" + args.toc_title <- "Table of Contents"; + args.toc_bookmark <- true (* Do not reset original_filename or cpdflin or was_encrypted or * was_decrypted_with_owner or recrypt or producer or creator or path_to_* or * gs_malformed or gs_quiet, since we want these to work across ANDs. Or @@ -1638,6 +1641,9 @@ let settypeset s = let settableofcontentstitle s = args.toc_title <- s +let settocnobookmark () = + args.toc_bookmark <- false + let whingemalformed () = prerr_string "Command line must be of exactly the form\ncpdf -gs -gs-malformed-force -o \n"; exit 1 @@ -2395,9 +2401,12 @@ and specs = ("-table-of-contents", Arg.Unit (setop TableOfContents), " Typeset a table of contents from bookmarks"); - ("-table-of-contents-title", + ("-toc-title", Arg.String settableofcontentstitle, " Set (or clear if empty) the TOC title"); + ("-toc-no-bookmark", + Arg.Unit settocnobookmark, + " Don't add the table of contents to the bookmarks"); ("-typeset", Arg.String settypeset, " Typeset a text file as a PDF"); @@ -3843,7 +3852,7 @@ let go () = let font = match args.font with StandardFont f -> f | _ -> error "TOC requires standard font only" in - let pdf = Cpdftoc.typeset_table_of_contents ~font ~fontsize:args.fontsize ~title:args.toc_title pdf in + let pdf = Cpdftoc.typeset_table_of_contents ~font ~fontsize:args.fontsize ~title:args.toc_title ~bookmark:args.toc_bookmark pdf in write_pdf false pdf | Some (Typeset filename) -> let text = Pdfio.bytes_of_input_channel (open_in filename) in diff --git a/cpdftoc.ml b/cpdftoc.ml index 1af1ff8..cda8c9b 100644 --- a/cpdftoc.ml +++ b/cpdftoc.ml @@ -22,7 +22,7 @@ let of_pdfdocencoding f t = (and CropBox) copied from first page of existing PDF. Margin of 50pts inside CropBox. Font size of title twice body font size. Null page labels added for TOC, others bumped up and so preserved. *) -let typeset_table_of_contents ~font ~fontsize ~title pdf = +let typeset_table_of_contents ~font ~fontsize ~title ~bookmark pdf = let marks = Pdfmarks.read_bookmarks pdf in if marks = [] then (Printf.eprintf "No bookmarks, not making table of contents\n%!"; pdf) else let f, fs = (Pdftext.StandardFont (font, Pdftext.WinAnsiEncoding), fontsize) in @@ -100,4 +100,15 @@ let typeset_table_of_contents ~font ~fontsize ~title pdf = in let labels' = label::map (fun l -> {l with Pdfpagelabels.startpage = l.Pdfpagelabels.startpage + toc_pages_len}) labels in Pdfpagelabels.write pdf labels'; - pdf + if bookmark then + let marks = Pdfmarks.read_bookmarks pdf in + let refnums = Pdf.page_reference_numbers pdf in + let newmark = + {Pdfmarks.level = 0; + Pdfmarks.text = Pdftext.pdfdocstring_of_utf8 title; + Pdfmarks.target = Pdfdest.XYZ (Pdfdest.PageObject (hd refnums), None, None, None); + Pdfmarks.isopen = false} + in + Pdfmarks.add_bookmarks (newmark::marks) pdf + else + pdf diff --git a/cpdftoc.mli b/cpdftoc.mli index 57c386c..7e8e6c3 100644 --- a/cpdftoc.mli +++ b/cpdftoc.mli @@ -1 +1 @@ -val typeset_table_of_contents : font:Pdftext.standard_font -> fontsize:float -> title:string -> Pdf.t -> Pdf.t +val typeset_table_of_contents : font:Pdftext.standard_font -> fontsize:float -> title:string -> bookmark:bool -> Pdf.t -> Pdf.t