~ubuntu-branches/ubuntu/wily/luatex/wily

« back to all changes in this revision

Viewing changes to source/libs/xpdf/xpdf-3.02/xpdf/GfxFont.cc

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Preining
  • Date: 2010-04-29 00:47:19 UTC
  • mfrom: (1.1.10 upstream)
  • Revision ID: james.westby@ubuntu.com-20100429004719-o42etkqe90n97b9e
Tags: 0.60.1-1
* new upstream release, adapt build-script patch
* disable patch: upstream-epstopdf_cc_no_xpdf_patching, included upstream
* disable patch: libpoppler-0.12, not needed anymore

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
//========================================================================
 
2
//
 
3
// GfxFont.cc
 
4
//
 
5
// Copyright 1996-2003 Glyph & Cog, LLC
 
6
//
 
7
//========================================================================
 
8
 
 
9
#include <aconf.h>
 
10
 
 
11
#ifdef USE_GCC_PRAGMAS
 
12
#pragma implementation
 
13
#endif
 
14
 
 
15
#include <stdio.h>
 
16
#include <stdlib.h>
 
17
#include <string.h>
 
18
#include <ctype.h>
 
19
#include "gmem.h"
 
20
#include "Error.h"
 
21
#include "Object.h"
 
22
#include "Dict.h"
 
23
#include "GlobalParams.h"
 
24
#include "CMap.h"
 
25
#include "CharCodeToUnicode.h"
 
26
#include "FontEncodingTables.h"
 
27
#include "BuiltinFontTables.h"
 
28
#include "FoFiType1.h"
 
29
#include "FoFiType1C.h"
 
30
#include "FoFiTrueType.h"
 
31
#include "GfxFont.h"
 
32
 
 
33
//------------------------------------------------------------------------
 
34
 
 
35
struct StdFontMapEntry {
 
36
  char *altName;
 
37
  char *properName;
 
38
};
 
39
 
 
40
// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
 
41
// providing Widths and a FontDescriptor, so we munge the names into
 
42
// the proper Base14 names.  This table is from implementation note 44
 
43
// in the PDF 1.4 spec, with some additions based on empirical
 
44
// evidence.
 
45
static StdFontMapEntry stdFontMap[] = {
 
46
  { "Arial",                        "Helvetica" },
 
47
  { "Arial,Bold",                   "Helvetica-Bold" },
 
48
  { "Arial,BoldItalic",             "Helvetica-BoldOblique" },
 
49
  { "Arial,Italic",                 "Helvetica-Oblique" },
 
50
  { "Arial-Bold",                   "Helvetica-Bold" },
 
51
  { "Arial-BoldItalic",             "Helvetica-BoldOblique" },
 
52
  { "Arial-BoldItalicMT",           "Helvetica-BoldOblique" },
 
53
  { "Arial-BoldMT",                 "Helvetica-Bold" },
 
54
  { "Arial-Italic",                 "Helvetica-Oblique" },
 
55
  { "Arial-ItalicMT",               "Helvetica-Oblique" },
 
56
  { "ArialMT",                      "Helvetica" },
 
57
  { "Courier,Bold",                 "Courier-Bold" },
 
58
  { "Courier,BoldItalic",           "Courier-BoldOblique" },
 
59
  { "Courier,Italic",               "Courier-Oblique" },
 
60
  { "CourierNew",                   "Courier" },
 
61
  { "CourierNew,Bold",              "Courier-Bold" },
 
62
  { "CourierNew,BoldItalic",        "Courier-BoldOblique" },
 
63
  { "CourierNew,Italic",            "Courier-Oblique" },
 
64
  { "CourierNew-Bold",              "Courier-Bold" },
 
65
  { "CourierNew-BoldItalic",        "Courier-BoldOblique" },
 
66
  { "CourierNew-Italic",            "Courier-Oblique" },
 
67
  { "CourierNewPS-BoldItalicMT",    "Courier-BoldOblique" },
 
68
  { "CourierNewPS-BoldMT",          "Courier-Bold" },
 
69
  { "CourierNewPS-ItalicMT",        "Courier-Oblique" },
 
70
  { "CourierNewPSMT",               "Courier" },
 
71
  { "Helvetica,Bold",               "Helvetica-Bold" },
 
72
  { "Helvetica,BoldItalic",         "Helvetica-BoldOblique" },
 
73
  { "Helvetica,Italic",             "Helvetica-Oblique" },
 
74
  { "Helvetica-BoldItalic",         "Helvetica-BoldOblique" },
 
75
  { "Helvetica-Italic",             "Helvetica-Oblique" },
 
76
  { "Symbol,Bold",                  "Symbol" },
 
77
  { "Symbol,BoldItalic",            "Symbol" },
 
78
  { "Symbol,Italic",                "Symbol" },
 
79
  { "TimesNewRoman",                "Times-Roman" },
 
80
  { "TimesNewRoman,Bold",           "Times-Bold" },
 
81
  { "TimesNewRoman,BoldItalic",     "Times-BoldItalic" },
 
82
  { "TimesNewRoman,Italic",         "Times-Italic" },
 
83
  { "TimesNewRoman-Bold",           "Times-Bold" },
 
84
  { "TimesNewRoman-BoldItalic",     "Times-BoldItalic" },
 
85
  { "TimesNewRoman-Italic",         "Times-Italic" },
 
86
  { "TimesNewRomanPS",              "Times-Roman" },
 
87
  { "TimesNewRomanPS-Bold",         "Times-Bold" },
 
88
  { "TimesNewRomanPS-BoldItalic",   "Times-BoldItalic" },
 
89
  { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
 
90
  { "TimesNewRomanPS-BoldMT",       "Times-Bold" },
 
91
  { "TimesNewRomanPS-Italic",       "Times-Italic" },
 
92
  { "TimesNewRomanPS-ItalicMT",     "Times-Italic" },
 
93
  { "TimesNewRomanPSMT",            "Times-Roman" },
 
94
  { "TimesNewRomanPSMT,Bold",       "Times-Bold" },
 
95
  { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
 
96
  { "TimesNewRomanPSMT,Italic",     "Times-Italic" }
 
97
};
 
98
 
 
99
//------------------------------------------------------------------------
 
100
// GfxFont
 
101
//------------------------------------------------------------------------
 
102
 
 
103
GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
 
104
  GString *nameA;
 
105
  GfxFont *font;
 
106
  Object obj1;
 
107
 
 
108
  // get base font name
 
109
  nameA = NULL;
 
110
  fontDict->lookup("BaseFont", &obj1);
 
111
  if (obj1.isName()) {
 
112
    nameA = new GString(obj1.getName());
 
113
  }
 
114
  obj1.free();
 
115
 
 
116
  // get font type
 
117
  font = NULL;
 
118
  fontDict->lookup("Subtype", &obj1);
 
119
  if (obj1.isName("Type1") || obj1.isName("MMType1")) {
 
120
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
 
121
  } else if (obj1.isName("Type1C")) {
 
122
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
 
123
  } else if (obj1.isName("Type3")) {
 
124
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
 
125
  } else if (obj1.isName("TrueType")) {
 
126
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
 
127
  } else if (obj1.isName("Type0")) {
 
128
    font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
 
129
  } else {
 
130
    error(-1, "Unknown font type: '%s'",
 
131
          obj1.isName() ? obj1.getName() : "???");
 
132
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
 
133
  }
 
134
  obj1.free();
 
135
 
 
136
  return font;
 
137
}
 
138
 
 
139
GfxFont::GfxFont(char *tagA, Ref idA, GString *nameA) {
 
140
  ok = gFalse;
 
141
  tag = new GString(tagA);
 
142
  id = idA;
 
143
  name = nameA;
 
144
  origName = nameA;
 
145
  embFontName = NULL;
 
146
  extFontFile = NULL;
 
147
}
 
148
 
 
149
GfxFont::~GfxFont() {
 
150
  delete tag;
 
151
  if (origName && origName != name) {
 
152
    delete origName;
 
153
  }
 
154
  if (name) {
 
155
    delete name;
 
156
  }
 
157
  if (embFontName) {
 
158
    delete embFontName;
 
159
  }
 
160
  if (extFontFile) {
 
161
    delete extFontFile;
 
162
  }
 
163
}
 
164
 
 
165
void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
 
166
  Object obj1, obj2, obj3, obj4;
 
167
  double t;
 
168
  int i;
 
169
 
 
170
  // assume Times-Roman by default (for substitution purposes)
 
171
  flags = fontSerif;
 
172
 
 
173
  embFontID.num = -1;
 
174
  embFontID.gen = -1;
 
175
  missingWidth = 0;
 
176
 
 
177
  if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
 
178
 
 
179
    // get flags
 
180
    if (obj1.dictLookup("Flags", &obj2)->isInt()) {
 
181
      flags = obj2.getInt();
 
182
    }
 
183
    obj2.free();
 
184
 
 
185
    // get name
 
186
    obj1.dictLookup("FontName", &obj2);
 
187
    if (obj2.isName()) {
 
188
      embFontName = new GString(obj2.getName());
 
189
    }
 
190
    obj2.free();
 
191
 
 
192
    // look for embedded font file
 
193
    if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
 
194
      embFontID = obj2.getRef();
 
195
      if (type != fontType1) {
 
196
        error(-1, "Mismatch between font type and embedded font file");
 
197
        type = fontType1;
 
198
      }
 
199
    }
 
