Coverage Report

Created: 2026-10-13 07:30

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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
}