cpdfposition

This commit is contained in:
John Whitington 2021-08-12 20:38:55 +01:00
parent afe80205dd
commit 671a637271
6 changed files with 210 additions and 212 deletions

View File

@ -1,6 +1,6 @@
# Build the cpdf command line tools and top level # Build the cpdf command line tools and top level
MODS = tjutil tjutf16 tjllist tjparserMonad tjjson xmlm \ MODS = tjutil tjutf16 tjllist tjparserMonad tjjson xmlm \
cpdfwriteJSON cpdfstrftime cpdfcoord cpdfpagespec cpdf cpdfcommand cpdfwriteJSON cpdfstrftime cpdfcoord cpdfpagespec cpdfposition cpdf cpdfcommand
SOURCES = $(foreach x,$(MODS),$(x).ml $(x).mli) cpdfcommandrun.ml SOURCES = $(foreach x,$(MODS),$(x).ml $(x).mli) cpdfcommandrun.ml

197
cpdf.ml
View File

@ -1268,94 +1268,6 @@ let print_fonts pdf =
(* \section{Superimpose text, page numbers etc.} *) (* \section{Superimpose text, page numbers etc.} *)
type position =
| PosCentre of float * float
| PosLeft of float * float
| PosRight of float * float
| Top of float
| TopLeft of float
| TopRight of float
| Left of float
| BottomLeft of float
| Bottom of float
| BottomRight of float
| Right of float
| Diagonal
| ReverseDiagonal
| Centre
let string_of_position = function
| PosCentre (a, b) -> Printf.sprintf "PosCentre %f %f" a b
| PosLeft (a, b) -> Printf.sprintf "PosLeft %f %f" a b
| PosRight (a, b) -> Printf.sprintf "PosRight %f %f" a b
| Top a -> Printf.sprintf "Top %f" a
| TopLeft a -> Printf.sprintf "TopLeft %f" a
| TopRight a -> Printf.sprintf "TopRight %f" a
| Left a -> Printf.sprintf "Left %f" a
| BottomLeft a -> Printf.sprintf "BottomLeft %f" a
| Bottom a -> Printf.sprintf "Bottom %f" a
| BottomRight a -> Printf.sprintf "BottomRight %f" a
| Right a -> Printf.sprintf "Right %f" a
| Diagonal -> "Diagonal"
| ReverseDiagonal -> "Reverse Diagonal"
| Centre -> "Centre"
type orientation =
| Horizontal
| Vertical
| VerticalDown
type justification = LeftJustify | CentreJustify | RightJustify
(* Given the mediabox, calculate an absolute position for the text. *)
let calculate_position ignore_d w (xmin, ymin, xmax, ymax) orientation pos =
let rot = if orientation = VerticalDown then rad_of_deg 270. else 0. in
match pos with
| Centre ->
(xmin +. xmax) /. 2. -. w /. 2.,
(ymin +. ymax) /. 2.,
rot
| Diagonal ->
let angle = atan ((ymax -. ymin) /. (xmax -. xmin))
in let cx, cy = (xmax +. xmin) /. 2., (ymax +. ymin) /. 2. in
let dl = w /. 2. in
let dx = dl *. cos angle
in let dy = dl *. sin angle in
cx -. dx, cy -. dy, angle
| ReverseDiagonal ->
let angle = atan ((ymax -. ymin) /. (xmax -. xmin))
in let cx, cy = (xmax +. xmin) /. 2., (ymax +. ymin) /. 2. in
let dl = w /. 2. in
let dx = dl *. cos angle
in let dy = dl *. sin angle in
cx -. dx, (ymax +. ymin) -. (cy -. dy), angle -. ((2. *. pi) -. ((pi -. (2. *. angle)) *. 2.) /. 2.) +. pi
| PosLeft (x, y) -> xmin +. x, ymin +. y, rot
| PosCentre (x, y) -> xmin +. x -. (w /. 2.), ymin +. y, rot
| PosRight (x, y) -> xmin +. x -. w, ymin +. y, rot
| Top d ->
let d = if ignore_d then 0. else d in
(xmin +. xmax) /. 2. -. w /. 2., ymax -. d, rot
| TopLeft d ->
let d = if ignore_d then 0. else d in
xmin +. d, ymax -. d, rot
| TopRight d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, ymax -. d, rot
| Left d ->
let d = if ignore_d then 0. else d in
xmin +. d, (ymax +. ymin) /. 2., rot
| BottomLeft d ->
let d = if ignore_d then 0. else d in
xmin +. d, ymin +. d, rot
| Bottom d ->
let d = if ignore_d then 0. else d in
(xmin +. xmax) /. 2. -. w /. 2., ymin +. d, rot
| BottomRight d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, ymin +. d, rot
| Right d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, (ymax +. ymin) /. 2., rot
(* Process UTF8 text to /WinAnsiEncoding string. *) (* Process UTF8 text to /WinAnsiEncoding string. *)
let winansi_of_utf8 s = let winansi_of_utf8 s =
@ -1445,33 +1357,37 @@ let ops longest_w metrics x y rotate hoffset voffset outline linewidth unique_fo
Pdfops.Op_EMC; Pdfops.Op_EMC;
Pdfops.Op_Q] Pdfops.Op_Q]
type justification = LeftJustify | CentreJustify | RightJustify
(* Find the h-offset for justification based on the longest width, the current (* Find the h-offset for justification based on the longest width, the current
width, the justification and the position. *) width, the justification and the position. *)
let find_justification_offsets longest_w w position = function let find_justification_offsets longest_w w position j =
| LeftJustify -> let open Cpdfposition in
begin match position with match j with
| TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> 0. | LeftJustify ->
| Top _ | PosCentre _ | Bottom _ | Centre -> (longest_w -. w) /. 2. begin match position with
| TopRight _ | BottomRight _ | PosRight _ | Right _ -> longest_w -. w | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> 0.
| Diagonal -> 0. | Top _ | PosCentre _ | Bottom _ | Centre -> (longest_w -. w) /. 2.
| ReverseDiagonal -> 0. | TopRight _ | BottomRight _ | PosRight _ | Right _ -> longest_w -. w
end | Diagonal -> 0.
| RightJustify -> | ReverseDiagonal -> 0.
begin match position with end
| TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.(longest_w -. w) | RightJustify ->
| Top _ | PosCentre _ | Bottom _ | Centre -> ~-.((longest_w -. w) /. 2.) begin match position with
| TopRight _ | BottomRight _ | PosRight _ | Right _ -> 0. | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.(longest_w -. w)
| Diagonal -> 0. | Top _ | PosCentre _ | Bottom _ | Centre -> ~-.((longest_w -. w) /. 2.)
| ReverseDiagonal -> 0. | TopRight _ | BottomRight _ | PosRight _ | Right _ -> 0.
end | Diagonal -> 0.
| CentreJustify -> | ReverseDiagonal -> 0.
begin match position with end
| TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.((longest_w -. w) /. 2.) | CentreJustify ->
| Top _ | PosCentre _ | Bottom _ | Centre -> 0. begin match position with
| TopRight _ | BottomRight _ | PosRight _ | Right _ -> (longest_w -. w) /. 2. | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.((longest_w -. w) /. 2.)
| Diagonal -> 0. | Top _ | PosCentre _ | Bottom _ | Centre -> 0.
| ReverseDiagonal -> 0. | TopRight _ | BottomRight _ | PosRight _ | Right _ -> (longest_w -. w) /. 2.
end | Diagonal -> 0.
| ReverseDiagonal -> 0.
end
(* Lex an integer from the table *) (* Lex an integer from the table *)
let extract_num header s = let extract_num header s =
@ -1599,6 +1515,8 @@ let extract_text extract_text_font_size pdf range =
fold_left (fun x y -> x ^ (if x <> "" && y <> "" then "\n" else "") ^ y) "" fold_left (fun x y -> x ^ (if x <> "" && y <> "" then "\n" else "") ^ y) ""
(map_pages (extract_page_text extract_text_font_size pdf) pdf range) (map_pages (extract_page_text extract_text_font_size pdf) pdf range)
let addtext let addtext
metrics lines linewidth outline fast colour fontname embed bates batespad fontsize font metrics lines linewidth outline fast colour fontname embed bates batespad fontsize font
underneath position hoffset voffset text pages orientation cropbox opacity underneath position hoffset voffset text pages orientation cropbox opacity
@ -1696,7 +1614,7 @@ let addtext
else else
Pdf.parse_rectangle page.Pdfpage.mediabox Pdf.parse_rectangle page.Pdfpage.mediabox
in in
let x, y, rotate = calculate_position false textwidth mediabox orientation position in let x, y, rotate = Cpdfposition.calculate_position false textwidth mediabox orientation position in
let hoffset, voffset = let hoffset, voffset =
if position = Diagonal || position = ReverseDiagonal if position = Diagonal || position = ReverseDiagonal
then -. (cos ((pi /. 2.) -. rotate) *. voffset), sin ((pi /. 2.) -. rotate) *. voffset then -. (cos ((pi /. 2.) -. rotate) *. voffset), sin ((pi /. 2.) -. rotate) *. voffset
@ -1785,6 +1703,7 @@ let
let lines = map unescape_string (split_at_newline text) in let lines = map unescape_string (split_at_newline text) in
let pdf = ref pdf in let pdf = ref pdf in
let voffset = let voffset =
let open Cpdfposition in
match position with match position with
| Bottom _ | BottomLeft _ | BottomRight _ -> | Bottom _ | BottomLeft _ | BottomRight _ ->
ref (0. -. (linespacing *. fontsize *. (float (length lines) -. 1.))) ref (0. -. (linespacing *. fontsize *. (float (length lines) -. 1.)))
@ -1824,7 +1743,7 @@ let
iter iter
(fun line -> (fun line ->
let voff, hoff = let voff, hoff =
if orientation = Vertical then 0., -.(!voffset) else !voffset, 0. if orientation = Cpdfposition.Vertical then 0., -.(!voffset) else !voffset, 0.
in in
pdf := pdf :=
addtext metrics lines linewidth outline fast colour fontname addtext metrics lines linewidth outline fast colour fontname
@ -2241,20 +2160,21 @@ let stamp_shift_of_position topline midline sw sh w h p =
else if topline then sh else if topline then sh
else 0. else 0.
in in
match p with let open Cpdfposition in
| PosCentre (ox, oy) -> ox -. half sw, oy -. dy match p with
| PosLeft (ox, oy) -> ox, oy -. dy | PosCentre (ox, oy) -> ox -. half sw, oy -. dy
| PosRight (ox, oy) -> ox -. sw, oy -. dy | PosLeft (ox, oy) -> ox, oy -. dy
| Top o -> half w -. half sw, h -. o -. sh -. dy | PosRight (ox, oy) -> ox -. sw, oy -. dy
| TopLeft o -> o, h -. sh -. o -. dy | Top o -> half w -. half sw, h -. o -. sh -. dy
| TopRight o -> w -. sw -. o, h -. sh -. o -. dy | TopLeft o -> o, h -. sh -. o -. dy
| Left o -> o, half h -. half sh -. dy | TopRight o -> w -. sw -. o, h -. sh -. o -. dy
| BottomLeft o -> o, o -. dy | Left o -> o, half h -. half sh -. dy
| Bottom o -> half w -. half sw, o -. dy | BottomLeft o -> o, o -. dy
| BottomRight o -> w -. sw -. o, o -. dy | Bottom o -> half w -. half sw, o -. dy
| Right o -> w -. sw -. o, half h -. half sh -. dy | BottomRight o -> w -. sw -. o, o -. dy
| Diagonal | ReverseDiagonal | Centre -> | Right o -> w -. sw -. o, half h -. half sh -. dy
half w -. half sw, half h -. half sh -. dy | Diagonal | ReverseDiagonal | Centre ->
half w -. half sw, half h -. half sh -. dy
(* Combine Pdfpage.rest items for two PDFs. For now, we combine /Annots, and (* Combine Pdfpage.rest items for two PDFs. For now, we combine /Annots, and
* copy everything else from adict. What else should we combine? *) * copy everything else from adict. What else should we combine? *)
@ -2819,13 +2739,13 @@ let scale_to_fit_pdf ?(fast=false) position input_scale xylist op pdf range =
let scale = fmin fx fy *. input_scale in let scale = fmin fx fy *. input_scale in
let trans_x = let trans_x =
match position with match position with
Left _ -> 0. Cpdfposition.Left _ -> 0.
| Right _ -> (x -. (maxx *. scale)) | Cpdfposition.Right _ -> (x -. (maxx *. scale))
| _ -> (x -. (maxx *. scale)) /. 2. | _ -> (x -. (maxx *. scale)) /. 2.
and trans_y = and trans_y =
match position with match position with
| Top _ -> (y -. (maxy *. scale)) | Cpdfposition.Top _ -> (y -. (maxy *. scale))
| Bottom _ -> 0. | Cpdfposition.Bottom _ -> 0.
| _ -> (y -. (maxy *. scale)) /. 2. | _ -> (y -. (maxy *. scale)) /. 2.
in in
(Pdftransform.matrix_of_transform (Pdftransform.matrix_of_transform
@ -2853,8 +2773,9 @@ let scale_page_contents ?(fast=false) scale position pdf pnum page =
| Some r -> r | Some r -> r
| None -> page.Pdfpage.mediabox) | None -> page.Pdfpage.mediabox)
in in
let sx, sy, _ = calculate_position true 0. box Horizontal position in let sx, sy, _ = Cpdfposition.calculate_position true 0. box Horizontal position in
let tx, ty = let tx, ty =
let open Cpdfposition in
match position with match position with
| Top t -> 0., -.t | Top t -> 0., -.t
| TopLeft t -> t, -.t | TopLeft t -> t, -.t
@ -3343,14 +3264,8 @@ let dc = "http://purl.org/dc/elements/1.1/"
let rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#" let rdf = "http://www.w3.org/1999/02/22-rdf-syntax-ns#"
(* For OCaml < 4.00 *)
let string_trim s =
implode
(rev (dropwhile
Pdf.is_whitespace (rev (dropwhile Pdf.is_whitespace (explode s)))))
let combine_with_spaces strs = let combine_with_spaces strs =
string_trim String.trim
(fold_left (fun x y -> x ^ (if x <> "" then ", " else "") ^ y) "" strs) (fold_left (fun x y -> x ^ (if x <> "" then ", " else "") ^ y) "" strs)
(* Collect all <li> elements inside a seq, bag, or alt. Combine with commas. If (* Collect all <li> elements inside a seq, bag, or alt. Combine with commas. If

View File

@ -14,23 +14,6 @@ exception HardError of string
(** Two exceptions recommended for use with the library, though currently not (** Two exceptions recommended for use with the library, though currently not
raised by any function in this module. Cpdfcommand uses them extensively. *) raised by any function in this module. Cpdfcommand uses them extensively. *)
(** Possible positions for adding text and other uses. See cpdfmanual.pdf *)
type position =
| PosCentre of float * float
| PosLeft of float * float
| PosRight of float * float
| Top of float
| TopLeft of float
| TopRight of float
| Left of float
| BottomLeft of float
| Bottom of float
| BottomRight of float
| Right of float
| Diagonal
| ReverseDiagonal
| Centre
(** {2 Debug} *) (** {2 Debug} *)
(** Debug: Print out a PDF in readable form to the terminal *) (** Debug: Print out a PDF in readable form to the terminal *)
@ -174,7 +157,7 @@ val combine_pages : bool -> Pdf.t -> Pdf.t -> bool -> bool -> bool -> Pdf.t
(** [stamp relative_to_cropbox position topline midline fast scale_to_fit isover range over pdf] stamps the first page of (** [stamp relative_to_cropbox position topline midline fast scale_to_fit isover range over pdf] stamps the first page of
[over] over each page of the PDF. The arguments have the same meaning as in [over] over each page of the PDF. The arguments have the same meaning as in
[combine_pages]. *) [combine_pages]. *)
val stamp : bool -> position -> bool -> bool -> bool -> bool -> bool -> int list -> Pdf.t -> Pdf.t -> Pdf.t val stamp : bool -> Cpdfposition.position -> bool -> bool -> bool -> bool -> bool -> int list -> Pdf.t -> Pdf.t -> Pdf.t
(** {2 Splitting PDFs} *) (** {2 Splitting PDFs} *)
@ -194,32 +177,12 @@ val list_fonts : Pdf.t -> (int * string * string * string * string) list
(** Expand the string "now" to a PDF date string, ignoring any other string *) (** Expand the string "now" to a PDF date string, ignoring any other string *)
val expand_date : string -> string val expand_date : string -> string
(** Produce a debug string of a [position] *)
val string_of_position : position -> string
(** Orientation of the string on the page *)
type orientation =
| Horizontal
| Vertical
| VerticalDown
(** Justification of multiline text *) (** Justification of multiline text *)
type justification = type justification =
| LeftJustify | LeftJustify
| CentreJustify | CentreJustify
| RightJustify | RightJustify
(** [calculate_position ignore_d w (xmin, ymin, xmax, ymax) orientation pos] calculates
the absolute position of text given its width, bounding box, orientation and
position. If [ignore_d] is true, the distance from the position (e.g 10 in
TopLeft 10) is ignored (considered zero). *)
val calculate_position :
bool ->
float ->
float * float * float * float ->
orientation -> position -> float * float * float
(** Call [add_texts metrics linewidth outline fast fontname font bates batespad colour (** Call [add_texts metrics linewidth outline fast fontname font bates batespad colour
position linespacing fontsize underneath text pages orientation position linespacing fontsize underneath text pages orientation
relative_to_cropbox midline_adjust topline filename pdf]. For details see cpdfmanual.pdf *) relative_to_cropbox midline_adjust topline filename pdf]. For details see cpdfmanual.pdf *)
@ -234,13 +197,13 @@ val addtexts :
int -> (* bates number *) int -> (* bates number *)
int option -> (* bates padding width *) int option -> (* bates padding width *)
float * float * float -> (*colour*) float * float * float -> (*colour*)
position -> (*position*) Cpdfposition.position -> (*position*)
float -> (*linespacing*) float -> (*linespacing*)
float -> (*fontsize*) float -> (*fontsize*)
bool -> (*underneath*) bool -> (*underneath*)
string ->(*text*) string ->(*text*)
int list ->(*page range*) int list ->(*page range*)
orientation ->(*orientation*) Cpdfposition.orientation ->(*orientation*)
bool ->(*relative to cropbox?*) bool ->(*relative to cropbox?*)
float ->(*opacity*) float ->(*opacity*)
justification ->(*justification*) justification ->(*justification*)
@ -323,10 +286,10 @@ val scale_pdf : ?fast:bool -> (float * float) list -> Pdf.t -> int list -> Pdf.t
(** [scale_to_fit_pdf fast position input_scale x y op pdf range] scales a page to fit the (** [scale_to_fit_pdf fast position input_scale x y op pdf range] scales a page to fit the
page size given by (x, y) and by the [input_scale] (e.g 1.0 = scale to fit, 0.9 page size given by (x, y) and by the [input_scale] (e.g 1.0 = scale to fit, 0.9
= scale to fit leaving a border etc.). [op] is unused. *) = scale to fit leaving a border etc.). [op] is unused. *)
val scale_to_fit_pdf : ?fast:bool -> position -> float -> (float * float) list -> 'a -> Pdf.t -> int list -> Pdf.t val scale_to_fit_pdf : ?fast:bool -> Cpdfposition.position -> float -> (float * float) list -> 'a -> Pdf.t -> int list -> Pdf.t
(** Scale the contents of a page by a given factor centred around a given point in a given range. *) (** 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 scale_contents : ?fast:bool -> Cpdfposition.position -> float -> Pdf.t -> int list -> Pdf.t
val trim_marks : ?fast:bool -> Pdf.t -> int list -> Pdf.t val trim_marks : ?fast:bool -> Pdf.t -> int list -> Pdf.t

View File

@ -379,7 +379,7 @@ type args =
mutable fontsize : float; mutable fontsize : float;
mutable color : float * float * float; mutable color : float * float * float;
mutable opacity : float; mutable opacity : float;
mutable position : Cpdf.position; mutable position : Cpdfposition.position;
mutable underneath : bool; mutable underneath : bool;
mutable linespacing : float; mutable linespacing : float;
mutable midline : bool; mutable midline : bool;
@ -388,7 +388,7 @@ type args =
mutable bates : int; mutable bates : int;
mutable batespad : int option; mutable batespad : int option;
mutable prerotate : bool; mutable prerotate : bool;
mutable orientation : Cpdf.orientation; mutable orientation : Cpdfposition.orientation;
mutable relative_to_cropbox : bool; mutable relative_to_cropbox : bool;
mutable keepversion : bool; mutable keepversion : bool;
mutable bycolumns : bool; mutable bycolumns : bool;
@ -483,7 +483,7 @@ let args =
fontsize = 12.; fontsize = 12.;
color = 0., 0., 0.; color = 0., 0., 0.;
opacity = 1.; opacity = 1.;
position = Cpdf.TopLeft 100.; position = Cpdfposition.TopLeft 100.;
underneath = false; underneath = false;
linespacing = 1.; linespacing = 1.;
midline = false; midline = false;
@ -492,7 +492,7 @@ let args =
bates = 0; bates = 0;
batespad = None; batespad = None;
prerotate = false; prerotate = false;
orientation = Cpdf.Horizontal; orientation = Cpdfposition.Horizontal;
relative_to_cropbox = false; relative_to_cropbox = false;
keepversion = false; keepversion = false;
bycolumns = false; bycolumns = false;
@ -587,7 +587,7 @@ let reset_arguments () =
args.fontsize <- 12.; args.fontsize <- 12.;
args.color <- 0., 0., 0.; args.color <- 0., 0., 0.;
args.opacity <- 1.; args.opacity <- 1.;
args.position <- Cpdf.TopLeft 100.; args.position <- Cpdfposition.TopLeft 100.;
args.underneath <- false; args.underneath <- false;
args.linespacing <- 1.; args.linespacing <- 1.;
args.midline <- false; args.midline <- false;
@ -596,7 +596,7 @@ let reset_arguments () =
args.bates <- 0; args.bates <- 0;
args.batespad <- None; args.batespad <- None;
args.prerotate <- false; args.prerotate <- false;
args.orientation <- Cpdf.Horizontal; args.orientation <- Cpdfposition.Horizontal;
args.relative_to_cropbox <- false; args.relative_to_cropbox <- false;
args.keepversion <- false; args.keepversion <- false;
args.bycolumns <- false; args.bycolumns <- false;
@ -1047,11 +1047,11 @@ let setaddbookmarks s =
let setstampon f = let setstampon f =
setop (StampOn f) (); setop (StampOn f) ();
(* Due to an earlier bad decision (default position), we have this nasty hack *) (* Due to an earlier bad decision (default position), we have this nasty hack *)
if args.position = Cpdf.TopLeft 100. then args.position <- Cpdf.BottomLeft 0. if args.position = Cpdfposition.TopLeft 100. then args.position <- Cpdfposition.BottomLeft 0.
let setstampunder f = let setstampunder f =
setop (StampUnder f) (); setop (StampUnder f) ();
if args.position = Cpdf.TopLeft 100. then args.position <- Cpdf.BottomLeft 0. if args.position = Cpdfposition.TopLeft 100. then args.position <- Cpdfposition.BottomLeft 0.
let setstampasxobject f = let setstampasxobject f =
setop (StampAsXObject f) () setop (StampAsXObject f) ()
@ -1061,58 +1061,58 @@ let setcombinepages f =
let setposcenter s = let setposcenter s =
let x, y = Cpdfcoord.parse_coordinate empty s in let x, y = Cpdfcoord.parse_coordinate empty s in
args.position <- Cpdf.PosCentre (x, y) args.position <- Cpdfposition.PosCentre (x, y)
let setposleft s = let setposleft s =
let x, y = Cpdfcoord.parse_coordinate empty s in let x, y = Cpdfcoord.parse_coordinate empty s in
args.position <- Cpdf.PosLeft (x, y) args.position <- Cpdfposition.PosLeft (x, y)
let setposright s = let setposright s =
let x, y = Cpdfcoord.parse_coordinate empty s in let x, y = Cpdfcoord.parse_coordinate empty s in
args.position <- Cpdf.PosRight (x, y) args.position <- Cpdfposition.PosRight (x, y)
let settop n = let settop n =
args.position <- Cpdf.Top (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.Top (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.CentreJustify args.justification <- Cpdf.CentreJustify
let settopleft n = let settopleft n =
args.position <- Cpdf.TopLeft (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.TopLeft (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.LeftJustify args.justification <- Cpdf.LeftJustify
let settopright n = let settopright n =
args.position <- Cpdf.TopRight (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.TopRight (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.RightJustify args.justification <- Cpdf.RightJustify
let setleft n = let setleft n =
args.position <- Cpdf.Left (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.Left (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.LeftJustify args.justification <- Cpdf.LeftJustify
let setbottomleft n = let setbottomleft n =
args.position <- Cpdf.BottomLeft (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.BottomLeft (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.LeftJustify args.justification <- Cpdf.LeftJustify
let setbottom n = let setbottom n =
args.position <- Cpdf.Bottom (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.Bottom (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.CentreJustify args.justification <- Cpdf.CentreJustify
let setbottomright n = let setbottomright n =
args.position <- Cpdf.BottomRight (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.BottomRight (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.RightJustify args.justification <- Cpdf.RightJustify
let setright n = let setright n =
args.position <- Cpdf.Right (Cpdfcoord.parse_single_number empty n); args.position <- Cpdfposition.Right (Cpdfcoord.parse_single_number empty n);
args.justification <- Cpdf.RightJustify args.justification <- Cpdf.RightJustify
let setdiagonal n = let setdiagonal n =
args.position <- Cpdf.Diagonal; args.position <- Cpdfposition.Diagonal;
args.justification <- Cpdf.CentreJustify args.justification <- Cpdf.CentreJustify
let setreversediagonal n = let setreversediagonal n =
args.position <- Cpdf.ReverseDiagonal; args.position <- Cpdfposition.ReverseDiagonal;
args.justification <- Cpdf.CentreJustify args.justification <- Cpdf.CentreJustify
let setcenter n = let setcenter n =
args.position <- Cpdf.Centre; args.position <- Cpdfposition.Centre;
args.justification <- Cpdf.CentreJustify args.justification <- Cpdf.CentreJustify
let setbatespad n = let setbatespad n =
@ -1220,7 +1220,7 @@ let setscaletofitscale f =
let setscalecontents f = let setscalecontents f =
detect_duplicate_op (ScaleContents f); detect_duplicate_op (ScaleContents f);
args.op <- Some (ScaleContents f); args.op <- Some (ScaleContents f);
args.position <- Cpdf.Diagonal (* Will be center *) args.position <- Cpdfposition.Diagonal (* Will be center *)
let setsqueeze () = let setsqueeze () =
args.squeeze <- true; args.squeeze <- true;
@ -1345,10 +1345,10 @@ let setp2ppath p =
args.path_to_p2p <- p args.path_to_p2p <- p
let settextvertical () = let settextvertical () =
args.orientation <- Cpdf.Vertical args.orientation <- Cpdfposition.Vertical
let settextverticaldown () = let settextverticaldown () =
args.orientation <- Cpdf.VerticalDown args.orientation <- Cpdfposition.VerticalDown
let setfrombox s = let setfrombox s =
detect_duplicate_op CopyBox; detect_duplicate_op CopyBox;
@ -3351,12 +3351,12 @@ let addrectangle
Pdf.parse_rectangle page.Pdfpage.mediabox Pdf.parse_rectangle page.Pdfpage.mediabox
in in
let x, y, _ = let x, y, _ =
Cpdf.calculate_position false w mediabox Cpdf.Horizontal position Cpdfposition.calculate_position false w mediabox Cpdfposition.Horizontal position
in in
let x, y = let x, y =
match position with match position with
Cpdf.Top _ | Cpdf.TopLeft _ | Cpdf.TopRight _ -> (x, y -. h) Cpdfposition.Top _ | Cpdfposition.TopLeft _ | Cpdfposition.TopRight _ -> (x, y -. h)
| Cpdf.Centre | Cpdf.PosCentre _ -> (x, y -. (h /. 2.)) | Cpdfposition.Centre | Cpdfposition.PosCentre _ -> (x, y -. (h /. 2.))
| _ -> (x, y) | _ -> (x, y)
in in
let ops = let ops =

88
cpdfposition.ml Normal file
View File

@ -0,0 +1,88 @@
open Pdfutil
type position =
| PosCentre of float * float
| PosLeft of float * float
| PosRight of float * float
| Top of float
| TopLeft of float
| TopRight of float
| Left of float
| BottomLeft of float
| Bottom of float
| BottomRight of float
| Right of float
| Diagonal
| ReverseDiagonal
| Centre
let string_of_position = function
| PosCentre (a, b) -> Printf.sprintf "PosCentre %f %f" a b
| PosLeft (a, b) -> Printf.sprintf "PosLeft %f %f" a b
| PosRight (a, b) -> Printf.sprintf "PosRight %f %f" a b
| Top a -> Printf.sprintf "Top %f" a
| TopLeft a -> Printf.sprintf "TopLeft %f" a
| TopRight a -> Printf.sprintf "TopRight %f" a
| Left a -> Printf.sprintf "Left %f" a
| BottomLeft a -> Printf.sprintf "BottomLeft %f" a
| Bottom a -> Printf.sprintf "Bottom %f" a
| BottomRight a -> Printf.sprintf "BottomRight %f" a
| Right a -> Printf.sprintf "Right %f" a
| Diagonal -> "Diagonal"
| ReverseDiagonal -> "Reverse Diagonal"
| Centre -> "Centre"
type orientation =
| Horizontal
| Vertical
| VerticalDown
(* Given the mediabox, calculate an absolute position for the text. *)
let calculate_position ignore_d w (xmin, ymin, xmax, ymax) orientation pos =
let rot = if orientation = VerticalDown then rad_of_deg 270. else 0. in
match pos with
| Centre ->
(xmin +. xmax) /. 2. -. w /. 2.,
(ymin +. ymax) /. 2.,
rot
| Diagonal ->
let angle = atan ((ymax -. ymin) /. (xmax -. xmin))
in let cx, cy = (xmax +. xmin) /. 2., (ymax +. ymin) /. 2. in
let dl = w /. 2. in
let dx = dl *. cos angle
in let dy = dl *. sin angle in
cx -. dx, cy -. dy, angle
| ReverseDiagonal ->
let angle = atan ((ymax -. ymin) /. (xmax -. xmin))
in let cx, cy = (xmax +. xmin) /. 2., (ymax +. ymin) /. 2. in
let dl = w /. 2. in
let dx = dl *. cos angle
in let dy = dl *. sin angle in
cx -. dx, (ymax +. ymin) -. (cy -. dy), angle -. ((2. *. pi) -. ((pi -. (2. *. angle)) *. 2.) /. 2.) +. pi
| PosLeft (x, y) -> xmin +. x, ymin +. y, rot
| PosCentre (x, y) -> xmin +. x -. (w /. 2.), ymin +. y, rot
| PosRight (x, y) -> xmin +. x -. w, ymin +. y, rot
| Top d ->
let d = if ignore_d then 0. else d in
(xmin +. xmax) /. 2. -. w /. 2., ymax -. d, rot
| TopLeft d ->
let d = if ignore_d then 0. else d in
xmin +. d, ymax -. d, rot
| TopRight d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, ymax -. d, rot
| Left d ->
let d = if ignore_d then 0. else d in
xmin +. d, (ymax +. ymin) /. 2., rot
| BottomLeft d ->
let d = if ignore_d then 0. else d in
xmin +. d, ymin +. d, rot
| Bottom d ->
let d = if ignore_d then 0. else d in
(xmin +. xmax) /. 2. -. w /. 2., ymin +. d, rot
| BottomRight d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, ymin +. d, rot
| Right d ->
let d = if ignore_d then 0. else d in
xmax -. d -. w, (ymax +. ymin) /. 2., rot

32
cpdfposition.mli Normal file
View File

@ -0,0 +1,32 @@
(** Possible positions for adding text and other uses. See cpdfmanual.pdf *)
type position =
PosCentre of float * float
| PosLeft of float * float
| PosRight of float * float
| Top of float
| TopLeft of float
| TopRight of float
| Left of float
| BottomLeft of float
| Bottom of float
| BottomRight of float
| Right of float
| Diagonal
| ReverseDiagonal
| Centre
(** Produce a debug string of a [position] *)
val string_of_position : position -> string
(** Orientation of the string on the page *)
type orientation = Horizontal | Vertical | VerticalDown
(** [calculate_position ignore_d w (xmin, ymin, xmax, ymax) orientation pos] calculates
the absolute position of text given its width, bounding box, orientation and
position. If [ignore_d] is true, the distance from the position (e.g 10 in
TopLeft 10) is ignored (considered zero). *)
val calculate_position :
bool ->
float ->
float * float * float * float ->
orientation -> position -> float * float * float