200
    obj2.free();
 
201
    if (embFontID.num == -1 &&
 
202
        obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
 
203
      embFontID = obj2.getRef();
 
204
      if (type != fontTrueType && type != fontCIDType2) {
 
205
        error(-1, "Mismatch between font type and embedded font file");
 
206
        type = type == fontCIDType0 ? fontCIDType2 : fontTrueType;
 
207
      }
 
208
    }
 
209
    obj2.free();
 
210
    if (embFontID.num == -1 &&
 
211
        obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
 
212
      if (obj2.fetch(xref, &obj3)->isStream()) {
 
213
        obj3.streamGetDict()->lookup("Subtype", &obj4);
 
214
        if (obj4.isName("Type1")) {
 
215
          embFontID = obj2.getRef();
 
216
          if (type != fontType1) {
 
217
            error(-1, "Mismatch between font type and embedded font file");
 
218
            type = fontType1;
 
219
          }
 
220
        } else if (obj4.isName("Type1C")) {
 
221
          embFontID = obj2.getRef();
 
222
          if (type != fontType1 && type != fontType1C) {
 
223
            error(-1, "Mismatch between font type and embedded font file");
 
224
          }
 
225
          type = fontType1C;
 
226
        } else if (obj4.isName("TrueType")) {
 
227
          embFontID = obj2.getRef();
 
228
          if (type != fontTrueType) {
 
229
            error(-1, "Mismatch between font type and embedded font file");
 
230
            type = fontTrueType;
 
231
          }
 
232
        } else if (obj4.isName("CIDFontType0C")) {
 
233
          embFontID = obj2.getRef();
 
234
          if (type != fontCIDType0) {
 
235
            error(-1, "Mismatch between font type and embedded font file");
 
236
          }
 
237
          type = fontCIDType0C;
 
238
        } else if (obj4.isName("OpenType")) {
 
239
          embFontID = obj2.getRef();
 
240
          if (type == fontTrueType) {
 
241
            type = fontTrueTypeOT;
 
242
          } else if (type == fontType1) {
 
243
            type = fontType1COT;
 
244
          } else if (type == fontCIDType0) {
 
245
            type = fontCIDType0COT;
 
246
          } else if (type == fontCIDType2) {
 
247
            type = fontCIDType2OT;
 
248
          } else {
 
249
            error(-1, "Mismatch between font type and embedded font file");
 
250
          }
 
251
        } else {
 
252
          error(-1, "Unknown embedded font type '%s'",
 
253
                obj4.isName() ? obj4.getName() : "???");
 
254
        }
 
255
        obj4.free();
 
256
      }
 
257
      obj3.free();
 
258
    }
 
259
    obj2.free();
 
260
 
 
261
    // look for MissingWidth
 
262
    obj1.dictLookup("MissingWidth", &obj2);
 
263
    if (obj2.isNum()) {
 
264
      missingWidth = obj2.getNum();
 
265
    }
 
266
    obj2.free();
 
267
 
 
268
    // get Ascent and Descent
 
269
    obj1.dictLookup("Ascent", &obj2);
 
270
    if (obj2.isNum()) {
 
271
      t = 0.001 * obj2.getNum();
 
272
      // some broken font descriptors set ascent and descent to 0
 
273
      if (t != 0) {
 
274
        ascent = t;
 
275
      }
 
276
    }
 
277
    obj2.free();
 
278
    obj1.dictLookup("Descent", &obj2);
 
279
    if (obj2.isNum()) {
 
280
      t = 0.001 * obj2.getNum();
 
281
      // some broken font descriptors set ascent and descent to 0
 
282
      if (t != 0) {
 
283
        descent = t;
 
284
      }
 
285
      // some broken font descriptors specify a positive descent
 
286
      if (descent > 0) {
 
287
        descent = -descent;
 
288
      }
 
289
    }
 
290
    obj2.free();
 
291
 
 
292
    // font FontBBox
 
293
    if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
 
294
      for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
 
295
        if (obj2.arrayGet(i, &obj3)->isNum()) {
 
296
          fontBBox[i] = 0.001 * obj3.getNum();
 
297
        }
 
298
        obj3.free();
 
299
      }
 
300
    }
 
301
    obj2.free();
 
302
 
 
303
  }
 
304
  obj1.free();
 
305
}
 
306
 
 
307
CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
 
308
                                              CharCodeToUnicode *ctu) {
 
309
  GString *buf;
 
310
  Object obj1;
 
311
  int c;
 
312
 
 
313
  if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
 
314
    obj1.free();
 
315
    return NULL;
 
316
  }
 
317
  buf = new GString();
 
318
  obj1.streamReset();
 
319
  while ((c = obj1.streamGetChar()) != EOF) {
 
320
    buf->append(c);
 
321
  }
 
322
  obj1.streamClose();
 
323
  obj1.free();
 
324
  if (ctu) {
 
325
    ctu->mergeCMap(buf, nBits);
 
326
  } else {
 
327
    ctu = CharCodeToUnicode::parseCMap(buf, nBits);
 
328
  }
 
329
  delete buf;
 
330
  return ctu;
 
331
}
 
332
 
 
333
void GfxFont::findExtFontFile() {
 
334
  static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
 
335
  static char *ttExts[] = { ".ttf", NULL };
 
336
 
 
337
  if (name) {
 
338
    if (type == fontType1) {
 
339
      extFontFile = globalParams->findFontFile(name, type1Exts);
 
340
    } else if (type == fontTrueType) {
 
341
      extFontFile = globalParams->findFontFile(name, ttExts);
 
342
    }
 
343
  }
 
344
}
 
345
 
 
346
char *GfxFont::readExtFontFile(int *len) {
 
347
  FILE *f;
 
348
  char *buf;
 
349
 
 
350
  if (!(f = fopen(extFontFile->getCString(), "rb"))) {
 
351
    error(-1, "External font file '%s' vanished", extFontFile->getCString());
 
352
    return NULL;
 
353
  }
 
354
  fseek(f, 0, SEEK_END);
 
355
  *len = (int)ftell(f);
 
356
  fseek(f, 0, SEEK_SET);
 
357
  buf = (char *)gmalloc(*len);
 
358
  if ((int)fread(buf, 1, *len, f) != *len) {
 
359
    error(-1, "Error reading external font file '%s'",
 
360
          extFontFile->getCString());
 
361
  }
 
362
  fclose(f);
 
363
  return buf;
 
364
}
 
365
 
 
366
char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
 
367
  char *buf;
 
368
  Object obj1, obj2;
 
369
  Stream *str;
 
370
  int c;
 
371
  int size, i;
 
372
 
 
373
  obj1.initRef(embFontID.num, embFontID.gen);
 
