Coverage Report

Created: 2026-04-09 06:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/xpdf-4.06/xpdf/GfxFont.cc
Line
Count
Source
1
//========================================================================
2
//
3
// GfxFont.cc
4
//
5
// Copyright 1996-2003 Glyph & Cog, LLC
6
//
7
//========================================================================
8
9
#include <aconf.h>
10
11
#include <stdio.h>
12
#include <stdlib.h>
13
#include <string.h>
14
#include <ctype.h>
15
#include <math.h>
16
#include <limits.h>
17
#include "gmem.h"
18
#include "gmempp.h"
19
#include "GList.h"
20
#include "GHash.h"
21
#include "Error.h"
22
#include "Object.h"
23
#include "Dict.h"
24
#include "GlobalParams.h"
25
#include "CMap.h"
26
#include "CharCodeToUnicode.h"
27
#include "FontEncodingTables.h"
28
#include "BuiltinFontTables.h"
29
#include "FoFiIdentifier.h"
30
#include "FoFiType1.h"
31
#include "FoFiType1C.h"
32
#include "FoFiTrueType.h"
33
#include "GfxFont.h"
34
35
//------------------------------------------------------------------------
36
37
struct Base14FontMapEntry {
38
  const char *altName;
39
  const char *base14Name;
40
};
41
42
static Base14FontMapEntry base14FontMap[] = {
43
  { "Arial",                        "Helvetica" },
44
  { "Arial,Bold",                   "Helvetica-Bold" },
45
  { "Arial,BoldItalic",             "Helvetica-BoldOblique" },
46
  { "Arial,Italic",                 "Helvetica-Oblique" },
47
  { "Arial-Bold",                   "Helvetica-Bold" },
48
  { "Arial-BoldItalic",             "Helvetica-BoldOblique" },
49
  { "Arial-BoldItalicMT",           "Helvetica-BoldOblique" },
50
  { "Arial-BoldMT",                 "Helvetica-Bold" },
51
  { "Arial-Italic",                 "Helvetica-Oblique" },
52
  { "Arial-ItalicMT",               "Helvetica-Oblique" },
53
  { "ArialMT",                      "Helvetica" },
54
  { "Courier",                      "Courier" },
55
  { "Courier,Bold",                 "Courier-Bold" },
56
  { "Courier,BoldItalic",           "Courier-BoldOblique" },
57
  { "Courier,Italic",               "Courier-Oblique" },
58
  { "Courier-Bold",                 "Courier-Bold" },
59
  { "Courier-BoldOblique",          "Courier-BoldOblique" },
60
  { "Courier-Oblique",              "Courier-Oblique" },
61
  { "CourierNew",                   "Courier" },
62
  { "CourierNew,Bold",              "Courier-Bold" },
63
  { "CourierNew,BoldItalic",        "Courier-BoldOblique" },
64
  { "CourierNew,Italic",            "Courier-Oblique" },
65
  { "CourierNew-Bold",              "Courier-Bold" },
66
  { "CourierNew-BoldItalic",        "Courier-BoldOblique" },
67
  { "CourierNew-Italic",            "Courier-Oblique" },
68
  { "CourierNewPS-BoldItalicMT",    "Courier-BoldOblique" },
69
  { "CourierNewPS-BoldMT",          "Courier-Bold" },
70
  { "CourierNewPS-ItalicMT",        "Courier-Oblique" },
71
  { "CourierNewPSMT",               "Courier" },
72
  { "Helvetica",                    "Helvetica" },
73
  { "Helvetica,Bold",               "Helvetica-Bold" },
74
  { "Helvetica,BoldItalic",         "Helvetica-BoldOblique" },
75
  { "Helvetica,Italic",             "Helvetica-Oblique" },
76
  { "Helvetica-Bold",               "Helvetica-Bold" },
77
  { "Helvetica-BoldItalic",         "Helvetica-BoldOblique" },
78
  { "Helvetica-BoldOblique",        "Helvetica-BoldOblique" },
79
  { "Helvetica-Italic",             "Helvetica-Oblique" },
80
  { "Helvetica-Oblique",            "Helvetica-Oblique" },
81
  { "Symbol",                       "Symbol" },
82
  { "Symbol,Bold",                  "Symbol" },
83
  { "Symbol,BoldItalic",            "Symbol" },
84
  { "Symbol,Italic",                "Symbol" },
85
  { "Times-Bold",                   "Times-Bold" },
86
  { "Times-BoldItalic",             "Times-BoldItalic" },
87
  { "Times-Italic",                 "Times-Italic" },
88
  { "Times-Roman",                  "Times-Roman" },
89
  { "TimesNewRoman",                "Times-Roman" },
90
  { "TimesNewRoman,Bold",           "Times-Bold" },
91
  { "TimesNewRoman,BoldItalic",     "Times-BoldItalic" },
92
  { "TimesNewRoman,Italic",         "Times-Italic" },
93
  { "TimesNewRoman-Bold",           "Times-Bold" },
94
  { "TimesNewRoman-BoldItalic",     "Times-BoldItalic" },
95
  { "TimesNewRoman-Italic",         "Times-Italic" },
96
  { "TimesNewRomanPS",              "Times-Roman" },
97
  { "TimesNewRomanPS-Bold",         "Times-Bold" },
98
  { "TimesNewRomanPS-BoldItalic",   "Times-BoldItalic" },
99
  { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
100
  { "TimesNewRomanPS-BoldMT",       "Times-Bold" },
101
  { "TimesNewRomanPS-Italic",       "Times-Italic" },
102
  { "TimesNewRomanPS-ItalicMT",     "Times-Italic" },
103
  { "TimesNewRomanPSMT",            "Times-Roman" },
104
  { "TimesNewRomanPSMT,Bold",       "Times-Bold" },
105
  { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
106
  { "TimesNewRomanPSMT,Italic",     "Times-Italic" },
107
  { "ZapfDingbats",                 "ZapfDingbats" }
108
};
109
110
//------------------------------------------------------------------------
111
112
// index: {fixed:0, sans-serif:4, serif:8} + bold*2 + italic
113
// NB: must be in same order as psSubstFonts in PSOutputDev.cc
114
static const char *base14SubstFonts[14] = {
115
  "Courier",
116
  "Courier-Oblique",
117
  "Courier-Bold",
118
  "Courier-BoldOblique",
119
  "Helvetica",
120
  "Helvetica-Oblique",
121
  "Helvetica-Bold",
122
  "Helvetica-BoldOblique",
123
  "Times-Roman",
124
  "Times-Italic",
125
  "Times-Bold",
126
  "Times-BoldItalic",
127
  // the last two are never used for substitution
128
  "Symbol",
129
  "ZapfDingbats"
130
};
131
132
//------------------------------------------------------------------------
133
134
3.22M
static int readFromStream(void *data) {
135
3.22M
  return ((Stream *)data)->getChar();
136
3.22M
}
137
138
//------------------------------------------------------------------------
139
// GfxFontLoc
140
//------------------------------------------------------------------------
141
142
7.43k
GfxFontLoc::GfxFontLoc() {
143
7.43k
  path = NULL;
144
7.43k
  fontNum = 0;
145
7.43k
  oblique = 0;
146
7.43k
  encoding = NULL;
147
7.43k
  substIdx = -1;
148
7.43k
}
149
150
7.43k
GfxFontLoc::~GfxFontLoc() {
151
7.43k
  if (path) {
152
0
    delete path;
153
0
  }
154
7.43k
  if (encoding) {
155
0
    delete encoding;
156
0
  }
157
7.43k
}
158
159
//------------------------------------------------------------------------
160
// GfxFont
161
//------------------------------------------------------------------------
162
163
GfxFont *GfxFont::makeFont(XRef *xref, const char *tagA,
164
94.2k
         Ref idA, Dict *fontDict) {
165
94.2k
  GString *nameA;
166
94.2k
  Ref embFontIDA;
167
94.2k
  GfxFontType typeA;
168
94.2k
  GfxFont *font;
169
94.2k
  Object obj1;
170
171
  // get base font name
172
94.2k
  nameA = NULL;
173
94.2k
  fontDict->lookup("BaseFont", &obj1);
174
94.2k
  if (obj1.isName()) {
175
43.6k
    nameA = new GString(obj1.getName());
176
50.6k
  } else if (obj1.isString()) {
177
9
    nameA = obj1.getString()->copy();
178
9
  }
179
94.2k
  obj1.free();
180
181
  // get embedded font ID and font type
182
94.2k
  typeA = getFontType(xref, fontDict, &embFontIDA);
183
184
  // create the font object
185
94.2k
  font = NULL;
186
94.2k
  if (typeA < fontCIDType0) {
187
51.0k
    font = new Gfx8BitFont(xref, tagA, idA, nameA, typeA, embFontIDA,
188
51.0k
         fontDict);
189
51.0k
  } else {
190
43.2k
    font = new GfxCIDFont(xref, tagA, idA, nameA, typeA, embFontIDA,
191
43.2k
        fontDict);
192
43.2k
  }
193
194
94.2k
  return font;
195
94.2k
}
196
197
23.2k
GfxFont *GfxFont::makeDefaultFont(XRef *xref) {
198
23.2k
  Object type, subtype, baseFont;
199
23.2k
  type.initName("Font");
200
23.2k
  subtype.initName("Type1");
201
23.2k
  baseFont.initName("Helvetica");
202
23.2k
  Object fontDict;
203
23.2k
  fontDict.initDict(xref);
204
23.2k
  fontDict.dictAdd(copyString("Type"), &type);
205
23.2k
  fontDict.dictAdd(copyString("Subtype"), &subtype);
206
23.2k
  fontDict.dictAdd(copyString("BaseFont"), &baseFont);
207
208
23.2k
  Ref r;
209
23.2k
  r.gen = 100000;
210
23.2k
  r.num = GfxFontDict::hashFontObject(&fontDict);
211
212
23.2k
  GfxFont *font = makeFont(xref, "undef", r, fontDict.getDict());
213
23.2k
  fontDict.free();
214
215
23.2k
  return font;
216
23.2k
}
217
218
GfxFont::GfxFont(const char *tagA, Ref idA, GString *nameA,
219
94.2k
     GfxFontType typeA, Ref embFontIDA) {
220
94.2k
  ok = gFalse;
221
94.2k
  tag = new GString(tagA);
222
94.2k
  id = idA;
223
94.2k
  name = nameA;
224
94.2k
  type = typeA;
225
94.2k
  embFontID = embFontIDA;
226
94.2k
  embFontName = NULL;
227
94.2k
  hasToUnicode = gFalse;
228
94.2k
}
229
230
94.2k
GfxFont::~GfxFont() {
231
94.2k
  delete tag;
232
94.2k
  if (name) {
233
43.6k
    delete name;
234
43.6k
  }
235
94.2k
  if (embFontName) {
236
50.4k
    delete embFontName;
237
50.4k
  }
238
94.2k
}
239
240
// This function extracts three pieces of information:
241
// 1. the "expected" font type, i.e., the font type implied by
242
//    Font.Subtype, DescendantFont.Subtype, and
243
//    FontDescriptor.FontFile3.Subtype
244
// 2. the embedded font object ID
245
// 3. the actual font type - determined by examining the embedded font
246
//    if there is one, otherwise equal to the expected font type
247
// If the expected and actual font types don't match, a warning
248
// message is printed.  The expected font type is not used for
249
// anything else.
250
94.2k
GfxFontType GfxFont::getFontType(XRef *xref, Dict *fontDict, Ref *embID) {
251
94.2k
  GfxFontType t, expectedType;
252
94.2k
  FoFiIdentifierType fft;
253
94.2k
  Dict *fontDict2;
254
94.2k
  Object subtype, fontDesc, obj1, obj2, obj3, obj4;
255
94.2k
  GBool isType0, err;
256
257
94.2k
  t = fontUnknownType;
258
94.2k
  embID->num = embID->gen = -1;
259
94.2k
  err = gFalse;
260
261
94.2k
  fontDict->lookup("Subtype", &subtype);
262
94.2k
  expectedType = fontUnknownType;
263
94.2k
  isType0 = gFalse;
264
94.2k
  if (subtype.isName("Type1") || subtype.isName("MMType1")) {
265
29.9k
    expectedType = fontType1;
266
64.3k
  } else if (subtype.isName("Type1C")) {
267
4
    expectedType = fontType1C;
268
64.3k
  } else if (subtype.isName("Type3")) {
269
6.78k
    expectedType = fontType3;
270
57.5k
  } else if (subtype.isName("TrueType")) {
271
2.28k
    expectedType = fontTrueType;
272
55.2k
  } else if (subtype.isName("Type0")) {
273
46.8k
    isType0 = gTrue;
274
46.8k
  } else {
275
8.34k
    error(errSyntaxWarning, -1, "Unknown font type: '{0:s}'",
276
8.34k
    subtype.isName() ? subtype.getName() : "???");
277
8.34k
  }
278
94.2k
  subtype.free();
279
280
94.2k
  fontDict2 = fontDict;
281
94.2k
  if (fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
282
50.4k
    if (obj1.arrayGetLength() == 0) {
283
2
      error(errSyntaxWarning, -1, "Empty DescendantFonts array in font");
284
2
      obj2.initNull();
285
50.4k
    } else if (obj1.arrayGet(0, &obj2)->isDict()) {
286
50.1k
      if (!isType0) {
287
3.98k
  error(errSyntaxWarning, -1, "Non-CID font with DescendantFonts array");
288
3.98k
      }
289
50.1k
      fontDict2 = obj2.getDict();
290
50.1k
      fontDict2->lookup("Subtype", &subtype);
291
50.1k
      if (subtype.isName("CIDFontType0")) {
292
38.0k
  if (isType0) {
293
36.6k
    expectedType = fontCIDType0;
294
36.6k
  }
295
38.0k
      } else if (subtype.isName("CIDFontType2")) {
296
6.94k
  if (isType0) {
297
5.84k
    expectedType = fontCIDType2;
298
5.84k
  }
299
6.94k
      }
300
50.1k
      subtype.free();
301
50.1k
    }
302
50.4k
  } else {
303
43.7k
    obj2.initNull();
304
43.7k
  }
305
306
  // NB: the PDF spec doesn't say anything about precedence, but Adobe
307
  // uses FontFile3 over FontFile2 if both are present.
308
94.2k
  if (fontDict2->lookup("FontDescriptor", &fontDesc)->isDict()) {
309
56.9k
    if (fontDesc.dictLookupNF("FontFile3", &obj3)->isRef()) {
310
42.2k
      *embID = obj3.getRef();
311
42.2k
      if (obj3.fetch(xref, &obj4)->isStream()) {
312
40.3k
  obj4.streamGetDict()->lookup("Subtype", &subtype);
313
40.3k
  if (subtype.isName("Type1")) {
314
18
    if (expectedType != fontType1) {
315
16
      err = gTrue;
316
16
      expectedType = isType0 ? fontCIDType0 : fontType1;
317
16
    }
318
40.2k
  } else if (subtype.isName("Type1C")) {
319
2.33k
    if (expectedType == fontType1) {
320
2.13k
      expectedType = fontType1C;
321
2.13k
    } else if (expectedType != fontType1C) {
322
200
      err = gTrue;
323
200
      expectedType = isType0 ? fontCIDType0C : fontType1C;
324
200
    }
325
37.9k
  } else if (subtype.isName("TrueType")) {
326
0
    if (expectedType != fontTrueType) {
327
0
      err = gTrue;
328
0
      expectedType = isType0 ? fontCIDType2 : fontTrueType;
329
0
    }
330
37.9k
  } else if (subtype.isName("CIDFontType0C")) {
331
672
    if (expectedType == fontCIDType0) {
332
98
      expectedType = fontCIDType0C;
333
574
    } else {
334
574
      err = gTrue;
335
574
      expectedType = isType0 ? fontCIDType0C : fontType1C;
336
574
    }
337
37.2k
  } else if (subtype.isName("OpenType")) {
338
209
    if (expectedType == fontTrueType) {
339
0
      expectedType = fontTrueTypeOT;
340
209
    } else if (expectedType == fontType1) {
341
87
      expectedType = fontType1COT;
342
122
    } else if (expectedType == fontCIDType0) {
343
30
      expectedType = fontCIDType0COT;
344
92
    } else if (expectedType == fontCIDType2) {
345
0
      expectedType = fontCIDType2OT;
346
92
    } else {
347
92
      err = gTrue;
348
92
    }
349
37.0k
  } else {
350
37.0k
    error(errSyntaxError, -1, "Unknown font type '{0:s}'",
351
37.0k
    subtype.isName() ? subtype.getName() : "???");
352
37.0k
  }
353
40.3k
  subtype.free();
354
40.3k
      }
355
42.2k
      obj4.free();
356
42.2k
    }
357
56.9k
    obj3.free();
358
56.9k
    if (embID->num == -1) {
359
14.7k
      if (fontDesc.dictLookupNF("FontFile2", &obj3)->isRef()) {
360
8.90k
  *embID = obj3.getRef();
361
8.90k
  if (isType0) {
362
5.46k
    expectedType = fontCIDType2;
363
5.46k
  } else if (expectedType != fontTrueType) {
364
1.25k
    err = gTrue;
365
1.25k
  }
366
8.90k
      }
367
14.7k
      obj3.free();
368
14.7k
    }
369
56.9k
    if (embID->num == -1) {
370
5.85k
      if (fontDesc.dictLookupNF("FontFile", &obj3)->isRef()) {
371
2.26k
  *embID = obj3.getRef();
372
2.26k
  if (expectedType != fontType1) {
373
469
    err = gTrue;
374
469
  }
375
2.26k
      }
376
5.85k
      obj3.free();
377
5.85k
    }
378
56.9k
  }
379
94.2k
  fontDesc.free();
380
381
94.2k
  t = fontUnknownType;
382
94.2k
  if (embID->num >= 0) {
383
53.3k
    obj3.initRef(embID->num, embID->gen);
384
53.3k
    obj3.fetch(xref, &obj4);
385
53.3k
    if (obj4.isStream()) {
386
50.9k
      obj4.streamReset();
387
50.9k
      fft = FoFiIdentifier::identifyStream(&readFromStream, obj4.getStream());
388
50.9k
      obj4.streamClose();
389
50.9k
      switch (fft) {
390
1.88k
      case fofiIdType1PFA:
391
1.88k
      case fofiIdType1PFB:
392
1.88k
  t = fontType1;
393
1.88k
  break;
394
2.87k
      case fofiIdCFF8Bit:
395
2.87k
  t = isType0 ? fontCIDType0C : fontType1C;
396
2.87k
  break;
397
68
      case fofiIdCFFCID:
398
68
  t = fontCIDType0C;
399
68
  break;
400
7.43k
      case fofiIdTrueType:
401
7.43k
      case fofiIdTrueTypeCollection:
402
7.43k
  t = isType0 ? fontCIDType2 : fontTrueType;
403
7.43k
  break;
404
12
      case fofiIdOpenTypeCFF8Bit:
405
12
  t = isType0 ? fontCIDType0COT : fontType1COT;
406
12
  break;
407
0
      case fofiIdOpenTypeCFFCID:
408
0
  t = fontCIDType0COT;
409
0
  break;
410
38.7k
      default:
411
38.7k
  error(errSyntaxError, -1, "Embedded font file may be invalid");
412
38.7k
  break;
413
50.9k
      }
414
50.9k
    } else {
415
2.40k
      error(errSyntaxError, -1, "Embedded font object is wrong type");
416
2.40k
    }
417
53.3k
    obj4.free();
418
53.3k
    obj3.free();
419
53.3k
  }
420
421
  // If the embedded font doesn't exist, or it's not a stream object,
422
  // or we couldn't identify its type, then remove the reference so
423
  // nothing tries to use it later.
424
94.2k
  if (t == fontUnknownType) {
425
81.9k
    embID->num = -1;
426
81.9k
    embID->gen = -1;
427
81.9k
    t = expectedType;
428
81.9k
  }
429
430
94.2k
  if (t != expectedType) {
431
2.22k
    err = gTrue;
432
2.22k
  }
433
434
94.2k
  if (err) {
435
3.28k
    error(errSyntaxWarning, -1,
436
3.28k
    "Mismatch between font type and embedded font file");
437
3.28k
  }
438
439
94.2k
  obj2.free();
440
94.2k
  obj1.free();
441
442
94.2k
  return t;
443
94.2k
}
444
445
94.2k
void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
446
94.2k
  Object obj1, obj2, obj3, obj4;
447
94.2k
  double t, t2;
448
94.2k
  int i;
449
450
  // assume Times-Roman by default (for substitution purposes)
451
94.2k
  flags = fontSerif;
452
453
94.2k
  if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
454
455
    // get flags
456
52.9k
    if (obj1.dictLookup("Flags", &obj2)->isInt()) {
457
48.9k
      flags = obj2.getInt();
458
48.9k
    }
459
52.9k
    obj2.free();
460
461
    // get name
462
52.9k
    obj1.dictLookup("FontName", &obj2);
463
52.9k
    if (obj2.isName()) {
464
49.8k
      embFontName = new GString(obj2.getName());
465
49.8k
    }
466
52.9k
    obj2.free();
467
468
    // look for MissingWidth
469
52.9k
    obj1.dictLookup("MissingWidth", &obj2);
470
52.9k
    if (obj2.isNum()) {
471
150
      missingWidth = obj2.getNum();
472
150
    }
473
52.9k
    obj2.free();
474
475
    // font FontBBox
476
52.9k
    if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
477
201k
      for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
478
161k
  if (obj2.arrayGet(i, &obj3)->isNum()) {
479
152k
    fontBBox[i] = 0.001 * obj3.getNum();
480
152k
  }
481
161k
  obj3.free();
482
161k
      }
483
40.3k
    }
