source: trunk/poppler/mypoppler/poppler/GfxFont.cc @ 461

Last change on this file since 461 was 461, checked in by Silvan Scherrer, 11 years ago

poppler update to 0.14.2

File size: 60.3 KB
Line 
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, 2010 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
57struct 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.
67static 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
121static 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
129GfxFont *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
165GfxFont::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
180GfxFont::~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
198void GfxFont::incRefCnt() {
199  refCnt++;
200}
201
202void GfxFont::decRefCnt() {
203  if (--refCnt == 0)
204    delete this;
205}
206
207void 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
420CharCodeToUnicode *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
446void 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
459char *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
487char *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
529Gfx8BitFont::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  char alpha;
545  Unicode toUnicode[256];
546  CharCodeToUnicode *utu, *ctu2;
547  Unicode uBuf[8];
548  double mul;
549  int firstChar, lastChar;
550  Gushort w;
551  Object obj1, obj2, obj3;
552  int n, i, a, b, m;
553
554  refCnt = 1;
555  type = typeA;
556  ctu = NULL;
557
558  // do font name substitution for various aliases of the Base 14 font
559  // names
560  if (name) {
561    name2 = name->copy();
562    i = 0;
563    while (i < name2->getLength()) {
564      if (name2->getChar(i) == ' ') {
565        name2->del(i);
566      } else {
567        ++i;
568      }
569    }
570    a = 0;
571    b = sizeof(stdFontMap) / sizeof(StdFontMapEntry);
572    // invariant: stdFontMap[a].altName <= name2 < stdFontMap[b].altName
573    while (b - a > 1) {
574      m = (a + b) / 2;
575      if (name2->cmp(stdFontMap[m].altName) >= 0) {
576        a = m;
577      } else {
578        b = m;
579      }
580    }
581    if (!name2->cmp(stdFontMap[a].altName)) {
582      name = new GooString(stdFontMap[a].properName);
583    }
584    delete name2;
585  }
586
587  // is it a built-in font?
588  builtinFont = NULL;
589  if (name) {
590    for (i = 0; i < nBuiltinFonts; ++i) {
591      if (!name->cmp(builtinFonts[i].name)) {
592        builtinFont = &builtinFonts[i];
593        break;
594      }
595    }
596  }
597
598  // default ascent/descent values
599  if (builtinFont) {
600    ascent = 0.001 * builtinFont->ascent;
601    descent = 0.001 * builtinFont->descent;
602    fontBBox[0] = 0.001 * builtinFont->bbox[0];
603    fontBBox[1] = 0.001 * builtinFont->bbox[1];
604    fontBBox[2] = 0.001 * builtinFont->bbox[2];
605    fontBBox[3] = 0.001 * builtinFont->bbox[3];
606  } else {
607    ascent = 0.95;
608    descent = -0.35;
609    fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
610  }
611
612  // get info from font descriptor
613  readFontDescriptor(xref, fontDict);
614
615  // for non-embedded fonts, don't trust the ascent/descent/bbox
616  // values from the font descriptor
617  if (builtinFont && embFontID.num < 0) {
618    ascent = 0.001 * builtinFont->ascent;
619    descent = 0.001 * builtinFont->descent;
620    fontBBox[0] = 0.001 * builtinFont->bbox[0];
621    fontBBox[1] = 0.001 * builtinFont->bbox[1];
622    fontBBox[2] = 0.001 * builtinFont->bbox[2];
623    fontBBox[3] = 0.001 * builtinFont->bbox[3];
624  }
625
626  // look for an external font file
627  findExtFontFile();
628
629  // get font matrix
630  fontMat[0] = fontMat[3] = 1;
631  fontMat[1] = fontMat[2] = fontMat[4] = fontMat[5] = 0;
632  if (fontDict->lookup("FontMatrix", &obj1)->isArray()) {
633    for (i = 0; i < 6 && i < obj1.arrayGetLength(); ++i) {
634      if (obj1.arrayGet(i, &obj2)->isNum()) {
635        fontMat[i] = obj2.getNum();
636      }
637      obj2.free();
638    }
639  }
640  obj1.free();
641
642  // get Type 3 bounding box, font definition, and resources
643  if (type == fontType3) {
644    if (fontDict->lookup("FontBBox", &obj1)->isArray()) {
645      for (i = 0; i < 4 && i < obj1.arrayGetLength(); ++i) {
646        if (obj1.arrayGet(i, &obj2)->isNum()) {
647          fontBBox[i] = obj2.getNum();
648        }
649        obj2.free();
650      }
651    }
652    obj1.free();
653    if (!fontDict->lookup("CharProcs", &charProcs)->isDict()) {
654      error(-1, "Missing or invalid CharProcs dictionary in Type 3 font");
655      charProcs.free();
656    }
657    if (!fontDict->lookup("Resources", &resources)->isDict()) {
658      resources.free();
659    }
660  }
661
662  //----- build the font encoding -----
663
664  // Encodings start with a base encoding, which can come from
665  // (in order of priority):
666  //   1. FontDict.Encoding or FontDict.Encoding.BaseEncoding
667  //        - MacRoman / MacExpert / WinAnsi / Standard
668  //   2. embedded or external font file
669  //   3. default:
670  //        - builtin --> builtin encoding
671  //        - TrueType --> WinAnsiEncoding
672  //        - others --> StandardEncoding
673  // and then add a list of differences (if any) from
674  // FontDict.Encoding.Differences.
675
676  // check FontDict for base encoding
677  hasEncoding = gFalse;
678  usesMacRomanEnc = gFalse;
679  baseEnc = NULL;
680  baseEncFromFontFile = gFalse;
681  fontDict->lookup("Encoding", &obj1);
682  if (obj1.isDict()) {
683    obj1.dictLookup("BaseEncoding", &obj2);
684    if (obj2.isName("MacRomanEncoding")) {
685      hasEncoding = gTrue;
686      usesMacRomanEnc = gTrue;
687      baseEnc = macRomanEncoding;
688    } else if (obj2.isName("MacExpertEncoding")) {
689      hasEncoding = gTrue;
690      baseEnc = macExpertEncoding;
691    } else if (obj2.isName("WinAnsiEncoding")) {
692      hasEncoding = gTrue;
693      baseEnc = winAnsiEncoding;
694    }
695    obj2.free();
696  } else if (obj1.isName("MacRomanEncoding")) {
697    hasEncoding = gTrue;
698    usesMacRomanEnc = gTrue;
699    baseEnc = macRomanEncoding;
700  } else if (obj1.isName("MacExpertEncoding")) {
701    hasEncoding = gTrue;
702    baseEnc = macExpertEncoding;
703  } else if (obj1.isName("WinAnsiEncoding")) {
704    hasEncoding = gTrue;
705    baseEnc = winAnsiEncoding;
706  }
707
708  // check embedded or external font file for base encoding
709  // (only for Type 1 fonts - trying to get an encoding out of a
710  // TrueType font is a losing proposition)
711  ffT1 = NULL;
712  ffT1C = NULL;
713  buf = NULL;
714  if (type == fontType1 && (extFontFile || embFontID.num >= 0)) {
715    if (extFontFile) {
716      ffT1 = FoFiType1::load(extFontFile->getCString());
717    } else {
718      buf = readEmbFontFile(xref, &len);
719      ffT1 = FoFiType1::make(buf, len);
720    }
721    if (ffT1) {
722      if (ffT1->getName()) {
723        if (embFontName) {
724          delete embFontName;
725        }
726        embFontName = new GooString(ffT1->getName());
727      }
728      if (!baseEnc) {
729        baseEnc = ffT1->getEncoding();
730        baseEncFromFontFile = gTrue;
731      }
732    }
733  } else if (type == fontType1C && (extFontFile || embFontID.num >= 0)) {
734    if (extFontFile) {
735      ffT1C = FoFiType1C::load(extFontFile->getCString());
736    } else {
737      buf = readEmbFontFile(xref, &len);
738      ffT1C = FoFiType1C::make(buf, len);
739    }
740    if (ffT1C) {
741      if (ffT1C->getName()) {
742        if (embFontName) {
743          delete embFontName;
744        }
745        embFontName = new GooString(ffT1C->getName());
746      }
747      if (!baseEnc) {
748        baseEnc = ffT1C->getEncoding();
749        baseEncFromFontFile = gTrue;
750      }
751    }
752  }
753  if (buf) {
754    gfree(buf);
755  }
756
757  // get default base encoding
758  if (!baseEnc) {
759    if (builtinFont && embFontID.num < 0) {
760      baseEnc = builtinFont->defaultBaseEnc;
761      hasEncoding = gTrue;
762    } else if (type == fontTrueType) {
763      baseEnc = winAnsiEncoding;
764    } else {
765      baseEnc = standardEncoding;
766    }
767  }
768
769  // copy the base encoding
770  for (i = 0; i < 256; ++i) {
771    enc[i] = baseEnc[i];
772    if ((encFree[i] = baseEncFromFontFile) && enc[i]) {
773      enc[i] = copyString(baseEnc[i]);
774    }
775  }
776
777  // some Type 1C font files have empty encodings, which can break the
778  // T1C->T1 conversion (since the 'seac' operator depends on having
779  // the accents in the encoding), so we fill in any gaps from
780  // StandardEncoding
781  if (type == fontType1C && (extFontFile || embFontID.num >= 0) &&
782      baseEncFromFontFile) {
783    for (i = 0; i < 256; ++i) {
784      if (!enc[i] && standardEncoding[i]) {
785        enc[i] = standardEncoding[i];
786        encFree[i] = gFalse;
787      }
788    }
789  }
790
791  // merge differences into encoding
792  if (obj1.isDict()) {
793    obj1.dictLookup("Differences", &obj2);
794    if (obj2.isArray()) {
795      hasEncoding = gTrue;
796      code = 0;
797      for (i = 0; i < obj2.arrayGetLength(); ++i) {
798        obj2.arrayGet(i, &obj3);
799        if (obj3.isInt()) {
800          code = obj3.getInt();
801        } else if (obj3.isName()) {
802          if (code >= 0 && code < 256) {
803            if (encFree[code]) {
804              gfree(enc[code]);
805            }
806            enc[code] = copyString(obj3.getName());
807            encFree[code] = gTrue;
808          }
809          ++code;
810        } else {
811          error(-1, "Wrong type in font encoding resource differences (%s)",
812                obj3.getTypeName());
813        }
814        obj3.free();
815      }
816    }
817    obj2.free();
818  }
819  obj1.free();
820  if (ffT1) {
821    delete ffT1;
822  }
823  if (ffT1C) {
824    delete ffT1C;
825  }
826
827  //----- build the mapping to Unicode -----
828
829  // pass 1: use the name-to-Unicode mapping table
830  missing = gFalse;
831  hex = gTrue;
832  alpha = -1;
833  for (code = 0; code < 256; ++code) {
834    if ((charName = enc[code])) {
835      if (!(toUnicode[code] = globalParams->mapNameToUnicode(charName)) &&
836          strcmp(charName, ".notdef")) {
837        // if it wasn't in the name-to-Unicode table, check for a
838        // name that looks like 'Axx' or 'xx', where 'A' is any letter
839        // and 'xx' is two hex digits. Be strict and assume that names are
840        // consistent (i.e. either all are 'Axx' or 'xx')
841    if (hex) {
842        if (strlen(charName) == 3 &&
843             isalpha(charName[0]) &&
844             isxdigit(charName[1]) && isxdigit(charName[2]) &&
845             ((charName[1] >= 'a' && charName[1] <= 'f') ||
846              (charName[1] >= 'A' && charName[1] <= 'F') ||
847              (charName[2] >= 'a' && charName[2] <= 'f') ||
848              (charName[2] >= 'A' && charName[2] <= 'F'))) {
849          if (alpha == -1)
850            alpha = charName[0];
851          else if (alpha != charName[0])
852            hex = gFalse;
853        } else
854        if (strlen(charName) == 2 &&
855             isxdigit(charName[0]) && isxdigit(charName[1]) &&
856             ((charName[0] >= 'a' && charName[0] <= 'f') ||
857              (charName[0] >= 'A' && charName[0] <= 'F') ||
858              (charName[1] >= 'a' && charName[1] <= 'f') ||
859              (charName[1] >= 'A' && charName[1] <= 'F'))) {
860          if (alpha == -1)
861            alpha = 0;
862          else if (alpha != 0)
863            hex = gFalse;
864        } else {
865            hex = gFalse;
866      }
867        }
868        missing = gTrue;
869      }
870    } else {
871      toUnicode[code] = 0;
872    }
873  }
874
875  // construct the char code -> Unicode mapping object
876  ctu = CharCodeToUnicode::make8BitToUnicode(toUnicode);
877
878  // pass 2: try to fill in the missing chars, looking for ligatures, numeric
879  // references and variants
880  if (missing) {
881    for (code = 0; code < 256; ++code) {
882      if (!toUnicode[code]) {
883        if ((charName = enc[code]) && strcmp(charName, ".notdef")
884            && (n = parseCharName(charName, uBuf, sizeof(uBuf)/sizeof(*uBuf), 
885                                  gFalse, // don't check simple names (pass 1)
886                                  gTrue, // do check ligatures
887                                  globalParams->getMapNumericCharNames(),
888                                  hex,
889                                  gTrue))) { // do check variants
890          ctu->setMapping((CharCode)code, uBuf, n);
891        } else if (globalParams->getMapUnknownCharNames()) {
892          // if the 'mapUnknownCharNames' flag is set, do a simple pass-through
893          // mapping for unknown character names
894          if (charName && charName[0]) {
895            for (n = 0; n < (int)(sizeof(uBuf)/sizeof(*uBuf)); ++n)
896              if (!(uBuf[n] = charName[n]))
897                break;
898            ctu->setMapping((CharCode)code, uBuf, n);
899          } else {
900            uBuf[0] = code;
901            ctu->setMapping((CharCode)code, uBuf, 1);
902          }
903        }
904      }
905    }
906  }
907
908  // merge in a ToUnicode CMap, if there is one -- this overwrites
909  // existing entries in ctu, i.e., the ToUnicode CMap takes
910  // precedence, but the other encoding info is allowed to fill in any
911  // holes
912  readToUnicodeCMap(fontDict, 8, ctu);
913
914  // look for a Unicode-to-Unicode mapping
915  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
916    Unicode *uAux;
917    for (i = 0; i < 256; ++i) {
918      toUnicode[i] = 0;
919    }
920    ctu2 = CharCodeToUnicode::make8BitToUnicode(toUnicode);
921    for (i = 0; i < 256; ++i) {
922      n = ctu->mapToUnicode((CharCode)i, &uAux);
923      if (n >= 1) {
924        n = utu->mapToUnicode((CharCode)uAux[0], &uAux);
925        if (n >= 1) {
926          ctu2->setMapping((CharCode)i, uAux, n);
927        }
928      }
929    }
930    utu->decRefCnt();
931    delete ctu;
932    ctu = ctu2;
933  }
934
935  //----- get the character widths -----
936
937  // initialize all widths
938  for (code = 0; code < 256; ++code) {
939    widths[code] = missingWidth * 0.001;
940  }
941
942  // use widths from font dict, if present
943  fontDict->lookup("FirstChar", &obj1);
944  firstChar = obj1.isInt() ? obj1.getInt() : 0;
945  obj1.free();
946  if (firstChar < 0 || firstChar > 255) {
947    firstChar = 0;
948  }
949  fontDict->lookup("LastChar", &obj1);
950  lastChar = obj1.isInt() ? obj1.getInt() : 255;
951  obj1.free();
952  if (lastChar < 0 || lastChar > 255) {
953    lastChar = 255;
954  }
955  mul = (type == fontType3) ? fontMat[0] : 0.001;
956  fontDict->lookup("Widths", &obj1);
957  if (obj1.isArray()) {
958    flags |= fontFixedWidth;
959    if (obj1.arrayGetLength() < lastChar - firstChar + 1) {
960      lastChar = firstChar + obj1.arrayGetLength() - 1;
961    }
962    for (code = firstChar; code <= lastChar; ++code) {
963      obj1.arrayGet(code - firstChar, &obj2);
964      if (obj2.isNum()) {
965        widths[code] = obj2.getNum() * mul;
966        if (widths[code] != widths[firstChar]) {
967          flags &= ~fontFixedWidth;
968        }
969      }
970      obj2.free();
971    }
972
973  // use widths from built-in font
974  } else if (builtinFont) {
975    // this is a kludge for broken PDF files that encode char 32
976    // as .notdef
977    if (builtinFont->widths->getWidth("space", &w)) {
978      widths[32] = 0.001 * w;
979    }
980    for (code = 0; code < 256; ++code) {
981      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
982        widths[code] = 0.001 * w;
983      }
984    }
985
986  // couldn't find widths -- use defaults
987  } else {
988    // this is technically an error -- the Widths entry is required
989    // for all but the Base-14 fonts -- but certain PDF generators
990    // apparently don't include widths for Arial and TimesNewRoman
991    if (isFixedWidth()) {
992      i = 0;
993    } else if (isSerif()) {
994      i = 8;
995    } else {
996      i = 4;
997    }
998    if (isBold()) {
999      i += 2;
1000    }
1001    if (isItalic()) {
1002      i += 1;
1003    }
1004    builtinFont = builtinFontSubst[i];
1005    // this is a kludge for broken PDF files that encode char 32
1006    // as .notdef
1007    if (builtinFont->widths->getWidth("space", &w)) {
1008      widths[32] = 0.001 * w;
1009    }
1010    for (code = 0; code < 256; ++code) {
1011      if (enc[code] && builtinFont->widths->getWidth(enc[code], &w)) {
1012        widths[code] = 0.001 * w;
1013      }
1014    }
1015  }
1016  obj1.free();
1017
1018  ok = gTrue;
1019}
1020
1021Gfx8BitFont::~Gfx8BitFont() {
1022  int i;
1023
1024  for (i = 0; i < 256; ++i) {
1025    if (encFree[i] && enc[i]) {
1026      gfree(enc[i]);
1027    }
1028  }
1029  ctu->decRefCnt();
1030  if (charProcs.isDict()) {
1031    charProcs.free();
1032  }
1033  if (resources.isDict()) {
1034    resources.free();
1035  }
1036}
1037
1038// This function is in part a derived work of the Adobe Glyph Mapping
1039// Convention: http://www.adobe.com/devnet/opentype/archives/glyph.html
1040// Algorithmic comments are excerpted from that document to aid
1041// maintainability.
1042static int parseCharName(char *charName, Unicode *uBuf, int uLen,
1043                         GBool names, GBool ligatures,
1044                         GBool numeric, GBool hex, GBool variants)
1045{
1046  if (uLen <= 0) {
1047    error(-1, "Zero-length output buffer (recursion overflow?) in "
1048          "parseCharName, component \"%s\"", charName);
1049    return 0;
1050  }
1051  // Step 1: drop all the characters from the glyph name starting with the
1052  // first occurrence of a period (U+002E FULL STOP), if any.
1053  if (variants) {
1054    char *var_part = strchr(charName, '.');
1055    if (var_part == charName) {
1056      return 0; // .notdef or similar
1057    } else if (var_part != NULL) {
1058      // parse names of the form 7.oldstyle, P.swash, s.sc, etc.
1059      char *main_part = gstrndup(charName, var_part - charName);
1060      GBool namesRecurse = gTrue, variantsRecurse = gFalse;
1061      int n = parseCharName(main_part, uBuf, uLen, namesRecurse, ligatures,
1062                            numeric, hex, variantsRecurse);
1063      gfree(main_part);
1064      return n;
1065    }
1066  }
1067  // Step 2: split the remaining string into a sequence of components, using
1068  // underscore (U+005F LOW LINE) as the delimiter.
1069  if (ligatures && strchr(charName, '_')) {
1070    // parse names of the form A_a (e.g. f_i, T_h, l_quotesingle)
1071    char *lig_part, *lig_end, *lig_copy;
1072    int n = 0, m;
1073    lig_part = lig_copy = copyString(charName);
1074    do {
1075      if ((lig_end = strchr(lig_part, '_')))
1076        *lig_end = '\0';
1077      if (lig_part[0] != '\0') {
1078        GBool namesRecurse = gTrue, ligaturesRecurse = gFalse;
1079        if ((m = parseCharName(lig_part, uBuf + n, uLen - n, namesRecurse,
1080                               ligaturesRecurse, numeric, hex, variants)))
1081          n += m;
1082        else
1083          error(-1, "Could not parse ligature component \"%s\" of \"%s\" in "
1084                "parseCharName", lig_part, charName);
1085      }
1086      lig_part = lig_end + 1;
1087    } while (lig_end && n < uLen);
1088    gfree(lig_copy);
1089    return n;
1090  }
1091  // Step 3: map each component to a character string according to the
1092  // procedure below, and concatenate those strings; the result is the
1093  // character string to which the glyph name is mapped.
1094  // 3.1. if the font is Zapf Dingbats (PostScript FontName ZapfDingbats), and
1095  // the component is in the ZapfDingbats list, then map it to the
1096  // corresponding character in that list.
1097  // 3.2. otherwise, if the component is in the Adobe Glyph List, then map it
1098  // to the corresponding character in that list.
1099  if (names && (uBuf[0] = globalParams->mapNameToUnicode(charName))) {
1100    return 1;
1101  }
1102  if (numeric) {
1103    unsigned int n = strlen(charName);
1104    // 3.3. otherwise, if the component is of the form "uni" (U+0075 U+006E
1105    // U+0069) followed by a sequence of uppercase hexadecimal digits (0 .. 9,
1106    // A .. F, i.e. U+0030 .. U+0039, U+0041 .. U+0046), the length of that
1107    // sequence is a multiple of four, and each group of four digits represents
1108    // a number in the set {0x0000 .. 0xD7FF, 0xE000 .. 0xFFFF}, then interpret
1109    // each such number as a Unicode scalar value and map the component to the
1110    // string made of those scalar values. Note that the range and digit length
1111    // restrictions mean that the "uni" prefix can be used only with Unicode
1112    // values from the Basic Multilingual Plane (BMP).
1113    if (n >= 7 && (n % 4) == 3 && !strncmp(charName, "uni", 3)) {
1114      int i;
1115      unsigned int m;
1116      for (i = 0, m = 3; i < uLen && m < n; m += 4) {
1117        if (isxdigit(charName[m]) && isxdigit(charName[m + 1]) && 
1118            isxdigit(charName[m + 2]) && isxdigit(charName[m + 3])) {
1119          unsigned int u;
1120          sscanf(charName + m, "%4x", &u);
1121          if (u <= 0xD7FF || (0xE000 <= u && u <= 0xFFFF)) {
1122            uBuf[i++] = u;
1123          }
1124        }
1125      }
1126      return i;
1127    }
1128    // 3.4. otherwise, if the component is of the form "u" (U+0075) followed by
1129    // a sequence of four to six uppercase hexadecimal digits {0 .. 9, A .. F}
1130    // (U+0030 .. U+0039, U+0041 .. U+0046), and those digits represent a
1131    // number in {0x0000 .. 0xD7FF, 0xE000 .. 0x10FFFF}, then interpret this
1132    // number as a Unicode scalar value and map the component to the string
1133    // made of this scalar value.
1134    if (n >= 5 && n <= 7 && charName[0] == 'u' && isxdigit(charName[1]) &&
1135        isxdigit(charName[2]) && isxdigit(charName[3]) && isxdigit(charName[4])
1136        && (n <= 5 || isxdigit(charName[5]))
1137        && (n <= 6 || isxdigit(charName[6]))) {
1138      unsigned int u;
1139      sscanf(charName + 1, "%x", &u);
1140      if (u <= 0xD7FF || (0xE000 <= u && u <= 0x10FFFF)) {
1141        uBuf[0] = u;
1142        return 1;
1143      }
1144    }
1145    // Not in Adobe Glyph Mapping convention: look for names of the form 'Axx',
1146    // 'xx', 'Ann', 'ABnn', or 'nn', where 'A' and 'B' are any letters, 'xx' is
1147    // two hex digits, and 'nn' is 2-4 decimal digits
1148    if (hex && n == 3 && isalpha(charName[0]) &&
1149        isxdigit(charName[1]) && isxdigit(charName[2])) {
1150      sscanf(charName+1, "%x", (unsigned int *)uBuf);
1151      return 1;
1152    } else if (hex && n == 2 &&
1153               isxdigit(charName[0]) && isxdigit(charName[1])) {
1154      sscanf(charName, "%x", (unsigned int *)uBuf);
1155      return 1;
1156    } else if (!hex && n >= 2 && n <= 4 &&
1157               isdigit(charName[0]) && isdigit(charName[1])) {
1158      uBuf[0] = (Unicode)atoi(charName);
1159      return 1;
1160    } else if (n >= 3 && n <= 5 &&
1161               isdigit(charName[1]) && isdigit(charName[2])) {
1162      uBuf[0] = (Unicode)atoi(charName+1);
1163      return 1;
1164    } else if (n >= 4 && n <= 6 &&
1165               isdigit(charName[2]) && isdigit(charName[3])) {
1166      uBuf[0] = (Unicode)atoi(charName+2);
1167      return 1;
1168    }
1169  }
1170  // 3.5. otherwise, map the component to the empty string
1171  return 0;
1172}
1173
1174int Gfx8BitFont::getNextChar(char *s, int len, CharCode *code,
1175                             Unicode **u, int *uLen,
1176                             double *dx, double *dy, double *ox, double *oy) {
1177  CharCode c;
1178
1179  *code = c = (CharCode)(*s & 0xff);
1180  *uLen = ctu->mapToUnicode(c, u);
1181  *dx = widths[c];
1182  *dy = *ox = *oy = 0;
1183  return 1;
1184}
1185
1186CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
1187  ctu->incRefCnt();
1188  return ctu;
1189}
1190
1191Gushort *Gfx8BitFont::getCodeToGIDMap(FoFiTrueType *ff) {
1192  Gushort *map;
1193  int cmapPlatform, cmapEncoding;
1194  int unicodeCmap, macRomanCmap, msSymbolCmap, cmap;
1195  GBool useMacRoman, useUnicode;
1196  char *charName;
1197  Unicode u;
1198  int code, i, n;
1199
1200  map = (Gushort *)gmallocn(256, sizeof(Gushort));
1201  for (i = 0; i < 256; ++i) {
1202    map[i] = 0;
1203  }
1204
1205  // To match up with the Adobe-defined behaviour, we choose a cmap
1206  // like this:
1207  // 1. If the PDF font has an encoding:
1208  //    1a. If the PDF font specified MacRomanEncoding and the
1209  //        TrueType font has a Macintosh Roman cmap, use it, and
1210  //        reverse map the char names through MacRomanEncoding to
1211  //        get char codes.
1212  //    1b. If the TrueType font has a Microsoft Unicode cmap or a
1213  //        non-Microsoft Unicode cmap, use it, and use the Unicode
1214  //        indexes, not the char codes.
1215  //    1c. If the PDF font is symbolic and the TrueType font has a
1216  //        Microsoft Symbol cmap, use it, and use char codes
1217  //        directly (possibly with an offset of 0xf000).
1218  //    1d. If the TrueType font has a Macintosh Roman cmap, use it,
1219  //        as in case 1a.
1220  // 2. If the PDF font does not have an encoding or the PDF font is
1221  //    symbolic:
1222  //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
1223  //        and use char codes directly (possibly with an offset of
1224  //        0xf000).
1225  //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
1226  //        and use char codes directly (possible with an offset of
1227  //        0xf000).
1228  // 3. If none of these rules apply, use the first cmap and hope for
1229  //    the best (this shouldn't happen).
1230  unicodeCmap = macRomanCmap = msSymbolCmap = -1;
1231  for (i = 0; i < ff->getNumCmaps(); ++i) {
1232    cmapPlatform = ff->getCmapPlatform(i);
1233    cmapEncoding = ff->getCmapEncoding(i);
1234    if ((cmapPlatform == 3 && cmapEncoding == 1) ||
1235        cmapPlatform == 0) {
1236      unicodeCmap = i;
1237    } else if (cmapPlatform == 1 && cmapEncoding == 0) {
1238      macRomanCmap = i;
1239    } else if (cmapPlatform == 3 && cmapEncoding == 0) {
1240      msSymbolCmap = i;
1241    }
1242  }
1243  cmap = 0;
1244  useMacRoman = gFalse;
1245  useUnicode = gFalse;
1246  if (hasEncoding) {
1247    if (usesMacRomanEnc && macRomanCmap >= 0) {
1248      cmap = macRomanCmap;
1249      useMacRoman = gTrue;
1250    } else if (unicodeCmap >= 0) {
1251      cmap = unicodeCmap;
1252      useUnicode = gTrue;
1253    } else if ((flags & fontSymbolic) && msSymbolCmap >= 0) {
1254      cmap = msSymbolCmap;
1255    } else if ((flags & fontSymbolic) && macRomanCmap >= 0) {
1256      cmap = macRomanCmap;
1257    } else if (macRomanCmap >= 0) {
1258      cmap = macRomanCmap;
1259      useMacRoman = gTrue;
1260    }
1261  } else {
1262    if (msSymbolCmap >= 0) {
1263      cmap = msSymbolCmap;
1264    } else if (macRomanCmap >= 0) {
1265      cmap = macRomanCmap;
1266    }
1267  }
1268
1269  // reverse map the char names through MacRomanEncoding, then map the
1270  // char codes through the cmap
1271  if (useMacRoman) {
1272    for (i = 0; i < 256; ++i) {
1273      if ((charName = enc[i])) {
1274        if ((code = globalParams->getMacRomanCharCode(charName))) {
1275          map[i] = ff->mapCodeToGID(cmap, code);
1276        }
1277      }
1278    }
1279
1280  // map Unicode through the cmap
1281  } else if (useUnicode) {
1282    Unicode *uAux;
1283    for (i = 0; i < 256; ++i) {
1284      if (((charName = enc[i]) && (u = globalParams->mapNameToUnicode(charName))))
1285        map[i] = ff->mapCodeToGID(cmap, u);
1286      else
1287      {
1288        n = ctu->mapToUnicode((CharCode)i, &uAux);
1289        if (n > 0) map[i] = ff->mapCodeToGID(cmap, uAux[0]);
1290      }
1291    }
1292
1293  // map the char codes through the cmap, possibly with an offset of
1294  // 0xf000
1295  } else {
1296    for (i = 0; i < 256; ++i) {
1297      if (!(map[i] = ff->mapCodeToGID(cmap, i))) {
1298        map[i] = ff->mapCodeToGID(cmap, 0xf000 + i);
1299      }
1300    }
1301  }
1302
1303  // try the TrueType 'post' table to handle any unmapped characters
1304  for (i = 0; i < 256; ++i) {
1305    if (!map[i] && (charName = enc[i])) {
1306      map[i] = (Gushort)(int)ff->mapNameToGID(charName);
1307    }
1308  }
1309
1310  return map;
1311}
1312
1313Dict *Gfx8BitFont::getCharProcs() {
1314  return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
1315}
1316
1317Object *Gfx8BitFont::getCharProc(int code, Object *proc) {
1318  if (enc[code] && charProcs.isDict()) {
1319    charProcs.dictLookup(enc[code], proc);
1320  } else {
1321    proc->initNull();
1322  }
1323  return proc;
1324}
1325
1326Dict *Gfx8BitFont::getResources() {
1327  return resources.isDict() ? resources.getDict() : (Dict *)NULL;
1328}
1329
1330//------------------------------------------------------------------------
1331// GfxCIDFont
1332//------------------------------------------------------------------------
1333
1334static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
1335  return ((GfxFontCIDWidthExcep *)w1)->first -
1336         ((GfxFontCIDWidthExcep *)w2)->first;
1337}
1338
1339static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
1340  return ((GfxFontCIDWidthExcepV *)w1)->first -
1341         ((GfxFontCIDWidthExcepV *)w2)->first;
1342}
1343
1344GfxCIDFont::GfxCIDFont(XRef *xref, char *tagA, Ref idA, GooString *nameA,
1345                       Dict *fontDict):
1346  GfxFont(tagA, idA, nameA)
1347{
1348  Dict *desFontDict;
1349  GooString *collection, *cMapName;
1350  Object desFontDictObj;
1351  Object obj1, obj2, obj3, obj4, obj5, obj6;
1352  CharCodeToUnicode *utu;
1353  CharCode c;
1354  Unicode *uBuf;
1355  int c1, c2;
1356  int excepsSize, i, j, k, n;
1357
1358  refCnt = 1;
1359  ascent = 0.95;
1360  descent = -0.35;
1361  fontBBox[0] = fontBBox[1] = fontBBox[2] = fontBBox[3] = 0;
1362  cMap = NULL;
1363  ctu = NULL;
1364  widths.defWidth = 1.0;
1365  widths.defHeight = -1.0;
1366  widths.defVY = 0.880;
1367  widths.exceps = NULL;
1368  widths.nExceps = 0;
1369  widths.excepsV = NULL;
1370  widths.nExcepsV = 0;
1371  cidToGID = NULL;
1372  cidToGIDLen = 0;
1373
1374  // get the descendant font
1375  if (!fontDict->lookup("DescendantFonts", &obj1)->isArray()) {
1376    error(-1, "Missing DescendantFonts entry in Type 0 font");
1377    obj1.free();
1378    goto err1;
1379  }
1380  if (!obj1.arrayGet(0, &desFontDictObj)->isDict()) {
1381    error(-1, "Bad descendant font in Type 0 font");
1382    goto err3;
1383  }
1384  obj1.free();
1385  desFontDict = desFontDictObj.getDict();
1386
1387  // font type
1388  if (!desFontDict->lookup("Subtype", &obj1)) {
1389    error(-1, "Missing Subtype entry in Type 0 descendant font");
1390    goto err3;
1391  }
1392  if (obj1.isName("CIDFontType0")) {
1393    type = fontCIDType0;
1394  } else if (obj1.isName("CIDFontType2")) {
1395    type = fontCIDType2;
1396  } else {
1397    error(-1, "Unknown Type 0 descendant font type '%s'",
1398          obj1.isName() ? obj1.getName() : "???");
1399    goto err3;
1400  }
1401  obj1.free();
1402
1403  // get info from font descriptor
1404  readFontDescriptor(xref, desFontDict);
1405
1406  // look for an external font file
1407  findExtFontFile();
1408
1409  //----- encoding info -----
1410
1411  // char collection
1412  if (!desFontDict->lookup("CIDSystemInfo", &obj1)->isDict()) {
1413    error(-1, "Missing CIDSystemInfo dictionary in Type 0 descendant font");
1414    goto err3;
1415  }
1416  obj1.dictLookup("Registry", &obj2);
1417  obj1.dictLookup("Ordering", &obj3);
1418  if (!obj2.isString() || !obj3.isString()) {
1419    error(-1, "Invalid CIDSystemInfo dictionary in Type 0 descendant font");
1420    goto err4;
1421  }
1422  collection = obj2.getString()->copy()->append('-')->append(obj3.getString());
1423  obj3.free();
1424  obj2.free();
1425  obj1.free();
1426
1427  // look for a ToUnicode CMap
1428  if (!(ctu = readToUnicodeCMap(fontDict, 16, NULL))) {
1429
1430    // the "Adobe-Identity" and "Adobe-UCS" collections don't have
1431    // cidToUnicode files
1432    if (collection->cmp("Adobe-Identity") &&
1433        collection->cmp("Adobe-UCS")) {
1434
1435      // look for a user-supplied .cidToUnicode file
1436      if (!(ctu = globalParams->getCIDToUnicode(collection))) {
1437        // I'm not completely sure that this is the best thing to do
1438        // but it seems to produce better results when the .cidToUnicode
1439        // files from the poppler-data package are missing. At least
1440        // we know that assuming the Identity mapping is definitely wrong.
1441        //   -- jrmuizel
1442        static const char * knownCollections [] = {
1443          "Adobe-CNS1",
1444          "Adobe-GB1",
1445          "Adobe-Japan1",
1446          "Adobe-Japan2",
1447          "Adobe-Korea1",
1448        };
1449        for (size_t i = 0; i < sizeof(knownCollections)/sizeof(knownCollections[0]); i++) {
1450          if (collection->cmp(knownCollections[i]) == 0) {
1451            error(-1, "Missing language pack for '%s' mapping", collection->getCString());
1452            delete collection;
1453            goto err2;
1454          }
1455        }
1456        error(-1, "Unknown character collection '%s'",
1457              collection->getCString());
1458        // fall-through, assuming the Identity mapping -- this appears
1459        // to match Adobe's behavior
1460      }
1461    }
1462  }
1463
1464  // look for a Unicode-to-Unicode mapping
1465  if (name && (utu = globalParams->getUnicodeToUnicode(name))) {
1466    if (ctu) {
1467      for (c = 0; c < ctu->getLength(); ++c) {
1468        n = ctu->mapToUnicode(c, &uBuf);
1469        if (n >= 1) {
1470          n = utu->mapToUnicode((CharCode)uBuf[0], &uBuf);
1471          if (n >= 1) {
1472            ctu->setMapping(c, uBuf, n);
1473          }
1474        }
1475      }
1476      utu->decRefCnt();
1477    } else {
1478      ctu = utu;
1479    }
1480  }
1481
1482  // encoding (i.e., CMap)
1483  //~ also need to deal with the UseCMap entry in the stream dict
1484  if (!fontDict->lookup("Encoding", &obj1)->isName()) {
1485    GBool success = gFalse;
1486    if (obj1.isStream()) {
1487      Object objName;
1488      Stream *s = obj1.getStream();
1489      s->getDict()->lookup("CMapName", &objName);
1490      if (objName.isName())
1491      {
1492        cMapName = new GooString(objName.getName());
1493        cMap = globalParams->getCMap(collection, cMapName, s);
1494        success = gTrue;
1495      }
1496      objName.free();
1497    }
1498   
1499    if (!success) {
1500      error(-1, "Missing or invalid Encoding entry in Type 0 font");
1501      delete collection;
1502      goto err3;
1503    }
1504  } else {
1505    cMapName = new GooString(obj1.getName());
1506    cMap = globalParams->getCMap(collection, cMapName);
1507  }
1508  if (!cMap) {
1509      error(-1, "Unknown CMap '%s' for character collection '%s'",
1510            cMapName->getCString(), collection->getCString());
1511      delete collection;
1512      delete cMapName;
1513      goto err2;
1514    }
1515  delete collection;
1516  delete cMapName;
1517  obj1.free();
1518
1519  // CIDToGIDMap (for embedded TrueType fonts)
1520  if (type == fontCIDType2 || type == fontCIDType2OT) {
1521    desFontDict->lookup("CIDToGIDMap", &obj1);
1522    if (obj1.isStream()) {
1523      cidToGIDLen = 0;
1524      i = 64;
1525      cidToGID = (Gushort *)gmallocn(i, sizeof(Gushort));
1526      obj1.streamReset();
1527      while ((c1 = obj1.streamGetChar()) != EOF &&
1528             (c2 = obj1.streamGetChar()) != EOF) {
1529        if (cidToGIDLen == i) {
1530          i *= 2;
1531          cidToGID = (Gushort *)greallocn(cidToGID, i, sizeof(Gushort));
1532        }
1533        cidToGID[cidToGIDLen++] = (Gushort)((c1 << 8) + c2);
1534      }
1535    } else if (!obj1.isName("Identity") && !obj1.isNull()) {
1536      error(-1, "Invalid CIDToGIDMap entry in CID font");
1537    }
1538    obj1.free();
1539  }
1540
1541  //----- character metrics -----
1542
1543  // default char width
1544  if (desFontDict->lookup("DW", &obj1)->isInt()) {
1545    widths.defWidth = obj1.getInt() * 0.001;
1546  }
1547  obj1.free();
1548
1549  // char width exceptions
1550  if (desFontDict->lookup("W", &obj1)->isArray()) {
1551    excepsSize = 0;
1552    i = 0;
1553    while (i + 1 < obj1.arrayGetLength()) {
1554      obj1.arrayGet(i, &obj2);
1555      obj1.arrayGet(i + 1, &obj3);
1556      if (obj2.isInt() && obj3.isInt() && i + 2 < obj1.arrayGetLength()) {
1557        if (obj1.arrayGet(i + 2, &obj4)->isNum()) {
1558          if (widths.nExceps == excepsSize) {
1559            excepsSize += 16;
1560            widths.exceps = (GfxFontCIDWidthExcep *)
1561              greallocn(widths.exceps,
1562                        excepsSize, sizeof(GfxFontCIDWidthExcep));
1563          }
1564          widths.exceps[widths.nExceps].first = obj2.getInt();
1565          widths.exceps[widths.nExceps].last = obj3.getInt();
1566          widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
1567          ++widths.nExceps;
1568        } else {
1569          error(-1, "Bad widths array in Type 0 font");
1570        }
1571        obj4.free();
1572        i += 3;
1573      } else if (obj2.isInt() && obj3.isArray()) {
1574        if (widths.nExceps + obj3.arrayGetLength() > excepsSize) {
1575          excepsSize = (widths.nExceps + obj3.arrayGetLength() + 15) & ~15;
1576          widths.exceps = (GfxFontCIDWidthExcep *)
1577            greallocn(widths.exceps,
1578                      excepsSize, sizeof(GfxFontCIDWidthExcep));
1579        }
1580        j = obj2.getInt();
1581        for (k = 0; k < obj3.arrayGetLength(); ++k) {
1582          if (obj3.arrayGet(k, &obj4)->isNum()) {
1583            widths.exceps[widths.nExceps].first = j;
1584            widths.exceps[widths.nExceps].last = j;
1585            widths.exceps[widths.nExceps].width = obj4.getNum() * 0.001;
1586            ++j;
1587            ++widths.nExceps;
1588          } else {
1589            error(-1, "Bad widths array in Type 0 font");
1590          }
1591          obj4.free();
1592        }
1593        i += 2;
1594      } else {
1595        error(-1, "Bad widths array in Type 0 font");
1596        ++i;
1597      }
1598      obj3.free();
1599      obj2.free();
1600    }
1601    qsort(widths.exceps, widths.nExceps, sizeof(GfxFontCIDWidthExcep),
1602          &cmpWidthExcep);
1603  }
1604  obj1.free();
1605
1606  // default metrics for vertical font
1607  if (desFontDict->lookup("DW2", &obj1)->isArray() &&
1608      obj1.arrayGetLength() == 2) {
1609    if (obj1.arrayGet(0, &obj2)->isNum()) {
1610      widths.defVY = obj2.getNum() * 0.001;
1611    }
1612    obj2.free();
1613    if (obj1.arrayGet(1, &obj2)->isNum()) {
1614      widths.defHeight = obj2.getNum() * 0.001;
1615    }
1616    obj2.free();
1617  }
1618  obj1.free();
1619
1620  // char metric exceptions for vertical font
1621  if (desFontDict->lookup("W2", &obj1)->isArray()) {
1622    excepsSize = 0;
1623    i = 0;
1624    while (i + 1 < obj1.arrayGetLength()) {
1625      obj1.arrayGet(i, &obj2);
1626      obj1.arrayGet(i+ 1, &obj3);
1627      if (obj2.isInt() && obj3.isInt() && i + 4 < obj1.arrayGetLength()) {
1628        if (obj1.arrayGet(i + 2, &obj4)->isNum() &&
1629            obj1.arrayGet(i + 3, &obj5)->isNum() &&
1630            obj1.arrayGet(i + 4, &obj6)->isNum()) {
1631          if (widths.nExcepsV == excepsSize) {
1632            excepsSize += 16;
1633            widths.excepsV = (GfxFontCIDWidthExcepV *)
1634              greallocn(widths.excepsV,
1635                        excepsSize, sizeof(GfxFontCIDWidthExcepV));
1636          }
1637          widths.excepsV[widths.nExcepsV].first = obj2.getInt();
1638          widths.excepsV[widths.nExcepsV].last = obj3.getInt();
1639          widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
1640          widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
1641          widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
1642          ++widths.nExcepsV;
1643        } else {
1644          error(-1, "Bad widths (W2) array in Type 0 font");
1645        }
1646        obj6.free();
1647        obj5.free();
1648        obj4.free();
1649        i += 5;
1650      } else if (obj2.isInt() && obj3.isArray()) {
1651        if (widths.nExcepsV + obj3.arrayGetLength() / 3 > excepsSize) {
1652          excepsSize =
1653            (widths.nExcepsV + obj3.arrayGetLength() / 3 + 15) & ~15;
1654          widths.excepsV = (GfxFontCIDWidthExcepV *)
1655            greallocn(widths.excepsV,
1656                      excepsSize, sizeof(GfxFontCIDWidthExcepV));
1657        }
1658        j = obj2.getInt();
1659        for (k = 0; k < obj3.arrayGetLength(); k += 3) {
1660          if (obj3.arrayGet(k, &obj4)->isNum() &&
1661              obj3.arrayGet(k+1, &obj5)->isNum() &&
1662              obj3.arrayGet(k+2, &obj6)->isNum()) {
1663            widths.excepsV[widths.nExcepsV].first = j;
1664            widths.excepsV[widths.nExcepsV].last = j;
1665            widths.excepsV[widths.nExcepsV].height = obj4.getNum() * 0.001;
1666            widths.excepsV[widths.nExcepsV].vx = obj5.getNum() * 0.001;
1667            widths.excepsV[widths.nExcepsV].vy = obj6.getNum() * 0.001;
1668            ++j;
1669            ++widths.nExcepsV;
1670          } else {
1671            error(-1, "Bad widths (W2) array in Type 0 font");
1672          }
1673          obj6.free();
1674          obj5.free();
1675          obj4.free();
1676        }
1677        i += 2;
1678      } else {
1679        error(-1, "Bad widths (W2) array in Type 0 font");
1680        ++i;
1681      }
1682      obj3.free();
1683      obj2.free();
1684    }
1685    qsort(widths.excepsV, widths.nExcepsV, sizeof(GfxFontCIDWidthExcepV),
1686          &cmpWidthExcepV);
1687  }
1688  obj1.free();
1689
1690  desFontDictObj.free();
1691  ok = gTrue;
1692  return;
1693
1694 err4:
1695  obj3.free();
1696  obj2.free();
1697 err3:
1698  obj1.free();
1699 err2:
1700  desFontDictObj.free();
1701 err1:;
1702}
1703
1704GfxCIDFont::~GfxCIDFont() {
1705  if (cMap) {
1706    cMap->decRefCnt();
1707  }
1708  if (ctu) {
1709    ctu->decRefCnt();
1710  }
1711  gfree(widths.exceps);
1712  gfree(widths.excepsV);
1713  if (cidToGID) {
1714    gfree(cidToGID);
1715  }
1716}
1717
1718int GfxCIDFont::getNextChar(char *s, int len, CharCode *code,
1719                            Unicode **u, int *uLen,
1720                            double *dx, double *dy, double *ox, double *oy) {
1721  CID cid;
1722  double w, h, vx, vy;
1723  int n, a, b, m;
1724
1725  if (!cMap) {
1726    *code = 0;
1727    *uLen = 0;
1728    *dx = *dy = 0;
1729    return 1;
1730  }
1731
1732  *code = (CharCode)(cid = cMap->getCID(s, len, &n));
1733  if (ctu) {
1734    *uLen = ctu->mapToUnicode(cid, u);
1735  } else {
1736    *uLen = 0;
1737  }
1738
1739  // horizontal
1740  if (cMap->getWMode() == 0) {
1741    w = widths.defWidth;
1742    h = vx = vy = 0;
1743    if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
1744      a = 0;
1745      b = widths.nExceps;
1746      // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
1747      while (b - a > 1) {
1748        m = (a + b) / 2;
1749        if (widths.exceps[m].first <= cid) {
1750          a = m;
1751        } else {
1752          b = m;
1753        }
1754      }
1755      if (cid <= widths.exceps[a].last) {
1756        w = widths.exceps[a].width;
1757      }
1758    }
1759
1760  // vertical
1761  } else {
1762    w = 0;
1763    h = widths.defHeight;
1764    vx = widths.defWidth / 2;
1765    vy = widths.defVY;
1766    if (widths.nExcepsV > 0 && cid >= widths.excepsV[0].first) {
1767      a = 0;
1768      b = widths.nExcepsV;
1769      // invariant: widths.excepsV[a].first <= cid < widths.excepsV[b].first
1770      while (b - a > 1) {
1771        m = (a + b) / 2;
1772        if (widths.excepsV[m].last <= cid) {
1773          a = m;
1774        } else {
1775          b = m;
1776        }
1777      }
1778      if (cid <= widths.excepsV[a].last) {
1779        h = widths.excepsV[a].height;
1780        vx = widths.excepsV[a].vx;
1781        vy = widths.excepsV[a].vy;
1782      }
1783    }
1784  }
1785
1786  *dx = w;
1787  *dy = h;
1788  *ox = vx;
1789  *oy = vy;
1790
1791  return n;
1792}
1793
1794int GfxCIDFont::getWMode() {
1795  return cMap ? cMap->getWMode() : 0;
1796}
1797
1798CharCodeToUnicode *GfxCIDFont::getToUnicode() {
1799  if (ctu) {
1800    ctu->incRefCnt();
1801  }
1802  return ctu;
1803}
1804
1805GooString *GfxCIDFont::getCollection() {
1806  return cMap ? cMap->getCollection() : (GooString *)NULL;
1807}
1808
1809Gushort GfxCIDFont::mapCodeToGID(FoFiTrueType *ff, int cmapi,
1810  Unicode unicode, GBool wmode) {
1811  Gushort gid = ff->mapCodeToGID(cmapi,unicode);
1812  if (wmode) {
1813    Gushort vgid = ff->mapToVertGID(gid);
1814    if (vgid != 0) gid = vgid;
1815  }
1816  return gid;
1817}
1818
1819Gushort *GfxCIDFont::getCodeToGIDMap(FoFiTrueType *ff, int *mapsizep) {
1820#define N_UCS_CANDIDATES 2
1821  /* space characters */
1822  static const unsigned long spaces[] = { 
1823    0x2000,0x2001,0x2002,0x2003,0x2004,0x2005,0x2006,0x2007,
1824    0x2008,0x2009,0x200A,0x00A0,0x200B,0x2060,0x3000,0xFEFF,
1825    0
1826  };
1827  static char *adobe_cns1_cmaps[] = {
1828    "UniCNS-UTF32-V",
1829    "UniCNS-UCS2-V",
1830    "UniCNS-UTF32-H",
1831    "UniCNS-UCS2-H",
1832    0
1833  };
1834  static char *adobe_gb1_cmaps[] = {
1835    "UniGB-UTF32-V",
1836    "UniGB-UCS2-V",
1837    "UniGB-UTF32-H",
1838    "UniGB-UCS2-H",
1839    0
1840  };
1841  static char *adobe_japan1_cmaps[] = {
1842    "UniJIS-UTF32-V",
1843    "UniJIS-UCS2-V",
1844    "UniJIS-UTF32-H",
1845    "UniJIS-UCS2-H",
1846    0
1847  };
1848  static char *adobe_japan2_cmaps[] = {
1849    "UniHojo-UTF32-V",
1850    "UniHojo-UCS2-V",
1851    "UniHojo-UTF32-H",
1852    "UniHojo-UCS2-H",
1853    0
1854  };
1855  static char *adobe_korea1_cmaps[] = {
1856    "UniKS-UTF32-V",
1857    "UniKS-UCS2-V",
1858    "UniKS-UTF32-H",
1859    "UniKS-UCS2-H",
1860    0
1861  };
1862  static struct CMapListEntry {
1863    char *collection;
1864    char *scriptTag;
1865    char *toUnicodeMap;
1866    char **CMaps;
1867  } CMapList[] = {
1868    {
1869      "Adobe-CNS1",
1870      "kana",
1871      "Adobe-CNS1-UCS2",
1872      adobe_cns1_cmaps,
1873    },
1874    {
1875      "Adobe-GB1",
1876      "kana",
1877      "Adobe-GB1-UCS2",
1878      adobe_gb1_cmaps,
1879    },
1880    {
1881      "Adobe-Japan1",
1882      "kana",
1883      "Adobe-Japan1-UCS2",
1884      adobe_japan1_cmaps,
1885    },
1886    {
1887      "Adobe-Japan2",
1888      "kana",
1889      "Adobe-Japan2-UCS2",
1890      adobe_japan2_cmaps,
1891    },
1892    {
1893      "Adobe-Korea1",
1894      "kana",
1895      "Adobe-Korea1-UCS2",
1896      adobe_korea1_cmaps,
1897    },
1898    {0, 0, 0, 0}
1899  };
1900  Unicode *humap = 0;
1901  Unicode *vumap = 0;
1902  Unicode *tumap = 0;
1903  Gushort *codeToGID = 0;
1904  unsigned long n;
1905  int i;
1906  unsigned long code;
1907  int wmode;
1908  char **cmapName;
1909  CMap *cMap;
1910  CMapListEntry *lp;
1911  int cmap;
1912  int cmapPlatform, cmapEncoding;
1913  Ref embID;
1914
1915  *mapsizep = 0;
1916  if (!ctu) return NULL;
1917  if (getCollection()->cmp("Adobe-Identity") == 0) return NULL;
1918  if (getEmbeddedFontID(&embID)) {
1919   /* if this font is embedded font,
1920    * CIDToGIDMap should be embedded in PDF file
1921    * and already set. So return it.
1922    */
1923    *mapsizep = getCIDToGIDLen();
1924    return getCIDToGID();
1925  }
1926
1927  /* we use only unicode cmap */
1928  cmap = -1;
1929  for (i = 0; i < ff->getNumCmaps(); ++i) {
1930    cmapPlatform = ff->getCmapPlatform(i);
1931    cmapEncoding = ff->getCmapEncoding(i);
1932    if (cmapPlatform == 3 && cmapEncoding == 10) {
1933        /* UCS-4 */
1934        cmap = i;
1935        /* use UCS-4 cmap */
1936        break;
1937    } else if (cmapPlatform == 3 && cmapEncoding == 1) {
1938        /* Unicode */
1939        cmap = i;
1940    } else if (cmapPlatform == 0 && cmap < 0) {
1941        cmap = i;
1942    }
1943  }
1944  if (cmap < 0)
1945    return NULL;
1946
1947  wmode = getWMode();
1948  for (lp = CMapList;lp->collection != 0;lp++) {
1949    if (strcmp(lp->collection,getCollection()->getCString()) == 0) {
1950      break;
1951    }
1952  }
1953  n = 65536;
1954  tumap = new Unicode[n];
1955  humap = new Unicode[n*N_UCS_CANDIDATES];
1956  memset(humap,0,sizeof(Unicode)*n*N_UCS_CANDIDATES);
1957  if (lp->collection != 0) {
1958    CharCodeToUnicode *tctu;
1959    GooString tname(lp->toUnicodeMap);
1960
1961    if ((tctu = CharCodeToUnicode::parseCMapFromFile(&tname,16)) != 0) {
1962      CharCode cid;
1963      for (cid = 0;cid < n ;cid++) {
1964        int len;
1965        Unicode *ucodes;
1966
1967        len = tctu->mapToUnicode(cid,&ucodes);
1968        if (len == 1) {
1969          tumap[cid] = ucodes[0];
1970        } else {
1971          /* if not single character, ignore it */
1972          tumap[cid] = 0;
1973        }
1974      }
1975      delete tctu;
1976    }
1977    vumap = new Unicode[n];
1978    memset(vumap,0,sizeof(Unicode)*n);
1979    for (cmapName = lp->CMaps;*cmapName != 0;cmapName++) {
1980      GooString cname(*cmapName);
1981
1982      if ((cMap = globalParams->getCMap(getCollection(),&cname))
1983           != 0) {
1984            if (cMap->getWMode()) {
1985                cMap->setReverseMap(vumap,n,1);
1986            } else {
1987                cMap->setReverseMap(humap,n,N_UCS_CANDIDATES);
1988            }
1989        cMap->decRefCnt();
1990      }
1991    }
1992    ff->setupGSUB(lp->scriptTag);
1993  } else {
1994    error(-1,"Unknown character collection %s\n",
1995      getCollection()->getCString());
1996    if ((ctu = getToUnicode()) != 0) {
1997      CharCode cid;
1998      for (cid = 0;cid < n ;cid++) {
1999        Unicode *ucode;
2000
2001        if (ctu->mapToUnicode(cid, &ucode))
2002          humap[cid*N_UCS_CANDIDATES] = ucode[0];
2003        else
2004          humap[cid*N_UCS_CANDIDATES] = 0;
2005        for (i = 1;i < N_UCS_CANDIDATES;i++) {
2006            humap[cid*N_UCS_CANDIDATES+i] = 0;
2007        }
2008      }
2009      ctu->decRefCnt();
2010    }
2011  }
2012  // map CID -> Unicode -> GID
2013  codeToGID = (Gushort *)gmallocn(n, sizeof(Gushort));
2014  for (code = 0; code < n; ++code) {
2015    Unicode unicode;
2016    unsigned long gid;
2017
2018    unicode = 0;
2019    gid = 0;
2020    if (humap != 0) {
2021      for (i = 0;i < N_UCS_CANDIDATES
2022        && gid == 0 && (unicode = humap[code*N_UCS_CANDIDATES+i]) != 0;i++) {
2023        gid = mapCodeToGID(ff,cmap,unicode,gFalse);
2024      }
2025    }
2026    if (gid == 0 && vumap != 0) {
2027      unicode = vumap[code];
2028      if (unicode != 0) {
2029        gid = mapCodeToGID(ff,cmap,unicode,gTrue);
2030        if (gid == 0 && tumap != 0) {
2031          if ((unicode = tumap[code]) != 0) {
2032            gid = mapCodeToGID(ff,cmap,unicode,gTrue);
2033          }
2034        }
2035      }
2036    }
2037    if (gid == 0 && tumap != 0) {
2038      if ((unicode = tumap[code]) != 0) {
2039        gid = mapCodeToGID(ff,cmap,unicode,gFalse);
2040      }
2041    }
2042    if (gid == 0) {
2043      /* special handling space characters */
2044      const unsigned long *p;
2045
2046      if (humap != 0) unicode = humap[code];
2047      if (unicode != 0) {
2048        /* check if code is space character , so map code to 0x0020 */
2049        for (p = spaces;*p != 0;p++) {
2050          if (*p == unicode) {
2051            unicode = 0x20;
2052            gid = mapCodeToGID(ff,cmap,unicode,wmode);
2053            break;
2054          }
2055        }
2056      }
2057    }
2058    codeToGID[code] = gid;
2059  }
2060  *mapsizep = n;
2061  if (humap != 0) delete[] humap;
2062  if (tumap != 0) delete[] tumap;
2063  if (vumap != 0) delete[] vumap;
2064  return codeToGID;
2065}
2066
2067double GfxCIDFont::getWidth (char* s, int len) {
2068  int nUsed;
2069  double w;
2070  int a, b, m;
2071
2072  CID cid = cMap->getCID(s, len, &nUsed);
2073
2074  w = widths.defWidth;
2075  if (widths.nExceps > 0 && cid >= widths.exceps[0].first) {
2076    a = 0;
2077    b = widths.nExceps;
2078    // invariant: widths.exceps[a].first <= cid < widths.exceps[b].first
2079    while (b - a > 1) {
2080      m = (a + b) / 2;
2081      if (widths.exceps[m].first <= cid) {
2082        a = m;
2083      } else {
2084        b = m;
2085      }
2086    }
2087    if (cid <= widths.exceps[a].last) {
2088      w = widths.exceps[a].width;
2089    }
2090  }
2091  return w;
2092}
2093
2094//------------------------------------------------------------------------
2095// GfxFontDict
2096//------------------------------------------------------------------------
2097
2098GfxFontDict::GfxFontDict(XRef *xref, Ref *fontDictRef, Dict *fontDict) {
2099  int i;
2100  Object obj1, obj2;
2101  Ref r;
2102
2103  numFonts = fontDict->getLength();
2104  fonts = (GfxFont **)gmallocn(numFonts, sizeof(GfxFont *));
2105  for (i = 0; i < numFonts; ++i) {
2106    fontDict->getValNF(i, &obj1);
2107    obj1.fetch(xref, &obj2);
2108    if (obj2.isDict()) {
2109      if (obj1.isRef()) {
2110        r = obj1.getRef();
2111      } else {
2112        // no indirect reference for this font, so invent a unique one
2113        // (legal generation numbers are five digits, so any 6-digit
2114        // number would be safe)
2115        r.num = i;
2116        if (fontDictRef) {
2117          r.gen = 100000 + fontDictRef->num;
2118        } else {
2119          r.gen = 999999;
2120        }
2121      }
2122      fonts[i] = GfxFont::makeFont(xref, fontDict->getKey(i),
2123                                   r, obj2.getDict());
2124      if (fonts[i] && !fonts[i]->isOk()) {
2125        // XXX: it may be meaningful to distinguish between
2126        // NULL and !isOk() so that when we do lookups
2127        // we can tell the difference between a missing font
2128        // and a font that is just !isOk()
2129        fonts[i]->decRefCnt();
2130        fonts[i] = NULL;
2131      }
2132    } else {
2133      error(-1, "font resource is not a dictionary");
2134      fonts[i] = NULL;
2135    }
2136    obj1.free();
2137    obj2.free();
2138  }
2139}
2140
2141GfxFontDict::~GfxFontDict() {
2142  int i;
2143
2144  for (i = 0; i < numFonts; ++i) {
2145    if (fonts[i]) {
2146      fonts[i]->decRefCnt();
2147    }
2148  }
2149  gfree(fonts);
2150}
2151
2152GfxFont *GfxFontDict::lookup(char *tag) {
2153  int i;
2154
2155  for (i = 0; i < numFonts; ++i) {
2156    if (fonts[i] && fonts[i]->matches(tag)) {
2157      return fonts[i];
2158    }
2159  }
2160  return NULL;
2161}
Note: See TracBrowser for help on using the repository browser.