source: trunk/poppler/mypoppler/fofi/FoFiType1C.cc @ 250

Last change on this file since 250 was 250, checked in by Eugene Romanenko, 13 years ago

PDF plugin: poppler library updated to version 0.8.3

File size: 75.3 KB
Line 
1//========================================================================
2//
3// FoFiType1C.cc
4//
5// Copyright 1999-2003 Glyph & Cog, LLC
6//
7//========================================================================
8
9#include <config.h>
10
11#ifdef USE_GCC_PRAGMAS
12#pragma implementation
13#endif
14
15#include <stdlib.h>
16#include <string.h>
17#include <math.h>
18#include "goo/gmem.h"
19#include "goo/GooString.h"
20#include "FoFiEncodings.h"
21#include "FoFiType1C.h"
22
23//------------------------------------------------------------------------
24
25static char hexChars[17] = "0123456789ABCDEF";
26
27//------------------------------------------------------------------------
28// FoFiType1C
29//------------------------------------------------------------------------
30
31FoFiType1C *FoFiType1C::make(char *fileA, int lenA) {
32  FoFiType1C *ff;
33
34  ff = new FoFiType1C(fileA, lenA, gFalse);
35  if (!ff->parse()) {
36    delete ff;
37    return NULL;
38  }
39  return ff;
40}
41
42FoFiType1C *FoFiType1C::load(char *fileName) {
43  FoFiType1C *ff;
44  char *fileA;
45  int lenA;
46
47  if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
48    return NULL;
49  }
50  ff = new FoFiType1C(fileA, lenA, gTrue);
51  if (!ff->parse()) {
52    delete ff;
53    return NULL;
54  }
55  return ff;
56}
57
58FoFiType1C::FoFiType1C(char *fileA, int lenA, GBool freeFileDataA):
59  FoFiBase(fileA, lenA, freeFileDataA)
60{
61  name = NULL;
62  encoding = NULL;
63  privateDicts = NULL;
64  fdSelect = NULL;
65  charset = NULL;
66}
67
68FoFiType1C::~FoFiType1C() {
69  int i;
70
71  if (name) {
72    delete name;
73  }
74  if (encoding &&
75      encoding != fofiType1StandardEncoding &&
76      encoding != fofiType1ExpertEncoding) {
77    for (i = 0; i < 256; ++i) {
78      gfree(encoding[i]);
79    }
80    gfree(encoding);
81  }
82  if (privateDicts) {
83    gfree(privateDicts);
84  }
85  if (fdSelect) {
86    gfree(fdSelect);
87  }
88  if (charset &&
89      charset != fofiType1CISOAdobeCharset &&
90      charset != fofiType1CExpertCharset &&
91      charset != fofiType1CExpertSubsetCharset) {
92    gfree(charset);
93  }
94}
95
96char *FoFiType1C::getName() {
97  return name ? name->getCString() : (char *)NULL;
98}
99
100char **FoFiType1C::getEncoding() {
101  return encoding;
102}
103
104Gushort *FoFiType1C::getCIDToGIDMap(int *nCIDs) {
105  Gushort *map;
106  int n, i;
107
108  // a CID font's top dict has ROS as the first operator
109  if (topDict.firstOp != 0x0c1e) {
110    *nCIDs = 0;
111    return NULL;
112  }
113
114  // in a CID font, the charset data is the GID-to-CID mapping, so all
115  // we have to do is reverse it
116  n = 0;
117  for (i = 0; i < nGlyphs; ++i) {
118    if (charset[i] > n) {
119      n = charset[i];
120    }
121  }
122  ++n;
123  map = (Gushort *)gmallocn(n, sizeof(Gushort));
124  memset(map, 0, n * sizeof(Gushort));
125  for (i = 0; i < nGlyphs; ++i) {
126    map[charset[i]] = i;
127  }
128  *nCIDs = n;
129  return map;
130}
131
132void FoFiType1C::convertToType1(char *psName, char **newEncoding, GBool ascii,
133                                FoFiOutputFunc outputFunc,
134                                void *outputStream) {
135  int psNameLen;
136  Type1CEexecBuf eb;
137  Type1CIndex subrIdx;
138  Type1CIndexVal val;
139  GooString *buf;
140  char buf2[256];
141  char **enc;
142  GBool ok;
143  int i;
144
145  if (psName) {
146    psNameLen = strlen(psName);
147  } else {
148    psName = name->getCString();
149    psNameLen = name->getLength();
150  }
151
152  // write header and font dictionary, up to encoding
153  ok = gTrue;
154  (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
155  (*outputFunc)(outputStream, psName, psNameLen);
156  if (topDict.versionSID != 0) {
157    getString(topDict.versionSID, buf2, &ok);
158    (*outputFunc)(outputStream, buf2, strlen(buf2));
159  }
160  (*outputFunc)(outputStream, "\n", 1);
161  // the dictionary needs room for 12 entries: the following 9, plus
162  // Private and CharStrings (in the eexec section) and FID (which is
163  // added by definefont)
164  (*outputFunc)(outputStream, "12 dict begin\n", 14);
165  (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
166  if (topDict.versionSID != 0) {
167    (*outputFunc)(outputStream, "/version (", 10);
168    (*outputFunc)(outputStream, buf2, strlen(buf2));
169    (*outputFunc)(outputStream, ") readonly def\n", 15);
170  }
171  if (topDict.noticeSID != 0) {
172    getString(topDict.noticeSID, buf2, &ok);
173    (*outputFunc)(outputStream, "/Notice (", 9);
174    (*outputFunc)(outputStream, buf2, strlen(buf2));
175    (*outputFunc)(outputStream, ") readonly def\n", 15);
176  }
177  if (topDict.copyrightSID != 0) {
178    getString(topDict.copyrightSID, buf2, &ok);
179    (*outputFunc)(outputStream, "/Copyright (", 12);
180    (*outputFunc)(outputStream, buf2, strlen(buf2));
181    (*outputFunc)(outputStream, ") readonly def\n", 15);
182  }
183  if (topDict.fullNameSID != 0) {
184    getString(topDict.fullNameSID, buf2, &ok);
185    (*outputFunc)(outputStream, "/FullName (", 11);
186    (*outputFunc)(outputStream, buf2, strlen(buf2));
187    (*outputFunc)(outputStream, ") readonly def\n", 15);
188  }
189  if (topDict.familyNameSID != 0) {
190    getString(topDict.familyNameSID, buf2, &ok);
191    (*outputFunc)(outputStream, "/FamilyName (", 13);
192    (*outputFunc)(outputStream, buf2, strlen(buf2));
193    (*outputFunc)(outputStream, ") readonly def\n", 15);
194  }
195  if (topDict.weightSID != 0) {
196    getString(topDict.weightSID, buf2, &ok);
197    (*outputFunc)(outputStream, "/Weight (", 9);
198    (*outputFunc)(outputStream, buf2, strlen(buf2));
199    (*outputFunc)(outputStream, ") readonly def\n", 15);
200  }
201  if (topDict.isFixedPitch) {
202    (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
203  } else {
204    (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
205  }
206  buf = GooString::format("/ItalicAngle {0:.4g} def\n", topDict.italicAngle);
207  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
208  delete buf;
209  buf = GooString::format("/UnderlinePosition {0:.4g} def\n",
210                        topDict.underlinePosition);
211  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
212  delete buf;
213  buf = GooString::format("/UnderlineThickness {0:.4g} def\n",
214                        topDict.underlineThickness);
215  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
216  delete buf;
217  (*outputFunc)(outputStream, "end readonly def\n", 17);
218  (*outputFunc)(outputStream, "/FontName /", 11);
219  (*outputFunc)(outputStream, psName, psNameLen);
220  (*outputFunc)(outputStream, " def\n", 5);
221  buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
222  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
223  delete buf;
224  (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
225  buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] readonly def\n",
226                        topDict.fontMatrix[0], topDict.fontMatrix[1],
227                        topDict.fontMatrix[2], topDict.fontMatrix[3],
228                        topDict.fontMatrix[4], topDict.fontMatrix[5]);
229  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
230  delete buf;
231  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] readonly def\n",
232                        topDict.fontBBox[0], topDict.fontBBox[1],
233                        topDict.fontBBox[2], topDict.fontBBox[3]);
234  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
235  delete buf;
236  buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
237  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
238  delete buf;
239  if (topDict.uniqueID != 0) {
240    buf = GooString::format("/UniqueID {0:d} def\n", topDict.uniqueID);
241    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
242    delete buf;
243  }
244
245  // write the encoding
246  (*outputFunc)(outputStream, "/Encoding ", 10);
247  if (!newEncoding && encoding == fofiType1StandardEncoding) {
248    (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
249  } else {
250    (*outputFunc)(outputStream, "256 array\n", 10);
251    (*outputFunc)(outputStream,
252                  "0 1 255 {1 index exch /.notdef put} for\n", 40);
253    enc = newEncoding ? newEncoding : encoding;
254    for (i = 0; i < 256; ++i) {
255      if (enc[i]) {
256        buf = GooString::format("dup {0:d} /{1:s} put\n", i, enc[i]);
257        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
258        delete buf;
259      }
260    }
261    (*outputFunc)(outputStream, "readonly def\n", 13);
262  }
263  (*outputFunc)(outputStream, "currentdict end\n", 16);
264
265  // start the binary section
266  (*outputFunc)(outputStream, "currentfile eexec\n", 18);
267  eb.outputFunc = outputFunc;
268  eb.outputStream = outputStream;
269  eb.ascii = ascii;
270  eb.r1 = 55665;
271  eb.line = 0;
272
273  // write the private dictionary
274  eexecWrite(&eb, "\x83\xca\x73\xd5");
275  eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
276  eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
277             " executeonly def\n");
278  eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
279  eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
280  eexecWrite(&eb, "/MinFeature {16 16} def\n");
281  eexecWrite(&eb, "/password 5839 def\n");
282  if (privateDicts[0].nBlueValues) {
283    eexecWrite(&eb, "/BlueValues [");
284    for (i = 0; i < privateDicts[0].nBlueValues; ++i) {
285      buf = GooString::format("{0:s}{1:d}",
286                            i > 0 ? " " : "", privateDicts[0].blueValues[i]);
287      eexecWrite(&eb, buf->getCString());
288      delete buf;
289    }
290    eexecWrite(&eb, "] def\n");
291  }
292  if (privateDicts[0].nOtherBlues) {
293    eexecWrite(&eb, "/OtherBlues [");
294    for (i = 0; i < privateDicts[0].nOtherBlues; ++i) {
295      buf = GooString::format("{0:s}{1:d}",
296                            i > 0 ? " " : "", privateDicts[0].otherBlues[i]);
297      eexecWrite(&eb, buf->getCString());
298      delete buf;
299    }
300    eexecWrite(&eb, "] def\n");
301  }
302  if (privateDicts[0].nFamilyBlues) {
303    eexecWrite(&eb, "/FamilyBlues [");
304    for (i = 0; i < privateDicts[0].nFamilyBlues; ++i) {
305      buf = GooString::format("{0:s}{1:d}",
306                            i > 0 ? " " : "", privateDicts[0].familyBlues[i]);
307      eexecWrite(&eb, buf->getCString());
308      delete buf;
309    }
310    eexecWrite(&eb, "] def\n");
311  }
312  if (privateDicts[0].nFamilyOtherBlues) {
313    eexecWrite(&eb, "/FamilyOtherBlues [");
314    for (i = 0; i < privateDicts[0].nFamilyOtherBlues; ++i) {
315      buf = GooString::format("{0:s}{1:d}", i > 0 ? " " : "",
316                            privateDicts[0].familyOtherBlues[i]);
317      eexecWrite(&eb, buf->getCString());
318      delete buf;
319    }
320    eexecWrite(&eb, "] def\n");
321  }
322  if (privateDicts[0].blueScale != 0.039625) {
323    buf = GooString::format("/BlueScale {0:.4g} def\n",
324                          privateDicts[0].blueScale);
325    eexecWrite(&eb, buf->getCString());
326    delete buf;
327  }
328  if (privateDicts[0].blueShift != 7) {
329    buf = GooString::format("/BlueShift {0:d} def\n", privateDicts[0].blueShift);
330    eexecWrite(&eb, buf->getCString());
331    delete buf;
332  }
333  if (privateDicts[0].blueFuzz != 1) {
334    buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[0].blueFuzz);
335    eexecWrite(&eb, buf->getCString());
336    delete buf;
337  }
338  if (privateDicts[0].hasStdHW) {
339    buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[0].stdHW);
340    eexecWrite(&eb, buf->getCString());
341    delete buf;
342  }
343  if (privateDicts[0].hasStdVW) {
344    buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[0].stdVW);
345    eexecWrite(&eb, buf->getCString());
346    delete buf;
347  }
348  if (privateDicts[0].nStemSnapH) {
349    eexecWrite(&eb, "/StemSnapH [");
350    for (i = 0; i < privateDicts[0].nStemSnapH; ++i) {
351      buf = GooString::format("{0:s}{1:.4g}",
352                            i > 0 ? " " : "", privateDicts[0].stemSnapH[i]);
353      eexecWrite(&eb, buf->getCString());
354      delete buf;
355    }
356    eexecWrite(&eb, "] def\n");
357  }
358  if (privateDicts[0].nStemSnapV) {
359    eexecWrite(&eb, "/StemSnapV [");
360    for (i = 0; i < privateDicts[0].nStemSnapV; ++i) {
361      buf = GooString::format("{0:s}{1:.4g}",
362                            i > 0 ? " " : "", privateDicts[0].stemSnapV[i]);
363      eexecWrite(&eb, buf->getCString());
364      delete buf;
365    }
366    eexecWrite(&eb, "] def\n");
367  }
368  if (privateDicts[0].hasForceBold) {
369    buf = GooString::format("/ForceBold {0:s} def\n",
370                          privateDicts[0].forceBold ? "true" : "false");
371    eexecWrite(&eb, buf->getCString());
372    delete buf;
373  }
374  if (privateDicts[0].forceBoldThreshold != 0) {
375    buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
376                          privateDicts[0].forceBoldThreshold);
377    eexecWrite(&eb, buf->getCString());
378    delete buf;
379  }
380  if (privateDicts[0].languageGroup != 0) {
381    buf = GooString::format("/LanguageGroup {0:d} def\n",
382                          privateDicts[0].languageGroup);
383    eexecWrite(&eb, buf->getCString());
384    delete buf;
385  }
386  if (privateDicts[0].expansionFactor != 0.06) {
387    buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
388                          privateDicts[0].expansionFactor);
389    eexecWrite(&eb, buf->getCString());
390    delete buf;
391  }
392
393  // set up subroutines
394  ok = gTrue;
395  getIndex(privateDicts[0].subrsOffset, &subrIdx, &ok);
396  if (!ok) {
397    subrIdx.pos = -1;
398  }
399
400  // write the CharStrings
401  buf = GooString::format("2 index /CharStrings {0:d} dict dup begin\n",
402                        nGlyphs);
403  eexecWrite(&eb, buf->getCString());
404  delete buf;
405  for (i = 0; i < nGlyphs; ++i) {
406    ok = gTrue;
407    getIndexVal(&charStringsIdx, i, &val, &ok);
408    if (ok) {
409      getString(charset[i], buf2, &ok);
410      if (ok) {
411        eexecCvtGlyph(&eb, buf2, val.pos, val.len, &subrIdx, &privateDicts[0]);
412      }
413    }
414  }
415  eexecWrite(&eb, "end\n");
416  eexecWrite(&eb, "end\n");
417  eexecWrite(&eb, "readonly put\n");
418  eexecWrite(&eb, "noaccess put\n");
419  eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
420  eexecWrite(&eb, "mark currentfile closefile\n");
421
422  // trailer
423  if (ascii && eb.line > 0) {
424    (*outputFunc)(outputStream, "\n", 1);
425  }
426  for (i = 0; i < 8; ++i) {
427    (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
428  }
429  (*outputFunc)(outputStream, "cleartomark\n", 12);
430}
431
432void FoFiType1C::convertToCIDType0(char *psName,
433                                   FoFiOutputFunc outputFunc,
434                                   void *outputStream) {
435  int *cidMap;
436  GooString *charStrings;
437  int *charStringOffsets;
438  Type1CIndex subrIdx;
439  Type1CIndexVal val;
440  int nCIDs, gdBytes;
441  GooString *buf;
442  char buf2[256];
443  GBool ok;
444  int gid, offset, n, i, j, k;
445
446  // compute the CID count and build the CID-to-GID mapping
447  nCIDs = 0;
448  for (i = 0; i < nGlyphs; ++i) {
449    if (charset[i] >= nCIDs) {
450      nCIDs = charset[i] + 1;
451    }
452  }
453  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
454  for (i = 0; i < nCIDs; ++i) {
455    cidMap[i] = -1;
456  }
457  for (i = 0; i < nGlyphs; ++i) {
458    cidMap[charset[i]] = i;
459  }
460
461  // build the charstrings
462  charStrings = new GooString();
463  charStringOffsets = (int *)gmallocn(nCIDs + 1, sizeof(int));
464  for (i = 0; i < nCIDs; ++i) {
465    charStringOffsets[i] = charStrings->getLength();
466    if ((gid = cidMap[i]) >= 0) {
467      ok = gTrue;
468      getIndexVal(&charStringsIdx, gid, &val, &ok);
469      if (ok) {
470        getIndex(privateDicts[fdSelect[gid]].subrsOffset, &subrIdx, &ok);
471        if (!ok) {
472          subrIdx.pos = -1;
473        }
474        cvtGlyph(val.pos, val.len, charStrings,
475                 &subrIdx, &privateDicts[fdSelect[gid]], gTrue);
476      }
477    }
478  }
479  charStringOffsets[nCIDs] = charStrings->getLength();
480
481  // compute gdBytes = number of bytes needed for charstring offsets
482  // (offset size needs to account for the charstring offset table,
483  // with a worst case of five bytes per entry, plus the charstrings
484  // themselves)
485  i = (nCIDs + 1) * 5 + charStrings->getLength();
486  if (i < 0x100) {
487    gdBytes = 1;
488  } else if (i < 0x10000) {
489    gdBytes = 2;
490  } else if (i < 0x1000000) {
491    gdBytes = 3;
492  } else {
493    gdBytes = 4;
494  }
495
496  // begin the font dictionary
497  (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
498  (*outputFunc)(outputStream, "20 dict begin\n", 14);
499  (*outputFunc)(outputStream, "/CIDFontName /", 14);
500  (*outputFunc)(outputStream, psName, strlen(psName));
501  (*outputFunc)(outputStream, " def\n", 5);
502  (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
503  (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
504  if (topDict.registrySID > 0 && topDict.orderingSID > 0) {
505    ok = gTrue;
506    getString(topDict.registrySID, buf2, &ok);
507    if (ok) {
508      (*outputFunc)(outputStream, "  /Registry (", 13);
509      (*outputFunc)(outputStream, buf2, strlen(buf2));
510      (*outputFunc)(outputStream, ") def\n", 6);
511    }
512    ok = gTrue;
513    getString(topDict.orderingSID, buf2, &ok);
514    if (ok) {
515      (*outputFunc)(outputStream, "  /Ordering (", 13);
516      (*outputFunc)(outputStream, buf2, strlen(buf2));
517      (*outputFunc)(outputStream, ") def\n", 6);
518    }
519  } else {
520    (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
521    (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
522  }
523  buf = GooString::format("  /Supplement {0:d} def\n", topDict.supplement);
524  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
525  delete buf;
526  (*outputFunc)(outputStream, "end def\n", 8);
527  if (topDict.hasFontMatrix) {
528    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
529                          topDict.fontMatrix[0], topDict.fontMatrix[1],
530                          topDict.fontMatrix[2], topDict.fontMatrix[3],
531                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
532    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
533    delete buf;
534  } else if (privateDicts[0].hasFontMatrix) {
535    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
536  } else {
537    (*outputFunc)(outputStream,
538                  "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
539  }
540  buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
541                        topDict.fontBBox[0], topDict.fontBBox[1],
542                        topDict.fontBBox[2], topDict.fontBBox[3]);
543  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
544  delete buf;
545  (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
546  (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
547  (*outputFunc)(outputStream, "end def\n", 8);
548
549  // CIDFont-specific entries
550  buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
551  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
552  delete buf;
553  (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
554  buf = GooString::format("/GDBytes {0:d} def\n", gdBytes);
555  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
556  delete buf;
557  (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
558  if (topDict.paintType != 0) {
559    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
560    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
561    delete buf;
562    buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
563    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
564    delete buf;
565  }
566
567  // FDArray entry
568  buf = GooString::format("/FDArray {0:d} array\n", nFDs);
569  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
570  delete buf;
571  for (i = 0; i < nFDs; ++i) {
572    buf = GooString::format("dup {0:d} 10 dict begin\n", i);
573    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
574    delete buf;
575    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
576    if (privateDicts[i].hasFontMatrix) {
577      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
578                            privateDicts[i].fontMatrix[0],
579                            privateDicts[i].fontMatrix[1],
580                            privateDicts[i].fontMatrix[2],
581                            privateDicts[i].fontMatrix[3],
582                            privateDicts[i].fontMatrix[4],
583                            privateDicts[i].fontMatrix[5]);
584      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
585      delete buf;
586    } else {
587      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
588    }
589    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
590    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
591    delete buf;
592    (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
593    if (privateDicts[i].nBlueValues) {
594      (*outputFunc)(outputStream, "/BlueValues [", 13);
595      for (j = 0; j < privateDicts[i].nBlueValues; ++j) {
596        buf = GooString::format("{0:s}{1:d}",
597                              j > 0 ? " " : "", privateDicts[i].blueValues[j]);
598        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
599        delete buf;
600      }
601      (*outputFunc)(outputStream, "] def\n", 6);
602    }
603    if (privateDicts[i].nOtherBlues) {
604      (*outputFunc)(outputStream, "/OtherBlues [", 13);
605      for (j = 0; j < privateDicts[i].nOtherBlues; ++j) {
606        buf = GooString::format("{0:s}{1:d}",
607                              j > 0 ? " " : "", privateDicts[i].otherBlues[j]);
608        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
609        delete buf;
610      }
611      (*outputFunc)(outputStream, "] def\n", 6);
612    }
613    if (privateDicts[i].nFamilyBlues) {
614      (*outputFunc)(outputStream, "/FamilyBlues [", 14);
615      for (j = 0; j < privateDicts[i].nFamilyBlues; ++j) {
616        buf = GooString::format("{0:s}{1:d}",
617                              j > 0 ? " " : "",
618                              privateDicts[i].familyBlues[j]);
619        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
620        delete buf;
621      }
622      (*outputFunc)(outputStream, "] def\n", 6);
623    }
624    if (privateDicts[i].nFamilyOtherBlues) {
625      (*outputFunc)(outputStream, "/FamilyOtherBlues [", 19);
626      for (j = 0; j < privateDicts[i].nFamilyOtherBlues; ++j) {
627        buf = GooString::format("{0:s}{1:d}", j > 0 ? " " : "",
628                              privateDicts[i].familyOtherBlues[j]);
629        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
630        delete buf;
631      }
632      (*outputFunc)(outputStream, "] def\n", 6);
633    }
634    if (privateDicts[i].blueScale != 0.039625) {
635      buf = GooString::format("/BlueScale {0:.4g} def\n",
636                            privateDicts[i].blueScale);
637      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
638      delete buf;
639    }
640    if (privateDicts[i].blueShift != 7) {
641      buf = GooString::format("/BlueShift {0:d} def\n",
642                            privateDicts[i].blueShift);
643      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
644      delete buf;
645    }
646    if (privateDicts[i].blueFuzz != 1) {
647      buf = GooString::format("/BlueFuzz {0:d} def\n", privateDicts[i].blueFuzz);
648      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
649      delete buf;
650    }
651    if (privateDicts[i].hasStdHW) {
652      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[i].stdHW);
653      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
654      delete buf;
655    }
656    if (privateDicts[i].hasStdVW) {
657      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[i].stdVW);
658      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
659      delete buf;
660    }
661    if (privateDicts[i].nStemSnapH) {
662      (*outputFunc)(outputStream, "/StemSnapH [", 12);
663      for (j = 0; j < privateDicts[i].nStemSnapH; ++j) {
664        buf = GooString::format("{0:s}{1:.4g}",
665                              j > 0 ? " " : "", privateDicts[i].stemSnapH[j]);
666        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
667        delete buf;
668      }
669      (*outputFunc)(outputStream, "] def\n", 6);
670    }
671    if (privateDicts[i].nStemSnapV) {
672      (*outputFunc)(outputStream, "/StemSnapV [", 12);
673      for (j = 0; j < privateDicts[i].nStemSnapV; ++j) {
674        buf = GooString::format("{0:s}{1:.4g}",
675                              j > 0 ? " " : "", privateDicts[i].stemSnapV[j]);
676        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
677        delete buf;
678      }
679      (*outputFunc)(outputStream, "] def\n", 6);
680    }
681    if (privateDicts[i].hasForceBold) {
682      buf = GooString::format("/ForceBold {0:s} def\n",
683                            privateDicts[i].forceBold ? "true" : "false");
684      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
685      delete buf;
686    }
687    if (privateDicts[i].forceBoldThreshold != 0) {
688      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
689                            privateDicts[i].forceBoldThreshold);
690      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
691      delete buf;
692    }
693    if (privateDicts[i].languageGroup != 0) {
694      buf = GooString::format("/LanguageGroup {0:d} def\n",
695                            privateDicts[i].languageGroup);
696      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
697      delete buf;
698    }
699    if (privateDicts[i].expansionFactor != 0.06) {
700      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
701                            privateDicts[i].expansionFactor);
702      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
703      delete buf;
704    }
705    (*outputFunc)(outputStream, "currentdict end def\n", 20);
706    (*outputFunc)(outputStream, "currentdict end put\n", 20);
707  }
708  (*outputFunc)(outputStream, "def\n", 4);
709
710  // start the binary section
711  offset = (nCIDs + 1) * (1 + gdBytes);
712  buf = GooString::format("(Hex) {0:d} StartData\n",
713                        offset + charStrings->getLength());
714  (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
715  delete buf;
716
717  // write the charstring offset (CIDMap) table
718  for (i = 0; i <= nCIDs; i += 6) {
719    for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
720      if (i+j < nCIDs && cidMap[i+j] >= 0) {
721        buf2[0] = (char)fdSelect[cidMap[i+j]];
722      } else {
723        buf2[0] = (char)0;
724      }
725      n = offset + charStringOffsets[i+j];
726      for (k = gdBytes; k >= 1; --k) {
727        buf2[k] = (char)(n & 0xff);
728        n >>= 8;
729      }
730      for (k = 0; k <= gdBytes; ++k) {
731        buf = GooString::format("{0:02x}", buf2[k] & 0xff);
732        (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
733        delete buf;
734      }
735    }
736    (*outputFunc)(outputStream, "\n", 1);
737  }
738
739  // write the charstring data
740  n = charStrings->getLength();
741  for (i = 0; i < n; i += 32) {
742    for (j = 0; j < 32 && i+j < n; ++j) {
743      buf = GooString::format("{0:02x}", charStrings->getChar(i+j) & 0xff);
744      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
745      delete buf;
746    }
747    if (i + 32 >= n) {
748      (*outputFunc)(outputStream, ">", 1);
749    }
750    (*outputFunc)(outputStream, "\n", 1);
751  }
752
753  gfree(charStringOffsets);
754  delete charStrings;
755  gfree(cidMap);
756}
757
758void FoFiType1C::convertToType0(char *psName,
759                                FoFiOutputFunc outputFunc,
760                                void *outputStream) {
761  int *cidMap;
762  Type1CIndex subrIdx;
763  Type1CIndexVal val;
764  int nCIDs;
765  GooString *buf;
766  Type1CEexecBuf eb;
767  GBool ok;
768  int fd, i, j, k;
769
770  // compute the CID count and build the CID-to-GID mapping
771  nCIDs = 0;
772  for (i = 0; i < nGlyphs; ++i) {
773    if (charset[i] >= nCIDs) {
774      nCIDs = charset[i] + 1;
775    }
776  }
777  cidMap = (int *)gmallocn(nCIDs, sizeof(int));
778  for (i = 0; i < nCIDs; ++i) {
779    cidMap[i] = -1;
780  }
781  for (i = 0; i < nGlyphs; ++i) {
782    cidMap[charset[i]] = i;
783  }
784
785  // write the descendant Type 1 fonts
786  for (i = 0; i < nCIDs; i += 256) {
787
788    //~ this assumes that all CIDs in this block have the same FD --
789    //~ to handle multiple FDs correctly, need to somehow divide the
790    //~ font up by FD; as a kludge we ignore CID 0, which is .notdef
791    fd = 0;
792    for (j = i==0 ? 1 : 0; j < 256 && i+j < nCIDs; ++j) {
793      if (cidMap[i+j] >= 0) {
794        fd = fdSelect[cidMap[i+j]];
795        break;
796      }
797    }
798
799    // font dictionary (unencrypted section)
800    (*outputFunc)(outputStream, "16 dict begin\n", 14);
801    (*outputFunc)(outputStream, "/FontName /", 11);
802    (*outputFunc)(outputStream, psName, strlen(psName));
803    buf = GooString::format("_{0:02x} def\n", i >> 8);
804    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
805    delete buf;
806    (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
807    if (privateDicts[fd].hasFontMatrix) {
808      buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
809                            privateDicts[fd].fontMatrix[0],
810                            privateDicts[fd].fontMatrix[1],
811                            privateDicts[fd].fontMatrix[2],
812                            privateDicts[fd].fontMatrix[3],
813                            privateDicts[fd].fontMatrix[4],
814                            privateDicts[fd].fontMatrix[5]);
815      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
816      delete buf;
817    } else if (topDict.hasFontMatrix) {
818      (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
819    } else {
820      (*outputFunc)(outputStream,
821                    "/FontMatrix [0.001 0 0 0.001 0 0] def\n", 38);
822    }
823    buf = GooString::format("/FontBBox [{0:.4g} {1:.4g} {2:.4g} {3:.4g}] def\n",
824                          topDict.fontBBox[0], topDict.fontBBox[1],
825                          topDict.fontBBox[2], topDict.fontBBox[3]);
826    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
827    delete buf;
828    buf = GooString::format("/PaintType {0:d} def\n", topDict.paintType);
829    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
830    delete buf;
831    if (topDict.paintType != 0) {
832      buf = GooString::format("/StrokeWidth {0:.4g} def\n", topDict.strokeWidth);
833      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
834      delete buf;
835    }
836    (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
837    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
838      buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
839      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
840      delete buf;
841    }
842    if (j < 256) {
843      buf = GooString::format("{0:d} 1 255 {{ 1 index exch /.notdef put }} for\n",
844                            j);
845      (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
846      delete buf;
847    }
848    (*outputFunc)(outputStream, "readonly def\n", 13);
849    (*outputFunc)(outputStream, "currentdict end\n", 16);
850
851    // start the binary section
852    (*outputFunc)(outputStream, "currentfile eexec\n", 18);
853    eb.outputFunc = outputFunc;
854    eb.outputStream = outputStream;
855    eb.ascii = gTrue;
856    eb.r1 = 55665;
857    eb.line = 0;
858
859    // start the private dictionary
860    eexecWrite(&eb, "\x83\xca\x73\xd5");
861    eexecWrite(&eb, "dup /Private 32 dict dup begin\n");
862    eexecWrite(&eb, "/RD {string currentfile exch readstring pop}"
863               " executeonly def\n");
864    eexecWrite(&eb, "/ND {noaccess def} executeonly def\n");
865    eexecWrite(&eb, "/NP {noaccess put} executeonly def\n");
866    eexecWrite(&eb, "/MinFeature {16 16} def\n");
867    eexecWrite(&eb, "/password 5839 def\n");
868    if (privateDicts[fd].nBlueValues) {
869      eexecWrite(&eb, "/BlueValues [");
870      for (k = 0; k < privateDicts[fd].nBlueValues; ++k) {
871        buf = GooString::format("{0:s}{1:d}",
872                              k > 0 ? " " : "",
873                              privateDicts[fd].blueValues[k]);
874        eexecWrite(&eb, buf->getCString());
875        delete buf;
876      }
877      eexecWrite(&eb, "] def\n");
878    }
879    if (privateDicts[fd].nOtherBlues) {
880      eexecWrite(&eb, "/OtherBlues [");
881      for (k = 0; k < privateDicts[fd].nOtherBlues; ++k) {
882        buf = GooString::format("{0:s}{1:d}",
883                              k > 0 ? " " : "",
884                              privateDicts[fd].otherBlues[k]);
885        eexecWrite(&eb, buf->getCString());
886        delete buf;
887      }
888      eexecWrite(&eb, "] def\n");
889    }
890    if (privateDicts[fd].nFamilyBlues) {
891      eexecWrite(&eb, "/FamilyBlues [");
892      for (k = 0; k < privateDicts[fd].nFamilyBlues; ++k) {
893        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
894                              privateDicts[fd].familyBlues[k]);
895        eexecWrite(&eb, buf->getCString());
896        delete buf;
897      }
898      eexecWrite(&eb, "] def\n");
899    }
900    if (privateDicts[fd].nFamilyOtherBlues) {
901      eexecWrite(&eb, "/FamilyOtherBlues [");
902      for (k = 0; k < privateDicts[fd].nFamilyOtherBlues; ++k) {
903        buf = GooString::format("{0:s}{1:d}", k > 0 ? " " : "",
904                              privateDicts[fd].familyOtherBlues[k]);
905        eexecWrite(&eb, buf->getCString());
906        delete buf;
907      }
908      eexecWrite(&eb, "] def\n");
909    }
910    if (privateDicts[fd].blueScale != 0.039625) {
911      buf = GooString::format("/BlueScale {0:.4g} def\n",
912                            privateDicts[fd].blueScale);
913      eexecWrite(&eb, buf->getCString());
914      delete buf;
915    }
916    if (privateDicts[fd].blueShift != 7) {
917      buf = GooString::format("/BlueShift {0:d} def\n",
918                            privateDicts[fd].blueShift);
919      eexecWrite(&eb, buf->getCString());
920      delete buf;
921    }
922    if (privateDicts[fd].blueFuzz != 1) {
923      buf = GooString::format("/BlueFuzz {0:d} def\n",
924                            privateDicts[fd].blueFuzz);
925      eexecWrite(&eb, buf->getCString());
926      delete buf;
927    }
928    if (privateDicts[fd].hasStdHW) {
929      buf = GooString::format("/StdHW [{0:.4g}] def\n", privateDicts[fd].stdHW);
930      eexecWrite(&eb, buf->getCString());
931      delete buf;
932    }
933    if (privateDicts[fd].hasStdVW) {
934      buf = GooString::format("/StdVW [{0:.4g}] def\n", privateDicts[fd].stdVW);
935      eexecWrite(&eb, buf->getCString());
936      delete buf;
937    }
938    if (privateDicts[fd].nStemSnapH) {
939      eexecWrite(&eb, "/StemSnapH [");
940      for (k = 0; k < privateDicts[fd].nStemSnapH; ++k) {
941        buf = GooString::format("{0:s}{1:.4g}",
942                              k > 0 ? " " : "", privateDicts[fd].stemSnapH[k]);
943        eexecWrite(&eb, buf->getCString());
944        delete buf;
945      }
946      eexecWrite(&eb, "] def\n");
947    }
948    if (privateDicts[fd].nStemSnapV) {
949      eexecWrite(&eb, "/StemSnapV [");
950      for (k = 0; k < privateDicts[fd].nStemSnapV; ++k) {
951        buf = GooString::format("{0:s}{1:.4g}",
952                              k > 0 ? " " : "", privateDicts[fd].stemSnapV[k]);
953        eexecWrite(&eb, buf->getCString());
954        delete buf;
955      }
956      eexecWrite(&eb, "] def\n");
957    }
958    if (privateDicts[fd].hasForceBold) {
959      buf = GooString::format("/ForceBold {0:s} def\n",
960                            privateDicts[fd].forceBold ? "true" : "false");
961      eexecWrite(&eb, buf->getCString());
962      delete buf;
963    }
964    if (privateDicts[fd].forceBoldThreshold != 0) {
965      buf = GooString::format("/ForceBoldThreshold {0:.4g} def\n",
966                            privateDicts[fd].forceBoldThreshold);
967      eexecWrite(&eb, buf->getCString());
968      delete buf;
969    }
970    if (privateDicts[fd].languageGroup != 0) {
971      buf = GooString::format("/LanguageGroup {0:d} def\n",
972                            privateDicts[fd].languageGroup);
973      eexecWrite(&eb, buf->getCString());
974      delete buf;
975    }
976    if (privateDicts[fd].expansionFactor != 0.06) {
977      buf = GooString::format("/ExpansionFactor {0:.4g} def\n",
978                            privateDicts[fd].expansionFactor);
979      eexecWrite(&eb, buf->getCString());
980      delete buf;
981    }
982
983    // set up the subroutines
984    ok = gTrue;
985    getIndex(privateDicts[fd].subrsOffset, &subrIdx, &ok);
986    if (!ok) {
987      subrIdx.pos = -1;
988    }
989
990    // start the CharStrings
991    eexecWrite(&eb, "2 index /CharStrings 256 dict dup begin\n");
992
993    // write the .notdef CharString
994    ok = gTrue;
995    getIndexVal(&charStringsIdx, 0, &val, &ok);
996    if (ok) {
997      eexecCvtGlyph(&eb, ".notdef", val.pos, val.len,
998                    &subrIdx, &privateDicts[fd]);
999    }
1000
1001    // write the CharStrings
1002    for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1003      if (cidMap[i+j] >= 0) {
1004        ok = gTrue;
1005        getIndexVal(&charStringsIdx, cidMap[i+j], &val, &ok);
1006        if (ok) {
1007          buf = GooString::format("c{0:02x}", j);
1008          eexecCvtGlyph(&eb, buf->getCString(), val.pos, val.len,
1009                        &subrIdx, &privateDicts[fd]);
1010          delete buf;
1011        }
1012      }
1013    }
1014    eexecWrite(&eb, "end\n");
1015    eexecWrite(&eb, "end\n");
1016    eexecWrite(&eb, "readonly put\n");
1017    eexecWrite(&eb, "noaccess put\n");
1018    eexecWrite(&eb, "dup /FontName get exch definefont pop\n");
1019    eexecWrite(&eb, "mark currentfile closefile\n");
1020
1021    // trailer
1022    if (eb.line > 0) {
1023      (*outputFunc)(outputStream, "\n", 1);
1024    }
1025    for (j = 0; j < 8; ++j) {
1026      (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1027    }
1028    (*outputFunc)(outputStream, "cleartomark\n", 12);
1029  }
1030
1031  // write the Type 0 parent font
1032  (*outputFunc)(outputStream, "16 dict begin\n", 14);
1033  (*outputFunc)(outputStream, "/FontName /", 11);
1034  (*outputFunc)(outputStream, psName, strlen(psName));
1035  (*outputFunc)(outputStream, " def\n", 5);
1036  (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1037  if (topDict.hasFontMatrix) {
1038    buf = GooString::format("/FontMatrix [{0:.8g} {1:.8g} {2:.8g} {3:.8g} {4:.8g} {5:.8g}] def\n",
1039                          topDict.fontMatrix[0], topDict.fontMatrix[1],
1040                          topDict.fontMatrix[2], topDict.fontMatrix[3],
1041                          topDict.fontMatrix[4], topDict.fontMatrix[5]);
1042    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1043    delete buf;
1044  } else {
1045    (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1046  }
1047  (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1048  (*outputFunc)(outputStream, "/Encoding [\n", 12);
1049  for (i = 0; i < nCIDs; i += 256) {
1050    buf = GooString::format("{0:d}\n", i >> 8);
1051    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1052    delete buf;
1053  }
1054  (*outputFunc)(outputStream, "] def\n", 6);
1055  (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1056  for (i = 0; i < nCIDs; i += 256) {
1057    (*outputFunc)(outputStream, "/", 1);
1058    (*outputFunc)(outputStream, psName, strlen(psName));
1059    buf = GooString::format("_{0:02x} findfont\n", i >> 8);
1060    (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1061    delete buf;
1062  }
1063  (*outputFunc)(outputStream, "] def\n", 6);
1064  (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1065
1066  gfree(cidMap);
1067}
1068
1069void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
1070                               int offset, int nBytes,
1071                               Type1CIndex *subrIdx,
1072                               Type1CPrivateDict *pDict) {
1073  GooString *buf;
1074  GooString *charBuf;
1075
1076  // generate the charstring
1077  charBuf = new GooString();
1078  cvtGlyph(offset, nBytes, charBuf, subrIdx, pDict, gTrue);
1079
1080  buf = GooString::format("/{0:s} {1:d} RD ", glyphName, charBuf->getLength());
1081  eexecWrite(eb, buf->getCString());
1082  delete buf;
1083  eexecWriteCharstring(eb, (Guchar *)charBuf->getCString(),
1084                       charBuf->getLength());
1085  eexecWrite(eb, " ND\n");
1086
1087  delete charBuf;
1088}
1089
1090void FoFiType1C::cvtGlyph(int offset, int nBytes, GooString *charBuf,
1091                          Type1CIndex *subrIdx, Type1CPrivateDict *pDict,
1092                          GBool top) {
1093  Type1CIndexVal val;
1094  GBool ok, dFP;
1095  double d, dx, dy;
1096  Gushort r2;
1097  Guchar byte;
1098  int pos, subrBias, start, i, k;
1099
1100  start = charBuf->getLength();
1101  if (top) {
1102    charBuf->append((char)73);
1103    charBuf->append((char)58);
1104    charBuf->append((char)147);
1105    charBuf->append((char)134);
1106    nOps = 0;
1107    nHints = 0;
1108    firstOp = gTrue;
1109    openPath = gFalse;
1110  }
1111
1112  pos = offset;
1113  while (pos < offset + nBytes) {
1114    ok = gTrue;
1115    pos = getOp(pos, gTrue, &ok);
1116    if (!ok) {
1117      break;
1118    }
1119    if (!ops[nOps - 1].isNum) {
1120      --nOps; // drop the operator
1121      switch (ops[nOps].op) {
1122      case 0x0001:              // hstem
1123        if (firstOp) {
1124          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1125          firstOp = gFalse;
1126        }
1127        if (nOps & 1) {
1128          //~ error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1129        }
1130        d = 0;
1131        dFP = gFalse;
1132        for (k = 0; k < nOps; k += 2) {
1133          // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1134          if (ops[k+1].num < 0) {
1135            d += ops[k].num + ops[k+1].num;
1136            dFP |= ops[k].isFP | ops[k+1].isFP;
1137            cvtNum(d, dFP, charBuf);
1138            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1139          } else {
1140            d += ops[k].num;
1141            dFP |= ops[k].isFP;
1142            cvtNum(d, dFP, charBuf);
1143            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1144            d += ops[k+1].num;
1145            dFP |= ops[k+1].isFP;
1146          }
1147          charBuf->append((char)1);
1148        }
1149        nHints += nOps / 2;
1150        nOps = 0;
1151        break;
1152      case 0x0003:              // vstem
1153        if (firstOp) {
1154          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1155          firstOp = gFalse;
1156        }
1157        if (nOps & 1) {
1158          //~ error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1159        }
1160        d = 0;
1161        dFP = gFalse;
1162        for (k = 0; k < nOps; k += 2) {
1163          // convert Type 2 edge hints (-20 or -21) to Type 1 ghost hints
1164          if (ops[k+1].num < 0) {
1165            d += ops[k].num + ops[k+1].num;
1166            dFP |= ops[k].isFP | ops[k+1].isFP;
1167            cvtNum(d, dFP, charBuf);
1168            cvtNum(-ops[k+1].num, ops[k+1].isFP, charBuf);
1169          } else {
1170            d += ops[k].num;
1171            dFP |= ops[k].isFP;
1172            cvtNum(d, dFP, charBuf);
1173            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1174            d += ops[k+1].num;
1175            dFP |= ops[k+1].isFP;
1176          }
1177          charBuf->append((char)3);
1178        }
1179        nHints += nOps / 2;
1180        nOps = 0;
1181        break;
1182      case 0x0004:              // vmoveto
1183        if (firstOp) {
1184          cvtGlyphWidth(nOps == 2, charBuf, pDict);
1185          firstOp = gFalse;
1186        }
1187        if (openPath) {
1188          charBuf->append((char)9);
1189          openPath = gFalse;
1190        }
1191        if (nOps != 1) {
1192          //~ error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1193        }
1194        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1195        charBuf->append((char)4);
1196        nOps = 0;
1197        break;
1198      case 0x0005:              // rlineto
1199        if (nOps < 2 || nOps % 2 != 0) {
1200          //~ error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1201        }
1202        for (k = 0; k < nOps; k += 2) {
1203          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1204          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1205          charBuf->append((char)5);
1206        }
1207        nOps = 0;
1208        openPath = gTrue;
1209        break;
1210      case 0x0006:              // hlineto
1211        if (nOps < 1) {
1212          //~ error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1213        }
1214        for (k = 0; k < nOps; ++k) {
1215          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1216          charBuf->append((char)((k & 1) ? 7 : 6));
1217        }
1218        nOps = 0;
1219        openPath = gTrue;
1220        break;
1221      case 0x0007:              // vlineto
1222        if (nOps < 1) {
1223          //~ error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1224        }
1225        for (k = 0; k < nOps; ++k) {
1226          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1227          charBuf->append((char)((k & 1) ? 6 : 7));
1228        }
1229        nOps = 0;
1230        openPath = gTrue;
1231        break;
1232      case 0x0008:              // rrcurveto
1233        if (nOps < 6 || nOps % 6 != 0) {
1234          //~ error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1235        }
1236        for (k = 0; k < nOps; k += 6) {
1237          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1238          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1239          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1240          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1241          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1242          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1243          charBuf->append((char)8);
1244        }
1245        nOps = 0;
1246        openPath = gTrue;
1247        break;
1248      case 0x000a:              // callsubr
1249        if (nOps >= 1) {
1250          subrBias = (subrIdx->len < 1240)
1251                       ? 107 : (subrIdx->len < 33900) ? 1131 : 32768;
1252          k = subrBias + (int)ops[nOps - 1].num;
1253          --nOps;
1254          ok = gTrue;
1255          getIndexVal(subrIdx, k, &val, &ok);
1256          if (ok) {
1257            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1258          }
1259        } else {
1260          //~ error(-1, "Too few args to Type 2 callsubr");
1261        }
1262        // don't clear the stack
1263        break;
1264      case 0x000b:              // return
1265        // don't clear the stack
1266        break;
1267      case 0x000e:              // endchar / seac
1268        if (firstOp) {
1269          cvtGlyphWidth(nOps == 1 || nOps == 5, charBuf, pDict);
1270          firstOp = gFalse;
1271        }
1272        if (openPath) {
1273          charBuf->append((char)9);
1274          openPath = gFalse;
1275        }
1276        if (nOps == 4) {
1277          cvtNum(0, gFalse, charBuf);
1278          cvtNum(ops[0].num, ops[0].isFP, charBuf);
1279          cvtNum(ops[1].num, ops[1].isFP, charBuf);
1280          cvtNum(ops[2].num, ops[2].isFP, charBuf);
1281          cvtNum(ops[3].num, ops[3].isFP, charBuf);
1282          charBuf->append((char)12)->append((char)6);
1283        } else if (nOps == 0) {
1284          charBuf->append((char)14);
1285        } else {
1286          //~ error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1287        }
1288        nOps = 0;
1289        break;
1290      case 0x000f:              // (obsolete)
1291        // this op is ignored, but we need the glyph width
1292        if (firstOp) {
1293          cvtGlyphWidth(nOps > 0, charBuf, pDict);
1294          firstOp = gFalse;
1295        }
1296        nOps = 0;
1297        break;
1298      case 0x0010:              // blend
1299        //~ error(-1, "Unimplemented Type 2 charstring op: %d", file[i]);
1300        nOps = 0;
1301        break;
1302      case 0x0012:              // hstemhm
1303        // ignored
1304        if (firstOp) {
1305          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1306          firstOp = gFalse;
1307        }
1308        if (nOps & 1) {
1309          //~ error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1310        }
1311        nHints += nOps / 2;
1312        nOps = 0;
1313        break;
1314      case 0x0013:              // hintmask
1315        // ignored
1316        if (firstOp) {
1317          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1318          firstOp = gFalse;
1319        }
1320        if (nOps > 0) {
1321          if (nOps & 1) {
1322            //~ error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1323            //~       nOps);
1324          }
1325          nHints += nOps / 2;
1326        }
1327        pos += (nHints + 7) >> 3;
1328        nOps = 0;
1329        break;
1330      case 0x0014:              // cntrmask
1331        // ignored
1332        if (firstOp) {
1333          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1334          firstOp = gFalse;
1335        }
1336        if (nOps > 0) {
1337          if (nOps & 1) {
1338            //~ error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1339            //~       nOps);
1340          }
1341          nHints += nOps / 2;
1342        }
1343        pos += (nHints + 7) >> 3;
1344        nOps = 0;
1345        break;
1346      case 0x0015:              // rmoveto
1347        if (firstOp) {
1348          cvtGlyphWidth(nOps == 3, charBuf, pDict);
1349          firstOp = gFalse;
1350        }
1351        if (openPath) {
1352          charBuf->append((char)9);
1353          openPath = gFalse;
1354        }
1355        if (nOps != 2) {
1356          //~ error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1357        }
1358        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1359        cvtNum(ops[1].num, ops[1].isFP, charBuf);
1360        charBuf->append((char)21);
1361        nOps = 0;
1362        break;
1363      case 0x0016:              // hmoveto
1364        if (firstOp) {
1365          cvtGlyphWidth(nOps == 2, charBuf, pDict);
1366          firstOp = gFalse;
1367        }
1368        if (openPath) {
1369          charBuf->append((char)9);
1370          openPath = gFalse;
1371        }
1372        if (nOps != 1) {
1373          //~ error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1374        }
1375        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1376        charBuf->append((char)22);
1377        nOps = 0;
1378        break;
1379      case 0x0017:              // vstemhm
1380        // ignored
1381        if (firstOp) {
1382          cvtGlyphWidth(nOps & 1, charBuf, pDict);
1383          firstOp = gFalse;
1384        }
1385        if (nOps & 1) {
1386          //~ error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1387        }
1388        nHints += nOps / 2;
1389        nOps = 0;
1390        break;
1391      case 0x0018:              // rcurveline
1392        if (nOps < 8 || (nOps - 2) % 6 != 0) {
1393          //~ error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1394        }
1395        for (k = 0; k < nOps - 2; k += 6) {
1396          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1397          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1398          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1399          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1400          cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1401          cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1402          charBuf->append((char)8);
1403        }
1404        cvtNum(ops[k].num, ops[k].isFP, charBuf);
1405        cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1406        charBuf->append((char)5);
1407        nOps = 0;
1408        openPath = gTrue;
1409        break;
1410      case 0x0019:              // rlinecurve
1411        if (nOps < 8 || (nOps - 6) % 2 != 0) {
1412          //~ error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1413        }
1414        for (k = 0; k < nOps - 6; k += 2) {
1415          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1416          cvtNum(ops[k+1].num, ops[k].isFP, charBuf);
1417          charBuf->append((char)5);
1418        }
1419        cvtNum(ops[k].num, ops[k].isFP, charBuf);
1420        cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1421        cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1422        cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1423        cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1424        cvtNum(ops[k+5].num, ops[k+5].isFP, charBuf);
1425        charBuf->append((char)8);
1426        nOps = 0;
1427        openPath = gTrue;
1428        break;
1429      case 0x001a:              // vvcurveto
1430        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1431          //~ error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1432        }
1433        if (nOps % 2 == 1) {
1434          cvtNum(ops[0].num, ops[0].isFP, charBuf);
1435          cvtNum(ops[1].num, ops[1].isFP, charBuf);
1436          cvtNum(ops[2].num, ops[2].isFP, charBuf);
1437          cvtNum(ops[3].num, ops[3].isFP, charBuf);
1438          cvtNum(0, gFalse, charBuf);
1439          cvtNum(ops[4].num, ops[4].isFP, charBuf);
1440          charBuf->append((char)8);
1441          k = 5;
1442        } else {
1443          k = 0;
1444        }
1445        for (; k < nOps; k += 4) {
1446          cvtNum(0, gFalse, charBuf);
1447          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1448          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1449          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1450          cvtNum(0, gFalse, charBuf);
1451          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1452          charBuf->append((char)8);
1453        }
1454        nOps = 0;
1455        openPath = gTrue;
1456        break;
1457      case 0x001b:              // hhcurveto
1458        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1459          //~ error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1460        }
1461        if (nOps % 2 == 1) {
1462          cvtNum(ops[1].num, ops[1].isFP, charBuf);
1463          cvtNum(ops[0].num, ops[0].isFP, charBuf);
1464          cvtNum(ops[2].num, ops[2].isFP, charBuf);
1465          cvtNum(ops[3].num, ops[3].isFP, charBuf);
1466          cvtNum(ops[4].num, ops[4].isFP, charBuf);
1467          cvtNum(0, gFalse, charBuf);
1468          charBuf->append((char)8);
1469          k = 5;
1470        } else {
1471          k = 0;
1472        }
1473        for (; k < nOps; k += 4) {
1474          cvtNum(ops[k].num, ops[k].isFP, charBuf);
1475          cvtNum(0, gFalse, charBuf);
1476          cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1477          cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1478          cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1479          cvtNum(0, gFalse, charBuf);
1480          charBuf->append((char)8);
1481        }
1482        nOps = 0;
1483        openPath = gTrue;
1484        break;
1485      case 0x001d:              // callgsubr
1486        if (nOps >= 1) {
1487          k = gsubrBias + (int)ops[nOps - 1].num;
1488          --nOps;
1489          ok = gTrue;
1490          getIndexVal(&gsubrIdx, k, &val, &ok);
1491          if (ok) {
1492            cvtGlyph(val.pos, val.len, charBuf, subrIdx, pDict, gFalse);
1493          }
1494        } else {
1495          //~ error(-1, "Too few args to Type 2 callgsubr");
1496        }
1497        // don't clear the stack
1498        break;
1499      case 0x001e:              // vhcurveto
1500        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1501          //~ error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1502        }
1503        for (k = 0; k < nOps && k != nOps-5; k += 4) {
1504          if (k % 8 == 0) {
1505            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1506            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1507            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1508            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1509            charBuf->append((char)30);
1510          } else {
1511            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1512            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1513            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1514            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1515            charBuf->append((char)31);
1516          }
1517        }
1518        if (k == nOps-5) {
1519          if (k % 8 == 0) {
1520            cvtNum(0, gFalse, charBuf);
1521            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1522            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1523            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1524            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1525            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1526          } else {
1527            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1528            cvtNum(0, gFalse, charBuf);
1529            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1530            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1531            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1532            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1533          }
1534          charBuf->append((char)8);
1535        }
1536        nOps = 0;
1537        openPath = gTrue;
1538        break;
1539      case 0x001f:              // hvcurveto
1540        if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1541          //~ error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1542        }
1543        for (k = 0; k < nOps && k != nOps-5; k += 4) {
1544          if (k % 8 == 0) {
1545            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1546            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1547            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1548            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1549            charBuf->append((char)31);
1550          } else {
1551            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1552            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1553            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1554            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1555            charBuf->append((char)30);
1556          }
1557        }
1558        if (k == nOps-5) {
1559          if (k % 8 == 0) {
1560            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1561            cvtNum(0, gFalse, charBuf);
1562            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1563            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1564            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1565            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1566          } else {
1567            cvtNum(0, gFalse, charBuf);
1568            cvtNum(ops[k].num, ops[k].isFP, charBuf);
1569            cvtNum(ops[k+1].num, ops[k+1].isFP, charBuf);
1570            cvtNum(ops[k+2].num, ops[k+2].isFP, charBuf);
1571            cvtNum(ops[k+3].num, ops[k+3].isFP, charBuf);
1572            cvtNum(ops[k+4].num, ops[k+4].isFP, charBuf);
1573          }
1574          charBuf->append((char)8);
1575        }
1576        nOps = 0;
1577        openPath = gTrue;
1578        break;
1579      case 0x0c00:              // dotsection (should be Type 1 only?)
1580        // ignored
1581        nOps = 0;
1582        break;
1583      case 0x0c03:              // and
1584      case 0x0c04:              // or
1585      case 0x0c05:              // not
1586      case 0x0c08:              // store
1587      case 0x0c09:              // abs
1588      case 0x0c0a:              // add
1589      case 0x0c0b:              // sub
1590      case 0x0c0c:              // div
1591      case 0x0c0d:              // load
1592      case 0x0c0e:              // neg
1593      case 0x0c0f:              // eq
1594      case 0x0c12:              // drop
1595      case 0x0c14:              // put
1596      case 0x0c15:              // get
1597      case 0x0c16:              // ifelse
1598      case 0x0c17:              // random
1599      case 0x0c18:              // mul
1600      case 0x0c1a:              // sqrt
1601      case 0x0c1b:              // dup
1602      case 0x0c1c:              // exch
1603      case 0x0c1d:              // index
1604      case 0x0c1e:              // roll
1605        //~ error(-1, "Unimplemented Type 2 charstring op: 12.%d", file[i+1]);
1606        nOps = 0;
1607        break;
1608      case 0x0c22:              // hflex
1609        if (nOps != 7) {
1610          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1611        }
1612        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1613        cvtNum(0, gFalse, charBuf);
1614        cvtNum(ops[1].num, ops[1].isFP, charBuf);
1615        cvtNum(ops[2].num, ops[2].isFP, charBuf);
1616        cvtNum(ops[3].num, ops[3].isFP, charBuf);
1617        cvtNum(0, gFalse, charBuf);
1618        charBuf->append((char)8);
1619        cvtNum(ops[4].num, ops[4].isFP, charBuf);
1620        cvtNum(0, gFalse, charBuf);
1621        cvtNum(ops[5].num, ops[5].isFP, charBuf);
1622        cvtNum(-ops[2].num, ops[2].isFP, charBuf);
1623        cvtNum(ops[6].num, ops[6].isFP, charBuf);
1624        cvtNum(0, gFalse, charBuf);
1625        charBuf->append((char)8);
1626        nOps = 0;
1627        openPath = gTrue;
1628        break;
1629      case 0x0c23:              // flex
1630        if (nOps != 13) {
1631          //~ error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1632        }
1633        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1634        cvtNum(ops[1].num, ops[1].isFP, charBuf);
1635        cvtNum(ops[2].num, ops[2].isFP, charBuf);
1636        cvtNum(ops[3].num, ops[3].isFP, charBuf);
1637        cvtNum(ops[4].num, ops[4].isFP, charBuf);
1638        cvtNum(ops[5].num, ops[5].isFP, charBuf);
1639        charBuf->append((char)8);
1640        cvtNum(ops[6].num, ops[6].isFP, charBuf);
1641        cvtNum(ops[7].num, ops[7].isFP, charBuf);
1642        cvtNum(ops[8].num, ops[8].isFP, charBuf);
1643        cvtNum(ops[9].num, ops[9].isFP, charBuf);
1644        cvtNum(ops[10].num, ops[10].isFP, charBuf);
1645        cvtNum(ops[11].num, ops[11].isFP, charBuf);
1646        charBuf->append((char)8);
1647        nOps = 0;
1648        openPath = gTrue;
1649        break;
1650      case 0x0c24:              // hflex1
1651        if (nOps != 9) {
1652          //~ error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1653        }
1654        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1655        cvtNum(ops[1].num, ops[1].isFP, charBuf);
1656        cvtNum(ops[2].num, ops[2].isFP, charBuf);
1657        cvtNum(ops[3].num, ops[3].isFP, charBuf);
1658        cvtNum(ops[4].num, ops[4].isFP, charBuf);
1659        cvtNum(0, gFalse, charBuf);
1660        charBuf->append((char)8);
1661        cvtNum(ops[5].num, ops[5].isFP, charBuf);
1662        cvtNum(0, gFalse, charBuf);
1663        cvtNum(ops[6].num, ops[6].isFP, charBuf);
1664        cvtNum(ops[7].num, ops[7].isFP, charBuf);
1665        cvtNum(ops[8].num, ops[8].isFP, charBuf);
1666        cvtNum(-(ops[1].num + ops[3].num + ops[7].num),
1667               ops[1].isFP | ops[3].isFP | ops[7].isFP, charBuf);
1668        charBuf->append((char)8);
1669        nOps = 0;
1670        openPath = gTrue;
1671        break;
1672      case 0x0c25:              // flex1
1673        if (nOps != 11) {
1674          //~ error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1675        }
1676        cvtNum(ops[0].num, ops[0].isFP, charBuf);
1677        cvtNum(ops[1].num, ops[1].isFP, charBuf);
1678        cvtNum(ops[2].num, ops[2].isFP, charBuf);
1679        cvtNum(ops[3].num, ops[3].isFP, charBuf);
1680        cvtNum(ops[4].num, ops[4].isFP, charBuf);
1681        cvtNum(ops[5].num, ops[5].isFP, charBuf);
1682        charBuf->append((char)8);
1683        cvtNum(ops[6].num, ops[6].isFP, charBuf);
1684        cvtNum(ops[7].num, ops[7].isFP, charBuf);
1685        cvtNum(ops[8].num, ops[8].isFP, charBuf);
1686        cvtNum(ops[9].num, ops[9].isFP, charBuf);
1687        dx = ops[0].num + ops[2].num + ops[4].num + ops[6].num + ops[8].num;
1688        dy = ops[1].num + ops[3].num + ops[5].num + ops[7].num + ops[9].num;
1689        if (fabs(dx) > fabs(dy)) {
1690          cvtNum(ops[10].num, ops[10].isFP, charBuf);
1691          cvtNum(-dy, ops[1].isFP | ops[3].isFP | ops[5].isFP |
1692                      ops[7].isFP | ops[9].isFP, charBuf);
1693        } else {
1694          cvtNum(-dx, ops[0].isFP | ops[2].isFP | ops[4].isFP |
1695                      ops[6].isFP | ops[8].isFP, charBuf);
1696          cvtNum(ops[10].num, ops[10].isFP, charBuf);
1697        }
1698        charBuf->append((char)8);
1699        nOps = 0;
1700        openPath = gTrue;
1701        break;
1702      default:
1703        //~ error(-1, "Illegal Type 2 charstring op: %04x",
1704        //~       ops[nOps].op);
1705        nOps = 0;
1706        break;
1707      }
1708    }
1709  }
1710
1711  // charstring encryption
1712  if (top) {
1713    r2 = 4330;
1714    for (i = start; i < charBuf->getLength(); ++i) {
1715      byte = charBuf->getChar(i) ^ (r2 >> 8);
1716      charBuf->setChar(i, byte);
1717      r2 = (byte + r2) * 52845 + 22719;
1718    }
1719  }
1720}
1721
1722void FoFiType1C::cvtGlyphWidth(GBool useOp, GooString *charBuf,
1723                               Type1CPrivateDict *pDict) {
1724  double w;
1725  GBool wFP;
1726  int i;
1727
1728  if (useOp) {
1729    w = pDict->nominalWidthX + ops[0].num;
1730    wFP = pDict->nominalWidthXFP | ops[0].isFP;
1731    for (i = 1; i < nOps; ++i) {
1732      ops[i-1] = ops[i];
1733    }
1734    --nOps;
1735  } else {
1736    w = pDict->defaultWidthX;
1737    wFP = pDict->defaultWidthXFP;
1738  }
1739  cvtNum(0, gFalse, charBuf);
1740  cvtNum(w, wFP, charBuf);
1741  charBuf->append((char)13);
1742}
1743
1744void FoFiType1C::cvtNum(double x, GBool isFP, GooString *charBuf) {
1745  Guchar buf[12];
1746  int y, n;
1747
1748  n = 0;
1749  if (isFP) {
1750    if (x >= -32768 && x < 32768) {
1751      y = (int)(x * 256.0);
1752      buf[0] = 255;
1753      buf[1] = (Guchar)(y >> 24);
1754      buf[2] = (Guchar)(y >> 16);
1755      buf[3] = (Guchar)(y >> 8);
1756      buf[4] = (Guchar)y;
1757      buf[5] = 255;
1758      buf[6] = 0;
1759      buf[7] = 0;
1760      buf[8] = 1;
1761      buf[9] = 0;
1762      buf[10] = 12;
1763      buf[11] = 12;
1764      n = 12;
1765    } else {
1766      //~ error(-1, "Type 2 fixed point constant out of range");
1767    }
1768  } else {
1769    y = (int)x;
1770    if (y >= -107 && y <= 107) {
1771      buf[0] = (Guchar)(y + 139);
1772      n = 1;
1773    } else if (y > 107 && y <= 1131) {
1774      y -= 108;
1775      buf[0] = (Guchar)((y >> 8) + 247);
1776      buf[1] = (Guchar)(y & 0xff);
1777      n = 2;
1778    } else if (y < -107 && y >= -1131) {
1779      y = -y - 108;
1780      buf[0] = (Guchar)((y >> 8) + 251);
1781      buf[1] = (Guchar)(y & 0xff);
1782      n = 2;
1783    } else {
1784      buf[0] = 255;
1785      buf[1] = (Guchar)(y >> 24);
1786      buf[2] = (Guchar)(y >> 16);
1787      buf[3] = (Guchar)(y >> 8);
1788      buf[4] = (Guchar)y;
1789      n = 5;
1790    }
1791  }
1792  charBuf->append((char *)buf, n);
1793}
1794
1795void FoFiType1C::eexecWrite(Type1CEexecBuf *eb, char *s) {
1796  Guchar *p;
1797  Guchar x;
1798
1799  for (p = (Guchar *)s; *p; ++p) {
1800    x = *p ^ (eb->r1 >> 8);
1801    eb->r1 = (x + eb->r1) * 52845 + 22719;
1802    if (eb->ascii) {
1803      (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1804      (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1805      eb->line += 2;
1806      if (eb->line == 64) {
1807        (*eb->outputFunc)(eb->outputStream, "\n", 1);
1808        eb->line = 0;
1809      }
1810    } else {
1811      (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1812    }
1813  }
1814}
1815
1816void FoFiType1C::eexecWriteCharstring(Type1CEexecBuf *eb,
1817                                      Guchar *s, int n) {
1818  Guchar x;
1819  int i;
1820
1821  // eexec encryption
1822  for (i = 0; i < n; ++i) {
1823    x = s[i] ^ (eb->r1 >> 8);
1824    eb->r1 = (x + eb->r1) * 52845 + 22719;
1825    if (eb->ascii) {
1826      (*eb->outputFunc)(eb->outputStream, &hexChars[x >> 4], 1);
1827      (*eb->outputFunc)(eb->outputStream, &hexChars[x & 0x0f], 1);
1828      eb->line += 2;
1829      if (eb->line == 64) {
1830        (*eb->outputFunc)(eb->outputStream, "\n", 1);
1831        eb->line = 0;
1832      }
1833    } else {
1834      (*eb->outputFunc)(eb->outputStream, (char *)&x, 1);
1835    }
1836  }
1837}
1838
1839GBool FoFiType1C::parse() {
1840  Type1CIndex fdIdx;
1841  Type1CIndexVal val;
1842  int i;
1843
1844  parsedOk = gTrue;
1845
1846  // some tools embed Type 1C fonts with an extra whitespace char at
1847  // the beginning
1848  if (len > 0 && file[0] != '\x01') {
1849    ++file;
1850    --len;
1851  }
1852
1853  // find the indexes
1854  getIndex(getU8(2, &parsedOk), &nameIdx, &parsedOk);
1855  getIndex(nameIdx.endPos, &topDictIdx, &parsedOk);
1856  getIndex(topDictIdx.endPos, &stringIdx, &parsedOk);
1857  getIndex(stringIdx.endPos, &gsubrIdx, &parsedOk);
1858  if (!parsedOk) {
1859    return gFalse;
1860  }
1861  gsubrBias = (gsubrIdx.len < 1240) ? 107
1862                                    : (gsubrIdx.len < 33900) ? 1131 : 32768;
1863
1864  // read the first font name
1865  getIndexVal(&nameIdx, 0, &val, &parsedOk);
1866  if (!parsedOk) {
1867    return gFalse;
1868  }
1869  name = new GooString((char *)&file[val.pos], val.len);
1870
1871  // read the top dict for the first font
1872  readTopDict();
1873
1874  // for CID fonts: read the FDArray dicts and private dicts
1875  if (topDict.firstOp == 0x0c1e) {
1876    if (topDict.fdArrayOffset == 0) {
1877      nFDs = 1;
1878      privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1879      readPrivateDict(0, 0, &privateDicts[0]);
1880    } else {
1881      getIndex(topDict.fdArrayOffset, &fdIdx, &parsedOk);
1882      if (!parsedOk) {
1883        return gFalse;
1884      }
1885      nFDs = fdIdx.len;
1886      privateDicts = (Type1CPrivateDict *)
1887                         gmallocn(nFDs, sizeof(Type1CPrivateDict));
1888      for (i = 0; i < nFDs; ++i) {
1889        getIndexVal(&fdIdx, i, &val, &parsedOk);
1890        if (!parsedOk) {
1891          return gFalse;
1892        }
1893        readFD(val.pos, val.len, &privateDicts[i]);
1894      }
1895    }
1896
1897  // for 8-bit fonts: read the private dict
1898  } else {
1899    privateDicts = (Type1CPrivateDict *)gmalloc(sizeof(Type1CPrivateDict));
1900    readPrivateDict(topDict.privateOffset, topDict.privateSize,
1901                    &privateDicts[0]);
1902  }
1903
1904  // check for parse errors in the private dict(s)
1905  if (!parsedOk) {
1906    return gFalse;
1907  }
1908
1909  // get the charstrings index
1910  if (topDict.charStringsOffset <= 0) {
1911    parsedOk = gFalse;
1912    return gFalse;
1913  }
1914  getIndex(topDict.charStringsOffset, &charStringsIdx, &parsedOk);
1915  if (!parsedOk) {
1916    return gFalse;
1917  }
1918  nGlyphs = charStringsIdx.len;
1919
1920  // for CID fonts: read the FDSelect table
1921  if (topDict.firstOp == 0x0c1e) {
1922    readFDSelect();
1923    if (!parsedOk) {
1924      return gFalse;
1925    }
1926  }
1927
1928  // read the charset
1929  if (!readCharset()) {
1930    parsedOk = gFalse;
1931    return gFalse;
1932  }
1933
1934  // for 8-bit fonts: build the encoding
1935  if (topDict.firstOp != 0x0c14 && topDict.firstOp != 0x0c1e) {
1936    buildEncoding();
1937    if (!parsedOk) {
1938      return gFalse;
1939    }
1940  }
1941
1942  return parsedOk;
1943}
1944
1945void FoFiType1C::readTopDict() {
1946  Type1CIndexVal topDictPtr;
1947  int pos;
1948
1949  topDict.firstOp = -1;
1950  topDict.versionSID = 0;
1951  topDict.noticeSID = 0;
1952  topDict.copyrightSID = 0;
1953  topDict.fullNameSID = 0;
1954  topDict.familyNameSID = 0;
1955  topDict.weightSID = 0;
1956  topDict.isFixedPitch = 0;
1957  topDict.italicAngle = 0;
1958  topDict.underlinePosition = -100;
1959  topDict.underlineThickness = 50;
1960  topDict.paintType = 0;
1961  topDict.charstringType = 2;
1962  topDict.fontMatrix[0] = 0.001;
1963  topDict.fontMatrix[1] = 0;
1964  topDict.fontMatrix[2] = 0;
1965  topDict.fontMatrix[3] = 0.001;
1966  topDict.fontMatrix[4] = 0;
1967  topDict.fontMatrix[5] = 0;
1968  topDict.hasFontMatrix = gFalse;
1969  topDict.uniqueID = 0;
1970  topDict.fontBBox[0] = 0;
1971  topDict.fontBBox[1] = 0;
1972  topDict.fontBBox[2] = 0;
1973  topDict.fontBBox[3] = 0;
1974  topDict.strokeWidth = 0;
1975  topDict.charsetOffset = 0;
1976  topDict.encodingOffset = 0;
1977  topDict.charStringsOffset = 0;
1978  topDict.privateSize = 0;
1979  topDict.privateOffset = 0;
1980  topDict.registrySID = 0;
1981  topDict.orderingSID = 0;
1982  topDict.supplement = 0;
1983  topDict.fdArrayOffset = 0;
1984  topDict.fdSelectOffset = 0;
1985
1986  getIndexVal(&topDictIdx, 0, &topDictPtr, &parsedOk);
1987  pos = topDictPtr.pos;
1988  nOps = 0;
1989  while (pos < topDictPtr.pos + topDictPtr.len) {
1990    pos = getOp(pos, gFalse, &parsedOk);
1991    if (!parsedOk) {
1992      break;
1993    }
1994    if (!ops[nOps - 1].isNum) {
1995      --nOps; // drop the operator
1996      if (topDict.firstOp < 0) {
1997        topDict.firstOp = ops[nOps].op;
1998      }
1999      switch (ops[nOps].op) {
2000      case 0x0000: topDict.versionSID = (int)ops[0].num; break;
2001      case 0x0001: topDict.noticeSID = (int)ops[0].num; break;
2002      case 0x0c00: topDict.copyrightSID = (int)ops[0].num; break;
2003      case 0x0002: topDict.fullNameSID = (int)ops[0].num; break;
2004      case 0x0003: topDict.familyNameSID = (int)ops[0].num; break;
2005      case 0x0004: topDict.weightSID = (int)ops[0].num; break;
2006      case 0x0c01: topDict.isFixedPitch = (int)ops[0].num; break;
2007      case 0x0c02: topDict.italicAngle = ops[0].num; break;
2008      case 0x0c03: topDict.underlinePosition = ops[0].num; break;
2009      case 0x0c04: topDict.underlineThickness = ops[0].num; break;
2010      case 0x0c05: topDict.paintType = (int)ops[0].num; break;
2011      case 0x0c06: topDict.charstringType = (int)ops[0].num; break;
2012      case 0x0c07: topDict.fontMatrix[0] = ops[0].num;
2013                   topDict.fontMatrix[1] = ops[1].num;
2014                   topDict.fontMatrix[2] = ops[2].num;
2015                   topDict.fontMatrix[3] = ops[3].num;
2016                   topDict.fontMatrix[4] = ops[4].num;
2017                   topDict.fontMatrix[5] = ops[5].num;
2018                   topDict.hasFontMatrix = gTrue; break;
2019      case 0x000d: topDict.uniqueID = (int)ops[0].num; break;
2020      case 0x0005: topDict.fontBBox[0] = ops[0].num;
2021                   topDict.fontBBox[1] = ops[1].num;
2022                   topDict.fontBBox[2] = ops[2].num;
2023                   topDict.fontBBox[3] = ops[3].num; break;
2024      case 0x0c08: topDict.strokeWidth = ops[0].num; break;
2025      case 0x000f: topDict.charsetOffset = (int)ops[0].num; break;
2026      case 0x0010: topDict.encodingOffset = (int)ops[0].num; break;
2027      case 0x0011: topDict.charStringsOffset = (int)ops[0].num; break;
2028      case 0x0012: topDict.privateSize = (int)ops[0].num;
2029                   topDict.privateOffset = (int)ops[1].num; break;
2030      case 0x0c1e: topDict.registrySID = (int)ops[0].num;
2031                   topDict.orderingSID = (int)ops[1].num;
2032                   topDict.supplement = (int)ops[2].num; break;
2033      case 0x0c24: topDict.fdArrayOffset = (int)ops[0].num; break;
2034      case 0x0c25: topDict.fdSelectOffset = (int)ops[0].num; break;
2035      }
2036      nOps = 0;
2037    }
2038  }
2039}
2040
2041// Read a CID font dict (FD) - this pulls out the private dict
2042// pointer, and reads the private dict.  It also pulls the FontMatrix
2043// (if any) out of the FD.
2044void FoFiType1C::readFD(int offset, int length, Type1CPrivateDict *pDict) {
2045  int pos, pSize, pOffset;
2046  double fontMatrix[6] = {0};
2047  GBool hasFontMatrix;
2048
2049  hasFontMatrix = gFalse;
2050  pSize = pOffset = 0;
2051  pos = offset;
2052  nOps = 0;
2053  while (pos < offset + length) {
2054    pos = getOp(pos, gFalse, &parsedOk);
2055    if (!parsedOk) {
2056      return;
2057    }
2058    if (!ops[nOps - 1].isNum) {
2059      if (ops[nOps - 1].op == 0x0012) {
2060        if (nOps < 3) {
2061          parsedOk = gFalse;
2062          return;
2063        }
2064        pSize = (int)ops[0].num;
2065        pOffset = (int)ops[1].num;
2066        break;
2067      } else if (ops[nOps - 1].op == 0x0c07) {
2068        fontMatrix[0] = ops[0].num;
2069        fontMatrix[1] = ops[1].num;
2070        fontMatrix[2] = ops[2].num;
2071        fontMatrix[3] = ops[3].num;
2072        fontMatrix[4] = ops[4].num;
2073        fontMatrix[5] = ops[5].num;
2074        hasFontMatrix = gTrue;
2075      }
2076      nOps = 0;
2077    }
2078  }
2079  readPrivateDict(pOffset, pSize, pDict);
2080  if (hasFontMatrix) {
2081    pDict->fontMatrix[0] = fontMatrix[0];
2082    pDict->fontMatrix[1] = fontMatrix[1];
2083    pDict->fontMatrix[2] = fontMatrix[2];
2084    pDict->fontMatrix[3] = fontMatrix[3];
2085    pDict->fontMatrix[4] = fontMatrix[4];
2086    pDict->fontMatrix[5] = fontMatrix[5];
2087    pDict->hasFontMatrix = gTrue;
2088  }
2089}
2090
2091void FoFiType1C::readPrivateDict(int offset, int length,
2092                                 Type1CPrivateDict *pDict) {
2093  int pos;
2094
2095  pDict->hasFontMatrix = gFalse;
2096  pDict->nBlueValues = 0;
2097  pDict->nOtherBlues = 0;
2098  pDict->nFamilyBlues = 0;
2099  pDict->nFamilyOtherBlues = 0;
2100  pDict->blueScale = 0.039625;
2101  pDict->blueShift = 7;
2102  pDict->blueFuzz = 1;
2103  pDict->hasStdHW = gFalse;
2104  pDict->hasStdVW = gFalse;
2105  pDict->nStemSnapH = 0;
2106  pDict->nStemSnapV = 0;
2107  pDict->hasForceBold = gFalse;
2108  pDict->forceBoldThreshold = 0;
2109  pDict->languageGroup = 0;
2110  pDict->expansionFactor = 0.06;
2111  pDict->initialRandomSeed = 0;
2112  pDict->subrsOffset = 0;
2113  pDict->defaultWidthX = 0;
2114  pDict->defaultWidthXFP = gFalse;
2115  pDict->nominalWidthX = 0;
2116  pDict->nominalWidthXFP = gFalse;
2117
2118  // no dictionary
2119  if (offset == 0 || length == 0) {
2120    return;
2121  }
2122
2123  pos = offset;
2124  nOps = 0;
2125  while (pos < offset + length) {
2126    pos = getOp(pos, gFalse, &parsedOk);
2127    if (!parsedOk) {
2128      break;
2129    }
2130    if (!ops[nOps - 1].isNum) {
2131      --nOps; // drop the operator
2132      switch (ops[nOps].op) {
2133      case 0x0006:
2134        pDict->nBlueValues = getDeltaIntArray(pDict->blueValues,
2135                                              type1CMaxBlueValues);
2136        break;
2137      case 0x0007:
2138        pDict->nOtherBlues = getDeltaIntArray(pDict->otherBlues,
2139                                              type1CMaxOtherBlues);
2140        break;
2141      case 0x0008:
2142        pDict->nFamilyBlues = getDeltaIntArray(pDict->familyBlues,
2143                                               type1CMaxBlueValues);
2144        break;
2145      case 0x0009:
2146        pDict->nFamilyOtherBlues = getDeltaIntArray(pDict->familyOtherBlues,
2147                                                    type1CMaxOtherBlues);
2148        break;
2149      case 0x0c09:
2150        pDict->blueScale = ops[0].num;
2151        break;
2152      case 0x0c0a:
2153        pDict->blueShift = (int)ops[0].num;
2154        break;
2155      case 0x0c0b:
2156        pDict->blueFuzz = (int)ops[0].num;
2157        break;
2158      case 0x000a:
2159        pDict->stdHW = ops[0].num;
2160        pDict->hasStdHW = gTrue;
2161        break;
2162      case 0x000b:
2163        pDict->stdVW = ops[0].num;
2164        pDict->hasStdVW = gTrue;
2165        break;
2166      case 0x0c0c:
2167        pDict->nStemSnapH = getDeltaFPArray(pDict->stemSnapH,
2168                                            type1CMaxStemSnap);
2169        break;
2170      case 0x0c0d:
2171        pDict->nStemSnapV = getDeltaFPArray(pDict->stemSnapV,
2172                                            type1CMaxStemSnap);
2173        break;
2174      case 0x0c0e:
2175        pDict->forceBold = ops[0].num != 0;
2176        pDict->hasForceBold = gTrue;
2177        break;
2178      case 0x0c0f:
2179        pDict->forceBoldThreshold = ops[0].num;
2180        break;
2181      case 0x0c11:
2182        pDict->languageGroup = (int)ops[0].num;
2183        break;
2184      case 0x0c12:
2185        pDict->expansionFactor = ops[0].num;
2186        break;
2187      case 0x0c13:
2188        pDict->initialRandomSeed = (int)ops[0].num;
2189        break;
2190      case 0x0013:
2191        pDict->subrsOffset = offset + (int)ops[0].num;
2192        break;
2193      case 0x0014:
2194        pDict->defaultWidthX = ops[0].num;
2195        pDict->defaultWidthXFP = ops[0].isFP;
2196        break;
2197      case 0x0015:
2198        pDict->nominalWidthX = ops[0].num;
2199        pDict->nominalWidthXFP = ops[0].isFP;
2200        break;
2201      }
2202      nOps = 0;
2203    }
2204  }
2205}
2206
2207void FoFiType1C::readFDSelect() {
2208  int fdSelectFmt, pos, nRanges, gid0, gid1, fd, i, j;
2209
2210  fdSelect = (Guchar *)gmalloc(nGlyphs);
2211  if (topDict.fdSelectOffset == 0) {
2212    for (i = 0; i < nGlyphs; ++i) {
2213      fdSelect[i] = 0;
2214    }
2215  } else {
2216    pos = topDict.fdSelectOffset;
2217    fdSelectFmt = getU8(pos++, &parsedOk);
2218    if (!parsedOk) {
2219      return;
2220    }
2221    if (fdSelectFmt == 0) {
2222      if (!checkRegion(pos, nGlyphs)) {
2223        parsedOk = gFalse;
2224        return;
2225      }
2226      memcpy(fdSelect, file + pos, nGlyphs);
2227    } else if (fdSelectFmt == 3) {
2228      nRanges = getU16BE(pos, &parsedOk);
2229      pos += 2;
2230      gid0 = getU16BE(pos, &parsedOk);
2231      pos += 2;
2232      for (i = 1; i <= nRanges; ++i) {
2233        fd = getU8(pos++, &parsedOk);
2234        gid1 = getU16BE(pos, &parsedOk);
2235        if (!parsedOk) {
2236          return;
2237        }
2238        pos += 2;
2239        if (gid0 > gid1 || gid1 > nGlyphs) {
2240          //~ error(-1, "Bad FDSelect table in CID font");
2241          parsedOk = gFalse;
2242          return;
2243        }
2244        for (j = gid0; j < gid1; ++j) {
2245          fdSelect[j] = fd;
2246        }
2247        gid0 = gid1;
2248      }
2249    } else {
2250      //~ error(-1, "Unknown FDSelect table format in CID font");
2251      for (i = 0; i < nGlyphs; ++i) {
2252        fdSelect[i] = 0;
2253      }
2254    }
2255  }
2256}
2257
2258void FoFiType1C::buildEncoding() {
2259  char buf[256];
2260  int nCodes, nRanges, encFormat;
2261  int pos, c, sid, nLeft, nSups, i, j;
2262
2263  if (topDict.encodingOffset == 0) {
2264    encoding = fofiType1StandardEncoding;
2265
2266  } else if (topDict.encodingOffset == 1) {
2267    encoding = fofiType1ExpertEncoding;
2268
2269  } else {
2270    encoding = (char **)gmallocn(256, sizeof(char *));
2271    for (i = 0; i < 256; ++i) {
2272      encoding[i] = NULL;
2273    }
2274    pos = topDict.encodingOffset;
2275    encFormat = getU8(pos++, &parsedOk);
2276    if (!parsedOk) {
2277      return;
2278    }
2279    if ((encFormat & 0x7f) == 0) {
2280      nCodes = 1 + getU8(pos++, &parsedOk);
2281      if (!parsedOk) {
2282        return;
2283      }
2284      if (nCodes > nGlyphs) {
2285        nCodes = nGlyphs;
2286      }
2287      for (i = 1; i < nCodes; ++i) {
2288        c = getU8(pos++, &parsedOk);
2289        if (!parsedOk) {
2290          return;
2291        }
2292        if (encoding[c]) {
2293          gfree(encoding[c]);
2294        }
2295        encoding[c] = copyString(getString(charset[i], buf, &parsedOk));
2296      }
2297    } else if ((encFormat & 0x7f) == 1) {
2298      nRanges = getU8(pos++, &parsedOk);
2299      if (!parsedOk) {
2300        return;
2301      }
2302      nCodes = 1;
2303      for (i = 0; i < nRanges; ++i) {
2304        c = getU8(pos++, &parsedOk);
2305        nLeft = getU8(pos++, &parsedOk);
2306        if (!parsedOk) {
2307          return;
2308        }
2309        for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
2310          if (c < 256) {
2311            if (encoding[c]) {
2312              gfree(encoding[c]);
2313            }
2314            encoding[c] = copyString(getString(charset[nCodes], buf,
2315                                               &parsedOk));
2316          }
2317          ++nCodes;
2318          ++c;
2319        }
2320      }
2321    }
2322    if (encFormat & 0x80) {
2323      nSups = getU8(pos++, &parsedOk);
2324      if (!parsedOk) {
2325        return;
2326      }
2327      for (i = 0; i < nSups; ++i) {
2328        c = getU8(pos++, &parsedOk);;
2329        if (!parsedOk) {
2330          return;;
2331        }
2332        sid = getU16BE(pos, &parsedOk);
2333        pos += 2;
2334        if (!parsedOk) {
2335          return;
2336        }
2337        if (encoding[c]) {
2338          gfree(encoding[c]);
2339        }
2340        encoding[c] = copyString(getString(sid, buf, &parsedOk));
2341      }
2342    }
2343  }
2344}
2345
2346GBool FoFiType1C::readCharset() {
2347  int charsetFormat, c, pos;
2348  int nLeft, i, j;
2349
2350  if (topDict.charsetOffset == 0) {
2351    charset = fofiType1CISOAdobeCharset;
2352  } else if (topDict.charsetOffset == 1) {
2353    charset = fofiType1CExpertCharset;
2354  } else if (topDict.charsetOffset == 2) {
2355    charset = fofiType1CExpertSubsetCharset;
2356  } else {
2357    charset = (Gushort *)gmallocn(nGlyphs, sizeof(Gushort));
2358    for (i = 0; i < nGlyphs; ++i) {
2359      charset[i] = 0;
2360    }
2361    pos = topDict.charsetOffset;
2362    charsetFormat = getU8(pos++, &parsedOk);
2363    if (charsetFormat == 0) {
2364      for (i = 1; i < nGlyphs; ++i) {
2365        charset[i] = (Gushort)getU16BE(pos, &parsedOk);
2366        pos += 2;
2367        if (!parsedOk) {
2368          break;
2369        }
2370      }
2371    } else if (charsetFormat == 1) {
2372      i = 1;
2373      while (i < nGlyphs) {
2374        c = getU16BE(pos, &parsedOk);
2375        pos += 2;
2376        nLeft = getU8(pos++, &parsedOk);
2377        if (!parsedOk) {
2378          break;
2379        }
2380        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2381          charset[i++] = (Gushort)c++;
2382        }
2383      }
2384    } else if (charsetFormat == 2) {
2385      i = 1;
2386      while (i < nGlyphs) {
2387        c = getU16BE(pos, &parsedOk);
2388        pos += 2;
2389        nLeft = getU16BE(pos, &parsedOk);
2390        pos += 2;
2391        if (!parsedOk) {
2392          break;
2393        }
2394        for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
2395          charset[i++] = (Gushort)c++;
2396        }
2397      }
2398    }
2399    if (!parsedOk) {
2400      gfree(charset);
2401      charset = NULL;
2402      return gFalse;
2403    }
2404  }
2405  return gTrue;
2406}
2407
2408int FoFiType1C::getOp(int pos, GBool charstring, GBool *ok) {
2409  static char nybChars[16] = "0123456789.ee -";
2410  Type1COp op;
2411  char buf[65];
2412  int b0, b1, nyb0, nyb1, x, i;
2413
2414  b0 = getU8(pos++, ok);
2415  op.isNum = gTrue;
2416  op.isFP = gFalse;
2417
2418  if (b0 == 28) {
2419    x = getU8(pos++, ok);
2420    x = (x << 8) | getU8(pos++, ok);
2421    if (x & 0x8000) {
2422      x |= ~0xffff;
2423    }
2424    op.num = x;
2425
2426  } else if (!charstring && b0 == 29) {
2427    x = getU8(pos++, ok);
2428    x = (x << 8) | getU8(pos++, ok);
2429    x = (x << 8) | getU8(pos++, ok);
2430    x = (x << 8) | getU8(pos++, ok);
2431    if (x & 0x80000000) {
2432      x |= ~0xffffffff;
2433    }
2434    op.num = x;
2435
2436  } else if (!charstring && b0 == 30) {
2437    i = 0;
2438    do {
2439      b1 = getU8(pos++, ok);
2440      nyb0 = b1 >> 4;
2441      nyb1 = b1 & 0x0f;
2442      if (nyb0 == 0xf) {
2443        break;
2444      }
2445      buf[i++] = nybChars[nyb0];
2446      if (i == 64) {
2447        break;
2448      }
2449      if (nyb0 == 0xc) {
2450        buf[i++] = '-';
2451      }
2452      if (i == 64) {
2453        break;
2454      }
2455      if (nyb1 == 0xf) {
2456        break;
2457      }
2458      buf[i++] = nybChars[nyb1];
2459      if (i == 64) {
2460        break;
2461      }
2462      if (nyb1 == 0xc) {
2463        buf[i++] = '-';
2464      }
2465    } while (i < 64);
2466    buf[i] = '\0';
2467    op.num = atof(buf);
2468    op.isFP = gTrue;
2469
2470  } else if (b0 >= 32 && b0 <= 246) {
2471    op.num = b0 - 139;
2472
2473  } else if (b0 >= 247 && b0 <= 250) {
2474    op.num = ((b0 - 247) << 8) + getU8(pos++, ok) + 108;
2475
2476  } else if (b0 >= 251 && b0 <= 254) {
2477    op.num = -((b0 - 251) << 8) - getU8(pos++, ok) - 108;
2478
2479  } else if (charstring && b0 == 255) {
2480    x = getU8(pos++, ok);
2481    x = (x << 8) | getU8(pos++, ok);
2482    x = (x << 8) | getU8(pos++, ok);
2483    x = (x << 8) | getU8(pos++, ok);
2484    if (x & 0x80000000) {
2485      x |= ~0xffffffff;
2486    }
2487    op.num = (double)x / 65536.0;
2488    op.isFP = gTrue;
2489
2490  } else if (b0 == 12) {
2491    op.isNum = gFalse;
2492    op.op = 0x0c00 + getU8(pos++, ok);
2493
2494  } else {
2495    op.isNum = gFalse;
2496    op.op = b0;
2497  }
2498
2499  if (nOps < 49) {
2500    ops[nOps++] = op;
2501  }
2502
2503  return pos;
2504}
2505
2506// Convert the delta-encoded ops array to an array of ints.
2507int FoFiType1C::getDeltaIntArray(int *arr, int maxLen) {
2508  int x;
2509  int n, i;
2510
2511  if ((n = nOps) > maxLen) {
2512    n = maxLen;
2513  }
2514  x = 0;
2515  for (i = 0; i < n; ++i) {
2516    x += (int)ops[i].num;
2517    arr[i] = x;
2518  }
2519  return n;
2520}
2521
2522// Convert the delta-encoded ops array to an array of doubles.
2523int FoFiType1C::getDeltaFPArray(double *arr, int maxLen) {
2524  double x;
2525  int n, i;
2526
2527  if ((n = nOps) > maxLen) {
2528    n = maxLen;
2529  }
2530  x = 0;
2531  for (i = 0; i < n; ++i) {
2532    x += ops[i].num;
2533    arr[i] = x;
2534  }
2535  return n;
2536}
2537
2538void FoFiType1C::getIndex(int pos, Type1CIndex *idx, GBool *ok) {
2539  idx->pos = pos;
2540  idx->len = getU16BE(pos, ok);
2541  if (idx->len == 0) {
2542    // empty indexes are legal and contain just the length field
2543    idx->offSize = 0;
2544    idx->startPos = idx->endPos = pos + 2;
2545  } else {
2546    idx->offSize = getU8(pos + 2, ok);
2547    if (idx->offSize < 1 || idx->offSize > 4) {
2548      *ok = gFalse;
2549    }
2550    idx->startPos = pos + 3 + (idx->len + 1) * idx->offSize - 1;
2551    if (idx->startPos < 0 || idx->startPos >= len) {
2552      *ok = gFalse;
2553    }
2554    idx->endPos = idx->startPos + getUVarBE(pos + 3 + idx->len * idx->offSize,
2555                                            idx->offSize, ok);
2556    if (idx->endPos < idx->startPos || idx->endPos > len) {
2557      *ok = gFalse;
2558    }
2559  }
2560}
2561
2562void FoFiType1C::getIndexVal(Type1CIndex *idx, int i,
2563                             Type1CIndexVal *val, GBool *ok) {
2564  int pos0, pos1;
2565
2566  if (i < 0 || i >= idx->len) {
2567    *ok = gFalse;
2568    return;
2569  }
2570  pos0 = idx->startPos + getUVarBE(idx->pos + 3 + i * idx->offSize,
2571                                   idx->offSize, ok);
2572  pos1 = idx->startPos + getUVarBE(idx->pos + 3 + (i + 1) * idx->offSize,
2573                                   idx->offSize, ok);
2574  if (pos0 < idx->startPos || pos0 > idx->endPos ||
2575      pos1 <= idx->startPos || pos1 > idx->endPos ||
2576      pos1 < pos0) {
2577    *ok = gFalse;
2578  }
2579  val->pos = pos0;
2580  val->len = pos1 - pos0;
2581}
2582
2583char *FoFiType1C::getString(int sid, char *buf, GBool *ok) {
2584  Type1CIndexVal val;
2585  int n;
2586
2587  if (sid < 391) {
2588    strcpy(buf, fofiType1CStdStrings[sid]);
2589  } else {
2590    sid -= 391;
2591    getIndexVal(&stringIdx, sid, &val, ok);
2592    if (*ok) {
2593      if ((n = val.len) > 255) {
2594        n = 255;
2595      }
2596      strncpy(buf, (char *)&file[val.pos], n);
2597      buf[n] = '\0';
2598    } else {
2599      buf[0] = '\0';
2600    }
2601  }
2602  return buf;
2603}
Note: See TracBrowser for help on using the repository browser.