484
52.9k
    obj2.free();
485
486
    // get Ascent (but also look at CapHeight)
487
52.9k
    obj1.dictLookup("Ascent", &obj2);
488
52.9k
    obj1.dictLookup("CapHeight", &obj3);
489
52.9k
    if (obj2.isNum() || obj3.isNum()) {
490
51.9k
      if (obj2.isNum()) {
491
50.1k
  t = 0.001 * obj2.getNum();
492
  // some broken font descriptors specify a negative ascent
493
50.1k
  if (t < 0) {
494
26
    t = -t;
495
26
  }
496
50.1k
      } else {
497
1.87k
  t = 0;
498
1.87k
      }
499
51.9k
      if (obj3.isNum()) {
500
49.0k
  t2 = 0.001 * obj3.getNum();
501
  // some broken font descriptors specify a negative ascent
502
49.0k
  if (t2 < 0) {
503
34
    t2 = -t2;
504
34
  }
505
49.0k
      } else {
506
2.89k
  t2 = 0;
507
2.89k
      }
508
51.9k
      if (t != 0 && t < 1.9) {
509
49.5k
  declaredAscent = t;
510
49.5k
      }
511
      // The ascent is generally expected to be in the (0.55, 1.9) range.
512
      // If Ascent and/or CapHeight is in that range, use the smaller one
513
      // (because the most common problem is that Ascent is too large).
514
      // Otherwise check for a value in (0, 0.55], and use that.
515
51.9k
      if (t > 0.55 && t < 1.9) {
516
48.9k
  if (t2 > 0.55 && t2 < 1.9) {
517
45.9k
    ascent = (t < t2) ? t : t2;
518
45.9k
  } else {
519
3.00k
    ascent = t;
520
3.00k
  }
521
48.9k
      } else if (t2 > 0.55 && t2 < 1.9) {
522
1.48k
  ascent = t2;
523
1.54k
      } else if (fontBBox[3] > 0.55 && fontBBox[3] < 1.9 &&
524
904
     fontBBox[1] < fontBBox[3]) {
525
903
  ascent = fontBBox[3];
526
903
      } else if (t > 0 && t < 1.9) {
527
67
  ascent = t;
528
571
      } else if (t2 > 0 && t2 < 1.9) {
529
31
  ascent = t2;
530
31
      }
531
51.9k
    }
532
52.9k
    obj2.free();
533
52.9k
    obj3.free();
534
535
    // get Descent
536
52.9k
    obj1.dictLookup("Descent", &obj2);
537
52.9k
    if (obj2.isNum()) {
538
51.2k
      t = 0.001 * obj2.getNum();
539
      // some broken font descriptors specify a positive descent
540
51.2k
      if (t > 0) {
541
1.40k
  t = -t;
542
1.40k
      }
543
      // some broken font descriptors set ascent and descent to 0
544
51.2k
      if (t < 0 && t > -1.9) {
545
47.3k
  descent = t;
546
47.3k
      } else if (fontBBox[1] > -1.9 && fontBBox[1] <= 0 &&
547
3.72k
     fontBBox[1] < fontBBox[3]) {
548
2.14k
  descent = fontBBox[1];
549
2.14k
      }
550
51.2k
    }
551
52.9k
    obj2.free();
552
553
52.9k
  }
554
94.2k
  obj1.free();
555
556
  // scan font name for bold/italic tags and update the flags
557
94.2k
  if (name) {
558
43.5k
    i = name->getLength();
559
43.5k
    if (i > 2 && !strncmp(name->getCString() + i - 2, "MT", 2)) {
560
6.10k
      i -= 2;
561
6.10k
    }
562
43.5k
    if (i > 6 && !strncmp(name->getCString() + i - 6, "Italic", 6)) {
563
337
      flags |= fontItalic;
564
337
      i -= 6;
565
43.2k
    } else if (i > 2 && !strncmp(name->getCString() + i - 2, "It", 2)) {
566
13
      flags |= fontItalic;
567
13
      i -= 2;
568
43.2k
    } else if (i > 7 && !strncmp(name->getCString() + i - 7, "Oblique", 7)) {
569
50
      flags |= fontItalic;
570
50
      i -= 7;
571
50
    }
572
43.5k
    if (i > 0) {
573
43.5k
      char c = name->getChar(i-1);
574
43.5k
      if (!((c >= 'A' && c <= 'Z') ||
575
34.2k
      (c >= 'a' && c <= 'z') ||
576
3.28k
      (c >= '0' && c <= '9'))) {
577
1.30k
  --i;
578
1.30k
      }
579
43.5k
    }
580
43.5k
    if (i > 4 && !strncmp(name->getCString() + i - 4, "Bold", 4)) {
581
1.37k
      flags |= fontBold;
582
1.37k
    }
583
43.5k
  }
584
94.2k
}
585
586
CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
587
84.0k
                CharCodeToUnicode *ctu) {
588
84.0k
  GString *buf;
589
84.0k
  Object obj1;
590
84.0k
  char buf2[4096];
591
84.0k
  int n;
592
593
84.0k
  if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
594
50.1k
    obj1.free();
595
50.1k
    return NULL;
596
50.1k
  }
597
33.8k
  buf = new GString();
598
33.8k
  obj1.streamReset();
599
63.2k
  while ((n = obj1.streamGetBlock(buf2, sizeof(buf2))) > 0) {
600
29.4k
    buf->append(buf2, n);
601
29.4k
  }
602
33.8k
  obj1.streamClose();
603
33.8k
  obj1.free();
604
33.8k
  if (ctu) {
605
5.50k
    ctu->mergeCMap(buf, nBits);
606
28.3k
  } else {
607
28.3k
    ctu = CharCodeToUnicode::parseCMap(buf, nBits);
608
28.3k
  }
609
33.8k
  delete buf;
610
33.8k
  hasToUnicode = gTrue;
611
33.8k
  return ctu;
