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