374
  obj1.fetch(xref, &obj2);
 
375
  if (!obj2.isStream()) {
 
376
    error(-1, "Embedded font file is not a stream");
 
377
    obj2.free();
 
378
    obj1.free();
 
379
    embFontID.num = -1;
 
380
    return NULL;
 
381
  }
 
382
  str = obj2.getStream();
 
383
 
 
384
  buf = NULL;
 
385
  i = size = 0;
 
386
  str->reset();
 
387
  while ((c = str->getChar()) != EOF) {
 
388
    if (i == size) {
 
389
      size += 4096;
 
390
      buf = (char *)grealloc(buf, size);
 
391
    }
 
392
    buf[i++] = c;
 
393
  }
 
394
  *len = i;
 
395
  str->close();
 
396
 
 
397
  obj2.free();
 
398
  obj1.free();
 
399
 
 
400
  return buf;
 
401
}
 
402
 
 
403
//------------------------------------------------------------------------
 
404
// Gfx8BitFont
 
405
//------------------------------------------------------------------------
 
406
 
 
407
Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
 
408
                         GfxFontType typeA, Dict *fontDict):
 
409
  GfxFont(tagA, idA, nameA)
 
410
{
 
411
  GString *name2;
 
412
  BuiltinFont *builtinFont;
 
413
  char **baseEnc;
 
414
  GBool baseEncFromFontFile;
 
415
  char *buf;
 
416
  int len;
 
417
  FoFiType1 *ffT1;
 
418
  FoFiType1C *ffT1C;
 
419
  int code, code2;
 
420
  char *charName;
 
421
  GBool missing, hex;
 
422
  Unicode toUnicode[256];
 
423
  CharCodeToUnicode *utu, *ctu2;
 
424
  Unicode uBuf[8];
 
425
  double mul;
 
426
  int firstChar, lastChar;
 
427
  Gushort w;
 
428
  Object obj1, obj2, obj3;
 
429
  int n, i, a, b, m;
 
430
 
 
431
  type = typeA;
 
432
  ctu = NULL;
 
433
 
 
434
  // do font name substitution for various aliases of the Base 14 font
 
435
  // names
 
436
  if (name) {
 
437
    name2 = name->copy();
 
438
    i = 0;
 
439
    while (i < name2->getLength()) {
 
440
      if (name2->getChar(i) == ' ') {
 
441
        name2->del(i);
 
442
      } else {
 
443
        ++i;
 
444
      }
 
445
    }
 
446
    a = 0;
 
447
    b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
 
448
    // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName
 
449
    while (b - a > 1) {
 
450
      m = (a + b) / 2;
 
451
      if (name2->cmp(stdFontMap[m].altName) >= 0) {
 
452
        a = m;
 
453
      } else {
 
454
        b = m;
 
455
      }
 
456
    }
 
457
    if (!name2->cmp(stdFontMap[a].altName)) {
 
458
      name = new GString(stdFontMap[a].properName);
 
459
    }
 
460
    delete name2;
 
461
  }
 
462
 
 
463
  // is it a built-in font?
 
464
  builtinFont = NULL;
 
465
  if (name) {
 
466
    for (i = 0; i < nBuiltinFonts; ++i) {
 
467
      if (!name->cmp(builtinFonts[i].name)) {
 
468
        builtinFont = &builtinFonts[i];
 
469
        break;
 
470
      }
 
471
    }
 
472
  }
 
473
 
 
474
  // default ascent/descent values
 
475
  if (builtinFont) {
 
476
    ascent = 0.001 * builtinFont->ascent;
 
477
    descent = 0.001 * builtinFont->descent;
 
478
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
 
479
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
 
480
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
 
481
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
 
482
  } else {
 
483
    ascent = 0.95;
 
484
    descent = -0.35;
 
485
    fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
 
486
  }
 
487
 
 
488
  // get info from font descriptor
 
489
  readFontDescriptor(xref, fontDict);
 
490
 
 
491
  // for non-embedded fonts, don't trust the ascent/descent/bbox
 
492
  // values from the font descriptor
 
493
  if (builtinFont && embFontID.num < 0) {
 
494
    ascent = 0.001 * builtinFont->ascent;
 
495
    descent = 0.001 * builtinFont->descent;
 
496
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
 
497
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
 
498
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
 
499
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
 
500
  }
 
501
 
 
502
  // look for an external font file
 
503
  findExtFontFile();
 
504
 
 
505
  // get font matrix
 
506
  fontMat[0] = fontMat[3] = 1;
 
507
  fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
 
508
  if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
 
509
    for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
 
510
      if (obj1.arrayGet(i, &obj2)->isNum()) {
 
511
        fontMat[i] = obj2.getNum();
 
512
      }
 
513
      obj2.free();
 
514
    }
 
515
  }
 
516
  obj1.free();
 
517
 
 
518
  // get Type 3 bounding box, font definition, and resources
 
519
  if (type == fontType3) {
 
520
    if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
 
521
      for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
 
522
        if (obj1.arrayGet(i, &obj2)->isNum()) {
 
523
          fontBBox[i] = obj2.getNum();
 
524
        }
 
525
        obj2.free();
 
526
      }
 
527
    }
 
528
    obj1.free();
 
529
    if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
 
530
      error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
 
531
      charProcs.free();
 
532
    }
 
533
    if (!fontDict->lookup("Resources", &resources)->isDict()) {
 
534
      resources.free();
 
535
    }
 
536
  }
 
537
 
 
538
  //----- build the font encoding -----
 
539
 
 
540
  // Encodings start with a base encoding, which can come from
 
541
  // (in order of priority):
 
542
  //   1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
 
543
  //        - MacRoman / MacExpert / WinAnsi / Standard
 
544
  //   2. embedded or external font file
 
545
  //   3. default:
 
546
  //        - builtin --> builtin encoding
 
547
  //        - TrueType --> WinAnsiEncoding
 
548
  //        - others --> StandardEncoding
 
549
  // and then add a list of differences (if any) from
 
550
  // FontDict.Encoding.Differences.
 
551
 
 
552
  // check FontDict for base encoding
 
553
  hasEncoding = gFalse;
 
554
  usesMacRomanEnc = gFalse;
 
555
  baseEnc = NULL;
 
556
  baseEncFromFontFile = gFalse;
 
557
  fontDict->lookup("Encoding", &obj1);
 
558
  if (obj1.isDict()) {
 
559
    obj1.dictLookup("BaseEncoding", &obj2);
 
560
    if (obj2.isName("MacRomanEncoding")) {
 
561
      hasEncoding = gTrue;
 
562
      usesMacRomanEnc = gTrue;
 
563
      baseEnc = macRomanEncoding;
 
564
    } else if (obj2.isName("MacExpertEncoding")) {
 
565
      hasEncoding = gTrue;
 
566
      baseEnc = macExpertEncoding;
 
567
    } else if (obj2.isName("WinAnsiEncoding")) {
 
568
      hasEncoding = gTrue;
 
569
      baseEnc = winAnsiEncoding;
 
570
    }
 
571
    obj2.free();
 
572
  } else if (obj1.isName("MacRomanEncoding")) {
 
573
    hasEncoding = gTrue;
 
574
    usesMacRomanEnc = gTrue;
 
575
    baseEnc = macRomanEncoding;
 
576
  } else if (obj1.isName("MacExpertEncoding")) {
 
577
    hasEncoding = gTrue;
 
578
    baseEnc = macExpertEncoding;
 
579
  } else if (obj1.isName("WinAnsiEncoding")) {
 
580
    hasEncoding = gTrue;
 
581
    baseEnc = winAnsiEncoding;
 
582
  }
 
583
 
 
584
  // check embedded or external font file for base encoding
 
585
  // (only for Type 1 fonts - trying to get an encoding out of a
 
586
  // TrueType font is a losing proposition)
 
587
  ffT1 = NULL;
 
588
  ffT1C = NULL;
 
589
  buf = NULL;
 
590
  if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
 
