Merged twoup/twoup stack

This commit is contained in:
John Whitington 2019-07-08 15:42:19 +01:00
parent 3df7a6817e
commit 52d9a768c4
1 changed files with 24 additions and 65 deletions

89
cpdf.ml
View File

@ -3083,7 +3083,7 @@ let copy_annotations range frompdf topdf =
(* \section{N-up} *) (* \section{N-up} *)
(* Given a number to fit and a mediabox, return a list of transforms for the (* Given a number to fit and a mediabox, return a list of transforms for the
2 pages. FIXME: Assumes mediabox (0, 0)-based. Check this for all operations for 1.8. *) 2 pages. *)
let twoup_transforms mediabox = let twoup_transforms mediabox =
let width, height = let width, height =
match Pdf.parse_rectangle mediabox with match Pdf.parse_rectangle mediabox with
@ -3109,9 +3109,21 @@ let twoup_transforms mediabox =
in let t1 = Pdftransform.matrix_of_transform [tr1; rotate; scale] in in let t1 = Pdftransform.matrix_of_transform [tr1; rotate; scale] in
[t0; t1] [t0; t1]
let twoup_stack_transforms mediabox =
let width, height =
match Pdf.parse_rectangle mediabox with
xmin, ymin, xmax, ymax -> xmax -. xmin, ymax -. ymin
in
let rotate = Pdftransform.Rotate ((0., 0.), rad_of_deg 90.)
in let tr0 = Pdftransform.Translate (height, 0.)
in let tr1 = Pdftransform.Translate (height, width) in
let t0 = Pdftransform.matrix_of_transform [tr0; rotate]
in let t1 = Pdftransform.matrix_of_transform [tr1; rotate] in
[t0; t1]
(* Combine two pages into one throughout the document. The pages have already (* Combine two pages into one throughout the document. The pages have already
had their objects renumbered so as not to clash.*) had their objects renumbered so as not to clash.*)
let twoup_pages fast pdf = function let twoup_pages_inner isstack fast pdf = function
| [] -> assert false | [] -> assert false
| (h::_) as pages -> | (h::_) as pages ->
let resources' = let resources' =
@ -3128,9 +3140,6 @@ let twoup_pages fast pdf = function
Pdfops.Op_n] Pdfops.Op_n]
in in
let ops = Pdfops.parse_operators pdf resources' contents in let ops = Pdfops.parse_operators pdf resources' contents in
(* Need protect_removeme here? especially new, Q-adding
* protect?. This will also make it faster on -fast, since Q
* adding will be disabled. *)
Pdfops.stream_of_ops Pdfops.stream_of_ops
([Pdfops.Op_q] @ [Pdfops.Op_cm transform] @ clipops @ ops @ [Pdfops.Op_Q]) ([Pdfops.Op_q] @ [Pdfops.Op_cm transform] @ clipops @ ops @ [Pdfops.Op_Q])
in in
@ -3142,71 +3151,21 @@ let twoup_pages fast pdf = function
| Some box -> box) | Some box -> box)
p.Pdfpage.content) p.Pdfpage.content)
pages pages
(take (twoup_transforms h.Pdfpage.mediabox) (length pages)) (take (((if isstack then twoup_stack_transforms else twoup_transforms) h.Pdfpage.mediabox)) (length pages))
in
{Pdfpage.mediabox = h.Pdfpage.mediabox;
Pdfpage.rotate = h.Pdfpage.rotate;
Pdfpage.content = content';
Pdfpage.resources = resources';
Pdfpage.rest = h.Pdfpage.rest}
let twoup_stack_transforms mediabox =
let width, height =
match Pdf.parse_rectangle mediabox with
xmin, ymin, xmax, ymax -> xmax -. xmin, ymax -. ymin
in
let rotate = Pdftransform.Rotate ((0., 0.), rad_of_deg 90.)
in let tr0 = Pdftransform.Translate (height, 0.)
in let tr1 = Pdftransform.Translate (height, width) in
let t0 = Pdftransform.matrix_of_transform [tr0; rotate]
in let t1 = Pdftransform.matrix_of_transform [tr1; rotate] in
[t0; t1]
(* FIXME: Add clipping, as for twoup, or merge these two functions properly *)
let twoup_pages_stack fast pdf = function
| [] -> assert false
| (h::_) as pages ->
let resources =
pair_reduce
(combine_pdf_resources pdf)
(map (fun p -> p.Pdfpage.resources) pages)
in
(* Remove any CropBox *)
let rest =
Pdf.remove_dict_entry h.Pdfpage.rest "/CropBox"
in
let content' =
let transform_stream clipbox contents transform =
let clipops =
let minx, miny, maxx, maxy = Pdf.parse_rectangle clipbox in
[Pdfops.Op_re (minx, miny, maxx -. minx, maxy -. miny);
Pdfops.Op_W;
Pdfops.Op_n]
in
let ops = Pdfops.parse_operators pdf resources contents in
Pdfops.stream_of_ops
([Pdfops.Op_q] @ [Pdfops.Op_cm transform] @ clipops @ ops @ [Pdfops.Op_Q])
in
map2
(fun p ->
transform_stream
(match Pdf.lookup_direct pdf "/CropBox" p.Pdfpage.rest with
None -> p.Pdfpage.mediabox
| Some box -> box)
p.Pdfpage.content)
pages
(take (twoup_stack_transforms h.Pdfpage.mediabox) (length pages))
in in
{Pdfpage.mediabox = {Pdfpage.mediabox =
(let width, height = if isstack then
let width, height =
match Pdf.parse_rectangle h.Pdfpage.mediabox with match Pdf.parse_rectangle h.Pdfpage.mediabox with
xmin, ymin, xmax, ymax -> xmax -. xmin, ymax -. ymin xmin, ymin, xmax, ymax -> xmax -. xmin, ymax -. ymin
in in
Pdf.Array [Pdf.Real 0.; Pdf.Real 0.; Pdf.Real height; Pdf.Real (width *. 2.)]); Pdf.Array [Pdf.Real 0.; Pdf.Real 0.; Pdf.Real height; Pdf.Real (width *. 2.)]
else
h.Pdfpage.mediabox;
Pdfpage.rotate = h.Pdfpage.rotate; Pdfpage.rotate = h.Pdfpage.rotate;
Pdfpage.content = content'; Pdfpage.content = content';
Pdfpage.resources = resources; Pdfpage.resources = resources';
Pdfpage.rest = rest} Pdfpage.rest = if isstack then Pdf.remove_dict_entry h.Pdfpage.rest "/CropBox" else h.Pdfpage.rest}
let f_twoup f_pages pdf = let f_twoup f_pages pdf =
let pagenums = ilist 1 (Pdfpage.endpage pdf) in let pagenums = ilist 1 (Pdfpage.endpage pdf) in
@ -3219,9 +3178,9 @@ let f_twoup f_pages pdf =
(*print_changes changes;*) (*print_changes changes;*)
Pdfpage.change_pages ~changes true pdf pages' Pdfpage.change_pages ~changes true pdf pages'
let twoup fast pdf = f_twoup (twoup_pages fast) pdf let twoup fast pdf = f_twoup (twoup_pages_inner false fast) pdf
let twoup_stack fast pdf = f_twoup (twoup_pages_stack fast) pdf let twoup_stack fast pdf = f_twoup (twoup_pages_inner true fast) pdf
(* \section{Output info} *) (* \section{Output info} *)
let get_info raw pdf = let get_info raw pdf =