diff --git a/Makefile b/Makefile
index b61d8f8..e9c6302 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
 # Build the cpdf command line tools and top level
 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
 
diff --git a/cpdf.ml b/cpdf.ml
index 73fe76f..463be48 100644
--- a/cpdf.ml
+++ b/cpdf.ml
@@ -1268,94 +1268,6 @@ let print_fonts pdf =
 
 (* \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. *)
 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_Q]
 
+type justification = LeftJustify | CentreJustify | RightJustify
+
 (* Find the h-offset for justification based on the longest width, the current
 width, the justification and the position. *)
-let find_justification_offsets longest_w w position = function
-  | LeftJustify ->
-      begin match position with
-      | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> 0.
-      | Top _ | PosCentre _ | Bottom _ | Centre -> (longest_w -. w) /. 2.
-      | TopRight _ | BottomRight _ | PosRight _ | Right _ -> longest_w -. w
-      | Diagonal -> 0.
-      | ReverseDiagonal -> 0.
-      end
-  | RightJustify ->
-      begin match position with
-      | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.(longest_w -. w)
-      | Top _ | PosCentre _ | Bottom _ | Centre -> ~-.((longest_w -. w) /. 2.)
-      | TopRight _ | BottomRight _ | PosRight _ | Right _ -> 0.
-      | Diagonal -> 0.
-      | ReverseDiagonal -> 0.
-      end
-  | CentreJustify ->
-      begin match position with
-      | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.((longest_w -. w) /. 2.)
-      | Top _ | PosCentre _ | Bottom _ | Centre -> 0.
-      | TopRight _ | BottomRight _ | PosRight _ | Right _ -> (longest_w -. w) /. 2.
-      | Diagonal -> 0.
-      | ReverseDiagonal -> 0.
-      end
+let find_justification_offsets longest_w w position j =
+  let open Cpdfposition in
+    match j with
+    | LeftJustify ->
+        begin match position with
+        | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> 0.
+        | Top _ | PosCentre _ | Bottom _ | Centre -> (longest_w -. w) /. 2.
+        | TopRight _ | BottomRight _ | PosRight _ | Right _ -> longest_w -. w
+        | Diagonal -> 0.
+        | ReverseDiagonal -> 0.
+        end
+    | RightJustify ->
+        begin match position with
+        | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.(longest_w -. w)
+        | Top _ | PosCentre _ | Bottom _ | Centre -> ~-.((longest_w -. w) /. 2.)
+        | TopRight _ | BottomRight _ | PosRight _ | Right _ -> 0.
+        | Diagonal -> 0.
+        | ReverseDiagonal -> 0.
+        end
+    | CentreJustify ->
+        begin match position with
+        | TopLeft _ | Left _ | PosLeft _ | BottomLeft _ -> ~-.((longest_w -. w) /. 2.)
+        | Top _ | PosCentre _ | Bottom _ | Centre -> 0.
+        | TopRight _ | BottomRight _ | PosRight _ | Right _ -> (longest_w -. w) /. 2.
+        | Diagonal -> 0.
+        | ReverseDiagonal -> 0.
+        end
 
 (* Lex an integer from the table *)
 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) ""
     (map_pages (extract_page_text extract_text_font_size pdf) pdf range)
 
+
+
 let addtext
   metrics lines linewidth outline fast colour fontname embed bates batespad fontsize font
   underneath position hoffset voffset text pages orientation cropbox opacity
@@ -1696,7 +1614,7 @@ let addtext
                     else
                       Pdf.parse_rectangle page.Pdfpage.mediabox
                   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 =
                         if position = Diagonal || position = ReverseDiagonal
                           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 pdf = ref pdf in
         let voffset =
+          let open Cpdfposition in
           match position with
           | Bottom _ | BottomLeft _ | BottomRight _ ->
               ref (0. -. (linespacing *. fontsize *. (float (length lines) -. 1.)))