591
    if (extFontFile) {
 
592
      ffT1 = FoFiType1::load(extFontFile->getCString());
 
593
    } else {
 
594
      buf = readEmbFontFile(xref, &len);
 
595
      ffT1 = FoFiType1::make(buf, len);
 
596
    }
 
597
    if (ffT1) {
 
598
      if (ffT1->getName()) {
 
599
        if (embFontName) {
 
600
          delete embFontName;
 
601
        }
 
602
        embFontName = new GString(ffT1->getName());
 
603
      }
 
604
      if (!baseEnc) {
 
605
        baseEnc = ffT1->getEncoding();
 
606
        baseEncFromFontFile = gTrue;
 
607
      }
 
608
    }
 
609
  } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
 
610
    if (extFontFile) {
 
611
      ffT1C = FoFiType1C::load(extFontFile->getCString());
 
612
    } else {
 
613
      buf = readEmbFontFile(xref, &len);
 
614
      ffT1C = FoFiType1C::make(buf, len);
 
615
    }
 
616
    if (ffT1C) {
 
617
      if (ffT1C->getName()) {
 
618
        if (embFontName) {
 
619
          delete embFontName;
 
620
        }
 
621
        embFontName = new GString(ffT1C->getName());
 
622
      }
 
623
      if (!baseEnc) {
 
624
        baseEnc = ffT1C->getEncoding();
 
625
        baseEncFromFontFile = gTrue;
 
626
      }
 
627
    }
 
628
  }
 
629
  if (buf) {
 
630
    gfree(buf);
 
631
  }
 
632
 
 
633
  // get default base encoding
 
634
  if (!baseEnc) {
 
635
    if (builtinFont && embFontID.num < 0) {
 
636
      baseEnc = builtinFont->defaultBaseEnc;
 
637
      hasEncoding = gTrue;
 
638
    } else if (type == fontTrueType) {
 
639
      baseEnc = winAnsiEncoding;
 
640
    } else {
 
641
      baseEnc = standardEncoding;
 
642
    }
 
643
  }
 
644
 
 
645
  // copy the base encoding
 
646
  for (i = 0; i < 256; ++i) {
 
647
    enc[i] = baseEnc[i];
 
648
    if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
 
649
      enc[i] = copyString(baseEnc[i]);
 
650
    }
 
651
  }
 
652
 
 
653
  // some Type 1C font files have empty encodings, which can break the
 
654
  // T1C->T1 conversion (since the 'seac' operator depends on having
 
655
  // the accents in the encoding), so we fill in any gaps from
 
656
  // StandardEncoding
 
657
  if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
 
658
      baseEncFromFontFile) {
 
659
    for (i = 0; i < 256; ++i) {
 
660
      if (!enc[i] && standardEncoding[i]) {
 
661
        enc[i] = standardEncoding[i];
 
662
        encFree[i] = gFalse;
 
663
      }
 
664
    }
 
665
  }
 
666
 
 
667
  // merge differences into encoding
 
668
  if (obj1.isDict()) {
 
669
    obj1.dictLookup("Differences", &obj2);
 
670
    if (obj2.isArray()) {
 
671
      hasEncoding = gTrue;
 
672
      code = 0;
 
673
      for (i = 0; i < obj2.arrayGetLength(); ++i) {
 
674
        obj2.arrayGet(i, &obj3);
 
675
        if (obj3.isInt()) {
 
676
          code = obj3.getInt();
 
677
        } else if (obj3.isName()) {
 
678
          if (code >= 0 && code < 256) {
 
679
            if (encFree[code]) {
 
680
              gfree(enc[code]);
 
681
            }
 
682
            enc[code] = copyString(obj3.getName());
 
683
            encFree[code] = gTrue;
 
684
          }
 
685
          ++code;
 
686
        } else {
 
687
          error(-1, "Wrong type in font encoding resource differences (%s)",
 
688
                obj3.getTypeName());
 
689
        }
 
690
        obj3.free();
 
691
      }
 
692
    }
 
693
    obj2.free();
 
694
  }
 
695
  obj1.free();
 
696
  if (ffT1) {
 
697
    delete ffT1;
 
698
  }
 
699
  if (ffT1C) {
 
700
    delete ffT1C;
 
701
  }
 
702
 
 
703
  //----- build the mapping to Unicode -----
 
704
 
 
705
  // pass 1: use the name-to-Unicode mapping table
 
706
  missing = hex = gFalse;
 
707
  for (code = 0; code < 256; ++code) {
 
708
    if ((charName = enc[code])) {
 
709
      if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
 
710
          strcmp(charName, ".notdef")) {
 
711
        // if it wasn't in the name-to-Unicode table, check for a
 
712
        // name that looks like 'Axx' or 'xx', where 'A' is any letter
 
713
        // and 'xx' is two hex digits
 
714
        if ((strlen(charName) == 3 &&
 
715
             isalpha(charName[0]) &&
 
716
             isxdigit(charName[1]) && isxdigit(charName[2]) &&
 
717
             ((charName[1] >= 'a' && charName[1] <= 'f') ||
 
718
              (charName[1] >= 'A' && charName[1] <= 'F') ||
 
719
              (charName[2] >= 'a' && charName[2] <= 'f') ||
 
720
              (charName[2] >= 'A' && charName[2] <= 'F'))) ||
 
721
            (strlen(charName) == 2 &&
 
722
             isxdigit(charName[0]) && isxdigit(charName[1]) &&
 
723
             ((charName[0] >= 'a' && charName[0] <= 'f') ||
 
724
              (charName[0] >= 'A' && charName[0] <= 'F') ||
 
725
              (charName[1] >= 'a' && charName[1] <= 'f') ||
 
726
              (charName[1] >= 'A' && charName[1] <= 'F')))) {
 
727
          hex = gTrue;
 
728
        }
 
729
        missing = gTrue;
 
730
      }
 
731
    } else {
 
732
      toUnicode[code] = 0;
 
733
    }
 
734
  }
 
735
 
 
736
  // pass 2: try to fill in the missing chars, looking for names of
 
737
  // the form 'Axx', 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B'
 
738
  // are any letters, 'xx' is two hex digits, and 'nn' is 2-4
 
739
  // decimal digits
 
740
  if (missing && globalParams->getMapNumericCharNames()) {
 
741
    for (code = 0; code < 256; ++code) {
 
742
      if ((charName = enc[code]) && !toUnicode[code] &&
 
743
          strcmp(charName, ".notdef")) {
 
744
        n = strlen(charName);
 
745
        code2 = -1;
 
746
        if (hex && n == 3 && isalpha(charName[0]) &&
 
747
            isxdigit(charName[1]) && isxdigit(charName[2])) {
 
748
          sscanf(charName+1, "%x", &code2);
 
749
        } else if (hex && n == 2 &&
 
750
                   isxdigit(charName[0]) && isxdigit(charName[1])) {
 
751
          sscanf(charName, "%x", &code2);
 
752
        } else if (!hex && n >= 2 && n <= 4 &&
 
753
                   isdigit(charName[0]) && isdigit(charName[1])) {
 
754
          code2 = atoi(charName);
 
755
        } else if (n >= 3 && n <= 5 &&
 
756
                   isdigit(charName[1]) && isdigit(charName[2])) {
 
757
          code2 = atoi(charName+1);
 
758
        } else if (n >= 4 && n <= 6 &&
 
759
                   isdigit(charName[2]) && isdigit(charName[3])) {
 
760
          code2 = atoi(charName+2);
 
761
        }
 
762
        if (code2 >= 0 && code2 <= 0xff) {
 
763
          toUnicode[code] = (Unicode)code2;
 
764
        }
 
765
      }
 
766
    }
 
767
 
 
768
  // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
 
769
  // mapping for unknown character names
 
770
  } else if (missing && globalParams->getMapUnknownCharNames()) {
 
771
    for (code = 0; code < 256; ++code) {
 
772
      if (!toUnicode[code]) {
 
773
        toUnicode[code] = code;
 
774
      }
 
775
    }
 
776
  }
 
777
 
 
778
  // construct the char code -> Unicode mapping object
 
779
  ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
 
780
 
 
781
  // merge in a ToUnicode CMap, if there is one -- this overwrites
 