612
84.0k
}
613
614
48.6k
GfxFontLoc *GfxFont::locateFont(XRef *xref, GBool ps) {
615
48.6k
  GfxFontLoc *fontLoc;
616
48.6k
  SysFontType sysFontType;
617
48.6k
  FoFiIdentifierType fft;
618
48.6k
  GString *path, *base14Name, *substName;
619
48.6k
  PSFontParam16 *psFont16;
620
48.6k
  Object refObj, embFontObj;
621
48.6k
  int substIdx, fontNum;
622
48.6k
  double oblique;
623
48.6k
  GBool embed;
624
625
48.6k
  if (type == fontType3) {
626
0
    return NULL;
627
0
  }
628
629
  //----- embedded font
630
48.6k
  if (embFontID.num >= 0) {
631
7.43k
    embed = gTrue;
632
7.43k
    refObj.initRef(embFontID.num, embFontID.gen);
633
7.43k
    refObj.fetch(xref, &embFontObj);
634
7.43k
    if (!embFontObj.isStream()) {
635
0
      error(errSyntaxError, -1, "Embedded font object is wrong type");
636
0
      embed = gFalse;
637
0
    }
638
7.43k
    embFontObj.free();
639
7.43k
    refObj.free();
640
7.43k
    if (embed) {
641
7.43k
      if (ps) {
642
0
  switch (type) {
643
0
  case fontType1:
644
0
  case fontType1C:
645
0
  case fontType1COT:
646
0
    embed = globalParams->getPSEmbedType1();
647
0
    break;
648
0
  case fontTrueType:
649
0
  case fontTrueTypeOT:
650
0
    embed = globalParams->getPSEmbedTrueType();
651
0
    break;
652
0
  case fontCIDType0C:
653
0
  case fontCIDType0COT:
654
0
    embed = globalParams->getPSEmbedCIDPostScript();
655
0
    break;
656
0
  case fontCIDType2:
657
0
  case fontCIDType2OT:
658
0
    embed = globalParams->getPSEmbedCIDTrueType();
659
0
    break;
660
0
  default:
661
0
    break;
662
0
  }
663
0
      }
664
7.43k
      if (embed) {
665
7.43k
  fontLoc = new GfxFontLoc();
666
7.43k
  fontLoc->locType = gfxFontLocEmbedded;
667
7.43k
  fontLoc->fontType = type;
668
7.43k
  fontLoc->embFontID = embFontID;
669
7.43k
  return fontLoc;
670
7.43k
      }
671
7.43k
    }
672
7.43k
  }
673
674
  //----- PS passthrough
675
41.1k
  if (ps && name && !isCIDFont() && globalParams->getPSFontPassthrough()) {
676
0
    fontLoc = new GfxFontLoc();
677
0
    fontLoc->locType = gfxFontLocResident;
678
0
    fontLoc->fontType = fontType1;
679
0
    fontLoc->path = name->copy();
680
0
    return fontLoc;
681
0
  }
682
683
  //----- external font file (fontFile, fontDir)
684
41.1k
  if (name && (path = globalParams->findFontFile(name))) {
685
0
    if ((fontLoc = getExternalFont(path, 0, 0, isCIDFont()))) {
686
0
      return fontLoc;
687
0
    }
688
0
  }
689
690
  //----- PS resident Base-14 font
691
41.1k
  if (ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
692
0
    fontLoc = new GfxFontLoc();
693
0
    fontLoc->locType = gfxFontLocResident;
694
0
    fontLoc->fontType = fontType1;
695
0
    fontLoc->path = new GString(((Gfx8BitFont *)this)->base14->base14Name);
696
0
    return fontLoc;
697
0
  }
698
699
  //----- external font file for Base-14 font
700
41.1k
  if (!ps && !isCIDFont() && ((Gfx8BitFont *)this)->base14) {
701
24.8k
    base14Name = new GString(((Gfx8BitFont *)this)->base14->base14Name);
702
24.8k
    path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique);
703
24.8k
    delete base14Name;
704
24.8k
    if (path && (fontLoc = getExternalFont(path, fontNum, oblique, gFalse))) {
705
0
      return fontLoc;
706
0
    }
707
24.8k
  }
708
709
  //----- system font
710
41.1k
  if (name && (path = globalParams->findSystemFontFile(name, &sysFontType,
711
38.8k
                   &fontNum))) {
712
0
    fontLoc = new GfxFontLoc();
713
0
    fontLoc->locType = gfxFontLocExternal;
714
0
    fontLoc->path = path;
715
0
    fontLoc->fontNum = fontNum;
716
0
    fft = FoFiIdentifier::identifyFile(fontLoc->path->getCString());
717
0
    switch (fft) {
718
0
    case fofiIdType1PFA:
719
0
    case fofiIdType1PFB:
720
0
      fontLoc->fontType = fontType1;
721
0
      break;
722
0
    case fofiIdCFF8Bit:
723
0
      fontLoc->fontType = fontType1C;
724
0
      break;
725
0
    case fofiIdCFFCID:
726
0
      fontLoc->fontType = fontCIDType0C;
727
0
      break;
728
0
    case fofiIdTrueType:
729
0
    case fofiIdTrueTypeCollection:
730
0
      fontLoc->fontType = isCIDFont() ? fontCIDType2 : fontTrueType;
731
0
      break;
732
0
    case fofiIdOpenTypeCFF8Bit:
733
0
      fontLoc->fontType = fontType1COT;
734
0
      break;
735
0
    case fofiIdOpenTypeCFFCID:
736
0
      fontLoc->fontType = fontCIDType0COT;
737
0
      break;
738
0
    case fofiIdDfont:
739
0
      fontLoc->fontType = isCIDFont() ? fontCIDType2 : fontTrueType;
740
0
      break;
741
0
    case fofiIdUnknown:
742
0
    case fofiIdError:
743
0
    default:
744
0
      delete fontLoc;
745
0
      fontLoc = NULL;
746
0
      break;
747
0
    }
748
0
    if (fontLoc) {
749
0
      return fontLoc;
750
0
    }
751
0
  }
752
753
41.1k
  if (!isCIDFont()) {
754
755
    //----- 8-bit PS resident font
756
28.9k
    if (ps) {
757
0
      if (name && (path = globalParams->getPSResidentFont(name))) {
758
0
  fontLoc = new GfxFontLoc();
759
0
  fontLoc->locType = gfxFontLocResident;
760
0
  fontLoc->fontType = fontType1;
761
0
  fontLoc->path = path;
762
0
  return fontLoc;
763
0
      }
764
0
    }
765
766
    //----- 8-bit font substitution
767
28.9k
    if (flags & fontFixedWidth) {
768
416
      substIdx = 0;
769
28.5k
    } else if (flags & fontSerif) {
770
27.8k
      substIdx = 8;
771
27.8k
    } else {
772
671
      substIdx = 4;
773
671
    }
774
28.9k
    if (isBold()) {
775
51
      substIdx += 2;
776
51
    }
777
28.9k
    if (isItalic()) {
778
4
      substIdx += 1;
779
4
    }
780
28.9k
    substName = new GString(base14SubstFonts[substIdx]);
781
28.9k
    if (ps) {
782
0
      error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
783
0
      base14SubstFonts[substIdx], name);
784
0
      fontLoc = new GfxFontLoc();
785
0
      fontLoc->locType = gfxFontLocResident;
786
0
      fontLoc->fontType = fontType1;
787
0
      fontLoc->path = substName;
788
0
      fontLoc->substIdx = substIdx;
789
0
      return fontLoc;
790
28.9k
    } else {
791
28.9k
      path = globalParams->findBase14FontFile(substName, &fontNum, &oblique);
792
28.9k
      delete substName;
793
28.9k
      if (path) {
794
0
  if ((fontLoc = getExternalFont(path, fontNum, oblique, gFalse))) {
795
0
    error(errSyntaxWarning, -1, "Substituting font '{0:s}' for '{1:t}'",
796
0
    base14SubstFonts[substIdx], name);
797
0
    fontLoc->substIdx = substIdx;
798
0
    return fontLoc;
799
0
  }
800
0
      }
801
28.9k
    }
802
803
    // failed to find a substitute font
804
28.9k
    return NULL;
805
28.9k
  }
806
807
  //----- 16-bit PS resident font
808
12.2k
  if (ps && name && ((psFont16 = globalParams->getPSResidentFont16(
809
0
           name,
810
0
           ((GfxCIDFont *)this)->getWMode())))) {
811
0
    fontLoc = new GfxFontLoc();
812
0
    fontLoc->locType = gfxFontLocResident;
813
0
    fontLoc->fontType = fontCIDType0; // this is not used
814
0
    fontLoc->path = psFont16->psFontName->copy();
815
0
    fontLoc->encoding = psFont16->encoding->copy();
816
0
    fontLoc->wMode = psFont16->wMode;
817
0
    return fontLoc;
818
0
  }
819
12.2k
  if (ps && ((psFont16 = globalParams->getPSResidentFontCC(
820
0
         ((GfxCIDFont *)this)->getCollection(),
821
0
         ((GfxCIDFont *)this)->getWMode())))) {
822
0
    error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
823
0
    psFont16->psFontName, name);
824
0
    fontLoc = new GfxFontLoc();
825
0
    fontLoc->locType = gfxFontLocResident;
826
0
    fontLoc->fontType = fontCIDType0; // this is not used
827
0
    fontLoc->path = psFont16->psFontName->copy();
828
0
    fontLoc->encoding = psFont16->encoding->copy();
829
0
    fontLoc->wMode = psFont16->wMode;
830
0
    return fontLoc;
831
0
  }
832
833
  //----- CID font substitution
834
12.2k
  if ((path = globalParams->findCCFontFile(
835
12.2k
        ((GfxCIDFont *)this)->getCollection()))) {
836
0
    if ((fontLoc = getExternalFont(path, 0, 0, gTrue))) {
837
0
      error(errSyntaxWarning, -1, "Substituting font '{0:t}' for '{1:t}'",
838
0
      fontLoc->path, name);
839
0
      return fontLoc;
840
0
    }
841
0
  }
842
843
  // failed to find a substitute font
844
12.2k
  return NULL;
845
12.2k
}
846
847
0
GfxFontLoc *GfxFont::locateBase14Font(GString *base14Name) {
848
0
  GString *path;
849
0
  int fontNum;
850
0
  double oblique;
851
852
0
  path = globalParams->findBase14FontFile(base14Name, &fontNum, &oblique);
853
0
  if (!path) {
854
0
    return NULL;
855
0
  }
856
0
  return getExternalFont(path, fontNum, oblique, gFalse);
857
0
}
858
859
GfxFontLoc *GfxFont::getExternalFont(GString *path, int fontNum,
860
0
             double oblique, GBool cid) {
861
0
  FoFiIdentifierType fft;
862
0
  GfxFontType fontType;
863
0
  GfxFontLoc *fontLoc;
864
865
0
  fft = FoFiIdentifier::identifyFile(path->getCString());
866
0
  switch (fft) {
867
0
  case fofiIdType1PFA:
868
0
  case fofiIdType1PFB:
869
0
    fontType = fontType1;
870
0
    break;
871
0
  case fofiIdCFF8Bit:
872
0
    fontType = fontType1C;
873
0
    break;
874
0
  case fofiIdCFFCID:
875
0
    fontType = fontCIDType0C;
876
0
    break;
877
0
  case fofiIdTrueType:
878
0
  case fofiIdTrueTypeCollection:
879
0
    fontType = cid ? fontCIDType2 : fontTrueType;
880
0
    break;
881
0
  case fofiIdOpenTypeCFF8Bit:
882
0
    fontType = fontType1COT;
883
0
    break;
884
0
  case fofiIdOpenTypeCFFCID:
885
0
    fontType = fontCIDType0COT;
886
0
    break;
887
0
  case fofiIdDfont:
888
0
    fontType = cid ? fontCIDType2 : fontTrueType;
889
0
    break;
890
0
  case fofiIdUnknown:
891
0
  case fofiIdError:
892
0
  default:
893
0
    fontType = fontUnknownType;
894
0
    break;
895
0
  }
896
0
  if (fontType == fontUnknownType ||
897
0
      (cid ? (fontType < fontCIDType0)
898
0
           : (fontType >= fontCIDType0))) {
899
0
    delete path;
900
0
    return NULL;
901
0
  }
902
0
  fontLoc = new GfxFontLoc();
903
0
  fontLoc->locType = gfxFontLocExternal;
904
0
  fontLoc->fontType = fontType;
905
0
  fontLoc->path = path;
906
0
  fontLoc->fontNum = fontNum;
907
0
  fontLoc->oblique = oblique;
908
0
  return fontLoc;
909
0
}
910
911
4.74k
char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
912
4.74k
  char *buf;
913
4.74k
  Object obj1, obj2;
914
4.74k
  Stream *str;
915
4.74k
  int size, n;
916
917
4.74k
  obj1.initRef(embFontID.num, embFontID.gen);
918
4.74k
  obj1.fetch(xref, &obj2);
919
4.74k
  if (!obj2.isStream()) {
920
0
    error(errSyntaxError, -1, "Embedded font file is not a stream");
921
0
    obj2.free();
922
0
    obj1.free();
923
0
    embFontID.num = -1;
924
0
    return NULL;
925
0
  }
926
4.74k
  str = obj2.getStream();
927
928
4.74k
  size = 4096;
929
4.74k
  buf = (char *)gmalloc(size);
930
4.74k
  *len = 0;
931
4.74k
  str->reset();
932
11.0k
  do {
933
11.0k
    if (*len > size - 4096) {
934
5.17k
      if (size > INT_MAX / 2) {
935
0
  error(errSyntaxError, -1, "Embedded font file is too large");
936
0
  break;
937
0
      }
938
5.17k
      size *= 2;
939
5.17k
      buf = (char *)grealloc(buf, size);
940
5.17k
    }
941
11.0k
    n = str->getBlock(buf + *len, 4096);
942
11.0k
    *len += n;
943
11.0k
  } while (n == 4096);
944
4.74k
  str->close();
945
946
4.74k
  obj2.free();
947
4.74k
  obj1.free();
948
949
4.74k
  return buf;
950
4.74k
}
951
952
//------------------------------------------------------------------------
953
// Gfx8BitFont
954
//------------------------------------------------------------------------
955
956
Gfx8BitFont::Gfx8BitFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
957
       GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
958
51.0k
  GfxFont(tagA, idA, nameA, typeA, embFontIDA)
959
51.0k
{
960
51.0k
  GString *name2;
961
51.0k
  BuiltinFont *builtinFont;
962
51.0k
  const char **baseEnc;
963
51.0k
  char *buf;
964
51.0k
  int len;
965
51.0k
  FoFiType1 *ffT1;
966
51.0k
  FoFiType1C *ffT1C;
967
51.0k
  int code, code2;
968
51.0k
  char *charName;
969
51.0k
  GBool missing, hex;
970
51.0k
  Unicode toUnicode[256];
971
51.0k
  CharCodeToUnicode *utu, *ctu2;
972
51.0k
  Unicode uBuf[8];
973
51.0k
  double mul;
974
51.0k
  int firstChar, lastChar;
975
51.0k
  Gushort w;
976
51.0k
  Object obj1, obj2, obj3;
977
51.0k
  int n, i, a, b, m;
978
979
51.0k
  ctu = NULL;
980
981
  // do font name substitution for various aliases of the Base 14 font
982
  // names
983
51.0k
  base14 = NULL;
984
51.0k
  if (name) {
985
36.7k
    name2 = name->copy();
986
36.7k
    i = 0;
987
471k
    while (i < name2->getLength()) {
988
434k
      if (name2->getChar(i) == ' ') {
989
1.79k
  name2->del(i);
990
432k
      } else {
991
432k
  ++i;
992
432k
      }
993
434k
    }
994
36.7k
    a = 0;
995
36.7k
    b = sizeof(base14FontMap) / sizeof(Base14FontMapEntry);
996
    // invariant: base14FontMap[a].altName <= name2 < base14FontMap[b].altName
997
258k
    while (b - a > 1) {
998
221k
      m = (a + b) / 2;
999
221k
      if (name2->cmp(base14FontMap[m].altName) >= 0) {
1000
127k
  a = m;
1001
127k
      } else {
1002
94.3k
  b = m;
1003
94.3k
      }
1004
221k
    }
1005
36.7k
    if (!name2->cmp(base14FontMap[a].altName)) {
1006
25.9k
      base14 = &base14FontMap[a];
1007
25.9k
    }
1008
36.7k
    delete name2;
1009
36.7k
  }
1010
1011
  // is it a built-in font?
1012
51.0k
  builtinFont = NULL;
1013
51.0k
  if (base14) {
1014
127k
    for (i = 0; i < nBuiltinFonts; ++i) {
1015
127k
      if (!strcmp(base14->base14Name, builtinFonts[i].name)) {
1016
25.9k
  builtinFont = &builtinFonts[i];
1017
25.9k
  break;
1018
25.9k
      }
1019
127k
    }
1020
25.9k
  }
1021
1022
  // default ascent/descent values
1023
51.0k
  if (builtinFont) {
1024
25.9k
    missingWidth = builtinFont->missingWidth;
1025
25.9k
    ascent = 0.001 * builtinFont->ascent;
1026
25.9k
    descent = 0.001 * builtinFont->descent;
1027
25.9k
    declaredAscent = ascent;
1028
25.9k
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
1029
25.9k
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
1030
25.9k
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
1031
25.9k
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
1032
25.9k
  } else {
1033
25.0k
    missingWidth = 0;
1034
25.0k
    ascent = 0.75;
1035
25.0k
    descent = -0.25;
1036
25.0k
    declaredAscent = ascent;
1037
25.0k
    fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
1038
25.0k
  }
1039
1040
  // get info from font descriptor
1041
51.0k
  readFontDescriptor(xref, fontDict);
1042
1043
  // for Base-14 fonts (even if embedded), don't trust the
1044
  // ascent/descent/bbox values from the font descriptor
1045
51.0k
  if (builtinFont) {
1046
25.9k
    ascent = 0.001 * builtinFont->ascent;
1047
25.9k
    descent = 0.001 * builtinFont->descent;
1048
25.9k
    declaredAscent = ascent;
1049
25.9k
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
1050
25.9k
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
1051
25.9k
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
1052
25.9k
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
1053
25.9k
  }
1054
1055
  // get font matrix
1056
51.0k
  fontMat[0] = fontMat[3] = 1;
1057
51.0k
  fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
1058
51.0k
  if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
1059
27.4k
    for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
1060
22.6k
      if (obj1.arrayGet(i, &obj2)->isNum()) {
1061
16.7k
  fontMat[i] = obj2.getNum();
1062
16.7k
      }
1063
22.6k
      obj2.free();
1064
22.6k
    }
