~ubuntu-branches/ubuntu/raring/luatex/raring

« back to all changes in this revision

Viewing changes to source/libs/poppler/poppler-0.12.4/poppler/GfxFont.cc

  • Committer: Package Import Robot
  • Author(s): Norbert Preining
  • Date: 2011-05-20 09:40:39 UTC
  • mfrom: (0.8.1) (1.8.1) (19.2.3 oneiric)
  • Revision ID: package-import@ubuntu.com-20110520094039-7sezr4kqonjqxqz6
Tags: 0.70.1-1
* new upstream release (probably) matching TeX Live 2011
* deactivate fix-luatex-build-with-old-libpng patch, included upstream

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
//========================================================================
 
10
//
 
11
// Modified under the Poppler project - http://poppler.freedesktop.org
 
12
//
 
13
// Copyright (C) 2005, 2006, 2008, 2009 Albert Astals Cid <aacid@kde.org>
 
14
// Copyright (C) 2005, 2006 Kristian Høgsberg <krh@redhat.com>
 
15
// Copyright (C) 2006 Takashi Iwai <tiwai@suse.de>
 
16
// Copyright (C) 2007 Julien Rebetez <julienr@svn.gnome.org>
 
17
// Copyright (C) 2007 Jeff Muizelaar <jeff@infidigm.net>
 
18
// Copyright (C) 2007 Koji Otani <sho@bbr.jp>
 
19
// Copyright (C) 2007 Ed Catmur <ed@catmur.co.uk>
 
20
// Copyright (C) 2008 Jonathan Kew <jonathan_kew@sil.org>
 
21
// Copyright (C) 2008 Ed Avis <eda@waniasset.com>
 
22
// Copyright (C) 2008 Hib Eris <hib@hiberis.nl>
 
23
// Copyright (C) 2009 Peter Kerzum <kerzum@yandex-team.ru>
 
24
// Copyright (C) 2009 David Benjamin <davidben@mit.edu>
 
25
//
 
26
// To see a description of the changes please see the Changelog file that
 
27
// came with your tarball or type make ChangeLog if you are building from git
 
28
//
 
29
//========================================================================
 
30
 
 
31
#include <config.h>
 
32
 
 
33
#ifdef USE_GCC_PRAGMAS
 
34
#pragma implementation
 
35
#endif
 
36
 
 
37
#include <stdio.h>
 
38
#include <stdlib.h>
 
39
#include <string.h>
 
40
#include <ctype.h>
 
41
#include "goo/gmem.h"
 
42
#include "Error.h"
 
43
#include "Object.h"
 
44
#include "Dict.h"
 
45
#include "GlobalParams.h"
 
46
#include "CMap.h"
 
47
#include "CharCodeToUnicode.h"
 
48
#include "FontEncodingTables.h"
 
49
#include "BuiltinFontTables.h"
 
50
#include <fofi/FoFiType1.h>
 
51
#include <fofi/FoFiType1C.h>
 
52
#include <fofi/FoFiTrueType.h>
 
53
#include "GfxFont.h"
 
54
 
 
55
//------------------------------------------------------------------------
 
56
 
 
57
struct StdFontMapEntry {
 
58
  char *altName;
 
59
  char *properName;
 
60
};
 
61
 
 
62
// Acrobat 4.0 and earlier substituted Base14-compatible fonts without
 
63
// providing Widths and a FontDescriptor, so we munge the names into
 
64
// the proper Base14 names.  This table is from implementation note 44
 
65
// in the PDF 1.4 spec, with some additions based on empirical
 
66
// evidence.
 
67
static const StdFontMapEntry stdFontMap[] = {
 
68
  { "Arial",                        "Helvetica" },
 
69
  { "Arial,Bold",                   "Helvetica-Bold" },
 
70
  { "Arial,BoldItalic",             "Helvetica-BoldOblique" },
 
71
  { "Arial,Italic",                 "Helvetica-Oblique" },
 
72
  { "Arial-Bold",                   "Helvetica-Bold" },
 
73
  { "Arial-BoldItalic",             "Helvetica-BoldOblique" },
 
74
  { "Arial-BoldItalicMT",           "Helvetica-BoldOblique" },
 
75
  { "Arial-BoldMT",                 "Helvetica-Bold" },
 
76
  { "Arial-Italic",                 "Helvetica-Oblique" },
 
77
  { "Arial-ItalicMT",               "Helvetica-Oblique" },
 
78
  { "ArialMT",                      "Helvetica" },
 
79
  { "Courier,Bold",                 "Courier-Bold" },
 
80
  { "Courier,BoldItalic",           "Courier-BoldOblique" },
 
81
  { "Courier,Italic",               "Courier-Oblique" },
 
82
  { "CourierNew",                   "Courier" },
 
83
  { "CourierNew,Bold",              "Courier-Bold" },
 
84
  { "CourierNew,BoldItalic",        "Courier-BoldOblique" },
 
85
  { "CourierNew,Italic",            "Courier-Oblique" },
 
86
  { "CourierNew-Bold",              "Courier-Bold" },
 
87
  { "CourierNew-BoldItalic",        "Courier-BoldOblique" },
 
88
  { "CourierNew-Italic",            "Courier-Oblique" },
 
89
  { "CourierNewPS-BoldItalicMT",    "Courier-BoldOblique" },
 
90
  { "CourierNewPS-BoldMT",          "Courier-Bold" },
 
91
  { "CourierNewPS-ItalicMT",        "Courier-Oblique" },
 
92
  { "CourierNewPSMT",               "Courier" },
 
93
  { "Helvetica,Bold",               "Helvetica-Bold" },
 
94
  { "Helvetica,BoldItalic",         "Helvetica-BoldOblique" },
 
95
  { "Helvetica,Italic",             "Helvetica-Oblique" },
 
96
  { "Helvetica-BoldItalic",         "Helvetica-BoldOblique" },
 
97
  { "Helvetica-Italic",             "Helvetica-Oblique" },
 
98
  { "Symbol,Bold",                  "Symbol" },
 
99
  { "Symbol,BoldItalic",            "Symbol" },
 
100
  { "Symbol,Italic",                "Symbol" },
 
101
  { "TimesNewRoman",                "Times-Roman" },
 
102
  { "TimesNewRoman,Bold",           "Times-Bold" },
 
103
  { "TimesNewRoman,BoldItalic",     "Times-BoldItalic" },
 
104
  { "TimesNewRoman,Italic",         "Times-Italic" },
 
105
  { "TimesNewRoman-Bold",           "Times-Bold" },
 
106
  { "TimesNewRoman-BoldItalic",     "Times-BoldItalic" },
 
107
  { "TimesNewRoman-Italic",         "Times-Italic" },
 
108
  { "TimesNewRomanPS",              "Times-Roman" },
 
109
  { "TimesNewRomanPS-Bold",         "Times-Bold" },
 
110
  { "TimesNewRomanPS-BoldItalic",   "Times-BoldItalic" },
 
111
  { "TimesNewRomanPS-BoldItalicMT", "Times-BoldItalic" },
 
112
  { "TimesNewRomanPS-BoldMT",       "Times-Bold" },
 
113
  { "TimesNewRomanPS-Italic",       "Times-Italic" },
 
114
  { "TimesNewRomanPS-ItalicMT",     "Times-Italic" },
 
115
  { "TimesNewRomanPSMT",            "Times-Roman" },
 
116
  { "TimesNewRomanPSMT,Bold",       "Times-Bold" },
 
117
  { "TimesNewRomanPSMT,BoldItalic", "Times-BoldItalic" },
 
118
  { "TimesNewRomanPSMT,Italic",     "Times-Italic" }
 
119
};
 
120
 
 
121
static int parseCharName(char *charName, Unicode *uBuf, int uLen,
 
122
                         GBool names, GBool ligatures, 
 
123
                         GBool numeric, GBool hex, GBool variants);
 
124
 
 
125
//------------------------------------------------------------------------
 
126
// GfxFont
 
127
//------------------------------------------------------------------------
 
128
 
 
129
GfxFont *GfxFont::makeFont(XRef *xref, char *tagA, Ref idA, Dict *fontDict) {
 
130
  GooString *nameA;
 
131
  GfxFont *font;
 
132
  Object obj1;
 
133
 
 
134
  // get base font name
 
135
  nameA = NULL;
 
136
  fontDict->lookup("BaseFont", &obj1);
 
137
  if (obj1.isName()) {
 
138
    nameA = new GooString(obj1.getName());
 
139
  }
 
140
  obj1.free();
 
141
 
 
142
  // get font type
 
143
  font = NULL;
 
144
  fontDict->lookup("Subtype", &obj1);
 
145
  if (obj1.isName("Type1") || obj1.isName("MMType1")) {
 
146
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1, fontDict);
 
147
  } else if (obj1.isName("Type1C")) {
 
148
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType1C, fontDict);
 
149
  } else if (obj1.isName("Type3")) {
 
150
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontType3, fontDict);
 
151
  } else if (obj1.isName("TrueType")) {
 
152
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontTrueType, fontDict);
 
153
  } else if (obj1.isName("Type0")) {
 
154
    font = new GfxCIDFont(xref, tagA, idA, nameA, fontDict);
 
155
  } else {
 
156
    error(-1, "Unknown font type: '%s'",
 
157
          obj1.isName() ? obj1.getName() : "???");
 
158
    font = new Gfx8BitFont(xref, tagA, idA, nameA, fontUnknownType, fontDict);
 
159
  }
 
160
  obj1.free();
 
161
 
 
162
  return font;
 
163
}
 
164
 
 
165
GfxFont::GfxFont(char *tagA, Ref idA, GooString *nameA) {
 
166
  ok = gFalse;
 
167
  tag = new GooString(tagA);
 
168
  id = idA;
 
169
  name = nameA;
 
170
  origName = nameA;
 
171
  embFontName = NULL;
 
172
  extFontFile = NULL;
 
173
  family = NULL;
 
174
  stretch = StretchNotDefined;
 
175
  weight = WeightNotDefined;
 
176
  refCnt = 1;
 
177
  dfp = NULL;
 
178
}
 
179
 
 
180
GfxFont::~GfxFont() {
 
181
  delete tag;
 
182
  delete family;
 
183
  if (origName && origName != name) {
 
184
    delete origName;
 
185
  }
 
186
  if (name) {
 
187
    delete name;
 
188
  }
 
189
  if (embFontName) {
 
190
    delete embFontName;
 
191
  }
 
192
  if (extFontFile) {
 
193
    delete extFontFile;
 
194
  }
 
195
  delete dfp;
 
196
}
 
197
 
 
198
void GfxFont::incRefCnt() {
 
199
  refCnt++;
 
200
}
 
201
 
 
202
void GfxFont::decRefCnt() {
 
203
  if (--refCnt == 0)
 
204
    delete this;
 
205
}
 
