Fixed -stamp-on/-stamp-under with positions
This commit is contained in:
parent
21ce677313
commit
a4f9d0322f
423
cpdf.ml
423
cpdf.ml
|
@ -1233,156 +1233,7 @@ let list_bookmarks encoding range pdf output =
|
|||
(if mark.Pdfmarks.isopen then "open" else "")))
|
||||
inrange
|
||||
|
||||
(* \section{Stamping files} *)
|
||||
(* o is the stamp, u is the main pdf page *)
|
||||
let do_stamp fast scale_to_fit isover pdf o u opdf =
|
||||
(* Scale page stamp o to fit page u *)
|
||||
let o =
|
||||
if scale_to_fit then
|
||||
let sxmin, symin, sxmax, symax =
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" o.Pdfpage.rest with | Some r -> r | None -> o.Pdfpage.mediabox)
|
||||
in let txmin, tymin, txmax, tymax =
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" u.Pdfpage.rest with | Some r -> r | None -> u.Pdfpage.mediabox)
|
||||
in
|
||||
let xmag = (txmax -. txmin) /. (sxmax -. sxmin)
|
||||
in let ymag = (tymax -. tymin) /. (symax -. symin) in
|
||||
let scale =
|
||||
if xmag < 0.999 && ymag < 0.999 then
|
||||
if xmag > ymag then xmag else ymag
|
||||
else if xmag >= 1.001 && ymag >= 1.001 then
|
||||
if xmag > ymag then ymag else xmag
|
||||
else if xmag >= 1.001 then ymag
|
||||
else xmag
|
||||
in
|
||||
let dx = txmin +. ((txmax -. txmin) -. (sxmax -. sxmin) *. scale) /. 2.
|
||||
in let dy = tymin +. ((tymax -. tymin) -. (symax -. symin) *. scale) /. 2. in
|
||||
let scale_op =
|
||||
Pdfops.Op_cm
|
||||
(Pdftransform.matrix_of_transform
|
||||
[Pdftransform.Translate (dx, dy);
|
||||
Pdftransform.Scale ((sxmin, symin), scale, scale)])
|
||||
in
|
||||
Pdfpage.prepend_operators opdf [scale_op] ~fast o
|
||||
else
|
||||
o
|
||||
in
|
||||
{u with
|
||||
Pdfpage.content =
|
||||
(if isover then ( @ ) else ( @@ ))
|
||||
[protect_removeme pdf u.Pdfpage.resources u.Pdfpage.content]
|
||||
[protect_removeme pdf o.Pdfpage.resources o.Pdfpage.content];
|
||||
Pdfpage.resources =
|
||||
combine_pdf_resources pdf u.Pdfpage.resources o.Pdfpage.resources}
|
||||
|
||||
(* Alter bookmark destinations given a hash table of (old page reference
|
||||
* number, new page reference number) pairings *)
|
||||
let change_destination t = function
|
||||
Pdfdest.XYZ (Pdfdest.PageObject p, a, b, c) ->
|
||||
Pdfdest.XYZ (Pdfdest.PageObject (Hashtbl.find t p), a, b, c)
|
||||
| Pdfdest.Fit (Pdfdest.PageObject p) ->
|
||||
Pdfdest.Fit (Pdfdest.PageObject (Hashtbl.find t p))
|
||||
| Pdfdest.FitH (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitH (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitV (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitV (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitR (Pdfdest.PageObject p, a, b, c, d) ->
|
||||
Pdfdest.FitR (Pdfdest.PageObject (Hashtbl.find t p), a, b, c, d)
|
||||
| Pdfdest.FitB (Pdfdest.PageObject p) ->
|
||||
Pdfdest.Fit (Pdfdest.PageObject (Hashtbl.find t p))
|
||||
| Pdfdest.FitBH (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitBH (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitBV (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitBV (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| x -> x
|
||||
|
||||
let change_bookmark t m =
|
||||
{m with Pdfmarks.target =
|
||||
try change_destination t m.Pdfmarks.target with Not_found -> m.Pdfmarks.target}
|
||||
|
||||
let stamp (fast : bool) scale_to_fit isover range over pdf =
|
||||
let marks = Pdfmarks.read_bookmarks pdf in
|
||||
let marks_refnumbers = Pdf.page_reference_numbers pdf in
|
||||
let pdf = Pdfmarks.remove_bookmarks pdf in
|
||||
let over = Pdfmarks.remove_bookmarks over in
|
||||
let pageseqs = ilist 1 (Pdfpage.endpage pdf) in
|
||||
let over_firstpage_pdf =
|
||||
match Pdfpage.pages_of_pagetree over with
|
||||
| [] -> error "empty PDF"
|
||||
| h::_ -> Pdfpage.change_pages true over [h]
|
||||
in
|
||||
let merged =
|
||||
Pdfmerge.merge_pdfs
|
||||
~rotations:[Pdfmerge.DNR; Pdfmerge.DNR]
|
||||
false false ["a"; "b"] [pdf; over_firstpage_pdf] [pageseqs; [1]]
|
||||
in
|
||||
let renamed_pdf =
|
||||
Pdfpage.change_pages true
|
||||
merged (Pdfpage.renumber_pages merged (Pdfpage.pages_of_pagetree merged))
|
||||
in
|
||||
let renamed_pages = Pdfpage.pages_of_pagetree renamed_pdf in
|
||||
let under_pages, over_page =
|
||||
all_but_last renamed_pages, last renamed_pages
|
||||
in
|
||||
let new_pages =
|
||||
map2
|
||||
(fun pageseq under_page ->
|
||||
do_stamp fast scale_to_fit isover renamed_pdf
|
||||
(if mem pageseq range then over_page else
|
||||
Pdfpage.blankpage Pdfpaper.a4)
|
||||
under_page over)
|
||||
pageseqs
|
||||
under_pages
|
||||
in
|
||||
let changed = Pdfpage.change_pages true renamed_pdf new_pages in
|
||||
let new_refnumbers = Pdf.page_reference_numbers changed in
|
||||
let changetable = hashtable_of_dictionary (List.combine marks_refnumbers new_refnumbers) in
|
||||
let new_marks = map (change_bookmark changetable) marks in
|
||||
Pdfmarks.add_bookmarks new_marks changed
|
||||
|
||||
(* Combine pages from two PDFs. For now, assume equal length. *)
|
||||
|
||||
(* If [over] has more pages than [under], chop the excess. If the converse, pad
|
||||
[over] to the same length *)
|
||||
let equalize_pages under over =
|
||||
let length_under = Pdfpage.endpage under
|
||||
in let length_over = Pdfpage.endpage over
|
||||
in
|
||||
if length_over > length_under then
|
||||
under,
|
||||
(Pdfpage.change_pages true over (take (Pdfpage.pages_of_pagetree over) length_under))
|
||||
else if length_under > length_over then
|
||||
under,
|
||||
Pdfpage.change_pages true
|
||||
over
|
||||
(Pdfpage.pages_of_pagetree over @
|
||||
(many (Pdfpage.blankpage Pdfpaper.a4) (length_under - length_over)))
|
||||
else
|
||||
under, over
|
||||
|
||||
let combine_pages (fast : bool) under over scaletofit swap equalize =
|
||||
let marks_under = Pdfmarks.read_bookmarks under in
|
||||
let marks_over = Pdfmarks.read_bookmarks over in
|
||||
let under, over = if equalize then equalize_pages under over else under, over in
|
||||
let under_length = Pdfpage.endpage under
|
||||
in let over_length = Pdfpage.endpage over in
|
||||
if under_length <> over_length then raise (Pdf.PDFError "combine_pages: not of equal length") else
|
||||
let pageseqs_under = ilist 1 (Pdfpage.endpage under)
|
||||
in let pageseqs_over = ilist 1 (Pdfpage.endpage over) in
|
||||
let merged =
|
||||
Pdfmerge.merge_pdfs ~rotations: [Pdfmerge.DNR; Pdfmerge.DNR] false false ["a"; "b"] [under; over] [pageseqs_under; pageseqs_over] in
|
||||
let renamed_pdf =
|
||||
Pdfpage.change_pages true
|
||||
merged (Pdfpage.renumber_pages merged (Pdfpage.pages_of_pagetree merged))
|
||||
in
|
||||
let under_pages, over_pages =
|
||||
cleave (Pdfpage.pages_of_pagetree renamed_pdf) under_length
|
||||
in
|
||||
let new_pages =
|
||||
map2 (fun o u -> do_stamp fast scaletofit (not swap) renamed_pdf o u over) over_pages under_pages
|
||||
in
|
||||
Pdfmarks.add_bookmarks (marks_under @ marks_over) (Pdfpage.change_pages true renamed_pdf new_pages)
|
||||
|
||||
(* \section{Split at bookmarks} *)
|
||||
|
||||
|
@ -1627,56 +1478,6 @@ let print_fonts pdf =
|
|||
flprint
|
||||
(fold_left ( ^ ) "" (map string_of_font (list_fonts pdf)))
|
||||
|
||||
(* \section{Nobbling for Demo Version} *)
|
||||
let nobble_page pdf _ page =
|
||||
let minx, miny, maxx, maxy =
|
||||
(* Use cropbox if available *)
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" page.Pdfpage.rest with
|
||||
| Some r -> r
|
||||
| None -> page.Pdfpage.mediabox)
|
||||
in
|
||||
let fontdict =
|
||||
match Pdf.lookup_direct pdf "/Font" page.Pdfpage.resources with
|
||||
| None -> Pdf.Dictionary []
|
||||
| Some d -> d
|
||||
in
|
||||
let fontname = Pdf.unique_key "F" fontdict in
|
||||
let width = maxx -. minx in let height = maxy -. miny in
|
||||
let scalex =
|
||||
(width *. 1000.) /. float (Pdfstandard14.textwidth false Pdftext.Helvetica "DEMO")
|
||||
in
|
||||
let page' =
|
||||
let font =
|
||||
Pdf.Dictionary
|
||||
[("/Type", Pdf.Name "/Font");
|
||||
("/Subtype", Pdf.Name "/Type1");
|
||||
("/BaseFont", Pdf.Name "/Helvetica")]
|
||||
in let ops =
|
||||
[Pdfops.Op_BMC "/CPDFSTAMP";
|
||||
Pdfops.Op_cm
|
||||
(Pdftransform.matrix_of_transform
|
||||
[Pdftransform.Translate (minx, miny +. height /. 2.)]);
|
||||
Pdfops.Op_gs "/gs0";
|
||||
Pdfops.Op_BT;
|
||||
Pdfops.Op_Tf (fontname, scalex);
|
||||
Pdfops.Op_Tj "DEMO";
|
||||
Pdfops.Op_ET;
|
||||
Pdfops.Op_EMC]
|
||||
in
|
||||
{(Pdfpage.blankpage Pdfpaper.a4) with
|
||||
Pdfpage.mediabox = page.Pdfpage.mediabox;
|
||||
Pdfpage.content = [Pdfops.stream_of_ops ops];
|
||||
Pdfpage.resources =
|
||||
Pdf.Dictionary
|
||||
[("/Font", Pdf.Dictionary [(fontname, font)]);
|
||||
("/ExtGState", Pdf.Dictionary
|
||||
["/gs0",
|
||||
Pdf.Dictionary["/Type", Pdf.Name "/ExtGState"; "/ca", Pdf.Real 0.2]]);
|
||||
]
|
||||
}
|
||||
in
|
||||
do_stamp false false true pdf page' page (Pdf.empty ())
|
||||
|
||||
(* \section{Superimpose text, page numbers etc.} *)
|
||||
|
||||
|
@ -2397,6 +2198,230 @@ let hflip_pdf ?(fast=false) pdf range =
|
|||
in
|
||||
process_pages (flip_page ~fast transform_op pdf) pdf range
|
||||
|
||||
let stamp_shift_of_position sw sh w h p =
|
||||
let half x = x /. 2. in
|
||||
match p with
|
||||
| PosCentre (ox, oy) -> ox -. half sw, oy
|
||||
| PosLeft (ox, oy) -> ox, oy
|
||||
| PosRight (ox, oy) -> ox -. sw, oy
|
||||
| Top o -> half w -. half sw, h -. o -. sh
|
||||
| TopLeft o -> o, h -. sh -. o
|
||||
| TopRight o -> w -. sw -. o, h -. sh -. o
|
||||
| Left o -> o, half h -. half sh
|
||||
| BottomLeft o -> o, o
|
||||
| Bottom o -> half w -. half sw, o
|
||||
| BottomRight o -> w -. sw, o
|
||||
| Right o -> w -. sw -. o, half h -. half sh
|
||||
| Diagonal | ReverseDiagonal | Centre -> half w -. half sw, half h -. half sh
|
||||
|
||||
let do_stamp fast position scale_to_fit isover pdf o u opdf =
|
||||
(* Scale page stamp o to fit page u *)
|
||||
let sxmin, symin, sxmax, symax =
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" o.Pdfpage.rest with | Some r -> r | None -> o.Pdfpage.mediabox)
|
||||
in let txmin, tymin, txmax, tymax =
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" u.Pdfpage.rest with | Some r -> r | None -> u.Pdfpage.mediabox)
|
||||
in
|
||||
let o =
|
||||
if scale_to_fit then
|
||||
let xmag = (txmax -. txmin) /. (sxmax -. sxmin) in
|
||||
let ymag = (tymax -. tymin) /. (symax -. symin) in
|
||||
let scale =
|
||||
if xmag < 0.999 && ymag < 0.999 then
|
||||
if xmag > ymag then xmag else ymag
|
||||
else if xmag >= 1.001 && ymag >= 1.001 then
|
||||
if xmag > ymag then ymag else xmag
|
||||
else if xmag >= 1.001 then ymag
|
||||
else xmag
|
||||
in
|
||||
let dx = txmin +. ((txmax -. txmin) -. (sxmax -. sxmin) *. scale) /. 2. in
|
||||
let dy = tymin +. ((tymax -. tymin) -. (symax -. symin) *. scale) /. 2. in
|
||||
let scale_op =
|
||||
Pdfops.Op_cm
|
||||
(Pdftransform.matrix_of_transform
|
||||
[Pdftransform.Translate (dx, dy);
|
||||
Pdftransform.Scale ((sxmin, symin), scale, scale)])
|
||||
in
|
||||
Pdfpage.prepend_operators pdf [scale_op] ~fast o
|
||||
else
|
||||
let sw = sxmax -. sxmin
|
||||
and sh = symax -. symin
|
||||
and w = txmax -. txmin
|
||||
and h = tymax -. tymin in
|
||||
let dx, dy = stamp_shift_of_position sw sh w h position in
|
||||
let translate_op =
|
||||
Pdfops.Op_cm
|
||||
(Pdftransform.matrix_of_transform [Pdftransform.Translate (dx, dy)])
|
||||
in
|
||||
Pdfpage.prepend_operators pdf [translate_op] ~fast o
|
||||
in
|
||||
{u with
|
||||
Pdfpage.content =
|
||||
(if isover then ( @ ) else ( @@ ))
|
||||
[protect_removeme pdf u.Pdfpage.resources u.Pdfpage.content]
|
||||
[protect_removeme pdf o.Pdfpage.resources o.Pdfpage.content];
|
||||
Pdfpage.resources =
|
||||
combine_pdf_resources pdf u.Pdfpage.resources o.Pdfpage.resources}
|
||||
|
||||
(* Alter bookmark destinations given a hash table of (old page reference
|
||||
* number, new page reference number) pairings *)
|
||||
let change_destination t = function
|
||||
Pdfdest.XYZ (Pdfdest.PageObject p, a, b, c) ->
|
||||
Pdfdest.XYZ (Pdfdest.PageObject (Hashtbl.find t p), a, b, c)
|
||||
| Pdfdest.Fit (Pdfdest.PageObject p) ->
|
||||
Pdfdest.Fit (Pdfdest.PageObject (Hashtbl.find t p))
|
||||
| Pdfdest.FitH (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitH (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitV (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitV (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitR (Pdfdest.PageObject p, a, b, c, d) ->
|
||||
Pdfdest.FitR (Pdfdest.PageObject (Hashtbl.find t p), a, b, c, d)
|
||||
| Pdfdest.FitB (Pdfdest.PageObject p) ->
|
||||
Pdfdest.Fit (Pdfdest.PageObject (Hashtbl.find t p))
|
||||
| Pdfdest.FitBH (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitBH (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| Pdfdest.FitBV (Pdfdest.PageObject p, x) ->
|
||||
Pdfdest.FitBV (Pdfdest.PageObject (Hashtbl.find t p), x)
|
||||
| x -> x
|
||||
|
||||
let change_bookmark t m =
|
||||
{m with Pdfmarks.target =
|
||||
try change_destination t m.Pdfmarks.target with Not_found -> m.Pdfmarks.target}
|
||||
|
||||
let stamp position fast scale_to_fit isover range over pdf =
|
||||
let marks = Pdfmarks.read_bookmarks pdf in
|
||||
let marks_refnumbers = Pdf.page_reference_numbers pdf in
|
||||
let pdf = Pdfmarks.remove_bookmarks pdf in
|
||||
let over = Pdfmarks.remove_bookmarks over in
|
||||
let pageseqs = ilist 1 (Pdfpage.endpage pdf) in
|
||||
let over_firstpage_pdf =
|
||||
match Pdfpage.pages_of_pagetree over with
|
||||
| [] -> error "empty PDF"
|
||||
| h::_ -> Pdfpage.change_pages true over [h]
|
||||
in
|
||||
let merged =
|
||||
Pdfmerge.merge_pdfs
|
||||
~rotations:[Pdfmerge.DNR; Pdfmerge.DNR]
|
||||
false false ["a"; "b"] [pdf; over_firstpage_pdf] [pageseqs; [1]]
|
||||
in
|
||||
let renamed_pdf =
|
||||
Pdfpage.change_pages true
|
||||
merged (Pdfpage.renumber_pages merged (Pdfpage.pages_of_pagetree merged))
|
||||
in
|
||||
let renamed_pages = Pdfpage.pages_of_pagetree renamed_pdf in
|
||||
let under_pages, over_page =
|
||||
all_but_last renamed_pages, last renamed_pages
|
||||
in
|
||||
let new_pages =
|
||||
map2
|
||||
(fun pageseq under_page ->
|
||||
do_stamp fast position scale_to_fit isover renamed_pdf
|
||||
(if mem pageseq range then over_page else
|
||||
Pdfpage.blankpage Pdfpaper.a4)
|
||||
under_page over)
|
||||
pageseqs
|
||||
under_pages
|
||||
in
|
||||
let changed = Pdfpage.change_pages true renamed_pdf new_pages in
|
||||
let new_refnumbers = Pdf.page_reference_numbers changed in
|
||||
let changetable = hashtable_of_dictionary (List.combine marks_refnumbers new_refnumbers) in
|
||||
let new_marks = map (change_bookmark changetable) marks in
|
||||
Pdfmarks.add_bookmarks new_marks changed
|
||||
|
||||
(* Combine pages from two PDFs. For now, assume equal length. *)
|
||||
|
||||
(* If [over] has more pages than [under], chop the excess. If the converse, pad
|
||||
[over] to the same length *)
|
||||
let equalize_pages under over =
|
||||
let length_under = Pdfpage.endpage under
|
||||
in let length_over = Pdfpage.endpage over
|
||||
in
|
||||
if length_over > length_under then
|
||||
under,
|
||||
(Pdfpage.change_pages true over (take (Pdfpage.pages_of_pagetree over) length_under))
|
||||
else if length_under > length_over then
|
||||
under,
|
||||
Pdfpage.change_pages true
|
||||
over
|
||||
(Pdfpage.pages_of_pagetree over @
|
||||
(many (Pdfpage.blankpage Pdfpaper.a4) (length_under - length_over)))
|
||||
else
|
||||
under, over
|
||||
|
||||
let combine_pages (fast : bool) under over scaletofit swap equalize =
|
||||
let marks_under = Pdfmarks.read_bookmarks under in
|
||||
let marks_over = Pdfmarks.read_bookmarks over in
|
||||
let under, over = if equalize then equalize_pages under over else under, over in
|
||||
let under_length = Pdfpage.endpage under
|
||||
in let over_length = Pdfpage.endpage over in
|
||||
if under_length <> over_length then raise (Pdf.PDFError "combine_pages: not of equal length") else
|
||||
let pageseqs_under = ilist 1 (Pdfpage.endpage under)
|
||||
in let pageseqs_over = ilist 1 (Pdfpage.endpage over) in
|
||||
let merged =
|
||||
Pdfmerge.merge_pdfs ~rotations: [Pdfmerge.DNR; Pdfmerge.DNR] false false ["a"; "b"] [under; over] [pageseqs_under; pageseqs_over] in
|
||||
let renamed_pdf =
|
||||
Pdfpage.change_pages true
|
||||
merged (Pdfpage.renumber_pages merged (Pdfpage.pages_of_pagetree merged))
|
||||
in
|
||||
let under_pages, over_pages =
|
||||
cleave (Pdfpage.pages_of_pagetree renamed_pdf) under_length
|
||||
in
|
||||
let new_pages =
|
||||
map2 (fun o u -> do_stamp fast (BottomLeft 0.) scaletofit (not swap) renamed_pdf o u over) over_pages under_pages
|
||||
in
|
||||
Pdfmarks.add_bookmarks (marks_under @ marks_over) (Pdfpage.change_pages true renamed_pdf new_pages)
|
||||
|
||||
let nobble_page pdf _ page =
|
||||
let minx, miny, maxx, maxy =
|
||||
(* Use cropbox if available *)
|
||||
Pdf.parse_rectangle
|
||||
(match Pdf.lookup_direct pdf "/CropBox" page.Pdfpage.rest with
|
||||
| Some r -> r
|
||||
| None -> page.Pdfpage.mediabox)
|
||||
in
|
||||
let fontdict =
|
||||
match Pdf.lookup_direct pdf "/Font" page.Pdfpage.resources with
|
||||
| None -> Pdf.Dictionary []
|
||||
| Some d -> d
|
||||
in
|
||||
let fontname = Pdf.unique_key "F" fontdict in
|
||||
let width = maxx -. minx in let height = maxy -. miny in
|
||||
let scalex =
|
||||
(width *. 1000.) /. float (Pdfstandard14.textwidth false Pdftext.Helvetica "DEMO")
|
||||
in
|
||||
let page' =
|
||||
let font =
|
||||
Pdf.Dictionary
|
||||
[("/Type", Pdf.Name "/Font");
|
||||
("/Subtype", Pdf.Name "/Type1");
|
||||
("/BaseFont", Pdf.Name "/Helvetica")]
|
||||
in let ops =
|
||||
[Pdfops.Op_BMC "/CPDFSTAMP";
|
||||
Pdfops.Op_cm
|
||||
(Pdftransform.matrix_of_transform
|
||||
[Pdftransform.Translate (minx, miny +. height /. 2.)]);
|
||||
Pdfops.Op_gs "/gs0";
|
||||
Pdfops.Op_BT;
|
||||
Pdfops.Op_Tf (fontname, scalex);
|
||||
Pdfops.Op_Tj "DEMO";
|
||||
Pdfops.Op_ET;
|
||||
Pdfops.Op_EMC]
|
||||
in
|
||||
{(Pdfpage.blankpage Pdfpaper.a4) with
|
||||
Pdfpage.mediabox = page.Pdfpage.mediabox;
|
||||
Pdfpage.content = [Pdfops.stream_of_ops ops];
|
||||
Pdfpage.resources =
|
||||
Pdf.Dictionary
|
||||
[("/Font", Pdf.Dictionary [(fontname, font)]);
|
||||
("/ExtGState", Pdf.Dictionary
|
||||
["/gs0",
|
||||
Pdf.Dictionary["/Type", Pdf.Name "/ExtGState"; "/ca", Pdf.Real 0.2]]);
|
||||
]
|
||||
}
|
||||
in
|
||||
do_stamp false (BottomLeft 0.) false true pdf page' page (Pdf.empty ())
|
||||
|
||||
(* \section{Set media box} *)
|
||||
let set_mediabox x y w h pdf range =
|
||||
let crop_page _ page =
|
||||
|
|
37
cpdf.mli
37
cpdf.mli
|
@ -14,6 +14,23 @@ 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 *)
|
||||
|
@ -178,10 +195,10 @@ swapped. If [fast] is true, the PDFs are assumed to be well-formed and no
|
|||
fixes are done. *)
|
||||
val combine_pages : bool -> Pdf.t -> Pdf.t -> bool -> bool -> bool -> Pdf.t
|
||||
|
||||
(** [stamp scale_to_fit fast isover range over pdf] stamps the first page of
|
||||
(** [stamp scale_to_fit position fast 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 -> bool -> bool -> int list -> Pdf.t -> Pdf.t -> Pdf.t
|
||||
val stamp : position -> bool -> bool -> bool -> int list -> Pdf.t -> Pdf.t -> Pdf.t
|
||||
|
||||
(** {2 Splitting PDFs} *)
|
||||
|
||||
|
@ -217,22 +234,6 @@ 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
|
||||
|
||||
(** 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
|
||||
|
|
|
@ -864,10 +864,13 @@ let setaddbookmarks s =
|
|||
setop (AddBookmarks s) ()
|
||||
|
||||
let setstampon f =
|
||||
setop (StampOn 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.
|
||||
|
||||
let setstampunder f =
|
||||
setop (StampUnder f) ()
|
||||
setop (StampUnder f) ();
|
||||
if args.position = Cpdf.TopLeft 100. then args.position <- Cpdf.BottomLeft 0.
|
||||
|
||||
let setstamponmulti f =
|
||||
setop (StampOn f) ();
|
||||
|
@ -3099,12 +3102,7 @@ let go () =
|
|||
| Some Split ->
|
||||
begin match args.inputs, args.out with
|
||||
| [(f, ranges, _, _, _)], File output_spec ->
|
||||
let pdf = get_single_pdf args.op true
|
||||
(*and filename =
|
||||
match f with
|
||||
| InFile n -> n
|
||||
| _ -> ""*)
|
||||
in
|
||||
let pdf = get_single_pdf args.op true in
|
||||
let enc =
|
||||
match args.crypt_method with
|
||||
| "" -> None
|
||||
|
@ -3245,7 +3243,6 @@ let go () =
|
|||
begin match args.inputs with
|
||||
| [(k, _, _, _, _) as input] ->
|
||||
let pdf = get_pdf_from_input_kind input args.op k in
|
||||
(* Convert from string to int *)
|
||||
let topage =
|
||||
try
|
||||
match args.topage with
|
||||
|
@ -3344,7 +3341,6 @@ let go () =
|
|||
in
|
||||
let overpdf = if args.uprightstamp then Cpdf.upright ~fast:args.fast (ilist 1 (Pdfpage.endpage overpdf)) overpdf else overpdf in
|
||||
let pdf = get_single_pdf args.op false in
|
||||
(*let marks = Pdfmarks.read_bookmarks pdf in*)
|
||||
let range = parse_pagespec pdf (get_pagespec ()) in
|
||||
let pdf =
|
||||
if args.ismulti
|
||||
|
@ -3352,10 +3348,8 @@ let go () =
|
|||
let overpdf = equalize_pages_extend pdf overpdf in
|
||||
Cpdf.combine_pages args.fast pdf overpdf true false false
|
||||
else
|
||||
Cpdf.stamp args.fast args.scale_stamp_to_fit true range overpdf pdf
|
||||
Cpdf.stamp args.position args.fast args.scale_stamp_to_fit true range overpdf pdf
|
||||
in
|
||||
(*let p = Pdfmarks.add_bookmarks marks pdf in
|
||||
Pdfwrite.debug_whole_pdf p;*)
|
||||
write_pdf false pdf
|
||||
| Some (StampUnder under) ->
|
||||
let underpdf =
|
||||
|
@ -3365,16 +3359,16 @@ let go () =
|
|||
in
|
||||
let underpdf = if args.uprightstamp then Cpdf.upright ~fast:args.fast (ilist 1 (Pdfpage.endpage underpdf)) underpdf else underpdf in
|
||||
let pdf = get_single_pdf args.op false in
|
||||
(*let marks = Pdfmarks.read_bookmarks pdf in*)
|
||||
let range = parse_pagespec pdf (get_pagespec ()) in
|
||||
let pdf =
|
||||
if args.ismulti
|
||||
then
|
||||
let underpdf = equalize_pages_extend pdf underpdf in
|
||||
Cpdf.combine_pages args.fast pdf underpdf true true false
|
||||
else Cpdf.stamp args.fast args.scale_stamp_to_fit false range underpdf pdf
|
||||
else
|
||||
Cpdf.stamp args.position args.fast args.scale_stamp_to_fit false range underpdf pdf
|
||||
in
|
||||
write_pdf false pdf (*(Pdfmarks.add_bookmarks marks pdf)*)
|
||||
write_pdf false pdf
|
||||
| Some (CombinePages over) ->
|
||||
write_pdf false
|
||||
(Cpdf.combine_pages args.fast (get_single_pdf args.op false) (pdfread_pdf_of_file None None over) false false true)
|
||||
|
|
BIN
cpdfmanual.pdf
BIN
cpdfmanual.pdf
Binary file not shown.
|
@ -6,6 +6,7 @@
|
|||
% Explain page labels in -page-info
|
||||
% Correct the documentation for -diagonal and -reverse-diagonal
|
||||
% Explain octal escape sequences in meta fields with -raw
|
||||
% is scale_to_fit in do_stamp documented?
|
||||
|
||||
\documentclass[a4paper,makeidx]{memoir}
|
||||
\usepackage{palatino}
|
||||
|
@ -1160,7 +1161,9 @@ writing to \texttt{out.pdf}. A watermark should go underneath each page:
|
|||
\small\verb!cpdf -stamp-under topsecret.pdf in.pdf -o out.pdf!
|
||||
\end{framed}
|
||||
|
||||
\noindent The \texttt{-combine-pages} operation takes two PDF files and stamps each
|
||||
\noindent The position commands in \Sref{position} can be used to locate the stamp more precisely (they are calculated relative to the crop box of the stamp). Or, preprocess the stamp with \texttt{-shift} first.
|
||||
|
||||
The \texttt{-combine-pages} operation takes two PDF files and stamps each
|
||||
page of one over each page of the other. The length of the output is the same
|
||||
as the length of the ``under'' file. For instance:
|
||||
\begin{framed}
|
||||
|
|
Loading…
Reference in New Issue