1065
4.78k
  }
1066
51.0k
  obj1.free();
1067
1068
  // get Type 3 bounding box, font definition, and resources
1069
51.0k
  if (type == fontType3) {
1070
6.78k
    if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
1071
29.2k
      for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
1072
23.3k
  if (obj1.arrayGet(i, &obj2)->isNum()) {
1073
22.0k
    fontBBox[i] = obj2.getNum();
1074
22.0k
  }
1075
23.3k
  obj2.free();
1076
23.3k
      }
1077
5.92k
    }
1078
6.78k
    obj1.free();
1079
6.78k
    if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
1080
4.29k
      error(errSyntaxError, -1,
1081
4.29k
      "Missing or invalid CharProcs dictionary in Type 3 font");
1082
4.29k
      charProcs.free();
1083
4.29k
    }
1084
6.78k
    if (!fontDict->lookup("Resources", &resources)->isDict()) {
1085
4.66k
      resources.free();
1086
4.66k
    }
1087
6.78k
  }
1088
1089
  //----- build the font encoding -----
1090
1091
  // Encodings start with a base encoding, which can come from
1092
  // (in order of priority):
1093
  //   1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
1094
  //        - MacRoman / MacExpert / WinAnsi / Standard
1095
  //   2. embedded or external font file
1096
  //   3. default:
1097
  //        - builtin --> builtin encoding
1098
  //        - TrueType --> WinAnsiEncoding
1099
  //        - others --> StandardEncoding
1100
  // and then add a list of differences (if any) from
1101
  // FontDict.Encoding.Differences.
1102
1103
  // check FontDict for base encoding
1104
51.0k
  hasEncoding = gFalse;
1105
51.0k
  usesMacRomanEnc = gFalse;
1106
51.0k
  baseEnc = NULL;
1107
51.0k
  baseEncFromFontFile = gFalse;
1108
51.0k
  fontDict->lookup("Encoding", &obj1);
1109
51.0k
  if (obj1.isDict()) {
1110
8.60k
    obj1.dictLookup("BaseEncoding", &obj2);
1111
8.60k
    if (obj2.isName("MacRomanEncoding")) {
1112
0
      hasEncoding = gTrue;
1113
0
      usesMacRomanEnc = gTrue;
1114
0
      baseEnc = macRomanEncoding;
1115
8.60k
    } else if (obj2.isName("MacExpertEncoding")) {
1116
0
      hasEncoding = gTrue;
1117
0
      baseEnc = macExpertEncoding;
1118
8.60k
    } else if (obj2.isName("WinAnsiEncoding")) {
1119
286
      hasEncoding = gTrue;
1120
286
      baseEnc = winAnsiEncoding;
1121
286
    }
1122
8.60k
    obj2.free();
1123
42.4k
  } else if (obj1.isName("MacRomanEncoding")) {
1124
1.48k
    hasEncoding = gTrue;
1125
1.48k
    usesMacRomanEnc = gTrue;
1126
1.48k
    baseEnc = macRomanEncoding;
1127
40.9k
  } else if (obj1.isName("MacExpertEncoding")) {
1128
0
    hasEncoding = gTrue;
1129
0
    baseEnc = macExpertEncoding;
1130
40.9k
  } else if (obj1.isName("WinAnsiEncoding")) {
1131
2.32k
    hasEncoding = gTrue;
1132
2.32k
    baseEnc = winAnsiEncoding;
1133
2.32k
  }
1134
1135
  // a non-embedded Symbol or ZapfDingbats font should never use one
1136
  // of the non-symbol encodings -- I've encountered PDF files that
1137
  // set the Encoding to WinAnsiEncoding, which doesn't make any sense
1138
  // (and other viewers also seem to ignore it)
1139
51.0k
  if (builtinFont && embFontID.num < 0 &&
1140
24.8k
      (builtinFont->defaultBaseEnc == symbolEncoding ||
1141
24.8k
       builtinFont->defaultBaseEnc == zapfDingbatsEncoding) &&
1142
35
      !obj1.isDict()) {
1143
35
    baseEnc = NULL;
1144
35
  }
1145
1146
  // check embedded font file for base encoding
1147
  // (only for Type 1 fonts - trying to get an encoding out of a
1148
  // TrueType font is a losing proposition)
1149
51.0k
  ffT1 = NULL;
1150
51.0k
  ffT1C = NULL;
1151
51.0k
  buf = NULL;
1152
51.0k
  if (type == fontType1 && embFontID.num >= 0) {
1153
1.88k
    if ((buf = readEmbFontFile(xref, &len))) {
1154
1.88k
      if ((ffT1 = FoFiType1::make(buf, len))) {
1155
1.88k
  if (ffT1->getName()) {
1156
502
    if (embFontName) {
1157
436
      delete embFontName;
1158
436
    }
1159
502
    embFontName = new GString(ffT1->getName());
1160
502
  }
1161
1.88k
  if (!baseEnc) {
1162
1.87k
    baseEnc = (const char **)ffT1->getEncoding();
1163
1.87k
    baseEncFromFontFile = gTrue;
1164
1.87k
  }
1165
1.88k
      }
1166
1.88k
      gfree(buf);
1167
1.88k
    }
1168
49.1k
  } else if (type == fontType1C && embFontID.num >= 0) {
1169
2.85k
    if ((buf = readEmbFontFile(xref, &len))) {
1170
2.85k
      if ((ffT1C = FoFiType1C::make(buf, len))) {
1171
1.76k
  if (ffT1C->getName()) {
1172
1.76k
    if (embFontName) {
1173
1.16k
      delete embFontName;
1174
1.16k
    }
1175
1.76k
    embFontName = new GString(ffT1C->getName());
1176
1.76k
  }
1177
1.76k
  if (!baseEnc) {
1178
842
    baseEnc = (const char **)ffT1C->getEncoding();
1179
842
    baseEncFromFontFile = gTrue;
1180
842
  }
1181
1.76k
      }
1182
2.85k
      gfree(buf);
1183
2.85k
    }
1184
2.85k
  }
1185
1186
  // get default base encoding
1187
51.0k
  if (!baseEnc) {
1188
45.4k
    if (builtinFont && embFontID.num < 0) {
1189
23.9k
      baseEnc = builtinFont->defaultBaseEnc;
1190
23.9k
      hasEncoding = gTrue;
1191
23.9k
    } else if (type == fontTrueType) {
1192
3.37k
      baseEnc = winAnsiEncoding;
1193
18.1k
    } else {
1194
18.1k
      baseEnc = standardEncoding;
1195
18.1k
    }
1196
45.4k
  }
1197
1198
  // copy the base encoding
1199
13.1M
  for (i = 0; i < 256; ++i) {
1200
13.0M
    enc[i] = (char *)baseEnc[i];
1201
13.0M
    if ((encFree[i] = (char)baseEncFromFontFile) && enc[i]) {
1202
243k
      enc[i] = copyString(baseEnc[i]);
1203
243k
    }
1204
13.0M
  }
1205
1206
  // some Type 1C font files have empty encodings, which can break the
1207
  // T1C->T1 conversion (since the 'seac' operator depends on having
1208
  // the accents in the encoding), so we fill in any gaps from
1209
  // StandardEncoding
1210
51.0k
  if (type == fontType1C && embFontID.num >= 0 && baseEncFromFontFile) {
1211
216k
    for (i = 0; i < 256; ++i) {
1212
215k
      if (!enc[i] && standardEncoding[i]) {
1213
86.6k
  enc[i] = (char *)standardEncoding[i];
1214
86.6k
  encFree[i] = gFalse;
1215
86.6k
      }
1216
215k
    }
1217
842
  }
1218
1219
  // merge differences into encoding
1220
51.0k
  if (obj1.isDict()) {
1221
8.60k
    obj1.dictLookup("Differences", &obj2);
1222
8.60k
    if (obj2.isArray()) {
1223
5.12k
      hasEncoding = gTrue;
1224
5.12k
      code = 0;
1225
315k
      for (i = 0; i < obj2.arrayGetLength(); ++i) {
1226
310k
  obj2.arrayGet(i, &obj3);
1227
310k
  if (obj3.isInt()) {
1228
61.6k
    code = obj3.getInt();
1229
248k
  } else if (obj3.isName()) {
1230
149k
    if (code >= 0 && code < 256) {
1231
147k
      if (encFree[code]) {
1232
26.2k
        gfree(enc[code]);
1233
26.2k
      }
1234
147k
      enc[code] = copyString(obj3.getName());
1235
147k
      encFree[code] = gTrue;
1236
147k
    }
1237
149k
    ++code;
1238
149k
  } else {
1239
99.7k
    error(errSyntaxError, -1,
1240
99.7k
    "Wrong type in font encoding resource differences ({0:s})",
1241
99.7k
    obj3.getTypeName());
1242
99.7k
  }
1243
310k
  obj3.free();
1244
310k
      }
1245
5.12k
    }
1246
8.60k
    obj2.free();
1247
8.60k
  }
1248
51.0k
  obj1.free();
1249
51.0k
  if (ffT1) {
1250
1.88k
    delete ffT1;
1251
1.88k
  }
1252
51.0k
  if (ffT1C) {
1253
1.76k
    delete ffT1C;
1254
1.76k
  }
1255
1256
  //----- build the mapping to Unicode -----
1257
1258
  // pass 1: use the name-to-Unicode mapping table
1259
51.0k
  missing = hex = gFalse;
1260
13.1M
  for (code = 0; code < 256; ++code) {
1261
13.0M
    if ((charName = enc[code])) {
1262
8.12M
      if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
1263
61.8k
    strcmp(charName, ".notdef")) {
1264
  // if it wasn't in the name-to-Unicode table, check for a
1265
  // name that looks like 'Axx' or 'xx', where 'A' is any letter
1266
  // and 'xx' is two hex digits
1267
52.7k
  if ((strlen(charName) == 3 &&
1268
15.7k
       isalpha(charName[0] & 0xff) &&
1269
15.6k
       isxdigit(charName[1] & 0xff) && isxdigit(charName[2] & 0xff) &&
1270
13.3k
       ((charName[1] >= 'a' && charName[1] <= 'f') ||
1271
12.6k
        (charName[1] >= 'A' && charName[1] <= 'F') ||
1272
12.6k
        (charName[2] >= 'a' && charName[2] <= 'f') ||
1273
11.9k
        (charName[2] >= 'A' && charName[2] <= 'F'))) ||
1274
51.3k
      (strlen(charName) == 2 &&
1275
5.09k
       isxdigit(charName[0] & 0xff) && isxdigit(charName[1] & 0xff) &&
1276
1.81k
       ((charName[0] >= 'a' && charName[0] <= 'f') ||
1277
1.57k
        (charName[0] >= 'A' && charName[0] <= 'F') ||
1278
220
        (charName[1] >= 'a' && charName[1] <= 'f') ||
1279
3.09k
        (charName[1] >= 'A' && charName[1] <= 'F')))) {
1280
3.09k
    hex = gTrue;
1281
3.09k
  }
1282
52.7k
  missing = gTrue;
1283
52.7k
      }
1284
8.12M
    } else {
1285
4.93M
      toUnicode[code] = 0;
1286
4.93M
    }
1287
13.0M
  }
1288
1289
  // pass 2: try to fill in the missing chars, looking for names of
1290
  // any of the following forms:
1291
  // - 'xx'
1292
  // - 'Axx'
1293
  // - 'nn'
1294
  // - 'Ann'
1295
  // - 'ABnn'
1296
  // - 'unixxxx' (possibly followed by garbage - some Arabic files
1297
  //             use 'uni0628.medi', etc.)
1298
  // where 'A' and 'B' are any letters, 'xx' is two hex digits, 'xxxx'
1299
  // is four hex digits, and 'nn' is 2-4 decimal digits
1300
51.0k
  usedNumericHeuristic = gFalse;
