From b897197443e40207481b6738f6c5755a74ba78d8 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Thu, 31 Oct 2024 13:17:33 +0000 Subject: [PATCH] Scaffolding for -center-to-fit --- cpdfcommand.ml | 18 +++++++++++++++++- cpdfmanual.tex | 1 + cpdfpage.ml | 22 ++++++++++++++++++++++ cpdfpage.mli | 2 ++ 4 files changed, 42 insertions(+), 1 deletion(-) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index 38b17c4..5d20f82 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -106,6 +106,7 @@ type op = | Scale | ScaleToFit | Stretch + | CenterToFit | ScaleContents of float | AttachFile of string list | RemoveAttachedFiles @@ -260,6 +261,7 @@ let string_of_op = function | Scale -> "Scale" | ScaleToFit -> "ScaleToFit" | Stretch -> "Stretch" + | CenterToFit -> "CenterToFit" | ScaleContents _ -> "ScaleContents" | AttachFile _ -> "AttachFile" | RemoveAttachedFiles -> "RemoveAttachedFiles" @@ -930,7 +932,7 @@ let banned banlist = function | Rotateby _ | Upright | VFlip | HFlip | Impose _ | Chop _ | ChopHV _ | Redact -> mem Pdfcrypt.NoAssemble banlist | TwoUp | TwoUpStack | RemoveBookmarks | AddRectangle | RemoveText| - Draft | Shift | ShiftBoxes | Scale | ScaleToFit|Stretch|RemoveAttachedFiles| + Draft | Shift | ShiftBoxes | Scale | ScaleToFit|Stretch|CenterToFit|RemoveAttachedFiles| RemoveAnnotations|RemoveFonts|Crop|RemoveCrop|Trim|RemoveTrim|Bleed|RemoveBleed|Art|RemoveArt| CopyBox|MediaBox|HardBox _|SetTrapped|SetUntrapped|Presentation| BlackText|BlackLines|BlackFills|CopyFont _|StampOn _|StampUnder _|StampAsXObject _| @@ -1217,6 +1219,10 @@ let setstretch s = setop Stretch (); args.coord <- s +let setcenter s = + setop CenterToFit (); + args.coord <- s + let setattachfile s = match args.op with | Some (AttachFile t) -> @@ -2095,6 +2101,9 @@ let specs = ("-stretch", Arg.String setstretch, " -stretch \"x y\" scales without preserving aspect ratio"); + ("-center-to-fit", + Arg.String setcenter, + " -center-to-fit \"x y\" centers pages on page size (x, y)"); ("-scale-contents", Arg.Float setscalecontents, " Scale contents by the given factor"); @@ -4208,6 +4217,13 @@ let go () = let pdf = if args.prerotate then prerotate range pdf else pdf in let xylist = Cpdfcoord.parse_coordinates pdf args.coord in write_pdf false (Cpdfpage.stretch ~fast:args.fast xylist pdf range) + | Some CenterToFit -> + let pdf = get_single_pdf args.op false in + let range = parse_pagespec_allow_empty pdf (get_pagespec ()) in + warn_prerotate range pdf; + let pdf = if args.prerotate then prerotate range pdf else pdf in + let xylist = Cpdfcoord.parse_coordinates pdf args.coord in + write_pdf false (Cpdfpage.center_to_fit ~fast:args.fast xylist pdf range) | Some (ScaleContents scale) -> let pdf = get_single_pdf args.op false in let range = parse_pagespec_allow_empty pdf (get_pagespec ()) in diff --git a/cpdfmanual.tex b/cpdfmanual.tex index 5de733b..8371fc2 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -1,3 +1,4 @@ +% Document -center-to-fit \documentclass{book} % Edit here to produce cpdfmanual.pdf, cpdflibmanual.pdf, pycpdfmanual.pdf, % dotnetcpdflibmanual.pdf, jcpdflibmanual.pdf jscpdflibmanual.pdf etc. diff --git a/cpdfpage.ml b/cpdfpage.ml index c53f86a..8fb4135 100644 --- a/cpdfpage.ml +++ b/cpdfpage.ml @@ -556,6 +556,28 @@ let stretch ?(fast=false) sxsylist pdf range = in process_pages stretch_page pdf range +(* Centre page content (crop box) on given page size, with no scaling. *) +let center_to_fit ?(fast=false) sxsylist pdf range = + let stretch_page pnum page = + let sx, sy = List.nth sxsylist (pnum - 1) in + let (minx, miny, maxx, maxy) = + Pdf.parse_rectangle + pdf + (match Pdf.lookup_direct pdf "/CropBox" page.Pdfpage.rest with + | Some r -> r + | None -> page.Pdfpage.mediabox) + in + let scale_x, scale_y = sx /. (maxx -. minx), sy /. (maxy -. miny) in + let f (xmin, ymin, xmax, ymax) = xmin *. scale_x, ymin *. scale_y, xmax *. scale_x, ymax *. scale_y in + let page = change_boxes f pdf page in + let matrix = Pdftransform.matrix_of_op (Pdftransform.Scale ((0., 0.), scale_x, scale_y)) in + let transform_op = Pdfops.Op_cm matrix in + let page = change_pattern_matrices_page pdf matrix page in + Pdfannot.transform_annotations pdf matrix page.Pdfpage.rest; + (Pdfpage.prepend_operators pdf ~fast [transform_op] page, pnum, matrix) + in + process_pages stretch_page pdf range + (* Scale to fit page of size x * y *) let scale_to_fit_pdf ?(fast=false) position input_scale xylist op pdf range = let scale_page_to_fit pnum page = diff --git a/cpdfpage.mli b/cpdfpage.mli index 02c4cf1..116b090 100644 --- a/cpdfpage.mli +++ b/cpdfpage.mli @@ -81,6 +81,8 @@ val scale_to_fit_pdf : ?fast:bool -> Cpdfposition.position -> float -> (float * val stretch : ?fast:bool -> (float * float) list -> Pdf.t -> int list -> Pdf.t +val center_to_fit : ?fast:bool -> (float * float) list -> Pdf.t -> int list -> Pdf.t + (** {2 Stamping} *) (** [combine_pages fast under over scaletofit swap equalize] combines the page