Beginning -font-ttf for -draw

This commit is contained in:
John Whitington 2023-07-07 14:34:51 +01:00
parent 64860ffbff
commit 7d1733b823
5 changed files with 48 additions and 73 deletions

View File

@ -2060,16 +2060,37 @@ let addopacity f =
let addsopacity f = let addsopacity f =
addop (Cpdfdraw.SOpacity 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 = let addtext s =
begin match !drawops with _::_::_ -> () | _ -> error "-text must be in a -bt / -et section" end; 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 (embed_font (), args.fontsize));
addop (Cpdfdraw.Font (font, args.fontsize));
addop (Cpdfdraw.Text s) addop (Cpdfdraw.Text s)
let addspecialtext s = let addspecialtext s =
begin match !drawops with _::_::_ -> () | _ -> error "-stext must be in a -bt / -et section" end; 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 (embed_font (), args.fontsize));
addop (Cpdfdraw.Font (font, args.fontsize));
addop (Cpdfdraw.SpecialText s) addop (Cpdfdraw.SpecialText s)
let setstderrtostdout () = let setstderrtostdout () =
@ -3454,30 +3475,6 @@ let warn_prerotate range pdf =
let prerotate range pdf = let prerotate range pdf =
Cpdfpage.upright ~fast:args.fast 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 () = let check_bookmarks_mistake () =
if args.merge_add_bookmarks_use_titles && not args.merge_add_bookmarks then 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" Pdfe.log "Warning: -merge-add-bookmarks-use-titles is for use with -merge-add-bookmarks\n"

View File

@ -38,7 +38,7 @@ type drawops =
| NewPage | NewPage
| Opacity of float | Opacity of float
| SOpacity of float | SOpacity of float
| Font of Pdftext.standard_font * float | Font of Cpdfembed.cpdffont * float
| TextSection of drawops list | TextSection of drawops list
| Text of string | Text of string
| SpecialText of string | SpecialText of string
@ -80,7 +80,7 @@ type res =
form_xobjects : (string, (string * int)) Hashtbl.t; (* (name, (pdf name, objnum)) *) form_xobjects : (string, (string * int)) Hashtbl.t; (* (name, (pdf name, objnum)) *)
mutable page_names : string list; mutable page_names : string list;
mutable time : Cpdfstrftime.t; mutable time : Cpdfstrftime.t;
mutable current_font : Pdftext.font; mutable current_fontpack : Cpdfembed.cpdffont;
mutable num : int} mutable num : int}
let empty_res () = let empty_res () =
@ -90,7 +90,10 @@ let empty_res () =
form_xobjects = null_hash (); form_xobjects = null_hash ();
page_names = []; page_names = [];
time = Cpdfstrftime.dummy; 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} num = 0}
let resstack = let resstack =
@ -133,7 +136,12 @@ let process_specials pdf endpage filename bates batespad num page s =
Cpdfaddtext.process_text (res ()).time s pairs Cpdfaddtext.process_text (res ()).time s pairs
let charcodes_of_utf8 s = 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 = let extgstate kind v =
try Hashtbl.find (res ()).extgstates (kind, v) with 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)] | Opacity v -> [Pdfops.Op_gs (extgstate "/ca" v)]
| SOpacity v -> [Pdfops.Op_gs (extgstate "/CA" v)] | SOpacity v -> [Pdfops.Op_gs (extgstate "/CA" v)]
| Font (s, f) -> | Font (s, f) ->
let font = Pdftext.StandardFont (s, Pdftext.WinAnsiEncoding) in []
(*let font = Pdftext.StandardFont (s, Pdftext.WinAnsiEncoding) in
let (n, _) = let (n, _) =
try Hashtbl.find (res ()).fonts font with try Hashtbl.find (res ()).fonts font with
Not_found -> Not_found ->
@ -233,7 +242,7 @@ let rec ops_of_drawop pdf endpage filename bates batespad num page = function
in in
(res ()).current_font <- font; (res ()).current_font <- font;
(res ()).page_names <- n::(res ()).page_names; (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] | 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)] | Text s -> [Pdfops.Op_Tj (charcodes_of_utf8 s)]
| SpecialText s -> | SpecialText s ->

View File