1301
51.0k
  if (missing && globalParams->getMapNumericCharNames()) {
1302
1.08M
    for (code = 0; code < 256; ++code) {
1303
1.08M
      if ((charName = enc[code]) && !toUnicode[code] &&
1304
56.6k
    strcmp(charName, ".notdef")) {
1305
52.7k
  n = (int)strlen(charName);
1306
52.7k
  code2 = -1;
1307
52.7k
  if (hex && n == 3 && isalpha(charName[0] & 0xff) &&
1308
6.74k
      isxdigit(charName[1] & 0xff) && isxdigit(charName[2] & 0xff)) {
1309
6.31k
    sscanf(charName+1, "%x", &code2);
1310
46.4k
  } else if (hex && n == 2 &&
1311
2.67k
       isxdigit(charName[0] & 0xff) &&
1312
2.51k
       isxdigit(charName[1] & 0xff)) {
1313
1.77k
    sscanf(charName, "%x", &code2);
1314
44.6k
  } else if (!hex && n >= 2 && n <= 4 &&
1315
28.0k
       isdigit(charName[0] & 0xff) && isdigit(charName[1] & 0xff)) {
1316
49
    code2 = atoi(charName);
1317
44.5k
  } else if (n >= 3 && n <= 5 &&
1318
29.7k
       isdigit(charName[1] & 0xff) && isdigit(charName[2] & 0xff)) {
1319
23.4k
    code2 = atoi(charName+1);
1320
23.4k
  } else if (n >= 4 && n <= 6 &&
1321
4.47k
       isdigit(charName[2] & 0xff) && isdigit(charName[3] & 0xff)) {
1322
70
    code2 = atoi(charName+2);
1323
21.0k
  } else if (n >= 7 && charName[0] == 'u' && charName[1] == 'n' &&
1324
69
       charName[2] == 'i' &&
1325
63
       isxdigit(charName[3] & 0xff) &&
1326
49
       isxdigit(charName[4] & 0xff) &&
1327
48
       isxdigit(charName[5] & 0xff) &&
1328
47
       isxdigit(charName[6] & 0xff)) {
1329
46
    sscanf(charName + 3, "%x", &code2);
1330
46
  }
1331
52.7k
  if (code2 >= 0 && code2 <= 0xffff) {
1332
31.6k
    toUnicode[code] = (Unicode)code2;
1333
31.6k
    usedNumericHeuristic = gTrue;
1334
31.6k
  }
1335
52.7k
      }
1336
1.08M
    }
1337
1338
  // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
1339
  // mapping for unknown character names
1340
46.8k
  } else if (missing && globalParams->getMapUnknownCharNames()) {
1341
0
    for (code = 0; code < 256; ++code) {
1342
0
      if (!toUnicode[code]) {
1343
0
  toUnicode[code] = code;
1344
0
      }
1345
0
    }
1346
0
  }
1347
1348
  // construct the char code -> Unicode mapping object
1349
51.0k
  ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
1350
1351
  // merge in a ToUnicode CMap, if there is one -- this overwrites
1352
  // existing entries in ctu, i.e., the ToUnicode CMap takes
1353
  // precedence, but the other encoding info is allowed to fill in any
1354
  // holes
1355
51.0k
  readToUnicodeCMap(fontDict, 8, ctu);
1356
1357
  // look for a Unicode-to-Unicode mapping
1358
51.0k
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
1359
0
    for (i = 0; i < 256; ++i) {
1360
0
      toUnicode[i] = 0;
1361
0
    }
1362
0
    ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
1363
0
    for (i = 0; i < 256; ++i) {
1364
0
      n = ctu->mapToUnicode((CharCode)i, uBuf, 8);
1365
0
      if (n >= 1) {
1366
0
  n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
1367
0
  if (n >= 1) {
1368
0
    ctu2->setMapping((CharCode)i, uBuf, n);
1369
0
  }
1370
0
      }
1371
0
    }
1372
0
    utu->decRefCnt();
1373
0
    delete ctu;
1374
0
    ctu = ctu2;
1375
0
  }
1376
1377
  //----- get the character widths -----
1378
1379
  // initialize all widths
1380
13.1M
  for (code = 0; code < 256; ++code) {
1381
13.0M
    widths[code] = missingWidth * 0.001;
1382
13.0M
  }
1383
1384
  // use widths from font dict, if present
1385
51.0k
  fontDict->lookup("FirstChar", &obj1);
1386
51.0k
  firstChar = obj1.isInt() ? obj1.getInt() : 0;
1387
51.0k
  obj1.free();
1388
51.0k
  if (firstChar < 0 || firstChar > 255) {
1389
36
    firstChar = 0;
1390
36
  }
1391
51.0k
  fontDict->lookup("LastChar", &obj1);
1392
51.0k
  lastChar = obj1.isInt() ? obj1.getInt() : 255;
1393
51.0k
  obj1.free();
1394
51.0k
  if (lastChar < 0 || lastChar > 255) {
1395
513
    lastChar = 255;
1396
513
  }
1397
51.0k
  mul = (type == fontType3) ? fontMat[0] : 0.001;
1398
51.0k
  fontDict->lookup("Widths", &obj1);
1399
51.0k
  if (obj1.isArray()) {
1400
14.7k
    flags |= fontFixedWidth;
1401
14.7k
    if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
1402
7.69k
      lastChar = firstChar + obj1.arrayGetLength() - 1;
1403
7.69k
    }
1404
637k
    for (code = firstChar; code <= lastChar; ++code) {
1405
622k
      obj1.arrayGet(code - firstChar, &obj2);
1406
622k
      if (obj2.isNum()) {
1407
563k
  widths[code] = obj2.getNum() * mul;
1408
563k
  if (fabs(widths[code] - widths[firstChar]) > 0.00001) {
1409
504k
    flags &= ~fontFixedWidth;
1410
504k
  }
1411
563k
      }
1412
622k
      obj2.free();
1413
622k
    }
1414
1415
  // use widths from built-in font
1416
36.3k
  } else if (builtinFont) {
1417
    // this is a kludge for broken PDF files that encode char 32
1418
    // as .notdef
1419
25.9k
    if (builtinFont->widths->getWidth("space", &w)) {
1420
25.9k
      widths[32] = 0.001 * w;
1421
25.9k
    }
1422
6.66M
    for (code = 0; code < 256; ++code) {
1423
6.63M
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
1424
4.01M
  widths[code] = 0.001 * w;
1425
4.01M
      }
1426
6.63M
    }
1427
1428
  // couldn't find widths -- use defaults 
1429
25.9k
  } else {
1430
    // this is technically an error -- the Widths entry is required
1431
    // for all but the Base-14 fonts -- but certain PDF generators
1432
    // apparently don't include widths for Arial and TimesNewRoman
1433
10.3k
    if (isFixedWidth()) {
1434
1.32k
      i = 0;
1435
9.07k
    } else if (isSerif()) {
1436
8.32k
      i = 8;
1437
8.32k
    } else {
1438
741
      i = 4;
1439
741
    }
1440
10.3k
    if (isBold()) {
1441
185
      i += 2;
1442
185
    }
1443
10.3k
    if (isItalic()) {
1444
47
      i += 1;
1445
47
    }
1446
10.3k
    builtinFont = builtinFontSubst[i];
1447
    // this is a kludge for broken PDF files that encode char 32
1448
    // as .notdef
1449
10.3k
    if (builtinFont->widths->getWidth("space", &w)) {
1450
10.3k
      widths[32] = 0.001 * w;
1451
10.3k
    }
1452
2.67M
    for (code = 0; code < 256; ++code) {
1453
2.66M
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
1454
1.58M
  widths[code] = 0.001 * w;
1455
1.58M
      }
1456
2.66M
    }
1457
10.3k
  }
1458
51.0k
  obj1.free();
1459
1460
51.0k
  ok = gTrue;
1461
51.0k
}
1462
1463
51.0k
Gfx8BitFont::~Gfx8BitFont() {
1464
51.0k
  int i;
1465
1466
13.1M
  for (i = 0; i < 256; ++i) {
1467
13.0M
    if (encFree[i] && enc[i]) {
1468
374k
      gfree(enc[i]);
1469
374k
    }
1470
13.0M
  }
1471
51.0k
  ctu->decRefCnt();
1472
51.0k
  if (charProcs.isDict()) {
1473
2.48k
    charProcs.free();
1474
2.48k
  }
1475
51.0k
  if (resources.isDict()) {
1476
2.12k
    resources.free();
1477
2.12k
  }
1478
51.0k
}
1479
1480
int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
1481
           Unicode *u, int uSize, int *uLen,
1482
8.08M
           double *dx, double *dy, double *ox, double *oy) {
1483
8.08M
  CharCode c;
1484
1485
8.08M
  *code = c = (CharCode)(*s & 0xff);
1486
8.08M
  *uLen = ctu->mapToUnicode(c, u, uSize);
1487
8.08M
  *dx = widths[c];
1488
8.08M
  *dy = *ox = *oy = 0;
1489
8.08M
  return 1;
1490
8.08M
}
1491
1492
0
CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
1493
0
  ctu->incRefCnt();
1494
0
  return ctu;
1495
0
}
1496
1497
2.26k
int *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
1498
2.26k
  int *map;
1499
2.26k
  int cmapPlatform, cmapEncoding;
1500
2.26k
  int unicodeCmap, macRomanCmap, macUnicodeCmap, msSymbolCmap, cmap;
1501
2.26k
  GBool nonsymbolic, useMacRoman, useUnicode;
1502
2.26k
  char *charName;
1503
2.26k
  Unicode u;
1504
2.26k
  int code, i, n;
1505
1506
2.26k
  map = (int *)gmallocn(256, sizeof(int));
1507
582k
  for (i = 0; i < 256; ++i) {
1508
580k
    map[i] = 0;
1509
580k
  }
1510
1511
  // This is based on the cmap/encoding selection algorithm in the PDF
1512
  // 2.0 spec, but with some differences to match up with Adobe's
1513
  // behavior.
1514
2.26k
  unicodeCmap = macRomanCmap = macUnicodeCmap = msSymbolCmap = -1;
1515
4.60k
  for (i = 0; i < ff->getNumCmaps(); ++i) {
1516
2.33k
    cmapPlatform = ff->getCmapPlatform(i);
1517
2.33k
    cmapEncoding = ff->getCmapEncoding(i);
1518
2.33k
    if (cmapPlatform == 3 && cmapEncoding == 1) {
1519
6
      unicodeCmap = i;
1520
2.32k
    } else if (cmapPlatform == 1 && cmapEncoding == 0) {
1521
1.20k
      macRomanCmap = i;
1522
1.20k
    } else if (cmapPlatform == 0 && cmapEncoding <= 4) {
1523
203
      macUnicodeCmap = i;
1524
925
    } else if (cmapPlatform == 3 && cmapEncoding == 0) {
1525
11
      msSymbolCmap = i;
1526
11
    }
1527
2.33k
  }
1528
2.26k
  useMacRoman = gFalse;
1529
2.26k
  useUnicode = gFalse;
1530
2.26k
  nonsymbolic = !(flags & fontSymbolic);
1531
2.26k
  if (embFontID.num < 0 && hasEncoding && unicodeCmap >= 0) { 
1532
0
    cmap = unicodeCmap;
1533
0
    useUnicode = gTrue;
1534
2.26k
  } else if (!nonsymbolic && msSymbolCmap >= 0) {
1535
11
    cmap = msSymbolCmap;
1536
2.25k
  } else if (unicodeCmap >= 0) {
1537
3
    cmap = unicodeCmap;
1538
3
    useUnicode = nonsymbolic;
1539
2.25k
  } else if (usesMacRomanEnc && macRomanCmap >= 0) {
1540
    // MacRoman cmap has higher precedence than Mac Unicode only if
1541
    // the font uses the MacRoman encoding
1542
0
    cmap = macRomanCmap;
1543
0
    useMacRoman = gTrue;
1544
2.25k
  } else if (macUnicodeCmap >= 0) {
1545
46
    cmap = macUnicodeCmap;
1546
46
    useUnicode = nonsymbolic;
1547
2.20k
  } else if (macRomanCmap >= 0) {
1548
1.19k
    cmap = macRomanCmap;
1549
1.19k
    useMacRoman = nonsymbolic;
1550
1.19k
  } else {
1551
1.01k
    cmap = 0;
1552
1.01k
  }
1553
1554
  // reverse map the char names through MacRomanEncoding, then map the
1555
  // char codes through the cmap; fall back on Unicode if that doesn't
1556
  // work
1557
2.26k
  if (useMacRoman) {
1558
119k
    for (i = 0; i < 256; ++i) {
1559
119k
      if ((charName = enc[i])) {
1560
104k
  if ((code = globalParams->getMacRomanCharCode(charName))) {
1561
95.3k
    map[i] = ff->mapCodeToGID(cmap, code);
1562
95.3k
  } else if (unicodeCmap >= 0 &&
1563
0
       (u = globalParams->mapNameToUnicode(charName))) {
1564
0
    map[i] = ff->mapCodeToGID(unicodeCmap, u);
1565
0
  }
1566
104k
      } else if (unicodeCmap >= 0 &&
1567
0
     (n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
1568
0
  map[i] = ff->mapCodeToGID(cmap, u);
1569
14.8k
      } else {
1570
14.8k
  map[i] = -1;
1571
14.8k
      }
1572
119k
    }
1573
1574
  // map Unicode through the cmap
1575
1.80k
  } else if (useUnicode) {
1576
8.22k
    for (i = 0; i < 256; ++i) {
1577
8.19k
      if (((charName = enc[i]) &&
1578
7.16k
     (u = globalParams->mapNameToUnicode(charName))) ||
1579
7.26k
    (n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
1580
7.26k
  map[i] = ff->mapCodeToGID(cmap, u);
1581
7.26k
      } else {
1582
926
  map[i] = -1;
1583
926
      }
1584
8.19k
    }
1585
1586
  // map the char codes through the cmap, possibly with an offset of
1587
  // 0xf000
1588
1.77k
  } else {
1589
454k
    for (i = 0; i < 256; ++i) {
1590
453k
      if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
1591
362k
  map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
1592
362k
      }
1593
453k
    }
1594
1.77k
  }
1595
1596
  // try the TrueType 'post' table to handle any unmapped characters
1597
582k
  for (i = 0; i < 256; ++i) {
1598
580k
    if (map[i] <= 0 && (charName = enc[i])) {
1599
412k
      map[i] = ff->mapNameToGID(charName);
1600
412k
    }
1601
580k
  }
1602
1603
2.26k
  return map;
1604
2.26k
}
1605
1606
1.24k
int *Gfx8BitFont::getCodeToGIDMap(FoFiType1C *ff) {
1607
1.24k
  int *map;
1608
1.24k
  GHash *nameToGID;
1609
1.24k
  int i, gid;
1610
1611
1.24k
  map = (int *)gmallocn(256, sizeof(int));
1612
319k
  for (i = 0; i < 256; ++i) {
1613
318k
    map[i] = 0;
1614
318k
  }
1615
1616
1.24k
  nameToGID = ff->getNameToGIDMap();
1617
319k
  for (i = 0; i < 256; ++i) {
1618
318k
    if (!enc[i]) {
1619
64.8k
      continue;
1620
64.8k
    }
1621
253k
    gid = nameToGID->lookupInt(enc[i]);
1622
253k
    if (gid < 0 || gid >= 65536) {
1623
0
      continue;
1624
0
    }
1625
253k
    map[i] = gid;
1626
253k
  }
1627
1628
1.24k
  delete nameToGID;
1629
1630
1.24k
  return map;
1631
1.24k
}
1632
1633
0
Dict *Gfx8BitFont::getCharProcs() {
1634
0
  return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
1635
0
}
1636
1637
0
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
1638
0
  if (enc[code] && charProcs.isDict()) {
1639
0
    charProcs.dictLookup(enc[code], proc);
1640
0
  } else {
1641
0
    proc->initNull();
1642
0
  }