782
  // existing entries in ctu, i.e., the ToUnicode CMap takes
 
783
  // precedence, but the other encoding info is allowed to fill in any
 
784
  // holes
 
785
  readToUnicodeCMap(fontDict, 8, ctu);
 
786
 
 
787
  // look for a Unicode-to-Unicode mapping
 
788
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
 
789
    for (i = 0; i < 256; ++i) {
 
790
      toUnicode[i] = 0;
 
791
    }
 
792
    ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
 
793
    for (i = 0; i < 256; ++i) {
 
794
      n = ctu->mapToUnicode((CharCode)i, uBuf, 8);
 
795
      if (n >= 1) {
 
796
        n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
 
797
        if (n >= 1) {
 
798
          ctu2->setMapping((CharCode)i, uBuf, n);
 
799
        }
 
800
      }
 
801
    }
 
802
    utu->decRefCnt();
 
803
    delete ctu;
 
804
    ctu = ctu2;
 
805
  }
 
806
 
 
807
  //----- get the character widths -----
 
808
 
 
809
  // initialize all widths
 
810
  for (code = 0; code < 256; ++code) {
 
811
    widths[code] = missingWidth * 0.001;
 
812
  }
 
813
 
 
814
  // use widths from font dict, if present
 
815
  fontDict->lookup("FirstChar", &obj1);
 
816
  firstChar = obj1.isInt() ? obj1.getInt() : 0;
 
817
  obj1.free();
 
818
  if (firstChar < 0 || firstChar > 255) {
 
819
    firstChar = 0;
 
820
  }
 
821
  fontDict->lookup("LastChar", &obj1);
 
822
  lastChar = obj1.isInt() ? obj1.getInt() : 255;
 
823
  obj1.free();
 
824
  if (lastChar < 0 || lastChar > 255) {
 
825
    lastChar = 255;
 
826
  }
 
827
  mul = (type == fontType3) ? fontMat[0] : 0.001;
 
828
  fontDict->lookup("Widths", &obj1);
 
829
  if (obj1.isArray()) {
 
830
    flags |= fontFixedWidth;
 
831
    if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
 
832
      lastChar = firstChar + obj1.arrayGetLength() - 1;
 
833
    }
 
834
    for (code = firstChar; code <= lastChar; ++code) {
 
835
      obj1.arrayGet(code - firstChar, &obj2);
 
836
      if (obj2.isNum()) {
 
837
        widths[code] = obj2.getNum() * mul;
 
838
        if (widths[code] != widths[firstChar]) {
 
839
          flags &= ~fontFixedWidth;
 
840
        }
 
841
      }
 
842
      obj2.free();
 
843
    }
 
844
 
 
845
  // use widths from built-in font
 
846
  } else if (builtinFont) {
 
847
    // this is a kludge for broken PDF files that encode char 32
 
848
    // as .notdef
 
849
    if (builtinFont->widths->getWidth("space", &w)) {
 
850
      widths[32] = 0.001 * w;
 
851
    }
 
852
    for (code = 0; code < 256; ++code) {
 
853
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
 
854
        widths[code] = 0.001 * w;
 
855
      }
 
856
    }
 
857
 
 
858
  // couldn't find widths -- use defaults 
 
859
  } else {
 
860
    // this is technically an error -- the Widths entry is required
 
861
    // for all but the Base-14 fonts -- but certain PDF generators
 
862
    // apparently don't include widths for Arial and TimesNewRoman
 
863
    if (isFixedWidth()) {
 
864
      i = 0;
 
865
    } else if (isSerif()) {
 
866
      i = 8;
 
867
    } else {
 
868
      i = 4;
 
869
    }
 
870
    if (isBold()) {
 
871
      i += 2;
 
872
    }
 
873
    if (isItalic()) {
 
874
      i += 1;
 
875
    }
 
876
    builtinFont = builtinFontSubst[i];
 
877
    // this is a kludge for broken PDF files that encode char 32
 
878
    // as .notdef
 
879
    if (builtinFont->widths->getWidth("space", &w)) {
 
880
      widths[32] = 0.001 * w;
 
881
    }
 
882
    for (code = 0; code < 256; ++code) {
 
883
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
 
884
        widths[code] = 0.001 * w;
 
885
      }
 
886
    }
 
887
  }
 
888
  obj1.free();
 
889
 
 
890
  ok = gTrue;
 
891
}
 
892
 
 
893
Gfx8BitFont::~Gfx8BitFont() {
 
894
  int i;
 
895
 
 
896
  for (i = 0; i < 256; ++i) {
 
897
    if (encFree[i] && enc[i]) {
 
898
      gfree(enc[i]);
 
899
    }
 
900
  }
 
901
  ctu->decRefCnt();
 
902
  if (charProcs.isDict()) {
 
903
    charProcs.free();
 
904
  }
 
905
  if (resources.isDict()) {
 
906
    resources.free();
 
907
  }
 
908
}
 
909
 
 
910
int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
 
911
                             Unicode *u, int uSize, int *uLen,
 
912
                             double *dx, double *dy, double *ox, double *oy) {
 
913
  CharCode c;
 
914
 
 
915
  *code = c = (CharCode)(*s & 0xff);
 
916
  *uLen = ctu->mapToUnicode(c, u, uSize);
 
917
  *dx = widths[c];
 
918
  *dy = *ox = *oy = 0;
 
919
  return 1;
 
920
}
 
921
 
 
922
CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
 
923
  ctu->incRefCnt();
 
924
  return ctu;
 
925
}
 
926
 
 
927
Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
 
928
  Gushort *map;
 
929
  int cmapPlatform, cmapEncoding;
 
930
  int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
 
931
  GBool useMacRoman, useUnicode;
 
932
  char *charName;
 
933
  Unicode u;
 
934
  int code, i, n;
 
935
 
 
936
  map = (Gushort *)gmallocn(256, sizeof(Gushort));
 
937
  for (i = 0; i < 256; ++i) {
 
938
    map[i] = 0;
 
939
  }
 
940
 
 
941
  // To match up with the Adobe-defined behaviour, we choose a cmap
 
942
  // like this:
 
943
  // 1. If the PDF font has an encoding:
 
944
  //    1a. If the PDF font specified MacRomanEncoding and the
 
945
  //        TrueType font has a Macintosh Roman cmap, use it, and
 
946
  //        reverse map the char names through MacRomanEncoding to
 
947
  //        get char codes.
 
948
  //    1b. If the TrueType font has a Microsoft Unicode cmap or a
 
949
  //        non-Microsoft Unicode cmap, use it, and use the Unicode
 
950
  //        indexes, not the char codes.
 
951
  //    1c. If the PDF font is symbolic and the TrueType font has a
 
952
  //        Microsoft Symbol cmap, use it, and use char codes
 
953
  //        directly (possibly with an offset of 0xf000).
 
954
  //    1d. If the TrueType font has a Macintosh Roman cmap, use it,
 
955
  //        as in case 1a.
 
956
  // 2. If the PDF font does not have an encoding or the PDF font is
 
957
  //    symbolic:
 
958
  //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
 
959
  //        and use char codes directly (possibly with an offset of
 
960
  //        0xf000).
 
961
  //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
 
962
  //        and use char codes directly (possible with an offset of
 
963
  //        0xf000).
 
964
  // 3. If none of these rules apply, use the first cmap and hope for
 
965
  //    the best (this shouldn't happen).
 
966
  unicodeCmap = macRomanCmap = msSymbolCmap = -1;
 
967
  for (i = 0; i < ff->getNumCmaps(); ++i) {
 
968
    cmapPlatform = ff->getCmapPlatform(i);
 
969
    cmapEncoding = ff->getCmapEncoding(i);
 
970
    if ((cmapPlatform == 3 && cmapEncoding == 1) ||
 
971
        cmapPlatform == 0) {
 
972
      unicodeCmap = i;
 
973
    } else if (cmapPlatform == 1 && cmapEncoding == 0) {
 
974
      macRomanCmap = i;
 
975
    } else if (cmapPlatform == 3 && cmapEncoding == 0) {
 
976
      msSymbolCmap = i;
 
977
    }
 
978
  }
 
