From 83d484a15cf89a96f1fff41fabec7ace61a8708a Mon Sep 17 00:00:00 2001 From: John Whitington Date: Mon, 27 Dec 2021 19:21:59 +0000 Subject: [PATCH] more --- cpdfbookmarks.ml | 132 +++++++++++++++++++++++------------------------ cpdfmanual.pdf | Bin 260131 -> 260708 bytes cpdfmanual.tex | 21 ++++++++ 3 files changed, 87 insertions(+), 66 deletions(-) diff --git a/cpdfbookmarks.ml b/cpdfbookmarks.ml index 1f552a4..1121586 100644 --- a/cpdfbookmarks.ml +++ b/cpdfbookmarks.ml @@ -192,75 +192,75 @@ let output_json_marks ch calculate_page_number pdf fastrefnums marks = let json = `List (map json_of_mark marks) in J.pretty_to_channel ch json +let process_string encoding s = + let rec replace c x y = function + | [] -> [] + | h::t when h = c -> x::y::replace c x y t + | h::t -> h::replace c x y t + in + (* Convert to UTF8, raw, or stripped, and escape backslashed and quotation marks *) + let codepoints = Pdftext.codepoints_of_pdfdocstring s in + let escaped = + let bs = int_of_char '\\' + and nl = int_of_char '\n' + and n = int_of_char 'n' + and q = int_of_char '\"' in + replace q bs q (replace nl bs n (replace bs bs bs codepoints)) + in + let process_stripped escaped = + let b = Buffer.create 200 in + iter + (fun x -> + if x <= 127 then Buffer.add_char b (char_of_int x)) + escaped; + Buffer.contents b + in + match encoding with + | Cpdfmetadata.UTF8 -> Pdftext.utf8_of_codepoints escaped + | Cpdfmetadata.Stripped -> process_stripped escaped + | Cpdfmetadata.Raw -> s + (* List the bookmarks in the given range to the given output *) let list_bookmarks ~json encoding range pdf output = - let process_stripped escaped = - let b = Buffer.create 200 in - iter - (fun x -> - if x <= 127 then Buffer.add_char b (char_of_int x)) - escaped; - Buffer.contents b - in - let process_string s = - let rec replace c x y = function - | [] -> [] - | h::t when h = c -> x::y::replace c x y t - | h::t -> h::replace c x y t + let bookmarks = Pdfmarks.read_bookmarks pdf in + let refnums = Pdf.page_reference_numbers pdf in + let rangetable = hashset_of_list range in + let range_is_all = range = ilist 1 (Pdfpage.endpage pdf) in + let fastrefnums = hashtable_of_dictionary (combine refnums (indx refnums)) in + (* Find the pagenumber of each bookmark target. If it is in the range, + * keep that bookmark. Also keep the bookmark if its target is the null + * destination. *) + let inrange = + keep + (function x -> + range_is_all || + x.Pdfmarks.target = Pdfdest.NullDestination || + (match x.Pdfmarks.target with Pdfdest.NamedDestinationElsewhere _ -> true | _ -> false) || + Hashtbl.mem rangetable (Pdfpage.pagenumber_of_target ~fastrefnums pdf x.Pdfmarks.target)) bookmarks in - (* Convert to UTF8, raw, or stripped, and escape backslashed and quotation marks *) - let codepoints = Pdftext.codepoints_of_pdfdocstring s in - let escaped = - let bs = int_of_char '\\' - and nl = int_of_char '\n' - and n = int_of_char 'n' - and q = int_of_char '\"' in - replace q bs q (replace nl bs n (replace bs bs bs codepoints)) - in - match encoding with - | Cpdfmetadata.UTF8 -> Pdftext.utf8_of_codepoints escaped - | Cpdfmetadata.Stripped -> process_stripped escaped - | Cpdfmetadata.Raw -> s - in - let bookmarks = Pdfmarks.read_bookmarks pdf in - let refnums = Pdf.page_reference_numbers pdf in - let rangetable = hashset_of_list range in - let range_is_all = range = ilist 1 (Pdfpage.endpage pdf) in - let fastrefnums = hashtable_of_dictionary (combine refnums (indx refnums)) in - (* Find the pagenumber of each bookmark target. If it is in the range, - * keep that bookmark. Also keep the bookmark if its target is the null - * destination. *) - let inrange = - keep - (function x -> - range_is_all || - x.Pdfmarks.target = Pdfdest.NullDestination || - (match x.Pdfmarks.target with Pdfdest.NamedDestinationElsewhere _ -> true | _ -> false) || - Hashtbl.mem rangetable (Pdfpage.pagenumber_of_target ~fastrefnums pdf x.Pdfmarks.target)) bookmarks - in - let calculate_page_number mark = - (* Some buggy PDFs use integers for page numbers instead of page - * object references. Adobe Reader and Preview seem to support - * this, for presumably historical reasons. So if we see a - * OtherDocPageNumber (which is what Pdfdest parses these as, - * because that's what they are legitimately, we use this as the - * page number. It is zero based, though, and we are one-based, so - * we add one. Pdfpage.pagenumber_of_target has been modified to support this.*) - Pdfpage.pagenumber_of_target ~fastrefnums pdf mark.Pdfmarks.target - in - if json then - output_json_marks stdout calculate_page_number pdf fastrefnums inrange - else - iter - (function mark -> - output.Pdfio.output_string - (Printf.sprintf "%i \"%s\" %i%s %s\n" - mark.Pdfmarks.level - (process_string mark.Pdfmarks.text) - (calculate_page_number mark) - (if mark.Pdfmarks.isopen then " open" else "") - (output_string_of_target pdf fastrefnums mark.Pdfmarks.target))) - inrange + let calculate_page_number mark = + (* Some buggy PDFs use integers for page numbers instead of page + * object references. Adobe Reader and Preview seem to support + * this, for presumably historical reasons. So if we see a + * OtherDocPageNumber (which is what Pdfdest parses these as, + * because that's what they are legitimately, we use this as the + * page number. It is zero based, though, and we are one-based, so + * we add one. Pdfpage.pagenumber_of_target has been modified to support this.*) + Pdfpage.pagenumber_of_target ~fastrefnums pdf mark.Pdfmarks.target + in + if json then + output_json_marks stdout calculate_page_number pdf fastrefnums inrange + else + iter + (function mark -> + output.Pdfio.output_string + (Printf.sprintf "%i \"%s\" %i%s %s\n" + mark.Pdfmarks.level + (process_string encoding mark.Pdfmarks.text) + (calculate_page_number mark) + (if mark.Pdfmarks.isopen then " open" else "") + (output_string_of_target pdf fastrefnums mark.Pdfmarks.target))) + inrange (* o is the stamp, u is the main pdf page *) diff --git a/cpdfmanual.pdf b/cpdfmanual.pdf index 556c891ba831942062713ddb266c51317254ba4d..f5e235ebd6b0eb3cefb6b2e66d268bc6b82afbc3 100644 GIT binary patch delta 12819 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 Hl|}wPI9!_x delta 12208 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 U3%)>+A+m9^BT`dKDoY{$9~Tgg4FCWD diff --git a/cpdfmanual.tex b/cpdfmanual.tex index 578a990..af68d6a 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -1562,6 +1562,9 @@ There are two options which turn off parts of the squeezer. They are \texttt{-sq \begin{framed} \small\noindent\verb!cpdf -list-bookmarks [-utf8 | -raw] in.pdf! + \vspace{1.5mm} + \small\noindent\verb!cpdf -list-bookmarks-json in.pdf! + \vspace{1.5mm} \small\noindent\verb!cpdf -remove-bookmarks in.pdf -o out.pdf! @@ -1608,6 +1611,24 @@ the ASCII range. To prevent this, and return unicode UTF8 output, add the \texttt{-utf8} option to the command. To prevent any processing, use the \texttt{-raw} option. See Section \ref{textencodings} for more information. A newline in a bookmark is represented as \texttt{"\textbackslash n"}. +By using \texttt{-list-bookmarks-json} instead, the bookmarks are formatted as a JSON array, in order, of dictionaries formatted thus: + +\begin{verbatim} +{ "level": 0, + "text": "1 Basic Usage", + "page": 17, + "open": false, + "target": + [ { "I": 17 }, + { "N": "/XYZ" }, + { "F": 85.039 }, + { "F": 609.307 }, + null ] +} +\end{verbatim} + +See chapter 15 for more details of cpdf's JSON formatting. Bookmark text in JSON bookmarks, however, is in UTF8 for ease of use. + \subsection{Destinations} The destination is an extended description of where the bookmark should point to (i.e it can be more detailed than just giving the page). For example, it may point to a section heading halfway down a page. Here are the possibilities: