From 7d1733b8230efbf9a4603278cffc42b20cea4a03 Mon Sep 17 00:00:00 2001 From: John Whitington Date: Fri, 7 Jul 2023 14:34:51 +0100 Subject: [PATCH] Beginning -font-ttf for -draw --- cpdfcommand.ml | 53 +++++++++++++++++++++++-------------------------- cpdfdraw.ml | 21 ++++++++++++++------ cpdfdraw.mli | 2 +- cpdfembed.mli | 6 ------ cpdftruetype.ml | 39 +++++++----------------------------- 5 files changed, 48 insertions(+), 73 deletions(-) diff --git a/cpdfcommand.ml b/cpdfcommand.ml index 66a221b..7d770bd 100644 --- a/cpdfcommand.ml +++ b/cpdfcommand.ml @@ -2060,16 +2060,37 @@ let addopacity f = let addsopacity f = addop (Cpdfdraw.SOpacity f) +let embed_font () = + match args.font with + | StandardFont f -> + begin match args.embedstd14 with + | Some dirname -> + begin try + let fontfile, fontname = + let filename = hd (List.assoc f fontnames) in + Pdfio.bytes_of_string (contents_of_file (Filename.concat dirname filename)), + Filename.remove_extension filename + in + Cpdfembed.EmbedInfo {fontfile; fontname; encoding = args.fontencoding} + with + e -> error (Printf.sprintf "Can't load font for embedding: %s\n" (Printexc.to_string e)) + end + | None -> + PreMadeFontPack (Cpdfembed.fontpack_of_standardfont (Pdftext.StandardFont (f, args.fontencoding))) + end + | OtherFont f -> + ExistingNamedFont + | FontToEmbed fontfile -> + EmbedInfo {fontfile; fontname = args.fontname; encoding = args.fontencoding} + let addtext s = begin match !drawops with _::_::_ -> () | _ -> error "-text must be in a -bt / -et section" end; - let font = match args.font with StandardFont s -> s | _ -> error "-text: not a standard font" in - addop (Cpdfdraw.Font (font, args.fontsize)); + addop (Cpdfdraw.Font (embed_font (), args.fontsize)); addop (Cpdfdraw.Text s) let addspecialtext s = begin match !drawops with _::_::_ -> () | _ -> error "-stext must be in a -bt / -et section" end; - let font = match args.font with StandardFont s -> s | _ -> error "-stext: not a standard font" in - addop (Cpdfdraw.Font (font, args.fontsize)); + addop (Cpdfdraw.Font (embed_font (), args.fontsize)); addop (Cpdfdraw.SpecialText s) let setstderrtostdout () = @@ -3454,30 +3475,6 @@ let warn_prerotate range pdf = let prerotate range pdf = Cpdfpage.upright ~fast:args.fast range pdf -let embed_font () = - match args.font with - | StandardFont f -> - (* FIXME proper error handling for missing file etc. *) - begin match args.embedstd14 with - | Some dirname -> - begin try - let fontfile, fontname = - let filename = hd (List.assoc f fontnames) in - Pdfio.bytes_of_string (contents_of_file (Filename.concat dirname filename)), - Filename.remove_extension filename - in - Cpdfembed.EmbedInfo {fontfile; fontname; encoding = args.fontencoding} - with - e -> error (Printf.sprintf "Can't load font for embedding: %s\n" (Printexc.to_string e)) - end - | None -> - PreMadeFontPack (Cpdfembed.fontpack_of_standardfont (Pdftext.StandardFont (f, args.fontencoding))) - end - | OtherFont f -> - ExistingNamedFont - | FontToEmbed fontfile -> - EmbedInfo {fontfile; fontname = args.fontname; encoding = args.fontencoding} - let check_bookmarks_mistake () = if args.merge_add_bookmarks_use_titles && not args.merge_add_bookmarks then Pdfe.log "Warning: -merge-add-bookmarks-use-titles is for use with -merge-add-bookmarks\n" diff --git a/cpdfdraw.ml b/cpdfdraw.ml index 4f46c14..6f34fa5 100644 --- a/cpdfdraw.ml +++ b/cpdfdraw.ml @@ -38,7 +38,7 @@ type drawops = | NewPage | Opacity of float | SOpacity of float - | Font of Pdftext.standard_font * float + | Font of Cpdfembed.cpdffont * float | TextSection of drawops list | Text of string | SpecialText of string @@ -80,7 +80,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_font : Pdftext.font; + mutable current_fontpack : Cpdfembed.cpdffont; mutable num : int} let empty_res () = @@ -90,7 +90,10 @@ let empty_res () = form_xobjects = null_hash (); page_names = []; time = Cpdfstrftime.dummy; - current_font = Pdftext.StandardFont (Pdftext.TimesRoman, Pdftext.WinAnsiEncoding); + current_fontpack = + Cpdfembed.PreMadeFontPack + (Cpdfembed.fontpack_of_standardfont + (Pdftext.StandardFont (Pdftext.TimesRoman, Pdftext.WinAnsiEncoding))); num = 0} let resstack = @@ -133,7 +136,12 @@ let process_specials pdf endpage filename bates batespad num page s = Cpdfaddtext.process_text (res ()).time s pairs let charcodes_of_utf8 s = - implode (map char_of_int (option_map (Pdftext.charcode_extractor_of_font_real (res ()).current_font) (Pdftext.codepoints_of_utf8 s))) + match (res ()).current_fontpack with + | PreMadeFontPack fontpack -> + let codepoints = Pdftext.codepoints_of_utf8 s in + let charcodes = option_map (Cpdfembed.get_char fontpack) codepoints in + implode (map (fun (c, _, _) -> char_of_int c) charcodes) + | _ -> failwith "charcodes_of_utf8: unknown font" let extgstate kind v = try Hashtbl.find (res ()).extgstates (kind, v) with @@ -222,7 +230,8 @@ let rec ops_of_drawop pdf endpage filename bates batespad num page = function | Opacity v -> [Pdfops.Op_gs (extgstate "/ca" v)] | SOpacity v -> [Pdfops.Op_gs (extgstate "/CA" v)] | Font (s, f) -> - let font = Pdftext.StandardFont (s, Pdftext.WinAnsiEncoding) in + [] + (*let font = Pdftext.StandardFont (s, Pdftext.WinAnsiEncoding) in let (n, _) = try Hashtbl.find (res ()).fonts font with Not_found -> @@ -233,7 +242,7 @@ let rec ops_of_drawop pdf endpage filename bates batespad num page = function in (res ()).current_font <- font; (res ()).page_names <- n::(res ()).page_names; - [Pdfops.Op_Tf (n, f)] + [Pdfops.Op_Tf (n, f)]*) | TextSection ops -> [Pdfops.Op_BT] @ ops_of_drawops pdf endpage filename bates batespad num page ops @ [Pdfops.Op_ET] | Text s -> [Pdfops.Op_Tj (charcodes_of_utf8 s)] | SpecialText s -> diff --git a/cpdfdraw.mli b/cpdfdraw.mli index 409421c..0ad9df2 100644 --- a/cpdfdraw.mli +++ b/cpdfdraw.mli @@ -35,7 +35,7 @@ type drawops = | NewPage | Opacity of float | SOpacity of float - | Font of Pdftext.standard_font * float + | Font of Cpdfembed.cpdffont * float | TextSection of drawops list | Text of string | SpecialText of string diff --git a/cpdfembed.mli b/cpdfembed.mli index 6cc89c7..4592a51 100644 --- a/cpdfembed.mli +++ b/cpdfembed.mli @@ -2,12 +2,6 @@ encoding, adding the fontfiles to the PDF and returning a list of font objects, together with a unicode codepoint --> (font number in list, charcode) table *) -(* FIXME: Really we want to create an interactive fontpack which creates fonts - when needed, but delays the actual production of the subset truetype data - until later. This will mean we don't need to pre-calculate the USED set. For - now, we just hack Cpdftoc, cpdfaddtext and cpdftextofpdf to pre-calculate - the subset. *) - type t = Pdftext.font list * (int, int * int) Hashtbl.t type cpdffont = diff --git a/cpdftruetype.ml b/cpdftruetype.ml index 7276946..4bb071d 100644 --- a/cpdftruetype.ml +++ b/cpdftruetype.ml @@ -4,10 +4,10 @@ open Pdfio (* FIXME Proper widths for .notdef, and warn on .notdef being produced *) (* FIXME Add suport for composite glyphs *) -(* FIXME No need for bitstream - everything is byte based, so we can use a normal input *) (* FIXME Get rid of double-calling 1) make font then 2) collect chars then 3) subset it i.e the subset = [] stuff *) -(* FIXME All uses - add text / drawing / texttopdf / table of contents *) -(* FIXME Work across AND? *) +(* FIXME Make it work with -draw *) +(* FIXME Base on bytes not bits *) +(* FIXME proper error handling for missing file in cpdfcommand.embed_font *) let dbg = ref false let _ = @@ -43,7 +43,7 @@ let debug_t t = Printf.printf "firstchar: %i\n" t.firstchar; Printf.printf "lastchar: %i\n" t.lastchar; Printf.printf "widths:"; Array.iter (Printf.printf " %i") t.widths; Printf.printf "\n"; - Printf.printf "fontfile of length %i\n" (Pdfio.bytes_size t.subset_fontfile); + Printf.printf "fontfile of length %i\n" (bytes_size t.subset_fontfile); Printf.printf "subset:"; iter (Printf.printf " U+%04X") t.subset; Printf.printf "\n"; Printf.printf "tounicode:\n"; begin match t.tounicode with @@ -162,7 +162,6 @@ let read_encoding_table fmt length version b = if !dbg then Printf.printf "read_encoding_table: format 0\n"; let t = null_hash () in for x = 0 to 255 do Hashtbl.add t x (read_byte b) done; - (*print_encoding_table 0 t;*) t | 4 -> if !dbg then Printf.printf "read_encoding_table: format 4\n"; @@ -476,23 +475,14 @@ let subset_font major minor tables indexToLocFormat subset encoding cmap loca mk with _ -> ()) newtables; - let obs = bytes_of_write_bitstream bs in - if !dbg then - begin - Printf.printf "Made subset font of length %i bytes\n" (bytes_size obs); - let o = open_out_bin ("fontout" ^ string_of_int (fonum ()) ^ ".ttf") in - output_string o (string_of_bytes obs); - close_out o - end; - obs + bytes_of_write_bitstream bs let write_font filename data = let fh = open_out_bin filename in - output_string fh (Pdfio.string_of_bytes data); + output_string fh (string_of_bytes data); close_out fh let find_main encoding subset = - (*(take subset 3, [drop subset 3])*) let encoding_table = Pdftext.table_of_encoding encoding in let first, rest = List.partition @@ -502,12 +492,6 @@ let find_main encoding subset = (first, splitinto 224 rest) let parse ~subset data encoding = - if !dbg then - begin - Printf.printf "********Cpdftruetype.parse SUBSET is "; - iter (Printf.printf "U+%04X ") subset; - Printf.printf "\n" - end; let mk_b byte_offset = bitbytes_of_input (let i = input_of_bytes data in i.seek_in byte_offset; i) in let b = mk_b 0 in let major, minor = read_fixed b in @@ -591,8 +575,7 @@ let parse ~subset data encoding = let version = read_ushort b in if !dbg then Printf.printf "subtable has format %i, length %i, version %i\n" fmt lngth version; let got_glyphcodes = read_encoding_table fmt lngth version b in - (*if fmt = 4 then print_encoding_table 4 got_glyphcodes;*) - (*if fmt = 4 then *)Hashtbl.iter (Hashtbl.add !glyphcodes) got_glyphcodes + Hashtbl.iter (Hashtbl.add !glyphcodes) got_glyphcodes done; end; let maxpoffset, maxplength = @@ -610,14 +593,6 @@ let parse ~subset data encoding = | [] -> raise (Pdf.PDFError "No loca table found in TrueType font") in let subset_1, subsets_2 = find_main encoding subset in - (*if !dbg && subset <> [] then - begin - Printf.printf "***********Chars for main WinAnsiEncoding subset:\n"; - iter (Printf.printf "U+%04X ") subset_1; - Printf.printf "\n***********Chars for higher subset:\n"; - iter (Printf.printf "U+%04X ") subset_2; - Printf.printf "\n"; - end;*) let flags_1 = calculate_flags false italicangle in let flags_2 = calculate_flags true italicangle in let firstchar_1, lastchar_1 = calculate_limits subset_1 in