Coverage Report

Created: 2026-03-31 07:17

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