1643
0
  return proc;
1644
0
}
1645
1646
2.24M
Object *Gfx8BitFont::getCharProcNF(int code, Object *proc) {
1647
2.24M
  if (enc[code] && charProcs.isDict()) {
1648
1.28M
    charProcs.dictLookupNF(enc[code], proc);
1649
1.28M
  } else {
1650
953k
    proc->initNull();
1651
953k
  }
1652
2.24M
  return proc;
1653
2.24M
}
1654
1655
2.24M
Dict *Gfx8BitFont::getResources() {
1656
2.24M
  return resources.isDict() ? resources.getDict() : (Dict *)NULL;
1657
2.24M
}
1658
1659
0
GBool Gfx8BitFont::problematicForUnicode() {
1660
0
  GString *nameLC;
1661
0
  GBool symbolic;
1662
1663
  // potential inputs:
1664
  // - font is embedded (GfxFont.embFontID.num >= 0)
1665
  // - font name (GfxFont.name)
1666
  // - font type (GfxFont.type)
1667
  // - Base-14 font (Gfx8BitFont.base14 != NULL)
1668
  // - symbolic (GfxFont.flags & fontSymbolic)
1669
  // - has Encoding array (Gfx8BitFont.hasEncoding)
1670
  // - extracted base encoding from embedded font file
1671
  //   (Gfx8BitFont.baseEncFromFontFile)
1672
  // - has a ToUnicode map (GfxFont.hasToUnicode)
1673
  // - used the numeric glyph name heuristic
1674
  //   (Gfx8BitFont.usedNumericHeuristic)
1675
1676
0
  if (name) {
1677
0
    nameLC = name->copy();
1678
0
    nameLC->lowerCase();
1679
0
    symbolic = strstr(nameLC->getCString(), "dingbat") ||
1680
0
               strstr(nameLC->getCString(), "wingding") ||
1681
0
               strstr(nameLC->getCString(), "commpi");
1682
0
    delete nameLC;
1683
0
    if (symbolic) {
1684
0
      return gFalse;
1685
0
    }
1686
0
  }
1687
1688
0
  if (embFontID.num >= 0) {
1689
0
    switch (type) {
1690
0
    case fontType1:
1691
0
    case fontType1C:
1692
0
    case fontType1COT:
1693
0
      return !hasToUnicode && (!hasEncoding || usedNumericHeuristic);
1694
1695
0
    case fontType3:
1696
      // this never happens -- Type 3 fonts don't set embFontID
1697
0
      return !hasToUnicode && (!hasEncoding || usedNumericHeuristic);
1698
1699
0
    case fontTrueType:
1700
0
    case fontTrueTypeOT:
1701
0
      return !hasToUnicode && !hasEncoding;
1702
1703
0
    default:
1704
0
      return !hasToUnicode;
1705
0
    }
1706
1707
0
  } else if (type == fontType3) {
1708
0
    return !hasToUnicode && (!hasEncoding || usedNumericHeuristic);
1709
1710
0
  } else {
1711
    // NB: type will be fontTypeUnknown if the PDF specifies an
1712
    // invalid font type -- which is ok, if we have a ToUnicode map or
1713
    // an encoding
1714
0
    return !hasToUnicode && !hasEncoding;
1715
0
  }
1716
0
}
1717
1718
0
GBool Gfx8BitFont::parensAreSwapped(XRef *xref) {
1719
0
  return gFalse;
1720
0
}
1721
1722
//------------------------------------------------------------------------
1723
// GfxCIDFont
1724
//------------------------------------------------------------------------
1725
1726
GfxCIDFont::GfxCIDFont(XRef *xref, const char *tagA, Ref idA, GString *nameA,
1727
           GfxFontType typeA, Ref embFontIDA, Dict *fontDict):
1728
43.2k
  GfxFont(tagA, idA, nameA, typeA, embFontIDA)
1729
43.2k
{
1730
43.2k
  Dict *desFontDict;
1731
43.2k
  Object desFontDictObj;
1732
43.2k
  Object obj1, obj2, obj3, obj4, obj5, obj6;
1733
43.2k
  CharCodeToUnicode *utu;
1734
43.2k
  CharCode c;
1735
43.2k
  Unicode uBuf[8];
1736
43.2k
  int c1, c2;
1737
43.2k
  int excepsSize, i, j, k, n;
1738
1739
43.2k
  missingWidth = 0;
1740
43.2k
  ascent = 0.95;
1741
43.2k
  descent = -0.35;
1742
43.2k
  declaredAscent = ascent;
1743
43.2k
  fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
1744
43.2k
  collection = NULL;
1745
43.2k
  cMap = NULL;
1746
43.2k
  ctu = NULL;
1747
43.2k
  ctuUsesCharCode = gTrue;
1748
43.2k
  widths.defWidth = 1.0;
1749
43.2k
  widths.defHeight = -1.0;
1750
43.2k
  widths.defVY = 0.880;
1751
43.2k
  widths.exceps = NULL;
1752
43.2k
  widths.nExceps = 0;
1753
43.2k
  widths.excepsV = NULL;
1754
43.2k
  widths.nExcepsV = 0;
1755
43.2k
  cidToGID = NULL;
1756
43.2k
  cidToGIDLen = 0;
1757
1758
  // get the descendant font
1759
43.2k
  if (!fontDict->lookup("DescendantFonts", &obj1)->isArray() ||
1760
43.1k
      obj1.arrayGetLength() == 0) {
1761
30
    error(errSyntaxError, -1,
1762
30
    "Missing or empty DescendantFonts entry in Type 0 font");
1763
30
    obj1.free();
1764
30
    goto err1;
1765
30
  }
1766
43.1k
  if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
1767
7
    error(errSyntaxError, -1, "Bad descendant font in Type 0 font");
1768
7
    goto err2;
1769
7
  }
1770
43.1k
  obj1.free();
1771
43.1k
  desFontDict = desFontDictObj.getDict();
1772
1773
  // get info from font descriptor
1774
43.1k
  readFontDescriptor(xref, desFontDict);
1775
1776
  //----- encoding info -----
1777
1778
  // char collection
1779
43.1k
  if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
1780
1.55k
    error(errSyntaxError, -1,
1781
1.55k
    "Missing CIDSystemInfo dictionary in Type 0 descendant font");
1782
1.55k
    goto err2;
1783
1.55k
  }
1784
41.6k
  obj1.dictLookup("Registry", &obj2);
1785
41.6k
  obj1.dictLookup("Ordering", &obj3);
1786
41.6k
  if (!obj2.isString() || !obj3.isString()) {
1787
4.20k
    error(errSyntaxError, -1,
1788
4.20k
    "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
1789
4.20k
    goto err3;
1790
4.20k
  }
1791
37.4k
  collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
1792
37.4k
  obj3.free();
1793
37.4k
  obj2.free();
1794
37.4k
  obj1.free();
1795
1796
  // encoding (i.e., CMap)
1797
37.4k
  if (fontDict->lookup("Encoding", &obj1)->isNull()) {
1798
1.53k
    error(errSyntaxError, -1, "Missing Encoding entry in Type 0 font");
1799
1.53k
    goto err2;
1800
1.53k
  }
1801
35.8k
  if (!(cMap = CMap::parse(NULL, collection, &obj1))) {
1802
2.89k
    goto err2;
1803
2.89k
  }
1804
1805
  // check for fonts that use the Identity-H encoding (cmap), and the
1806
  // Adobe-Identity character collection
1807
32.9k
  identityEnc = obj1.isName("Identity-H") &&
1808
5.38k
                !collection->cmp("Adobe-Identity");
1809
1810
32.9k
  obj1.free();
1811
1812
  // CIDToGIDMap
1813
  // (the PDF 1.7 spec only allows these for TrueType fonts, but
1814
  // Acrobat apparently also allows them for OpenType CFF fonts -- and
1815
  // the PDF 2.0 spec has removed the prohibition)
1816
32.9k
  hasIdentityCIDToGID = gFalse;
1817
32.9k
  desFontDict->lookup("CIDToGIDMap", &obj1);
1818
32.9k
  if (obj1.isStream()) {
1819
64
    cidToGIDLen = 0;
1820
64
    i = 64;
1821
64
    cidToGID = (int *)gmallocn(i, sizeof(int));
1822
64
    obj1.streamReset();
1823
278k
    while ((c1 = obj1.streamGetChar()) != EOF &&
1824
278k
     (c2 = obj1.streamGetChar()) != EOF) {
1825
278k
      if (cidToGIDLen == i) {
1826
182
  i *= 2;
1827
182
  cidToGID = (int *)greallocn(cidToGID, i, sizeof(int));
1828
182
      }
1829
278k
      cidToGID[cidToGIDLen++] = (c1 << 8) + c2;
1830
278k
    }
1831
64
    obj1.streamClose();
1832
64
    identityEnc = gFalse;
1833
32.9k
  } else if (obj1.isName("Identity")) {
1834
4.22k
    hasIdentityCIDToGID = gTrue;
1835
28.7k
  } else if (!obj1.isNull()) {
1836
839
    error(errSyntaxError, -1, "Invalid CIDToGIDMap entry in CID font");
1837
839
  }
1838
32.9k
  obj1.free();
1839
1840
  // look for a ToUnicode CMap
1841
32.9k
  hasKnownCollection = gFalse;
1842
32.9k
  if (globalParams->getUseTrueTypeUnicodeMapping()) {
1843
0
    readTrueTypeUnicodeMapping(xref);
1844
0
  }
1845
32.9k
  if (!ctu) {
1846
32.9k
    ctu = readToUnicodeCMap(fontDict, 16, NULL);
1847
32.9k
  }
1848
32.9k
  if (!ctu) {
1849
29.1k
    ctuUsesCharCode = gFalse;
1850
1851
    // use an identity mapping for the "Adobe-Identity" and
1852
    // "Adobe-UCS" collections
1853
29.1k
    if (!collection->cmp("Adobe-Identity") ||
1854
26.8k
  !collection->cmp("Adobe-UCS")) {
1855
2.32k
      ctu = CharCodeToUnicode::makeIdentityMapping();
1856
1857
    // look for a user-supplied .cidToUnicode file
1858
26.8k
    } else if ((ctu = globalParams->getCIDToUnicode(collection))) {
1859
0
      hasKnownCollection = gTrue;
1860
1861
26.8k
    } else {
1862
26.8k
      error(errSyntaxError, -1,
1863
26.8k
      "Unknown character collection '{0:t}'", collection);
1864
1865
      // fall back to an identity mapping
1866
26.8k
      ctu = CharCodeToUnicode::makeIdentityMapping();
1867
26.8k
    }
1868
29.1k
  }
1869
1870
  // look for a Unicode-to-Unicode mapping
1871
32.9k
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
1872
0
    if (ctu) {
1873
0
      if (ctu->isIdentity()) {
1874
0
  ctu->decRefCnt();
1875
0
  ctu = utu;
1876
0
      } else {
1877
0
  for (c = 0; c < ctu->getLength(); ++c) {
1878
0
    n = ctu->mapToUnicode(c, uBuf, 8);
1879
0
    if (n >= 1) {
1880
0
      n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
1881
0
      if (n >= 1) {
1882
0
        ctu->setMapping(c, uBuf, n);
1883
0
      }
1884
0
    }
1885
0
  }
1886
0
  utu->decRefCnt();
1887
0
      }
1888
0
    } else {
1889
0
      ctu = utu;
1890
0
    }
1891
0
  }
1892
1893
  //----- character metrics -----
1894
1895
  // default char width
1896
32.9k
  if (desFontDict->lookup("DW", &obj1)->isNum()) {
1897
1.39k
    widths.defWidth = obj1.getNum() * 0.001;
1898
1.39k
  }
1899
32.9k
  obj1.free();
1900
1901
  // char width exceptions
1902
32.9k
  if (desFontDict->lookup("W", &obj1)->isArray()) {
1903
31.3k
    excepsSize = 0;
1904
31.3k
    i = 0;
1905
209k
    while (i + 1 < obj1.arrayGetLength()) {
1906
178k
      obj1.arrayGet(i, &obj2);
1907
178k
      obj1.arrayGet(i + 1, &obj3);
1908
178k
      if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
1909
53.8k
  if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
1910
49.5k
    if (widths.nExceps == excepsSize) {
1911
1.34k
      excepsSize += 16;
1912
1.34k
      widths.exceps = (GfxFontCIDWidthExcep *)
1913
1.34k
        greallocn(widths.exceps,
1914
1.34k
      excepsSize, sizeof(GfxFontCIDWidthExcep));
1915
1.34k
    }
1916
49.5k
    widths.exceps[widths.nExceps].first = obj2.getInt();
1917
49.5k
    widths.exceps[widths.nExceps].last = obj3.getInt();
1918
49.5k
    widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
1919
49.5k
    ++widths.nExceps;
1920
49.5k
  } else {
1921
4.27k
    error(errSyntaxError, -1, "Bad widths array in Type 0 font");
1922
4.27k
  }
1923
53.8k
  obj4.free();
1924
53.8k
  i += 3;
1925
124k
      } else if (obj2.isInt() && obj3.isArray()) {
1926
61.7k
  if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
1927
29.7k
    excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
1928
29.7k
    widths.exceps = (GfxFontCIDWidthExcep *)
1929
29.7k
      greallocn(widths.exceps,
1930
29.7k
          excepsSize, sizeof(GfxFontCIDWidthExcep));
1931
29.7k
  }
1932
61.7k
  j = obj2.getInt();
1933
181k
  for (k = 0; k < obj3.arrayGetLength(); ++k) {
1934
119k
    if (obj3.arrayGet(k, &obj4)->isNum()) {
1935
118k
      widths.exceps[widths.nExceps].first = j;
1936
118k
      widths.exceps[widths.nExceps].last = j;
1937
118k
      widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
1938
118k
      ++j;
1939
118k
      ++widths.nExceps;
1940
118k
    } else {
1941
1.12k
      error(errSyntaxError, -1, "Bad widths array in Type 0 font");
1942
1.12k
    }
1943
119k
    obj4.free();
1944
119k
  }
1945
61.7k
  i += 2;
1946
63.1k
      } else {
1947
63.1k
  error(errSyntaxError, -1, "Bad widths array in Type 0 font");
1948
63.1k
  ++i;
1949
63.1k
      }
1950
178k
      obj3.free();
1951
178k
      obj2.free();
1952
178k
    }
1953
31.3k
  }
1954
32.9k
  obj1.free();
1955
1956
  // default metrics for vertical font
