This commit is contained in:
John Whitington 2021-11-15 11:17:15 -08:00
parent b908e5f57d
commit 0b5f46044e
5 changed files with 61 additions and 35 deletions

View File

@ -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

57
cpdf.ml
View File

@ -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 =
<ops minus any text positioning or text rendering ones>
\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)

View File

@ -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

View File

@ -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 =

View File

@ -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}