206
 
 
207
void GfxFont::readFontDescriptor(XRef *xref, Dict *fontDict) {
 
208
  Object obj1, obj2, obj3, obj4;
 
209
  double t;
 
210
  int i;
 
211
 
 
212
  // assume Times-Roman by default (for substitution purposes)
 
213
  flags = fontSerif;
 
214
 
 
215
  embFontID.num = -1;
 
216
  embFontID.gen = -1;
 
217
  missingWidth = 0;
 
218
 
 
219
  if (fontDict->lookup("FontDescriptor", &obj1)->isDict()) {
 
220
 
 
221
    // get flags
 
222
    if (obj1.dictLookup("Flags", &obj2)->isInt()) {
 
223
      flags = obj2.getInt();
 
224
    }
 
225
    obj2.free();
 
226
 
 
227
    // get name
 
228
    obj1.dictLookup("FontName", &obj2);
 
229
    if (obj2.isName()) {
 
230
      embFontName = new GooString(obj2.getName());
 
231
    }
 
232
    obj2.free();
 
233
    if (embFontName == NULL) {
 
234
      // get name with typo
 
235
      obj1.dictLookup("Fontname", &obj2);
 
236
      if (obj2.isName()) {
 
237
        embFontName = new GooString(obj2.getName());
 
238
        error(-1, "The file uses Fontname instead of FontName please notify the creator that the file is broken");
 
239
      }
 
240
      obj2.free();
 
241
    }
 
242
 
 
243
    // get family
 
244
    obj1.dictLookup("FontFamily", &obj2);
 
245
    if (obj2.isString()) family = new GooString(obj2.getString());
 
246
    obj2.free();
 
247
 
 
248
    // get stretch
 
249
    obj1.dictLookup("FontStretch", &obj2);
 
250
    if (obj2.isName()) {
 
251
      if (strcmp(obj2.getName(), "UltraCondensed") == 0) stretch = UltraCondensed;
 
252
      else if (strcmp(obj2.getName(), "ExtraCondensed") == 0) stretch = ExtraCondensed;
 
253
      else if (strcmp(obj2.getName(), "Condensed") == 0) stretch = Condensed;
 
254
      else if (strcmp(obj2.getName(), "SemiCondensed") == 0) stretch = SemiCondensed;
 
255
      else if (strcmp(obj2.getName(), "Normal") == 0) stretch = Normal;
 
256
      else if (strcmp(obj2.getName(), "SemiExpanded") == 0) stretch = SemiExpanded;
 
257
      else if (strcmp(obj2.getName(), "Expanded") == 0) stretch = Expanded;
 
258
      else if (strcmp(obj2.getName(), "ExtraExpanded") == 0) stretch = ExtraExpanded;
 
259
      else if (strcmp(obj2.getName(), "UltraExpanded") == 0) stretch = UltraExpanded;
 
260
      else error(-1, "Invalid Font Stretch");
 
261
    }
 
262
    obj2.free();
 
263
    
 
264
    // get weight
 
265
    obj1.dictLookup("FontWeight", &obj2);
 
266
    if (obj2.isNum()) {
 
267
      if (obj2.getNum() == 100) weight = W100;
 
268
      else if (obj2.getNum() == 200) weight = W200;
 
269
      else if (obj2.getNum() == 300) weight = W300;
 
270
      else if (obj2.getNum() == 400) weight = W400;
 
271
      else if (obj2.getNum() == 500) weight = W500;
 
272
      else if (obj2.getNum() == 600) weight = W600;
 
273
      else if (obj2.getNum() == 700) weight = W700;
 
274
      else if (obj2.getNum() == 800) weight = W800;
 
275
      else if (obj2.getNum() == 900) weight = W900;
 
276
      else error(-1, "Invalid Font Weight");
 
277
    }
 
278
    obj2.free();
 
279
 
 
280
    // look for embedded font file
 
281
    if (obj1.dictLookupNF("FontFile", &obj2)->isRef()) {
 
282
      embFontID = obj2.getRef();
 
283
      if (type != fontType1) {
 
284
        error(-1, "Mismatch between font type and embedded font file");
 
285
        if (isCIDFont()) {
 
286
          error(-1, "CID font has FontFile attribute; assuming CIDType0");
 
287
          type = fontCIDType0;
 
288
        } else {
 
289
          type = fontType1;
 
290
        }
 
291
      }
 
292
    }
 
293
    obj2.free();
 
294
    if (embFontID.num == -1 &&
 
295
        obj1.dictLookupNF("FontFile2", &obj2)->isRef()) {
 
296
      embFontID = obj2.getRef();
 
297
      if (type != fontTrueType && type != fontCIDType2) {
 
298
        error(-1, "Mismatch between font type and embedded font file");
 
299
        type = isCIDFont() ? fontCIDType2 : fontTrueType;
 
300
      }
 
301
    }
 
302
    obj2.free();
 
303
    if (embFontID.num == -1 &&
 
304
        obj1.dictLookupNF("FontFile3", &obj2)->isRef()) {
 
305
      if (obj2.fetch(xref, &obj3)->isStream()) {
 
306
        obj3.streamGetDict()->lookup("Subtype", &obj4);
 
307
        if (obj4.isName("Type1")) {
 
308
          embFontID = obj2.getRef();
 
309
          if (type != fontType1) {
 
310
            error(-1, "Mismatch between font type and embedded font file");
 
311
            if (isCIDFont()) {
 
312
              error(-1, "Embedded CID font has type Type1; assuming CIDType0");
 
313
              type = fontCIDType0;
 
314
            } else {
 
315
              type = fontType1;
 
316
            }
 
317
          }
 
318
        } else if (obj4.isName("Type1C")) {
 
319
          embFontID = obj2.getRef();
 
320
          if (type != fontType1 && type != fontType1C) {
 
321
            error(-1, "Mismatch between font type and embedded font file");
 
322
          }
 
323
          if (isCIDFont()) {
 
324
            error(-1, "Embedded CID font has type Type1C; assuming CIDType0C");
 
325
            type = fontCIDType0C;
 
326
          } else {
 
327
            type = fontType1C;
 
328
          }
 
329
        } else if (obj4.isName("TrueType")) {
 
330
          embFontID = obj2.getRef();
 
331
          if (type != fontTrueType) {
 
332
            error(-1, "Mismatch between font type and embedded font file");
 
333
            if (isCIDFont()) {
 
334
              error(-1, "Embedded CID font has type TrueType; assuming CIDType2");
 
335
              type = fontCIDType2;
 
336
            } else {
 
337
              type = fontTrueType;
 
338
            }
 
339
          }
 
340
        } else if (obj4.isName("CIDFontType0C")) {
 
341
          embFontID = obj2.getRef();
 
342
          if (type != fontCIDType0) {
 
343
            error(-1, "Mismatch between font type and embedded font file");
 
344
          }
 
345
          if (isCIDFont()) {
 
346
            type = fontCIDType0C;
 
347
          } else {
 
348
            error(-1, "Embedded non-CID font has type CIDFontType0c; assuming Type1C");
 
349
            type = fontType1C;
 
350
          }
 
351
        } else if (obj4.isName("OpenType")) {
 
352
          embFontID = obj2.getRef();
 
353
          if (type == fontTrueType) {
 
354
            type = fontTrueTypeOT;
 
355
          } else if (type == fontType1) {
 
356
            type = fontType1COT;
 
357
          } else if (type == fontCIDType0) {
 
358
            type = fontCIDType0COT;
 
359
          } else if (type == fontCIDType2) {
 
360
            type = fontCIDType2OT;
 
361
          } else {
 
362
            error(-1, "Mismatch between font type and embedded font file");
 
363
          }
 
364
        } else {
 
365
          error(-1, "Unknown embedded font type '%s'",
 
366
                obj4.isName() ? obj4.getName() : "???");
 
367
        }
 
368
        obj4.free();
 
369
      }
 
370
      obj3.free();
 
371
    }
 
372
    obj2.free();
 
373
 
 
374
    // look for MissingWidth
 
375
    obj1.dictLookup("MissingWidth", &obj2);
 
376
    if (obj2.isNum()) {
 
377
      missingWidth = obj2.getNum();
 
378
    }
 
379
    obj2.free();
 
380
 
 
381
    // get Ascent and Descent
 
382
    obj1.dictLookup("Ascent", &obj2);
 
383
    if (obj2.isNum()) {
 
384
      t = 0.001 * obj2.getNum();
 
385
      // some broken font descriptors set ascent and descent to 0
 
386
      if (t != 0) {
 
387
        ascent = t;
 
388
      }
 
389
    }
 
390
    obj2.free();
 
391
    obj1.dictLookup("Descent", &obj2);
 
392
    if (obj2.isNum()) {
 
393
      t = 0.001 * obj2.getNum();
 
394
      // some broken font descriptors set ascent and descent to 0
 
395
      if (t != 0) {
 
396
        descent = t;
 
397
      }
 
398
      // some broken font descriptors specify a positive descent
 
399
      if (descent > 0) {
 
400
        descent = -descent;
 
401
      }
 
402
    }
 
403
    obj2.free();
 
404
 
 
405
    // font FontBBox
 
406
    if (obj1.dictLookup("FontBBox", &obj2)->isArray()) {
 
407
      for (i = 0; i < 4 && i < obj2.arrayGetLength(); ++i) {
 
408
        if (obj2.arrayGet(i, &obj3)->isNum()) {
 
409
          fontBBox[i] = 0.001 * obj3.getNum();
 
410
        }
 
411
        obj3.free();
 
412
      }
 
413
    }
 
414
    obj2.free();
 
415
 
 
416
  }
 
417
  obj1.free();
 
418
}
 
419
 
 
420
CharCodeToUnicode *GfxFont::readToUnicodeCMap(Dict *fontDict, int nBits,
 
421
                                              CharCodeToUnicode *ctu) {
 
422
  GooString *buf;
 
423
  Object obj1;
 
424
  int c;
 
425
 
 
426
  if (!fontDict->lookup("ToUnicode", &obj1)->isStream()) {
 
427
    obj1.free();
 
428
    return NULL;
 
429
  }
 
430
  buf = new GooString();
 
431
  obj1.streamReset();
 
432
  while ((c = obj1.streamGetChar()) != EOF) {
 
433
    buf->append(c);
 
434
  }
 
435
  obj1.streamClose();
 
436
  obj1.free();
 
437
  if (ctu) {
 
438
    ctu->mergeCMap(buf, nBits);
 
439
  } else {
 
440
    ctu = CharCodeToUnicode::parseCMap(buf, nBits);
 
441
  }
 
442
  delete buf;
 
443
  return ctu;
 
444
}
 
445
 
 
446
void GfxFont::findExtFontFile() {
 
447
  static char *type1Exts[] = { ".pfa", ".pfb", ".ps", "", NULL };
 
448
  static char *ttExts[] = { ".ttf", ".ttc", NULL };
 
449
 
 
450
  if (name) {
 
451
    if (type == fontType1) {
 
452
      extFontFile = globalParams->findFontFile(name, type1Exts);
 
453
    } else if (type == fontTrueType) {
 
454
      extFontFile = globalParams->findFontFile(name, ttExts);
 
455
    }
 
456
  }
 
457
}
 
458
 
 
459
char *GfxFont::readExtFontFile(int *len) {
 
460
  FILE *f;
 
461
  char *buf;
 
462
 
 
463
  if (!(f = fopen(extFontFile->getCString(), "rb"))) {
 
464
    error(-1, "External font file '%s' vanished", extFontFile->getCString());
 
465
    return NULL;
 
466
  }
 
467
  if (fseek(f, 0, SEEK_END) != 0) {
 
468
    error(-1, "Cannot seek to end of '%s'", extFontFile->getCString());
 
469
    fclose(f);
 
470
    return NULL;
 
471
  }
 
472
  *len = (int)ftell(f);
 
473
  if (fseek(f, 0, SEEK_SET) != 0) {
 
474
    error(-1, "Cannot seek to start of '%s'", extFontFile->getCString());
 
475
    fclose(f);
 
476
    return NULL;
 
477
  }
 
478
  buf = (char *)gmalloc(*len);
 
479
  if ((int)fread(buf, 1, *len, f) != *len) {
 
480
    error(-1, "Error reading external font file '%s'",
 
481
          extFontFile->getCString());
 
482
  }
 
483
  fclose(f);
 
484
  return buf;
 
485
}
 
