/src/mupdf/source/pdf/pdf-font.c
Line | Count | Source |
1 | | // Copyright (C) 2004-2026 Artifex Software, Inc. |
2 | | // |
3 | | // This file is part of MuPDF. |
4 | | // |
5 | | // MuPDF is free software: you can redistribute it and/or modify it under the |
6 | | // terms of the GNU Affero General Public License as published by the Free |
7 | | // Software Foundation, either version 3 of the License, or (at your option) |
8 | | // any later version. |
9 | | // |
10 | | // MuPDF is distributed in the hope that it will be useful, but WITHOUT ANY |
11 | | // WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
12 | | // FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more |
13 | | // details. |
14 | | // |
15 | | // You should have received a copy of the GNU Affero General Public License |
16 | | // along with MuPDF. If not, see <https://www.gnu.org/licenses/agpl-3.0.en.html> |
17 | | // |
18 | | // Alternative licensing terms are available from the licensor. |
19 | | // For commercial licensing, see <https://www.artifex.com/> or contact |
20 | | // Artifex Software, Inc., 39 Mesa Street, Suite 108A, San Francisco, |
21 | | // CA 94129, USA, for further information. |
22 | | |
23 | | #include "mupdf/fitz.h" |
24 | | #include "mupdf/pdf.h" |
25 | | |
26 | | #include <assert.h> |
27 | | |
28 | | #include <ft2build.h> |
29 | | #include FT_FREETYPE_H |
30 | | #include FT_ADVANCES_H |
31 | | #ifdef FT_FONT_FORMATS_H |
32 | | #include FT_FONT_FORMATS_H |
33 | | #else |
34 | | #include FT_XFREE86_H |
35 | | #endif |
36 | | #include FT_TRUETYPE_TABLES_H |
37 | | |
38 | | #ifndef FT_SFNT_HEAD |
39 | | #define FT_SFNT_HEAD ft_sfnt_head |
40 | | #endif |
41 | | |
42 | | void |
43 | | pdf_load_encoding(const char **estrings, const char *encoding) |
44 | 128 | { |
45 | 128 | const char * const *bstrings = NULL; |
46 | 128 | int i; |
47 | | |
48 | 128 | if (!strcmp(encoding, "StandardEncoding")) |
49 | 48 | bstrings = fz_glyph_name_from_adobe_standard; |
50 | 128 | if (!strcmp(encoding, "MacRomanEncoding")) |
51 | 28 | bstrings = fz_glyph_name_from_mac_roman; |
52 | 128 | if (!strcmp(encoding, "MacExpertEncoding")) |
53 | 0 | bstrings = fz_glyph_name_from_mac_expert; |
54 | 128 | if (!strcmp(encoding, "WinAnsiEncoding")) |
55 | 52 | bstrings = fz_glyph_name_from_win_ansi; |
56 | | |
57 | 128 | if (bstrings) |
58 | 32.8k | for (i = 0; i < 256; i++) |
59 | 32.7k | estrings[i] = bstrings[i]; |
60 | 128 | } |
61 | | |
62 | | static void pdf_load_font_descriptor(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, pdf_obj *dict, |
63 | | const char *collection, const char *basefont, int iscidfont, pdf_obj *fftype); |
64 | | |
65 | | static const char *base_font_names[][10] = |
66 | | { |
67 | | { "Courier", "CourierNew", "CourierNewPSMT", NULL }, |
68 | | { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", |
69 | | "CourierNewPS-BoldMT", "CourierNew-Bold", NULL }, |
70 | | { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", |
71 | | "CourierNewPS-ItalicMT", "CourierNew-Italic", NULL }, |
72 | | { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", |
73 | | "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", NULL }, |
74 | | { "Helvetica", "ArialMT", "Arial", NULL }, |
75 | | { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", |
76 | | "Helvetica,Bold", NULL }, |
77 | | { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", |
78 | | "Helvetica,Italic", "Helvetica-Italic", NULL }, |
79 | | { "Helvetica-BoldOblique", "Arial-BoldItalicMT", |
80 | | "Arial,BoldItalic", "Arial-BoldItalic", |
81 | | "Helvetica,BoldItalic", "Helvetica-BoldItalic", NULL }, |
82 | | { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", |
83 | | "TimesNewRomanPS", NULL }, |
84 | | { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", |
85 | | "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", NULL }, |
86 | | { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", |
87 | | "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", NULL }, |
88 | | { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", |
89 | | "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", |
90 | | "TimesNewRoman-BoldItalic", NULL }, |
91 | | { "Symbol", "Symbol,Italic", "Symbol,Bold", "Symbol,BoldItalic", |
92 | | "SymbolMT", "SymbolMT,Italic", "SymbolMT,Bold", "SymbolMT,BoldItalic", NULL }, |
93 | | { "ZapfDingbats", NULL } |
94 | | }; |
95 | | |
96 | | const unsigned char * |
97 | | pdf_lookup_substitute_font(fz_context *ctx, int mono, int serif, int bold, int italic, int *len) |
98 | 72 | { |
99 | 72 | if (mono) { |
100 | 0 | if (bold) { |
101 | 0 | if (italic) return fz_lookup_base14_font(ctx, "Courier-BoldOblique", len); |
102 | 0 | else return fz_lookup_base14_font(ctx, "Courier-Bold", len); |
103 | 0 | } else { |
104 | 0 | if (italic) return fz_lookup_base14_font(ctx, "Courier-Oblique", len); |
105 | 0 | else return fz_lookup_base14_font(ctx, "Courier", len); |
106 | 0 | } |
107 | 72 | } else if (serif) { |
108 | 18 | if (bold) { |
109 | 4 | if (italic) return fz_lookup_base14_font(ctx, "Times-BoldItalic", len); |
110 | 0 | else return fz_lookup_base14_font(ctx, "Times-Bold", len); |
111 | 14 | } else { |
112 | 14 | if (italic) return fz_lookup_base14_font(ctx, "Times-Italic", len); |
113 | 10 | else return fz_lookup_base14_font(ctx, "Times-Roman", len); |
114 | 14 | } |
115 | 54 | } else { |
116 | 54 | if (bold) { |
117 | 4 | if (italic) return fz_lookup_base14_font(ctx, "Helvetica-BoldOblique", len); |
118 | 4 | else return fz_lookup_base14_font(ctx, "Helvetica-Bold", len); |
119 | 50 | } else { |
120 | 50 | if (italic) return fz_lookup_base14_font(ctx, "Helvetica-Oblique", len); |
121 | 50 | else return fz_lookup_base14_font(ctx, "Helvetica", len); |
122 | 50 | } |
123 | 54 | } |
124 | 72 | } |
125 | | |
126 | | static int is_dynalab(char *name) |
127 | 228 | { |
128 | 228 | if (strstr(name, "HuaTian")) |
129 | 0 | return 1; |
130 | 228 | if (strstr(name, "MingLi")) |
131 | 0 | return 1; |
132 | 228 | if ((strstr(name, "DF") == name) || strstr(name, "+DF")) |
133 | 0 | return 1; |
134 | 228 | if ((strstr(name, "DLC") == name) || strstr(name, "+DLC")) |
135 | 0 | return 1; |
136 | 228 | return 0; |
137 | 228 | } |
138 | | |
139 | | static const char *skip_subset_prefix(const char *name) |
140 | 246 | { |
141 | 246 | int i; |
142 | 949 | for (i = 0; i < 6; ++i) |
143 | 881 | if (name[i] < 'A' || name[i] > 'Z') |
144 | 178 | return name; |
145 | 68 | return (name[6] == '+' && name[7] != 0) ? name + 7 : name; |
146 | 246 | } |
147 | | |
148 | | static int strcmp_ignore_space(const char *a, const char *b) |
149 | 9.08k | { |
150 | 19.5k | while (1) |
151 | 19.5k | { |
152 | 19.5k | while (*a == ' ') |
153 | 0 | a++; |
154 | 19.6k | while (*b == ' ') |
155 | 147 | b++; |
156 | 19.5k | if (*a != *b) |
157 | 8.98k | return 1; |
158 | 10.5k | if (*a == 0) |
159 | 107 | return *a != *b; |
160 | 10.4k | if (*b == 0) |
161 | 0 | return *a != *b; |
162 | 10.4k | a++; |
163 | 10.4k | b++; |
164 | 10.4k | } |
165 | 9.08k | } |
166 | | |
167 | | const char *pdf_clean_font_name(const char *fontname) |
168 | 174 | { |
169 | 174 | int i, k; |
170 | 174 | const char *s = skip_subset_prefix(fontname); |
171 | 2.05k | for (i = 0; i < (int)nelem(base_font_names); i++) |
172 | 10.9k | for (k = 0; base_font_names[i][k]; k++) |
173 | 9.08k | if (!strcmp_ignore_space(base_font_names[i][k], s)) |
174 | 107 | return base_font_names[i][0]; |
175 | 67 | return fontname; |
176 | 174 | } |
177 | | |
178 | | /* |
179 | | * FreeType and Rendering glue |
180 | | */ |
181 | | |
182 | | enum { UNKNOWN, TYPE1, TRUETYPE }; |
183 | | |
184 | | static int ft_kind(fz_context *ctx, FT_Face face) |
185 | 1.10k | { |
186 | 1.10k | const char *kind; |
187 | 1.10k | fz_ft_lock(ctx); |
188 | 1.10k | #ifdef FT_FONT_FORMATS_H |
189 | 1.10k | kind = FT_Get_Font_Format(face); |
190 | | #else |
191 | | kind = FT_Get_X11_Font_Format(face); |
192 | | #endif |
193 | 1.10k | fz_ft_unlock(ctx); |
194 | 1.10k | if (!strcmp(kind, "TrueType")) return TRUETYPE; |
195 | 708 | if (!strcmp(kind, "Type 1")) return TYPE1; |
196 | 238 | if (!strcmp(kind, "CFF")) return TYPE1; |
197 | 0 | if (!strcmp(kind, "CID Type 1")) return TYPE1; |
198 | 0 | return UNKNOWN; |
199 | 0 | } |
200 | | |
201 | | /* We abuse the ctx param here; NULL means we are locked already! */ |
202 | | static int ft_cid_to_gid(fz_context *ctx, pdf_font_desc *fontdesc, int cid) |
203 | 1.71M | { |
204 | 1.71M | if (fontdesc->to_ttf_cmap) |
205 | 108k | { |
206 | 108k | cid = pdf_lookup_cmap(fontdesc->to_ttf_cmap, cid); |
207 | | |
208 | | /* vertical presentation forms */ |
209 | 108k | if (fontdesc->font->flags.ft_substitute && fontdesc->wmode) |
210 | 0 | { |
211 | 0 | switch (cid) |
212 | 0 | { |
213 | 0 | case 0x0021: cid = 0xFE15; break; /* ! */ |
214 | 0 | case 0x0028: cid = 0xFE35; break; /* ( */ |
215 | 0 | case 0x0029: cid = 0xFE36; break; /* ) */ |
216 | 0 | case 0x002C: cid = 0xFE10; break; /* , */ |
217 | 0 | case 0x003A: cid = 0xFE13; break; /* : */ |
218 | 0 | case 0x003B: cid = 0xFE14; break; /* ; */ |
219 | 0 | case 0x003F: cid = 0xFE16; break; /* ? */ |
220 | 0 | case 0x005B: cid = 0xFE47; break; /* [ */ |
221 | 0 | case 0x005D: cid = 0xFE48; break; /* ] */ |
222 | 0 | case 0x005F: cid = 0xFE33; break; /* _ */ |
223 | 0 | case 0x007B: cid = 0xFE37; break; /* { */ |
224 | 0 | case 0x007D: cid = 0xFE38; break; /* } */ |
225 | 0 | case 0x2013: cid = 0xFE32; break; /* EN DASH */ |
226 | 0 | case 0x2014: cid = 0xFE31; break; /* EM DASH */ |
227 | 0 | case 0x2025: cid = 0xFE30; break; /* TWO DOT LEADER */ |
228 | 0 | case 0x2026: cid = 0xFE19; break; /* HORIZONTAL ELLIPSIS */ |
229 | 0 | case 0x3001: cid = 0xFE11; break; /* IDEOGRAPHIC COMMA */ |
230 | 0 | case 0x3002: cid = 0xFE12; break; /* IDEOGRAPHIC FULL STOP */ |
231 | 0 | case 0x3008: cid = 0xFE3F; break; /* OPENING ANGLE BRACKET */ |
232 | 0 | case 0x3009: cid = 0xFE40; break; /* CLOSING ANGLE BRACKET */ |
233 | 0 | case 0x300A: cid = 0xFE3D; break; /* LEFT DOUBLE ANGLE BRACKET */ |
234 | 0 | case 0x300B: cid = 0xFE3E; break; /* RIGHT DOUBLE ANGLE BRACKET */ |
235 | 0 | case 0x300C: cid = 0xFE41; break; /* LEFT CORNER BRACKET */ |
236 | 0 | case 0x300D: cid = 0xFE42; break; /* RIGHT CORNER BRACKET */ |
237 | 0 | case 0x300E: cid = 0xFE43; break; /* LEFT WHITE CORNER BRACKET */ |
238 | 0 | case 0x300F: cid = 0xFE44; break; /* RIGHT WHITE CORNER BRACKET */ |
239 | 0 | case 0x3010: cid = 0xFE3B; break; /* LEFT BLACK LENTICULAR BRACKET */ |
240 | 0 | case 0x3011: cid = 0xFE3C; break; /* RIGHT BLACK LENTICULAR BRACKET */ |
241 | 0 | case 0x3014: cid = 0xFE39; break; /* LEFT TORTOISE SHELL BRACKET */ |
242 | 0 | case 0x3015: cid = 0xFE3A; break; /* RIGHT TORTOISE SHELL BRACKET */ |
243 | 0 | case 0x3016: cid = 0xFE17; break; /* LEFT WHITE LENTICULAR BRACKET */ |
244 | 0 | case 0x3017: cid = 0xFE18; break; /* RIGHT WHITE LENTICULAR BRACKET */ |
245 | | |
246 | 0 | case 0xFF01: cid = 0xFE15; break; /* FULLWIDTH EXCLAMATION MARK */ |
247 | 0 | case 0xFF08: cid = 0xFE35; break; /* FULLWIDTH LEFT PARENTHESIS */ |
248 | 0 | case 0xFF09: cid = 0xFE36; break; /* FULLWIDTH RIGHT PARENTHESIS */ |
249 | 0 | case 0xFF0C: cid = 0xFE10; break; /* FULLWIDTH COMMA */ |
250 | 0 | case 0xFF1A: cid = 0xFE13; break; /* FULLWIDTH COLON */ |
251 | 0 | case 0xFF1B: cid = 0xFE14; break; /* FULLWIDTH SEMICOLON */ |
252 | 0 | case 0xFF1F: cid = 0xFE16; break; /* FULLWIDTH QUESTION MARK */ |
253 | 0 | case 0xFF3B: cid = 0xFE47; break; /* FULLWIDTH LEFT SQUARE BRACKET */ |
254 | 0 | case 0xFF3D: cid = 0xFE48; break; /* FULLWIDTH RIGHT SQUARE BRACKET */ |
255 | 0 | case 0xFF3F: cid = 0xFE33; break; /* FULLWIDTH LOW LINE */ |
256 | 0 | case 0xFF5B: cid = 0xFE37; break; /* FULLWIDTH LEFT CURLY BRACKET */ |
257 | 0 | case 0xFF5D: cid = 0xFE38; break; /* FULLWIDTH RIGHT CURLY BRACKET */ |
258 | | |
259 | 0 | case 0x30FC: cid = 0xFE31; break; /* KATAKANA-HIRAGANA PROLONGED SOUND MARK */ |
260 | 0 | case 0xFF0D: cid = 0xFE31; break; /* FULLWIDTH HYPHEN-MINUS */ |
261 | 0 | } |
262 | 0 | } |
263 | | |
264 | 108k | if (ctx) |
265 | 108k | fz_ft_lock(ctx); |
266 | 108k | cid = ft_char_index(fontdesc->font->ft_face, cid); |
267 | 108k | if (ctx) |
268 | 108k | fz_ft_unlock(ctx); |
269 | 108k | return cid; |
270 | 108k | } |
271 | | |
272 | 1.61M | if (fontdesc->cid_to_gid && (size_t)cid < fontdesc->cid_to_gid_len && cid >= 0) |
273 | 1.38M | return fontdesc->cid_to_gid[cid]; |
274 | | |
275 | 224k | return cid; |
276 | 1.61M | } |
277 | | |
278 | | int |
279 | | pdf_font_cid_to_gid(fz_context *ctx, pdf_font_desc *fontdesc, int cid) |
280 | 1.70M | { |
281 | 1.70M | if (fontdesc->font->ft_face) |
282 | 1.70M | return ft_cid_to_gid(ctx, fontdesc, cid); |
283 | 0 | return cid; |
284 | 1.70M | } |
285 | | |
286 | | static int ft_width(fz_context *ctx, pdf_font_desc *fontdesc, int cid) |
287 | 9.21k | { |
288 | 9.21k | int mask = FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM; |
289 | 9.21k | int gid = ft_cid_to_gid(NULL, fontdesc, cid); |
290 | 9.21k | FT_Fixed adv = 0; |
291 | 9.21k | int fterr; |
292 | 9.21k | FT_Face face = fontdesc->font->ft_face; |
293 | 9.21k | FT_UShort units_per_EM; |
294 | | |
295 | 9.21k | fterr = FT_Get_Advance(face, gid, mask, &adv); |
296 | 9.21k | if (fterr && fterr != FT_Err_Invalid_Argument) |
297 | 0 | fz_warn(ctx, "FT_Get_Advance(%d): %s", gid, ft_error_string(fterr)); |
298 | | |
299 | 9.21k | units_per_EM = face->units_per_EM; |
300 | 9.21k | if (units_per_EM == 0) |
301 | 0 | units_per_EM = 2048; |
302 | | |
303 | 9.21k | return adv * 1000 / units_per_EM; |
304 | 9.21k | } |
305 | | |
306 | | static const struct { int code; const char *name; } mre_diff_table[] = |
307 | | { |
308 | | { 173, "notequal" }, |
309 | | { 176, "infinity" }, |
310 | | { 178, "lessequal" }, |
311 | | { 179, "greaterequal" }, |
312 | | { 182, "partialdiff" }, |
313 | | { 183, "summation" }, |
314 | | { 184, "product" }, |
315 | | { 185, "pi" }, |
316 | | { 186, "integral" }, |
317 | | { 189, "Omega" }, |
318 | | { 195, "radical" }, |
319 | | { 197, "approxequal" }, |
320 | | { 198, "Delta" }, |
321 | | { 215, "lozenge" }, |
322 | | { 219, "Euro" }, |
323 | | { 240, "apple" }, |
324 | | }; |
325 | | |
326 | | static int lookup_mre_code(const char *name) |
327 | 4.99k | { |
328 | 4.99k | int i; |
329 | 84.8k | for (i = 0; i < (int)nelem(mre_diff_table); ++i) |
330 | 79.8k | if (!strcmp(name, mre_diff_table[i].name)) |
331 | 0 | return mre_diff_table[i].code; |
332 | 700k | for (i = 0; i < 256; i++) |
333 | 700k | if (fz_glyph_name_from_mac_roman[i] && !strcmp(name, fz_glyph_name_from_mac_roman[i])) |
334 | 4.99k | return i; |
335 | 0 | return -1; |
336 | 4.99k | } |
337 | | |
338 | | static int ft_find_glyph_by_unicode_name(FT_Face face, const char *name) |
339 | 2.45k | { |
340 | 2.45k | int unicode, glyph; |
341 | | |
342 | | /* Prefer exact unicode match if available. */ |
343 | 2.45k | unicode = fz_unicode_from_glyph_name_strict(name); |
344 | 2.45k | if (unicode > 0) |
345 | 2.01k | { |
346 | 2.01k | glyph = ft_char_index(face, unicode); |
347 | 2.01k | if (glyph > 0) |
348 | 2.01k | return glyph; |
349 | 2.01k | } |
350 | | |
351 | | /* Fall back to font glyph name if we can. */ |
352 | 440 | glyph = ft_name_index(face, name); |
353 | 440 | if (glyph > 0) |
354 | 0 | return glyph; |
355 | | |
356 | | /* Fuzzy unicode match as last attempt. */ |
357 | 440 | unicode = fz_unicode_from_glyph_name(name); |
358 | 440 | if (unicode > 0) |
359 | 440 | return ft_char_index(face, unicode); |
360 | | |
361 | | /* Failed. */ |
362 | 0 | return 0; |
363 | 440 | } |
364 | | |
365 | | static void |
366 | | pdf_make_font_family(fz_context *ctx, fz_font *font) |
367 | 600 | { |
368 | 600 | if (font->flags.ft_substitute || font->t3procs) |
369 | 72 | { |
370 | | /* Remove "ABCDEF+" prefix and "-Bold" suffix. */ |
371 | 72 | char *p; |
372 | 72 | fz_strlcpy(font->family, skip_subset_prefix(font->name), sizeof font->family); |
373 | 72 | p = strrchr(font->family, '-'); |
374 | 72 | if (p) |
375 | 20 | *p = 0; |
376 | 72 | } |
377 | 600 | } |
378 | | |
379 | | /* |
380 | | * Load font files. |
381 | | */ |
382 | | |
383 | | static void |
384 | | pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, const char *fontname, int has_descriptor) |
385 | 68 | { |
386 | 68 | FT_Face face; |
387 | 68 | const char *clean_name = pdf_clean_font_name(fontname); |
388 | 68 | if (clean_name == fontname) |
389 | 10 | clean_name = "Times-Roman"; |
390 | | |
391 | 68 | fontdesc->font = fz_load_system_font(ctx, fontname, 0, 0, !has_descriptor); |
392 | 68 | if (!fontdesc->font) |
393 | 68 | { |
394 | 68 | const unsigned char *data; |
395 | 68 | int len; |
396 | | |
397 | 68 | data = fz_lookup_base14_font(ctx, clean_name, &len); |
398 | 68 | if (!data) |
399 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot find builtin font: '%s'", fontname); |
400 | | |
401 | 68 | fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1); |
402 | 68 | fontdesc->font->flags.is_serif = !!strstr(clean_name, "Times"); |
403 | 68 | } |
404 | | |
405 | 68 | if (!strcmp(clean_name, "Symbol") || !strcmp(clean_name, "ZapfDingbats")) |
406 | 4 | fontdesc->flags |= PDF_FD_SYMBOLIC; |
407 | | |
408 | 68 | face = fontdesc->font->ft_face; |
409 | 68 | fontdesc->ascent = 1000.0f * face->ascender / face->units_per_EM; |
410 | 68 | fontdesc->descent = 1000.0f * face->descender / face->units_per_EM; |
411 | 68 | } |
412 | | |
413 | | static void |
414 | | pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, const char *fontname, int mono, int serif, int bold, int italic) |
415 | 72 | { |
416 | 72 | fontdesc->font = fz_load_system_font(ctx, fontname, bold, italic, 0); |
417 | 72 | if (!fontdesc->font) |
418 | 72 | { |
419 | 72 | const unsigned char *data; |
420 | 72 | int len; |
421 | | |
422 | 72 | data = pdf_lookup_substitute_font(ctx, mono, serif, bold, italic, &len); |
423 | 72 | if (!data) |
424 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot find substitute font"); |
425 | | |
426 | 72 | fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1); |
427 | 72 | fontdesc->font->flags.fake_bold = bold && !fontdesc->font->flags.is_bold; |
428 | 72 | fontdesc->font->flags.fake_italic = italic && !fontdesc->font->flags.is_italic; |
429 | | |
430 | 72 | fontdesc->font->flags.is_mono = mono; |
431 | 72 | fontdesc->font->flags.is_serif = serif; |
432 | 72 | fontdesc->font->flags.is_bold = bold; |
433 | 72 | fontdesc->font->flags.is_italic = italic; |
434 | 72 | } |
435 | | |
436 | 72 | fontdesc->font->flags.ft_substitute = 1; |
437 | 72 | fontdesc->font->flags.ft_stretch = 1; |
438 | 72 | } |
439 | | |
440 | | static void |
441 | | pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, const char *fontname, int ros, int serif) |
442 | 0 | { |
443 | 0 | fontdesc->font = fz_load_system_cjk_font(ctx, fontname, ros, serif); |
444 | 0 | if (!fontdesc->font) |
445 | 0 | { |
446 | 0 | const unsigned char *data; |
447 | 0 | int size; |
448 | 0 | int subfont; |
449 | |
|
450 | 0 | data = fz_lookup_cjk_font(ctx, ros, &size, &subfont); |
451 | 0 | if (!data) |
452 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "cannot find builtin CJK font"); |
453 | | |
454 | | /* A glyph bbox cache is too big for CJK fonts. */ |
455 | 0 | fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, size, subfont, 0); |
456 | 0 | } |
457 | | |
458 | 0 | fontdesc->font->flags.ft_substitute = 1; |
459 | 0 | fontdesc->font->flags.ft_stretch = 0; |
460 | 0 | fontdesc->font->flags.cjk = 1; |
461 | 0 | fontdesc->font->flags.cjk_lang = ros; |
462 | 0 | } |
463 | | |
464 | | static struct { int ros, serif; const char *name; } known_cjk_fonts[] = { |
465 | | { FZ_ADOBE_GB, 1, "SimFang" }, |
466 | | { FZ_ADOBE_GB, 0, "SimHei" }, |
467 | | { FZ_ADOBE_GB, 1, "SimKai" }, |
468 | | { FZ_ADOBE_GB, 1, "SimLi" }, |
469 | | { FZ_ADOBE_GB, 1, "SimSun" }, |
470 | | { FZ_ADOBE_GB, 1, "Song" }, |
471 | | |
472 | | { FZ_ADOBE_CNS, 1, "MingLiU" }, |
473 | | |
474 | | { FZ_ADOBE_JAPAN, 0, "Gothic" }, |
475 | | { FZ_ADOBE_JAPAN, 1, "Mincho" }, |
476 | | |
477 | | { FZ_ADOBE_KOREA, 1, "Batang" }, |
478 | | { FZ_ADOBE_KOREA, 0, "Gulim" }, |
479 | | { FZ_ADOBE_KOREA, 0, "Dotum" }, |
480 | | }; |
481 | | |
482 | | static int match_font_name(const char *s, const char *ref) |
483 | 180 | { |
484 | 180 | return !!strstr(s, ref); |
485 | 180 | } |
486 | | |
487 | | static void |
488 | | pdf_load_system_font(fz_context *ctx, pdf_font_desc *fontdesc, const char *fontname, const char *collection) |
489 | 72 | { |
490 | 72 | int bold = 0; |
491 | 72 | int italic = 0; |
492 | 72 | int serif = 0; |
493 | 72 | int mono = 0; |
494 | | |
495 | 72 | if (strstr(fontname, "Bold")) |
496 | 7 | bold = 1; |
497 | 72 | if (strstr(fontname, "Italic")) |
498 | 8 | italic = 1; |
499 | 72 | if (strstr(fontname, "Oblique")) |
500 | 0 | italic = 1; |
501 | | |
502 | 72 | if (fontdesc->flags & PDF_FD_FIXED_PITCH) |
503 | 0 | mono = 1; |
504 | 72 | if (fontdesc->flags & PDF_FD_SERIF) |
505 | 18 | serif = 1; |
506 | 72 | if (fontdesc->flags & PDF_FD_ITALIC) |
507 | 8 | italic = 1; |
508 | 72 | if (fontdesc->flags & PDF_FD_FORCE_BOLD) |
509 | 1 | bold = 1; |
510 | | |
511 | 72 | if (collection) |
512 | 15 | { |
513 | 15 | if (!strcmp(collection, "Adobe-CNS1")) |
514 | 0 | pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_CNS, serif); |
515 | 15 | else if (!strcmp(collection, "Adobe-GB1")) |
516 | 0 | pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_GB, serif); |
517 | 15 | else if (!strcmp(collection, "Adobe-Japan1")) |
518 | 0 | pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_JAPAN, serif); |
519 | 15 | else if (!strcmp(collection, "Adobe-Korea1")) |
520 | 0 | pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_KOREA, serif); |
521 | 15 | else |
522 | 15 | { |
523 | 15 | size_t i; |
524 | 15 | if (strcmp(collection, "Adobe-Identity") != 0) |
525 | 1 | fz_warn(ctx, "unknown cid collection: %s", collection); |
526 | | |
527 | | // Recognize common CJK fonts when using Identity or other non-CJK CMap |
528 | 195 | for (i = 0; i < nelem(known_cjk_fonts); ++i) |
529 | 180 | { |
530 | 180 | if (match_font_name(fontname, known_cjk_fonts[i].name)) |
531 | 0 | { |
532 | 0 | pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, |
533 | 0 | known_cjk_fonts[i].ros, known_cjk_fonts[i].serif); |
534 | 0 | return; |
535 | 0 | } |
536 | 180 | } |
537 | | |
538 | 15 | pdf_load_substitute_font(ctx, fontdesc, fontname, mono, serif, bold, italic); |
539 | 15 | } |
540 | 15 | } |
541 | 57 | else |
542 | 57 | { |
543 | 57 | pdf_load_substitute_font(ctx, fontdesc, fontname, mono, serif, bold, italic); |
544 | 57 | } |
545 | 72 | } |
546 | | |
547 | 0 | #define TTF_U16(p) fz_unpack_uint16(p) |
548 | 0 | #define TTF_U32(p) fz_unpack_uint32(p) |
549 | | |
550 | | static fz_buffer * |
551 | | pdf_extract_cff_subtable(fz_context *ctx, unsigned char *data, size_t size) |
552 | 0 | { |
553 | 0 | size_t num_tables = TTF_U16(data + 4); |
554 | 0 | size_t i; |
555 | |
|
556 | 0 | if (12 + num_tables * 16 > size) |
557 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "invalid TTF header"); |
558 | | |
559 | 0 | for (i = 0; i < num_tables; ++i) |
560 | 0 | { |
561 | 0 | unsigned char *record = data + 12 + i * 16; |
562 | 0 | if (!memcmp("CFF ", record, 4)) |
563 | 0 | { |
564 | 0 | uint64_t offset = TTF_U32(record + 8); |
565 | 0 | uint64_t length = TTF_U32(record + 12); |
566 | 0 | uint64_t end = offset + length; |
567 | 0 | if (end > size) |
568 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "invalid TTF subtable offset/length"); |
569 | 0 | return fz_new_buffer_from_copied_data(ctx, data + offset, length); |
570 | 0 | } |
571 | 0 | } |
572 | | |
573 | 0 | return NULL; |
574 | 0 | } |
575 | | |
576 | | static void |
577 | | pdf_load_embedded_font(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, const char *fontname, pdf_obj *stmref) |
578 | 506 | { |
579 | 506 | fz_buffer *buf; |
580 | 506 | unsigned char *data; |
581 | 506 | size_t size; |
582 | | |
583 | 506 | fz_var(buf); |
584 | | |
585 | 506 | buf = pdf_load_stream(ctx, stmref); |
586 | | |
587 | 996 | fz_try(ctx) |
588 | 996 | { |
589 | | /* Extract CFF subtable for OpenType fonts: */ |
590 | 498 | size = fz_buffer_storage(ctx, buf, &data); |
591 | 498 | if (size > 12) { |
592 | 497 | if (!memcmp("OTTO", data, 4)) { |
593 | 0 | fz_buffer *cff = pdf_extract_cff_subtable(ctx, data, size); |
594 | 0 | if (cff) |
595 | 0 | { |
596 | 0 | fz_drop_buffer(ctx, buf); |
597 | 0 | buf = cff; |
598 | 0 | } |
599 | 0 | } |
600 | 497 | } |
601 | | |
602 | 498 | fontdesc->font = fz_new_font_from_buffer(ctx, fontname, buf, 0, 1); |
603 | 498 | } |
604 | 996 | fz_always(ctx) |
605 | 498 | fz_drop_buffer(ctx, buf); |
606 | 498 | fz_catch(ctx) |
607 | 31 | fz_rethrow(ctx); |
608 | | |
609 | 475 | fontdesc->size += fz_buffer_storage(ctx, buf, NULL); |
610 | 475 | fontdesc->is_embedded = 1; |
611 | 475 | } |
612 | | |
613 | | /* |
614 | | * Create and destroy |
615 | | */ |
616 | | |
617 | | pdf_font_desc * |
618 | | pdf_keep_font(fz_context *ctx, pdf_font_desc *fontdesc) |
619 | 29.9k | { |
620 | 29.9k | if (fontdesc) |
621 | 28.9k | return fz_keep_storable(ctx, &fontdesc->storable); |
622 | 991 | return NULL; |
623 | 29.9k | } |
624 | | |
625 | | void |
626 | | pdf_drop_font(fz_context *ctx, pdf_font_desc *fontdesc) |
627 | 206k | { |
628 | 206k | if (fontdesc) |
629 | 48.8k | fz_drop_storable(ctx, &fontdesc->storable); |
630 | 206k | } |
631 | | |
632 | | static int |
633 | | pdf_font_is_droppable(fz_context *ctx, fz_storable *fontdesc) |
634 | 0 | { |
635 | | /* If we aren't holding the FT lock, then we can drop. */ |
636 | 0 | return !fz_ft_lock_held(ctx); |
637 | 0 | } |
638 | | |
639 | | static void |
640 | | pdf_drop_font_imp(fz_context *ctx, fz_storable *fontdesc_) |
641 | 607 | { |
642 | 607 | pdf_font_desc *fontdesc = (pdf_font_desc *)fontdesc_; |
643 | | |
644 | 607 | fz_drop_font(ctx, fontdesc->font); |
645 | 607 | pdf_drop_cmap(ctx, fontdesc->encoding); |
646 | 607 | pdf_drop_cmap(ctx, fontdesc->to_ttf_cmap); |
647 | 607 | pdf_drop_cmap(ctx, fontdesc->to_unicode); |
648 | 607 | fz_free(ctx, fontdesc->cid_to_gid); |
649 | 607 | fz_free(ctx, fontdesc->cid_to_ucs); |
650 | 607 | fz_free(ctx, fontdesc->hmtx); |
651 | 607 | fz_free(ctx, fontdesc->vmtx); |
652 | 607 | fz_free(ctx, fontdesc); |
653 | 607 | } |
654 | | |
655 | | pdf_font_desc * |
656 | | pdf_new_font_desc(fz_context *ctx) |
657 | 607 | { |
658 | 607 | pdf_font_desc *fontdesc; |
659 | | |
660 | 607 | fontdesc = fz_malloc_struct(ctx, pdf_font_desc); |
661 | 607 | FZ_INIT_AWKWARD_STORABLE(fontdesc, 1, pdf_drop_font_imp, pdf_font_is_droppable); |
662 | 607 | fontdesc->size = sizeof(pdf_font_desc); |
663 | | |
664 | 607 | fontdesc->font = NULL; |
665 | | |
666 | 607 | fontdesc->flags = 0; |
667 | 607 | fontdesc->italic_angle = 0; |
668 | 607 | fontdesc->ascent = 800; |
669 | 607 | fontdesc->descent = -200; |
670 | 607 | fontdesc->cap_height = 800; |
671 | 607 | fontdesc->x_height = 500; |
672 | 607 | fontdesc->missing_width = 0; |
673 | | |
674 | 607 | fontdesc->encoding = NULL; |
675 | 607 | fontdesc->to_ttf_cmap = NULL; |
676 | 607 | fontdesc->cid_to_gid_len = 0; |
677 | 607 | fontdesc->cid_to_gid = NULL; |
678 | | |
679 | 607 | fontdesc->to_unicode = NULL; |
680 | 607 | fontdesc->cid_to_ucs_len = 0; |
681 | 607 | fontdesc->cid_to_ucs = NULL; |
682 | | |
683 | 607 | fontdesc->wmode = 0; |
684 | | |
685 | 607 | fontdesc->hmtx_cap = 0; |
686 | 607 | fontdesc->vmtx_cap = 0; |
687 | 607 | fontdesc->hmtx_len = 0; |
688 | 607 | fontdesc->vmtx_len = 0; |
689 | 607 | fontdesc->hmtx = NULL; |
690 | 607 | fontdesc->vmtx = NULL; |
691 | | |
692 | 607 | fontdesc->dhmtx.lo = 0x0000; |
693 | 607 | fontdesc->dhmtx.hi = 0xFFFF; |
694 | 607 | fontdesc->dhmtx.w = 1000; |
695 | | |
696 | 607 | fontdesc->dvmtx.lo = 0x0000; |
697 | 607 | fontdesc->dvmtx.hi = 0xFFFF; |
698 | 607 | fontdesc->dvmtx.x = 0; |
699 | 607 | fontdesc->dvmtx.y = 880; |
700 | 607 | fontdesc->dvmtx.w = -1000; |
701 | | |
702 | 607 | fontdesc->is_embedded = 0; |
703 | | |
704 | 607 | return fontdesc; |
705 | 607 | } |
706 | | |
707 | | /* |
708 | | * Simple fonts (Type1 and TrueType) |
709 | | */ |
710 | | |
711 | | static FT_CharMap |
712 | | select_type1_cmap(FT_Face face) |
713 | 364 | { |
714 | 364 | int i; |
715 | 712 | for (i = 0; i < face->num_charmaps; i++) |
716 | 712 | if (face->charmaps[i]->platform_id == 7) |
717 | 364 | return face->charmaps[i]; |
718 | 0 | if (face->num_charmaps > 0) |
719 | 0 | return face->charmaps[0]; |
720 | 0 | return NULL; |
721 | 0 | } |
722 | | |
723 | | static FT_CharMap |
724 | | select_truetype_cmap(fz_context *ctx, FT_Face face, int symbolic) |
725 | 164 | { |
726 | 164 | int i; |
727 | | |
728 | | /* First look for a Microsoft symbolic cmap, if applicable */ |
729 | 164 | if (symbolic) |
730 | 129 | { |
731 | 262 | for (i = 0; i < face->num_charmaps; i++) |
732 | 140 | if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 0) |
733 | 7 | return face->charmaps[i]; |
734 | 129 | } |
735 | | |
736 | 157 | fz_ft_lock(ctx); |
737 | | |
738 | | /* Then look for a Microsoft Unicode cmap */ |
739 | 351 | for (i = 0; i < face->num_charmaps; i++) |
740 | 207 | if (face->charmaps[i]->platform_id == 3 && face->charmaps[i]->encoding_id == 1) |
741 | 37 | if (FT_Get_CMap_Format(face->charmaps[i]) != -1) |
742 | 13 | { |
743 | 13 | fz_ft_unlock(ctx); |
744 | 13 | return face->charmaps[i]; |
745 | 13 | } |
746 | | |
747 | | /* Finally look for an Apple MacRoman cmap */ |
748 | 144 | for (i = 0; i < face->num_charmaps; i++) |
749 | 144 | if (face->charmaps[i]->platform_id == 1 && face->charmaps[i]->encoding_id == 0) |
750 | 144 | if (FT_Get_CMap_Format(face->charmaps[i]) != -1) |
751 | 144 | { |
752 | 144 | fz_ft_unlock(ctx); |
753 | 144 | return face->charmaps[i]; |
754 | 144 | } |
755 | | |
756 | 0 | if (face->num_charmaps > 0) |
757 | 0 | if (FT_Get_CMap_Format(face->charmaps[0]) != -1) |
758 | 0 | { |
759 | 0 | fz_ft_unlock(ctx); |
760 | 0 | return face->charmaps[0]; |
761 | 0 | } |
762 | | |
763 | 0 | fz_ft_unlock(ctx); |
764 | 0 | return NULL; |
765 | 0 | } |
766 | | |
767 | | static FT_CharMap |
768 | | select_unknown_cmap(FT_Face face) |
769 | 0 | { |
770 | 0 | if (face->num_charmaps > 0) |
771 | 0 | return face->charmaps[0]; |
772 | 0 | return NULL; |
773 | 0 | } |
774 | | |
775 | | static int use_s22pdf_workaround(fz_context *ctx, pdf_obj *dict, pdf_obj *descriptor) |
776 | 528 | { |
777 | 528 | if (descriptor) |
778 | 493 | { |
779 | 493 | if (pdf_dict_get(ctx, dict, PDF_NAME(Encoding)) != PDF_NAME(WinAnsiEncoding)) |
780 | 451 | return 0; |
781 | 42 | if (pdf_dict_get_int(ctx, descriptor, PDF_NAME(Flags)) != 4) |
782 | 42 | return 0; |
783 | 0 | return 1; |
784 | 42 | } |
785 | 35 | return 0; |
786 | 528 | } |
787 | | |
788 | | static pdf_font_desc * |
789 | | pdf_load_simple_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict, pdf_obj *fftype) |
790 | 528 | { |
791 | 528 | const char *basefont; |
792 | 528 | pdf_obj *descriptor; |
793 | 528 | pdf_obj *encoding; |
794 | 528 | pdf_obj *widths; |
795 | 528 | unsigned short *etable = NULL; |
796 | 528 | pdf_font_desc *fontdesc = NULL; |
797 | 528 | pdf_obj *subtype; |
798 | 528 | FT_Face face; |
799 | 528 | FT_CharMap cmap; |
800 | 528 | int symbolic; |
801 | 528 | int kind; |
802 | 528 | int glyph; |
803 | | |
804 | 528 | const char *estrings[256]; |
805 | 528 | char ebuffer[256][32]; |
806 | 528 | int i, k, n; |
807 | 528 | int fterr; |
808 | 528 | int has_lock = 0; |
809 | | |
810 | 528 | fz_var(fontdesc); |
811 | 528 | fz_var(etable); |
812 | 528 | fz_var(has_lock); |
813 | | |
814 | | /* Load font file */ |
815 | 1.05k | fz_try(ctx) |
816 | 1.05k | { |
817 | 528 | fontdesc = pdf_new_font_desc(ctx); |
818 | | |
819 | 528 | basefont = pdf_dict_get_name(ctx, dict, PDF_NAME(BaseFont)); |
820 | | |
821 | 528 | descriptor = pdf_dict_get(ctx, dict, PDF_NAME(FontDescriptor)); |
822 | 528 | if (descriptor) |
823 | 493 | pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, NULL, basefont, 0, fftype); |
824 | 35 | else |
825 | 35 | pdf_load_builtin_font(ctx, fontdesc, basefont, 0); |
826 | | |
827 | | /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ |
828 | 528 | if (use_s22pdf_workaround(ctx, dict, descriptor)) |
829 | 0 | { |
830 | 0 | char *cp936fonts[] = { |
831 | 0 | "\xCB\xCE\xCC\xE5", "SimSun,Regular", |
832 | 0 | "\xBA\xDA\xCC\xE5", "SimHei,Regular", |
833 | 0 | "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", |
834 | 0 | "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", |
835 | 0 | "\xC1\xA5\xCA\xE9", "SimLi,Regular", |
836 | 0 | NULL |
837 | 0 | }; |
838 | 0 | for (i = 0; cp936fonts[i]; i += 2) |
839 | 0 | if (!strcmp(basefont, cp936fonts[i])) |
840 | 0 | break; |
841 | 0 | if (cp936fonts[i]) |
842 | 0 | { |
843 | 0 | fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings"); |
844 | 0 | pdf_drop_font(ctx, fontdesc); |
845 | 0 | fontdesc = NULL; |
846 | 0 | fontdesc = pdf_new_font_desc(ctx); |
847 | 0 | pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, "Adobe-GB1", cp936fonts[i+1], 0, fftype); |
848 | 0 | fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H"); |
849 | 0 | fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); |
850 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); |
851 | |
|
852 | 0 | goto skip_encoding; |
853 | 0 | } |
854 | 0 | } |
855 | | |
856 | 528 | face = fontdesc->font->ft_face; |
857 | 528 | kind = ft_kind(ctx, face); |
858 | | |
859 | | /* Encoding */ |
860 | | |
861 | 528 | symbolic = fontdesc->flags & 4; |
862 | | /* Bug 703273: If non-symbolic, we're not symbolic. */ |
863 | 528 | if (fontdesc->flags & 32) |
864 | 94 | symbolic = 0; |
865 | | |
866 | 528 | if (kind == TYPE1) |
867 | 364 | cmap = select_type1_cmap(face); |
868 | 164 | else if (kind == TRUETYPE) |
869 | 164 | cmap = select_truetype_cmap(ctx, face, symbolic); |
870 | 0 | else |
871 | 0 | cmap = select_unknown_cmap(face); |
872 | | |
873 | 528 | if (cmap) |
874 | 528 | { |
875 | 528 | fz_ft_lock(ctx); |
876 | 528 | fterr = FT_Set_Charmap(face, cmap); |
877 | 528 | fz_ft_unlock(ctx); |
878 | 528 | if (fterr) |
879 | 0 | fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr)); |
880 | 528 | } |
881 | 0 | else |
882 | 0 | fz_warn(ctx, "freetype could not find any cmaps"); |
883 | | |
884 | | /* FIXME: etable may leak on error. */ |
885 | 528 | etable = Memento_label(fz_malloc_array(ctx, 256, unsigned short), "cid_to_gid"); |
886 | 528 | fontdesc->size += 256 * sizeof(unsigned short); |
887 | 135k | for (i = 0; i < 256; i++) |
888 | 135k | { |
889 | 135k | estrings[i] = NULL; |
890 | 135k | etable[i] = 0; |
891 | 135k | } |
892 | | |
893 | 528 | encoding = pdf_dict_get(ctx, dict, PDF_NAME(Encoding)); |
894 | 528 | if (encoding) |
895 | 377 | { |
896 | 377 | if (pdf_is_name(ctx, encoding)) |
897 | 69 | pdf_load_encoding(estrings, pdf_to_name(ctx, encoding)); |
898 | | |
899 | 377 | if (pdf_is_dict(ctx, encoding)) |
900 | 305 | { |
901 | 305 | pdf_obj *base, *diff, *item; |
902 | | |
903 | 305 | base = pdf_dict_get(ctx, encoding, PDF_NAME(BaseEncoding)); |
904 | 305 | if (pdf_is_name(ctx, base)) |
905 | 11 | pdf_load_encoding(estrings, pdf_to_name(ctx, base)); |
906 | 294 | else if (!fontdesc->is_embedded && !symbolic) |
907 | 30 | pdf_load_encoding(estrings, "StandardEncoding"); |
908 | | |
909 | 305 | diff = pdf_dict_get(ctx, encoding, PDF_NAME(Differences)); |
910 | 305 | if (pdf_is_array(ctx, diff)) |
911 | 305 | { |
912 | 305 | n = pdf_array_len(ctx, diff); |
913 | 305 | k = 0; |
914 | 33.6k | for (i = 0; i < n; i++) |
915 | 33.3k | { |
916 | 33.3k | item = pdf_array_get(ctx, diff, i); |
917 | 33.3k | if (pdf_is_int(ctx, item)) |
918 | 3.22k | k = pdf_to_int(ctx, item); |
919 | 33.3k | if (pdf_is_name(ctx, item) && k >= 0 && k < (int)nelem(estrings)) |
920 | 30.1k | estrings[k++] = pdf_to_name(ctx, item); |
921 | 33.3k | } |
922 | 305 | } |
923 | 305 | } |
924 | 377 | } |
925 | 151 | else if (!fontdesc->is_embedded && !symbolic) |
926 | 18 | pdf_load_encoding(estrings, "StandardEncoding"); |
927 | | |
928 | 528 | fz_ft_lock(ctx); |
929 | 528 | has_lock = 1; |
930 | | |
931 | | /* start with the builtin encoding */ |
932 | 135k | for (i = 0; i < 256; i++) |
933 | 135k | etable[i] = ft_char_index(face, i); |
934 | | |
935 | | /* built-in and substitute fonts may be a different type than what the document expects */ |
936 | 528 | subtype = pdf_dict_get(ctx, dict, PDF_NAME(Subtype)); |
937 | 528 | if (pdf_name_eq(ctx, subtype, PDF_NAME(Type1))) |
938 | 316 | kind = TYPE1; |
939 | 212 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(MMType1))) |
940 | 0 | kind = TYPE1; |
941 | 212 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(TrueType))) |
942 | 202 | kind = TRUETYPE; |
943 | 10 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(CIDFontType0))) |
944 | 0 | kind = TYPE1; |
945 | 10 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(CIDFontType2))) |
946 | 0 | kind = TRUETYPE; |
947 | | |
948 | | /* encode by glyph name where we can */ |
949 | 528 | if (kind == TYPE1) |
950 | 326 | { |
951 | 83.7k | for (i = 0; i < 256; i++) |
952 | 83.4k | { |
953 | 83.4k | if (estrings[i]) |
954 | 36.0k | { |
955 | 36.0k | glyph = ft_name_index(face, estrings[i]); |
956 | 36.0k | if (glyph > 0) |
957 | 19.4k | etable[i] = glyph; |
958 | 36.0k | } |
959 | 83.4k | } |
960 | 326 | } |
961 | | |
962 | | /* encode by glyph name where we can */ |
963 | 528 | if (kind == TRUETYPE) |
964 | 202 | { |
965 | | /* Unicode cmap */ |
966 | 202 | if (!symbolic && face->charmap && face->charmap->platform_id == 3) |
967 | 11 | { |
968 | 2.82k | for (i = 0; i < 256; i++) |
969 | 2.81k | { |
970 | 2.81k | if (estrings[i]) |
971 | 2.45k | { |
972 | 2.45k | glyph = ft_find_glyph_by_unicode_name(face, estrings[i]); |
973 | 2.45k | if (glyph > 0) |
974 | 2.45k | etable[i] = glyph; |
975 | 2.45k | } |
976 | 2.81k | } |
977 | 11 | } |
978 | | |
979 | | /* MacRoman cmap */ |
980 | 191 | else if (!symbolic && face->charmap && face->charmap->platform_id == 1) |
981 | 24 | { |
982 | 6.16k | for (i = 0; i < 256; i++) |
983 | 6.14k | { |
984 | 6.14k | if (estrings[i]) |
985 | 4.99k | { |
986 | 4.99k | int mrcode = lookup_mre_code(estrings[i]); |
987 | 4.99k | glyph = 0; |
988 | 4.99k | if (mrcode > 0) |
989 | 4.99k | glyph = ft_char_index(face, mrcode); |
990 | 4.99k | if (glyph == 0) |
991 | 4.26k | glyph = ft_name_index(face, estrings[i]); |
992 | 4.99k | if (glyph > 0) |
993 | 732 | etable[i] = glyph; |
994 | 4.99k | } |
995 | 6.14k | } |
996 | 24 | } |
997 | | |
998 | | /* Symbolic cmap */ |
999 | 167 | else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL) |
1000 | 160 | { |
1001 | 41.1k | for (i = 0; i < 256; i++) |
1002 | 40.9k | { |
1003 | 40.9k | if (estrings[i]) |
1004 | 7.02k | { |
1005 | 7.02k | glyph = ft_name_index(face, estrings[i]); |
1006 | 7.02k | if (glyph > 0) |
1007 | 7.02k | etable[i] = glyph; |
1008 | 7.02k | } |
1009 | 40.9k | } |
1010 | 160 | } |
1011 | 202 | } |
1012 | | |
1013 | | /* try to reverse the glyph names from the builtin encoding */ |
1014 | 135k | for (i = 0; i < 256; i++) |
1015 | 135k | { |
1016 | 135k | if (etable[i] && !estrings[i]) |
1017 | 7.85k | { |
1018 | 7.85k | if (FT_HAS_GLYPH_NAMES(face)) |
1019 | 4.33k | { |
1020 | 4.33k | fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); |
1021 | 4.33k | if (fterr) |
1022 | 0 | fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); |
1023 | 4.33k | if (ebuffer[i][0]) |
1024 | 4.33k | estrings[i] = ebuffer[i]; |
1025 | 4.33k | } |
1026 | 3.51k | else |
1027 | 3.51k | { |
1028 | 3.51k | estrings[i] = (char*) fz_glyph_name_from_win_ansi[i]; /* discard const */ |
1029 | 3.51k | } |
1030 | 7.85k | } |
1031 | 135k | } |
1032 | | |
1033 | | /* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */ |
1034 | 528 | if (kind == TYPE1 && symbolic) |
1035 | 267 | { |
1036 | 68.6k | for (i = 0; i < 256; i++) |
1037 | 68.3k | if (etable[i] && estrings[i] && !fz_unicode_from_glyph_name(estrings[i])) |
1038 | 0 | estrings[i] = (char*) fz_glyph_name_from_adobe_standard[i]; |
1039 | 267 | } |
1040 | | |
1041 | 528 | fz_ft_unlock(ctx); |
1042 | 528 | has_lock = 0; |
1043 | | |
1044 | 528 | fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1); |
1045 | 528 | fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); |
1046 | 528 | fontdesc->cid_to_gid_len = 256; |
1047 | 528 | fontdesc->cid_to_gid = etable; |
1048 | | |
1049 | 1.05k | fz_try(ctx) |
1050 | 1.05k | { |
1051 | 528 | pdf_load_to_unicode(ctx, doc, fontdesc, estrings, NULL, pdf_dict_get(ctx, dict, PDF_NAME(ToUnicode))); |
1052 | 528 | } |
1053 | 1.05k | fz_catch(ctx) |
1054 | 0 | { |
1055 | 0 | fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); |
1056 | 0 | fz_rethrow_if(ctx, FZ_ERROR_SYSTEM); |
1057 | 0 | fz_report_error(ctx); |
1058 | 0 | fz_warn(ctx, "cannot load ToUnicode CMap"); |
1059 | 0 | } |
1060 | | |
1061 | 528 | skip_encoding: |
1062 | | |
1063 | | /* Widths */ |
1064 | | |
1065 | 528 | pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width); |
1066 | | |
1067 | 528 | widths = pdf_dict_get(ctx, dict, PDF_NAME(Widths)); |
1068 | 528 | if (widths) |
1069 | 492 | { |
1070 | 492 | int first, last; |
1071 | | |
1072 | 492 | first = pdf_dict_get_int(ctx, dict, PDF_NAME(FirstChar)); |
1073 | 492 | last = pdf_dict_get_int(ctx, dict, PDF_NAME(LastChar)); |
1074 | | |
1075 | 492 | if (first < 0 || last > 255 || first > last) |
1076 | 0 | first = last = 0; |
1077 | | |
1078 | 42.1k | for (i = 0; i < last - first + 1; i++) |
1079 | 41.6k | { |
1080 | 41.6k | int wid = pdf_array_get_int(ctx, widths, i); |
1081 | 41.6k | pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid); |
1082 | 41.6k | } |
1083 | 492 | } |
1084 | 36 | else |
1085 | 36 | { |
1086 | 36 | fz_ft_lock(ctx); |
1087 | 36 | has_lock = 1; |
1088 | 9.25k | for (i = 0; i < 256; i++) |
1089 | 9.21k | pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i)); |
1090 | 36 | fz_ft_unlock(ctx); |
1091 | 36 | has_lock = 0; |
1092 | 36 | } |
1093 | | |
1094 | 528 | pdf_end_hmtx(ctx, fontdesc); |
1095 | 528 | } |
1096 | 1.05k | fz_catch(ctx) |
1097 | 0 | { |
1098 | 0 | if (has_lock) |
1099 | 0 | fz_ft_unlock(ctx); |
1100 | 0 | if (fontdesc && etable != fontdesc->cid_to_gid) |
1101 | 0 | fz_free(ctx, etable); |
1102 | 0 | pdf_drop_font(ctx, fontdesc); |
1103 | 0 | fz_rethrow(ctx); |
1104 | 0 | } |
1105 | 528 | return fontdesc; |
1106 | 528 | } |
1107 | | |
1108 | | static int |
1109 | | hail_mary_make_hash_key(fz_context *ctx, fz_store_hash *hash, void *key_) |
1110 | 1.34k | { |
1111 | 1.34k | hash->u.pi.i = 0; |
1112 | 1.34k | hash->u.pi.ptr = NULL; |
1113 | 1.34k | return 1; |
1114 | 1.34k | } |
1115 | | |
1116 | | static void * |
1117 | | hail_mary_keep_key(fz_context *ctx, void *key) |
1118 | 7 | { |
1119 | 7 | return key; |
1120 | 7 | } |
1121 | | |
1122 | | static void |
1123 | | hail_mary_drop_key(fz_context *ctx, void *key) |
1124 | 7 | { |
1125 | 7 | } |
1126 | | |
1127 | | static int |
1128 | | hail_mary_cmp_key(fz_context *ctx, void *k0, void *k1) |
1129 | 0 | { |
1130 | 0 | return k0 == k1; |
1131 | 0 | } |
1132 | | |
1133 | | static void |
1134 | | hail_mary_format_key(fz_context *ctx, char *s, size_t n, void *key_) |
1135 | 0 | { |
1136 | 0 | fz_strlcpy(s, "(hail mary font)", n); |
1137 | 0 | } |
1138 | | |
1139 | | static int hail_mary_store_key; /* Dummy */ |
1140 | | |
1141 | | static const fz_store_type hail_mary_store_type = |
1142 | | { |
1143 | | "hail-mary", |
1144 | | hail_mary_make_hash_key, |
1145 | | hail_mary_keep_key, |
1146 | | hail_mary_drop_key, |
1147 | | hail_mary_cmp_key, |
1148 | | hail_mary_format_key, |
1149 | | NULL |
1150 | | }; |
1151 | | |
1152 | | pdf_font_desc * |
1153 | | pdf_load_hail_mary_font(fz_context *ctx, pdf_document *doc) |
1154 | 1.32k | { |
1155 | 1.32k | pdf_font_desc *fontdesc; |
1156 | 1.32k | pdf_font_desc *existing; |
1157 | | |
1158 | 1.32k | if ((fontdesc = fz_find_item(ctx, pdf_drop_font_imp, &hail_mary_store_key, &hail_mary_store_type)) != NULL) |
1159 | 1.31k | { |
1160 | 1.31k | return fontdesc; |
1161 | 1.31k | } |
1162 | | |
1163 | | /* FIXME: Get someone with a clue about fonts to fix this */ |
1164 | 7 | fontdesc = pdf_load_simple_font(ctx, doc, NULL, PDF_NAME(FontFile)); |
1165 | | |
1166 | 7 | existing = fz_store_item(ctx, &hail_mary_store_key, fontdesc, fontdesc->size, &hail_mary_store_type); |
1167 | 7 | assert(existing == NULL); |
1168 | 7 | (void)existing; /* Silence warning in release builds */ |
1169 | | |
1170 | 7 | return fontdesc; |
1171 | 7 | } |
1172 | | |
1173 | | /* |
1174 | | * CID Fonts |
1175 | | */ |
1176 | | |
1177 | | static pdf_font_desc * |
1178 | | load_cid_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict, pdf_obj *encoding, pdf_obj *to_unicode, pdf_obj *fftype) |
1179 | 79 | { |
1180 | 79 | pdf_obj *widths; |
1181 | 79 | pdf_obj *descriptor; |
1182 | 79 | pdf_font_desc *fontdesc; |
1183 | 79 | fz_buffer *buf = NULL; |
1184 | 79 | FT_Face face; |
1185 | 79 | char collection[256]; |
1186 | 79 | const char *basefont; |
1187 | 79 | int i, k, fterr; |
1188 | 79 | pdf_obj *cidtogidmap; |
1189 | 79 | pdf_obj *obj; |
1190 | 79 | int dw; |
1191 | | |
1192 | 79 | fz_var(buf); |
1193 | | |
1194 | 79 | fontdesc = pdf_new_font_desc(ctx); |
1195 | | |
1196 | 158 | fz_try(ctx) |
1197 | 158 | { |
1198 | | /* Get font name and CID collection */ |
1199 | | |
1200 | 79 | basefont = pdf_dict_get_name(ctx, dict, PDF_NAME(BaseFont)); |
1201 | | |
1202 | 79 | { |
1203 | 79 | pdf_obj *cidinfo; |
1204 | 79 | const char *reg, *ord; |
1205 | | |
1206 | 79 | cidinfo = pdf_dict_get(ctx, dict, PDF_NAME(CIDSystemInfo)); |
1207 | 79 | if (cidinfo) |
1208 | 79 | { |
1209 | 79 | reg = pdf_dict_get_string(ctx, cidinfo, PDF_NAME(Registry), NULL); |
1210 | 79 | ord = pdf_dict_get_string(ctx, cidinfo, PDF_NAME(Ordering), NULL); |
1211 | 79 | fz_snprintf(collection, sizeof collection, "%s-%s", reg, ord); |
1212 | 79 | } |
1213 | 0 | else |
1214 | 0 | { |
1215 | 0 | fz_warn(ctx, "CIDFont is missing CIDSystemInfo dictionary; assuming Adobe-Identity"); |
1216 | 0 | fz_strlcpy(collection, "Adobe-Identity", sizeof collection); |
1217 | 0 | } |
1218 | 79 | } |
1219 | | |
1220 | | /* Encoding */ |
1221 | | |
1222 | 79 | if (pdf_is_name(ctx, encoding)) |
1223 | 79 | { |
1224 | 79 | fontdesc->encoding = pdf_load_system_cmap(ctx, pdf_to_name(ctx, encoding)); |
1225 | 79 | } |
1226 | 0 | else if (pdf_is_indirect(ctx, encoding)) |
1227 | 0 | { |
1228 | 0 | fontdesc->encoding = pdf_load_embedded_cmap(ctx, doc, encoding); |
1229 | 0 | } |
1230 | 0 | else |
1231 | 0 | { |
1232 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "font missing encoding"); |
1233 | 0 | } |
1234 | | |
1235 | | /* Load font file */ |
1236 | | |
1237 | 79 | fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding); |
1238 | | |
1239 | 79 | pdf_set_font_wmode(ctx, fontdesc, pdf_cmap_wmode(ctx, fontdesc->encoding)); |
1240 | | |
1241 | 79 | descriptor = pdf_dict_get(ctx, dict, PDF_NAME(FontDescriptor)); |
1242 | 79 | if (!descriptor) |
1243 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "missing font descriptor"); |
1244 | 79 | pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, collection, basefont, 1, fftype); |
1245 | | |
1246 | 79 | face = fontdesc->font->ft_face; |
1247 | | |
1248 | | /* Apply encoding */ |
1249 | | |
1250 | 79 | cidtogidmap = pdf_dict_get(ctx, dict, PDF_NAME(CIDToGIDMap)); |
1251 | 79 | if (pdf_is_stream(ctx, cidtogidmap)) |
1252 | 1 | { |
1253 | 1 | size_t z, len; |
1254 | 1 | unsigned char *data; |
1255 | | |
1256 | 1 | buf = pdf_load_stream(ctx, cidtogidmap); |
1257 | | |
1258 | 1 | len = fz_buffer_storage(ctx, buf, &data); |
1259 | 1 | fontdesc->cid_to_gid_len = len / 2; |
1260 | 1 | fontdesc->cid_to_gid = Memento_label(fz_malloc_array(ctx, fontdesc->cid_to_gid_len, unsigned short), "cid_to_gid_map"); |
1261 | 1 | fontdesc->size += fontdesc->cid_to_gid_len * sizeof(unsigned short); |
1262 | 5 | for (z = 0; z < fontdesc->cid_to_gid_len; z++) |
1263 | 4 | fontdesc->cid_to_gid[z] = (data[z * 2] << 8) + data[z * 2 + 1]; |
1264 | 1 | } |
1265 | 78 | else if (cidtogidmap && !pdf_name_eq(ctx, PDF_NAME(Identity), cidtogidmap)) |
1266 | 0 | { |
1267 | 0 | fz_warn(ctx, "ignoring unknown CIDToGIDMap entry"); |
1268 | 0 | } |
1269 | | |
1270 | | /* if font is external, cidtogidmap should not be identity */ |
1271 | | /* so we map from cid to unicode and then map that through the (3 1) */ |
1272 | | /* unicode cmap to get a glyph id */ |
1273 | 78 | else if (fontdesc->font->flags.ft_substitute) |
1274 | 15 | { |
1275 | 15 | fz_ft_lock(ctx); |
1276 | 15 | fterr = FT_Select_Charmap(face, ft_encoding_unicode); |
1277 | 15 | fz_ft_unlock(ctx); |
1278 | 15 | if (fterr) |
1279 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "no unicode cmap when emulating CID font: %s", ft_error_string(fterr)); |
1280 | | |
1281 | 15 | if (!strcmp(collection, "Adobe-CNS1")) |
1282 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2"); |
1283 | 15 | else if (!strcmp(collection, "Adobe-GB1")) |
1284 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2"); |
1285 | 15 | else if (!strcmp(collection, "Adobe-Japan1")) |
1286 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2"); |
1287 | 15 | else if (!strcmp(collection, "Adobe-Japan2")) |
1288 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan2-UCS2"); |
1289 | 15 | else if (!strcmp(collection, "Adobe-Korea1")) |
1290 | 0 | fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2"); |
1291 | 15 | } |
1292 | | |
1293 | 79 | pdf_load_to_unicode(ctx, doc, fontdesc, NULL, collection, to_unicode); |
1294 | | |
1295 | | /* If we have an identity encoding, we're supposed to use the glyph ids directly. |
1296 | | * If we only have a substitute font, that won't work. |
1297 | | * Make a last ditch attempt by using |
1298 | | * the ToUnicode table if it exists to map via the substitute font's cmap. */ |
1299 | 79 | if (strstr(fontdesc->encoding->cmap_name, "Identity-") && fontdesc->font->flags.ft_substitute) |
1300 | 15 | { |
1301 | 15 | if (!fontdesc->to_ttf_cmap) |
1302 | 15 | { |
1303 | 15 | if (fontdesc->to_unicode) |
1304 | 2 | { |
1305 | | // Use ToUnicode from PDF file if possible. |
1306 | 2 | fontdesc->to_ttf_cmap = pdf_keep_cmap(ctx, fontdesc->to_unicode); |
1307 | 2 | } |
1308 | 13 | else |
1309 | 13 | { |
1310 | | // Attempt a generic ToUnicode (default MacRoman ordering for TrueType) |
1311 | 13 | fontdesc->to_ttf_cmap = pdf_load_builtin_cmap(ctx, "TrueType-UCS2"); |
1312 | 13 | } |
1313 | 15 | } |
1314 | | |
1315 | 15 | if (fontdesc->to_ttf_cmap) |
1316 | 15 | { |
1317 | 15 | fz_warn(ctx, "non-embedded font using identity encoding: %s (mapping via %s)", basefont, fontdesc->to_ttf_cmap->cmap_name); |
1318 | 15 | if (!fontdesc->to_unicode) |
1319 | 13 | fontdesc->to_unicode = pdf_keep_cmap(ctx, fontdesc->to_ttf_cmap); |
1320 | 15 | } |
1321 | 0 | else |
1322 | 0 | fz_warn(ctx, "non-embedded font using identity encoding: %s", basefont); |
1323 | 15 | } |
1324 | | |
1325 | | /* Horizontal */ |
1326 | | |
1327 | 79 | dw = pdf_dict_get_int_default(ctx, dict, PDF_NAME(DW), 1000); |
1328 | 79 | pdf_set_default_hmtx(ctx, fontdesc, dw); |
1329 | | |
1330 | 79 | widths = pdf_dict_get(ctx, dict, PDF_NAME(W)); |
1331 | 79 | if (widths) |
1332 | 79 | { |
1333 | 79 | int c0, c1, w, n, m; |
1334 | | |
1335 | 79 | n = pdf_array_len(ctx, widths); |
1336 | 3.92k | for (i = 0; i < n; ) |
1337 | 3.84k | { |
1338 | 3.84k | c0 = pdf_array_get_int(ctx, widths, i); |
1339 | 3.84k | obj = pdf_array_get(ctx, widths, i + 1); |
1340 | 3.84k | if (pdf_is_array(ctx, obj)) |
1341 | 1.84k | { |
1342 | 1.84k | m = pdf_array_len(ctx, obj); |
1343 | 145k | for (k = 0; k < m; k++) |
1344 | 143k | { |
1345 | 143k | w = pdf_array_get_int(ctx, obj, k); |
1346 | 143k | pdf_add_hmtx(ctx, fontdesc, c0 + k, c0 + k, w); |
1347 | 143k | } |
1348 | 1.84k | i += 2; |
1349 | 1.84k | } |
1350 | 2.00k | else |
1351 | 2.00k | { |
1352 | 2.00k | c1 = pdf_to_int(ctx, obj); |
1353 | 2.00k | w = pdf_array_get_int(ctx, widths, i + 2); |
1354 | 2.00k | pdf_add_hmtx(ctx, fontdesc, c0, c1, w); |
1355 | 2.00k | i += 3; |
1356 | 2.00k | } |
1357 | 3.84k | } |
1358 | 79 | } |
1359 | 0 | else |
1360 | 0 | { |
1361 | | /* don't stretch to match widths if no widths table was given */ |
1362 | 0 | fontdesc->font->flags.ft_stretch = 0; |
1363 | 0 | } |
1364 | | |
1365 | 79 | pdf_end_hmtx(ctx, fontdesc); |
1366 | | |
1367 | | /* Vertical */ |
1368 | | |
1369 | 79 | if (pdf_cmap_wmode(ctx, fontdesc->encoding) == 1) |
1370 | 0 | { |
1371 | 0 | int dw2y = 880; |
1372 | 0 | int dw2w = -1000; |
1373 | |
|
1374 | 0 | obj = pdf_dict_get(ctx, dict, PDF_NAME(DW2)); |
1375 | 0 | if (obj) |
1376 | 0 | { |
1377 | 0 | dw2y = pdf_array_get_int(ctx, obj, 0); |
1378 | 0 | dw2w = pdf_array_get_int(ctx, obj, 1); |
1379 | 0 | } |
1380 | |
|
1381 | 0 | pdf_set_default_vmtx(ctx, fontdesc, dw2y, dw2w); |
1382 | |
|
1383 | 0 | widths = pdf_dict_get(ctx, dict, PDF_NAME(W2)); |
1384 | 0 | if (widths) |
1385 | 0 | { |
1386 | 0 | int c0, c1, w, x, y, n; |
1387 | |
|
1388 | 0 | n = pdf_array_len(ctx, widths); |
1389 | 0 | for (i = 0; i < n; ) |
1390 | 0 | { |
1391 | 0 | c0 = pdf_array_get_int(ctx, widths, i); |
1392 | 0 | obj = pdf_array_get(ctx, widths, i + 1); |
1393 | 0 | if (pdf_is_array(ctx, obj)) |
1394 | 0 | { |
1395 | 0 | int m = pdf_array_len(ctx, obj); |
1396 | 0 | for (k = 0; k * 3 < m; k ++) |
1397 | 0 | { |
1398 | 0 | w = pdf_array_get_int(ctx, obj, k * 3 + 0); |
1399 | 0 | x = pdf_array_get_int(ctx, obj, k * 3 + 1); |
1400 | 0 | y = pdf_array_get_int(ctx, obj, k * 3 + 2); |
1401 | 0 | pdf_add_vmtx(ctx, fontdesc, c0 + k, c0 + k, x, y, w); |
1402 | 0 | } |
1403 | 0 | i += 2; |
1404 | 0 | } |
1405 | 0 | else |
1406 | 0 | { |
1407 | 0 | c1 = pdf_to_int(ctx, obj); |
1408 | 0 | w = pdf_array_get_int(ctx, widths, i + 2); |
1409 | 0 | x = pdf_array_get_int(ctx, widths, i + 3); |
1410 | 0 | y = pdf_array_get_int(ctx, widths, i + 4); |
1411 | 0 | pdf_add_vmtx(ctx, fontdesc, c0, c1, x, y, w); |
1412 | 0 | i += 5; |
1413 | 0 | } |
1414 | 0 | } |
1415 | 0 | } |
1416 | |
|
1417 | 0 | pdf_end_vmtx(ctx, fontdesc); |
1418 | 0 | } |
1419 | 79 | } |
1420 | 158 | fz_always(ctx) |
1421 | 79 | fz_drop_buffer(ctx, buf); |
1422 | 79 | fz_catch(ctx) |
1423 | 0 | { |
1424 | 0 | pdf_drop_font(ctx, fontdesc); |
1425 | 0 | fz_rethrow(ctx); |
1426 | 0 | } |
1427 | | |
1428 | 79 | return fontdesc; |
1429 | 79 | } |
1430 | | |
1431 | | static pdf_font_desc * |
1432 | | pdf_load_type0_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict) |
1433 | 149 | { |
1434 | 149 | pdf_obj *dfonts; |
1435 | 149 | pdf_obj *dfont; |
1436 | 149 | pdf_obj *subtype; |
1437 | 149 | pdf_obj *encoding; |
1438 | 149 | pdf_obj *to_unicode; |
1439 | | |
1440 | 149 | dfonts = pdf_dict_get(ctx, dict, PDF_NAME(DescendantFonts)); |
1441 | 149 | if (!dfonts) |
1442 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "cid font is missing descendant fonts"); |
1443 | | |
1444 | 149 | dfont = pdf_array_get(ctx, dfonts, 0); |
1445 | | |
1446 | 149 | subtype = pdf_dict_get(ctx, dfont, PDF_NAME(Subtype)); |
1447 | 149 | encoding = pdf_dict_get(ctx, dict, PDF_NAME(Encoding)); |
1448 | 149 | to_unicode = pdf_dict_get(ctx, dict, PDF_NAME(ToUnicode)); |
1449 | | |
1450 | 149 | if (pdf_is_name(ctx, subtype) && pdf_name_eq(ctx, subtype, PDF_NAME(CIDFontType0))) |
1451 | 2 | return load_cid_font(ctx, doc, dfont, encoding, to_unicode, PDF_NAME(FontFile3)); |
1452 | 147 | if (pdf_is_name(ctx, subtype) && pdf_name_eq(ctx, subtype, PDF_NAME(CIDFontType2))) |
1453 | 77 | return load_cid_font(ctx, doc, dfont, encoding, to_unicode, PDF_NAME(FontFile2)); |
1454 | 70 | fz_throw(ctx, FZ_ERROR_SYNTAX, "unknown cid font type"); |
1455 | 147 | } |
1456 | | |
1457 | | /* |
1458 | | * FontDescriptor |
1459 | | */ |
1460 | | |
1461 | | static void |
1462 | | pdf_load_font_descriptor(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, pdf_obj *dict, |
1463 | | const char *collection, const char *basefont, int iscidfont, pdf_obj *fftype) |
1464 | 572 | { |
1465 | 572 | pdf_obj *obj; |
1466 | 572 | const char *fontname; |
1467 | 572 | FT_Face face; |
1468 | | |
1469 | | /* Prefer BaseFont; don't bother with FontName */ |
1470 | 572 | fontname = basefont; |
1471 | | |
1472 | 572 | fontdesc->flags = pdf_dict_get_int(ctx, dict, PDF_NAME(Flags)); |
1473 | 572 | fontdesc->italic_angle = pdf_dict_get_real(ctx, dict, PDF_NAME(ItalicAngle)); |
1474 | | /* fontdesc->ascent and descent have already been set to sane defaults */ |
1475 | 572 | fontdesc->cap_height = pdf_dict_get_real(ctx, dict, PDF_NAME(CapHeight)); |
1476 | 572 | fontdesc->x_height = pdf_dict_get_real(ctx, dict, PDF_NAME(XHeight)); |
1477 | 572 | fontdesc->missing_width = pdf_dict_get_real(ctx, dict, PDF_NAME(MissingWidth)); |
1478 | | |
1479 | 572 | obj = pdf_dict_get(ctx, dict, fftype); |
1480 | 572 | if (!obj) obj = pdf_dict_get(ctx, dict, PDF_NAME(FontFile)); |
1481 | 572 | if (!obj) obj = pdf_dict_get(ctx, dict, PDF_NAME(FontFile2)); |
1482 | 572 | if (!obj) obj = pdf_dict_get(ctx, dict, PDF_NAME(FontFile3)); |
1483 | | |
1484 | 572 | if (pdf_is_indirect(ctx, obj)) |
1485 | 506 | { |
1486 | 1.01k | fz_try(ctx) |
1487 | 1.01k | { |
1488 | 506 | pdf_load_embedded_font(ctx, doc, fontdesc, fontname, obj); |
1489 | 506 | } |
1490 | 1.01k | fz_catch(ctx) |
1491 | 39 | { |
1492 | 39 | fz_rethrow_if(ctx, FZ_ERROR_TRYLATER); |
1493 | 39 | fz_rethrow_if(ctx, FZ_ERROR_SYSTEM); |
1494 | 39 | fz_report_error(ctx); |
1495 | 39 | fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font"); |
1496 | 39 | if (!iscidfont && fontname != pdf_clean_font_name(fontname)) |
1497 | 0 | pdf_load_builtin_font(ctx, fontdesc, fontname, 1); |
1498 | 39 | else |
1499 | 39 | pdf_load_system_font(ctx, fontdesc, fontname, collection); |
1500 | 39 | } |
1501 | 506 | } |
1502 | 66 | else |
1503 | 66 | { |
1504 | 66 | if (!iscidfont && fontname != pdf_clean_font_name(fontname)) |
1505 | 33 | pdf_load_builtin_font(ctx, fontdesc, fontname, 1); |
1506 | 33 | else |
1507 | 33 | pdf_load_system_font(ctx, fontdesc, fontname, collection); |
1508 | 66 | } |
1509 | | |
1510 | | /* Check for DynaLab fonts that must use hinting */ |
1511 | 572 | face = fontdesc->font->ft_face; |
1512 | 572 | if (ft_kind(ctx, face) == TRUETYPE) |
1513 | 228 | { |
1514 | | /* FreeType's own 'tricky' font detection needs a bit of help */ |
1515 | 228 | if (is_dynalab(fontdesc->font->name)) |
1516 | 0 | face->face_flags |= FT_FACE_FLAG_TRICKY; |
1517 | | |
1518 | 228 | fontdesc->ascent = 1000.0f * face->ascender / face->units_per_EM; |
1519 | | |
1520 | 228 | fontdesc->descent = 1000.0f * face->descender / face->units_per_EM; |
1521 | 228 | } |
1522 | | |
1523 | | /* Prefer FontDescriptor Ascent/Descent values to embedded font's */ |
1524 | 572 | fontdesc->ascent = pdf_dict_get_real_default(ctx, dict, PDF_NAME(Ascent), fontdesc->ascent); |
1525 | 572 | fontdesc->descent = pdf_dict_get_real_default(ctx, dict, PDF_NAME(Descent), fontdesc->descent); |
1526 | | /* Allow for naughty producers that give us a positive descent. */ |
1527 | 572 | if (fontdesc->descent > 0) |
1528 | 0 | fontdesc->descent = -fontdesc->descent; |
1529 | | |
1530 | 572 | if (fontdesc->ascent <= 0 || fontdesc->ascent > FZ_MAX_TRUSTWORTHY_ASCENT * 1000 || |
1531 | 568 | fontdesc->descent < FZ_MAX_TRUSTWORTHY_DESCENT * 1000) |
1532 | 4 | { |
1533 | 4 | if (fontdesc->ascent != 0 || fontdesc->descent != 0) |
1534 | 0 | fz_warn(ctx, "bogus font (%s) ascent/descent values (%g / %g)", fontname, fontdesc->ascent, fontdesc->descent); |
1535 | 4 | fontdesc->font->ascender = 0.8f; |
1536 | 4 | fontdesc->font->descender = -0.2f; |
1537 | 4 | fontdesc->font->ascdesc_src = FZ_ASCDESC_DEFAULT; |
1538 | 4 | } |
1539 | 568 | else |
1540 | 568 | { |
1541 | 568 | fontdesc->font->ascender = fontdesc->ascent / 1000.0f; |
1542 | 568 | fontdesc->font->descender = fontdesc->descent / 1000.0f; |
1543 | 568 | fontdesc->font->ascdesc_src = FZ_ASCDESC_FROM_FONT; |
1544 | 568 | } |
1545 | 572 | } |
1546 | | |
1547 | | static void |
1548 | | pdf_make_width_table(fz_context *ctx, pdf_font_desc *fontdesc) |
1549 | 600 | { |
1550 | 600 | fz_font *font = fontdesc->font; |
1551 | 600 | int i, k, n, cid, gid; |
1552 | | |
1553 | 600 | n = 0; |
1554 | 195k | for (i = 0; i < fontdesc->hmtx_len; i++) |
1555 | 194k | { |
1556 | 394k | for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) |
1557 | 200k | { |
1558 | 200k | cid = pdf_lookup_cmap(fontdesc->encoding, k); |
1559 | 200k | gid = pdf_font_cid_to_gid(ctx, fontdesc, cid); |
1560 | 200k | if (gid > n) |
1561 | 110k | n = gid; |
1562 | 200k | } |
1563 | 194k | } |
1564 | | |
1565 | 600 | font->width_count = n + 1; |
1566 | 600 | font->width_table = Memento_label(fz_malloc_array(ctx, font->width_count, short), "font_widths"); |
1567 | 600 | fontdesc->size += font->width_count * sizeof(short); |
1568 | | |
1569 | 600 | font->width_default = fontdesc->dhmtx.w; |
1570 | 170k | for (i = 0; i < font->width_count; i++) |
1571 | 169k | font->width_table[i] = -1; |
1572 | | |
1573 | 195k | for (i = 0; i < fontdesc->hmtx_len; i++) |
1574 | 194k | { |
1575 | 394k | for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) |
1576 | 200k | { |
1577 | 200k | cid = pdf_lookup_cmap(fontdesc->encoding, k); |
1578 | 200k | gid = pdf_font_cid_to_gid(ctx, fontdesc, cid); |
1579 | 200k | if (gid >= 0 && gid < font->width_count) |
1580 | 200k | font->width_table[gid] = fz_maxi(fontdesc->hmtx[i].w, font->width_table[gid]); |
1581 | 200k | } |
1582 | 194k | } |
1583 | | |
1584 | 170k | for (i = 0; i < font->width_count; i++) |
1585 | 169k | if (font->width_table[i] == -1) |
1586 | 35.2k | font->width_table[i] = font->width_default; |
1587 | 600 | } |
1588 | | |
1589 | | pdf_font_desc * |
1590 | | pdf_load_font(fz_context *ctx, pdf_document *doc, pdf_resource_stack *rdb, pdf_obj *dict) |
1591 | 18.5k | { |
1592 | 18.5k | pdf_obj *subtype; |
1593 | 18.5k | pdf_obj *dfonts; |
1594 | 18.5k | pdf_obj *charprocs; |
1595 | 18.5k | pdf_font_desc *fontdesc = NULL; |
1596 | 18.5k | int type3 = 0; |
1597 | | |
1598 | 18.5k | if ((fontdesc = pdf_find_item(ctx, pdf_drop_font_imp, dict)) != NULL) |
1599 | 17.8k | { |
1600 | 17.8k | if (fontdesc->font->t3loading) |
1601 | 0 | { |
1602 | 0 | pdf_drop_font(ctx, fontdesc); |
1603 | 0 | fz_throw(ctx, FZ_ERROR_SYNTAX, "recursive type3 font"); |
1604 | 0 | } |
1605 | 17.8k | return fontdesc; |
1606 | 17.8k | } |
1607 | | |
1608 | 670 | subtype = pdf_dict_get(ctx, dict, PDF_NAME(Subtype)); |
1609 | 670 | dfonts = pdf_dict_get(ctx, dict, PDF_NAME(DescendantFonts)); |
1610 | 670 | charprocs = pdf_dict_get(ctx, dict, PDF_NAME(CharProcs)); |
1611 | | |
1612 | 670 | if (pdf_name_eq(ctx, subtype, PDF_NAME(Type0))) |
1613 | 149 | fontdesc = pdf_load_type0_font(ctx, doc, dict); |
1614 | 521 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(Type1))) |
1615 | 316 | fontdesc = pdf_load_simple_font(ctx, doc, dict, PDF_NAME(FontFile)); |
1616 | 205 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(MMType1))) |
1617 | 0 | fontdesc = pdf_load_simple_font(ctx, doc, dict, PDF_NAME(FontFile)); |
1618 | 205 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(TrueType))) |
1619 | 202 | fontdesc = pdf_load_simple_font(ctx, doc, dict, PDF_NAME(FontFile2)); |
1620 | 3 | else if (pdf_name_eq(ctx, subtype, PDF_NAME(Type3))) |
1621 | 0 | { |
1622 | 0 | fontdesc = pdf_load_type3_font(ctx, doc, rdb, dict); |
1623 | 0 | type3 = 1; |
1624 | 0 | } |
1625 | 3 | else if (charprocs) |
1626 | 0 | { |
1627 | 0 | fz_warn(ctx, "unknown font format, guessing type3."); |
1628 | 0 | fontdesc = pdf_load_type3_font(ctx, doc, rdb, dict); |
1629 | 0 | type3 = 1; |
1630 | 0 | } |
1631 | 3 | else if (dfonts) |
1632 | 0 | { |
1633 | 0 | fz_warn(ctx, "unknown font format, guessing type0."); |
1634 | 0 | fontdesc = pdf_load_type0_font(ctx, doc, dict); |
1635 | 0 | } |
1636 | 3 | else |
1637 | 3 | { |
1638 | 3 | fz_warn(ctx, "unknown font format, guessing type1 or truetype."); |
1639 | 3 | fontdesc = pdf_load_simple_font(ctx, doc, dict, PDF_NAME(FontFile)); |
1640 | 3 | } |
1641 | | |
1642 | 1.20k | fz_try(ctx) |
1643 | 1.20k | { |
1644 | | /* Set family name from font name for substitute and Type 3 fonts */ |
1645 | 600 | pdf_make_font_family(ctx, fontdesc->font); |
1646 | | |
1647 | | /* Create glyph width table for stretching substitute fonts and text extraction. */ |
1648 | 600 | pdf_make_width_table(ctx, fontdesc); |
1649 | | |
1650 | 600 | pdf_store_item(ctx, dict, fontdesc, fontdesc->size); |
1651 | | |
1652 | | /* Load CharProcs */ |
1653 | 600 | if (type3) |
1654 | 0 | { |
1655 | 0 | fontdesc->font->t3loading = 1; |
1656 | 0 | fz_try(ctx) |
1657 | 0 | pdf_load_type3_glyphs(ctx, doc, fontdesc); |
1658 | 0 | fz_always(ctx) |
1659 | 0 | fontdesc->font->t3loading = 0; |
1660 | 0 | fz_catch(ctx) |
1661 | 0 | { |
1662 | 0 | pdf_remove_item(ctx, fontdesc->storable.drop, dict); |
1663 | 0 | fz_rethrow(ctx); |
1664 | 0 | } |
1665 | 0 | } |
1666 | 600 | } |
1667 | 1.20k | fz_catch(ctx) |
1668 | 0 | { |
1669 | 0 | pdf_drop_font(ctx, fontdesc); |
1670 | 0 | fz_rethrow(ctx); |
1671 | 0 | } |
1672 | | |
1673 | 670 | return fontdesc; |
1674 | 670 | } |
1675 | | |
1676 | | void |
1677 | | pdf_print_font(fz_context *ctx, fz_output *out, pdf_font_desc *fontdesc) |
1678 | 0 | { |
1679 | 0 | int i; |
1680 | |
|
1681 | 0 | fz_write_printf(ctx, out, "fontdesc {\n"); |
1682 | |
|
1683 | 0 | if (fontdesc->font->ft_face) |
1684 | 0 | fz_write_printf(ctx, out, "\tfreetype font\n"); |
1685 | 0 | if (fontdesc->font->t3procs) |
1686 | 0 | fz_write_printf(ctx, out, "\ttype3 font\n"); |
1687 | |
|
1688 | 0 | fz_write_printf(ctx, out, "\twmode %d\n", fontdesc->wmode); |
1689 | 0 | fz_write_printf(ctx, out, "\tDW %d\n", fontdesc->dhmtx.w); |
1690 | |
|
1691 | 0 | fz_write_printf(ctx, out, "\tW {\n"); |
1692 | 0 | for (i = 0; i < fontdesc->hmtx_len; i++) |
1693 | 0 | fz_write_printf(ctx, out, "\t\t<%04x> <%04x> %d\n", |
1694 | 0 | fontdesc->hmtx[i].lo, fontdesc->hmtx[i].hi, fontdesc->hmtx[i].w); |
1695 | 0 | fz_write_printf(ctx, out, "\t}\n"); |
1696 | |
|
1697 | 0 | if (fontdesc->wmode) |
1698 | 0 | { |
1699 | 0 | fz_write_printf(ctx, out, "\tDW2 [%d %d]\n", fontdesc->dvmtx.y, fontdesc->dvmtx.w); |
1700 | 0 | fz_write_printf(ctx, out, "\tW2 {\n"); |
1701 | 0 | for (i = 0; i < fontdesc->vmtx_len; i++) |
1702 | 0 | fz_write_printf(ctx, out, "\t\t<%04x> <%04x> %d %d %d\n", fontdesc->vmtx[i].lo, fontdesc->vmtx[i].hi, |
1703 | 0 | fontdesc->vmtx[i].x, fontdesc->vmtx[i].y, fontdesc->vmtx[i].w); |
1704 | 0 | fz_write_printf(ctx, out, "\t}\n"); |
1705 | 0 | } |
1706 | 0 | } |