diff --git a/cpdf.ml b/cpdf.ml index 306afe0..b6e343d 100644 --- a/cpdf.ml +++ b/cpdf.ml @@ -4492,3 +4492,78 @@ let ocg_order_all pdf = end | _ -> () +(* Add rectangles on top of pages to show Media, Crop, Art, Trim, Bleed boxes. + * + * We use different dash lengths and colours to help distinguish coincident + * boxes The sequence of operators is postpended to the page content, + * appropriately protected to prevent pollution of matrices. + * + * /MediaBox: Solid red line + * /CropBox: Dashed 7 on 7 off green line + * /ArtBox: Dashed 5 on 5 off blue line + * /TrimBox: Dashed 3 on 3 off orange line + * /BleedBox: Dashed 2 on 2 off pink line *) +let get_rectangle pdf page box = + if box = "/MediaBox" then + match page.Pdfpage.mediabox with + Pdf.Array [a; b; c; d] as r -> Some (Pdf.parse_rectangle r) + | _ -> None + else + match Pdf.lookup_direct pdf box page.Pdfpage.rest with + Some (Pdf.Array [a; b; c; d] as r) -> Some (Pdf.parse_rectangle r) + | _ -> None + +let show_boxes_page fast pdf _ page = + let make_ops (r, g, b) on off boxname = + match get_rectangle pdf page boxname with + Some (r1, r2, r3, r4) -> + [Pdfops.Op_q; + Pdfops.Op_RG (r /. 255., g /. 255., b /. 255.); + Pdfops.Op_w 1.; + Pdfops.Op_d ((if on = 0. && off = 0. then [] else [on; off]), 0.); + Pdfops.Op_re (r1, r2, r3 -. r1, r4 -. r2); + Pdfops.Op_S; + Pdfops.Op_Q] + | None -> [] + in + let ops = + make_ops (255., 0., 0.) 0. 0. "/MediaBox" + @ make_ops (0., 255., 0.) 7. 7. "/CropBox" + @ make_ops (0., 0., 255.) 5. 5. "/ArtBox" + @ make_ops (255.,150.,0.) 3. 3. "/TrimBox" + @ make_ops (255.,9.,147.) 2. 2. "/BleedBox" + in + Pdfpage.postpend_operators pdf ops ~fast page + +let show_boxes ?(fast=false) pdf range = + process_pages (show_boxes_page fast pdf) pdf range + +let allowance = 9. + +let line (x0, y0, x1, y1) = + [Pdfops.Op_m (x0, y0); + Pdfops.Op_l (x1, y1); + Pdfops.Op_s] + +let trim_marks_page fast pdf n page = + match get_rectangle pdf page "/TrimBox", get_rectangle pdf page "/MediaBox" with + | Some (tminx, tminy, tmaxx, tmaxy), Some (minx, miny, maxx, maxy) -> + let ops = + [Pdfops.Op_q; + Pdfops.Op_K (1., 1., 1., 1.); + Pdfops.Op_w 1.] + @ line (minx, tmaxy, tminy -. allowance, tmaxy) (* top left *) + @ line (tminx, tmaxy +. allowance, tminx, maxy) + @ line (tmaxx +. allowance, tmaxy, maxx, tmaxy) (* top right *) + @ line (tmaxx, tmaxy +. allowance, tmaxx, maxy) + @ line (tmaxx +. allowance, tminy, maxx, tminy) (* bottom right *) + @ line (tmaxx, tminy -. allowance, tmaxx, miny) + @ line (tminx -. allowance, tminy, minx, tminy) (* bottom left *) + @ line (tminx, tminy -. allowance, tminx, miny) + @ [Pdfops.Op_Q] + in + Pdfpage.postpend_operators pdf ops ~fast page + | _, _ -> Printf.eprintf "warning: no /TrimBox found on page %i\n" n; page + +let trim_marks ?(fast=false) pdf range = + process_pages (trim_marks_page fast pdf) pdf range diff --git a/cpdf.mli b/cpdf.mli index d8f2a71..2a51631 100644 --- a/cpdf.mli +++ b/cpdf.mli @@ -354,6 +354,10 @@ val scale_to_fit_pdf : ?fast:bool -> position -> float -> (float * float) list - (** Scale the contents of a page by a given factor centred around a given point in a given range. *) val scale_contents : ?fast:bool -> position -> float -> Pdf.t -> int list -> Pdf.t +val trim_marks : ?fast:bool -> Pdf.t -> int list -> Pdf.t + +val show_boxes : ?fast:bool -> Pdf.t -> int list -> Pdf.t + (** {2 Padding} *) (** Put blank pages before the given page numbers *) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index f3cb330..53fce7f 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -3504,81 +3504,6 @@ let remove_all_text range pdf = pagenums; Pdfpage.change_pages true !pdf (rev !pages') -(* Add rectangles on top of pages to show Media, Crop, Art, Trim, Bleed boxes. - * - * We use different dash lengths and colours to help distinguish coincident - * boxes The sequence of operators is postpended to the page content, - * appropriately protected to prevent pollution of matrices. - * - * /MediaBox: Solid red line - * /CropBox: Dashed 7 on 7 off green line - * /ArtBox: Dashed 5 on 5 off blue line - * /TrimBox: Dashed 3 on 3 off orange line - * /BleedBox: Dashed 2 on 2 off pink line *) -let get_rectangle pdf page box = - if box = "/MediaBox" then - match page.Pdfpage.mediabox with - Pdf.Array [a; b; c; d] as r -> Some (Pdf.parse_rectangle r) - | _ -> None - else - match Pdf.lookup_direct pdf box page.Pdfpage.rest with - Some (Pdf.Array [a; b; c; d] as r) -> Some (Pdf.parse_rectangle r) - | _ -> None - -let show_boxes_page pdf _ page = - let make_ops (r, g, b) on off boxname = - match get_rectangle pdf page boxname with - Some (r1, r2, r3, r4) -> - [Pdfops.Op_q; - Pdfops.Op_RG (r /. 255., g /. 255., b /. 255.); - Pdfops.Op_w 1.; - Pdfops.Op_d ((if on = 0. && off = 0. then [] else [on; off]), 0.); - Pdfops.Op_re (r1, r2, r3 -. r1, r4 -. r2); - Pdfops.Op_S; - Pdfops.Op_Q] - | None -> [] - in - let ops = - make_ops (255., 0., 0.) 0. 0. "/MediaBox" - @ make_ops (0., 255., 0.) 7. 7. "/CropBox" - @ make_ops (0., 0., 255.) 5. 5. "/ArtBox" - @ make_ops (255.,150.,0.) 3. 3. "/TrimBox" - @ make_ops (255.,9.,147.) 2. 2. "/BleedBox" - in - Pdfpage.postpend_operators pdf ops ~fast:args.fast page - -let show_boxes range pdf = - Cpdf.process_pages (show_boxes_page pdf) pdf range - -let allowance = 9. - -let line (x0, y0, x1, y1) = - [Pdfops.Op_m (x0, y0); - Pdfops.Op_l (x1, y1); - Pdfops.Op_s] - -let trim_marks_page pdf n page = - match get_rectangle pdf page "/TrimBox", get_rectangle pdf page "/MediaBox" with - | Some (tminx, tminy, tmaxx, tmaxy), Some (minx, miny, maxx, maxy) -> - let ops = - [Pdfops.Op_q; - Pdfops.Op_K (1., 1., 1., 1.); - Pdfops.Op_w 1.] - @ line (minx, tmaxy, tminy -. allowance, tmaxy) (* top left *) - @ line (tminx, tmaxy +. allowance, tminx, maxy) - @ line (tmaxx +. allowance, tmaxy, maxx, tmaxy) (* top right *) - @ line (tmaxx, tmaxy +. allowance, tmaxx, maxy) - @ line (tmaxx +. allowance, tminy, maxx, tminy) (* bottom right *) - @ line (tmaxx, tminy -. allowance, tmaxx, miny) - @ line (tminx -. allowance, tminy, minx, tminy) (* bottom left *) - @ line (tminx, tminy -. allowance, tminx, miny) - @ [Pdfops.Op_Q] - in - Pdfpage.postpend_operators pdf ops ~fast:args.fast page - | _, _ -> Printf.eprintf "warning: no /TrimBox found on page %i\n" n; page - -let trim_marks range pdf = - Cpdf.process_pages (trim_marks_page pdf) pdf range let write_json output pdf = match output with @@ -4458,11 +4383,11 @@ let go () = | Some ShowBoxes -> let pdf = get_single_pdf args.op false in let range = parse_pagespec pdf (get_pagespec ()) in - write_pdf false (show_boxes range pdf) + write_pdf false (Cpdf.show_boxes pdf range) | Some TrimMarks -> let pdf = get_single_pdf args.op false in let range = parse_pagespec pdf (get_pagespec ()) in - write_pdf false (trim_marks range pdf) + write_pdf false (Cpdf.trim_marks pdf range) | Some (Postpend s | Prepend s as x) -> let pdf = get_single_pdf args.op false in let range = parse_pagespec pdf (get_pagespec ()) in diff --git a/cpdfmanual.pdf b/cpdfmanual.pdf index 67e74c0..29e0092 100644 Binary files a/cpdfmanual.pdf and b/cpdfmanual.pdf differ diff --git a/cpdfmanual.tex b/cpdfmanual.tex index bfc6873..15173ee 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -657,7 +657,7 @@ the result is unspecified. The following format operators may be used: \end{tabular} \end{table} -Numbers padded to a fixed width field by zeroes may be obtained for \texttt{@S} and \texttt{@E} by following them with more \texttt{@} signs e.g \texttt{@E@@@} for a fixed width of three. +\noindent Numbers padded to a fixed width field by zeroes may be obtained for \texttt{@S} and \texttt{@E} by following them with more \texttt{@} signs e.g \texttt{@E@@@} for a fixed width of three. \section{Splitting on Bookmarks} \index{splitting!on bookmarks}