@@ -1824,7 +1743,7 @@ let
           iter
             (fun line ->
                let voff, hoff =
-                 if orientation = Vertical then 0., -.(!voffset) else !voffset, 0.
+                 if orientation = Cpdfposition.Vertical then 0., -.(!voffset) else !voffset, 0.
                in
                  pdf :=
                    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 0.
   in
-    match p with
-    | PosCentre (ox, oy) -> ox -. half sw, oy -. dy
-    | PosLeft (ox, oy) -> ox, oy -. dy
-    | PosRight (ox, oy) -> ox -. sw, oy -. dy
-    | Top o -> half w -. half sw, h -. o -. sh -. dy
-    | TopLeft o -> o, h -. sh -. o -. dy
-    | TopRight o -> w -. sw -. o, h -. sh -. o -. dy
-    | Left o -> o, half h -. half sh -. dy
-    | BottomLeft o -> o, o -. dy
-    | Bottom o -> half w -. half sw, o -. dy
-    | BottomRight o -> w -. sw -. o, o -. dy
-    | Right o -> w -. sw -. o, half h -. half sh -. dy
-    | Diagonal | ReverseDiagonal | Centre ->
-        half w -. half sw, half h -. half sh -. dy
+    let open Cpdfposition in
+      match p with
+      | PosCentre (ox, oy) -> ox -. half sw, oy -. dy
+      | PosLeft (ox, oy) -> ox, oy -. dy
+      | PosRight (ox, oy) -> ox -. sw, oy -. dy
+      | Top o -> half w -. half sw, h -. o -. sh -. dy
+      | TopLeft o -> o, h -. sh -. o -. dy
+      | TopRight o -> w -. sw -. o, h -. sh -. o -. dy
+      | Left o -> o, half h -. half sh -. dy
+      | BottomLeft o -> o, o -. dy
+      | Bottom o -> half w -. half sw, o -. dy
+      | BottomRight o -> w -. sw -. o, o -. dy
+      | Right o -> w -. sw -. o, 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
  * 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 trans_x =
                 match position with
-                  Left _ -> 0.
-                | Right _ -> (x -. (maxx *. scale))
+                  Cpdfposition.Left _ -> 0.
+                | Cpdfposition.Right _ -> (x -. (maxx *. scale))
                 | _ -> (x -. (maxx *. scale)) /. 2.
               and trans_y =
                 match position with
-                | Top _ -> (y -. (maxy *. scale))
-                | Bottom _ -> 0.
+                | Cpdfposition.Top _ -> (y -. (maxy *. scale))
+                | Cpdfposition.Bottom _ -> 0.
                 | _ -> (y -. (maxy *. scale)) /. 2.
               in
                 (Pdftransform.matrix_of_transform
@@ -2853,8 +2773,9 @@ let scale_page_contents ?(fast=false) scale position pdf pnum page =
        | Some r -> r
        | None -> page.Pdfpage.mediabox)
   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 open Cpdfposition in
         match position with
         | Top t -> 0., -.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#"
 
-(* 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 =
-  string_trim
+  String.trim
     (fold_left (fun x y -> x ^ (if x <> "" then ", " else "") ^ y) "" strs)
 
 (* Collect all 
 elements inside a seq, bag, or alt. Combine with commas. If
diff --git a/cpdf.mli b/cpdf.mli
index ea06c35..027cc18 100644
--- a/cpdf.mli
+++ b/cpdf.mli
@@ -14,23 +14,6 @@ exception HardError of string
 (** Two exceptions recommended for use with the library, though currently not
 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} *)
 
 (** 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
 [over] over each page of the PDF. The arguments have the same meaning as in
 [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} *)
 
@@ -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 *)
 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 *)
 type justification =
   | LeftJustify
   | CentreJustify
   | 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
 position linespacing fontsize underneath text pages orientation
 relative_to_cropbox midline_adjust topline filename pdf]. For details see cpdfmanual.pdf *)
@@ -234,13 +197,13 @@ val addtexts :
     int -> (* bates number *)
     int option -> (* bates padding width *)
     float * float * float -> (*colour*)
-    position -> (*position*)
+    Cpdfposition.position -> (*position*)
     float -> (*linespacing*)
     float -> (*fontsize*)
     bool -> (*underneath*)
     string ->(*text*)
     int list ->(*page range*)
-    orientation ->(*orientation*)
+    Cpdfposition.orientation ->(*orientation*)
     bool ->(*relative to cropbox?*)
     float ->(*opacity*)
     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
 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. *) 
-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. *)
-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
 
diff --git a/cpdfcommand.ml b/cpdfcommand.ml
index 938fcc8..78cb56d 100644
--- a/cpdfcommand.ml
+++ b/cpdfcommand.ml
@@ -379,7 +379,7 @@ type args =
    mutable fontsize : float;
    mutable color : float * float * float;
    mutable opacity : float;
-   mutable position : Cpdf.position;
+   mutable position : Cpdfposition.position;
    mutable underneath : bool;
    mutable linespacing : float;
    mutable midline : bool;
@@ -388,7 +388,7 @@ type args =
    mutable bates : int;
    mutable batespad : int option;
    mutable prerotate : bool;
-   mutable orientation : Cpdf.orientation;
+   mutable orientation : Cpdfposition.orientation;
    mutable relative_to_cropbox : bool;
    mutable keepversion : bool;
    mutable bycolumns : bool;
@@ -483,7 +483,7 @@ let args =
    fontsize = 12.;
    color = 0., 0., 0.;
    opacity = 1.;
