Support PDF/UA annotations

This commit is contained in:
John Whitington
2025-02-26 16:37:27 +00:00
parent d4563d2efc
commit 5c58029844
5 changed files with 17 additions and 12 deletions

View File

@ -4783,7 +4783,8 @@ let go () =
let cpdffont = embed_font () in let cpdffont = embed_font () in
let pdf = let pdf =
Cpdftoc.typeset_table_of_contents Cpdftoc.typeset_table_of_contents
~font:cpdffont ~fontsize:args.fontsize ~title:args.toc_title ~bookmark:args.toc_bookmark ~dotleader:args.dot_leader pdf ~font:cpdffont ~fontsize:args.fontsize ~title:args.toc_title
~bookmark:args.toc_bookmark ~dotleader:args.dot_leader ~process_struct_tree:args.process_struct_trees pdf
in in
write_pdf false pdf write_pdf false pdf
| Some (Typeset filename) -> | Some (Typeset filename) ->

View File

@ -106,7 +106,7 @@ let make_dots space fontpack fontsize =
(and CropBox) copied from first page of existing PDF. Margin of 10% inside (and CropBox) copied from first page of existing PDF. Margin of 10% inside
CropBox. Font size of title twice body font size. Null page labels added for CropBox. Font size of title twice body font size. Null page labels added for
TOC, others bumped up and so preserved. *) TOC, others bumped up and so preserved. *)
let typeset_table_of_contents ~font ~fontsize ~title ~bookmark ~dotleader pdf = let typeset_table_of_contents ~font ~fontsize ~title ~bookmark ~dotleader ~process_struct_tree pdf =
Hashtbl.clear width_table_cache; Hashtbl.clear width_table_cache;
let marks = Pdfmarks.read_bookmarks pdf in let marks = Pdfmarks.read_bookmarks pdf in
if marks = [] then (Pdfe.log "No bookmarks, not making table of contents\n"; pdf) else if marks = [] then (Pdfe.log "No bookmarks, not making table of contents\n"; pdf) else
@ -158,7 +158,7 @@ let typeset_table_of_contents ~font ~fontsize ~title ~bookmark ~dotleader pdf =
then make_dots space fontpack fontsize then make_dots space fontpack fontsize
else [Cpdftype.HGlue space] else [Cpdftype.HGlue space]
in in
[Cpdftype.BeginDest mark.Pdfmarks.target; Cpdftype.HGlue indent] @ textruns @ leader @ labelruns [Cpdftype.BeginDest (mark.Pdfmarks.target, Some mark.Pdfmarks.text); Cpdftype.HGlue indent] @ textruns @ leader @ labelruns
@ [Cpdftype.EndDest; Cpdftype.NewLine]) @ [Cpdftype.EndDest; Cpdftype.NewLine])
(Pdfmarks.read_bookmarks pdf) (Pdfmarks.read_bookmarks pdf)
in in
@ -181,7 +181,7 @@ let typeset_table_of_contents ~font ~fontsize ~title ~bookmark ~dotleader pdf =
let firstfont = let firstfont =
hd (keep (function Cpdftype.Font _ -> true | _ -> false) (title @ flatten lines)) hd (keep (function Cpdftype.Font _ -> true | _ -> false) (title @ flatten lines))
in in
Cpdftype.typeset ~process_struct_tree:false lm rm tm bm firstpage_papersize pdf Cpdftype.typeset ~process_struct_tree lm rm tm bm firstpage_papersize pdf
([firstfont; Cpdftype.BeginDocument] @ title @ flatten lines) ([firstfont; Cpdftype.BeginDocument] @ title @ flatten lines)
in in
let toc_pages = let toc_pages =

View File

@ -1,4 +1,4 @@
(** Table of contents *) (** Table of contents *)
(** Typeset a table of contents and prepend to the document. *) (** Typeset a table of contents and prepend to the document. *)
val typeset_table_of_contents : font:Cpdfembed.cpdffont -> fontsize:float -> title:string -> bookmark:bool -> dotleader:bool -> Pdf.t -> Pdf.t val typeset_table_of_contents : font:Cpdfembed.cpdffont -> fontsize:float -> title:string -> bookmark:bool -> dotleader:bool -> process_struct_tree:bool -> Pdf.t -> Pdf.t