486
 
 
487
char *GfxFont::readEmbFontFile(XRef *xref, int *len) {
 
488
  char *buf;
 
489
  Object obj1, obj2;
 
490
  Stream *str;
 
491
  int c;
 
492
  int size, i;
 
493
 
 
494
  obj1.initRef(embFontID.num, embFontID.gen);
 
495
  obj1.fetch(xref, &obj2);
 
496
  if (!obj2.isStream()) {
 
497
    error(-1, "Embedded font file is not a stream");
 
498
    obj2.free();
 
499
    obj1.free();
 
500
    embFontID.num = -1;
 
501
    *len = 0;
 
502
    return NULL;
 
503
  }
 
504
  str = obj2.getStream();
 
505
 
 
506
  buf = NULL;
 
507
  i = size = 0;
 
508
  str->reset();
 
509
  while ((c = str->getChar()) != EOF) {
 
510
    if (i == size) {
 
511
      size += 4096;
 
512
      buf = (char *)grealloc(buf, size);
 
513
    }
 
514
    buf[i++] = c;
 
515
  }
 
516
  *len = i;
 
517
  str->close();
 
518
 
 
519
  obj2.free();
 
520
  obj1.free();
 
521
 
 
522
  return buf;
 
523
}
 
524
 
 
525
//------------------------------------------------------------------------
 
526
// Gfx8BitFont
 
527
//------------------------------------------------------------------------
 
528
 
 
529
Gfx8BitFont::Gfx8BitFont(XRef *xref, char *tagA, Ref idA, GooString *nameA,
 
530
                         GfxFontType typeA, Dict *fontDict):
 
531
  GfxFont(tagA, idA, nameA)
 
532
{
 
533
  GooString *name2;
 
534
  BuiltinFont *builtinFont;
 
535
  char **baseEnc;
 
536
  GBool baseEncFromFontFile;
 
537
  char *buf;
 
538
  int len;
 
539
  FoFiType1 *ffT1;
 
540
  FoFiType1C *ffT1C;
 
541
  int code;
 
542
  char *charName;
 
543
  GBool missing, hex;
 
544
  Unicode toUnicode[256];
 
545
  CharCodeToUnicode *utu, *ctu2;
 
546
  Unicode uBuf[8];
 
547
  double mul;
 
548
  int firstChar, lastChar;
 
549
  Gushort w;
 
550
  Object obj1, obj2, obj3;
 
551
  int n, i, a, b, m;
 
552
 
 
553
  refCnt = 1;
 
554
  type = typeA;
 
555
  ctu = NULL;
 
556
 
 
557
  // do font name substitution for various aliases of the Base 14 font
 
558
  // names
 
559
  if (name) {
 
560
    name2 = name->copy();
 
561
    i = 0;
 
562
    while (i < name2->getLength()) {
 
563
      if (name2->getChar(i) == ' ') {
 
564
        name2->del(i);
 
565
      } else {
 
566
        ++i;
 
567
      }
 
568
    }
 
569
    a = 0;
 
570
    b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
 
571
    // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName
 
572
    while (b - a > 1) {
 
573
      m = (a + b) / 2;
 
574
      if (name2->cmp(stdFontMap[m].altName) >= 0) {
 
575
        a = m;
 
576
      } else {
 
577
        b = m;
 
578
      }
 
579
    }
 
580
    if (!name2->cmp(stdFontMap[a].altName)) {
 
581
      name = new GooString(stdFontMap[a].properName);
 
582
    }
 
583
    delete name2;
 
584
  }
 
585
 
 
586
  // is it a built-in font?
 
587
  builtinFont = NULL;
 
588
  if (name) {
 
589
    for (i = 0; i < nBuiltinFonts; ++i) {
 
590
      if (!name->cmp(builtinFonts[i].name)) {
 
591
        builtinFont = &builtinFonts[i];
 
592
        break;
 
593
      }
 
594
    }
 
595
  }
 
596
 
 
597
  // default ascent/descent values
 
598
  if (builtinFont) {
 
599
    ascent = 0.001 * builtinFont->ascent;
 
600
    descent = 0.001 * builtinFont->descent;
 
601
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
 
602
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
 
603
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
 
604
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
 
605
  } else {
 
606
    ascent = 0.95;
 
607
    descent = -0.35;
 
608
    fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
 
609
  }
 
610
 
 
611
  // get info from font descriptor
 
612
  readFontDescriptor(xref, fontDict);
 
613
 
 
614
  // for non-embedded fonts, don't trust the ascent/descent/bbox
 
615
  // values from the font descriptor
 
616
  if (builtinFont && embFontID.num < 0) {
 
617
    ascent = 0.001 * builtinFont->ascent;
 
618
    descent = 0.001 * builtinFont->descent;
 
619
    fontBBox[0] = 0.001 * builtinFont->bbox[0];
 
620
    fontBBox[1] = 0.001 * builtinFont->bbox[1];
 
621
    fontBBox[2] = 0.001 * builtinFont->bbox[2];
 
622
    fontBBox[3] = 0.001 * builtinFont->bbox[3];
 
623
  }
 
624
 
 
625
  // look for an external font file
 
626
  findExtFontFile();
 
627
 
 
628
  // get font matrix
 
629
  fontMat[0] = fontMat[3] = 1;
 
630
  fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
 
631
  if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
 
632
    for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
 
633
      if (obj1.arrayGet(i, &obj2)->isNum()) {
 
634
        fontMat[i] = obj2.getNum();
 
635
      }
 
636
      obj2.free();
 
637
    }
 
638
  }
 
639
  obj1.free();
 
640
 
 
641
  // get Type 3 bounding box, font definition, and resources
 
642
  if (type == fontType3) {
 
643
    if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
 
644
      for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
 
645
        if (obj1.arrayGet(i, &obj2)->isNum()) {
 
646
          fontBBox[i] = obj2.getNum();
 
647
        }
 
648
        obj2.free();
 
649
      }
 
650
    }
 
651
    obj1.free();
 
652
    if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
 
653
      error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
 
654
      charProcs.free();
 
655
    }
 
656
    if (!fontDict->lookup("Resources", &resources)->isDict()) {
 
657
      resources.free();
 
658
    }
 
659
  }
 
660
 
 
661
  //----- build the font encoding -----
 
662
 
 
663
  // Encodings start with a base encoding, which can come from
 
664
  // (in order of priority):
 
665
  //   1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
 
666
  //        - MacRoman / MacExpert / WinAnsi / Standard
 
667
  //   2. embedded or external font file
 
668
  //   3. default:
 
669
  //        - builtin --> builtin encoding
 
670
  //        - TrueType --> WinAnsiEncoding
 
671
  //        - others --> StandardEncoding
 
672
  // and then add a list of differences (if any) from
 
673
  // FontDict.Encoding.Differences.
 
674
 
 
675
  // check FontDict for base encoding
 
676
  hasEncoding = gFalse;
 
677
  usesMacRomanEnc = gFalse;
 
678
  baseEnc = NULL;
 
679
  baseEncFromFontFile = gFalse;
 
680
  fontDict->lookup("Encoding", &obj1);
 
681
  if (obj1.isDict()) {
 
682
    obj1.dictLookup("BaseEncoding", &obj2);
 
683
    if (obj2.isName("MacRomanEncoding")) {
 
684
      hasEncoding = gTrue;
 
685
      usesMacRomanEnc = gTrue;
 
686
      baseEnc = macRomanEncoding;
 
687
    } else if (obj2.isName("MacExpertEncoding")) {
 
688
      hasEncoding = gTrue;
 
689
      baseEnc = macExpertEncoding;
 
690
    } else if (obj2.isName("WinAnsiEncoding")) {
 
691
      hasEncoding = gTrue;
 
692
      baseEnc = winAnsiEncoding;
 
693
    }
 
694
    obj2.free();
 
695
  } else if (obj1.isName("MacRomanEncoding")) {
 
696
    hasEncoding = gTrue;
 
697
    usesMacRomanEnc = gTrue;
 
698
    baseEnc = macRomanEncoding;
 
699
  } else if (obj1.isName("MacExpertEncoding")) {
 
700
    hasEncoding = gTrue;
 
701
    baseEnc = macExpertEncoding;
 
702
  } else if (obj1.isName("WinAnsiEncoding")) {
 
703
    hasEncoding = gTrue;
 
704
    baseEnc = winAnsiEncoding;
 
705
  }
 
706
 
 
707
  // check embedded or external font file for base encoding
 
708
  // (only for Type 1 fonts - trying to get an encoding out of a
 
709
  // TrueType font is a losing proposition)
 
710
  ffT1 = NULL;
 
711
  ffT1C = NULL;
 
712
  buf = NULL;
 
713
  if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
 
714
    if (extFontFile) {
 
715
      ffT1 = FoFiType1::load(extFontFile->getCString());
 
716
    } else {
 
717
      buf = readEmbFontFile(xref, &len);
 
718
      ffT1 = FoFiType1::make(buf, len);
 
719
    }
 
720
    if (ffT1) {
 
721
      if (ffT1->getName()) {
 
722
        if (embFontName) {
 
723
          delete embFontName;
 
724
        }
 
725
        embFontName = new GooString(ffT1->getName());
 
726
      }
 
727
      if (!baseEnc) {
 
728
        baseEnc = ffT1->getEncoding();
 
729
        baseEncFromFontFile = gTrue;
 
730
      }
 
731
    }
 
732
  } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
 
733
    if (extFontFile) {
 
734
      ffT1C = FoFiType1C::load(extFontFile->getCString());
 
735
    } else {
 
736
      buf = readEmbFontFile(xref, &len);
 
737
      ffT1C = FoFiType1C::make(buf, len);
 
738
    }
 
739
    if (ffT1C) {
 
740
      if (ffT1C->getName()) {
 
741
        if (embFontName) {
 
742
          delete embFontName;
 
743
        }
 
744
        embFontName = new GooString(ffT1C->getName());
 
745
      }
 
746
      if (!baseEnc) {
 
747
        baseEnc = ffT1C->getEncoding();
 
748
        baseEncFromFontFile = gTrue;
 
749
      }
 
750
    }
 
751
  }
 
752
  if (buf) {
 
753
    gfree(buf);
 
754
  }
 
755
 
 
756
  // get default base encoding
 
757
  if (!baseEnc) {
 
758
    if (builtinFont && embFontID.num < 0) {
 
759
      baseEnc = builtinFont->defaultBaseEnc;
 
760
      hasEncoding = gTrue;
 
761
    } else if (type == fontTrueType) {
 
762
      baseEnc = winAnsiEncoding;
 
763
    } else {
 
764
      baseEnc = standardEncoding;
 
765
    }
 
766
  }
 
767
 
 
768
  // copy the base encoding
 
769
  for (i = 0; i < 256; ++i) {
 
770
    enc[i] = baseEnc[i];
 
771
    if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
 
772
      enc[i] = copyString(baseEnc[i]);
 
773
    }
 
774
  }
 
775
 
 
776
  // some Type 1C font files have empty encodings, which can break the
 
777
  // T1C->T1 conversion (since the 'seac' operator depends on having
 
778
  // the accents in the encoding), so we fill in any gaps from
 
779
  // StandardEncoding
 
780
  if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
 
781
      baseEncFromFontFile) {
 
782
    for (i = 0; i < 256; ++i) {
 
783
      if (!enc[i] && standardEncoding[i]) {
 
784
        enc[i] = standardEncoding[i];
 
785
        encFree[i] = gFalse;
 
786
      }
 
787
    }
 
788
  }
 
789
 
 
790
  // merge differences into encoding
 
