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

Last change on this file since 277 was 277, checked in by rbri, 11 years ago

PDF plugin: Poppler library updated to version 0.12.3

File size: 59.9 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 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  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
1005Gfx8BitFont::~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.
1026static 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
1158int 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
1170CharCodeToUnicode *Gfx8BitFont::getToUnicode() {
1171  ctu->incRefCnt();
1172  return ctu;
1173}
1174
1175Gushort *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
1297Dict *Gfx8BitFont::getCharProcs() {
1298  return charProcs.isDict() ? charProcs.getDict() : (Dict *)NULL;
1299}
1300
1301Object *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
1310Dict *Gfx8BitFont::getResources() {
1311  return resources.isDict() ? resources.getDict() : (Dict *)NULL;
1312}
1313
1314//------------------------------------------------------------------------
1315// GfxCIDFont
1316//------------------------------------------------------------------------
1317
1318static int CDECL cmpWidthExcep(const void *w1, const void *w2) {
1319  return ((GfxFontCIDWidthExcep *)w1)->first -
1320         ((GfxFontCIDWidthExcep *)w2)->first;
1321}
1322
1323static int CDECL cmpWidthExcepV(const void *w1, const void *w2) {
1324  return ((GfxFontCIDWidthExcepV *)w1)->first -
1325         ((GfxFontCIDWidthExcepV *)w2)->first;
1326}
1327
1328GfxCIDFont::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
1686GfxCIDFont::~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
1700int 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
1776int GfxCIDFont::getWMode() {
1777  return cMap ? cMap->getWMode() : 0;
1778}
1779
1780CharCodeToUnicode *GfxCIDFont::getToUnicode() {
1781  if (ctu) {
1782    ctu->incRefCnt();
1783  }
1784  return ctu;
1785}
1786
1787GooString *GfxCIDFont::getCollection() {
1788  return cMap ? cMap->getCollection() : (GooString *)NULL;
1789}
1790
1791Gushort 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
1801Gushort *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
2049double 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
2080GfxFontDict::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
2123GfxFontDict::~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
2134GfxFont *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}
Note: See TracBrowser for help on using the repository browser.