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