cpdf-source/cpdfembed.ml

98 lines
3.3 KiB
OCaml
Raw Normal View History

2022-09-12 17:06:56 +02:00
(* Embed a font *)
2022-09-11 15:52:08 +02:00
open Pdfutil
2022-10-19 15:36:26 +02:00
type t = Pdftext.font list * (int, int * int) Hashtbl.t (* Table returns font number and charcode for given unicode codepoint *)
2022-10-13 18:00:33 +02:00
2022-10-18 20:13:02 +02:00
type cpdffont =
PreMadeFontPack of t
2022-10-19 14:48:13 +02:00
| EmbedInfo of {fontfile : Pdfio.bytes; fontname : string; encoding : Pdftext.encoding}
2022-10-18 20:13:02 +02:00
| ExistingNamedFont of string
2022-09-11 21:07:55 +02:00
let pdfcode_of_unicode_codepoint encoding_table glyphlist_table u =
2022-09-11 15:52:08 +02:00
try
Some (Hashtbl.find encoding_table (Hashtbl.find glyphlist_table [u]))
with
Not_found -> None
2022-09-11 21:07:55 +02:00
let calc_accepted_unicodepoints encoding_table glyphlist_table codepoints =
2022-09-11 15:52:08 +02:00
setify
(option_map
2022-09-12 17:06:56 +02:00
(fun u ->
match
pdfcode_of_unicode_codepoint encoding_table glyphlist_table u
with
| Some _ -> Some u
| None -> None)
2022-09-11 15:52:08 +02:00
codepoints)
let fontnum = ref 0
let basename () =
incr fontnum;
"AAAAA" ^ string_of_char (char_of_int (!fontnum + 65))
2022-10-10 17:40:57 +02:00
let make_single_font ~fontname ~encoding pdf f =
2022-09-11 21:07:55 +02:00
let name_1 = basename () in
2022-09-29 15:48:34 +02:00
let module TT = Cpdftruetype in
2022-09-11 21:07:55 +02:00
let fontfile =
2022-10-10 15:51:58 +02:00
let len = Pdfio.bytes_size f.TT.subset_fontfile in
2022-09-11 21:07:55 +02:00
Pdf.Stream
{contents =
2022-09-12 17:06:56 +02:00
(Pdf.Dictionary
[("/Length", Pdf.Integer len); ("/Length1", Pdf.Integer len)],
2022-10-10 15:51:58 +02:00
Pdf.Got f.TT.subset_fontfile)}
2022-09-11 21:07:55 +02:00
in
let fontfile_num = Pdf.addobj pdf fontfile in
2022-09-15 19:13:42 +02:00
let open Pdftext in
2022-09-16 17:53:47 +02:00
let fontmetrics =
let a = Array.make 256 0. in
for x = f.TT.firstchar to f.TT.lastchar do
a.(x) <- float_of_int (f.TT.widths.(x - f.TT.firstchar))
done;
a
in
2022-10-10 17:40:57 +02:00
(f.TT.subset,
2022-10-10 17:08:07 +02:00
SimpleFont
2022-09-15 19:13:42 +02:00
{fonttype = Truetype;
basefont = Printf.sprintf "/%s+%s" name_1 fontname;
2022-09-16 17:53:47 +02:00
fontmetrics = Some fontmetrics;
2022-09-15 19:13:42 +02:00
firstchar = f.TT.firstchar;
lastchar = f.TT.lastchar;
widths = f.TT.widths;
fontdescriptor = Some
{ascent = float_of_int f.TT.ascent;
descent = float_of_int f.TT.descent;
avgwidth = float_of_int f.TT.avgwidth;
maxwidth = float_of_int f.TT.maxwidth;
flags = f.TT.flags;
italicangle = float_of_int f.TT.italicangle;
capheight = float_of_int f.TT.capheight;
xheight = float_of_int f.TT.xheight;
stemv = float_of_int f.TT.stemv;
fontbbox = (float_of_int f.TT.minx, float_of_int f.TT.miny,
float_of_int f.TT.maxx, float_of_int f.TT.maxy);
fontfile = Some (FontFile2 fontfile_num);
charset = None;
2022-10-10 17:40:57 +02:00
tounicode = f.TT.tounicode};
encoding})
2022-10-13 18:00:33 +02:00
let make_fontpack_hashtable fs =
let indexes = indx0 fs in
let table = null_hash () in
iter2
(fun i (subset, f) ->
let charcode_extractor = Pdftext.charcode_extractor_of_font_real f in
iter
(fun u -> Hashtbl.add table u (i, unopt (charcode_extractor u)))
subset)
indexes fs;
table
2022-10-10 17:40:57 +02:00
let embed_truetype pdf ~fontfile ~fontname ~codepoints ~encoding =
let glyphlist_table = Pdfglyphlist.reverse_glyph_hashes () in
let encoding_table = Pdftext.reverse_table_of_encoding encoding in
2022-10-13 18:00:33 +02:00
let accepted_unicodepoints = calc_accepted_unicodepoints encoding_table glyphlist_table codepoints in
2022-10-10 17:40:57 +02:00
let fs = Cpdftruetype.parse ~subset:accepted_unicodepoints fontfile encoding in
2022-10-13 18:00:33 +02:00
let subsets_and_their_fonts = map (make_single_font ~fontname ~encoding pdf) fs in
(map snd subsets_and_their_fonts, make_fontpack_hashtable subsets_and_their_fonts)