diff --git a/Changes b/Changes index 4e08576..3af7c45 100644 --- a/Changes +++ b/Changes @@ -1,5 +1,6 @@ 2.5 (Upcoming 2022) +o When adding text or graphics, may choose CYMK or Grey instead of RGB o Append e.g DUP2 to a page range to make 1,2,3 --> 1,1,2,2,3,3 etc. o The -list-fonts operation now obeys the range o New operation -print-font-table gives (charcode, unicode, glyph name) triples diff --git a/cpdf.ml b/cpdf.ml index 3e967aa..8b81787 100644 --- a/cpdf.ml +++ b/cpdf.ml @@ -3,6 +3,11 @@ open Pdfutil open Pdfio open Cpdferror +type color = + Grey of float +| RGB of float * float * float +| CYMK of float * float * float * float + let debug = ref false let xmp_template = @@ -1183,6 +1188,16 @@ let metrics_rot n = let metrics_baseline_adjustment () = !ops_baseline_adjustment +let colour_op = function + | RGB (r, g, b) -> Pdfops.Op_rg (r, g, b) + | Grey g -> Pdfops.Op_g g + | CYMK (c, y, m, k) -> Pdfops.Op_k (c, y, m, k) + +let colour_op_stroke = function + | RGB (r, g, b) -> Pdfops.Op_RG (r, g, b) + | Grey g -> Pdfops.Op_G g + | CYMK (c, y, m, k) -> Pdfops.Op_K (c, y, m, k) + let ops longest_w metrics x y rotate hoffset voffset outline linewidth unique_fontname unique_extgstatename colour fontsize text = if metrics then ops_metrics := @@ -1197,9 +1212,7 @@ let ops longest_w metrics x y rotate hoffset voffset outline linewidth unique_fo Pdfops.Op_BT; ] @ (if outline then [Pdfops.Op_w linewidth; Pdfops.Op_Tr 1] else [Pdfops.Op_Tr 0]) @ - [ - (match colour with (r, g, b) -> Pdfops.Op_rg (r, g, b)); - (match colour with (r, g, b) -> Pdfops.Op_RG (r, g, b))] + [colour_op colour; colour_op_stroke colour] @ (match unique_extgstatename with None -> [] | Some n -> [Pdfops.Op_gs n]) @ @@ -2850,8 +2863,8 @@ let addrectangle [ Pdfops.Op_q; Pdfops.Op_BMC "/CPDFSTAMP"; - (match colour with (r, g, b) -> Pdfops.Op_rg (r, g, b)); - (match colour with (r, g, b) -> Pdfops.Op_RG (r, g, b)) + colour_op colour; + colour_op_stroke colour; ] @ (if outline then [Pdfops.Op_w linewidth] else []) @@ -3061,7 +3074,7 @@ let add_border linewidth ~fast pdf = let firstpage = hd (Pdfpage.pages_of_pagetree pdf) in let _, _, w, h = Pdf.parse_rectangle firstpage.Pdfpage.mediabox in addrectangle - fast (w -. linewidth, h -. linewidth) (0., 0., 0.) true linewidth 1. (Cpdfposition.BottomLeft (linewidth /. 2.)) + fast (w -. linewidth, h -. linewidth) (RGB (0., 0., 0.)) true linewidth 1. (Cpdfposition.BottomLeft (linewidth /. 2.)) false false (ilist 1 (Pdfpage.endpage pdf)) pdf let impose ~x ~y ~fit ~columns ~rtl ~btt ~center ~margin ~spacing ~linewidth ~fast pdf = @@ -3579,7 +3592,7 @@ let create_metadata pdf = \end{verbatim} *) -let blacktext_ops (r, g, b) pdf resources content = +let blacktext_ops colour pdf resources content = let not_text = function | Pdfops.Op_Tj _ | Pdfops.Op_TJ _ | Pdfops.Op_' _ | Pdfops.Op_'' (_, _, _) @@ -3603,7 +3616,7 @@ let blacktext_ops (r, g, b) pdf resources content = | Pdfops.Op_BT::more -> incr textlevel; remove_colourops - (Pdfops.Op_rg (r, g, b)::Pdfops.Op_BT::prev) + (colour_op colour::Pdfops.Op_BT::prev) more | Pdfops.Op_ET::more -> decr textlevel; @@ -3643,25 +3656,25 @@ let blacktext_ops (r, g, b) pdf resources content = (* Blacken a form xobject, writing it to the same object. *) -let blacktext (r, g, b) range pdf = +let blacktext c range pdf = let blacktext_page _ page = let content' = - blacktext_ops (r, g, b) pdf page.Pdfpage.resources page.Pdfpage.content + blacktext_ops c pdf page.Pdfpage.resources page.Pdfpage.content in - process_xobjects pdf page (blacktext_ops (r, g, b)); + process_xobjects pdf page (blacktext_ops c); {page with Pdfpage.content = content'} in process_pages (ppstub blacktext_page) pdf range (* \section{Blacken lines} *) -let blacklines_ops (r, g, b) pdf resources content = +let blacklines_ops c pdf resources content = let rec blacken_strokeops prev = function | [] -> rev prev | Pdfops.Op_CS _::t -> blacken_strokeops (Pdfops.Op_CS "/DeviceRGB"::prev) t | (Pdfops.Op_SC _ | Pdfops.Op_SCN _ | Pdfops.Op_SCNName _ | Pdfops.Op_G _ | Pdfops.Op_RG _ | Pdfops.Op_K _)::t -> - blacken_strokeops (Pdfops.Op_RG (r, g, b)::prev) t + blacken_strokeops (colour_op_stroke c::prev) t | h::t -> blacken_strokeops (h::prev) t and operators = Pdfops.parse_operators pdf resources content @@ -3669,25 +3682,25 @@ let blacklines_ops (r, g, b) pdf resources content = let operators' = blacken_strokeops [] operators in [Pdfops.stream_of_ops operators'] -let blacklines (r, g, b) range pdf = +let blacklines c range pdf = let blacklines_page _ page = let content' = - blacklines_ops (r, g, b) pdf page.Pdfpage.resources page.Pdfpage.content + blacklines_ops c pdf page.Pdfpage.resources page.Pdfpage.content in - process_xobjects pdf page (blacklines_ops (r, g, b)); + process_xobjects pdf page (blacklines_ops c); {page with Pdfpage.content = content'} in process_pages (ppstub blacklines_page) pdf range (* \section{Blacken Fills} *) -let blackfills_ops (r, g, b) pdf resources content = +let blackfills_ops c pdf resources content = let rec blacken_fillops prev = function | [] -> rev prev | Pdfops.Op_cs _::t -> blacken_fillops (Pdfops.Op_cs "/DeviceRGB"::prev) t | (Pdfops.Op_sc _ | Pdfops.Op_scn _ | Pdfops.Op_scnName _ | Pdfops.Op_g _ | Pdfops.Op_rg _ | Pdfops.Op_k _)::t -> - blacken_fillops (Pdfops.Op_rg (r, g, b)::prev) t + blacken_fillops (colour_op c::prev) t | h::t -> blacken_fillops (h::prev) t and operators = Pdfops.parse_operators pdf resources content @@ -3695,12 +3708,12 @@ let blackfills_ops (r, g, b) pdf resources content = let operators' = blacken_fillops [] operators in [Pdfops.stream_of_ops operators'] -let blackfills (r, g, b) range pdf = +let blackfills c range pdf = let blackfills_page _ page = let content' = - blackfills_ops (r, g, b) pdf page.Pdfpage.resources page.Pdfpage.content + blackfills_ops c pdf page.Pdfpage.resources page.Pdfpage.content in - process_xobjects pdf page (blackfills_ops (r, g, b)); + process_xobjects pdf page (blackfills_ops c); {page with Pdfpage.content = content'} in process_pages (ppstub blackfills_page) pdf range @@ -4857,3 +4870,5 @@ let extract_images path_to_p2p path_to_im encoding dedup dedup_per_page pdf rang iter (extract_images_form_xobject path_to_p2p path_to_im encoding dedup dedup_per_page pdf serial stem pnum) forms) pages (indx pages) + + diff --git a/cpdf.mli b/cpdf.mli index 3be20fa..cee8fdc 100644 --- a/cpdf.mli +++ b/cpdf.mli @@ -9,6 +9,11 @@ all - the PDF string is output as-is. [UTF8] converts loslessly to UTF8. correspond to 7 bit ASCII. *) type encoding = Raw | UTF8 | Stripped +type color = + Grey of float +| RGB of float * float * float +| CYMK of float * float * float * float + (** {2 Debug} *) (** Debug: Print out a PDF in readable form to the terminal *) @@ -178,7 +183,7 @@ val addtexts : bool -> (* embed font *) int -> (* bates number *) int option -> (* bates padding width *) - float * float * float -> (*colour*) + color -> (*colour*) Cpdfposition.position -> (*position*) float -> (*linespacing*) float -> (*fontsize*) @@ -201,7 +206,7 @@ val addtexts : val addrectangle : bool -> float * float -> - float * float * float -> + color -> bool -> float -> float -> @@ -346,13 +351,13 @@ val add_page_labels : val thinlines : int list -> float -> Pdf.t -> Pdf.t (** Make all text on certain pages black. *) -val blacktext : float * float * float -> int list -> Pdf.t -> Pdf.t +val blacktext : color -> int list -> Pdf.t -> Pdf.t (** Make all lines on certain pages black. *) -val blacklines : float * float * float -> int list -> Pdf.t -> Pdf.t +val blacklines : color -> int list -> Pdf.t -> Pdf.t (** Make all fills on certain pages black. *) -val blackfills : float * float * float -> int list -> Pdf.t -> Pdf.t +val blackfills : color -> int list -> Pdf.t -> Pdf.t (** Remove images from a PDF, optionally adding crossed boxes. *) val draft : string option -> bool -> int list -> Pdf.t -> Pdf.t @@ -419,3 +424,5 @@ val name_of_spec : encoding -> val extract_images : string -> string -> encoding -> bool -> bool -> Pdf.t -> int list -> string -> unit + + diff --git a/cpdfcommand.ml b/cpdfcommand.ml index b0d7393..10c919e 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -377,7 +377,7 @@ type args = mutable font : font; mutable fontname : string; mutable fontsize : float; - mutable color : float * float * float; + mutable color : Cpdf.color; mutable opacity : float; mutable position : Cpdfposition.position; mutable underneath : bool; @@ -493,7 +493,7 @@ let args = font = StandardFont Pdftext.TimesRoman; fontname = "Times-Roman"; fontsize = 12.; - color = 0., 0., 0.; + color = Cpdf.RGB (0., 0., 0.); opacity = 1.; position = Cpdfposition.TopLeft 100.; underneath = false; @@ -609,7 +609,7 @@ let reset_arguments () = args.font <- StandardFont Pdftext.TimesRoman; args.fontname <- "Times-Roman"; args.fontsize <- 12.; - args.color <- 0., 0., 0.; + args.color <- Cpdf.RGB (0., 0., 0.); args.opacity <- 1.; args.position <- Cpdfposition.TopLeft 100.; args.underneath <- false; @@ -1050,11 +1050,11 @@ let setaddtext s = let parse_color s = match String.lowercase s with - | "white" -> 1., 1., 1. - | "black" -> 0., 0., 0. - | "red" -> 1., 0., 0. - | "green" -> 0., 1., 0. - | "blue" -> 0., 0., 1. + | "white" -> Cpdf.RGB (1., 1., 1.) + | "black" -> Cpdf.RGB (0., 0., 0.) + | "red" -> Cpdf.RGB (1., 0., 0.) + | "green" -> Cpdf.RGB (0., 1., 0.) + | "blue" -> Cpdf.RGB (0., 0., 1.) | _ -> let getnum = function | Pdfgenlex.LexInt i -> float i @@ -1062,7 +1062,9 @@ let parse_color s = | _ -> error "Bad color" in match Pdfgenlex.lex_string s with - | [a;b;c] -> getnum a, getnum b, getnum c + | [g] -> Cpdf.Grey (getnum g) + | [r;g;b] -> Cpdf.RGB (getnum r, getnum g, getnum b) + | [c; y; m; k] -> Cpdf.CYMK (getnum c, getnum y, getnum m, getnum k) | _ -> error "Bad color" let setcolor s = diff --git a/cpdfmanual.tex b/cpdfmanual.tex index cb7f636..3a0c206 100644 --- a/cpdfmanual.tex +++ b/cpdfmanual.tex @@ -8,6 +8,7 @@ %Document new text lookup for -add-text and new -raw mode %Document -print-font-table %Document NOT and DUP page ranges +%Document new colourspaces for -add-text -add-rectangle \documentclass{book} % Edit here to produce cpdfmanual.pdf, cpdflibmanual.pdf, pycpdfmanual.pdf etc. \usepackage{comment}\excludecomment{cpdflib}\excludecomment{pycpdflib}