791
  if (obj1.isDict()) {
 
792
    obj1.dictLookup("Differences", &obj2);
 
793
    if (obj2.isArray()) {
 
794
      hasEncoding = gTrue;
 
795
      code = 0;
 
796
      for (i = 0; i < obj2.arrayGetLength(); ++i) {
 
797
        obj2.arrayGet(i, &obj3);
 
798
        if (obj3.isInt()) {
 
799
          code = obj3.getInt();
 
800
        } else if (obj3.isName()) {
 
801
          if (code >= 0 && code < 256) {
 
802
            if (encFree[code]) {
 
803
              gfree(enc[code]);
 
804
            }
 
805
            enc[code] = copyString(obj3.getName());
 
806
            encFree[code] = gTrue;
 
807
          }
 
808
          ++code;
 
809
        } else {
 
810
          error(-1, "Wrong type in font encoding resource differences (%s)",
 
811
                obj3.getTypeName());
 
812
        }
 
813
        obj3.free();
 
814
      }
 
815
    }
 
816
    obj2.free();
 
817
  }
 
818
  obj1.free();
 
819
  if (ffT1) {
 
820
    delete ffT1;
 
821
  }
 
822
  if (ffT1C) {
 
823
    delete ffT1C;
 
824
  }
 
825
 
 
826
  //----- build the mapping to Unicode -----
 
827
 
 
828
  // pass 1: use the name-to-Unicode mapping table
 
829
  missing = hex = gFalse;
 
830
  for (code = 0; code < 256; ++code) {
 
831
    if ((charName = enc[code])) {
 
832
      if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
 
833
          strcmp(charName, ".notdef")) {
 
834
        // if it wasn't in the name-to-Unicode table, check for a
 
835
        // name that looks like 'Axx' or 'xx', where 'A' is any letter
 
836
        // and 'xx' is two hex digits
 
837
        if ((strlen(charName) == 3 &&
 
838
             isalpha(charName[0]) &&
 
839
             isxdigit(charName[1]) && isxdigit(charName[2]) &&
 
840
             ((charName[1] >= 'a' && charName[1] <= 'f') ||
 
841
              (charName[1] >= 'A' && charName[1] <= 'F') ||
 
842
              (charName[2] >= 'a' && charName[2] <= 'f') ||
 
843
              (charName[2] >= 'A' && charName[2] <= 'F'))) ||
 
844
            (strlen(charName) == 2 &&
 
845
             isxdigit(charName[0]) && isxdigit(charName[1]) &&
 
846
             ((charName[0] >= 'a' && charName[0] <= 'f') ||
 
847
              (charName[0] >= 'A' && charName[0] <= 'F') ||
 
848
              (charName[1] >= 'a' && charName[1] <= 'f') ||
 
849
              (charName[1] >= 'A' && charName[1] <= 'F')))) {
 
850
          hex = gTrue;
 
851
        }
 
852
        missing = gTrue;
 
853
      }
 
854
    } else {
 
855
      toUnicode[code] = 0;
 
856
    }
 
857
  }
 
858
 
 
859
  // construct the char code -> Unicode mapping object
 
860
  ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
 
861
 
 
862
  // pass 2: try to fill in the missing chars, looking for ligatures, numeric
 
863
  // references and variants
 
864
  if (missing) {
 
865
    for (code = 0; code < 256; ++code) {
 
866
      if (!toUnicode[code]) {
 
867
        if ((charName = enc[code]) && strcmp(charName, ".notdef")
 
868
            && (n = parseCharName(charName, uBuf, sizeof(uBuf)/sizeof(*uBuf), 
 
869
                                  gFalse, // don't check simple names (pass 1)
 
870
                                  gTrue, // do check ligatures
 
871
                                  globalParams->getMapNumericCharNames(),
 
872
                                  hex,
 
873
                                  gTrue))) { // do check variants
 
874
          ctu->setMapping((CharCode)code, uBuf, n);
 
875
        } else if (globalParams->getMapUnknownCharNames()) {
 
876
          // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
 
877
          // mapping for unknown character names
 
878
          if (charName && charName[0]) {
 
879
            for (n = 0; n < (int)(sizeof(uBuf)/sizeof(*uBuf)); ++n)
 
880
              if (!(uBuf[n] = charName[n]))
 
881
                break;
 
882
            ctu->setMapping((CharCode)code, uBuf, n);
 
883
          } else {
 
884
            uBuf[0] = code;
 
885
            ctu->setMapping((CharCode)code, uBuf, 1);
 
886
          }
 
887
        }
 
888
      }
 
889
    }
 
890
  }
 
891
 
 
892
  // merge in a ToUnicode CMap, if there is one -- this overwrites
 
893
  // existing entries in ctu, i.e., the ToUnicode CMap takes
 
894
  // precedence, but the other encoding info is allowed to fill in any
 
895
  // holes
 
896
  readToUnicodeCMap(fontDict, 8, ctu);
 
897
 
 
898
  // look for a Unicode-to-Unicode mapping
 
899
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
 
900
    Unicode *uAux;
 
901
    for (i = 0; i < 256; ++i) {
 
902
      toUnicode[i] = 0;
 
903
    }
 
904
    ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
 
905
    for (i = 0; i < 256; ++i) {
 
906
      n = ctu->mapToUnicode((CharCode)i, &uAux);
 
907
      if (n >= 1) {
 
908
        n = utu->mapToUnicode((CharCode)uAux[0], &uAux);
 
909
        if (n >= 1) {
 
910
          ctu2->setMapping((CharCode)i, uAux, n);
 
911
        }
 
912
      }
 
913
    }
 
914
    utu->decRefCnt();
 
915
    delete ctu;
 
916
    ctu = ctu2;
 
917
  }
 
918
 
 
919
  //----- get the character widths -----
 
920
 
 
921
  // initialize all widths
 
922
  for (code = 0; code < 256; ++code) {
 
923
    widths[code] = missingWidth * 0.001;
 
924
  }
 
925
 
 
926
  // use widths from font dict, if present
 
927
  fontDict->lookup("FirstChar", &obj1);
 
928
  firstChar = obj1.isInt() ? obj1.getInt() : 0;
 
929
  obj1.free();
 
930
  if (firstChar < 0 || firstChar > 255) {
 
931
    firstChar = 0;
 
932
  }
 
933
  fontDict->lookup("LastChar", &obj1);
 
934
  lastChar = obj1.isInt() ? obj1.getInt() : 255;
 
935
  obj1.free();
 
936
  if (lastChar < 0 || lastChar > 255) {
 
937
    lastChar = 255;
 
938
  }
 
939
  mul = (type == fontType3) ? fontMat[0] : 0.001;
 
940
  fontDict->lookup("Widths", &obj1);
 
941
  if (obj1.isArray()) {
 
942
    flags |= fontFixedWidth;
 
943
    if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
 
944
      lastChar = firstChar + obj1.arrayGetLength() - 1;
 
945
    }
 
946
    for (code = firstChar; code <= lastChar; ++code) {
 
947
      obj1.arrayGet(code - firstChar, &obj2);
 
948
      if (obj2.isNum()) {
 
949
        widths[code] = obj2.getNum() * mul;
 
950
        if (widths[code] != widths[firstChar]) {
 
951
          flags &= ~fontFixedWidth;
 
952
        }
 
953
      }
 
954
      obj2.free();
 
955
    }
 
956
 
 
957
  // use widths from built-in font
 
958
  } else if (builtinFont) {
 
959
    // this is a kludge for broken PDF files that encode char 32
 
960
    // as .notdef
 
961
    if (builtinFont->widths->getWidth("space", &w)) {
 
962
      widths[32] = 0.001 * w;
 
963
    }
 
964
    for (code = 0; code < 256; ++code) {
 
965
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
 
966
        widths[code] = 0.001 * w;
 
967
      }
 
968
    }
 
969
 
 
970
  // couldn't find widths -- use defaults 
 
971
  } else {
 
972
    // this is technically an error -- the Widths entry is required
 
973
    // for all but the Base-14 fonts -- but certain PDF generators
 
974
    // apparently don't include widths for Arial and TimesNewRoman
 
975
    if (isFixedWidth()) {
 
976
      i = 0;
 
977
    } else if (isSerif()) {
 
978
      i = 8;
 
979
    } else {
 
980
      i = 4;
 
981
    }
 
982
    if (isBold()) {
 
983
      i += 2;
 
984
    }
 
985
    if (isItalic()) {
 
986
      i += 1;
 
987
    }
 
988
    builtinFont = builtinFontSubst[i];
 
989
    // this is a kludge for broken PDF files that encode char 32
 
990
    // as .notdef
 
991
    if (builtinFont->widths->getWidth("space", &w)) {
 
992
      widths[32] = 0.001 * w;
 
993
    }
 
994
    for (code = 0; code < 256; ++code) {
 
995
      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
 
996
        widths[code] = 0.001 * w;
 
997
      }
 
998
    }
 
999
  }
 
1000
  obj1.free();
 
1001
 
 
1002
  ok = gTrue;
 
1003
}
 
1004
 
 
1005
Gfx8BitFont::~Gfx8BitFont() {
 
1006
  int i;
 
1007
 
 
1008
  for (i = 0; i < 256; ++i) {
 
1009
    if (encFree[i] && enc[i]) {
 
1010
      gfree(enc[i]);
 
1011
    }
 
1012
  }
 
1013
  ctu->decRefCnt();
 
1014
  if (charProcs.isDict()) {
 
1015
    charProcs.free();
 
1016
  }
 
1017
  if (resources.isDict()) {
 
1018
    resources.free();
 
1019
  }
 
1020
}
 
1021
 
 
1022
// This function is in part a derived work of the Adobe Glyph Mapping
 
1023
// Convention: http://www.adobe.com/devnet/opentype/archives/glyph.html
 
1024
// Algorithmic comments are excerpted from that document to aid
 
1025
// maintainability.
 
1026
static int parseCharName(char *charName, Unicode *uBuf, int uLen,
 
1027
                         GBool names, GBool ligatures,
 
1028
                         GBool numeric, GBool hex, GBool variants)
 
