Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
Download
7639 views
1
#include "mupdf/pdf.h"
2
3
#include <ft2build.h>
4
#include FT_FREETYPE_H
5
#include FT_XFREE86_H
6
7
static void pdf_load_font_descriptor(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, pdf_obj *dict, char *collection, char *basefont, int iscidfont);
8
9
static const char *base_font_names[][10] =
10
{
11
{ "Courier", "CourierNew", "CourierNewPSMT", NULL },
12
{ "Courier-Bold", "CourierNew,Bold", "Courier,Bold",
13
"CourierNewPS-BoldMT", "CourierNew-Bold", NULL },
14
{ "Courier-Oblique", "CourierNew,Italic", "Courier,Italic",
15
"CourierNewPS-ItalicMT", "CourierNew-Italic", NULL },
16
{ "Courier-BoldOblique", "CourierNew,BoldItalic", "Courier,BoldItalic",
17
"CourierNewPS-BoldItalicMT", "CourierNew-BoldItalic", NULL },
18
{ "Helvetica", "ArialMT", "Arial", NULL },
19
{ "Helvetica-Bold", "Arial-BoldMT", "Arial,Bold", "Arial-Bold",
20
"Helvetica,Bold", NULL },
21
{ "Helvetica-Oblique", "Arial-ItalicMT", "Arial,Italic", "Arial-Italic",
22
"Helvetica,Italic", "Helvetica-Italic", NULL },
23
{ "Helvetica-BoldOblique", "Arial-BoldItalicMT",
24
"Arial,BoldItalic", "Arial-BoldItalic",
25
"Helvetica,BoldItalic", "Helvetica-BoldItalic", NULL },
26
{ "Times-Roman", "TimesNewRomanPSMT", "TimesNewRoman",
27
"TimesNewRomanPS", NULL },
28
{ "Times-Bold", "TimesNewRomanPS-BoldMT", "TimesNewRoman,Bold",
29
"TimesNewRomanPS-Bold", "TimesNewRoman-Bold", NULL },
30
{ "Times-Italic", "TimesNewRomanPS-ItalicMT", "TimesNewRoman,Italic",
31
"TimesNewRomanPS-Italic", "TimesNewRoman-Italic", NULL },
32
{ "Times-BoldItalic", "TimesNewRomanPS-BoldItalicMT",
33
"TimesNewRoman,BoldItalic", "TimesNewRomanPS-BoldItalic",
34
"TimesNewRoman-BoldItalic", NULL },
35
{ "Symbol", "Symbol,Italic", "Symbol,Bold", "Symbol,BoldItalic",
36
"SymbolMT", "SymbolMT,Italic", "SymbolMT,Bold", "SymbolMT,BoldItalic", 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(const char *a, const 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 const char *clean_font_name(const char *fontname)
73
{
74
int i, k;
75
for (i = 0; i < nelem(base_font_names); 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
{
90
const char *kind = FT_Get_X11_Font_Format(face);
91
if (!strcmp(kind, "TrueType"))
92
return TRUETYPE;
93
if (!strcmp(kind, "Type 1"))
94
return TYPE1;
95
if (!strcmp(kind, "CFF"))
96
return TYPE1;
97
if (!strcmp(kind, "CID Type 1"))
98
return TYPE1;
99
return UNKNOWN;
100
}
101
102
static int ft_is_bold(FT_Face face)
103
{
104
return face->style_flags & FT_STYLE_FLAG_BOLD;
105
}
106
107
static int ft_is_italic(FT_Face face)
108
{
109
return face->style_flags & FT_STYLE_FLAG_ITALIC;
110
}
111
112
static int ft_char_index(FT_Face face, int cid)
113
{
114
int gid = FT_Get_Char_Index(face, cid);
115
if (gid == 0)
116
gid = FT_Get_Char_Index(face, 0xf000 + cid);
117
118
/* some chinese fonts only ship the similarly looking 0x2026 */
119
if (gid == 0 && cid == 0x22ef)
120
gid = FT_Get_Char_Index(face, 0x2026);
121
122
return gid;
123
}
124
125
static int ft_cid_to_gid(pdf_font_desc *fontdesc, int cid)
126
{
127
if (fontdesc->to_ttf_cmap)
128
{
129
cid = pdf_lookup_cmap(fontdesc->to_ttf_cmap, cid);
130
return ft_char_index(fontdesc->font->ft_face, cid);
131
}
132
133
if (fontdesc->cid_to_gid && cid < fontdesc->cid_to_gid_len && cid >= 0)
134
return fontdesc->cid_to_gid[cid];
135
136
return cid;
137
}
138
139
int
140
pdf_font_cid_to_gid(fz_context *ctx, pdf_font_desc *fontdesc, int cid)
141
{
142
if (fontdesc->font->ft_face)
143
return ft_cid_to_gid(fontdesc, cid);
144
return cid;
145
}
146
147
static int ft_width(fz_context *ctx, pdf_font_desc *fontdesc, int cid)
148
{
149
int gid = ft_cid_to_gid(fontdesc, cid);
150
int fterr;
151
152
fterr = FT_Load_Glyph(fontdesc->font->ft_face, gid,
153
FT_LOAD_NO_HINTING | FT_LOAD_NO_BITMAP | FT_LOAD_IGNORE_TRANSFORM);
154
if (fterr)
155
{
156
fz_warn(ctx, "freetype load glyph (gid %d): %s", gid, ft_error_string(fterr));
157
return 0;
158
}
159
return ((FT_Face)fontdesc->font->ft_face)->glyph->advance.x;
160
}
161
162
static int lookup_mre_code(char *name)
163
{
164
int i;
165
for (i = 0; i < 256; i++)
166
if (pdf_mac_roman[i] && !strcmp(name, pdf_mac_roman[i]))
167
return i;
168
return -1;
169
}
170
171
/*
172
* Load font files.
173
*/
174
175
static void
176
pdf_load_builtin_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, int has_descriptor)
177
{
178
FT_Face face;
179
const char *clean_name = clean_font_name(fontname);
180
181
fontdesc->font = fz_load_system_font(ctx, fontname, 0, 0, !has_descriptor);
182
if (!fontdesc->font)
183
{
184
unsigned char *data;
185
unsigned int len;
186
187
data = pdf_lookup_builtin_font(ctx, clean_name, &len);
188
if (!data)
189
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find builtin font: '%s'", fontname);
190
191
fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1);
192
}
193
194
if (!strcmp(clean_name, "Symbol") || !strcmp(clean_name, "ZapfDingbats"))
195
fontdesc->flags |= PDF_FD_SYMBOLIC;
196
197
face = fontdesc->font->ft_face;
198
fontdesc->ascent = 1000.0f * face->ascender / face->units_per_EM;
199
fontdesc->descent = 1000.0f * face->descender / face->units_per_EM;
200
}
201
202
static void
203
pdf_load_substitute_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, int mono, int serif, int bold, int italic)
204
{
205
fontdesc->font = fz_load_system_font(ctx, fontname, bold, italic, 0);
206
if (!fontdesc->font)
207
{
208
unsigned char *data;
209
unsigned int len;
210
211
data = pdf_lookup_substitute_font(ctx, mono, serif, bold, italic, &len);
212
if (!data)
213
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find substitute font");
214
215
fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, 0, 1);
216
fontdesc->font->ft_bold = bold && !ft_is_bold(fontdesc->font->ft_face);
217
fontdesc->font->ft_italic = italic && !ft_is_italic(fontdesc->font->ft_face);
218
}
219
220
fontdesc->font->ft_substitute = 1;
221
}
222
223
static void
224
pdf_load_substitute_cjk_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, int ros, int serif)
225
{
226
fontdesc->font = fz_load_system_cjk_font(ctx, fontname, ros, serif);
227
if (!fontdesc->font)
228
{
229
unsigned char *data;
230
unsigned int len;
231
int index;
232
233
data = pdf_lookup_substitute_cjk_font(ctx, ros, serif, fontdesc->wmode, &len, &index);
234
if (!data)
235
fz_throw(ctx, FZ_ERROR_GENERIC, "cannot find builtin CJK font");
236
237
/* A glyph bbox cache is too big for CJK fonts. */
238
fontdesc->font = fz_new_font_from_memory(ctx, fontname, data, len, index, 0);
239
}
240
241
fontdesc->font->ft_substitute = 1;
242
}
243
244
static void
245
pdf_load_system_font(fz_context *ctx, pdf_font_desc *fontdesc, char *fontname, char *collection)
246
{
247
int bold = 0;
248
int italic = 0;
249
int serif = 0;
250
int mono = 0;
251
252
if (strstr(fontname, "Bold"))
253
bold = 1;
254
if (strstr(fontname, "Italic"))
255
italic = 1;
256
if (strstr(fontname, "Oblique"))
257
italic = 1;
258
259
if (fontdesc->flags & PDF_FD_FIXED_PITCH)
260
mono = 1;
261
if (fontdesc->flags & PDF_FD_SERIF)
262
serif = 1;
263
if (fontdesc->flags & PDF_FD_ITALIC)
264
italic = 1;
265
if (fontdesc->flags & PDF_FD_FORCE_BOLD)
266
bold = 1;
267
268
if (collection)
269
{
270
if (!strcmp(collection, "Adobe-CNS1"))
271
pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_CNS_1, serif);
272
else if (!strcmp(collection, "Adobe-GB1"))
273
pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_GB_1, serif);
274
else if (!strcmp(collection, "Adobe-Japan1"))
275
pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_JAPAN_1, serif);
276
else if (!strcmp(collection, "Adobe-Korea1"))
277
pdf_load_substitute_cjk_font(ctx, fontdesc, fontname, FZ_ADOBE_KOREA_1, serif);
278
else
279
{
280
if (strcmp(collection, "Adobe-Identity") != 0)
281
fz_warn(ctx, "unknown cid collection: %s", collection);
282
pdf_load_substitute_font(ctx, fontdesc, fontname, mono, serif, bold, italic);
283
}
284
}
285
else
286
{
287
pdf_load_substitute_font(ctx, fontdesc, fontname, mono, serif, bold, italic);
288
}
289
}
290
291
static void
292
pdf_load_embedded_font(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, char *fontname, pdf_obj *stmref)
293
{
294
fz_buffer *buf;
295
296
fz_try(ctx)
297
{
298
buf = pdf_load_stream(ctx, doc, pdf_to_num(ctx, stmref), pdf_to_gen(ctx, stmref));
299
}
300
fz_catch(ctx)
301
{
302
fz_rethrow_message(ctx, "cannot load font stream (%d %d R)", pdf_to_num(ctx, stmref), pdf_to_gen(ctx, stmref));
303
}
304
305
fz_try(ctx)
306
{
307
fontdesc->font = fz_new_font_from_buffer(ctx, fontname, buf, 0, 1);
308
}
309
fz_always(ctx)
310
{
311
fz_drop_buffer(ctx, buf);
312
}
313
fz_catch(ctx)
314
{
315
fz_rethrow_message(ctx, "cannot load embedded font (%d %d R)", pdf_to_num(ctx, stmref), pdf_to_gen(ctx, stmref));
316
}
317
fontdesc->size += buf->len;
318
319
fontdesc->is_embedded = 1;
320
}
321
322
/*
323
* Create and destroy
324
*/
325
326
pdf_font_desc *
327
pdf_keep_font(fz_context *ctx, pdf_font_desc *fontdesc)
328
{
329
return (pdf_font_desc *)fz_keep_storable(ctx, &fontdesc->storable);
330
}
331
332
void
333
pdf_drop_font(fz_context *ctx, pdf_font_desc *fontdesc)
334
{
335
fz_drop_storable(ctx, &fontdesc->storable);
336
}
337
338
static void
339
pdf_drop_font_imp(fz_context *ctx, fz_storable *fontdesc_)
340
{
341
pdf_font_desc *fontdesc = (pdf_font_desc *)fontdesc_;
342
343
if (fontdesc->font)
344
fz_drop_font(ctx, fontdesc->font);
345
if (fontdesc->encoding)
346
pdf_drop_cmap(ctx, fontdesc->encoding);
347
if (fontdesc->to_ttf_cmap)
348
pdf_drop_cmap(ctx, fontdesc->to_ttf_cmap);
349
if (fontdesc->to_unicode)
350
pdf_drop_cmap(ctx, fontdesc->to_unicode);
351
fz_free(ctx, fontdesc->cid_to_gid);
352
fz_free(ctx, fontdesc->cid_to_ucs);
353
fz_free(ctx, fontdesc->hmtx);
354
fz_free(ctx, fontdesc->vmtx);
355
fz_free(ctx, fontdesc);
356
}
357
358
pdf_font_desc *
359
pdf_new_font_desc(fz_context *ctx)
360
{
361
pdf_font_desc *fontdesc;
362
363
fontdesc = fz_malloc_struct(ctx, pdf_font_desc);
364
FZ_INIT_STORABLE(fontdesc, 1, pdf_drop_font_imp);
365
fontdesc->size = sizeof(pdf_font_desc);
366
367
fontdesc->font = NULL;
368
369
fontdesc->flags = 0;
370
fontdesc->italic_angle = 0;
371
fontdesc->ascent = 0;
372
fontdesc->descent = 0;
373
fontdesc->cap_height = 0;
374
fontdesc->x_height = 0;
375
fontdesc->missing_width = 0;
376
377
fontdesc->encoding = NULL;
378
fontdesc->to_ttf_cmap = NULL;
379
fontdesc->cid_to_gid_len = 0;
380
fontdesc->cid_to_gid = NULL;
381
382
fontdesc->to_unicode = NULL;
383
fontdesc->cid_to_ucs_len = 0;
384
fontdesc->cid_to_ucs = NULL;
385
386
fontdesc->wmode = 0;
387
388
fontdesc->hmtx_cap = 0;
389
fontdesc->vmtx_cap = 0;
390
fontdesc->hmtx_len = 0;
391
fontdesc->vmtx_len = 0;
392
fontdesc->hmtx = NULL;
393
fontdesc->vmtx = NULL;
394
395
fontdesc->dhmtx.lo = 0x0000;
396
fontdesc->dhmtx.hi = 0xFFFF;
397
fontdesc->dhmtx.w = 1000;
398
399
fontdesc->dvmtx.lo = 0x0000;
400
fontdesc->dvmtx.hi = 0xFFFF;
401
fontdesc->dvmtx.x = 0;
402
fontdesc->dvmtx.y = 880;
403
fontdesc->dvmtx.w = -1000;
404
405
fontdesc->is_embedded = 0;
406
407
return fontdesc;
408
}
409
410
/*
411
* Simple fonts (Type1 and TrueType)
412
*/
413
414
static pdf_font_desc *
415
pdf_load_simple_font_by_name(fz_context *ctx, pdf_document *doc, pdf_obj *dict, char *basefont)
416
{
417
pdf_obj *descriptor;
418
pdf_obj *encoding;
419
pdf_obj *widths;
420
unsigned short *etable = NULL;
421
pdf_font_desc *fontdesc = NULL;
422
pdf_obj *subtype;
423
FT_Face face;
424
FT_CharMap cmap;
425
int symbolic;
426
int kind;
427
428
char *estrings[256];
429
char ebuffer[256][32];
430
int i, k, n;
431
int fterr;
432
int has_lock = 0;
433
434
fz_var(fontdesc);
435
fz_var(etable);
436
fz_var(has_lock);
437
438
/* Load font file */
439
fz_try(ctx)
440
{
441
fontdesc = pdf_new_font_desc(ctx);
442
443
descriptor = pdf_dict_get(ctx, dict, PDF_NAME_FontDescriptor);
444
if (descriptor)
445
pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, NULL, basefont, 0);
446
else
447
pdf_load_builtin_font(ctx, fontdesc, basefont, 0);
448
449
/* Some chinese documents mistakenly consider WinAnsiEncoding to be codepage 936 */
450
if (descriptor && pdf_is_string(ctx, pdf_dict_get(ctx, descriptor, PDF_NAME_FontName)) &&
451
!pdf_dict_get(ctx, dict, PDF_NAME_ToUnicode) &&
452
pdf_name_eq(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Encoding), PDF_NAME_WinAnsiEncoding) &&
453
pdf_to_int(ctx, pdf_dict_get(ctx, descriptor, PDF_NAME_Flags)) == 4)
454
{
455
char *cp936fonts[] = {
456
"\xCB\xCE\xCC\xE5", "SimSun,Regular",
457
"\xBA\xDA\xCC\xE5", "SimHei,Regular",
458
"\xBF\xAC\xCC\xE5_GB2312", "SimKai,Regular",
459
"\xB7\xC2\xCB\xCE_GB2312", "SimFang,Regular",
460
"\xC1\xA5\xCA\xE9", "SimLi,Regular",
461
NULL
462
};
463
for (i = 0; cp936fonts[i]; i += 2)
464
if (!strcmp(basefont, cp936fonts[i]))
465
break;
466
if (cp936fonts[i])
467
{
468
fz_warn(ctx, "workaround for S22PDF lying about chinese font encodings");
469
pdf_drop_font(ctx, fontdesc);
470
fontdesc = NULL;
471
fontdesc = pdf_new_font_desc(ctx);
472
pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, "Adobe-GB1", cp936fonts[i+1], 0);
473
fontdesc->encoding = pdf_load_system_cmap(ctx, "GBK-EUC-H");
474
fontdesc->to_unicode = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
475
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
476
477
face = fontdesc->font->ft_face;
478
/* kind = ft_kind(face); */
479
goto skip_encoding;
480
}
481
}
482
483
face = fontdesc->font->ft_face;
484
kind = ft_kind(face);
485
486
/* Encoding */
487
488
symbolic = fontdesc->flags & 4;
489
490
if (face->num_charmaps > 0)
491
cmap = face->charmaps[0];
492
else
493
cmap = NULL;
494
495
for (i = 0; i < face->num_charmaps; i++)
496
{
497
FT_CharMap test = face->charmaps[i];
498
499
if (kind == TYPE1)
500
{
501
if (test->platform_id == 7)
502
cmap = test;
503
}
504
505
if (kind == TRUETYPE)
506
{
507
if (test->platform_id == 1 && test->encoding_id == 0)
508
cmap = test;
509
if (test->platform_id == 3 && test->encoding_id == 1)
510
cmap = test;
511
if (symbolic && test->platform_id == 3 && test->encoding_id == 0)
512
cmap = test;
513
}
514
}
515
516
if (cmap)
517
{
518
fterr = FT_Set_Charmap(face, cmap);
519
if (fterr)
520
fz_warn(ctx, "freetype could not set cmap: %s", ft_error_string(fterr));
521
}
522
else
523
fz_warn(ctx, "freetype could not find any cmaps");
524
525
etable = fz_malloc_array(ctx, 256, sizeof(unsigned short));
526
fontdesc->size += 256 * sizeof(unsigned short);
527
for (i = 0; i < 256; i++)
528
{
529
estrings[i] = NULL;
530
etable[i] = 0;
531
}
532
533
encoding = pdf_dict_get(ctx, dict, PDF_NAME_Encoding);
534
if (encoding)
535
{
536
if (pdf_is_name(ctx, encoding))
537
pdf_load_encoding(estrings, pdf_to_name(ctx, encoding));
538
539
if (pdf_is_dict(ctx, encoding))
540
{
541
pdf_obj *base, *diff, *item;
542
543
base = pdf_dict_get(ctx, encoding, PDF_NAME_BaseEncoding);
544
if (pdf_is_name(ctx, base))
545
pdf_load_encoding(estrings, pdf_to_name(ctx, base));
546
else if (!fontdesc->is_embedded && !symbolic)
547
pdf_load_encoding(estrings, "StandardEncoding");
548
549
diff = pdf_dict_get(ctx, encoding, PDF_NAME_Differences);
550
if (pdf_is_array(ctx, diff))
551
{
552
n = pdf_array_len(ctx, diff);
553
k = 0;
554
for (i = 0; i < n; i++)
555
{
556
item = pdf_array_get(ctx, diff, i);
557
if (pdf_is_int(ctx, item))
558
k = pdf_to_int(ctx, item);
559
if (pdf_is_name(ctx, item) && k >= 0 && k < nelem(estrings))
560
estrings[k++] = pdf_to_name(ctx, item);
561
}
562
}
563
}
564
}
565
else if (!fontdesc->is_embedded && !symbolic)
566
pdf_load_encoding(estrings, "StandardEncoding");
567
568
/* start with the builtin encoding */
569
for (i = 0; i < 256; i++)
570
etable[i] = ft_char_index(face, i);
571
572
fz_lock(ctx, FZ_LOCK_FREETYPE);
573
has_lock = 1;
574
575
/* built-in and substitute fonts may be a different type than what the document expects */
576
subtype = pdf_dict_get(ctx, dict, PDF_NAME_Subtype);
577
if (pdf_name_eq(ctx, subtype, PDF_NAME_Type1))
578
kind = TYPE1;
579
else if (pdf_name_eq(ctx, subtype, PDF_NAME_MMType1))
580
kind = TYPE1;
581
else if (pdf_name_eq(ctx, subtype, PDF_NAME_TrueType))
582
kind = TRUETYPE;
583
else if (pdf_name_eq(ctx, subtype, PDF_NAME_CIDFontType0))
584
kind = TYPE1;
585
else if (pdf_name_eq(ctx, subtype, PDF_NAME_CIDFontType2))
586
kind = TRUETYPE;
587
588
/* encode by glyph name where we can */
589
if (kind == TYPE1)
590
{
591
for (i = 0; i < 256; i++)
592
{
593
if (estrings[i])
594
{
595
etable[i] = FT_Get_Name_Index(face, estrings[i]);
596
if (etable[i] == 0)
597
{
598
int aglcode = pdf_lookup_agl(estrings[i]);
599
const char **dupnames = pdf_lookup_agl_duplicates(aglcode);
600
while (*dupnames)
601
{
602
etable[i] = FT_Get_Name_Index(face, (char*)*dupnames);
603
if (etable[i])
604
break;
605
dupnames++;
606
}
607
if (etable[i] == 0)
608
{
609
char buf[10];
610
sprintf(buf, "uni%04X", aglcode);
611
etable[i] = FT_Get_Name_Index(face, buf);
612
}
613
}
614
}
615
}
616
}
617
618
/* encode by glyph name where we can */
619
if (kind == TRUETYPE)
620
{
621
/* Unicode cmap */
622
if (!symbolic && face->charmap && face->charmap->platform_id == 3)
623
{
624
for (i = 0; i < 256; i++)
625
{
626
if (estrings[i])
627
{
628
int aglcode = pdf_lookup_agl(estrings[i]);
629
if (!aglcode)
630
etable[i] = FT_Get_Name_Index(face, estrings[i]);
631
else
632
etable[i] = ft_char_index(face, aglcode);
633
}
634
}
635
}
636
637
/* MacRoman cmap */
638
else if (!symbolic && face->charmap && face->charmap->platform_id == 1)
639
{
640
for (i = 0; i < 256; i++)
641
{
642
if (estrings[i])
643
{
644
k = lookup_mre_code(estrings[i]);
645
if (k <= 0)
646
etable[i] = FT_Get_Name_Index(face, estrings[i]);
647
else
648
etable[i] = ft_char_index(face, k);
649
}
650
}
651
}
652
653
/* Symbolic cmap */
654
else if (!face->charmap || face->charmap->encoding != FT_ENCODING_MS_SYMBOL)
655
{
656
for (i = 0; i < 256; i++)
657
{
658
if (estrings[i])
659
{
660
etable[i] = FT_Get_Name_Index(face, estrings[i]);
661
if (etable[i] == 0)
662
etable[i] = ft_char_index(face, i);
663
}
664
}
665
}
666
}
667
668
/* try to reverse the glyph names from the builtin encoding */
669
for (i = 0; i < 256; i++)
670
{
671
if (etable[i] && !estrings[i])
672
{
673
if (FT_HAS_GLYPH_NAMES(face))
674
{
675
fterr = FT_Get_Glyph_Name(face, etable[i], ebuffer[i], 32);
676
if (fterr)
677
fz_warn(ctx, "freetype get glyph name (gid %d): %s", etable[i], ft_error_string(fterr));
678
if (ebuffer[i][0])
679
estrings[i] = ebuffer[i];
680
}
681
else
682
{
683
estrings[i] = (char*) pdf_win_ansi[i]; /* discard const */
684
}
685
}
686
}
687
688
/* symbolic Type 1 fonts with an implicit encoding and non-standard glyph names */
689
if (kind == TYPE1 && symbolic)
690
{
691
for (i = 0; i < 256; i++)
692
if (etable[i] && estrings[i] && !pdf_lookup_agl(estrings[i]))
693
estrings[i] = (char*) pdf_standard[i];
694
}
695
696
fz_unlock(ctx, FZ_LOCK_FREETYPE);
697
has_lock = 0;
698
699
fontdesc->encoding = pdf_new_identity_cmap(ctx, 0, 1);
700
fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
701
fontdesc->cid_to_gid_len = 256;
702
fontdesc->cid_to_gid = etable;
703
704
fz_try(ctx)
705
{
706
pdf_load_to_unicode(ctx, doc, fontdesc, estrings, NULL, pdf_dict_get(ctx, dict, PDF_NAME_ToUnicode));
707
}
708
fz_catch(ctx)
709
{
710
fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
711
fz_warn(ctx, "cannot load ToUnicode CMap");
712
}
713
714
skip_encoding:
715
716
/* Widths */
717
718
pdf_set_default_hmtx(ctx, fontdesc, fontdesc->missing_width);
719
720
widths = pdf_dict_get(ctx, dict, PDF_NAME_Widths);
721
if (widths)
722
{
723
int first, last;
724
725
first = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_FirstChar));
726
last = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_LastChar));
727
728
if (first < 0 || last > 255 || first > last)
729
first = last = 0;
730
731
for (i = 0; i < last - first + 1; i++)
732
{
733
int wid = pdf_to_int(ctx, pdf_array_get(ctx, widths, i));
734
pdf_add_hmtx(ctx, fontdesc, i + first, i + first, wid);
735
}
736
}
737
else
738
{
739
fz_lock(ctx, FZ_LOCK_FREETYPE);
740
has_lock = 1;
741
fterr = FT_Set_Char_Size(face, 1000, 1000, 72, 72);
742
if (fterr)
743
fz_warn(ctx, "freetype set character size: %s", ft_error_string(fterr));
744
for (i = 0; i < 256; i++)
745
{
746
pdf_add_hmtx(ctx, fontdesc, i, i, ft_width(ctx, fontdesc, i));
747
}
748
fz_unlock(ctx, FZ_LOCK_FREETYPE);
749
has_lock = 0;
750
}
751
752
pdf_end_hmtx(ctx, fontdesc);
753
}
754
fz_catch(ctx)
755
{
756
if (has_lock)
757
fz_unlock(ctx, FZ_LOCK_FREETYPE);
758
if (fontdesc && etable != fontdesc->cid_to_gid)
759
fz_free(ctx, etable);
760
pdf_drop_font(ctx, fontdesc);
761
fz_rethrow_message(ctx, "cannot load simple font (%d %d R)", pdf_to_num(ctx, dict), pdf_to_gen(ctx, dict));
762
}
763
return fontdesc;
764
}
765
766
static pdf_font_desc *
767
pdf_load_simple_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict)
768
{
769
char *basefont = pdf_to_name(ctx, pdf_dict_get(ctx, dict, PDF_NAME_BaseFont));
770
771
return pdf_load_simple_font_by_name(ctx, doc, dict, basefont);
772
}
773
774
static int
775
hail_mary_make_hash_key(fz_context *ctx, fz_store_hash *hash, void *key_)
776
{
777
hash->u.i.i0 = 0;
778
hash->u.i.i1 = 0;
779
hash->u.i.ptr = NULL;
780
return 1;
781
}
782
783
static void *
784
hail_mary_keep_key(fz_context *ctx, void *key)
785
{
786
return key;
787
}
788
789
static void
790
hail_mary_drop_key(fz_context *ctx, void *key)
791
{
792
}
793
794
static int
795
hail_mary_cmp_key(fz_context *ctx, void *k0, void *k1)
796
{
797
return k0 == k1;
798
}
799
800
#ifndef NDEBUG
801
static void
802
hail_mary_debug_key(fz_context *ctx, FILE *out, void *key_)
803
{
804
fprintf(out, "hail mary ");
805
}
806
#endif
807
808
static fz_store_type hail_mary_store_type =
809
{
810
hail_mary_make_hash_key,
811
hail_mary_keep_key,
812
hail_mary_drop_key,
813
hail_mary_cmp_key,
814
#ifndef NDEBUG
815
hail_mary_debug_key
816
#endif
817
};
818
819
pdf_font_desc *
820
pdf_load_hail_mary_font(fz_context *ctx, pdf_document *doc)
821
{
822
pdf_font_desc *fontdesc;
823
pdf_font_desc *existing;
824
825
if ((fontdesc = fz_find_item(ctx, pdf_drop_font_imp, &hail_mary_store_type, &hail_mary_store_type)) != NULL)
826
{
827
return fontdesc;
828
}
829
830
/* FIXME: Get someone with a clue about fonts to fix this */
831
fontdesc = pdf_load_simple_font_by_name(ctx, doc, NULL, "Helvetica");
832
833
existing = fz_store_item(ctx, &hail_mary_store_type, fontdesc, fontdesc->size, &hail_mary_store_type);
834
assert(existing == NULL);
835
836
return fontdesc;
837
}
838
839
/*
840
* CID Fonts
841
*/
842
843
static pdf_font_desc *
844
load_cid_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict, pdf_obj *encoding, pdf_obj *to_unicode)
845
{
846
pdf_obj *widths;
847
pdf_obj *descriptor;
848
pdf_font_desc *fontdesc = NULL;
849
pdf_cmap *cmap;
850
FT_Face face;
851
char collection[256];
852
char *basefont;
853
int i, k, fterr;
854
pdf_obj *cidtogidmap;
855
pdf_obj *obj;
856
int dw;
857
858
fz_var(fontdesc);
859
860
fz_try(ctx)
861
{
862
/* Get font name and CID collection */
863
864
basefont = pdf_to_name(ctx, pdf_dict_get(ctx, dict, PDF_NAME_BaseFont));
865
866
{
867
pdf_obj *cidinfo;
868
char tmpstr[64];
869
int tmplen;
870
871
cidinfo = pdf_dict_get(ctx, dict, PDF_NAME_CIDSystemInfo);
872
if (!cidinfo)
873
fz_throw(ctx, FZ_ERROR_GENERIC, "cid font is missing info");
874
875
obj = pdf_dict_get(ctx, cidinfo, PDF_NAME_Registry);
876
tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(ctx, obj));
877
memcpy(tmpstr, pdf_to_str_buf(ctx, obj), tmplen);
878
tmpstr[tmplen] = '\0';
879
fz_strlcpy(collection, tmpstr, sizeof collection);
880
881
fz_strlcat(collection, "-", sizeof collection);
882
883
obj = pdf_dict_get(ctx, cidinfo, PDF_NAME_Ordering);
884
tmplen = fz_mini(sizeof tmpstr - 1, pdf_to_str_len(ctx, obj));
885
memcpy(tmpstr, pdf_to_str_buf(ctx, obj), tmplen);
886
tmpstr[tmplen] = '\0';
887
fz_strlcat(collection, tmpstr, sizeof collection);
888
}
889
890
/* Encoding */
891
892
if (pdf_is_name(ctx, encoding))
893
{
894
if (pdf_name_eq(ctx, encoding, PDF_NAME_Identity_H))
895
cmap = pdf_new_identity_cmap(ctx, 0, 2);
896
else if (pdf_name_eq(ctx, encoding, PDF_NAME_Identity_V))
897
cmap = pdf_new_identity_cmap(ctx, 1, 2);
898
else
899
cmap = pdf_load_system_cmap(ctx, pdf_to_name(ctx, encoding));
900
}
901
else if (pdf_is_indirect(ctx, encoding))
902
{
903
cmap = pdf_load_embedded_cmap(ctx, doc, encoding);
904
}
905
else
906
{
907
fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: font missing encoding");
908
}
909
910
/* Load font file */
911
912
fontdesc = pdf_new_font_desc(ctx);
913
914
fontdesc->encoding = cmap;
915
fontdesc->size += pdf_cmap_size(ctx, fontdesc->encoding);
916
917
pdf_set_font_wmode(ctx, fontdesc, pdf_cmap_wmode(ctx, fontdesc->encoding));
918
919
descriptor = pdf_dict_get(ctx, dict, PDF_NAME_FontDescriptor);
920
if (!descriptor)
921
fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: missing font descriptor");
922
pdf_load_font_descriptor(ctx, doc, fontdesc, descriptor, collection, basefont, 1);
923
924
face = fontdesc->font->ft_face;
925
926
/* Apply encoding */
927
928
cidtogidmap = pdf_dict_get(ctx, dict, PDF_NAME_CIDToGIDMap);
929
if (pdf_is_indirect(ctx, cidtogidmap))
930
{
931
fz_buffer *buf;
932
933
buf = pdf_load_stream(ctx, doc, pdf_to_num(ctx, cidtogidmap), pdf_to_gen(ctx, cidtogidmap));
934
935
fontdesc->cid_to_gid_len = (buf->len) / 2;
936
fontdesc->cid_to_gid = fz_malloc_array(ctx, fontdesc->cid_to_gid_len, sizeof(unsigned short));
937
fontdesc->size += fontdesc->cid_to_gid_len * sizeof(unsigned short);
938
for (i = 0; i < fontdesc->cid_to_gid_len; i++)
939
fontdesc->cid_to_gid[i] = (buf->data[i * 2] << 8) + buf->data[i * 2 + 1];
940
941
fz_drop_buffer(ctx, buf);
942
}
943
944
/* if font is external, cidtogidmap should not be identity */
945
/* so we map from cid to unicode and then map that through the (3 1) */
946
/* unicode cmap to get a glyph id */
947
else if (fontdesc->font->ft_substitute)
948
{
949
fterr = FT_Select_Charmap(face, ft_encoding_unicode);
950
if (fterr)
951
{
952
fz_throw(ctx, FZ_ERROR_GENERIC, "fonterror: no unicode cmap when emulating CID font: %s", ft_error_string(fterr));
953
}
954
955
if (!strcmp(collection, "Adobe-CNS1"))
956
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-CNS1-UCS2");
957
else if (!strcmp(collection, "Adobe-GB1"))
958
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-GB1-UCS2");
959
else if (!strcmp(collection, "Adobe-Japan1"))
960
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan1-UCS2");
961
else if (!strcmp(collection, "Adobe-Japan2"))
962
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Japan2-UCS2");
963
else if (!strcmp(collection, "Adobe-Korea1"))
964
fontdesc->to_ttf_cmap = pdf_load_system_cmap(ctx, "Adobe-Korea1-UCS2");
965
}
966
967
pdf_load_to_unicode(ctx, doc, fontdesc, NULL, collection, to_unicode);
968
969
/* If we have an identity encoding, we're supposed to use the glyph ids directly.
970
* If we only have a substitute font, that won't work.
971
* Make a last ditch attempt by using
972
* the ToUnicode table if it exists to map via the substitute font's cmap. */
973
if (strstr(fontdesc->encoding->cmap_name, "Identity-") && fontdesc->font->ft_substitute)
974
{
975
fz_warn(ctx, "non-embedded font using identity encoding: %s", basefont);
976
if (fontdesc->to_unicode && !fontdesc->to_ttf_cmap)
977
fontdesc->to_ttf_cmap = pdf_keep_cmap(ctx, fontdesc->to_unicode);
978
}
979
980
/* Horizontal */
981
982
dw = 1000;
983
obj = pdf_dict_get(ctx, dict, PDF_NAME_DW);
984
if (obj)
985
dw = pdf_to_int(ctx, obj);
986
pdf_set_default_hmtx(ctx, fontdesc, dw);
987
988
widths = pdf_dict_get(ctx, dict, PDF_NAME_W);
989
if (widths)
990
{
991
int c0, c1, w, n, m;
992
993
n = pdf_array_len(ctx, widths);
994
for (i = 0; i < n; )
995
{
996
c0 = pdf_to_int(ctx, pdf_array_get(ctx, widths, i));
997
obj = pdf_array_get(ctx, widths, i + 1);
998
if (pdf_is_array(ctx, obj))
999
{
1000
m = pdf_array_len(ctx, obj);
1001
for (k = 0; k < m; k++)
1002
{
1003
w = pdf_to_int(ctx, pdf_array_get(ctx, obj, k));
1004
pdf_add_hmtx(ctx, fontdesc, c0 + k, c0 + k, w);
1005
}
1006
i += 2;
1007
}
1008
else
1009
{
1010
c1 = pdf_to_int(ctx, obj);
1011
w = pdf_to_int(ctx, pdf_array_get(ctx, widths, i + 2));
1012
pdf_add_hmtx(ctx, fontdesc, c0, c1, w);
1013
i += 3;
1014
}
1015
}
1016
}
1017
1018
pdf_end_hmtx(ctx, fontdesc);
1019
1020
/* Vertical */
1021
1022
if (pdf_cmap_wmode(ctx, fontdesc->encoding) == 1)
1023
{
1024
int dw2y = 880;
1025
int dw2w = -1000;
1026
1027
obj = pdf_dict_get(ctx, dict, PDF_NAME_DW2);
1028
if (obj)
1029
{
1030
dw2y = pdf_to_int(ctx, pdf_array_get(ctx, obj, 0));
1031
dw2w = pdf_to_int(ctx, pdf_array_get(ctx, obj, 1));
1032
}
1033
1034
pdf_set_default_vmtx(ctx, fontdesc, dw2y, dw2w);
1035
1036
widths = pdf_dict_get(ctx, dict, PDF_NAME_W2);
1037
if (widths)
1038
{
1039
int c0, c1, w, x, y, n;
1040
1041
n = pdf_array_len(ctx, widths);
1042
for (i = 0; i < n; )
1043
{
1044
c0 = pdf_to_int(ctx, pdf_array_get(ctx, widths, i));
1045
obj = pdf_array_get(ctx, widths, i + 1);
1046
if (pdf_is_array(ctx, obj))
1047
{
1048
int m = pdf_array_len(ctx, obj);
1049
for (k = 0; k * 3 < m; k ++)
1050
{
1051
w = pdf_to_int(ctx, pdf_array_get(ctx, obj, k * 3 + 0));
1052
x = pdf_to_int(ctx, pdf_array_get(ctx, obj, k * 3 + 1));
1053
y = pdf_to_int(ctx, pdf_array_get(ctx, obj, k * 3 + 2));
1054
pdf_add_vmtx(ctx, fontdesc, c0 + k, c0 + k, x, y, w);
1055
}
1056
i += 2;
1057
}
1058
else
1059
{
1060
c1 = pdf_to_int(ctx, obj);
1061
w = pdf_to_int(ctx, pdf_array_get(ctx, widths, i + 2));
1062
x = pdf_to_int(ctx, pdf_array_get(ctx, widths, i + 3));
1063
y = pdf_to_int(ctx, pdf_array_get(ctx, widths, i + 4));
1064
pdf_add_vmtx(ctx, fontdesc, c0, c1, x, y, w);
1065
i += 5;
1066
}
1067
}
1068
}
1069
1070
pdf_end_vmtx(ctx, fontdesc);
1071
}
1072
}
1073
fz_catch(ctx)
1074
{
1075
pdf_drop_font(ctx, fontdesc);
1076
fz_rethrow_message(ctx, "cannot load cid font (%d %d R)", pdf_to_num(ctx, dict), pdf_to_gen(ctx, dict));
1077
}
1078
1079
return fontdesc;
1080
}
1081
1082
static pdf_font_desc *
1083
pdf_load_type0_font(fz_context *ctx, pdf_document *doc, pdf_obj *dict)
1084
{
1085
pdf_obj *dfonts;
1086
pdf_obj *dfont;
1087
pdf_obj *subtype;
1088
pdf_obj *encoding;
1089
pdf_obj *to_unicode;
1090
1091
dfonts = pdf_dict_get(ctx, dict, PDF_NAME_DescendantFonts);
1092
if (!dfonts)
1093
fz_throw(ctx, FZ_ERROR_GENERIC, "cid font is missing descendant fonts");
1094
1095
dfont = pdf_array_get(ctx, dfonts, 0);
1096
1097
subtype = pdf_dict_get(ctx, dfont, PDF_NAME_Subtype);
1098
encoding = pdf_dict_get(ctx, dict, PDF_NAME_Encoding);
1099
to_unicode = pdf_dict_get(ctx, dict, PDF_NAME_ToUnicode);
1100
1101
if (pdf_is_name(ctx, subtype) && pdf_name_eq(ctx, subtype, PDF_NAME_CIDFontType0))
1102
return load_cid_font(ctx, doc, dfont, encoding, to_unicode);
1103
if (pdf_is_name(ctx, subtype) && pdf_name_eq(ctx, subtype, PDF_NAME_CIDFontType2))
1104
return load_cid_font(ctx, doc, dfont, encoding, to_unicode);
1105
fz_throw(ctx, FZ_ERROR_GENERIC, "syntaxerror: unknown cid font type");
1106
}
1107
1108
/*
1109
* FontDescriptor
1110
*/
1111
1112
static void
1113
pdf_load_font_descriptor(fz_context *ctx, pdf_document *doc, pdf_font_desc *fontdesc, pdf_obj *dict, char *collection, char *basefont, int iscidfont)
1114
{
1115
pdf_obj *obj1, *obj2, *obj3, *obj;
1116
char *fontname;
1117
FT_Face face;
1118
1119
/* Prefer BaseFont; don't bother with FontName */
1120
fontname = basefont;
1121
1122
fontdesc->flags = pdf_to_int(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Flags));
1123
fontdesc->italic_angle = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_ItalicAngle));
1124
fontdesc->ascent = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Ascent));
1125
fontdesc->descent = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_Descent));
1126
fontdesc->cap_height = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_CapHeight));
1127
fontdesc->x_height = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_XHeight));
1128
fontdesc->missing_width = pdf_to_real(ctx, pdf_dict_get(ctx, dict, PDF_NAME_MissingWidth));
1129
1130
obj1 = pdf_dict_get(ctx, dict, PDF_NAME_FontFile);
1131
obj2 = pdf_dict_get(ctx, dict, PDF_NAME_FontFile2);
1132
obj3 = pdf_dict_get(ctx, dict, PDF_NAME_FontFile3);
1133
obj = obj1 ? obj1 : obj2 ? obj2 : obj3;
1134
1135
if (pdf_is_indirect(ctx, obj))
1136
{
1137
fz_try(ctx)
1138
{
1139
pdf_load_embedded_font(ctx, doc, fontdesc, fontname, obj);
1140
}
1141
fz_catch(ctx)
1142
{
1143
fz_rethrow_if(ctx, FZ_ERROR_TRYLATER);
1144
fz_warn(ctx, "ignored error when loading embedded font; attempting to load system font");
1145
if (!iscidfont && fontname != clean_font_name(fontname))
1146
pdf_load_builtin_font(ctx, fontdesc, fontname, 1);
1147
else
1148
pdf_load_system_font(ctx, fontdesc, fontname, collection);
1149
}
1150
}
1151
else
1152
{
1153
if (!iscidfont && fontname != clean_font_name(fontname))
1154
pdf_load_builtin_font(ctx, fontdesc, fontname, 1);
1155
else
1156
pdf_load_system_font(ctx, fontdesc, fontname, collection);
1157
}
1158
1159
/* Check for DynaLab fonts that must use hinting */
1160
face = fontdesc->font->ft_face;
1161
if (ft_kind(face) == TRUETYPE)
1162
{
1163
if (FT_IS_TRICKY(face) || is_dynalab(fontdesc->font->name))
1164
fontdesc->font->ft_hint = 1;
1165
1166
if (fontdesc->ascent == 0.0f)
1167
fontdesc->ascent = 1000.0f * face->ascender / face->units_per_EM;
1168
1169
if (fontdesc->descent == 0.0f)
1170
fontdesc->descent = 1000.0f * face->descender / face->units_per_EM;
1171
}
1172
}
1173
1174
static void
1175
pdf_make_width_table(fz_context *ctx, pdf_font_desc *fontdesc)
1176
{
1177
fz_font *font = fontdesc->font;
1178
int i, k, n, cid, gid;
1179
1180
n = 0;
1181
for (i = 0; i < fontdesc->hmtx_len; i++)
1182
{
1183
for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++)
1184
{
1185
cid = pdf_lookup_cmap(fontdesc->encoding, k);
1186
gid = pdf_font_cid_to_gid(ctx, fontdesc, cid);
1187
if (gid > n)
1188
n = gid;
1189
}
1190
};
1191
1192
font->width_count = n + 1;
1193
font->width_table = fz_malloc_array(ctx, font->width_count, sizeof(int));
1194
memset(font->width_table, 0, font->width_count * sizeof(int));
1195
fontdesc->size += font->width_count * sizeof(int);
1196
1197
for (i = 0; i < fontdesc->hmtx_len; i++)
1198
{
1199
for (k = fontdesc->hmtx[i].lo; k <= fontdesc->hmtx[i].hi; k++)
1200
{
1201
cid = pdf_lookup_cmap(fontdesc->encoding, k);
1202
gid = pdf_font_cid_to_gid(ctx, fontdesc, cid);
1203
if (gid >= 0 && gid < font->width_count)
1204
font->width_table[gid] = fz_maxi(fontdesc->hmtx[i].w, font->width_table[gid]);
1205
}
1206
}
1207
}
1208
1209
pdf_font_desc *
1210
pdf_load_font(fz_context *ctx, pdf_document *doc, pdf_obj *rdb, pdf_obj *dict, int nested_depth)
1211
{
1212
pdf_obj *subtype;
1213
pdf_obj *dfonts;
1214
pdf_obj *charprocs;
1215
pdf_font_desc *fontdesc;
1216
int type3 = 0;
1217
1218
if ((fontdesc = pdf_find_item(ctx, pdf_drop_font_imp, dict)) != NULL)
1219
{
1220
return fontdesc;
1221
}
1222
1223
subtype = pdf_dict_get(ctx, dict, PDF_NAME_Subtype);
1224
dfonts = pdf_dict_get(ctx, dict, PDF_NAME_DescendantFonts);
1225
charprocs = pdf_dict_get(ctx, dict, PDF_NAME_CharProcs);
1226
1227
if (pdf_name_eq(ctx, subtype, PDF_NAME_Type0))
1228
fontdesc = pdf_load_type0_font(ctx, doc, dict);
1229
else if (pdf_name_eq(ctx, subtype, PDF_NAME_Type1))
1230
fontdesc = pdf_load_simple_font(ctx, doc, dict);
1231
else if (pdf_name_eq(ctx, subtype, PDF_NAME_MMType1))
1232
fontdesc = pdf_load_simple_font(ctx, doc, dict);
1233
else if (pdf_name_eq(ctx, subtype, PDF_NAME_TrueType))
1234
fontdesc = pdf_load_simple_font(ctx, doc, dict);
1235
else if (pdf_name_eq(ctx, subtype, PDF_NAME_Type3))
1236
{
1237
fontdesc = pdf_load_type3_font(ctx, doc, rdb, dict);
1238
type3 = 1;
1239
}
1240
else if (charprocs)
1241
{
1242
fz_warn(ctx, "unknown font format, guessing type3.");
1243
fontdesc = pdf_load_type3_font(ctx, doc, rdb, dict);
1244
type3 = 1;
1245
}
1246
else if (dfonts)
1247
{
1248
fz_warn(ctx, "unknown font format, guessing type0.");
1249
fontdesc = pdf_load_type0_font(ctx, doc, dict);
1250
}
1251
else
1252
{
1253
fz_warn(ctx, "unknown font format, guessing type1 or truetype.");
1254
fontdesc = pdf_load_simple_font(ctx, doc, dict);
1255
}
1256
1257
/* Save the widths to stretch non-CJK substitute fonts */
1258
if (fontdesc->font->ft_substitute && !fontdesc->to_ttf_cmap)
1259
pdf_make_width_table(ctx, fontdesc);
1260
1261
pdf_store_item(ctx, dict, fontdesc, fontdesc->size);
1262
1263
if (type3)
1264
pdf_load_type3_glyphs(ctx, doc, fontdesc, nested_depth);
1265
1266
return fontdesc;
1267
}
1268
1269
#ifndef NDEBUG
1270
void
1271
pdf_print_font(fz_context *ctx, pdf_font_desc *fontdesc)
1272
{
1273
int i;
1274
1275
printf("fontdesc {\n");
1276
1277
if (fontdesc->font->ft_face)
1278
printf("\tfreetype font\n");
1279
if (fontdesc->font->t3procs)
1280
printf("\ttype3 font\n");
1281
1282
printf("\twmode %d\n", fontdesc->wmode);
1283
printf("\tDW %d\n", fontdesc->dhmtx.w);
1284
1285
printf("\tW {\n");
1286
for (i = 0; i < fontdesc->hmtx_len; i++)
1287
printf("\t\t<%04x> <%04x> %d\n",
1288
fontdesc->hmtx[i].lo, fontdesc->hmtx[i].hi, fontdesc->hmtx[i].w);
1289
printf("\t}\n");
1290
1291
if (fontdesc->wmode)
1292
{
1293
printf("\tDW2 [%d %d]\n", fontdesc->dvmtx.y, fontdesc->dvmtx.w);
1294
printf("\tW2 {\n");
1295
for (i = 0; i < fontdesc->vmtx_len; i++)
1296
printf("\t\t<%04x> <%04x> %d %d %d\n", fontdesc->vmtx[i].lo, fontdesc->vmtx[i].hi,
1297
fontdesc->vmtx[i].x, fontdesc->vmtx[i].y, fontdesc->vmtx[i].w);
1298
printf("\t}\n");
1299
}
1300
}
1301
#endif
1302
1303
fz_rect *pdf_measure_text(fz_context *ctx, pdf_font_desc *fontdesc, unsigned char *buf, int len, fz_rect *acc)
1304
{
1305
int i;
1306
int w = 0;
1307
1308
for (i = 0; i < len; i++)
1309
w += pdf_lookup_hmtx(ctx, fontdesc, buf[i]).w;
1310
1311
acc->x0 = 0;
1312
acc->x1 = w / 1000.0f;
1313
acc->y0 = fontdesc->descent / 1000.0f;
1314
acc->y1 = fontdesc->ascent / 1000.0f;
1315
1316
return acc;
1317
}
1318
1319
float pdf_text_stride(fz_context *ctx, pdf_font_desc *fontdesc, float fontsize, unsigned char *buf, int len, float room, int *count)
1320
{
1321
pdf_hmtx h;
1322
int i = 0;
1323
float x = 0.0;
1324
1325
while(i < len)
1326
{
1327
float span;
1328
1329
h = pdf_lookup_hmtx(ctx, fontdesc, buf[i]);
1330
1331
span = h.w * fontsize / 1000.0;
1332
1333
if (x + span > room)
1334
break;
1335
1336
x += span;
1337
i ++;
1338
}
1339
1340
if (count)
1341
*count = i;
1342
1343
return x;
1344
}
1345
1346