Rev 8402 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
8402 | maxcodehac | 1 | #include "fitz.h" |
2 | #include "mupdf.h" |
||
3 | |||
4 | #include |
||
5 | #include FT_FREETYPE_H |
||
6 | #include FT_XFREE86_H |
||
7 | |||
8 | static fz_error pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont); |
||
9 | |||
10 | static char *base_font_names[14][7] = |
||
11 | { |
||
12 | { "Courier", "CourierNew", "CourierNewPSMT", NULL }, |
||
13 | { "Courier-Bold", "CourierNew,Bold", "Courier,Bold", |
||
14 | "CourierNewPS-BoldMT", "CourierNew-Bold", NULL }, |
||
15 | { "Courier-Oblique", "CourierNew,Italic", "Courier,Italic", |
||
16 | "CourierNewPS-ItalicMT", "CourierNew-Italic", NULL }, |
||
17 | { "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic", |
||
18 | "CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", NULL }, |
||
19 | { "Helvetica", "ArialMT", "Arial", NULL }, |
||
20 | { "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold", |
||
21 | "Helvetica,Bold", NULL }, |
||
22 | { "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic", |
||
23 | "Helvetica,Italic", "Helvetica-Italic", NULL }, |
||
24 | { "Helvetica-BoldOblique", "Arial-BoldItalicMT", |
||
25 | "Arial,BoldItalic", "Arial-BoldItalic", |
||
26 | "Helvetica,BoldItalic", "Helvetica-BoldItalic", NULL }, |
||
27 | { "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman", |
||
28 | "TimesNewRomanPS", NULL }, |
||
29 | { "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold", |
||
30 | "TimesNewRomanPS-Bold", "TimesNewRoman-Bold", NULL }, |
||
31 | { "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic", |
||
32 | "TimesNewRomanPS-Italic", "TimesNewRoman-Italic", NULL }, |
||
33 | { "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT", |
||
34 | "TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic", |
||
35 | "TimesNewRoman-BoldItalic", NULL }, |
||
36 | { "Symbol", NULL }, |
||
37 | { "ZapfDingbats", NULL } |
||
38 | }; |
||
39 | |||
40 | static int is_dynalab(char *name) |
||
41 | { |
||
42 | if (strstr(name, "HuaTian")) |
||
43 | return 1; |
||
44 | if (strstr(name, "MingLi")) |
||
45 | return 1; |
||
46 | if ((strstr(name, "DF") == name) || strstr(name, "+DF")) |
||
47 | return 1; |
||
48 | if ((strstr(name, "DLC") == name) || strstr(name, "+DLC")) |
||
49 | return 1; |
||
50 | return 0; |
||
51 | } |
||
52 | |||
53 | static int strcmp_ignore_space(char *a, char *b) |
||
54 | { |
||
55 | while (1) |
||
56 | { |
||
57 | while (*a == ' ') |
||
58 | a++; |
||
59 | while (*b == ' ') |
||
60 | b++; |
||
61 | if (*a != *b) |
||
62 | return 1; |
||
63 | if (*a == 0) |
||
64 | return *a != *b; |
||
65 | if (*b == 0) |
||
66 | return *a != *b; |
||
67 | a++; |
||
68 | b++; |
||
69 | } |
||
70 | } |
||
71 | |||
72 | static char *clean_font_name(char *fontname) |
||
73 | { |
||
74 | int i, k; |
||
75 | for (i = 0; i < 14; i++) |
||
76 | for (k = 0; base_font_names[i][k]; k++) |
||
77 | if (!strcmp_ignore_space(base_font_names[i][k], fontname)) |
||
78 | return base_font_names[i][0]; |
||
79 | return fontname; |
||
80 | } |
||
81 | |||
82 | /* |
||
83 | * FreeType and Rendering glue |
||
84 | */ |
||
85 | |||
86 | enum { UNKNOWN, TYPE1, TRUETYPE }; |
||
87 | |||
88 | static int ft_kind(FT_Face face) |
||
89 | { |
||
8411 | maxcodehac | 90 | /// STUB /// |
8402 | maxcodehac | 91 | //const char *kind = FT_Get_X11_Font_Format(face); |
92 | const char *kind = "TrueType"; |
||
93 | |||
94 | if (!strcmp(kind, "TrueType")) |
||
95 | return TRUETYPE; |
||
96 | if (!strcmp(kind, "Type 1")) |
||
97 | return TYPE1; |
||
98 | if (!strcmp(kind, "CFF")) |
||
99 | return TYPE1; |
||
100 | if (!strcmp(kind, "CID Type 1")) |
||
101 | return TYPE1; |
||
102 | return UNKNOWN; |
||
103 | } |
||
104 | |||
105 | static int ft_is_bold(FT_Face face) |
||
106 | { |
||
107 | return face->style_flags & FT_STYLE_FLAG_BOLD; |
||
108 | } |
||
109 | |||
110 | static int ft_is_italic(FT_Face face) |
||
111 | { |
||
112 | return face->style_flags & FT_STYLE_FLAG_ITALIC; |
||
113 | } |
||
114 | |||
115 | static int ft_char_index(FT_Face face, int cid) |
||
116 | { |
||
117 | int gid = FT_Get_Char_Index(face, cid); |
||
118 | if (gid == 0) |
||
119 | gid = FT_Get_Char_Index(face, 0xf000 + cid); |
||
120 | |||
121 | /* some chinese fonts only ship the similarly looking 0x2026 */ |
||
122 | if (gid == 0 && cid == 0x22ef) |
||
123 | gid = FT_Get_Char_Index(face, 0x2026); |
||
124 | |||
125 | return gid; |
||
126 | } |
||
127 | |||
128 | static int ft_cid_to_gid(pdf_font_desc *fontdesc, int cid) |
||
129 | { |
||
130 | if (fontdesc->to_ttf_cmap) |
||
131 | { |
||
132 | cid = pdf_lookup_cmap(fontdesc->to_ttf_cmap, cid); |
||
133 | return ft_char_index(fontdesc->font->ft_face, cid); |
||
134 | } |
||
135 | |||
136 | if (fontdesc->cid_to_gid) |
||
137 | return fontdesc->cid_to_gid[cid]; |
||
138 | |||
139 | return cid; |
||
140 | } |
||
141 | |||
142 | int |
||
143 | pdf_font_cid_to_gid(pdf_font_desc *fontdesc, int cid) |
||
144 | { |
||
145 | if (fontdesc->font->ft_face) |
||
146 | return ft_cid_to_gid(fontdesc, cid); |
||
147 | return cid; |
||
148 | } |
||
149 | |||
150 | static int ft_width(pdf_font_desc *fontdesc, int cid) |
||
151 | { |
||
152 | int gid = ft_cid_to_gid(fontdesc, cid); |
||
153 | int fterr = FT_Load_Glyph(fontdesc->font->ft_face, gid, |
||
154 | FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM); |
||
155 | if (fterr) |
||
156 | { |
||
157 | fz_warn("freetype load glyph (gid %d): %s", gid, ft_error_string(fterr)); |
||
158 | return 0; |
||
159 | } |
||
160 | return ((FT_Face)fontdesc->font->ft_face)->glyph->advance.x; |
||
161 | } |
||
162 | |||
163 | static int lookup_mre_code(char *name) |
||
164 | { |
||
165 | int i; |
||
166 | for (i = 0; i < 256; i++) |
||
167 | if (pdf_mac_roman[i] && !strcmp(name, pdf_mac_roman[i])) |
||
168 | return i; |
||
169 | return -1; |
||
170 | } |
||
171 | |||
172 | /* |
||
173 | * Load font files. |
||
174 | */ |
||
175 | |||
176 | static fz_error |
||
177 | pdf_load_builtin_font(pdf_font_desc *fontdesc, char *fontname) |
||
178 | { |
||
179 | fz_error error; |
||
180 | unsigned char *data; |
||
181 | unsigned int len; |
||
182 | |||
183 | data = pdf_find_builtin_font(fontname, &len); |
||
184 | if (!data) |
||
185 | return fz_throw("cannot find builtin font: '%s'", fontname); |
||
186 | |||
187 | error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); |
||
188 | if (error) |
||
189 | return fz_rethrow(error, "cannot load freetype font from memory"); |
||
190 | |||
191 | if (!strcmp(fontname, "Symbol") || !strcmp(fontname, "ZapfDingbats")) |
||
192 | fontdesc->flags |= PDF_FD_SYMBOLIC; |
||
193 | |||
194 | return fz_okay; |
||
195 | } |
||
196 | |||
197 | static fz_error |
||
198 | pdf_load_substitute_font(pdf_font_desc *fontdesc, int mono, int serif, int bold, int italic) |
||
199 | { |
||
200 | fz_error error; |
||
201 | unsigned char *data; |
||
202 | unsigned int len; |
||
203 | |||
204 | data = pdf_find_substitute_font(mono, serif, bold, italic, &len); |
||
205 | if (!data) |
||
206 | return fz_throw("cannot find substitute font"); |
||
207 | |||
208 | error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); |
||
209 | if (error) |
||
210 | return fz_rethrow(error, "cannot load freetype font from memory"); |
||
211 | |||
212 | fontdesc->font->ft_substitute = 1; |
||
213 | fontdesc->font->ft_bold = bold && !ft_is_bold(fontdesc->font->ft_face); |
||
214 | fontdesc->font->ft_italic = italic && !ft_is_italic(fontdesc->font->ft_face); |
||
215 | return fz_okay; |
||
216 | } |
||
217 | |||
218 | static fz_error |
||
219 | pdf_load_substitute_cjk_font(pdf_font_desc *fontdesc, int ros, int serif) |
||
220 | { |
||
221 | fz_error error; |
||
222 | unsigned char *data; |
||
223 | unsigned int len; |
||
224 | |||
225 | data = pdf_find_substitute_cjk_font(ros, serif, &len); |
||
226 | if (!data) |
||
227 | return fz_throw("cannot find builtin CJK font"); |
||
228 | |||
229 | error = fz_new_font_from_memory(&fontdesc->font, data, len, 0); |
||
230 | if (error) |
||
231 | return fz_rethrow(error, "cannot load builtin CJK font"); |
||
232 | |||
233 | fontdesc->font->ft_substitute = 1; |
||
234 | return fz_okay; |
||
235 | } |
||
236 | |||
237 | static fz_error |
||
238 | pdf_load_system_font(pdf_font_desc *fontdesc, char *fontname, char *collection) |
||
239 | { |
||
240 | fz_error error; |
||
241 | int bold = 0; |
||
242 | int italic = 0; |
||
243 | int serif = 0; |
||
244 | int mono = 0; |
||
245 | |||
246 | if (strstr(fontname, "Bold")) |
||
247 | bold = 1; |
||
248 | if (strstr(fontname, "Italic")) |
||
249 | italic = 1; |
||
250 | if (strstr(fontname, "Oblique")) |
||
251 | italic = 1; |
||
252 | |||
253 | if (fontdesc->flags & PDF_FD_FIXED_PITCH) |
||
254 | mono = 1; |
||
255 | if (fontdesc->flags & PDF_FD_SERIF) |
||
256 | serif = 1; |
||
257 | if (fontdesc->flags & PDF_FD_ITALIC) |
||
258 | italic = 1; |
||
259 | if (fontdesc->flags & PDF_FD_FORCE_BOLD) |
||
260 | bold = 1; |
||
261 | |||
262 | if (collection) |
||
263 | { |
||
264 | if (!strcmp(collection, "Adobe-CNS1")) |
||
265 | return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_CNS, serif); |
||
266 | else if (!strcmp(collection, "Adobe-GB1")) |
||
267 | return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_GB, serif); |
||
268 | else if (!strcmp(collection, "Adobe-Japan1")) |
||
269 | return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_JAPAN, serif); |
||
270 | else if (!strcmp(collection, "Adobe-Korea1")) |
||
271 | return pdf_load_substitute_cjk_font(fontdesc, PDF_ROS_KOREA, serif); |
||
272 | return fz_throw("unknown cid collection: %s", collection); |
||
273 | } |
||
274 | |||
275 | error = pdf_load_substitute_font(fontdesc, mono, serif, bold, italic); |
||
276 | if (error) |
||
277 | return fz_rethrow(error, "cannot load substitute font"); |
||
278 | |||
279 | return fz_okay; |
||
280 | } |
||
281 | |||
282 | static fz_error |
||
283 | pdf_load_embedded_font(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *stmref) |
||
284 | { |
||
285 | fz_error error; |
||
286 | fz_buffer *buf; |
||
287 | |||
288 | error = pdf_load_stream(&buf, xref, fz_to_num(stmref), fz_to_gen(stmref)); |
||
289 | if (error) |
||
290 | return fz_rethrow(error, "cannot load font stream (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); |
||
291 | |||
292 | error = fz_new_font_from_memory(&fontdesc->font, buf->data, buf->len, 0); |
||
293 | if (error) |
||
294 | { |
||
295 | fz_drop_buffer(buf); |
||
296 | return fz_rethrow(error, "cannot load embedded font (%d %d R)", fz_to_num(stmref), fz_to_gen(stmref)); |
||
297 | } |
||
298 | |||
299 | /* save the buffer so we can free it later */ |
||
300 | fontdesc->font->ft_data = buf->data; |
||
301 | fontdesc->font->ft_size = buf->len; |
||
302 | fz_free(buf); /* only free the fz_buffer struct, not the contained data */ |
||
303 | |||
304 | fontdesc->is_embedded = 1; |
||
305 | |||
306 | return fz_okay; |
||
307 | } |
||
308 | |||
309 | /* |
||
310 | * Create and destroy |
||
311 | */ |
||
312 | |||
313 | pdf_font_desc * |
||
314 | pdf_keep_font(pdf_font_desc *fontdesc) |
||
315 | { |
||
316 | fontdesc->refs ++; |
||
317 | return fontdesc; |
||
318 | } |
||
319 | |||
320 | void |
||
321 | pdf_drop_font(pdf_font_desc *fontdesc) |
||
322 | { |
||
323 | if (fontdesc && --fontdesc->refs == 0) |
||
324 | { |
||
325 | if (fontdesc->font) |
||
326 | fz_drop_font(fontdesc->font); |
||
327 | if (fontdesc->encoding) |
||
328 | pdf_drop_cmap(fontdesc->encoding); |
||
329 | if (fontdesc->to_ttf_cmap) |
||
330 | pdf_drop_cmap(fontdesc->to_ttf_cmap); |
||
331 | if (fontdesc->to_unicode) |
||
332 | pdf_drop_cmap(fontdesc->to_unicode); |
||
333 | fz_free(fontdesc->cid_to_gid); |
||
334 | fz_free(fontdesc->cid_to_ucs); |
||
335 | fz_free(fontdesc->hmtx); |
||
336 | fz_free(fontdesc->vmtx); |
||
337 | fz_free(fontdesc); |
||
338 | } |
||
339 | } |
||
340 | |||
341 | pdf_font_desc * |
||
342 | pdf_new_font_desc(void) |
||
343 | { |
||
344 | pdf_font_desc *fontdesc; |
||
345 | |||
346 | fontdesc = fz_malloc(sizeof(pdf_font_desc)); |
||
347 | fontdesc->refs = 1; |
||
348 | |||
349 | fontdesc->font = NULL; |
||
350 | |||
351 | fontdesc->flags = 0; |
||
352 | fontdesc->italic_angle = 0; |
||
353 | fontdesc->ascent = 0; |
||
354 | fontdesc->descent = 0; |
||
355 | fontdesc->cap_height = 0; |
||
356 | fontdesc->x_height = 0; |
||
357 | fontdesc->missing_width = 0; |
||
358 | |||
359 | fontdesc->encoding = NULL; |
||
360 | fontdesc->to_ttf_cmap = NULL; |
||
361 | fontdesc->cid_to_gid_len = 0; |
||
362 | fontdesc->cid_to_gid = NULL; |
||
363 | |||
364 | fontdesc->to_unicode = NULL; |
||
365 | fontdesc->cid_to_ucs_len = 0; |
||
366 | fontdesc->cid_to_ucs = NULL; |
||
367 | |||
368 | fontdesc->wmode = 0; |
||
369 | |||
370 | fontdesc->hmtx_cap = 0; |
||
371 | fontdesc->vmtx_cap = 0; |
||
372 | fontdesc->hmtx_len = 0; |
||
373 | fontdesc->vmtx_len = 0; |
||
374 | fontdesc->hmtx = NULL; |
||
375 | fontdesc->vmtx = NULL; |
||
376 | |||
377 | fontdesc->dhmtx.lo = 0x0000; |
||
378 | fontdesc->dhmtx.hi = 0xFFFF; |
||
379 | fontdesc->dhmtx.w = 1000; |
||
380 | |||
381 | fontdesc->dvmtx.lo = 0x0000; |
||
382 | fontdesc->dvmtx.hi = 0xFFFF; |
||
383 | fontdesc->dvmtx.x = 0; |
||
384 | fontdesc->dvmtx.y = 880; |
||
385 | fontdesc->dvmtx.w = -1000; |
||
386 | |||
387 | fontdesc->is_embedded = 0; |
||
388 | |||
389 | return fontdesc; |
||
390 | } |
||
391 | |||
392 | /* |
||
393 | * Simple fonts (Type1 and TrueType) |
||
394 | */ |
||
395 | |||
396 | static fz_error |
||
397 | pdf_load_simple_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) |
||
398 | { |
||
399 | fz_error error; |
||
400 | fz_obj *descriptor; |
||
401 | fz_obj *encoding; |
||
402 | fz_obj *widths; |
||
403 | unsigned short *etable = NULL; |
||
404 | pdf_font_desc *fontdesc; |
||
405 | FT_Face face; |
||
406 | FT_CharMap cmap; |
||
407 | int symbolic; |
||
408 | int kind; |
||
409 | |||
410 | char *basefont; |
||
411 | char *fontname; |
||
412 | char *estrings[256]; |
||
413 | char ebuffer[256][32]; |
||
414 | int i, k, n; |
||
415 | int fterr; |
||
416 | |||
417 | basefont = fz_to_name(fz_dict_gets(dict, "BaseFont")); |
||
418 | fontname = clean_font_name(basefont); |
||
419 | |||
420 | /* Load font file */ |
||
421 | |||
422 | fontdesc = pdf_new_font_desc(); |
||
423 | |||
424 | descriptor = fz_dict_gets(dict, "FontDescriptor"); |
||
425 | if (descriptor) |
||
426 | error = pdf_load_font_descriptor(fontdesc, xref, descriptor, NULL, basefont); |
||
427 | else |
||
428 | error = pdf_load_builtin_font(fontdesc, fontname); |
||
429 | if (error) |
||
430 | goto cleanup; |
||
431 | |||
432 | /* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */ |
||
433 | if (!*fontdesc->font->name && |
||
434 | !fz_dict_gets(dict, "ToUnicode") && |
||
435 | !strcmp(fz_to_name(fz_dict_gets(dict, "Encoding")), "WinAnsiEncoding") && |
||
436 | fz_to_int(fz_dict_gets(descriptor, "Flags")) == 4) |
||
437 | { |
||
438 | /* note: without the comma, pdf_load_font_descriptor would prefer /FontName over /BaseFont */ |
||
439 | char *cp936fonts[] = { |
||
440 | "\xCB\xCE\xCC\xE5", "SimSun,Regular", |
||
441 | "\xBA\xDA\xCC\xE5", "SimHei,Regular", |
||
442 | "\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular", |
||
443 | "\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular", |
||
444 | "\xC1\xA5\xCA\xE9", "SimLi,Regular", |
||
445 | NULL |
||
446 | }; |
||
447 | for (i = 0; cp936fonts[i]; i += 2) |
||
448 | if (!strcmp(basefont, cp936fonts[i])) |
||
449 | break; |
||
450 | if (cp936fonts[i]) |
||
451 | { |
||
452 | fz_warn("workaround for S22PDF lying about chinese font encodings"); |
||
453 | pdf_drop_font(fontdesc); |
||
454 | fontdesc = pdf_new_font_desc(); |
||
455 | error = pdf_load_font_descriptor(fontdesc, xref, descriptor, "Adobe-GB1", cp936fonts[i+1]); |
||
456 | error |= pdf_load_system_cmap(&fontdesc->encoding, "GBK-EUC-H"); |
||
457 | error |= pdf_load_system_cmap(&fontdesc->to_unicode, "Adobe-GB1-UCS2"); |
||
458 | error |= pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-GB1-UCS2"); |
||
459 | if (error) |
||
460 | return fz_rethrow(error, "cannot load font"); |
||
461 | |||
462 | face = fontdesc->font->ft_face; |
||
463 | kind = ft_kind(face); |
||
464 | goto skip_encoding; |
||
465 | } |
||
466 | } |
||
467 | |||
468 | face = fontdesc->font->ft_face; |
||
469 | kind = ft_kind(face); |
||
470 | |||
471 | /* Encoding */ |
||
472 | |||
473 | symbolic = fontdesc->flags & 4; |
||
474 | |||
475 | if (face->num_charmaps > 0) |
||
476 | cmap = face->charmaps[0]; |
||
477 | else |
||
478 | cmap = NULL; |
||
479 | |||
480 | for (i = 0; i < face->num_charmaps; i++) |
||
481 | { |
||
482 | FT_CharMap test = face->charmaps[i]; |
||
483 | |||
484 | if (kind == TYPE1) |
||
485 | { |
||
486 | if (test->platform_id == 7) |
||
487 | cmap = test; |
||
488 | } |
||
489 | |||
490 | if (kind == TRUETYPE) |
||
491 | { |
||
492 | if (test->platform_id == 1 && test->encoding_id == 0) |
||
493 | cmap = test; |
||
494 | if (test->platform_id == 3 && test->encoding_id == 1) |
||
495 | cmap = test; |
||
496 | } |
||
497 | } |
||
498 | |||
499 | if (cmap) |
||
500 | { |
||
501 | fterr = FT_Set_Charmap(face, cmap); |
||
502 | if (fterr) |
||
503 | fz_warn("freetype could not set cmap: %s", ft_error_string(fterr)); |
||
504 | } |
||
505 | else |
||
506 | fz_warn("freetype could not find any cmaps"); |
||
507 | |||
508 | etable = fz_calloc(256, sizeof(unsigned short)); |
||
509 | for (i = 0; i < 256; i++) |
||
510 | { |
||
511 | estrings[i] = NULL; |
||
512 | etable[i] = 0; |
||
513 | } |
||
514 | |||
515 | encoding = fz_dict_gets(dict, "Encoding"); |
||
516 | if (encoding) |
||
517 | { |
||
518 | if (fz_is_name(encoding)) |
||
519 | pdf_load_encoding(estrings, fz_to_name(encoding)); |
||
520 | |||
521 | if (fz_is_dict(encoding)) |
||
522 | { |
||
523 | fz_obj *base, *diff, *item; |
||
524 | |||
525 | base = fz_dict_gets(encoding, "BaseEncoding"); |
||
526 | if (fz_is_name(base)) |
||
527 | pdf_load_encoding(estrings, fz_to_name(base)); |
||
528 | else if (!fontdesc->is_embedded && !symbolic) |
||
529 | pdf_load_encoding(estrings, "StandardEncoding"); |
||
530 | |||
531 | diff = fz_dict_gets(encoding, "Differences"); |
||
532 | if (fz_is_array(diff)) |
||
533 | { |
||
534 | n = fz_array_len(diff); |
||
535 | k = 0; |
||
536 | for (i = 0; i < n; i++) |
||
537 | { |
||
538 | item = fz_array_get(diff, i); |
||
539 | if (fz_is_int(item)) |
||
540 | k = fz_to_int(item); |
||
541 | if (fz_is_name(item)) |
||
542 | estrings[k++] = fz_to_name(item); |
||
543 | if (k < 0) k = 0; |
||
544 | if (k > 255) k = 255; |
||
545 | } |
||
546 | } |
||
547 | } |
||
548 | } |
||
549 | |||
550 | /* start with the builtin encoding */ |
||
551 | for (i = 0; i < 256; i++) |
||
552 | etable[i] = ft_char_index(face, i); |
||
553 | |||
554 | /* encode by glyph name where we can */ |
||
555 | if (kind == TYPE1) |
||
556 | { |
||
557 | for (i = 0; i < 256; i++) |
||
558 | { |
||
559 | if (estrings[i]) |
||
560 | { |
||
561 | etable[i] = FT_Get_Name_Index(face, estrings[i]); |
||
562 | if (etable[i] == 0) |
||
563 | { |
||
564 | int aglcode = pdf_lookup_agl(estrings[i]); |
||
565 | const char **dupnames = pdf_lookup_agl_duplicates(aglcode); |
||
566 | while (*dupnames) |
||
567 | { |
||
568 | etable[i] = FT_Get_Name_Index(face, (char*)*dupnames); |
||
569 | if (etable[i]) |
||
570 | break; |
||
571 | dupnames++; |
||
572 | } |
||
573 | } |
||
574 | } |
||
575 | } |
||
576 | } |
||
577 | |||
578 | /* encode by glyph name where we can */ |
||
579 | if (kind == TRUETYPE) |
||
580 | { |
||
581 | /* Unicode cmap */ |
||
582 | if (!symbolic && face->charmap && face->charmap->platform_id == 3) |
||
583 | { |
||
584 | for (i = 0; i < 256; i++) |
||
585 | { |
||
586 | if (estrings[i]) |
||
587 | { |
||
588 | int aglcode = pdf_lookup_agl(estrings[i]); |
||
589 | if (!aglcode) |
||
590 | etable[i] = FT_Get_Name_Index(face, estrings[i]); |
||
591 | else |
||
592 | etable[i] = ft_char_index(face, aglcode); |
||
593 | } |
||
594 | } |
||
595 | } |
||
596 | |||
597 | /* MacRoman cmap */ |
||
598 | else if (!symbolic && face->charmap && face->charmap->platform_id == 1) |
||
599 | { |
||
600 | for (i = 0; i < 256; i++) |
||
601 | { |
||
602 | if (estrings[i]) |
||
603 | { |
||
604 | k = lookup_mre_code(estrings[i]); |
||
605 | if (k <= 0) |
||
606 | etable[i] = FT_Get_Name_Index(face, estrings[i]); |
||
607 | else |
||
608 | etable[i] = ft_char_index(face, k); |
||
609 | } |
||
610 | } |
||
611 | } |
||
612 | |||
613 | /* Symbolic cmap */ |
||
614 | else |
||
615 | { |
||
616 | for (i = 0; i < 256; i++) |
||
617 | { |
||
618 | if (estrings[i]) |
||
619 | { |
||
620 | etable[i] = FT_Get_Name_Index(face, estrings[i]); |
||
621 | if (etable[i] == 0) |
||
622 | etable[i] = ft_char_index(face, i); |
||
623 | } |
||
624 | } |
||
625 | } |
||
626 | } |
||
627 | |||
628 | /* try to reverse the glyph names from the builtin encoding */ |
||
629 | for (i = 0; i < 256; i++) |
||
630 | { |
||
631 | if (etable[i] && !estrings[i]) |
||
632 | { |
||
633 | if (FT_HAS_GLYPH_NAMES(face)) |
||
634 | { |
||
635 | fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32); |
||
636 | if (fterr) |
||
637 | fz_warn("freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr)); |
||
638 | if (ebuffer[i][0]) |
||
639 | estrings[i] = ebuffer[i]; |
||
640 | } |
||
641 | else |
||
642 | { |
||
643 | estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */ |
||
644 | } |
||
645 | } |
||
646 | } |
||
647 | |||
648 | fontdesc->encoding = pdf_new_identity_cmap(0, 1); |
||
649 | fontdesc->cid_to_gid_len = 256; |
||
650 | fontdesc->cid_to_gid = etable; |
||
651 | |||
652 | error = pdf_load_to_unicode(fontdesc, xref, estrings, NULL, fz_dict_gets(dict, "ToUnicode")); |
||
653 | if (error) |
||
654 | fz_catch(error, "cannot load to_unicode"); |
||
655 | |||
656 | skip_encoding: |
||
657 | |||
658 | /* Widths */ |
||
659 | |||
660 | pdf_set_default_hmtx(fontdesc, fontdesc->missing_width); |
||
661 | |||
662 | widths = fz_dict_gets(dict, "Widths"); |
||
663 | if (widths) |
||
664 | { |
||
665 | int first, last; |
||
666 | |||
667 | first = fz_to_int(fz_dict_gets(dict, "FirstChar")); |
||
668 | last = fz_to_int(fz_dict_gets(dict, "LastChar")); |
||
669 | |||
670 | if (first < 0 || last > 255 || first > last) |
||
671 | first = last = 0; |
||
672 | |||
673 | for (i = 0; i < last - first + 1; i++) |
||
674 | { |
||
675 | int wid = fz_to_int(fz_array_get(widths, i)); |
||
676 | pdf_add_hmtx(fontdesc, i + first, i + first, wid); |
||
677 | } |
||
678 | } |
||
679 | else |
||
680 | { |
||
681 | fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72); |
||
682 | if (fterr) |
||
683 | fz_warn("freetype set character size: %s", ft_error_string(fterr)); |
||
684 | for (i = 0; i < 256; i++) |
||
685 | { |
||
686 | pdf_add_hmtx(fontdesc, i, i, ft_width(fontdesc, i)); |
||
687 | } |
||
688 | } |
||
689 | |||
690 | pdf_end_hmtx(fontdesc); |
||
691 | |||
692 | *fontdescp = fontdesc; |
||
693 | return fz_okay; |
||
694 | |||
695 | cleanup: |
||
696 | if (etable != fontdesc->cid_to_gid) |
||
697 | fz_free(etable); |
||
698 | pdf_drop_font(fontdesc); |
||
699 | return fz_rethrow(error, "cannot load simple font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); |
||
700 | } |
||
701 | |||
702 | /* |
||
703 | * CID Fonts |
||
704 | */ |
||
705 | |||
706 | static fz_error |
||
707 | load_cid_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict, fz_obj *encoding, fz_obj *to_unicode) |
||
708 | { |
||
709 | fz_error error; |
||
710 | fz_obj *widths; |
||
711 | fz_obj *descriptor; |
||
712 | pdf_font_desc *fontdesc; |
||
713 | FT_Face face; |
||
714 | int kind; |
||
715 | char collection[256]; |
||
716 | char *basefont; |
||
717 | int i, k, fterr; |
||
718 | fz_obj *obj; |
||
719 | int dw; |
||
720 | |||
721 | /* Get font name and CID collection */ |
||
722 | |||
723 | basefont = fz_to_name(fz_dict_gets(dict, "BaseFont")); |
||
724 | |||
725 | { |
||
726 | fz_obj *cidinfo; |
||
727 | char tmpstr[64]; |
||
728 | int tmplen; |
||
729 | |||
730 | cidinfo = fz_dict_gets(dict, "CIDSystemInfo"); |
||
731 | if (!cidinfo) |
||
732 | return fz_throw("cid font is missing info"); |
||
733 | |||
734 | obj = fz_dict_gets(cidinfo, "Registry"); |
||
735 | tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); |
||
736 | memcpy(tmpstr, fz_to_str_buf(obj), tmplen); |
||
737 | tmpstr[tmplen] = '\0'; |
||
738 | fz_strlcpy(collection, tmpstr, sizeof collection); |
||
739 | |||
740 | fz_strlcat(collection, "-", sizeof collection); |
||
741 | |||
742 | obj = fz_dict_gets(cidinfo, "Ordering"); |
||
743 | tmplen = MIN(sizeof tmpstr - 1, fz_to_str_len(obj)); |
||
744 | memcpy(tmpstr, fz_to_str_buf(obj), tmplen); |
||
745 | tmpstr[tmplen] = '\0'; |
||
746 | fz_strlcat(collection, tmpstr, sizeof collection); |
||
747 | } |
||
748 | |||
749 | /* Load font file */ |
||
750 | |||
751 | fontdesc = pdf_new_font_desc(); |
||
752 | |||
753 | descriptor = fz_dict_gets(dict, "FontDescriptor"); |
||
754 | if (descriptor) |
||
755 | error = pdf_load_font_descriptor(fontdesc, xref, descriptor, collection, basefont); |
||
756 | else |
||
757 | error = fz_throw("syntaxerror: missing font descriptor"); |
||
758 | if (error) |
||
759 | goto cleanup; |
||
760 | |||
761 | face = fontdesc->font->ft_face; |
||
762 | kind = ft_kind(face); |
||
763 | |||
764 | /* Encoding */ |
||
765 | |||
766 | error = fz_okay; |
||
767 | if (fz_is_name(encoding)) |
||
768 | { |
||
769 | if (!strcmp(fz_to_name(encoding), "Identity-H")) |
||
770 | fontdesc->encoding = pdf_new_identity_cmap(0, 2); |
||
771 | else if (!strcmp(fz_to_name(encoding), "Identity-V")) |
||
772 | fontdesc->encoding = pdf_new_identity_cmap(1, 2); |
||
773 | else |
||
774 | error = pdf_load_system_cmap(&fontdesc->encoding, fz_to_name(encoding)); |
||
775 | } |
||
776 | else if (fz_is_indirect(encoding)) |
||
777 | { |
||
778 | error = pdf_load_embedded_cmap(&fontdesc->encoding, xref, encoding); |
||
779 | } |
||
780 | else |
||
781 | { |
||
782 | error = fz_throw("syntaxerror: font missing encoding"); |
||
783 | } |
||
784 | if (error) |
||
785 | goto cleanup; |
||
786 | |||
787 | pdf_set_font_wmode(fontdesc, pdf_get_wmode(fontdesc->encoding)); |
||
788 | |||
789 | if (kind == TRUETYPE) |
||
790 | { |
||
791 | fz_obj *cidtogidmap; |
||
792 | |||
793 | cidtogidmap = fz_dict_gets(dict, "CIDToGIDMap"); |
||
794 | if (fz_is_indirect(cidtogidmap)) |
||
795 | { |
||
796 | fz_buffer *buf; |
||
797 | |||
798 | error = pdf_load_stream(&buf, xref, fz_to_num(cidtogidmap), fz_to_gen(cidtogidmap)); |
||
799 | if (error) |
||
800 | goto cleanup; |
||
801 | |||
802 | fontdesc->cid_to_gid_len = (buf->len) / 2; |
||
803 | fontdesc->cid_to_gid = fz_calloc(fontdesc->cid_to_gid_len, sizeof(unsigned short)); |
||
804 | for (i = 0; i < fontdesc->cid_to_gid_len; i++) |
||
805 | fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1]; |
||
806 | |||
807 | fz_drop_buffer(buf); |
||
808 | } |
||
809 | |||
810 | /* if truetype font is external, cidtogidmap should not be identity */ |
||
811 | /* so we map from cid to unicode and then map that through the (3 1) */ |
||
812 | /* unicode cmap to get a glyph id */ |
||
813 | else if (fontdesc->font->ft_substitute) |
||
814 | { |
||
815 | fterr = FT_Select_Charmap(face, ft_encoding_unicode); |
||
816 | if (fterr) |
||
817 | { |
||
818 | error = fz_throw("fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr)); |
||
819 | goto cleanup; |
||
820 | } |
||
821 | |||
822 | if (!strcmp(collection, "Adobe-CNS1")) |
||
823 | error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-CNS1-UCS2"); |
||
824 | else if (!strcmp(collection, "Adobe-GB1")) |
||
825 | error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-GB1-UCS2"); |
||
826 | else if (!strcmp(collection, "Adobe-Japan1")) |
||
827 | error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Japan1-UCS2"); |
||
828 | else if (!strcmp(collection, "Adobe-Japan2")) |
||
829 | error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Japan2-UCS2"); |
||
830 | else if (!strcmp(collection, "Adobe-Korea1")) |
||
831 | error = pdf_load_system_cmap(&fontdesc->to_ttf_cmap, "Adobe-Korea1-UCS2"); |
||
832 | else |
||
833 | error = fz_okay; |
||
834 | |||
835 | if (error) |
||
836 | { |
||
837 | error = fz_rethrow(error, "cannot load system cmap %s", collection); |
||
838 | goto cleanup; |
||
839 | } |
||
840 | } |
||
841 | } |
||
842 | |||
843 | error = pdf_load_to_unicode(fontdesc, xref, NULL, collection, to_unicode); |
||
844 | if (error) |
||
845 | fz_catch(error, "cannot load to_unicode"); |
||
846 | |||
847 | /* Horizontal */ |
||
848 | |||
849 | dw = 1000; |
||
850 | obj = fz_dict_gets(dict, "DW"); |
||
851 | if (obj) |
||
852 | dw = fz_to_int(obj); |
||
853 | pdf_set_default_hmtx(fontdesc, dw); |
||
854 | |||
855 | widths = fz_dict_gets(dict, "W"); |
||
856 | if (widths) |
||
857 | { |
||
858 | int c0, c1, w; |
||
859 | |||
860 | for (i = 0; i < fz_array_len(widths); ) |
||
861 | { |
||
862 | c0 = fz_to_int(fz_array_get(widths, i)); |
||
863 | obj = fz_array_get(widths, i + 1); |
||
864 | if (fz_is_array(obj)) |
||
865 | { |
||
866 | for (k = 0; k < fz_array_len(obj); k++) |
||
867 | { |
||
868 | w = fz_to_int(fz_array_get(obj, k)); |
||
869 | pdf_add_hmtx(fontdesc, c0 + k, c0 + k, w); |
||
870 | } |
||
871 | i += 2; |
||
872 | } |
||
873 | else |
||
874 | { |
||
875 | c1 = fz_to_int(obj); |
||
876 | w = fz_to_int(fz_array_get(widths, i + 2)); |
||
877 | pdf_add_hmtx(fontdesc, c0, c1, w); |
||
878 | i += 3; |
||
879 | } |
||
880 | } |
||
881 | } |
||
882 | |||
883 | pdf_end_hmtx(fontdesc); |
||
884 | |||
885 | /* Vertical */ |
||
886 | |||
887 | if (pdf_get_wmode(fontdesc->encoding) == 1) |
||
888 | { |
||
889 | int dw2y = 880; |
||
890 | int dw2w = -1000; |
||
891 | |||
892 | obj = fz_dict_gets(dict, "DW2"); |
||
893 | if (obj) |
||
894 | { |
||
895 | dw2y = fz_to_int(fz_array_get(obj, 0)); |
||
896 | dw2w = fz_to_int(fz_array_get(obj, 1)); |
||
897 | } |
||
898 | |||
899 | pdf_set_default_vmtx(fontdesc, dw2y, dw2w); |
||
900 | |||
901 | widths = fz_dict_gets(dict, "W2"); |
||
902 | if (widths) |
||
903 | { |
||
904 | int c0, c1, w, x, y; |
||
905 | |||
906 | for (i = 0; i < fz_array_len(widths); ) |
||
907 | { |
||
908 | c0 = fz_to_int(fz_array_get(widths, i)); |
||
909 | obj = fz_array_get(widths, i + 1); |
||
910 | if (fz_is_array(obj)) |
||
911 | { |
||
912 | for (k = 0; k * 3 < fz_array_len(obj); k ++) |
||
913 | { |
||
914 | w = fz_to_int(fz_array_get(obj, k * 3 + 0)); |
||
915 | x = fz_to_int(fz_array_get(obj, k * 3 + 1)); |
||
916 | y = fz_to_int(fz_array_get(obj, k * 3 + 2)); |
||
917 | pdf_add_vmtx(fontdesc, c0 + k, c0 + k, x, y, w); |
||
918 | } |
||
919 | i += 2; |
||
920 | } |
||
921 | else |
||
922 | { |
||
923 | c1 = fz_to_int(obj); |
||
924 | w = fz_to_int(fz_array_get(widths, i + 2)); |
||
925 | x = fz_to_int(fz_array_get(widths, i + 3)); |
||
926 | y = fz_to_int(fz_array_get(widths, i + 4)); |
||
927 | pdf_add_vmtx(fontdesc, c0, c1, x, y, w); |
||
928 | i += 5; |
||
929 | } |
||
930 | } |
||
931 | } |
||
932 | |||
933 | pdf_end_vmtx(fontdesc); |
||
934 | } |
||
935 | |||
936 | *fontdescp = fontdesc; |
||
937 | return fz_okay; |
||
938 | |||
939 | cleanup: |
||
940 | pdf_drop_font(fontdesc); |
||
941 | return fz_rethrow(error, "cannot load cid font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); |
||
942 | } |
||
943 | |||
944 | static fz_error |
||
945 | pdf_load_type0_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *dict) |
||
946 | { |
||
947 | fz_error error; |
||
948 | fz_obj *dfonts; |
||
949 | fz_obj *dfont; |
||
950 | fz_obj *subtype; |
||
951 | fz_obj *encoding; |
||
952 | fz_obj *to_unicode; |
||
953 | |||
954 | dfonts = fz_dict_gets(dict, "DescendantFonts"); |
||
955 | if (!dfonts) |
||
956 | return fz_throw("cid font is missing descendant fonts"); |
||
957 | |||
958 | dfont = fz_array_get(dfonts, 0); |
||
959 | |||
960 | subtype = fz_dict_gets(dfont, "Subtype"); |
||
961 | encoding = fz_dict_gets(dict, "Encoding"); |
||
962 | to_unicode = fz_dict_gets(dict, "ToUnicode"); |
||
963 | |||
964 | if (fz_is_name(subtype) && !strcmp(fz_to_name(subtype), "CIDFontType0")) |
||
965 | error = load_cid_font(fontdescp, xref, dfont, encoding, to_unicode); |
||
966 | else if (fz_is_name(subtype) && !strcmp(fz_to_name(subtype), "CIDFontType2")) |
||
967 | error = load_cid_font(fontdescp, xref, dfont, encoding, to_unicode); |
||
968 | else |
||
969 | error = fz_throw("syntaxerror: unknown cid font type"); |
||
970 | if (error) |
||
971 | return fz_rethrow(error, "cannot load descendant font (%d %d R)", fz_to_num(dfont), fz_to_gen(dfont)); |
||
972 | |||
973 | return fz_okay; |
||
974 | } |
||
975 | |||
976 | /* |
||
977 | * FontDescriptor |
||
978 | */ |
||
979 | |||
980 | static fz_error |
||
981 | pdf_load_font_descriptor(pdf_font_desc *fontdesc, pdf_xref *xref, fz_obj *dict, char *collection, char *basefont) |
||
982 | { |
||
983 | fz_error error; |
||
984 | fz_obj *obj1, *obj2, *obj3, *obj; |
||
985 | char *fontname; |
||
986 | char *origname; |
||
987 | FT_Face face; |
||
988 | |||
989 | if (!strchr(basefont, ',') || strchr(basefont, '+')) |
||
990 | origname = fz_to_name(fz_dict_gets(dict, "FontName")); |
||
991 | else |
||
992 | origname = basefont; |
||
993 | fontname = clean_font_name(origname); |
||
994 | |||
995 | fontdesc->flags = fz_to_int(fz_dict_gets(dict, "Flags")); |
||
996 | fontdesc->italic_angle = fz_to_real(fz_dict_gets(dict, "ItalicAngle")); |
||
997 | fontdesc->ascent = fz_to_real(fz_dict_gets(dict, "Ascent")); |
||
998 | fontdesc->descent = fz_to_real(fz_dict_gets(dict, "Descent")); |
||
999 | fontdesc->cap_height = fz_to_real(fz_dict_gets(dict, "CapHeight")); |
||
1000 | fontdesc->x_height = fz_to_real(fz_dict_gets(dict, "XHeight")); |
||
1001 | fontdesc->missing_width = fz_to_real(fz_dict_gets(dict, "MissingWidth")); |
||
1002 | |||
1003 | obj1 = fz_dict_gets(dict, "FontFile"); |
||
1004 | obj2 = fz_dict_gets(dict, "FontFile2"); |
||
1005 | obj3 = fz_dict_gets(dict, "FontFile3"); |
||
1006 | obj = obj1 ? obj1 : obj2 ? obj2 : obj3; |
||
1007 | |||
1008 | if (fz_is_indirect(obj)) |
||
1009 | { |
||
1010 | error = pdf_load_embedded_font(fontdesc, xref, obj); |
||
1011 | if (error) |
||
1012 | { |
||
1013 | fz_catch(error, "ignored error when loading embedded font, attempting to load system font"); |
||
1014 | if (origname != fontname) |
||
1015 | error = pdf_load_builtin_font(fontdesc, fontname); |
||
1016 | else |
||
1017 | error = pdf_load_system_font(fontdesc, fontname, collection); |
||
1018 | if (error) |
||
1019 | return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); |
||
1020 | } |
||
1021 | } |
||
1022 | else |
||
1023 | { |
||
1024 | if (origname != fontname) |
||
1025 | error = pdf_load_builtin_font(fontdesc, fontname); |
||
1026 | else |
||
1027 | error = pdf_load_system_font(fontdesc, fontname, collection); |
||
1028 | if (error) |
||
1029 | return fz_rethrow(error, "cannot load font descriptor (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); |
||
1030 | } |
||
1031 | |||
1032 | fz_strlcpy(fontdesc->font->name, fontname, sizeof fontdesc->font->name); |
||
1033 | |||
1034 | /* Check for DynaLab fonts that must use hinting */ |
||
1035 | face = fontdesc->font->ft_face; |
||
1036 | if (ft_kind(face) == TRUETYPE) |
||
1037 | { |
||
1038 | if (FT_IS_TRICKY(face) || is_dynalab(fontdesc->font->name)) |
||
1039 | fontdesc->font->ft_hint = 1; |
||
1040 | } |
||
1041 | |||
1042 | return fz_okay; |
||
1043 | |||
1044 | } |
||
1045 | |||
1046 | static void |
||
1047 | pdf_make_width_table(pdf_font_desc *fontdesc) |
||
1048 | { |
||
1049 | fz_font *font = fontdesc->font; |
||
1050 | int i, k, cid, gid; |
||
1051 | |||
1052 | font->width_count = 0; |
||
1053 | for (i = 0; i < fontdesc->hmtx_len; i++) |
||
1054 | { |
||
1055 | for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) |
||
1056 | { |
||
1057 | cid = pdf_lookup_cmap(fontdesc->encoding, k); |
||
1058 | gid = pdf_font_cid_to_gid(fontdesc, cid); |
||
1059 | if (gid > font->width_count) |
||
1060 | font->width_count = gid; |
||
1061 | } |
||
1062 | } |
||
1063 | font->width_count ++; |
||
1064 | |||
1065 | font->width_table = fz_calloc(font->width_count, sizeof(int)); |
||
1066 | memset(font->width_table, 0, sizeof(int) * font->width_count); |
||
1067 | |||
1068 | for (i = 0; i < fontdesc->hmtx_len; i++) |
||
1069 | { |
||
1070 | for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++) |
||
1071 | { |
||
1072 | cid = pdf_lookup_cmap(fontdesc->encoding, k); |
||
1073 | gid = pdf_font_cid_to_gid(fontdesc, cid); |
||
1074 | if (gid >= 0 && gid < font->width_count) |
||
1075 | font->width_table[gid] = fontdesc->hmtx[i].w; |
||
1076 | } |
||
1077 | } |
||
1078 | } |
||
1079 | |||
1080 | fz_error |
||
1081 | pdf_load_font(pdf_font_desc **fontdescp, pdf_xref *xref, fz_obj *rdb, fz_obj *dict) |
||
1082 | { |
||
1083 | fz_error error; |
||
1084 | char *subtype; |
||
1085 | fz_obj *dfonts; |
||
1086 | fz_obj *charprocs; |
||
1087 | |||
1088 | if ((*fontdescp = pdf_find_item(xref->store, pdf_drop_font, dict))) |
||
1089 | { |
||
1090 | pdf_keep_font(*fontdescp); |
||
1091 | return fz_okay; |
||
1092 | } |
||
1093 | |||
1094 | subtype = fz_to_name(fz_dict_gets(dict, "Subtype")); |
||
1095 | dfonts = fz_dict_gets(dict, "DescendantFonts"); |
||
1096 | charprocs = fz_dict_gets(dict, "CharProcs"); |
||
1097 | |||
1098 | if (subtype && !strcmp(subtype, "Type0")) |
||
1099 | error = pdf_load_type0_font(fontdescp, xref, dict); |
||
1100 | else if (subtype && !strcmp(subtype, "Type1")) |
||
1101 | error = pdf_load_simple_font(fontdescp, xref, dict); |
||
1102 | else if (subtype && !strcmp(subtype, "MMType1")) |
||
1103 | error = pdf_load_simple_font(fontdescp, xref, dict); |
||
1104 | else if (subtype && !strcmp(subtype, "TrueType")) |
||
1105 | error = pdf_load_simple_font(fontdescp, xref, dict); |
||
1106 | else if (subtype && !strcmp(subtype, "Type3")) |
||
1107 | error = pdf_load_type3_font(fontdescp, xref, rdb, dict); |
||
1108 | else if (charprocs) |
||
1109 | { |
||
1110 | fz_warn("unknown font format, guessing type3."); |
||
1111 | error = pdf_load_type3_font(fontdescp, xref, rdb, dict); |
||
1112 | } |
||
1113 | else if (dfonts) |
||
1114 | { |
||
1115 | fz_warn("unknown font format, guessing type0."); |
||
1116 | error = pdf_load_type0_font(fontdescp, xref, dict); |
||
1117 | } |
||
1118 | else |
||
1119 | { |
||
1120 | fz_warn("unknown font format, guessing type1 or truetype."); |
||
1121 | error = pdf_load_simple_font(fontdescp, xref, dict); |
||
1122 | } |
||
1123 | if (error) |
||
1124 | return fz_rethrow(error, "cannot load font (%d %d R)", fz_to_num(dict), fz_to_gen(dict)); |
||
1125 | |||
1126 | /* Save the widths to stretch non-CJK substitute fonts */ |
||
1127 | if ((*fontdescp)->font->ft_substitute && !(*fontdescp)->to_ttf_cmap) |
||
1128 | pdf_make_width_table(*fontdescp); |
||
1129 | |||
1130 | pdf_store_item(xref->store, pdf_keep_font, pdf_drop_font, dict, *fontdescp); |
||
1131 | |||
1132 | return fz_okay; |
||
1133 | } |
||
1134 | |||
1135 | void |
||
1136 | pdf_debug_font(pdf_font_desc *fontdesc) |
||
1137 | { |
||
1138 | int i; |
||
1139 | |||
1140 | printf("fontdesc {\n"); |
||
1141 | |||
1142 | if (fontdesc->font->ft_face) |
||
1143 | printf("\tfreetype font\n"); |
||
1144 | if (fontdesc->font->t3procs) |
||
1145 | printf("\ttype3 font\n"); |
||
1146 | |||
1147 | printf("\twmode %d\n", fontdesc->wmode); |
||
1148 | printf("\tDW %d\n", fontdesc->dhmtx.w); |
||
1149 | |||
1150 | printf("\tW {\n"); |
||
1151 | for (i = 0; i < fontdesc->hmtx_len; i++) |
||
1152 | printf("\t\t<%04x> <%04x> %d\n", |
||
1153 | fontdesc->hmtx[i].lo, fontdesc->hmtx[i].hi, fontdesc->hmtx[i].w); |
||
1154 | printf("\t}\n"); |
||
1155 | |||
1156 | if (fontdesc->wmode) |
||
1157 | { |
||
1158 | printf("\tDW2 [%d %d]\n", fontdesc->dvmtx.y, fontdesc->dvmtx.w); |
||
1159 | printf("\tW2 {\n"); |
||
1160 | for (i = 0; i < fontdesc->vmtx_len; i++) |
||
1161 | printf("\t\t<%04x> <%04x> %d %d %d\n", fontdesc->vmtx[i].lo, fontdesc->vmtx[i].hi, |
||
1162 | fontdesc->vmtx[i].x, fontdesc->vmtx[i].y, fontdesc->vmtx[i].w); |
||
1163 | printf("\t}\n"); |
||
1164 | } |
||
1165 | }%04x>%04x>>%04x>%04x>>>=>>=>>>>>>><>>>>>>>=>>>>>>>>>>> |