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