1029
{
 
1030
  if (uLen <= 0) {
 
1031
    error(-1, "Zero-length output buffer (recursion overflow?) in "
 
1032
          "parseCharName, component \"%s\"", charName);
 
1033
    return 0;
 
1034
  }
 
1035
  // Step 1: drop all the characters from the glyph name starting with the
 
1036
  // first occurrence of a period (U+002E FULL STOP), if any.
 
1037
  if (variants) {
 
1038
    char *var_part = strchr(charName, '.');
 
1039
    if (var_part == charName) {
 
1040
      return 0; // .notdef or similar
 
1041
    } else if (var_part != NULL) {
 
1042
      // parse names of the form 7.oldstyle, P.swash, s.sc, etc.
 
1043
      char *main_part = gstrndup(charName, var_part - charName);
 
1044
      GBool namesRecurse = gTrue, variantsRecurse = gFalse;
 
1045
      int n = parseCharName(main_part, uBuf, uLen, namesRecurse, ligatures,
 
1046
                            numeric, hex, variantsRecurse);
 
1047
      gfree(main_part);
 
1048
      return n;
 
1049
    }
 
1050
  }
 
1051
  // Step 2: split the remaining string into a sequence of components, using
 
1052
  // underscore (U+005F LOW LINE) as the delimiter.
 
1053
  if (ligatures && strchr(charName, '_')) {
 
1054
    // parse names of the form A_a (e.g. f_i, T_h, l_quotesingle)
 
1055
    char *lig_part, *lig_end, *lig_copy;
 
1056
    int n = 0, m;
 
1057
    lig_part = lig_copy = copyString(charName);
 
1058
    do {
 
1059
      if ((lig_end = strchr(lig_part, '_')))
 
1060
        *lig_end = '\0';
 
1061
      if (lig_part[0] != '\0') {
 
1062
        GBool namesRecurse = gTrue, ligaturesRecurse = gFalse;
 
1063
        if ((m = parseCharName(lig_part, uBuf + n, uLen - n, namesRecurse,
 
1064
                               ligaturesRecurse, numeric, hex, variants)))
 
1065
          n += m;
 
1066
        else
 
1067
          error(-1, "Could not parse ligature component \"%s\" of \"%s\" in "
 
1068
                "parseCharName", lig_part, charName);
 
1069
      }
 
1070
      lig_part = lig_end + 1;
 
1071
    } while (lig_end && n < uLen);
 
1072
    gfree(lig_copy);
 
1073
    return n;
 
1074
  }
 
1075
  // Step 3: map each component to a character string according to the
 
1076
  // procedure below, and concatenate those strings; the result is the
 
1077
  // character string to which the glyph name is mapped.
 
1078
  // 3.1. if the font is Zapf Dingbats (PostScript FontName ZapfDingbats), and
 
1079
  // the component is in the ZapfDingbats list, then map it to the
 
1080
  // corresponding character in that list.
 
1081
  // 3.2. otherwise, if the component is in the Adobe Glyph List, then map it
 
1082
  // to the corresponding character in that list.
 
1083
  if (names && (uBuf[0] = globalParams->mapNameToUnicode(charName))) {
 
1084
    return 1;
 
1085
  }
 
1086
  if (numeric) {
 
1087
    unsigned int n = strlen(charName);
 
1088
    // 3.3. otherwise, if the component is of the form "uni" (U+0075 U+006E
 
1089
    // U+0069) followed by a sequence of uppercase hexadecimal digits (0 .. 9,
 
1090
    // A .. F, i.e. U+0030 .. U+0039, U+0041 .. U+0046), the length of that
 
1091
    // sequence is a multiple of four, and each group of four digits represents
 
1092
    // a number in the set {0x0000 .. 0xD7FF, 0xE000 .. 0xFFFF}, then interpret
 
1093
    // each such number as a Unicode scalar value and map the component to the
 
1094
    // string made of those scalar values. Note that the range and digit length
 
1095
    // restrictions mean that the "uni" prefix can be used only with Unicode
 
1096
    // values from the Basic Multilingual Plane (BMP).
 
1097
    if (n >= 7 && (n % 4) == 3 && !strncmp(charName, "uni", 3)) {
 
1098
      int i;
 
1099
      unsigned int m;
 
1100
      for (i = 0, m = 3; i < uLen && m < n; m += 4) {
 
1101
        if (isxdigit(charName[m]) && isxdigit(charName[m + 1]) && 
 
1102
            isxdigit(charName[m + 2]) && isxdigit(charName[m + 3])) {
 
1103
          unsigned int u;
 
1104
          sscanf(charName + m, "%4x", &u);
 
1105
          if (u <= 0xD7FF || (0xE000 <= u && u <= 0xFFFF)) {
 
1106
            uBuf[i++] = u;
 
1107
          }
 
1108
        }
 
1109
      }
 
1110
      return i;
 
1111
    }
 
1112
    // 3.4. otherwise, if the component is of the form "u" (U+0075) followed by
 
1113
    // a sequence of four to six uppercase hexadecimal digits {0 .. 9, A .. F}
 
1114
    // (U+0030 .. U+0039, U+0041 .. U+0046), and those digits represent a
 
1115
    // number in {0x0000 .. 0xD7FF, 0xE000 .. 0x10FFFF}, then interpret this
 
1116
    // number as a Unicode scalar value and map the component to the string
 
1117
    // made of this scalar value.
 
1118
    if (n >= 5 && n <= 7 && charName[0] == 'u' && isxdigit(charName[1]) &&
 
1119
        isxdigit(charName[2]) && isxdigit(charName[3]) && isxdigit(charName[4])
 
1120
        && (n <= 5 || isxdigit(charName[5]))
 
1121
        && (n <= 6 || isxdigit(charName[6]))) {
 
1122
      unsigned int u;
 
1123
      sscanf(charName + 1, "%x", &u);
 
1124
      if (u <= 0xD7FF || (0xE000 <= u && u <= 0x10FFFF)) {
 
1125
        uBuf[0] = u;
 
1126
        return 1;
 
1127
      }
 
1128
    }
 
1129
    // Not in Adobe Glyph Mapping convention: look for names of the form 'Axx',
 
1130
    // 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' are any letters, 'xx' is
 
1131
    // two hex digits, and 'nn' is 2-4 decimal digits
 
1132
    if (hex && n == 3 && isalpha(charName[0]) &&
 
1133
        isxdigit(charName[1]) && isxdigit(charName[2])) {
 
1134
      sscanf(charName+1, "%x", (unsigned int *)uBuf);
 
1135
      return 1;
 
1136
    } else if (hex && n == 2 &&
 
1137
               isxdigit(charName[0]) && isxdigit(charName[1])) {
 
1138
      sscanf(charName, "%x", (unsigned int *)uBuf);
 
1139
      return 1;
 
1140
    } else if (!hex && n >= 2 && n <= 4 &&
 
1141
               isdigit(charName[0]) && isdigit(charName[1])) {
 
1142
      uBuf[0] = (Unicode)atoi(charName);
 
1143
      return 1;
 
1144
    } else if (n >= 3 && n <= 5 &&
 
1145
               isdigit(charName[1]) && isdigit(charName[2])) {
 
1146
      uBuf[0] = (Unicode)atoi(charName+1);
 
1147
      return 1;
 
1148
    } else if (n >= 4 && n <= 6 &&
 
1149
               isdigit(charName[2]) && isdigit(charName[3])) {
 
1150
      uBuf[0] = (Unicode)atoi(charName+2);
 
1151
      return 1;
 
1152
    }
 
1153
  }
 
1154
  // 3.5. otherwise, map the component to the empty string
 
1155
  return 0;
 
1156
}
 
1157
 
 
1158
int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
 
1159
                             Unicode **u, int *uLen,
 
1160
                             double *dx, double *dy, double *ox, double *oy) {
 
1161
  CharCode c;
 
1162
 
 
1163
  *code = c = (CharCode)(*s & 0xff);
 
1164
  *uLen = ctu->mapToUnicode(c, u);
 
1165
  *dx = widths[c];
 
1166
  *dy = *ox = *oy = 0;
 
1167
  return 1;
 
1168
}
 
1169
 
 
1170
CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
 
1171
  ctu->incRefCnt();
 
1172
  return ctu;
 
1173
}
 
1174
 
 
1175
Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
 
1176
  Gushort *map;
 
1177
  int cmapPlatform, cmapEncoding;
 
1178
  int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
 
1179
  GBool useMacRoman, useUnicode;
 
1180
  char *charName;
 
1181
  Unicode u;
 
1182
  int code, i, n;
 
1183
 
 
1184
  map = (Gushort *)gmallocn(256, sizeof(Gushort));
 
1185
  for (i = 0; i < 256; ++i) {
 
1186
    map[i] = 0;
 
1187
  }
 
1188
 
 
1189
  // To match up with the Adobe-defined behaviour, we choose a cmap
 
1190
  // like this:
 
1191
  // 1. If the PDF font has an encoding:
 
1192
  //    1a. If the PDF font specified MacRomanEncoding and the
 
1193
  //        TrueType font has a Macintosh Roman cmap, use it, and
 
1194
  //        reverse map the char names through MacRomanEncoding to
 
1195
  //        get char codes.
 
1196
  //    1b. If the TrueType font has a Microsoft Unicode cmap or a
 
1197
  //        non-Microsoft Unicode cmap, use it, and use the Unicode
 
1198
  //        indexes, not the char codes.
 
1199
  //    1c. If the PDF font is symbolic and the TrueType font has a
 
1200
  //        Microsoft Symbol cmap, use it, and use char codes
 
1201
  //        directly (possibly with an offset of 0xf000).
 
1202
  //    1d. If the TrueType font has a Macintosh Roman cmap, use it,
 
1203
  //        as in case 1a.
 
1204
  // 2. If the PDF font does not have an encoding or the PDF font is
 
1205
  //    symbolic:
 
1206
  //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
 
1207
  //        and use char codes directly (possibly with an offset of
 
1208
  //        0xf000).
 
1209
  //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
 
1210
  //        and use char codes directly (possible with an offset of
 
1211
  //        0xf000).
 
1212
  // 3. If none of these rules apply, use the first cmap and hope for
 
1213
  //    the best (this shouldn't happen).
 
1214
  unicodeCmap = macRomanCmap = msSymbolCmap = -1;
 
1215
  for (i = 0; i < ff->getNumCmaps(); ++i) {
 
1216
    cmapPlatform = ff->getCmapPlatform(i);
 
1217
    cmapEncoding = ff->getCmapEncoding(i);
 
1218
    if ((cmapPlatform == 3 && cmapEncoding == 1) ||
 
1219
        cmapPlatform == 0) {
 
1220
      unicodeCmap = i;
 
1221
    } else if (cmapPlatform == 1 && cmapEncoding == 0) {
 
1222
      macRomanCmap = i;
 
1223
    } else if (cmapPlatform == 3 && cmapEncoding == 0) {
 
1224
      msSymbolCmap = i;
 
1225
    }
 
1226
  }
 
1227
  cmap = 0;
 
1228
  useMacRoman = gFalse;
 
1229
  useUnicode = gFalse;
 
1230
  if (hasEncoding) {
 
1231
    if (usesMacRomanEnc && macRomanCmap >= 0) {
 
1232
      cmap = macRomanCmap;
 
1233
      useMacRoman = gTrue;
 
1234
    } else if (unicodeCmap >= 0) {
 
1235
      cmap = unicodeCmap;
 
1236
      useUnicode = gTrue;
 
1237
    } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
 
1238
      cmap = msSymbolCmap;
 
1239
    } else if ((flags & fontSymbolic) && macRomanCmap >= 0) {
 
1240
      cmap = macRomanCmap;
 
1241
    } else if (macRomanCmap >= 0) {
 
1242
      cmap = macRomanCmap;
 
1243
      useMacRoman = gTrue;
 
1244
    }
 
1245
  } else {
 
1246
    if (msSymbolCmap >= 0) {
 
1247
      cmap = msSymbolCmap;
 
1248
    } else if (macRomanCmap >= 0) {
 
1249
      cmap = macRomanCmap;
 
1250
    }
 
1251
  }
 
1252
 
 
1253
  // reverse map the char names through MacRomanEncoding, then map the
 
1254
  // char codes through the cmap
 
1255
  if (useMacRoman) {
 
1256
    for (i = 0; i < 256; ++i) {
 
1257
      if ((charName = enc[i])) {
 
1258
        if ((code = globalParams->getMacRomanCharCode(charName))) {
 
1259
          map[i] = ff->mapCodeToGID(cmap, code);
 
1260
        }
 
1261
      }
 
1262
    }
 
1263
 
 
1264
  // map Unicode through the cmap
 
1265
  } else if (useUnicode) {
 
1266
    Unicode *uAux;
 
1267
    for (i = 0; i < 256; ++i) {
 
1268
      if (((charName = enc[i]) && (u = globalParams->mapNameToUnicode(charName))))
 
1269
        map[i] = ff->mapCodeToGID(cmap, u);
 
1270
      else
 
1271
      {
 
1272
        n = ctu->mapToUnicode((CharCode)i, &uAux);
 
1273
        if (n > 0) map[i] = ff->mapCodeToGID(cmap, uAux[0]);
 
1274
      }
 
1275
    }
 
1276
 
 
1277
  // map the char codes through the cmap, possibly with an offset of
 
1278
  // 0xf000
 
1279
  } else {
 
1280
    for (i = 0; i < 256; ++i) {
 
1281
      if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
 
1282
        map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
 
1283
      }
 
1284
    }
 
1285
  }
 
1286
 
 
1287
  // try the TrueType 'post' table to handle any unmapped characters
 