979
  cmap = 0;
 
980
  useMacRoman = gFalse;
 
981
  useUnicode = gFalse;
 
982
  if (hasEncoding) {
 
983
    if (usesMacRomanEnc && macRomanCmap >= 0) {
 
984
      cmap = macRomanCmap;
 
985
      useMacRoman = gTrue;
 
986
    } else if (unicodeCmap >= 0) {
 
987
      cmap = unicodeCmap;
 
988
      useUnicode = gTrue;
 
989
    } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
 
990
      cmap = msSymbolCmap;
 
991
    } else if ((flags & fontSymbolic) && macRomanCmap >= 0) {
 
992
      cmap = macRomanCmap;
 
993
    } else if (macRomanCmap >= 0) {
 
994
      cmap = macRomanCmap;
 
995
      useMacRoman = gTrue;
 
996
    }
 
997
  } else {
 
998
    if (msSymbolCmap >= 0) {
 
999
      cmap = msSymbolCmap;
 
1000
    } else if (macRomanCmap >= 0) {
 
1001
      cmap = macRomanCmap;
 
1002
    }
 
1003
  }
 
1004
 
 
1005
  // reverse map the char names through MacRomanEncoding, then map the
 
1006
  // char codes through the cmap
 
1007
  if (useMacRoman) {
 
1008
    for (i = 0; i < 256; ++i) {
 
1009
      if ((charName = enc[i])) {
 
1010
        if ((code = globalParams->getMacRomanCharCode(charName))) {
 
1011
          map[i] = ff->mapCodeToGID(cmap, code);
 
1012
        }
 
1013
      }
 
1014
    }
 
1015
 
 
1016
  // map Unicode through the cmap
 
1017
  } else if (useUnicode) {
 
1018
    for (i = 0; i < 256; ++i) {
 
1019
      if (((charName = enc[i]) &&
 
1020
           (u = globalParams->mapNameToUnicode(charName))) ||
 
1021
          (n = ctu->mapToUnicode((CharCode)i, &u, 1))) {
 
1022
        map[i] = ff->mapCodeToGID(cmap, u);
 
1023
      }
 
1024
    }
 
1025
 
 
1026
  // map the char codes through the cmap, possibly with an offset of
 
1027
  // 0xf000
 
1028
  } else {
 
1029
    for (i = 0; i < 256; ++i) {
 
1030
      if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
 
1031
        map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
 
1032
      }
 
1033
    }
 
1034
  }
 
1035
 
 
1036
  // try the TrueType 'post' table to handle any unmapped characters
 
1037
  for (i = 0; i < 256; ++i) {
 
1038
    if (!map[i] && (charName = enc[i])) {
 
1039
      map[i] = (Gushort)(int)ff->mapNameToGID(charName);
 
1040
    }
 
1041
  }
 
1042
 
 
1043
  return map;
 
1044
}
 
1045
 
 
1046
Dict *Gfx8BitFont::getCharProcs() {
 
1047
  return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
 
1048
}
 
1049
 
 
1050
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
 
1051
  if (enc[code] && charProcs.isDict()) {
 
1052
    charProcs.dictLookup(enc[code], proc);
 
1053
  } else {
 
1054
    proc->initNull();
 
1055
  }
 
1056
  return proc;
 
1057
}
 
1058
 
 
1059
Dict *Gfx8BitFont::getResources() {
 
1060
  return resources.isDict() ? resources.getDict() : (Dict *)NULL;
 
1061
}
 
1062
 
 
1063
//------------------------------------------------------------------------
 
1064
// GfxCIDFont
 
1065
//------------------------------------------------------------------------
 
1066
 
 
1067
static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
 
1068
  return ((GfxFontCIDWidthExcep *)w1)->first -
 
1069
         ((GfxFontCIDWidthExcep *)w2)->first;
 
1070
}
 
1071
 
 
1072
static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
 
1073
  return ((GfxFontCIDWidthExcepV *)w1)->first -
 
1074
         ((GfxFontCIDWidthExcepV *)w2)->first;
 
1075
}
 
1076
 
 
1077
GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GString *nameA,
 
1078
                       Dict *fontDict):
 
1079
  GfxFont(tagA, idA, nameA)
 
1080
{
 
1081
  Dict *desFontDict;
 
1082
  GString *collection, *cMapName;
 
1083
  Object desFontDictObj;
 
1084
  Object obj1, obj2, obj3, obj4, obj5, obj6;
 
1085
  CharCodeToUnicode *utu;
 
1086
  CharCode c;
 
1087
  Unicode uBuf[8];
 
1088
  int c1, c2;
 
1089
  int excepsSize, i, j, k, n;
 
1090
 
 
1091
  ascent = 0.95;
 
1092
  descent = -0.35;
 
1093
  fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
 
1094
  cMap = NULL;
 
1095
  ctu = NULL;
 
1096
  widths.defWidth = 1.0;
 
1097
  widths.defHeight = -1.0;
 
1098
  widths.defVY = 0.880;
 
1099
  widths.exceps = NULL;
 
1100
  widths.nExceps = 0;
 
1101
  widths.excepsV = NULL;
 
1102
  widths.nExcepsV = 0;
 
1103
  cidToGID = NULL;
 
1104
  cidToGIDLen = 0;
 
1105
 
 
1106
  // get the descendant font
 
1107
  if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
 
1108
    error(-1, "Missing DescendantFonts entry in Type 0 font");
 
1109
    obj1.free();
 
1110
    goto err1;
 
1111
  }
 
1112
  if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
 
1113
    error(-1, "Bad descendant font in Type 0 font");
 
1114
    goto err3;
 
1115
  }
 
1116
  obj1.free();
 
1117
  desFontDict = desFontDictObj.getDict();
 
1118
 
 
1119
  // font type
 
1120
  if (!desFontDict->lookup("Subtype", &obj1)) {
 
1121
    error(-1, "Missing Subtype entry in Type 0 descendant font");
 
1122
    goto err3;
 
1123
  }
 
1124
  if (obj1.isName("CIDFontType0")) {
 
1125
    type = fontCIDType0;
 
1126
  } else if (obj1.isName("CIDFontType2")) {
 
1127
    type = fontCIDType2;
 
1128
  } else {
 
1129
    error(-1, "Unknown Type 0 descendant font type '%s'",
 
1130
          obj1.isName() ? obj1.getName() : "???");
 
1131
    goto err3;
 
1132
  }
 
1133
  obj1.free();
 
1134
 
 
1135
  // get info from font descriptor
 
1136
  readFontDescriptor(xref, desFontDict);
 
1137
 
 
1138
  // look for an external font file
 
1139
  findExtFontFile();
 
1140
 
 
1141
  //----- encoding info -----
 
1142
 
 
1143
  // char collection
 
1144
  if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
 
1145
    error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
 
1146
    goto err3;
 
1147
  }
 
1148
  obj1.dictLookup("Registry", &obj2);
 
1149
  obj1.dictLookup("Ordering", &obj3);
 
1150
  if (!obj2.isString() || !obj3.isString()) {
 
1151
    error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
 
1152
    goto err4;
 
1153
  }
 
1154
  collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
 
1155
  obj3.free();
 
1156
  obj2.free();
 
1157
  obj1.free();
 
1158
 
 
1159
  // look for a ToUnicode CMap
 
1160
  if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
 
1161
 
 
1162
    // the "Adobe-Identity" and "Adobe-UCS" collections don't have
 
1163
    // cidToUnicode files
 
1164
    if (collection->cmp("Adobe-Identity") &&
 
1165
        collection->cmp("Adobe-UCS")) {
 
1166
 
 
1167
      // look for a user-supplied .cidToUnicode file
 
1168
      if (!(ctu = globalParams->getCIDToUnicode(collection))) {
 
1169
        error(-1, "Unknown character collection '%s'",
 
1170
              collection->getCString());
 
1171
        // fall-through, assuming the Identity mapping -- this appears
 
1172
        // to match Adobe's behavior
 
1173
      }
 
1174
    }
 
