From 951a947f439335b5bcaaa311a606b1e61a034b82 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Mon, 17 Jul 2023 13:38:35 +0100 Subject: [PATCH] mixed ttf fonts in -draw --- cpdfcommand.ml | 58 ++++++++++++++++--------------- cpdfdraw.ml | 92 +++++++++++++++++++++++++++----------------------- 2 files changed, 81 insertions(+), 69 deletions(-) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index e55d178..41386ed 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -1728,10 +1728,6 @@ let setidironlypdfs () = let setnowarnrotate () = args.no_warn_rotate <- true -let setfontttf s = - let fontname, _ = Hashtbl.find ttfs s in - args.font <- EmbeddedFont s; - args.fontname <- fontname let setfontttfencoding s = args.fontencoding <- @@ -2046,9 +2042,10 @@ let addopacity f = let addsopacity f = addop (Cpdfdraw.SOpacity f) -let embed_font () = - match args.font with +let embed_font_inner font = + match font with | StandardFont f -> + Printf.printf "embed_font: StandardFont\n"; begin match args.embedstd14 with | Some dirname -> begin try @@ -2067,6 +2064,7 @@ let embed_font () = | OtherFont f -> ExistingNamedFont | EmbeddedFont name -> + Printf.printf "embed_font: TTF\n"; try let fontname, font = Hashtbl.find ttfs name in args.fontname <- fontname; @@ -2074,24 +2072,32 @@ let embed_font () = with Not_found -> error (Printf.sprintf "Font %s not found" name) +let embed_font () = embed_font_inner args.font + let setfont f = - let convert f = (* convert from written PDF representation to internal PDF string e.g # sequences *) - match Pdfread.lex_name (Pdfio.input_of_string f) with Pdfgenlex.LexName s -> s | _ -> assert false - in - args.font <- - begin match Pdftext.standard_font_of_name ("/" ^ f) with - | Some x -> StandardFont x - | None -> - if f <> "" && hd (explode f) <> '/' then error "Custom font names must begin with /"; - OtherFont (convert f) - end; - args.fontname <- - begin match Pdftext.standard_font_of_name ("/" ^ f) with - | Some x -> f - | None -> convert f - end; - (* If drawing, add the font pack as an op. *) - begin match args.op with Some Draw -> addop (Cpdfdraw.FontPack (f, embed_font (), null_hash ())) | _ -> () end + try + let fontname, _ = Hashtbl.find ttfs f in + args.font <- EmbeddedFont f; + args.fontname <- fontname + with + Not_found -> + let convert f = (* convert from written PDF representation to internal PDF string e.g # sequences *) + match Pdfread.lex_name (Pdfio.input_of_string f) with Pdfgenlex.LexName s -> s | _ -> assert false + in + args.font <- + begin match Pdftext.standard_font_of_name ("/" ^ f) with + | Some x -> StandardFont x + | None -> + if f <> "" && hd (explode f) <> '/' then error "Custom font names must begin with /"; + OtherFont (convert f) + end; + args.fontname <- + begin match Pdftext.standard_font_of_name ("/" ^ f) with + | Some x -> f + | None -> convert f + end; + (* If drawing, add the font pack as an op. *) + begin match args.op with Some Draw -> addop (Cpdfdraw.FontPack (f, embed_font (), null_hash ())) | _ -> () end let loadttf n = Printf.printf "loadttf: %s\n" n; @@ -2108,7 +2114,8 @@ let loadttf n = name (fontname, Cpdfembed.EmbedInfo {fontfile; fontname; encoding = args.fontencoding}); (* If drawing, add the font pack as an op. *) - begin match args.op with Some Draw -> addop (Cpdfdraw.FontPack (fontname, embed_font (), null_hash ())) | _ -> () end + begin match args.op with + Some Draw -> addop (Cpdfdraw.FontPack (fontname, embed_font_inner (EmbeddedFont name), null_hash ())) | _ -> () end with _ -> error "addjpeg: could not load JPEG" @@ -2447,9 +2454,6 @@ and specs = ("-font-encoding", Arg.String setfontttfencoding, " Set the encoding for the TrueType font"); - ("-font-ttf", - Arg.String setfontttf, - " Use a TrueType font"); ("-embed-std14", Arg.String setembedstd14, " Embed standard 14 fonts"); diff --git a/cpdfdraw.ml b/cpdfdraw.ml index 3b3c0a5..965b5a9 100644 --- a/cpdfdraw.ml +++ b/cpdfdraw.ml @@ -1,8 +1,6 @@ open Pdfutil open Cpdferror -(* FIXME Use hashtbl.replace everywhere? *) - type colspec = NoCol | RGB of float * float * float @@ -84,7 +82,7 @@ type res = form_xobjects : (string, (string * int)) Hashtbl.t; (* (name, (pdf name, objnum)) *) mutable page_names : string list; mutable time : Cpdfstrftime.t; - mutable current_fontpack : Cpdfembed.t; + mutable current_fontpack : string * Cpdfembed.t; mutable current_fontpack_codepoints : (int, unit) Hashtbl.t; mutable font_size : float; mutable num : int} @@ -102,7 +100,7 @@ let empty_res () = form_xobjects = null_hash (); page_names = []; time = Cpdfstrftime.dummy; - current_fontpack = default_fontpack; + current_fontpack = ("Times-Roman", default_fontpack); current_fontpack_codepoints = null_hash (); font_size = 12.; num = 0} @@ -147,13 +145,14 @@ let process_specials pdf endpage filename bates batespad num page s = Cpdfaddtext.process_text (res ()).time s pairs let runs_of_utf8 s = - let fontpack = (res ()).current_fontpack in + let identifier, fontpack = (res ()).current_fontpack in + Printf.printf "runs_of_utf8: %s\n" identifier; let codepoints = Pdftext.codepoints_of_utf8 s in - (*Printf.printf "%i codepoints\n" (length codepoints);*) + Printf.printf "%i codepoints\n" (length codepoints); let triples = option_map (Cpdfembed.get_char fontpack) codepoints in - (*Printf.printf "%i triples\n" (length triples);*) + Printf.printf "%i triples\n" (length triples); let collated = Cpdfembed.collate_runs triples in - (*Printf.printf "Collated of length %i\n" (length collated);*) + Printf.printf "Collated of length %i\n" (length collated); flatten (map (fun l -> @@ -169,7 +168,7 @@ let extgstate kind v = try Hashtbl.find (res ()).extgstates (kind, v) with Not_found -> let n = fresh_name "/G" in - Hashtbl.add (res ()).extgstates (kind, v) n; + Hashtbl.replace (res ()).extgstates (kind, v) n; n let read_resource pdf n res = @@ -247,46 +246,54 @@ let rec ops_of_drawop dryrun pdf endpage filename bates batespad num page = func (res ()).page_names <- pdfname::(res ()).page_names; [Pdfops.Op_Do pdfname] | ImageXObject (s, obj) -> - Hashtbl.add (res ()).images s (fresh_name "/I", Pdf.addobj pdf obj); + Hashtbl.replace (res ()).images s (fresh_name "/I", Pdf.addobj pdf obj); [] | NewPage -> Pdfe.log ("NewPage remaining in graphic stream"); assert false | Opacity v -> [Pdfops.Op_gs (extgstate "/ca" v)] | SOpacity v -> [Pdfops.Op_gs (extgstate "/CA" v)] | FontPack (identifier, cpdffont, codepoints) -> - begin match Hashtbl.find fontpacks identifier with - | fontpack -> () - (*Printf.printf "Cpdfdraw: using existing fontpack %s\n" identifier*) - | exception Not_found -> - (*Printf.printf "Cpdfdraw: storing new fontpack %s\n" identifier;*) - let fontpack = - match cpdffont with - | PreMadeFontPack fp -> fp - | EmbedInfo {fontfile; fontname; encoding} -> - let codepoints = map fst (list_of_hashtbl codepoints) in - if codepoints = [] then default_fontpack else - Cpdfembed.embed_truetype pdf ~fontfile ~fontname ~codepoints ~encoding - | ExistingNamedFont -> - error "-draw does not support using an existing named font" - in - Hashtbl.add fontpacks identifier (fontpack, codepoints); - let ns = - map - (fun font -> - try fst (Hashtbl.find (res ()).fonts font) with - Not_found -> - let o = if dryrun then 0 else Pdftext.write_font pdf font in - let n = fresh_name "/F" in - Hashtbl.add (res ()).fonts font (n, o); - n) - (fst fontpack) + Printf.printf "FontPack op: %s\n" identifier; + let fontpack = + match Hashtbl.find fontpacks identifier with + | (fontpack, _) -> + Printf.printf "Cpdfdraw FontPack op: using existing fontpack %s\n" identifier; + fontpack + | exception Not_found -> + Printf.printf "Cpdfdraw FontPack op: storing new fontpack %s\n" identifier; + let fontpack = + match cpdffont with + | PreMadeFontPack fp -> + Printf.printf "it's a pre-made font pack\n"; + fp + | EmbedInfo {fontfile; fontname; encoding} -> + let codepoints = map fst (list_of_hashtbl codepoints) in + Printf.printf "%i codepoints to embed\n" (length codepoints); + if codepoints = [] then default_fontpack else + Cpdfembed.embed_truetype pdf ~fontfile ~fontname ~codepoints ~encoding + | ExistingNamedFont -> + error "-draw does not support using an existing named font" in - (res ()).page_names <- ns @ (res ()).page_names - end; - [] + Hashtbl.replace fontpacks identifier (fontpack, codepoints); + fontpack + in + let ns = + map + (fun font -> + try fst (Hashtbl.find (res ()).fonts font) with + Not_found -> + let o = if dryrun then 0 else Pdftext.write_font pdf font in + let n = fresh_name "/F" in + Printf.printf "Adding font %s as %s\n" identifier n; + Hashtbl.replace (res ()).fonts font (n, o); + n) + (fst fontpack) + in + (res ()).page_names <- ns @ (res ()).page_names; + [] | Font (identifier, size) -> - (*Printf.printf "Changing to stored font %s\n" identifier;*) + Printf.printf "Cpdfdraw Font op: Changing to stored font %s\n" identifier; let fontpack, codepoints = Hashtbl.find fontpacks identifier in - (res ()).current_fontpack <- fontpack; + (res ()).current_fontpack <- (identifier, fontpack); if dryrun then (res ()).current_fontpack_codepoints <- codepoints; (res ()).font_size <- size; [] @@ -327,7 +334,7 @@ and create_form_xobject dryrun a b c d pdf endpage filename bates batespad num p Pdf.Got data)} in respop (); - Hashtbl.add (res ()).form_xobjects n (fresh_name "/X", (if dryrun then 0 else Pdf.addobj pdf obj)) + Hashtbl.replace (res ()).form_xobjects n (fresh_name "/X", (if dryrun then 0 else Pdf.addobj pdf obj)) let minimum_resource_number pdf range = let pages = Pdfpage.pages_of_pagetree pdf in @@ -381,6 +388,7 @@ let draw_single ~fast ~underneath ~filename ~bates ~batespad fast range pdf draw ignore (ops_of_drawops true pdf endpage filename bates batespad 0 (hd pages) drawops); restore_whole_stack r; Hashtbl.clear fontpacks; + Printf.printf "--------------------------\n"; Some (ops_of_drawops false pdf endpage filename bates batespad 0 (hd pages) drawops) end in