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

Last change on this file since 2 was 2, checked in by Eugene Romanenko, 15 years ago

First import

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