1957
32.9k
  if (desFontDict->lookup("DW2", &obj1)->isArray() &&
1958
13
      obj1.arrayGetLength() == 2) {
1959
12
    if (obj1.arrayGet(0, &obj2)->isNum()) {
1960
11
      widths.defVY = obj2.getNum() * 0.001;
1961
11
    }
1962
12
    obj2.free();
1963
12
    if (obj1.arrayGet(1, &obj2)->isNum()) {
1964
4
      widths.defHeight = obj2.getNum() * 0.001;
1965
4
    }
1966
12
    obj2.free();
1967
12
  }
1968
32.9k
  obj1.free();
1969
1970
  // char metric exceptions for vertical font
1971
32.9k
  if (desFontDict->lookup("W2", &obj1)->isArray()) {
1972
53
    excepsSize = 0;
1973
53
    i = 0;
1974
412
    while (i + 1 < obj1.arrayGetLength()) {
1975
359
      obj1.arrayGet(i, &obj2);
1976
359
      obj1.arrayGet(i+ 1, &obj3);
1977
359
      if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
1978
69
  if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
1979
54
      obj1.arrayGet(i + 3, &obj5)->isNum() &&
1980
40
      obj1.arrayGet(i + 4, &obj6)->isNum()) {
1981
28
    if (widths.nExcepsV == excepsSize) {
1982
18
      excepsSize += 16;
1983
18
      widths.excepsV = (GfxFontCIDWidthExcepV *)
1984
18
        greallocn(widths.excepsV,
1985
18
      excepsSize, sizeof(GfxFontCIDWidthExcepV));
1986
18
    }
1987
28
    widths.excepsV[widths.nExcepsV].first = obj2.getInt();
1988
28
    widths.excepsV[widths.nExcepsV].last = obj3.getInt();
1989
28
    widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
1990
28
    widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
1991
28
    widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
1992
28
    ++widths.nExcepsV;
1993
41
  } else {
1994
41
    error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
1995
41
  }
1996
69
  obj6.free();
1997
69
  obj5.free();
1998
69
  obj4.free();
1999
69
  i += 5;
2000
290
      } else if (obj2.isInt() && obj3.isArray()) {
2001
23
  if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
2002
20
    excepsSize =
2003
20
      (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
2004
20
    widths.excepsV = (GfxFontCIDWidthExcepV *)
2005
20
      greallocn(widths.excepsV,
2006
20
          excepsSize, sizeof(GfxFontCIDWidthExcepV));
2007
20
  }
2008
23
  j = obj2.getInt();
2009
91
  for (k = 0; k + 2 < obj3.arrayGetLength(); k += 3) {
2010
68
    if (obj3.arrayGet(k, &obj4)->isNum() &&
2011
50
        obj3.arrayGet(k+1, &obj5)->isNum() &&
2012
31
        obj3.arrayGet(k+2, &obj6)->isNum()) {
2013
16
      widths.excepsV[widths.nExcepsV].first = j;
2014
16
      widths.excepsV[widths.nExcepsV].last = j;
2015
16
      widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
2016
16
      widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
2017
16
      widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
2018
16
      ++j;
2019
16
      ++widths.nExcepsV;
2020
52
    } else {
2021
52
      error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
2022
52
    }
2023
68
    obj6.free();
2024
68
    obj5.free();
2025
68
    obj4.free();
2026
68
  }
2027
23
  i += 2;
2028
267
      } else {
2029
267
  error(errSyntaxError, -1, "Bad widths (W2) array in Type 0 font");
2030
267
  ++i;
2031
267
      }
2032
359
      obj3.free();
2033
359
      obj2.free();
2034
359
    }
2035
53
  }
2036
32.9k
  obj1.free();
2037
2038
32.9k
  desFontDictObj.free();
2039
32.9k
  ok = gTrue;
2040
32.9k
  return;
2041
2042
4.20k
 err3:
2043
4.20k
  obj3.free();
2044
4.20k
  obj2.free();
2045
10.1k
 err2:
2046
10.1k
  obj1.free();
2047
10.1k
  desFontDictObj.free();
2048
10.2k
 err1:
2049
10.2k
  error(errSyntaxError, -1, "Failed to parse font object for '{0:t}'", name);
2050
10.2k
}
2051
2052
43.2k
GfxCIDFont::~GfxCIDFont() {
2053
43.2k
  if (collection) {
2054
37.4k
    delete collection;
2055
37.4k
  }
2056
43.2k
  if (cMap) {
2057
32.9k
    cMap->decRefCnt();
2058
32.9k
  }
2059
43.2k
  if (ctu) {
2060
32.9k
    ctu->decRefCnt();
2061
32.9k
  }
2062
43.2k
  gfree(widths.exceps);
2063
43.2k
  gfree(widths.excepsV);
2064
43.2k
  if (cidToGID) {
2065
64
    gfree(cidToGID);
2066
64
  }
2067
43.2k
}
2068
2069
// Construct a code-to-Unicode mapping, based on the TrueType Unicode
2070
// cmap (if present).  Constructs ctu if succesful; leaves ctu = null
2071
// otherwise.  Always leaves ctu = null for non-TrueType fonts.
2072
0
void GfxCIDFont::readTrueTypeUnicodeMapping(XRef *xref) {
2073
0
  char *buf;
2074
0
  FoFiTrueType *ff;
2075
0
  Unicode *gidToUnicode, *codeToUnicode;
2076
0
  Unicode u;
2077
0
  int bufLen, cmapPlatform, cmapEncoding, unicodeCmap;
2078
0
  int nGlyphs, nMappings, gid, i;
2079
2080
  // must be an embedded TrueType font, with an unknown char collection
2081
0
  if ((type != fontCIDType2 && type != fontCIDType2OT) ||
2082
0
      embFontID.num < 0 ||
2083
0
      hasKnownCollection) {
2084
0
    goto err0;
2085
0
  }
2086
2087
  // read the embedded font and construct a FoFiTrueType
2088
0
  if (!(buf = readEmbFontFile(xref, &bufLen))) {
2089
0
    goto err0;
2090
0
  }
2091
0
  if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) {
2092
0
    goto err1;
2093
0
  }
2094
2095
  // find the TrueType Unicode cmap
2096
0
  unicodeCmap = -1;
2097
0
  for (i = 0; i < ff->getNumCmaps(); ++i) {
2098
0
    cmapPlatform = ff->getCmapPlatform(i);
2099
0
    cmapEncoding = ff->getCmapEncoding(i);
2100
0
    if ((cmapPlatform == 3 && cmapEncoding == 1) ||
2101
0
  (cmapPlatform == 0 && cmapEncoding <= 4)) {
2102
0
      unicodeCmap = i;
2103
0
      break;
2104
0
    }
2105
0
  }
2106
0
  if (unicodeCmap < 0) {
2107
0
    goto err2;
2108
0
  }
2109
2110
  // construct reverse GID-to-Unicode map
2111
0
  nGlyphs = ff->getNumGlyphs();
2112
0
  gidToUnicode = (Unicode *)gmallocn(nGlyphs, sizeof(Unicode));
2113
0
  memset(gidToUnicode, 0, nGlyphs * sizeof(Unicode));
2114
0
  nMappings = 0;
2115
0
  for (u = 1; u <= 0xffff; ++u) {
2116
0
    gid = ff->mapCodeToGID(unicodeCmap, (int)u);
2117
0
    if (gid > 0 && gid < nGlyphs) {
2118
0
      gidToUnicode[gid] = u;
2119
0
      ++nMappings;
2120
0
    }
2121
0
  }
2122
  // bail out if the Unicode cmap was completely empty
2123
0
  if (nMappings == 0) {
2124
0
    goto err3;
2125
0
  }
2126
2127
  // construct code-to-Unicode map
2128
0
  codeToUnicode = (Unicode *)gmallocn(65536, sizeof(Unicode));
2129
0
  memset(codeToUnicode, 0, 65536 * sizeof(Unicode));
2130
0
  for (i = 0; i <= 0xffff; ++i) {
2131
    // we've already checked for an identity encoding, so CID = i
2132
0
    if (cidToGID && i < cidToGIDLen) {
2133
0
      gid = cidToGID[i];
2134
0
    } else {
2135
0
      gid = i;
2136
0
    }
2137
0
    if (gid < nGlyphs && gidToUnicode[gid] > 0) {
2138
0
      codeToUnicode[i] = gidToUnicode[gid];
2139
0
    }
2140
0
  }
2141
0
  ctu = CharCodeToUnicode::make16BitToUnicode(codeToUnicode);
2142
2143
0
  gfree(codeToUnicode);
2144
0
 err3:
2145
0
  gfree(gidToUnicode);
2146
0
 err2:
2147
0
  delete ff;
2148
0
 err1:
2149
0
  gfree(buf);
2150
0
 err0:
2151
0
  return;
2152
0
}
2153
2154
int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
2155
          Unicode *u, int uSize, int *uLen,
2156
222k
          double *dx, double *dy, double *ox, double *oy) {
2157
222k
  CID cid;
2158
222k
  CharCode c;
2159
222k
  int n;
2160
2161
222k
  if (!cMap) {
2162
0
    *code = 0;
2163
0
    *uLen = 0;
2164
0
    *dx = *dy = 0;
2165
0
    return 1;
2166
0
  }
2167
2168
222k
  *code = (CharCode)(cid = cMap->getCID(s, len, &c, &n));
2169
222k
  if (ctu) {
2170
222k
    *uLen = ctu->mapToUnicode(ctuUsesCharCode ? c : cid, u, uSize);
2171
222k
  } else {
2172
0
    *uLen = 0;
2173
0
  }
2174
222k
  if (!*uLen && uSize >= 1 && globalParams->getMapUnknownCharNames()) {
2175
0
    u[0] = *code;
2176
0
    *uLen = 1;
2177
0
  }
2178
2179
  // horizontal
2180
222k
  if (cMap->getWMode() == 0) {
2181
220k
    getHorizontalMetrics(cid, dx);
2182
220k
    *dy = *ox = *oy = 0;
2183
2184
  // vertical
2185
220k
  } else {
2186
1.74k
    getVerticalMetrics(cid, dy, ox, oy);
2187
1.74k
    *dx = 0;
2188
1.74k
  }
2189
2190
222k
  return n;
2191
222k
}
2192
2193
// NB: Section 9.7.4.3 in the PDF 2.0 spec says that, in the case of
2194
// duplicate entries in the metrics, the first entry should be used.
2195
// This means we need to leave the metrics in the original order and
2196
// perform a linear search.  (Or use a more complex data structure.)
2197
222k
void GfxCIDFont::getHorizontalMetrics(CID cid, double *w) {
2198
222k
  int i;
2199
1.16M
  for (i = 0; i < widths.nExceps; ++i) {
2200
966k
    if (widths.exceps[i].first <= cid && cid <= widths.exceps[i].last) {
2201
20.0k
      *w = widths.exceps[i].width;
2202
20.0k
      return;
2203
20.0k
    }
2204
966k
  }
2205
202k
  *w = widths.defWidth;
2206
202k
}
2207
2208
// NB: Section 9.7.4.3 in the PDF 2.0 spec says that, in the case of
2209
// duplicate entries in the metrics, the first entry should be used.
2210
// This means we need to leave the metrics in the original order and
2211
// perform a linear search.  (Or use a more complex data structure.)
2212
void GfxCIDFont::getVerticalMetrics(CID cid, double *h,
2213
1.74k
            double *vx, double *vy) {
2214
1.74k
  int i;
2215
1.93k
  for (i = 0; i < widths.nExcepsV; ++i) {
2216
266
    if (widths.excepsV[i].first <= cid && cid <= widths.excepsV[i].last) {
2217
82
      *h = widths.excepsV[i].height;
2218
82
      *vx = widths.excepsV[i].vx;
2219
82
      *vy = widths.excepsV[i].vy;
2220
82
      return;
2221
82
    }
2222
266
  }
2223
1.66k
  *h = widths.defHeight;
2224
1.66k
  getHorizontalMetrics(cid, vx);
2225
1.66k
  *vx /= 2;
2226
1.66k
  *vy = widths.defVY;
2227
1.66k
}
2228
2229
97.1k
int GfxCIDFont::getWMode() {
2230
97.1k
  return cMap ? cMap->getWMode() : 0;
2231
97.1k
}
2232
2233
0
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
2234
0
  if (ctu) {
2235
0
    ctu->incRefCnt();
2236
0
  }
2237
0
  return ctu;