-   position = Cpdf.TopLeft 100.;
+   position = Cpdfposition.TopLeft 100.;
    underneath = false;
    linespacing = 1.;
    midline = false;
@@ -492,7 +492,7 @@ let args =
    bates = 0;
    batespad = None;
    prerotate = false;
-   orientation = Cpdf.Horizontal;
+   orientation = Cpdfposition.Horizontal;
    relative_to_cropbox = false;
    keepversion = false;
    bycolumns = false;
@@ -587,7 +587,7 @@ let reset_arguments () =
   args.fontsize <- 12.;
   args.color <- 0., 0., 0.;
   args.opacity <- 1.;
-  args.position <- Cpdf.TopLeft 100.;
+  args.position <- Cpdfposition.TopLeft 100.;
   args.underneath <- false;
   args.linespacing <- 1.;
   args.midline <- false;
@@ -596,7 +596,7 @@ let reset_arguments () =
   args.bates <- 0;
   args.batespad <- None;
   args.prerotate <- false;
-  args.orientation <- Cpdf.Horizontal;
+  args.orientation <- Cpdfposition.Horizontal;
   args.relative_to_cropbox <- false;
   args.keepversion <- false;
   args.bycolumns <- false;
@@ -1047,11 +1047,11 @@ let setaddbookmarks s =
 let setstampon f =
   setop (StampOn f) ();
   (* 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 =
   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 =
   setop (StampAsXObject f) ()
@@ -1061,58 +1061,58 @@ let setcombinepages f =
 
 let setposcenter s =
   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 x, y = Cpdfcoord.parse_coordinate empty s in
-    args.position <- Cpdf.PosLeft (x, y)
+    args.position <- Cpdfposition.PosLeft (x, y)
 
 let setposright s =
   let x, y = Cpdfcoord.parse_coordinate empty s in
-    args.position <- Cpdf.PosRight (x, y)
+    args.position <- Cpdfposition.PosRight (x, y)
 
 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
 
 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
 
 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
 
 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
 
 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
 
 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
 
 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
 
 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
 
 let setdiagonal n =
-  args.position <- Cpdf.Diagonal;
+  args.position <- Cpdfposition.Diagonal;
   args.justification <- Cpdf.CentreJustify
 
 let setreversediagonal n =
-  args.position <- Cpdf.ReverseDiagonal;
+  args.position <- Cpdfposition.ReverseDiagonal;
   args.justification <- Cpdf.CentreJustify
 
 let setcenter n =
-  args.position <- Cpdf.Centre;
+  args.position <- Cpdfposition.Centre;
   args.justification <- Cpdf.CentreJustify
 
 let setbatespad n =
@@ -1220,7 +1220,7 @@ let setscaletofitscale f =
 let setscalecontents f =
   detect_duplicate_op (ScaleContents f);
   args.op <- Some (ScaleContents f);
-  args.position <- Cpdf.Diagonal (* Will be center *)
+  args.position <- Cpdfposition.Diagonal (* Will be center *)
 
 let setsqueeze () =
   args.squeeze <- true;
@@ -1345,10 +1345,10 @@ let setp2ppath p =
   args.path_to_p2p <- p
 
 let settextvertical () =
-  args.orientation <- Cpdf.Vertical
+  args.orientation <- Cpdfposition.Vertical
 
 let settextverticaldown () =
-  args.orientation <- Cpdf.VerticalDown
+  args.orientation <- Cpdfposition.VerticalDown
 
 let setfrombox s =
   detect_duplicate_op CopyBox;
@@ -3351,12 +3351,12 @@ let addrectangle
         Pdf.parse_rectangle page.Pdfpage.mediabox
     in
     let x, y, _ =
-      Cpdf.calculate_position false w mediabox Cpdf.Horizontal position
+      Cpdfposition.calculate_position false w mediabox Cpdfposition.Horizontal position
     in
     let x, y =
       match position with
-        Cpdf.Top _ | Cpdf.TopLeft _ | Cpdf.TopRight _ -> (x, y -. h)
-      | Cpdf.Centre | Cpdf.PosCentre _ -> (x, y -. (h /. 2.))
+        Cpdfposition.Top _ | Cpdfposition.TopLeft _ | Cpdfposition.TopRight _ -> (x, y -. h)
+      | Cpdfposition.Centre | Cpdfposition.PosCentre _ -> (x, y -. (h /. 2.))
       | _ -> (x, y)
     in
     let ops =
diff --git a/cpdfposition.ml b/cpdfposition.ml
new file mode 100644
index 0000000..b139603
--- /dev/null
+++ b/cpdfposition.ml
@@ -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
diff --git a/cpdfposition.mli b/cpdfposition.mli
new file mode 100644
index 0000000..a70cfe1
--- /dev/null
+++ b/cpdfposition.mli
@@ -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