@ -35,7 +35,7 @@ type drawops =
| NewPage | NewPage
| Opacity of float | Opacity of float
| SOpacity of float | SOpacity of float
| Font of Pdftext.standard_font * float | Font of Cpdfembed.cpdffont * float
| TextSection of drawops list | TextSection of drawops list
| Text of string | Text of string
| SpecialText of string | SpecialText of string

View File

@ -2,12 +2,6 @@
encoding, adding the fontfiles to the PDF and returning a list of font objects, 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 *) 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 t = Pdftext.font list * (int, int * int) Hashtbl.t
type cpdffont = type cpdffont =

View File

@ -4,10 +4,10 @@ open Pdfio
(* FIXME Proper widths for .notdef, and warn on .notdef being produced *) (* FIXME Proper widths for .notdef, and warn on .notdef being produced *)
(* FIXME Add suport for composite glyphs *) (* 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 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 Make it work with -draw *)
(* FIXME Work across AND? *) (* FIXME Base on bytes not bits *)
(* FIXME proper error handling for missing file in cpdfcommand.embed_font *)
let dbg = ref false let dbg = ref false
let _ = let _ =
@ -43,7 +43,7 @@ let debug_t t =
Printf.printf "firstchar: %i\n" t.firstchar; Printf.printf "firstchar: %i\n" t.firstchar;
Printf.printf "lastchar: %i\n" t.lastchar; Printf.printf "lastchar: %i\n" t.lastchar;
Printf.printf "widths:"; Array.iter (Printf.printf " %i") t.widths; Printf.printf "\n"; 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 "subset:"; iter (Printf.printf " U+%04X") t.subset; Printf.printf "\n";
Printf.printf "tounicode:\n"; Printf.printf "tounicode:\n";
begin match t.tounicode with 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"; if !dbg then Printf.printf "read_encoding_table: format 0\n";
let t = null_hash () in let t = null_hash () in
for x = 0 to 255 do Hashtbl.add t x (read_byte b) done; for x = 0 to 255 do Hashtbl.add t x (read_byte b) done;
(*print_encoding_table 0 t;*)
t t
| 4 -> | 4 ->
if !dbg then Printf.printf "read_encoding_table: format 4\n"; 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 with
_ -> ()) _ -> ())
newtables; newtables;
let obs = bytes_of_write_bitstream bs in bytes_of_write_bitstream bs
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
let write_font filename data = let write_font filename data =
let fh = open_out_bin filename in 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 close_out fh
let find_main encoding subset = let find_main encoding subset =
(*(take subset 3, [drop subset 3])*)
let encoding_table = Pdftext.table_of_encoding encoding in let encoding_table = Pdftext.table_of_encoding encoding in
let first, rest = let first, rest =
List.partition List.partition
@ -502,12 +492,6 @@ let find_main encoding subset =
(first, splitinto 224 rest) (first, splitinto 224 rest)
let parse ~subset data encoding = 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 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 b = mk_b 0 in
let major, minor = read_fixed b in let major, minor = read_fixed b in
@ -591,8 +575,7 @@ let parse ~subset data encoding =
let version = read_ushort b in let version = read_ushort b in
if !dbg then Printf.printf "subtable has format %i, length %i, version %i\n" fmt lngth version; 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 let got_glyphcodes = read_encoding_table fmt lngth version b in
(*if fmt = 4 then print_encoding_table 4 got_glyphcodes;*) Hashtbl.iter (Hashtbl.add !glyphcodes) got_glyphcodes
(*if fmt = 4 then *)Hashtbl.iter (Hashtbl.add !glyphcodes) got_glyphcodes
done; done;
end; end;
let maxpoffset, maxplength = let maxpoffset, maxplength =
@ -610,14 +593,6 @@ let parse ~subset data encoding =
| [] -> raise (Pdf.PDFError "No loca table found in TrueType font") | [] -> raise (Pdf.PDFError "No loca table found in TrueType font")
in in
let subset_1, subsets_2 = find_main encoding subset 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_1 = calculate_flags false italicangle in
let flags_2 = calculate_flags true italicangle in let flags_2 = calculate_flags true italicangle in
let firstchar_1, lastchar_1 = calculate_limits subset_1 in let firstchar_1, lastchar_1 = calculate_limits subset_1 in