1175
  }
 
1176
 
 
1177
  // look for a Unicode-to-Unicode mapping
 
1178
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
 
1179
    if (ctu) {
 
1180
      for (c = 0; c < ctu->getLength(); ++c) {
 
1181
        n = ctu->mapToUnicode(c, uBuf, 8);
 
1182
        if (n >= 1) {
 
1183
          n = utu->mapToUnicode((CharCode)uBuf[0], uBuf, 8);
 
1184
          if (n >= 1) {
 
1185
            ctu->setMapping(c, uBuf, n);
 
1186
          }
 
1187
        }
 
1188
      }
 
1189
      utu->decRefCnt();
 
1190
    } else {
 
1191
      ctu = utu;
 
1192
    }
 
1193
  }
 
1194
 
 
1195
  // encoding (i.e., CMap)
 
1196
  //~ need to handle a CMap stream here
 
1197
  //~ also need to deal with the UseCMap entry in the stream dict
 
1198
  if (!fontDict->lookup("Encoding", &obj1)->isName()) {
 
1199
    error(-1, "Missing or invalid Encoding entry in Type 0 font");
 
1200
    delete collection;
 
1201
    goto err3;
 
1202
  }
 
1203
  cMapName = new GString(obj1.getName());
 
1204
  obj1.free();
 
1205
  if (!(cMap = globalParams->getCMap(collection, cMapName))) {
 
1206
    error(-1, "Unknown CMap '%s' for character collection '%s'",
 
1207
          cMapName->getCString(), collection->getCString());
 
1208
    delete collection;
 
1209
    delete cMapName;
 
1210
    goto err2;
 
1211
  }
 
1212
  delete collection;
 
1213
  delete cMapName;
 
1214
 
 
1215
  // CIDToGIDMap (for embedded TrueType fonts)
 
1216
  if (type == fontCIDType2) {
 
1217
    desFontDict->lookup("CIDToGIDMap", &obj1);
 
1218
    if (obj1.isStream()) {
 
1219
      cidToGIDLen = 0;
 
1220
      i = 64;
 
1221
      cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort));
 
1222
      obj1.streamReset();
 
1223
      while ((c1 = obj1.streamGetChar()) != EOF &&
 
1224
             (c2 = obj1.streamGetChar()) != EOF) {
 
1225
        if (cidToGIDLen == i) {
 
1226
          i *= 2;
 
1227
          cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort));
 
1228
        }
 
1229
        cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
 
1230
      }
 
1231
    } else if (!obj1.isName("Identity") && !obj1.isNull()) {
 
1232
      error(-1, "Invalid CIDToGIDMap entry in CID font");
 
1233
    }
 
1234
    obj1.free();
 
1235
  }
 
1236
 
 
1237
  //----- character metrics -----
 
1238
 
 
1239
  // default char width
 
1240
  if (desFontDict->lookup("DW", &obj1)->isInt()) {
 
1241
    widths.defWidth = obj1.getInt() * 0.001;
 
1242
  }
 
1243
  obj1.free();
 
1244
 
 
1245
  // char width exceptions
 
1246
  if (desFontDict->lookup("W", &obj1)->isArray()) {
 
1247
    excepsSize = 0;
 
1248
    i = 0;
 
1249
    while (i + 1 < obj1.arrayGetLength()) {
 
1250
      obj1.arrayGet(i, &obj2);
 
1251
      obj1.arrayGet(i + 1, &obj3);
 
1252
      if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
 
1253
        if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
 
1254
          if (widths.nExceps == excepsSize) {
 
1255
            excepsSize += 16;
 
1256
            widths.exceps = (GfxFontCIDWidthExcep *)
 
1257
              greallocn(widths.exceps,
 
1258
                        excepsSize, sizeof(GfxFontCIDWidthExcep));
 
1259
          }
 
1260
          widths.exceps[widths.nExceps].first = obj2.getInt();
 
1261
          widths.exceps[widths.nExceps].last = obj3.getInt();
 
1262
          widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
 
1263
          ++widths.nExceps;
 
1264
        } else {
 
1265
          error(-1, "Bad widths array in Type 0 font");
 
1266
        }
 
1267
        obj4.free();
 
1268
        i += 3;
 
1269
      } else if (obj2.isInt() && obj3.isArray()) {
 
1270
        if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
 
1271
          excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
 
1272
          widths.exceps = (GfxFontCIDWidthExcep *)
 
1273
            greallocn(widths.exceps,
 
1274
                      excepsSize, sizeof(GfxFontCIDWidthExcep));
 
1275
        }
 
1276
        j = obj2.getInt();
 
1277
        for (k = 0; k < obj3.arrayGetLength(); ++k) {
 
1278
          if (obj3.arrayGet(k, &obj4)->isNum()) {
 
1279
            widths.exceps[widths.nExceps].first = j;
 
1280
            widths.exceps[widths.nExceps].last = j;
 
1281
            widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
 
1282
            ++j;
 
1283
            ++widths.nExceps;
 
1284
          } else {
 
1285
            error(-1, "Bad widths array in Type 0 font");
 
1286
          }
 
1287
          obj4.free();
 
1288
        }
 
1289
        i += 2;
 
1290
      } else {
 
1291
        error(-1, "Bad widths array in Type 0 font");
 
1292
        ++i;
 
1293
      }
 
1294
      obj3.free();
 
1295
      obj2.free();
 
1296
    }
 
1297
    qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
 
1298
          &cmpWidthExcep);
 
1299
  }
 
1300
  obj1.free();
 
1301
 
 
1302
  // default metrics for vertical font
 
1303
  if (desFontDict->lookup("DW2", &obj1)->isArray() &&
 
1304
      obj1.arrayGetLength() == 2) {
 
1305
    if (obj1.arrayGet(0, &obj2)->isNum()) {
 
1306
      widths.defVY = obj2.getNum() * 0.001;
 
1307
    }
 
1308
    obj2.free();
 
1309
    if (obj1.arrayGet(1, &obj2)->isNum()) {
 
1310
      widths.defHeight = obj2.getNum() * 0.001;
 
1311
    }
 
1312
    obj2.free();
 
1313
  }
 
1314
  obj1.free();
 
1315
 
 
1316
  // char metric exceptions for vertical font
 
1317
  if (desFontDict->lookup("W2", &obj1)->isArray()) {
 
1318
    excepsSize = 0;
 
1319
    i = 0;
 
1320
    while (i + 1 < obj1.arrayGetLength()) {
 
1321
      obj1.arrayGet(i, &obj2);
 
1322
      obj1.arrayGet(i+ 1, &obj3);
 
1323
      if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
 
1324
        if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
 
1325
            obj1.arrayGet(i + 3, &obj5)->isNum() &&
 
1326
            obj1.arrayGet(i + 4, &obj6)->isNum()) {
 
1327
          if (widths.nExcepsV == excepsSize) {
 
1328
            excepsSize += 16;
 
1329
            widths.excepsV = (GfxFontCIDWidthExcepV *)
 
1330
              greallocn(widths.excepsV,
 
1331
                        excepsSize, sizeof(GfxFontCIDWidthExcepV));
 
1332
          }
 
1333
          widths.excepsV[widths.nExcepsV].first = obj2.getInt();
 
1334
          widths.excepsV[widths.nExcepsV].last = obj3.getInt();
 
1335
          widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
 
1336
          widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
 
1337
          widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
 
1338
          ++widths.nExcepsV;
 
1339
        } else {
 
1340
          error(-1, "Bad widths (W2) array in Type 0 font");
 
1341
        }
 
1342
        obj6.free();
 
1343
        obj5.free();
 
1344
        obj4.free();
 
1345
        i += 5;
 
1346
      } else if (obj2.isInt() && obj3.isArray()) {
 
1347
        if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
 
1348
          excepsSize =
 
1349
            (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
 
1350
          widths.excepsV = (GfxFontCIDWidthExcepV *)
 
1351
            greallocn(widths.excepsV,
 
1352
                      excepsSize, sizeof(GfxFontCIDWidthExcepV));
 
1353
        }
 
1354
        j = obj2.getInt();
 
1355
        for (k = 0; k < obj3.arrayGetLength(); k += 3) {
 
1356
          if (obj3.arrayGet(k, &obj4)->isNum() &&
 
1357
              obj3.arrayGet(k+1, &obj5)->isNum() &&
 
1358
              obj3.arrayGet(k+2, &obj6)->isNum()) {
 
1359
            widths.excepsV[widths.nExceps].first = j;
 
1360
            widths.excepsV[widths.nExceps].last = j;
 
1361
            widths.excepsV[widths.nExceps].height = obj4.getNum() * 0.001;
 
1362
            widths.excepsV[widths.nExceps].vx = obj5.getNum() * 0.001;
 
1363
            widths.excepsV[widths.nExceps].vy = obj6.getNum() * 0.001;
 
1364
            ++j;
 
1365
            ++widths.nExcepsV;
 
1366
          } else {
 
1367
            error(-1, "Bad widths (W2) array in Type 0 font");
 
1368
          }
 
1369
          obj6.free();
 
1370
          obj5.free();
 
1371
          obj4.free();
 
1372
        }
 
1373
        i += 2;
 
1374
      } else {
 
1375
        error(-1, "Bad widths (W2) array in Type 0 font");
 
1376
        ++i;
 
1377
      }
 
