upgraded to xpdf-3.01pl1
[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 *)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
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     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
386 void FoFiType1C::convertToCIDType0(char *psName,
387                                    FoFiOutputFunc outputFunc,
388                                    void *outputStream) {
389   int *cidMap;
390   GString *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 GString();
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
673 void 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
948 void FoFiType1C::eexecCvtGlyph(Type1CEexecBuf *eb, char *glyphName,
949                                int offset, int nBytes,
950                                Type1CIndex *subrIdx,
951                                Type1CPrivateDict *pDict) {
952   char buf[512];
953   GString *charBuf;
954
955   // generate the charstring
956   charBuf = new GString();
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
968 void FoFiType1C::cvtGlyph(int offset, int nBytes, GString *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
1600 void FoFiType1C::cvtGlyphWidth(GBool useOp, GString *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
1622 void FoFiType1C::cvtNum(double x, GBool isFP, GString *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
1673 void 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
1694 void 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
1717 GBool 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 GString((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
1823 void 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.
1922 void 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
1969 void 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
2085 void 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
2136 void 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
2224 GBool 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
2286 int 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.
2385 int 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.
2401 int 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
2416 void 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
2440 void 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
2461 char *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 }