1288
  for (i = 0; i < 256; ++i) {
 
1289
    if (!map[i] && (charName = enc[i])) {
 
1290
      map[i] = (Gushort)(int)ff->mapNameToGID(charName);
 
1291
    }
 
1292
  }
 
1293
 
 
1294
  return map;
 
1295
}
 
1296
 
 
1297
Dict *Gfx8BitFont::getCharProcs() {
 
1298
  return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
 
1299
}
 
1300
 
 
1301
Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
 
1302
  if (enc[code] && charProcs.isDict()) {
 
1303
    charProcs.dictLookup(enc[code], proc);
 
1304
  } else {
 
1305
    proc->initNull();
 
1306
  }
 
1307
  return proc;
 
1308
}
 
1309
 
 
1310
Dict *Gfx8BitFont::getResources() {
 
1311
  return resources.isDict() ? resources.getDict() : (Dict *)NULL;
 
1312
}
 
1313
 
 
1314
//------------------------------------------------------------------------
 
1315
// GfxCIDFont
 
1316
//------------------------------------------------------------------------
 
1317
 
 
1318
static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
 
1319
  return ((GfxFontCIDWidthExcep *)w1)->first -
 
1320
         ((GfxFontCIDWidthExcep *)w2)->first;
 
1321
}
 
1322
 
 
1323
static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
 
1324
  return ((GfxFontCIDWidthExcepV *)w1)->first -
 
1325
         ((GfxFontCIDWidthExcepV *)w2)->first;
 
1326
}
 
1327
 
 
1328
GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GooString *nameA,
 
1329
                       Dict *fontDict):
 
1330
  GfxFont(tagA, idA, nameA)
 
1331
{
 
1332
  Dict *desFontDict;
 
1333
  GooString *collection, *cMapName;
 
1334
  Object desFontDictObj;
 
1335
  Object obj1, obj2, obj3, obj4, obj5, obj6;
 
1336
  CharCodeToUnicode *utu;
 
1337
  CharCode c;
 
1338
  Unicode *uBuf;
 
1339
  int c1, c2;
 
1340
  int excepsSize, i, j, k, n;
 
1341
 
 
1342
  refCnt = 1;
 
1343
  ascent = 0.95;
 
1344
  descent = -0.35;
 
1345
  fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
 
1346
  cMap = NULL;
 
1347
  ctu = NULL;
 
1348
  widths.defWidth = 1.0;
 
1349
  widths.defHeight = -1.0;
 
1350
  widths.defVY = 0.880;
 
1351
  widths.exceps = NULL;
 
1352
  widths.nExceps = 0;
 
1353
  widths.excepsV = NULL;
 
1354
  widths.nExcepsV = 0;
 
1355
  cidToGID = NULL;
 
1356
  cidToGIDLen = 0;
 
1357
 
 
1358
  // get the descendant font
 
1359
  if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
 
1360
    error(-1, "Missing DescendantFonts entry in Type 0 font");
 
1361
    obj1.free();
 
1362
    goto err1;
 
1363
  }
 
1364
  if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
 
1365
    error(-1, "Bad descendant font in Type 0 font");
 
1366
    goto err3;
 
1367
  }
 
1368
  obj1.free();
 
1369
  desFontDict = desFontDictObj.getDict();
 
1370
 
 
1371
  // font type
 
1372
  if (!desFontDict->lookup("Subtype", &obj1)) {
 
1373
    error(-1, "Missing Subtype entry in Type 0 descendant font");
 
1374
    goto err3;
 
1375
  }
 
1376
  if (obj1.isName("CIDFontType0")) {
 
1377
    type = fontCIDType0;
 
1378
  } else if (obj1.isName("CIDFontType2")) {
 
1379
    type = fontCIDType2;
 
1380
  } else {
 
1381
    error(-1, "Unknown Type 0 descendant font type '%s'",
 
1382
          obj1.isName() ? obj1.getName() : "???");
 
1383
    goto err3;
 
1384
  }
 
1385
  obj1.free();
 
1386
 
 
1387
  // get info from font descriptor
 
1388
  readFontDescriptor(xref, desFontDict);
 
1389
 
 
1390
  // look for an external font file
 
1391
  findExtFontFile();
 
1392
 
 
1393
  //----- encoding info -----
 
1394
 
 
1395
  // char collection
 
1396
  if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
 
1397
    error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
 
1398
    goto err3;
 
1399
  }
 
1400
  obj1.dictLookup("Registry", &obj2);
 
1401
  obj1.dictLookup("Ordering", &obj3);
 
1402
  if (!obj2.isString() || !obj3.isString()) {
 
1403
    error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
 
1404
    goto err4;
 
1405
  }
 
1406
  collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
 
1407
  obj3.free();
 
1408
  obj2.free();
 
1409
  obj1.free();
 
1410
 
 
1411
  // look for a ToUnicode CMap
 
1412
  if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
 
1413
 
 
1414
    // the "Adobe-Identity" and "Adobe-UCS" collections don't have
 
1415
    // cidToUnicode files
 
1416
    if (collection->cmp("Adobe-Identity") &&
 
1417
        collection->cmp("Adobe-UCS")) {
 
1418
 
 
1419
      // look for a user-supplied .cidToUnicode file
 
1420
      if (!(ctu = globalParams->getCIDToUnicode(collection))) {
 
1421
        // I'm not completely sure that this is the best thing to do
 
1422
        // but it seems to produce better results when the .cidToUnicode
 
1423
        // files from the poppler-data package are missing. At least
 
1424
        // we know that assuming the Identity mapping is definitely wrong.
 
1425
        //   -- jrmuizel
 
1426
        static const char * knownCollections [] = {
 
1427
          "Adobe-CNS1",
 
1428
          "Adobe-GB1",
 
1429
          "Adobe-Japan1",
 
1430
          "Adobe-Japan2",
 
1431
          "Adobe-Korea1",
 
1432
        };
 
1433
        for (size_t i = 0; i < sizeof(knownCollections)/sizeof(knownCollections[0]); i++) {
 
1434
          if (collection->cmp(knownCollections[i]) == 0) {
 
1435
            error(-1, "Missing language pack for '%s' mapping", collection->getCString());
 
1436
            delete collection;
 
1437
            goto err2;
 
1438
          }
 
1439
        }
 
1440
        error(-1, "Unknown character collection '%s'",
 
1441
              collection->getCString());
 
1442
        // fall-through, assuming the Identity mapping -- this appears
 
1443
        // to match Adobe's behavior
 
1444
      }
 
1445
    }
 
1446
  }
 
1447
 
 
1448
  // look for a Unicode-to-Unicode mapping
 
1449
  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
 
1450
    if (ctu) {
 
1451
      for (c = 0; c < ctu->getLength(); ++c) {
 
1452
        n = ctu->mapToUnicode(c, &uBuf);
 
1453
        if (n >= 1) {
 
1454
          n = utu->mapToUnicode((CharCode)uBuf[0], &uBuf);
 
1455
          if (n >= 1) {
 
1456
            ctu->setMapping(c, uBuf, n);
 
1457
          }
 
1458
        }
 
1459
      }
 
1460
      utu->decRefCnt();
 
1461
    } else {
 
1462
      ctu = utu;
 
1463
    }
 
1464
  }
 
1465
 
 
1466
  // encoding (i.e., CMap)
 
1467
  //~ also need to deal with the UseCMap entry in the stream dict
 
1468
  if (!fontDict->lookup("Encoding", &obj1)->isName()) {
 
1469
    GBool success = gFalse;
 
1470
    if (obj1.isStream()) {
 
1471
      Object objName;
 
1472
      Stream *s = obj1.getStream();
 
1473
      s->getDict()->lookup("CMapName", &objName);
 
1474
      if (objName.isName())
 
1475
      {
 
1476
        cMapName = new GooString(objName.getName());
 
1477
        cMap = globalParams->getCMap(collection, cMapName, s);
 
1478
        success = gTrue;
 
1479
      }
 
1480
      objName.free();
 
1481
    }
 
1482
    
 
1483
    if (!success) {
 
1484
      error(-1, "Missing or invalid Encoding entry in Type 0 font");
 
1485
      delete collection;
 
1486
      goto err3;
 
1487
    }
 
1488
  } else {
 
1489
    cMapName = new GooString(obj1.getName());
 
1490
    cMap = globalParams->getCMap(collection, cMapName);
 
1491
  }
 
1492
  delete collection;
 
1493
  delete cMapName;
 
1494
  if (!cMap) {
 
1495
      error(-1, "Unknown CMap '%s' for character collection '%s'",
 
1496
            cMapName->getCString(), collection->getCString());
 
1497
      goto err2;
 
1498
    }
 
1499
  obj1.free();
 
1500
 
 
1501
  // CIDToGIDMap (for embedded TrueType fonts)
 
1502
  if (type == fontCIDType2 || type == fontCIDType2OT) {
 
1503
    desFontDict->lookup("CIDToGIDMap", &obj1);
 
1504
    if (obj1.isStream()) {
 
1505
      cidToGIDLen = 0;
 
1506
      i = 64;
 
1507
      cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort));
 
1508
      obj1.streamReset();
 
1509
      while ((c1 = obj1.streamGetChar()) != EOF &&
 
1510
             (c2 = obj1.streamGetChar()) != EOF) {
 
1511
        if (cidToGIDLen == i) {
 
1512
          i *= 2;
 
1513
          cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort));
 
1514
        }
 
1515
        cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
 
1516
      }
 
1517
    } else if (!obj1.isName("Identity") && !obj1.isNull()) {
 
1518
      error(-1, "Invalid CIDToGIDMap entry in CID font");
 
1519
    }
 
1520
    obj1.free();
 
1521
  }
 
1522
 
 
1523
  //----- character metrics -----
 
1524
 
 
1525
  // default char width
 
1526
  if (desFontDict->lookup("DW", &obj1)->isInt()) {
 
1527
    widths.defWidth = obj1.getInt() * 0.001;
 
1528
  }
 
1529
  obj1.free();
 
1530
 
 
1531
  // char width exceptions
 
1532
  if (desFontDict->lookup("W", &obj1)->isArray()) {
 
1533
    excepsSize = 0;
 
1534
    i = 0;
 
1535
    while (i + 1 < obj1.arrayGetLength()) {
 
1536
      obj1.arrayGet(i, &obj2);
 
1537
      obj1.arrayGet(i + 1, &obj3);
 
1538
      if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
 
1539
        if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
 
1540
          if (widths.nExceps == excepsSize) {
 
1541
            excepsSize += 16;
 
1542
            widths.exceps = (GfxFontCIDWidthExcep *)
 
1543
              greallocn(widths.exceps,
 
1544
                        excepsSize, sizeof(GfxFontCIDWidthExcep));
 
1545
          }
 
1546
          widths.exceps[widths.nExceps].first = obj2.getInt();
 
1547
          widths.exceps[widths.nExceps].last = obj3.getInt();
 
1548
          widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
 
1549
          ++widths.nExceps;
 
1550
        } else {
 
1551
          error(-1, "Bad widths array in Type 0 font");
 
1552
        }
 
1553
        obj4.free();
 
1554
        i += 3;
 
1555
      } else if (obj2.isInt() && obj3.isArray()) {
 
1556
        if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
 
1557
          excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
 
1558
          widths.exceps = (GfxFontCIDWidthExcep *)
 
1559
            greallocn(widths.exceps,
 
1560
                      excepsSize, sizeof(GfxFontCIDWidthExcep));
 
1561
        }
 
1562
        j = obj2.getInt();
 
