root/middleware-offline/trunk/_src/eidmw/pteid-poppler/poppler/GfxFont.cc @ 226

Revision 226, 71.0 KB (checked in by vsilva, 8 years ago)

Improve PDF native Signature

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