2238
0
}
2239
2240
12.2k
GString *GfxCIDFont::getCollection() {
2241
12.2k
  return cMap ? cMap->getCollection() : (GString *)NULL;
2242
12.2k
}
2243
2244
0
double GfxCIDFont::getWidth(CID cid) {
2245
0
  double w;
2246
2247
0
  getHorizontalMetrics(cid, &w);
2248
0
  return w;
2249
0
}
2250
2251
0
GBool GfxCIDFont::problematicForUnicode() {
2252
0
  GString *nameLC;
2253
0
  GBool symbolic;
2254
2255
  // potential inputs:
2256
  // - font is embedded (GfxFont.embFontID.num >= 0)
2257
  // - font name (GfxFont.name)
2258
  // - font type (GfxFont.type)
2259
  // - symbolic (GfxFont.flags & fontSymbolic)
2260
  // - has a ToUnicode map (GfxFont.hasToUnicode)
2261
  // - collection is Adobe-Identity or Adobe-UCS
2262
  //   (GfxCIDFont.collection - compare string)
2263
  // - collection is known AdobeCJK (GfxCIDFont.hasKnownCollection)
2264
  // - has non-Identity CIDToGIDMap (GfxCIDFont.cidToGID != NULL)
2265
  // - has Identity CIDToGIDMap (GfxCIDFont.hasIdentityCIDToGID)
2266
2267
0
  if (name) {
2268
0
    nameLC = name->copy();
2269
0
    nameLC->lowerCase();
2270
0
    symbolic = strstr(nameLC->getCString(), "dingbat") ||
2271
0
               strstr(nameLC->getCString(), "wingding") ||
2272
0
               strstr(nameLC->getCString(), "commpi");
2273
0
    delete nameLC;
2274
0
    if (symbolic) {
2275
0
      return gFalse;
2276
0
    }
2277
0
  }
2278
2279
0
  if (embFontID.num >= 0) {
2280
0
    switch (type) {
2281
0
    case fontCIDType0:
2282
0
    case fontCIDType0C:
2283
0
    case fontCIDType0COT:
2284
0
      return !hasToUnicode && !hasKnownCollection;
2285
2286
0
    case fontCIDType2:
2287
0
    case fontCIDType2OT:
2288
0
      return !hasToUnicode && !hasKnownCollection;
2289
2290
0
    default:
2291
0
      return !hasToUnicode;
2292
0
    }
2293
2294
0
  } else {
2295
0
    return !hasToUnicode;
2296
0
  }
2297
0
}
2298
2299
0
GBool GfxCIDFont::parensAreSwapped(XRef *xref) {
2300
0
  char *buf = NULL;
2301
0
  FoFiTrueType *ff = NULL;
2302
0
  int bufLen;
2303
0
  int unicodeCmap, leftParenGID, rightParenGID, leftParenCID, rightParenCID;
2304
0
  Unicode leftParenUnicode, rightParenUnicode;
2305
0
  GBool swapped;
2306
2307
  // only relevant for embedded TrueType fonts, with unknown char
2308
  // collections, and with ToUnicode maps
2309
0
  if ((type != fontCIDType2 && type != fontCIDType2OT) ||
2310
0
      embFontID.num < 0 ||
2311
0
      hasKnownCollection ||
2312
0
      !hasToUnicode) {
2313
0
    return gFalse;
2314
0
  }
2315
2316
  // read the embedded font and construct a FoFiTrueType
2317
0
  if (!(buf = readEmbFontFile(xref, &bufLen))) {
2318
0
    goto err;
2319
0
  }
2320
0
  if (!(ff = FoFiTrueType::make(buf, bufLen, 0))) {
2321
0
    goto err;
2322
0
  }
2323
2324
  // find the TrueType Unicode cmap
2325
0
  unicodeCmap = -1;
2326
0
  for (int i = 0; i < ff->getNumCmaps(); ++i) {
2327
0
    int cmapPlatform = ff->getCmapPlatform(i);
2328
0
    int cmapEncoding = ff->getCmapEncoding(i);
2329
0
    if ((cmapPlatform == 3 && cmapEncoding == 1) ||
2330
0
  (cmapPlatform == 0 && cmapEncoding <= 4)) {
2331
0
      unicodeCmap = i;
2332
0
      break;
2333
0
    }
2334
0
  }
2335
0
  if (unicodeCmap < 0) {
2336
0
    goto err;
2337
0
  }
2338
2339
  // map parens to GIDs using the TrueType Unicode cmap
2340
0
  leftParenGID = ff->mapCodeToGID(unicodeCmap, 0x28);
2341
0
  rightParenGID = ff->mapCodeToGID(unicodeCmap, 0x29);
2342
0
  if (leftParenGID == 0 || rightParenGID == 0) {
2343
0
    goto err;
2344
0
  }
2345
2346
  // map GIDs to CIDs using the inverted CIDToGID map
2347
0
  leftParenCID = -1;
2348
0
  rightParenCID = -1;
2349
0
  if (cidToGID) {
2350
0
    for (int i = 0;
2351
0
   i <= cidToGIDLen && leftParenCID < 0 && rightParenCID < 0;
2352
0
   ++i) {
2353
0
      if (cidToGID[i] == leftParenGID) {
2354
0
  leftParenCID = i;
2355
0
      } else if (cidToGID[i] == rightParenGID) {
2356
0
  rightParenCID = i;
2357
0
      }
2358
0
    }
2359
0
    if (leftParenCID < 0 || rightParenCID < 0) {
2360
0
      goto err;
2361
0
    }
2362
0
  } else {
2363
0
    leftParenCID = leftParenGID;
2364
0
    rightParenCID = rightParenGID;
2365
0
  }
2366
2367
  // map CIDs to Unicode using the ToUnicode map
2368
0
  if (ctu->mapToUnicode((CharCode)leftParenCID, &leftParenUnicode, 1) < 1 ||
2369
0
      ctu->mapToUnicode((CharCode)rightParenCID, &rightParenUnicode, 1) < 1) {
2370
0
    goto err;
2371
0
  }
2372
2373
  // check for swap
2374
0
  swapped = leftParenUnicode == 0x29 && rightParenUnicode == 0x28;
2375
2376
0
  delete ff;
2377
0
  ff = NULL;
2378
0
  gfree(buf);
2379
0
  buf = NULL;
2380
2381
0
  return swapped;
2382
2383
0
 err:
2384
0
  if (ff) {
2385
0
    delete ff;
2386
0
  }
2387
0
  if (buf) {
2388
0
    gfree(buf);
2389
0
  }
2390
0
  return gFalse;
2391
0
}
2392
2393
//------------------------------------------------------------------------
2394
// GfxFontDict
2395
//------------------------------------------------------------------------
2396
2397
class GfxFontDictEntry {
2398
public:
2399
2400
  GfxFontDictEntry(Ref refA, Object *fontObjA);
2401
  ~GfxFontDictEntry();
2402
  void load(GfxFont *fontA);
2403
2404
  GBool loaded;
2405
  Ref ref;
2406
  Object fontObj;   // valid if unloaded
2407
  GfxFont *font;    // valid if loaded
2408
};
2409
2410
164k
GfxFontDictEntry::GfxFontDictEntry(Ref refA, Object *fontObjA) {
2411
164k
  loaded = gFalse;
2412
164k
  ref = refA;
2413
164k
  fontObjA->copy(&fontObj);
2414
164k
  font = NULL;
2415
164k
}
2416
2417
164k
GfxFontDictEntry::~GfxFontDictEntry() {
2418
  // NB: If the font has been loaded, font is non-NULL and is owned by
2419
  // GfxFontDict.uniqueFonts.
2420
164k
  if (!loaded) {
2421
81.6k
    fontObj.free();
2422
81.6k
  }
2423
164k
}
2424
2425
83.0k
void GfxFontDictEntry::load(GfxFont *fontA) {
2426
83.0k
  loaded = gTrue;
2427
83.0k
  font = fontA;
2428
83.0k
  fontObj.free();
2429
83.0k
}
2430
2431
98.1k
GfxFontDict::GfxFontDict(XRef *xrefA, Ref *fontDictRef, Dict *fontDict) {
2432
98.1k
  xref = xrefA;
2433
98.1k
  fonts = new GHash(gTrue);
2434
98.1k
  uniqueFonts = new GList();
2435
2436
262k
  for (int i = 0; i < fontDict->getLength(); ++i) {
2437
164k
    char *tag = fontDict->getKey(i);
2438
164k
    Object fontObj;
2439
164k
    fontDict->getValNF(i, &fontObj);
2440
164k
    Ref r;
2441
164k
    if (fontObj.isRef()) {
2442
139k
      r = fontObj.getRef();
2443
139k
    } else if (fontDictRef) {
2444
      // legal generation numbers are five digits, so we use a
2445
      // 6-digit number here
2446
277
      r.gen = 100000 + fontDictRef->num;
2447
277
      r.num = i;
2448
24.9k
    } else {
2449
      // no indirect reference for this font, or for the containing
2450
      // font dict, so hash the font and use that
2451
24.9k
      r.gen = 100000;
2452
24.9k
      r.num = hashFontObject(&fontObj);
2453
24.9k
    }
2454
164k
    fonts->add(new GString(tag), new GfxFontDictEntry(r, &fontObj));
2455
164k
    fontObj.free();
2456
164k
  }
2457
98.1k
}
2458
2459
98.1k
GfxFontDict::~GfxFontDict() {
2460
98.1k
  deleteGList(uniqueFonts, GfxFont);
2461
98.1k
  deleteGHash(fonts, GfxFontDictEntry);
2462
98.1k
}
2463
2464
166k
GfxFont *GfxFontDict::lookup(char *tag) {
2465
166k
  GfxFontDictEntry *entry = (GfxFontDictEntry *)fonts->lookup(tag);
2466
166k
  if (!entry) {
2467
48.2k
    return NULL;
2468
48.2k
  }
2469
118k
  load(tag, entry);
2470
118k
  return entry->font;
2471
166k
}
2472
2473
24
GfxFont *GfxFontDict::lookupByRef(Ref ref) {
2474
24
  GHashIter *iter;
2475
24
  GString *tag;
2476
24
  GfxFontDictEntry *entry;
2477
24
  fonts->startIter(&iter);
2478
107
  while (fonts->getNext(&iter, &tag, (void **)&entry)) {
2479
92
    if (entry->ref.num == ref.num && entry->ref.gen == ref.gen) {
2480
9
      fonts->killIter(&iter);
2481
9
      load(tag->getCString(), entry);
2482
9
      return entry->font;
2483
9
    }
2484
92
  }
2485
15
  return NULL;
2486
24
}
2487
2488
0
int GfxFontDict::getNumFonts() {
2489
0
  loadAll();
2490
0
  return uniqueFonts->getLength();
2491
0
}
2492
2493
0
GfxFont *GfxFontDict::getFont(int i) {
2494
0
  return (GfxFont *)uniqueFonts->get(i);
2495
0
}
2496
2497
0
void GfxFontDict::loadAll() {
2498
0
  GHashIter *iter;
2499
0
  GString *tag;
2500
0
  GfxFontDictEntry *entry;
2501
0
  fonts->startIter(&iter);
2502
0
  while (fonts->getNext(&iter, &tag, (void **)&entry)) {
2503
0
    load(tag->getCString(), entry);
2504
0
  }
2505
0
}
2506
2507
118k
void GfxFontDict::load(char *tag, GfxFontDictEntry *entry) {
2508
118k
  if (entry->loaded) {
2509
35.4k
    return;
2510
35.4k
  }
2511
2512
  // check for a duplicate that has already been loaded
2513
  // (don't do this for "synthetic" refs)
2514
83.0k
  if (entry->fontObj.isRef()) {
2515
90.2k
    for (int i = 0; i < uniqueFonts->getLength(); ++i) {
2516
8.52k
      GfxFont *font = (GfxFont *)uniqueFonts->get(i);
2517
8.52k
      if (font->getID()->num == entry->ref.num &&
2518
5
    font->getID()->gen == entry->ref.gen) {
2519
3
  entry->load(font);
2520
3
  return;
2521
3
      }
2522
8.52k
    }
2523
81.6k
  }
2524
2525
83.0k
  GfxFont *font = NULL;
2526
83.0k
  Object obj;
2527
83.0k
  entry->fontObj.fetch(xref, &obj);
2528
83.0k
  if (obj.isDict()) {
2529
70.9k
    font = GfxFont::makeFont(xref, tag, entry->ref, obj.getDict());
2530
70.9k
    if (font->isOk()) {
2531
60.7k
      uniqueFonts->append(font);
2532
60.7k
    } else {
2533
10.2k
      delete font;
2534
10.2k
      font = NULL;
2535
10.2k
    }
2536
70.9k
  } else {
2537
12.0k
    error(errSyntaxError, -1, "font resource is not a dictionary");
2538
12.0k
  }
2539
83.0k
  obj.free();
2540
83.0k
  entry->load(font);
2541
83.0k
}
2542
2543
// FNV-1a hash
2544
class FNVHash {
2545
public:
2546
2547
48.2k
  FNVHash() {
2548
48.2k
    h = 2166136261U;
2549
48.2k
  }
2550
2551
5.88M
  void hash(char c) {
2552
5.88M
    h ^= c & 0xff;
2553
5.88M
    h *= 16777619;
2554
5.88M
  }
2555
2556
578k
  void hash(char *p, int n) {
2557
578k
    int i;
2558
6.12M
    for (i = 0; i < n; ++i) {
2559
5.54M
      hash(p[i]);
2560
5.54M
    }
2561
578k
  }
2562
2563
48.2k
  int get31() {
2564
48.2k
    return (h ^ (h >> 31)) & 0x7fffffff;
2565
48.2k
  }
2566
2567
private:
2568
2569
  Guint h;
2570
};
2571
2572
48.2k
int GfxFontDict::hashFontObject(Object *obj) {
2573
48.2k
  FNVHash h;
2574
2575
48.2k
  hashFontObject1(obj, &h);
2576
48.2k
  return h.get31();
2577
48.2k
}
2578
2579
333k
void GfxFontDict::hashFontObject1(Object *obj, FNVHash *h) {
2580
333k
  Object obj2;
2581
333k
  GString *s;
2582
333k
  char *p;
2583
333k
  double r;
2584
333k
  int n, i;
2585
2586
333k
  switch (obj->getType()) {
2587
259
  case objBool:
2588
259
    h->hash('b');
2589
259
    h->hash(obj->getBool() ? 1 : 0);
2590
259
    break;
2591
69.7k
  case objInt:
2592
69.7k
    h->hash('i');
2593
69.7k
    n = obj->getInt();
2594
69.7k
    h->hash((char *)&n, sizeof(int));
2595
69.7k
    break;
2596
3.52k
  case objReal:
2597
3.52k
    h->hash('r');
2598
3.52k
    r = obj->getReal();
2599
3.52k
    h->hash((char *)&r, sizeof(double));
2600
3.52k
    break;
2601
2.51k
  case objString:
2602
2.51k
    h->hash('s');
2603
2.51k
    s = obj->getString();
2604
2.51k
    h->hash(s->getCString(), s->getLength());
2605
2.51k
    break;
2606
95.4k
  case objName:
2607
95.4k
    h->hash('n');
2608
95.4k
    p = obj->getName();
2609
95.4k
    h->hash(p, (int)strlen(p));
2610
95.4k
    break;
2611
101
  case objNull:
2612
101
    h->hash('z');
2613
101
    break;
2614
6.01k
  case objArray:
2615
6.01k
    h->hash('a');
2616
6.01k
    n = obj->arrayGetLength();
2617
6.01k
    h->hash((char *)&n, sizeof(int));
2618
86.2k
    for (i = 0; i < n; ++i) {
2619
80.2k
      obj->arrayGetNF(i, &obj2);
2620
80.2k
      hashFontObject1(&obj2, h);
2621
80.2k
      obj2.free();
2622
80.2k
    }
2623
6.01k
    break;
2624
33.5k
  case objDict:
2625
33.5k
    h->hash('d');
2626
33.5k
    n = obj->dictGetLength();
2627
33.5k
    h->hash((char *)&n, sizeof(int));
2628
238k
    for (i = 0; i < n; ++i) {
2629
204k
      p = obj->dictGetKey(i);
2630
204k
      h->hash(p, (int)strlen(p));
2631
204k
      obj->dictGetValNF(i, &obj2);
2632
204k
      hashFontObject1(&obj2, h);
2633
204k
      obj2.free();
2634
204k
    }
2635
33.5k
    break;
2636
1.34k
  case objStream:
2637
    // this should never happen - streams must be indirect refs
2638
1.34k
    break;
2639
81.5k
  case objRef:
2640
81.5k
    h->hash('f');
2641
81.5k
    n = obj->getRefNum();
2642
81.5k
    h->hash((char *)&n, sizeof(int));
2643
81.5k
    n = obj->getRefGen();
2644
81.5k
    h->hash((char *)&n, sizeof(int));
2645
81.5k
    break;
2646
39.2k
  default:
2647
39.2k
    h->hash('u');
2648
39.2k
    break;
2649
333k
  }
2650
333k
}