1563
        for (k = 0; k < obj3.arrayGetLength(); ++k) {
 
1564
          if (obj3.arrayGet(k, &obj4)->isNum()) {
 
1565
            widths.exceps[widths.nExceps].first = j;
 
1566
            widths.exceps[widths.nExceps].last = j;
 
1567
            widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
 
1568
            ++j;
 
1569
            ++widths.nExceps;
 
1570
          } else {
 
1571
            error(-1, "Bad widths array in Type 0 font");
 
1572
          }
 
1573
          obj4.free();
 
1574
        }
 
1575
        i += 2;
 
1576
      } else {
 
1577
        error(-1, "Bad widths array in Type 0 font");
 
1578
        ++i;
 
1579
      }
 
1580
      obj3.free();
 
1581
      obj2.free();
 
1582
    }
 
1583
    qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
 
1584
          &cmpWidthExcep);
 
1585
  }
 
1586
  obj1.free();
 
1587
 
 
1588
  // default metrics for vertical font
 
1589
  if (desFontDict->lookup("DW2", &obj1)->isArray() &&
 
1590
      obj1.arrayGetLength() == 2) {
 
1591
    if (obj1.arrayGet(0, &obj2)->isNum()) {
 
1592
      widths.defVY = obj2.getNum() * 0.001;
 
1593
    }
 
1594
    obj2.free();
 
1595
    if (obj1.arrayGet(1, &obj2)->isNum()) {
 
1596
      widths.defHeight = obj2.getNum() * 0.001;
 
1597
    }
 
1598
    obj2.free();
 
1599
  }
 
1600
  obj1.free();
 
1601
 
 
1602
  // char metric exceptions for vertical font
 
1603
  if (desFontDict->lookup("W2", &obj1)->isArray()) {
 
1604
    excepsSize = 0;
 
1605
    i = 0;
 
1606
    while (i + 1 < obj1.arrayGetLength()) {
 
1607
      obj1.arrayGet(i, &obj2);
 
1608
      obj1.arrayGet(i+ 1, &obj3);
 
1609
      if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
 
1610
        if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
 
1611
            obj1.arrayGet(i + 3, &obj5)->isNum() &&
 
1612
            obj1.arrayGet(i + 4, &obj6)->isNum()) {
 
1613
          if (widths.nExcepsV == excepsSize) {
 
1614
            excepsSize += 16;
 
1615
            widths.excepsV = (GfxFontCIDWidthExcepV *)
 
1616
              greallocn(widths.excepsV,
 
1617
                        excepsSize, sizeof(GfxFontCIDWidthExcepV));
 
1618
          }
 
1619
          widths.excepsV[widths.nExcepsV].first = obj2.getInt();
 
1620
          widths.excepsV[widths.nExcepsV].last = obj3.getInt();
 
1621
          widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
 
1622
          widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
 
1623
          widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
 
1624
          ++widths.nExcepsV;
 
1625
        } else {
 
1626
          error(-1, "Bad widths (W2) array in Type 0 font");
 
1627
        }
 
1628
        obj6.free();
 
1629
        obj5.free();
 
1630
        obj4.free();
 
1631
        i += 5;
 
1632
      } else if (obj2.isInt() && obj3.isArray()) {
 
1633
        if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
 
1634
          excepsSize =
 
1635
            (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
 
1636
          widths.excepsV = (GfxFontCIDWidthExcepV *)
 
1637
            greallocn(widths.excepsV,
 
1638
                      excepsSize, sizeof(GfxFontCIDWidthExcepV));
 
1639
        }
 
1640
        j = obj2.getInt();
 
1641
        for (k = 0; k < obj3.arrayGetLength(); k += 3) {
 
1642
          if (obj3.arrayGet(k, &obj4)->isNum() &&
 
1643
              obj3.arrayGet(k+1, &obj5)->isNum() &&
 
1644
              obj3.arrayGet(k+2, &obj6)->isNum()) {
 
1645
            widths.excepsV[widths.nExcepsV].first = j;
 
1646
            widths.excepsV[widths.nExcepsV].last = j;
 
1647
            widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
 
1648
            widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
 
1649
            widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
 
1650
            ++j;
 
1651
            ++widths.nExcepsV;
 
1652
          } else {
 
1653
            error(-1, "Bad widths (W2) array in Type 0 font");
 
1654
          }
 
1655
          obj6.free();
 
1656
          obj5.free();
 
1657
          obj4.free();
 
1658
        }
 
1659
        i += 2;
 
1660
      } else {
 
1661
        error(-1, "Bad widths (W2) array in Type 0 font");
 
1662
        ++i;
 
1663
      }
 
1664
      obj3.free();
 
1665
      obj2.free();
 
1666
    }
 
1667
    qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
 
1668
          &cmpWidthExcepV);
 
1669
  }
 
1670
  obj1.free();
 
1671
 
 
1672
  desFontDictObj.free();
 
1673
  ok = gTrue;
 
1674
  return;
 
1675
 
 
1676
 err4:
 
1677
  obj3.free();
 
1678
  obj2.free();
 
1679
 err3:
 
1680
  obj1.free();
 
1681
 err2:
 
1682
  desFontDictObj.free();
 
1683
 err1:;
 
1684
}
 
1685
 
 
1686
GfxCIDFont::~GfxCIDFont() {
 
1687
  if (cMap) {
 
1688
    cMap->decRefCnt();
 
1689
  }
 
1690
  if (ctu) {
 
1691
    ctu->decRefCnt();
 
1692
  }
 
1693
  gfree(widths.exceps);
 
1694
  gfree(widths.excepsV);
 
1695
  if (cidToGID) {
 
1696
    gfree(cidToGID);
 
1697
  }
 
1698
}
 
1699
 
 
1700
int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
 
1701
                            Unicode **u, int *uLen,
 
1702
                            double *dx, double *dy, double *ox, double *oy) {
 
1703
  CID cid;
 
1704
  double w, h, vx, vy;
 
1705
  int n, a, b, m;
 
1706
 
 
1707
  if (!cMap) {
 
1708
    *code = 0;
 
1709
    *uLen = 0;
 
1710
    *dx = *dy = 0;
 
1711
    return 1;
 
1712
  }
 
1713
 
 
1714
  *code = (CharCode)(cid = cMap->getCID(s, len, &n));
 
1715
  if (ctu) {
 
1716
    *uLen = ctu->mapToUnicode(cid, u);
 
1717
  } else {
 
1718
    *uLen = 0;
 
1719
  }
 
1720
 
 
1721
  // horizontal
 
1722
  if (cMap->getWMode() == 0) {
 
1723
    w = widths.defWidth;
 
1724
    h = vx = vy = 0;
 
1725
    if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
 
1726
      a = 0;
 
1727
      b = widths.nExceps;
 
1728
      // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
 
1729
      while (b - a > 1) {
 
1730
        m = (a + b) / 2;
 
1731
        if (widths.exceps[m].first <= cid) {
 
1732
          a = m;
 
1733
        } else {
 
1734
          b = m;
 
1735
        }
 
1736
      }
 
1737
      if (cid <= widths.exceps[a].last) {
 
1738
        w = widths.exceps[a].width;
 
1739
      }
 
1740
    }
 
1741
 
 
1742
  // vertical
 
1743
  } else {
 
1744
    w = 0;
 
1745
    h = widths.defHeight;
 
1746
    vx = widths.defWidth / 2;
 
1747
    vy = widths.defVY;
 
1748
    if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
 
1749
      a = 0;
 
1750
      b = widths.nExcepsV;
 
1751
      // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
 
1752
      while (b - a > 1) {
 
1753
        m = (a + b) / 2;
 
1754
        if (widths.excepsV[m].last <= cid) {
 
1755
          a = m;
 
1756
        } else {
 
1757
          b = m;
 
1758
        }
 
1759
      }
 
1760
      if (cid <= widths.excepsV[a].last) {
 
1761
        h = widths.excepsV[a].height;
 
1762
        vx = widths.excepsV[a].vx;
 
1763
        vy = widths.excepsV[a].vy;
 
1764
      }
 
1765
    }
 
1766
  }
 
1767
 
 
1768
  *dx = w;
 
1769
  *dy = h;
 
1770
  *ox = vx;
 
1771
  *oy = vy;
 
1772
 
 
1773
  return n;
 
1774
}
 
1775
 
 
1776
int GfxCIDFont::getWMode() {
 
1777
  return cMap ? cMap->getWMode() : 0;
 
1778
}
 
1779
 
 
1780
CharCodeToUnicode *GfxCIDFont::getToUnicode() {
 
1781
  if (ctu) {
 
1782
    ctu->incRefCnt();
 
1783
  }
 
1784
  return ctu;
 
1785
}
 
1786
 
 
1787
GooString *GfxCIDFont::getCollection() {
 
1788
  return cMap ? cMap->getCollection() : (GooString *)NULL;
 
1789
}
 
1790
 
 
1791
Gushort GfxCIDFont::mapCodeToGID(FoFiTrueType *ff, int cmapi,
 
1792
  Unicode unicode, GBool wmode) {
 
1793
  Gushort gid = ff->mapCodeToGID(cmapi,unicode);
 
1794
  if (wmode) {
 
1795
    Gushort vgid = ff->mapToVertGID(gid);
 
1796
    if (vgid != 0) gid = vgid;
 
1797
  }
 
1798
  return gid;
 
1799
}
 
1800
 
 
1801
Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
 
1802
#define N_UCS_CANDIDATES 2
 
1803
  /* space characters */
 
1804
  static const unsigned long spaces[] = { 
 
1805
    0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
 
1806
    0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
 
1807
    0
 
1808
  };
 
1809
  static char *adobe_cns1_cmaps[] = {
 
1810
    "UniCNS-UTF32-V",
 
1811
    "UniCNS-UCS2-V",
 
1812
    "UniCNS-UTF32-H",
 
1813
    "UniCNS-UCS2-H",
 
1814
    0
 
1815
  };
 
1816
  static char *adobe_gb1_cmaps[] = {
 
1817
    "UniGB-UTF32-V",
 
1818
    "UniGB-UCS2-V",
 
1819
    "UniGB-UTF32-H",
 
1820
    "UniGB-UCS2-H",
 
1821
    0
 
1822
  };
 
1823
  static char *adobe_japan1_cmaps[] = {
 
1824
    "UniJIS-UTF32-V",
 
1825
    "UniJIS-UCS2-V",
 
1826
    "UniJIS-UTF32-H",
 
1827
    "UniJIS-UCS2-H",
 
1828
    0
 
1829
  };
 
1830
  static char *adobe_japan2_cmaps[] = {
 
1831
    "UniHojo-UTF32-V",
 
1832
    "UniHojo-UCS2-V",
 
1833
    "UniHojo-UTF32-H",
 
1834
    "UniHojo-UCS2-H",
 
1835
    0
 
1836
  };
 
1837
  static char *adobe_korea1_cmaps[] = {
 
1838
    "UniKS-UTF32-V",
 
1839
    "UniKS-UCS2-V",
 
1840
    "UniKS-UTF32-H",
 
1841
    "UniKS-UCS2-H",
 
1842
    0
 
1843
  };
 