1378
      obj3.free();
 
1379
      obj2.free();
 
1380
    }
 
1381
    qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
 
1382
          &cmpWidthExcepV);
 
1383
  }
 
1384
  obj1.free();
 
1385
 
 
1386
  desFontDictObj.free();
 
1387
  ok = gTrue;
 
1388
  return;
 
1389
 
 
1390
 err4:
 
1391
  obj3.free();
 
1392
  obj2.free();
 
1393
 err3:
 
1394
  obj1.free();
 
1395
 err2:
 
1396
  desFontDictObj.free();
 
1397
 err1:;
 
1398
}
 
1399
 
 
1400
GfxCIDFont::~GfxCIDFont() {
 
1401
  if (cMap) {
 
1402
    cMap->decRefCnt();
 
1403
  }
 
1404
  if (ctu) {
 
1405
    ctu->decRefCnt();
 
1406
  }
 
1407
  gfree(widths.exceps);
 
1408
  gfree(widths.excepsV);
 
1409
  if (cidToGID) {
 
1410
    gfree(cidToGID);
 
1411
  }
 
1412
}
 
1413
 
 
1414
int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
 
1415
                            Unicode *u, int uSize, int *uLen,
 
1416
                            double *dx, double *dy, double *ox, double *oy) {
 
1417
  CID cid;
 
1418
  double w, h, vx, vy;
 
1419
  int n, a, b, m;
 
1420
 
 
1421
  if (!cMap) {
 
1422
    *code = 0;
 
1423
    *uLen = 0;
 
1424
    *dx = *dy = 0;
 
1425
    return 1;
 
1426
  }
 
1427
 
 
1428
  *code = (CharCode)(cid = cMap->getCID(s, len, &n));
 
1429
  if (ctu) {
 
1430
    *uLen = ctu->mapToUnicode(cid, u, uSize);
 
1431
  } else {
 
1432
    *uLen = 0;
 
1433
  }
 
1434
 
 
1435
  // horizontal
 
1436
  if (cMap->getWMode() == 0) {
 
1437
    w = widths.defWidth;
 
1438
    h = vx = vy = 0;
 
1439
    if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
 
1440
      a = 0;
 
1441
      b = widths.nExceps;
 
1442
      // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
 
1443
      while (b - a > 1) {
 
1444
        m = (a + b) / 2;
 
1445
        if (widths.exceps[m].first <= cid) {
 
1446
          a = m;
 
1447
        } else {
 
1448
          b = m;
 
1449
        }
 
1450
      }
 
1451
      if (cid <= widths.exceps[a].last) {
 
1452
        w = widths.exceps[a].width;
 
1453
      }
 
1454
    }
 
1455
 
 
1456
  // vertical
 
1457
  } else {
 
1458
    w = 0;
 
1459
    h = widths.defHeight;
 
1460
    vx = widths.defWidth / 2;
 
1461
    vy = widths.defVY;
 
1462
    if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
 
1463
      a = 0;
 
1464
      b = widths.nExcepsV;
 
1465
      // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
 
1466
      while (b - a > 1) {
 
1467
        m = (a + b) / 2;
 
1468
        if (widths.excepsV[m].last <= cid) {
 
1469
          a = m;
 
1470
        } else {
 
1471
          b = m;
 
1472
        }
 
1473
      }
 
1474
      if (cid <= widths.excepsV[a].last) {
 
1475
        h = widths.excepsV[a].height;
 
1476
        vx = widths.excepsV[a].vx;
 
1477
        vy = widths.excepsV[a].vy;
 
1478
      }
 
1479
    }
 
1480
  }
 
1481
 
 
1482
  *dx = w;
 
1483
  *dy = h;
 
1484
  *ox = vx;
 
1485
  *oy = vy;
 
1486
 
 
1487
  return n;
 
1488
}
 
1489
 
 
1490
int GfxCIDFont::getWMode() {
 
1491
  return cMap ? cMap->getWMode() : 0;
 
1492
}
 
1493
 
 
1494
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
 
1495
  if (ctu) {
 
1496
    ctu->incRefCnt();
 
1497
  }
 
1498
  return ctu;
 
1499
}
 
1500
 
 
1501
GString *GfxCIDFont::getCollection() {
 
1502
  return cMap ? cMap->getCollection() : (GString *)NULL;
 
1503
}
 
1504
 
 
1505
//------------------------------------------------------------------------
 
1506
// GfxFontDict
 
1507
//------------------------------------------------------------------------
 
1508
 
 
1509
GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
 
1510
  int i;
 
1511
  Object obj1, obj2;
 
1512
  Ref r;
 
1513
 
 
1514
  numFonts = fontDict->getLength();
 
1515
  fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *));
 
1516
  for (i = 0; i < numFonts; ++i) {
 
1517
    fontDict->getValNF(i, &obj1);
 
1518
    obj1.fetch(xref, &obj2);
 
1519
    if (obj2.isDict()) {
 
1520
      if (obj1.isRef()) {
 
1521
        r = obj1.getRef();
 
1522
      } else {
 
1523
        // no indirect reference for this font, so invent a unique one
 
1524
        // (legal generation numbers are five digits, so any 6-digit
 
1525
        // number would be safe)
 
1526
        r.num = i;
 
1527
        if (fontDictRef) {
 
1528
          r.gen = 100000 + fontDictRef->num;
 
1529
        } else {
 
1530
          r.gen = 999999;
 
1531
        }
 
1532
      }
 
1533
      fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
 
1534
                                   r, obj2.getDict());
 
1535
      if (fonts[i] && !fonts[i]->isOk()) {
 
1536
        delete fonts[i];
 
1537
        fonts[i] = NULL;
 
1538
      }
 
1539
    } else {
 
1540
      error(-1, "font resource is not a dictionary");
 
1541
      fonts[i] = NULL;
 
1542
    }
 
1543
    obj1.free();
 
1544
    obj2.free();
 
1545
  }
 
1546
}
 
1547
 
 
1548
GfxFontDict::~GfxFontDict() {
 
1549
  int i;
 
1550
 
 
1551
  for (i = 0; i < numFonts; ++i) {
 
1552
    if (fonts[i]) {
 
1553
      delete fonts[i];
 
1554
    }
 
1555
  }
 
1556
  gfree(fonts);
 
1557
}
 
1558
 
 
1559
GfxFont *GfxFontDict::lookup(char *tag) {
 
1560
  int i;
 
1561
 
 
1562
  for (i = 0; i < numFonts; ++i) {
 
1563
    if (fonts[i] && fonts[i]->matches(tag)) {
 
1564
      return fonts[i];
 
1565
    }
 
1566
  }
 
1567
  return NULL;
 
1568
}