View File

@ -15,7 +15,7 @@ type element =
| NewLine | NewLine
| NewPage | NewPage
| Font of string * Pdftext.font * float | Font of string * Pdftext.font * float
| BeginDest of Pdfdest.t | BeginDest of Pdfdest.t * string option
| EndDest | EndDest
| BeginDocument | BeginDocument
| Tag of string * int | Tag of string * int
@ -45,7 +45,7 @@ type state =
mutable width_table : float array; (* Widths for charcodes 0..255 *) mutable width_table : float array; (* Widths for charcodes 0..255 *)
mutable xpos : float; mutable xpos : float;
mutable ypos : float; mutable ypos : float;
mutable dest : Pdfdest.t option} mutable dest : (Pdfdest.t * string option) option}
let width_table_cache = null_hash () let width_table_cache = null_hash ()
@ -232,7 +232,8 @@ let make_resources fontobjnums =
let make_annotations pdf annots = let make_annotations pdf annots =
if annots = [] then Pdf.Dictionary [] else if annots = [] then Pdf.Dictionary [] else
Pdf.Dictionary ["/Annots", Pdf.Array (map (function a -> Pdf.Indirect (Pdf.addobj pdf a)) annots)] Pdf.Dictionary ["/Annots", Pdf.Array (map (function a -> Pdf.Indirect (Pdf.addobj pdf a)) annots);
"/Tabs", Pdf.Name "/S"]
let rec number_tags n = function let rec number_tags n = function
| Tag (s, _)::t -> Tag (s, n)::number_tags (n + 1) t | Tag (s, _)::t -> Tag (s, n)::number_tags (n + 1) t
@ -329,17 +330,20 @@ let typeset ~process_struct_tree lmargin rmargin tmargin bmargin papersize pdf i
s.ypos <- tmargin +. s.fontsize s.ypos <- tmargin +. s.fontsize
| BeginDocument -> | BeginDocument ->
s.ypos <- tmargin +. s.fontsize s.ypos <- tmargin +. s.fontsize
| BeginDest dest -> | BeginDest (dest, contents) ->
s.dest <- Some dest s.dest <- Some (dest, contents)
| EndDest -> | EndDest ->
if !thisdestrectangles <> [] && s.dest <> None then if !thisdestrectangles <> [] && s.dest <> None then
let annot (minx, miny, maxx, maxy) = let annot (minx, miny, maxx, maxy) =
let dest, contents = unopt s.dest in
Pdf.Dictionary Pdf.Dictionary
((match contents with None -> [] | Some s -> [("/Contents", Pdf.String s)])
@
[("/Type", Pdf.Name "/Annot"); [("/Type", Pdf.Name "/Annot");
("/Subtype", Pdf.Name "/Link"); ("/Subtype", Pdf.Name "/Link");
("/Border", Pdf.Array [Pdf.Real 0.; Pdf.Real 0.; Pdf.Real 0.]); ("/Border", Pdf.Array [Pdf.Real 0.; Pdf.Real 0.; Pdf.Real 0.]);
("/Rect", Pdf.Array [Pdf.Real minx; Pdf.Real miny; Pdf.Real maxx; Pdf.Real maxy]); ("/Rect", Pdf.Array [Pdf.Real minx; Pdf.Real miny; Pdf.Real maxx; Pdf.Real maxy]);
("/Dest", Pdfdest.pdfobject_of_destination (unopt s.dest))] ("/Dest", Pdfdest.pdfobject_of_destination dest)])
in in
thispageannotations := map annot !thisdestrectangles @ !thispageannotations; thispageannotations := map annot !thisdestrectangles @ !thispageannotations;
s.dest <- None; s.dest <- None;

View File

@ -6,7 +6,7 @@ type element =
| NewLine | NewLine
| NewPage | NewPage
| Font of string * Pdftext.font * float | Font of string * Pdftext.font * float
| BeginDest of Pdfdest.t | BeginDest of Pdfdest.t * string option
| EndDest | EndDest
| BeginDocument | BeginDocument
| Tag of string * int | Tag of string * int