1844
  static struct CMapListEntry {
 
1845
    char *collection;
 
1846
    char *scriptTag;
 
1847
    char *toUnicodeMap;
 
1848
    char **CMaps;
 
1849
  } CMapList[] = {
 
1850
    {
 
1851
      "Adobe-CNS1",
 
1852
      "kana",
 
1853
      "Adobe-CNS1-UCS2",
 
1854
      adobe_cns1_cmaps,
 
1855
    },
 
1856
    {
 
1857
      "Adobe-GB1",
 
1858
      "kana",
 
1859
      "Adobe-GB1-UCS2",
 
1860
      adobe_gb1_cmaps,
 
1861
    },
 
1862
    {
 
1863
      "Adobe-Japan1",
 
1864
      "kana",
 
1865
      "Adobe-Japan1-UCS2",
 
1866
      adobe_japan1_cmaps,
 
1867
    },
 
1868
    {
 
1869
      "Adobe-Japan2",
 
1870
      "kana",
 
1871
      "Adobe-Japan2-UCS2",
 
1872
      adobe_japan2_cmaps,
 
1873
    },
 
1874
    {
 
1875
      "Adobe-Korea1",
 
1876
      "kana",
 
1877
      "Adobe-Korea1-UCS2",
 
1878
      adobe_korea1_cmaps,
 
1879
    },
 
1880
    {0, 0, 0, 0}
 
1881
  };
 
1882
  Unicode *humap = 0;
 
1883
  Unicode *vumap = 0;
 
1884
  Unicode *tumap = 0;
 
1885
  Gushort *codeToGID = 0;
 
1886
  unsigned long n;
 
1887
  int i;
 
1888
  unsigned long code;
 
1889
  int wmode;
 
1890
  char **cmapName;
 
1891
  CMap *cMap;
 
1892
  CMapListEntry *lp;
 
1893
  int cmap;
 
1894
  int cmapPlatform, cmapEncoding;
 
1895
  Ref embID;
 
1896
 
 
1897
  *mapsizep = 0;
 
1898
  if (!ctu) return NULL;
 
1899
  if (getCollection()->cmp("Adobe-Identity") == 0) return NULL;
 
1900
  if (getEmbeddedFontID(&embID)) {
 
1901
   /* if this font is embedded font, 
 
1902
    * CIDToGIDMap should be embedded in PDF file
 
1903
    * and already set. So return it.
 
1904
    */
 
1905
    *mapsizep = getCIDToGIDLen();
 
1906
    return getCIDToGID();
 
1907
  }
 
1908
 
 
1909
  /* we use only unicode cmap */
 
1910
  cmap = -1;
 
1911
  for (i = 0; i < ff->getNumCmaps(); ++i) {
 
1912
    cmapPlatform = ff->getCmapPlatform(i);
 
1913
    cmapEncoding = ff->getCmapEncoding(i);
 
1914
    if (cmapPlatform == 3 && cmapEncoding == 10) {
 
1915
        /* UCS-4 */
 
1916
        cmap = i;
 
1917
        /* use UCS-4 cmap */
 
1918
        break;
 
1919
    } else if (cmapPlatform == 3 && cmapEncoding == 1) {
 
1920
        /* Unicode */
 
1921
        cmap = i;
 
1922
    } else if (cmapPlatform == 0 && cmap < 0) {
 
1923
        cmap = i;
 
1924
    }
 
1925
  }
 
1926
  if (cmap < 0)
 
1927
    return NULL;
 
1928
 
 
1929
  wmode = getWMode();
 
1930
  for (lp = CMapList;lp->collection != 0;lp++) {
 
1931
    if (strcmp(lp->collection,getCollection()->getCString()) == 0) {
 
1932
      break;
 
1933
    }
 
1934
  }
 
1935
  n = 65536;
 
1936
  tumap = new Unicode[n];
 
1937
  humap = new Unicode[n*N_UCS_CANDIDATES];
 
1938
  memset(humap,0,sizeof(Unicode)*n*N_UCS_CANDIDATES);
 
1939
  if (lp->collection != 0) {
 
1940
    CharCodeToUnicode *tctu;
 
1941
    GooString tname(lp->toUnicodeMap);
 
1942
 
 
1943
    if ((tctu = CharCodeToUnicode::parseCMapFromFile(&tname,16)) != 0) {
 
1944
      CharCode cid;
 
1945
      for (cid = 0;cid < n ;cid++) {
 
1946
        int len;
 
1947
        Unicode *ucodes;
 
1948
 
 
1949
        len = tctu->mapToUnicode(cid,&ucodes);
 
1950
        if (len == 1) {
 
1951
          tumap[cid] = ucodes[0];
 
1952
        } else {
 
1953
          /* if not single character, ignore it */
 
1954
          tumap[cid] = 0;
 
1955
        }
 
1956
      }
 
1957
      delete tctu;
 
1958
    }
 
1959
    vumap = new Unicode[n];
 
1960
    memset(vumap,0,sizeof(Unicode)*n);
 
1961
    for (cmapName = lp->CMaps;*cmapName != 0;cmapName++) {
 
1962
      GooString cname(*cmapName);
 
1963
 
 
1964
      if ((cMap = globalParams->getCMap(getCollection(),&cname))
 
1965
           != 0) {
 
1966
            if (cMap->getWMode()) {
 
1967
                cMap->setReverseMap(vumap,n,1);
 
1968
            } else {
 
1969
                cMap->setReverseMap(humap,n,N_UCS_CANDIDATES);
 
1970
            }
 
1971
        cMap->decRefCnt();
 
1972
      }
 
1973
    }
 
1974
    ff->setupGSUB(lp->scriptTag);
 
1975
  } else {
 
1976
    error(-1,"Unknown character collection %s\n",
 
1977
      getCollection()->getCString());
 
1978
    if ((ctu = getToUnicode()) != 0) {
 
1979
      CharCode cid;
 
1980
      for (cid = 0;cid < n ;cid++) {
 
1981
        Unicode *ucode;
 
1982
 
 
1983
        if (ctu->mapToUnicode(cid, &ucode))
 
1984
          humap[cid*N_UCS_CANDIDATES] = ucode[0];
 
1985
        else
 
1986
          humap[cid*N_UCS_CANDIDATES] = 0;
 
1987
        for (i = 1;i < N_UCS_CANDIDATES;i++) {
 
1988
            humap[cid*N_UCS_CANDIDATES+i] = 0;
 
1989
        }
 
1990
      }
 
1991
      ctu->decRefCnt();
 
1992
    }
 
1993
  }
 
1994
  // map CID -> Unicode -> GID
 
1995
  codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
 
1996
  for (code = 0; code < n; ++code) {
 
1997
    Unicode unicode;
 
1998
    unsigned long gid;
 
1999
 
 
2000
    unicode = 0;
 
2001
    gid = 0;
 
2002
    if (humap != 0) {
 
2003
      for (i = 0;i < N_UCS_CANDIDATES
 
2004
        && gid == 0 && (unicode = humap[code*N_UCS_CANDIDATES+i]) != 0;i++) {
 
2005
        gid = mapCodeToGID(ff,cmap,unicode,gFalse);
 
2006
      }
 
2007
    }
 
2008
    if (gid == 0 && vumap != 0) {
 
2009
      unicode = vumap[code];
 
2010
      if (unicode != 0) {
 
2011
        gid = mapCodeToGID(ff,cmap,unicode,gTrue);
 
2012
        if (gid == 0 && tumap != 0) {
 
2013
          if ((unicode = tumap[code]) != 0) {
 
2014
            gid = mapCodeToGID(ff,cmap,unicode,gTrue);
 
2015
          }
 
2016
        }
 
2017
      }
 
2018
    }
 
2019
    if (gid == 0 && tumap != 0) {
 
2020
      if ((unicode = tumap[code]) != 0) {
 
2021
        gid = mapCodeToGID(ff,cmap,unicode,gFalse);
 
2022
      }
 
2023
    }
 
2024
    if (gid == 0) {
 
2025
      /* special handling space characters */
 
2026
      const unsigned long *p;
 
2027
 
 
2028
      if (humap != 0) unicode = humap[code];
 
2029
      if (unicode != 0) {
 
2030
        /* check if code is space character , so map code to 0x0020 */
 
2031
        for (p = spaces;*p != 0;p++) {
 
2032
          if (*p == unicode) {
 
2033
            unicode = 0x20;
 
2034
            gid = mapCodeToGID(ff,cmap,unicode,wmode);
 
2035
            break;
 
2036
          }
 
2037
        }
 
2038
      }
 
2039
    }
 
2040
    codeToGID[code] = gid;
 
2041
  }
 
2042
  *mapsizep = n;
 
2043
  if (humap != 0) delete[] humap;
 
2044
  if (tumap != 0) delete[] tumap;
 
2045
  if (vumap != 0) delete[] vumap;
 
2046
  return codeToGID;
 
2047
}
 
2048
 
 
2049
double GfxCIDFont::getWidth (char* s, int len) {
 
2050
  int nUsed;
 
2051
  double w;
 
2052
  int a, b, m;
 
2053
 
 
2054
  CID cid = cMap->getCID(s, len, &nUsed);
 
2055
 
 
2056
  w = widths.defWidth;
 
2057
  if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
 
2058
    a = 0;
 
2059
    b = widths.nExceps;
 
2060
    // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
 
2061
    while (b - a > 1) {
 
2062
      m = (a + b) / 2;
 
2063
      if (widths.exceps[m].first <= cid) {
 
2064
        a = m;
 
2065
      } else {
 
2066
        b = m;
 
2067
      }
 
2068
    }
 
2069
    if (cid <= widths.exceps[a].last) {
 
2070
      w = widths.exceps[a].width;
 
2071
    }
 
2072
  }
 
2073
  return w;
 
2074
}
 
2075
 
 
2076
//------------------------------------------------------------------------
 
2077
// GfxFontDict
 
2078
//------------------------------------------------------------------------
 
2079
 
 
2080
GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
 
2081
  int i;
 
2082
  Object obj1, obj2;
 
2083
  Ref r;
 
2084
 
 
2085
  numFonts = fontDict->getLength();
 
2086
  fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *));
 
2087
  for (i = 0; i < numFonts; ++i) {
 
2088
    fontDict->getValNF(i, &obj1);
 
2089
    obj1.fetch(xref, &obj2);
 
2090
    if (obj2.isDict()) {
 
2091
      if (obj1.isRef()) {
 
2092
        r = obj1.getRef();
 
2093
      } else {
 
2094
        // no indirect reference for this font, so invent a unique one
 
2095
        // (legal generation numbers are five digits, so any 6-digit
 
2096
        // number would be safe)
 
2097
        r.num = i;
 
2098
        if (fontDictRef) {
 
2099
          r.gen = 100000 + fontDictRef->num;
 
2100
        } else {
 
2101
          r.gen = 999999;
 
2102
        }
 
2103
      }
 
2104
      fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
 
2105
                                   r, obj2.getDict());
 
2106
      if (fonts[i] && !fonts[i]->isOk()) {
 
2107
        // XXX: it may be meaningful to distinguish between
 
2108
        // NULL and !isOk() so that when we do lookups
 
2109
        // we can tell the difference between a missing font
 
2110
        // and a font that is just !isOk()
 
2111
        fonts[i]->decRefCnt();
 
2112
        fonts[i] = NULL;
 
2113
      }
 
2114
    } else {
 
2115
      error(-1, "font resource is not a dictionary");
 
2116
      fonts[i] = NULL;
 
2117
    }
 
2118
    obj1.free();
 
2119
    obj2.free();
 
2120
  }
 
2121
}
 
2122
 
 
2123
GfxFontDict::~GfxFontDict() {
 
2124
  int i;
 
2125
 
 
2126
  for (i = 0; i < numFonts; ++i) {
 
2127
    if (fonts[i]) {
 
2128
      fonts[i]->decRefCnt();
 
2129
    }
 
2130
  }
 
2131
  gfree(fonts);
 
2132
}
 
2133
 
 
2134
GfxFont *GfxFontDict::lookup(char *tag) {
 
2135
  int i;
 
2136
 
 
2137
  for (i = 0; i < numFonts; ++i) {
 
2138
    if (fonts[i] && fonts[i]->matches(tag)) {
 
2139
      return fonts[i];
 
2140
    }
 
2141
  }
 
2142
  return NULL;
 
2143
}