]> www.fi.muni.cz Git - evince.git/blob - pdf/xpdf/FontFile.cc
6860e4acec3791cfd92e0d01f89f540abfc6865d
[evince.git] / pdf / xpdf / FontFile.cc
1 //========================================================================
2 //
3 // FontFile.cc
4 //
5 // Copyright 1999-2002 Glyph & Cog, LLC
6 //
7 //========================================================================
8
9 #include <aconf.h>
10
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
13 #endif
14
15 #include <locale.h>
16 #include <math.h>
17 #include <stdlib.h>
18 #include <stddef.h>
19 #include <stdarg.h>
20 #include <string.h>
21 #include <ctype.h>
22 #include "gmem.h"
23 #include "Error.h"
24 #include "GlobalParams.h"
25 #include "CharCodeToUnicode.h"
26 #include "FontEncodingTables.h"
27 #include "FontFile.h"
28
29 #include "CompactFontTables.h"
30
31 //------------------------------------------------------------------------
32
33 static inline char *nextLine(char *line, char *end) {
34   while (line < end && *line != '\n' && *line != '\r')
35     ++line;
36   while (line < end && *line == '\n' || *line == '\r')
37     ++line;
38   return line;
39 }
40
41 static char hexChars[17] = "0123456789ABCDEF";
42
43 //------------------------------------------------------------------------
44 // FontFile
45 //------------------------------------------------------------------------
46
47 FontFile::FontFile() {
48 }
49
50 FontFile::~FontFile() {
51 }
52
53 //------------------------------------------------------------------------
54 // Type1FontFile
55 //------------------------------------------------------------------------
56
57 Type1FontFile::Type1FontFile(char *file, int len) {
58   char *line, *line1, *p, *p2;
59   GBool haveEncoding;
60   char buf[256];
61   char c;
62   int n, code, i, j;
63
64   name = NULL;
65   encoding = (char **)gmalloc(256 * sizeof(char *));
66   for (i = 0; i < 256; ++i) {
67     encoding[i] = NULL;
68   }
69   haveEncoding = gFalse;
70
71   for (i = 1, line = file;
72        i <= 100 && line < file + len && !haveEncoding;
73        ++i) {
74
75     // get font name
76     if (!strncmp(line, "/FontName", 9)) {
77       strncpy(buf, line, 255);
78       buf[255] = '\0';
79       if ((p = strchr(buf+9, '/')) &&
80           (p = strtok(p+1, " \t\n\r"))) {
81         name = copyString(p);
82       }
83       line = nextLine(line, file + len);
84
85     // get encoding
86     } else if (!strncmp(line, "/Encoding StandardEncoding def", 30)) {
87       for (j = 0; j < 256; ++j) {
88         if (standardEncoding[j]) {
89           encoding[j] = copyString(standardEncoding[j]);
90         }
91       }
92       haveEncoding = gTrue;
93     } else if (!strncmp(line, "/Encoding 256 array", 19)) {
94       for (j = 0; j < 300; ++j) {
95         line1 = nextLine(line, file + len);
96         if ((n = line1 - line) > 255) {
97           n = 255;
98         }
99         strncpy(buf, line, n);
100         buf[n] = '\0';
101         for (p = buf; *p == ' ' || *p == '\t'; ++p) ;
102         if (!strncmp(p, "dup", 3)) {
103           for (p += 3; *p == ' ' || *p == '\t'; ++p) ;
104           for (p2 = p; *p2 >= '0' && *p2 <= '9'; ++p2) ;
105           if (*p2) {
106             c = *p2;
107             *p2 = '\0';
108             if ((code = atoi(p)) < 256) {
109               *p2 = c;
110               for (p = p2; *p == ' ' || *p == '\t'; ++p) ;
111               if (*p == '/') {
112                 ++p;
113                 for (p2 = p; *p2 && *p2 != ' ' && *p2 != '\t'; ++p2) ;
114                 *p2 = '\0';
115                 encoding[code] = copyString(p);
116               }
117             }
118           }
119         } else {
120           if (strtok(buf, " \t") &&
121               (p = strtok(NULL, " \t\n\r")) && !strcmp(p, "def")) {
122             break;
123           }
124         }
125         line = line1;
126       }
127       //~ check for getinterval/putinterval junk
128       haveEncoding = gTrue;
129
130     } else {
131       line = nextLine(line, file + len);
132     }
133   }
134 }
135
136 Type1FontFile::~Type1FontFile() {
137   int i;
138
139   if (name) {
140     gfree(name);
141   }
142   for (i = 0; i < 256; ++i) {
143     gfree(encoding[i]);
144   }
145   gfree(encoding);
146 }
147
148 //------------------------------------------------------------------------
149 // Type1CFontFile
150 //------------------------------------------------------------------------
151
152 struct Type1CTopDict {
153   int version;
154   int notice;
155   int copyright;
156   int fullName;
157   int familyName;
158   int weight;
159   int isFixedPitch;
160   double italicAngle;
161   double underlinePosition;
162   double underlineThickness;
163   int paintType;
164   int charstringType;
165   double fontMatrix[6];
166   int uniqueID;
167   double fontBBox[4];
168   double strokeWidth;
169   int charset;
170   int encoding;
171   int charStrings;
172   int privateSize;
173   int privateOffset;
174
175   //----- CIDFont entries
176   int registry;
177   int ordering;
178   int supplement;
179   int fdArrayOffset;
180   int fdSelectOffset;
181 };
182
183 struct Type1CPrivateDict {
184   GString *dictData;
185   int subrsOffset;
186   double defaultWidthX;
187   GBool defaultWidthXFP;
188   double nominalWidthX;
189   GBool nominalWidthXFP;
190 };
191
192 Type1CFontFile::Type1CFontFile(char *fileA, int lenA) {
193   Guchar *nameIdxPtr, *idxPtr0, *idxPtr1;
194
195   file = fileA;
196   len = lenA;
197   name = NULL;
198   encoding = NULL;
199
200   // some tools embed Type 1C fonts with an extra whitespace char at
201   // the beginning
202   if (file[0] != '\x01') {
203     ++file;
204   }
205
206   // read header
207   topOffSize = file[3] & 0xff;
208
209   // read name index (first font only)
210   nameIdxPtr = (Guchar *)file + (file[2] & 0xff);
211   idxPtr0 = getIndexValPtr(nameIdxPtr, 0);
212   idxPtr1 = getIndexValPtr(nameIdxPtr, 1);
213   name = new GString((char *)idxPtr0, idxPtr1 - idxPtr0);
214
215   topDictIdxPtr = getIndexEnd(nameIdxPtr);
216   stringIdxPtr = getIndexEnd(topDictIdxPtr);
217   gsubrIdxPtr = getIndexEnd(stringIdxPtr);
218 }
219
220 Type1CFontFile::~Type1CFontFile() {
221   int i;
222
223   delete name;
224   if (encoding) {
225     for (i = 0; i < 256; ++i) {
226       gfree(encoding[i]);
227     }
228     gfree(encoding);
229   }
230 }
231
232 char *Type1CFontFile::getName() {
233   return name->getCString();
234 }
235
236 char **Type1CFontFile::getEncoding() {
237   if (!encoding) {
238     readNameAndEncoding();
239   }
240   return encoding;
241 }
242
243 void Type1CFontFile::readNameAndEncoding() {
244   char buf[256];
245   Guchar *idxPtr0, *idxPtr1, *ptr;
246   int nGlyphs;
247   int nCodes, nRanges, nLeft, nSups;
248   Gushort *glyphNames;
249   int charset, enc, charstrings;
250   int encFormat;
251   int c, sid;
252   double x;
253   GBool isFP;
254   int key;
255   int i, j;
256
257   encoding = (char **)gmalloc(256 * sizeof(char *));
258   for (i = 0; i < 256; ++i) {
259     encoding[i] = NULL;
260   }
261
262   // read top dict (first font only)
263   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
264   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
265   charset = enc = charstrings = 0;
266   i = 0;
267   ptr = idxPtr0;
268   while (ptr < idxPtr1) {
269     if (*ptr <= 27 || *ptr == 31) {
270       key = *ptr++;
271       if (key == 0x0c) {
272         key = (key << 8) | *ptr++;
273       }
274       if (key == 0x0f) { // charset
275         charset = (int)op[0];
276       } else if (key == 0x10) { // encoding
277         enc = (int)op[0];
278       } else if (key == 0x11) { // charstrings
279         charstrings = (int)op[0];
280       }
281       i = 0;
282     } else {
283       x = getNum(&ptr, &isFP);
284       if (i < 48) {
285         op[i++] = x;
286       }
287     }
288   }
289
290   // get number of glyphs from charstrings index
291   nGlyphs = getIndexLen((Guchar *)file + charstrings);
292
293   // read charset (GID -> name mapping)
294   glyphNames = readCharset(charset, nGlyphs);
295
296   // read encoding (GID -> code mapping)
297   if (enc == 0) {
298     for (i = 0; i < 256; ++i) {
299       if (standardEncoding[i]) {
300         encoding[i] = copyString(standardEncoding[i]);
301       }
302     }
303   } else if (enc == 1) {
304     for (i = 0; i < 256; ++i) {
305       if (expertEncoding[i]) {
306         encoding[i] = copyString(expertEncoding[i]);
307       }
308     }
309   } else {
310     ptr = (Guchar *)file + enc;
311     encFormat = *ptr++;
312     if ((encFormat & 0x7f) == 0) {
313       nCodes = 1 + *ptr++;
314       if (nCodes > nGlyphs) {
315         nCodes = nGlyphs;
316       }
317       for (i = 1; i < nCodes; ++i) {
318         c = *ptr++;
319         encoding[c] = copyString(getString(glyphNames[i], buf));
320       }
321     } else if ((encFormat & 0x7f) == 1) {
322       nRanges = *ptr++;
323       nCodes = 1;
324       for (i = 0; i < nRanges; ++i) {
325         c = *ptr++;
326         nLeft = *ptr++;
327         for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
328           encoding[c] = copyString(getString(glyphNames[nCodes], buf));
329           ++nCodes;
330           ++c;
331         }
332       }
333     }
334     if (encFormat & 0x80) {
335       nSups = *ptr++;
336       for (i = 0; i < nSups; ++i) {
337         c = *ptr++;
338         sid = getWord(ptr, 2);
339         ptr += 2;
340         encoding[c] = copyString(getString(sid, buf));
341       }
342     }
343   }
344
345   if (charset > 2) {
346     gfree(glyphNames);
347   }
348 }
349
350 void Type1CFontFile::convertToType1(FontFileOutputFunc outputFuncA,
351                                     void *outputStreamA) {
352   Type1CTopDict dict;
353   Type1CPrivateDict privateDict;
354   char buf[512], eBuf[256];
355   Guchar *idxPtr0, *idxPtr1, *subrsIdxPtr, *charStringsIdxPtr, *ptr;
356   int nGlyphs, nCodes, nRanges, nLeft, nSups;
357   Gushort *glyphNames;
358   int encFormat, nSubrs, nCharStrings;
359   int c, sid;
360   int i, j, n;
361
362   outputFunc = outputFuncA;
363   outputStream = outputStreamA;
364
365   // read top dict (first font only)
366   readTopDict(&dict);
367
368   // get global subrs
369   //~ ... global subrs are unimplemented
370
371   // write header and font dictionary, up to encoding
372   (*outputFunc)(outputStream, "%!FontType1-1.0: ", 17);
373   (*outputFunc)(outputStream, name->getCString(), name->getLength());
374   if (dict.version != 0) {
375     getString(dict.version, buf);
376     (*outputFunc)(outputStream, buf, strlen(buf));
377   }
378   (*outputFunc)(outputStream, "\n", 1);
379   (*outputFunc)(outputStream, "11 dict begin\n", 14);
380   (*outputFunc)(outputStream, "/FontInfo 10 dict dup begin\n", 28);
381   if (dict.version != 0) {
382     (*outputFunc)(outputStream, "/version (", 10);
383     (*outputFunc)(outputStream, buf, strlen(buf));
384     (*outputFunc)(outputStream, ") readonly def\n", 15);
385   }
386   if (dict.notice != 0) {
387     getString(dict.notice, buf);
388     (*outputFunc)(outputStream, "/Notice (", 9);
389     (*outputFunc)(outputStream, buf, strlen(buf));
390     (*outputFunc)(outputStream, ") readonly def\n", 15);
391   }
392   if (dict.copyright != 0) {
393     getString(dict.copyright, buf);
394     (*outputFunc)(outputStream, "/Copyright (", 12);
395     (*outputFunc)(outputStream, buf, strlen(buf));
396     (*outputFunc)(outputStream, ") readonly def\n", 15);
397   }
398   if (dict.fullName != 0) {
399     getString(dict.fullName, buf);
400     (*outputFunc)(outputStream, "/FullName (", 11);
401     (*outputFunc)(outputStream, buf, strlen(buf));
402     (*outputFunc)(outputStream, ") readonly def\n", 15);
403   }
404   if (dict.familyName != 0) {
405     getString(dict.familyName, buf);
406     (*outputFunc)(outputStream, "/FamilyName (", 13);
407     (*outputFunc)(outputStream, buf, strlen(buf));
408     (*outputFunc)(outputStream, ") readonly def\n", 15);
409   }
410   if (dict.weight != 0) {
411     getString(dict.weight, buf);
412     (*outputFunc)(outputStream, "/Weight (", 9);
413     (*outputFunc)(outputStream, buf, strlen(buf));
414     (*outputFunc)(outputStream, ") readonly def\n", 15);
415   }
416   if (dict.isFixedPitch) {
417     (*outputFunc)(outputStream, "/isFixedPitch true def\n", 23);
418   } else {
419     (*outputFunc)(outputStream, "/isFixedPitch false def\n", 24);
420   }
421   sprintf(buf, "/ItalicAngle %g def\n", dict.italicAngle);
422   (*outputFunc)(outputStream, buf, strlen(buf));
423   sprintf(buf, "/UnderlinePosition %g def\n", dict.underlinePosition);
424   (*outputFunc)(outputStream, buf, strlen(buf));
425   sprintf(buf, "/UnderlineThickness %g def\n", dict.underlineThickness);
426   (*outputFunc)(outputStream, buf, strlen(buf));
427   (*outputFunc)(outputStream, "end readonly def\n", 17);
428   (*outputFunc)(outputStream, "/FontName /", 11);
429   (*outputFunc)(outputStream, name->getCString(), name->getLength());
430   (*outputFunc)(outputStream, " def\n", 5);
431   sprintf(buf, "/PaintType %d def\n", dict.paintType);
432   (*outputFunc)(outputStream, buf, strlen(buf));
433   (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
434   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] readonly def\n",
435           dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
436           dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
437   (*outputFunc)(outputStream, buf, strlen(buf));
438   sprintf(buf, "/FontBBox [%g %g %g %g] readonly def\n",
439           dict.fontBBox[0], dict.fontBBox[1],
440           dict.fontBBox[2], dict.fontBBox[3]);
441   (*outputFunc)(outputStream, buf, strlen(buf));
442   sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
443   (*outputFunc)(outputStream, buf, strlen(buf));
444   if (dict.uniqueID != 0) {
445     sprintf(buf, "/UniqueID %d def\n", dict.uniqueID);
446     (*outputFunc)(outputStream, buf, strlen(buf));
447   }
448
449   // get number of glyphs from charstrings index
450   nGlyphs = getIndexLen((Guchar *)file + dict.charStrings);
451
452   // read charset
453   glyphNames = readCharset(dict.charset, nGlyphs);
454
455   // read encoding (glyph -> code mapping), write Type 1 encoding
456   (*outputFunc)(outputStream, "/Encoding ", 10);
457   if (dict.encoding == 0) {
458     (*outputFunc)(outputStream, "StandardEncoding def\n", 21);
459   } else {
460     (*outputFunc)(outputStream, "256 array\n", 10);
461     (*outputFunc)(outputStream,
462                   "0 1 255 {1 index exch /.notdef put} for\n", 40);
463     if (dict.encoding == 1) {
464       for (i = 0; i < 256; ++i) {
465         if (expertEncoding[i]) {
466           sprintf(buf, "dup %d /%s put\n", i, expertEncoding[i]);
467           (*outputFunc)(outputStream, buf, strlen(buf));
468         }
469       }
470     } else {
471       ptr = (Guchar *)file + dict.encoding;
472       encFormat = *ptr++;
473       if ((encFormat & 0x7f) == 0) {
474         nCodes = 1 + *ptr++;
475         if (nCodes > nGlyphs) {
476           nCodes = nGlyphs;
477         }
478         for (i = 1; i < nCodes; ++i) {
479           c = *ptr++;
480           sprintf(buf, "dup %d /", c);
481           (*outputFunc)(outputStream, buf, strlen(buf));
482           getString(glyphNames[i], buf);
483           (*outputFunc)(outputStream, buf, strlen(buf));
484           (*outputFunc)(outputStream, " put\n", 5);
485         }
486       } else if ((encFormat & 0x7f) == 1) {
487         nRanges = *ptr++;
488         nCodes = 1;
489         for (i = 0; i < nRanges; ++i) {
490           c = *ptr++;
491           nLeft = *ptr++;
492           for (j = 0; j <= nLeft && nCodes < nGlyphs; ++j) {
493             sprintf(buf, "dup %d /", c);
494             (*outputFunc)(outputStream, buf, strlen(buf));
495             getString(glyphNames[nCodes], buf);
496             (*outputFunc)(outputStream, buf, strlen(buf));
497             (*outputFunc)(outputStream, " put\n", 5);
498             ++nCodes;
499             ++c;
500           }
501         }
502       }
503       if (encFormat & 0x80) {
504         nSups = *ptr++;
505         for (i = 0; i < nSups; ++i) {
506           c = *ptr++;
507           sid = getWord(ptr, 2);
508           ptr += 2;
509           sprintf(buf, "dup %d /", c);
510           (*outputFunc)(outputStream, buf, strlen(buf));
511           getString(sid, buf);
512           (*outputFunc)(outputStream, buf, strlen(buf));
513           (*outputFunc)(outputStream, " put\n", 5);
514         }
515       }
516     }
517     (*outputFunc)(outputStream, "readonly def\n", 13);
518   }
519   (*outputFunc)(outputStream, "currentdict end\n", 16);
520
521   // start the binary section
522   (*outputFunc)(outputStream, "currentfile eexec\n", 18);
523   r1 = 55665;
524   line = 0;
525
526   // get private dictionary
527   eexecWrite("\x83\xca\x73\xd5");
528   eexecWrite("dup /Private 32 dict dup begin\n");
529   eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
530   eexecWrite("/ND {noaccess def} executeonly def\n");
531   eexecWrite("/NP {noaccess put} executeonly def\n");
532   eexecWrite("/MinFeature {16 16} ND\n");
533   readPrivateDict(&privateDict, dict.privateOffset, dict.privateSize);
534   eexecWrite(privateDict.dictData->getCString());
535   defaultWidthX = privateDict.defaultWidthX;
536   defaultWidthXFP = privateDict.defaultWidthXFP;
537   nominalWidthX = privateDict.nominalWidthX;
538   nominalWidthXFP = privateDict.nominalWidthXFP;
539
540   // get subrs
541   if (privateDict.subrsOffset != 0) {
542     subrsIdxPtr = (Guchar *)file + dict.privateOffset +
543                   privateDict.subrsOffset;
544     nSubrs = getIndexLen(subrsIdxPtr);
545     sprintf(eBuf, "/Subrs %d array\n", nSubrs);
546     eexecWrite(eBuf);
547     idxPtr1 = getIndexValPtr(subrsIdxPtr, 0);
548     for (i = 0; i < nSubrs; ++i) {
549       idxPtr0 = idxPtr1;
550       idxPtr1 = getIndexValPtr(subrsIdxPtr, i+1);
551       n = idxPtr1 - idxPtr0;
552 #if 1 //~ Type 2 subrs are unimplemented
553       error(-1, "Unimplemented Type 2 subrs");
554 #else
555       sprintf(eBuf, "dup %d %d RD ", i, n);
556       eexecWrite(eBuf);
557       eexecCvtGlyph(idxPtr0, n);
558       eexecWrite(" NP\n");
559 #endif
560     }
561     eexecWrite("ND\n");
562   }
563
564   // get CharStrings
565   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
566   nCharStrings = getIndexLen(charStringsIdxPtr);
567   sprintf(eBuf, "2 index /CharStrings %d dict dup begin\n", nCharStrings);
568   eexecWrite(eBuf);
569   idxPtr1 = getIndexValPtr(charStringsIdxPtr, 0);
570   for (i = 0; i < nCharStrings; ++i) {
571     idxPtr0 = idxPtr1;
572     idxPtr1 = getIndexValPtr(charStringsIdxPtr, i+1);
573     n = idxPtr1 - idxPtr0;
574     eexecCvtGlyph(getString(glyphNames[i], buf), idxPtr0, n);
575   }
576   eexecWrite("end\n");
577   eexecWrite("end\n");
578   eexecWrite("readonly put\n");
579   eexecWrite("noaccess put\n");
580   eexecWrite("dup /FontName get exch definefont pop\n");
581   eexecWrite("mark currentfile closefile\n");
582
583   // trailer
584   if (line > 0) {
585     (*outputFunc)(outputStream, "\n", 1);
586   }
587   for (i = 0; i < 8; ++i) {
588     (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
589   }
590   (*outputFunc)(outputStream, "cleartomark\n", 12);
591
592   // clean up
593   delete privateDict.dictData;
594   if (dict.charset > 2) {
595     gfree(glyphNames);
596   }
597 }
598
599 void Type1CFontFile::convertToCIDType0(char *psName,
600                                        FontFileOutputFunc outputFuncA,
601                                        void *outputStreamA) {
602   Type1CTopDict dict;
603   Type1CPrivateDict *privateDicts;
604   GString *charStrings;
605   int *charStringOffsets;
606   Gushort *charset;
607   int *cidMap;
608   Guchar *fdSelect;
609   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
610   char buf[512], buf2[16];
611   int nGlyphs, nCIDs, gdBytes, nFDs;
612   int fdSelectFmt, nRanges, gid0, gid1, fd, offset;
613   int key;
614   double x;
615   GBool isFP;
616   int i, j, k, n;
617
618   outputFunc = outputFuncA;
619   outputStream = outputStreamA;
620
621   (*outputFunc)(outputStream, "/CIDInit /ProcSet findresource begin\n", 37);
622
623   // read top dict (first font only)
624   readTopDict(&dict);
625
626   // read the FDArray dictionaries and Private dictionaries
627   if (dict.fdArrayOffset == 0) {
628     nFDs = 1;
629     privateDicts = (Type1CPrivateDict *)
630                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
631     privateDicts[0].dictData = new GString();
632     privateDicts[0].subrsOffset = 0;
633     privateDicts[0].defaultWidthX = 0;
634     privateDicts[0].defaultWidthXFP = gFalse;
635     privateDicts[0].nominalWidthX = 0;
636     privateDicts[0].nominalWidthXFP = gFalse;
637   } else {
638     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
639     nFDs = getIndexLen(fdArrayIdx);
640     privateDicts = (Type1CPrivateDict *)
641                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
642     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
643     for (i = 0; i < nFDs; ++i) {
644       privateDicts[i].dictData = NULL;
645       idxPtr0 = idxPtr1;
646       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
647       ptr = idxPtr0;
648       j = 0;
649       while (ptr < idxPtr1) {
650         if (*ptr <= 27 || *ptr == 31) {
651           key = *ptr++;
652           if (key == 0x0c) {
653             key = (key << 8) | *ptr++;
654           }
655           if (key == 0x0012) {
656             readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
657           }
658           j = 0;
659         } else {
660           x = getNum(&ptr, &isFP);
661           if (j < 48) {
662             op[j] = x;
663             fp[j++] = isFP;
664           }
665         }
666       }
667       if (!privateDicts[i].dictData) {
668         privateDicts[i].dictData = new GString();
669         privateDicts[i].subrsOffset = 0;
670         privateDicts[i].defaultWidthX = 0;
671         privateDicts[i].defaultWidthXFP = gFalse;
672         privateDicts[i].nominalWidthX = 0;
673         privateDicts[i].nominalWidthXFP = gFalse;
674       }
675     }
676   }
677
678   // get the glyph count
679   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
680   nGlyphs = getIndexLen(charStringsIdxPtr);
681
682   // read the FDSelect table
683   fdSelect = (Guchar *)gmalloc(nGlyphs);
684   if (dict.fdSelectOffset == 0) {
685     for (i = 0; i < nGlyphs; ++i) {
686       fdSelect[i] = 0;
687     }
688   } else {
689     ptr = (Guchar *)file + dict.fdSelectOffset;
690     fdSelectFmt = *ptr++;
691     if (fdSelectFmt == 0) {
692       memcpy(fdSelect, ptr, nGlyphs);
693     } else if (fdSelectFmt == 3) {
694       nRanges = getWord(ptr, 2);
695       ptr += 2;
696       gid0 = getWord(ptr, 2);
697       ptr += 2;
698       for (i = 1; i <= nRanges; ++i) {
699         fd = *ptr++;
700         gid1 = getWord(ptr, 2);
701         ptr += 2;
702         for (j = gid0; j < gid1; ++j) {
703           fdSelect[j] = fd;
704         }
705         gid0 = gid1;
706       }
707     } else {
708       error(-1, "Unknown FDSelect table format in CID font");
709       for (i = 0; i < nGlyphs; ++i) {
710         fdSelect[i] = 0;
711       }
712     }
713   }
714
715   // read the charset, compute the CID-to-GID mapping
716   charset = readCharset(dict.charset, nGlyphs);
717   nCIDs = 0;
718   for (i = 0; i < nGlyphs; ++i) {
719     if (charset[i] >= nCIDs) {
720       nCIDs = charset[i] + 1;
721     }
722   }
723   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
724   for (i = 0; i < nCIDs; ++i) {
725     cidMap[i] = -1;
726   }
727   for (i = 0; i < nGlyphs; ++i) {
728     cidMap[charset[i]] = i;
729   }
730
731   // build the charstrings
732   charStrings = new GString();
733   charStringOffsets = (int *)gmalloc((nCIDs + 1) * sizeof(int));
734   for (i = 0; i < nCIDs; ++i) {
735     charStringOffsets[i] = charStrings->getLength();
736     if (cidMap[i] >= 0) {
737       idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i]);
738       idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i]+1);
739       n = idxPtr1 - idxPtr0;
740       j = fdSelect[cidMap[i]];
741       defaultWidthX = privateDicts[j].defaultWidthX;
742       defaultWidthXFP = privateDicts[j].defaultWidthXFP;
743       nominalWidthX = privateDicts[j].nominalWidthX;
744       nominalWidthXFP = privateDicts[j].nominalWidthXFP;
745       cvtGlyph(idxPtr0, n);
746       charStrings->append(charBuf);
747       delete charBuf;
748     }
749   }
750   charStringOffsets[nCIDs] = charStrings->getLength();
751
752   // compute gdBytes = number of bytes needed for charstring offsets
753   // (offset size needs to account for the charstring offset table,
754   // with a worst case of five bytes per entry, plus the charstrings
755   // themselves)
756   i = (nCIDs + 1) * 5 + charStrings->getLength();
757   if (i < 0x100) {
758     gdBytes = 1;
759   } else if (i < 0x10000) {
760     gdBytes = 2;
761   } else if (i < 0x1000000) {
762     gdBytes = 3;
763   } else {
764     gdBytes = 4;
765   }
766
767   // begin the font dictionary
768   (*outputFunc)(outputStream, "20 dict begin\n", 14);
769   (*outputFunc)(outputStream, "/CIDFontName /", 14);
770   (*outputFunc)(outputStream, psName, strlen(psName));
771   (*outputFunc)(outputStream, " def\n", 5);
772   (*outputFunc)(outputStream, "/CIDFontType 0 def\n", 19);
773   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
774   if (dict.registry > 0 && dict.ordering > 0) {
775     getString(dict.registry, buf);
776     (*outputFunc)(outputStream, "  /Registry (", 13);
777     (*outputFunc)(outputStream, buf, strlen(buf));
778     (*outputFunc)(outputStream, ") def\n", 6);
779     getString(dict.ordering, buf);
780     (*outputFunc)(outputStream, "  /Ordering (", 13);
781     (*outputFunc)(outputStream, buf, strlen(buf));
782     (*outputFunc)(outputStream, ") def\n", 6);
783   } else {
784     (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
785     (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
786   }
787   sprintf(buf, "  /Supplement %d def\n", dict.supplement);
788   (*outputFunc)(outputStream, buf, strlen(buf));
789   (*outputFunc)(outputStream, "end def\n", 8);
790   sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
791           dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
792           dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
793   (*outputFunc)(outputStream, buf, strlen(buf));
794   sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
795           dict.fontBBox[0], dict.fontBBox[1],
796           dict.fontBBox[2], dict.fontBBox[3]);
797   (*outputFunc)(outputStream, buf, strlen(buf));
798   (*outputFunc)(outputStream, "/FontInfo 1 dict dup begin\n", 27);
799   (*outputFunc)(outputStream, "  /FSType 8 def\n", 16);
800   (*outputFunc)(outputStream, "end def\n", 8);
801
802   // CIDFont-specific entries
803   sprintf(buf, "/CIDCount %d def\n", nCIDs);
804   (*outputFunc)(outputStream, buf, strlen(buf));
805   (*outputFunc)(outputStream, "/FDBytes 1 def\n", 15);
806   sprintf(buf, "/GDBytes %d def\n", gdBytes);
807   (*outputFunc)(outputStream, buf, strlen(buf));
808   (*outputFunc)(outputStream, "/CIDMapOffset 0 def\n", 20);
809   if (dict.paintType != 0) {
810     sprintf(buf, "/PaintType %d def\n", dict.paintType);
811     (*outputFunc)(outputStream, buf, strlen(buf));
812     sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
813     (*outputFunc)(outputStream, buf, strlen(buf));
814   }
815
816   // FDArray entry
817   sprintf(buf, "/FDArray %d array\n", nFDs);
818   (*outputFunc)(outputStream, buf, strlen(buf));
819   for (i = 0; i < nFDs; ++i) {
820     sprintf(buf, "dup %d 10 dict begin\n", i);
821     (*outputFunc)(outputStream, buf, strlen(buf));
822     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
823     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
824     sprintf(buf, "/PaintType %d def\n", dict.paintType);
825     (*outputFunc)(outputStream, buf, strlen(buf));
826     (*outputFunc)(outputStream, "/Private 32 dict begin\n", 23);
827     (*outputFunc)(outputStream, privateDicts[i].dictData->getCString(),
828                   privateDicts[i].dictData->getLength());
829     (*outputFunc)(outputStream, "currentdict end def\n", 20);
830     (*outputFunc)(outputStream, "currentdict end put\n", 20);
831   }
832   (*outputFunc)(outputStream, "def\n", 4);
833
834   //~ need to deal with subrs
835   
836   // start the binary section
837   offset = (nCIDs + 1) * (1 + gdBytes);
838   sprintf(buf, "(Hex) %d StartData\n",
839           offset + charStrings->getLength());
840   (*outputFunc)(outputStream, buf, strlen(buf));
841
842   // write the charstring offset (CIDMap) table
843   for (i = 0; i <= nCIDs; i += 6) {
844     for (j = 0; j < 6 && i+j <= nCIDs; ++j) {
845       if (i+j < nCIDs && cidMap[i+j] >= 0) {
846         buf[0] = (char)fdSelect[cidMap[i+j]];
847       } else {
848         buf[0] = (char)0;
849       }
850       n = offset + charStringOffsets[i+j];
851       for (k = gdBytes; k >= 1; --k) {
852         buf[k] = (char)(n & 0xff);
853         n >>= 8;
854       }
855       for (k = 0; k <= gdBytes; ++k) {
856         sprintf(buf2, "%02x", buf[k] & 0xff);
857         (*outputFunc)(outputStream, buf2, 2);
858       }
859     }
860     (*outputFunc)(outputStream, "\n", 1);
861   }
862
863   // write the charstring data
864   n = charStrings->getLength();
865   for (i = 0; i < n; i += 32) {
866     for (j = 0; j < 32 && i+j < n; ++j) {
867       sprintf(buf, "%02x", charStrings->getChar(i+j) & 0xff);
868       (*outputFunc)(outputStream, buf, strlen(buf));
869     }
870     if (i + 32 >= n) {
871       (*outputFunc)(outputStream, ">", 1);
872     }
873     (*outputFunc)(outputStream, "\n", 1);
874   }
875
876   for (i = 0; i < nFDs; ++i) {
877     delete privateDicts[i].dictData;
878   }
879   gfree(privateDicts);
880   gfree(cidMap);
881   gfree(charset);
882   gfree(charStringOffsets);
883   delete charStrings;
884   gfree(fdSelect);
885 }
886
887 void Type1CFontFile::convertToType0(char *psName,
888                                     FontFileOutputFunc outputFuncA,
889                                     void *outputStreamA) {
890   Type1CTopDict dict;
891   Type1CPrivateDict *privateDicts;
892   Gushort *charset;
893   int *cidMap;
894   Guchar *fdSelect;
895   Guchar *charStringsIdxPtr, *fdArrayIdx, *idxPtr0, *idxPtr1, *ptr;
896   char buf[512];
897   char eBuf[256];
898   int nGlyphs, nCIDs, nFDs;
899   int fdSelectFmt, nRanges, gid0, gid1, fd;
900   int key;
901   double x;
902   GBool isFP;
903   int i, j, n;
904
905   outputFunc = outputFuncA;
906   outputStream = outputStreamA;
907
908   // read top dict (first font only)
909   readTopDict(&dict);
910
911   // read the FDArray dictionaries and Private dictionaries
912   if (dict.fdArrayOffset == 0) {
913     nFDs = 1;
914     privateDicts = (Type1CPrivateDict *)
915                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
916     privateDicts[0].dictData = new GString();
917     privateDicts[0].subrsOffset = 0;
918     privateDicts[0].defaultWidthX = 0;
919     privateDicts[0].defaultWidthXFP = gFalse;
920     privateDicts[0].nominalWidthX = 0;
921     privateDicts[0].nominalWidthXFP = gFalse;
922   } else {
923     fdArrayIdx = (Guchar *)file + dict.fdArrayOffset;
924     nFDs = getIndexLen(fdArrayIdx);
925     privateDicts = (Type1CPrivateDict *)
926                      gmalloc(nFDs * sizeof(Type1CPrivateDict));
927     idxPtr1 = getIndexValPtr(fdArrayIdx, 0);
928     for (i = 0; i < nFDs; ++i) {
929       privateDicts[i].dictData = NULL;
930       idxPtr0 = idxPtr1;
931       idxPtr1 = getIndexValPtr(fdArrayIdx, i + 1);
932       ptr = idxPtr0;
933       j = 0;
934       while (ptr < idxPtr1) {
935         if (*ptr <= 27 || *ptr == 31) {
936           key = *ptr++;
937           if (key == 0x0c) {
938             key = (key << 8) | *ptr++;
939           }
940           if (key == 0x0012) {
941             readPrivateDict(&privateDicts[i], (int)op[1], (int)op[0]);
942           }
943           j = 0;
944         } else {
945           x = getNum(&ptr, &isFP);
946           if (j < 48) {
947             op[j] = x;
948             fp[j++] = isFP;
949           }
950         }
951       }
952       if (!privateDicts[i].dictData) {
953         privateDicts[i].dictData = new GString();
954         privateDicts[i].subrsOffset = 0;
955         privateDicts[i].defaultWidthX = 0;
956         privateDicts[i].defaultWidthXFP = gFalse;
957         privateDicts[i].nominalWidthX = 0;
958         privateDicts[i].nominalWidthXFP = gFalse;
959       }
960     }
961   }
962
963   // get the glyph count
964   charStringsIdxPtr = (Guchar *)file + dict.charStrings;
965   nGlyphs = getIndexLen(charStringsIdxPtr);
966
967   // read the FDSelect table
968   fdSelect = (Guchar *)gmalloc(nGlyphs);
969   if (dict.fdSelectOffset == 0) {
970     for (i = 0; i < nGlyphs; ++i) {
971       fdSelect[i] = 0;
972     }
973   } else {
974     ptr = (Guchar *)file + dict.fdSelectOffset;
975     fdSelectFmt = *ptr++;
976     if (fdSelectFmt == 0) {
977       memcpy(fdSelect, ptr, nGlyphs);
978     } else if (fdSelectFmt == 3) {
979       nRanges = getWord(ptr, 2);
980       ptr += 2;
981       gid0 = getWord(ptr, 2);
982       ptr += 2;
983       for (i = 1; i <= nRanges; ++i) {
984         fd = *ptr++;
985         gid1 = getWord(ptr, 2);
986         ptr += 2;
987         for (j = gid0; j < gid1; ++j) {
988           fdSelect[j] = fd;
989         }
990         gid0 = gid1;
991       }
992     } else {
993       error(-1, "Unknown FDSelect table format in CID font");
994       for (i = 0; i < nGlyphs; ++i) {
995         fdSelect[i] = 0;
996       }
997     }
998   }
999
1000   // read the charset, compute the CID-to-GID mapping
1001   charset = readCharset(dict.charset, nGlyphs);
1002   nCIDs = 0;
1003   for (i = 0; i < nGlyphs; ++i) {
1004     if (charset[i] >= nCIDs) {
1005       nCIDs = charset[i] + 1;
1006     }
1007   }
1008   cidMap = (int *)gmalloc(nCIDs * sizeof(int));
1009   for (i = 0; i < nCIDs; ++i) {
1010     cidMap[i] = -1;
1011   }
1012   for (i = 0; i < nGlyphs; ++i) {
1013     cidMap[charset[i]] = i;
1014   }
1015
1016   // write the descendant Type 1 fonts
1017   for (i = 0; i < nCIDs; i += 256) {
1018
1019     //~ this assumes that all CIDs in this block have the same FD --
1020     //~ to handle multiple FDs correctly, need to somehow divide the
1021     //~ font up by FD
1022     fd = 0;
1023     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1024       if (cidMap[i+j] >= 0) {
1025         fd = fdSelect[cidMap[i+j]];
1026         break;
1027       }
1028     }
1029
1030     // font dictionary (unencrypted section)
1031     (*outputFunc)(outputStream, "16 dict begin\n", 14);
1032     (*outputFunc)(outputStream, "/FontName /", 11);
1033     (*outputFunc)(outputStream, psName, strlen(psName));
1034     sprintf(buf, "_%02x def\n", i >> 8);
1035     (*outputFunc)(outputStream, buf, strlen(buf));
1036     (*outputFunc)(outputStream, "/FontType 1 def\n", 16);
1037     sprintf(buf, "/FontMatrix [%g %g %g %g %g %g] def\n",
1038             dict.fontMatrix[0], dict.fontMatrix[1], dict.fontMatrix[2],
1039             dict.fontMatrix[3], dict.fontMatrix[4], dict.fontMatrix[5]);
1040     (*outputFunc)(outputStream, buf, strlen(buf));
1041     sprintf(buf, "/FontBBox [%g %g %g %g] def\n",
1042             dict.fontBBox[0], dict.fontBBox[1],
1043             dict.fontBBox[2], dict.fontBBox[3]);
1044     (*outputFunc)(outputStream, buf, strlen(buf));
1045     sprintf(buf, "/PaintType %d def\n", dict.paintType);
1046     (*outputFunc)(outputStream, buf, strlen(buf));
1047     if (dict.paintType != 0) {
1048       sprintf(buf, "/StrokeWidth %g def\n", dict.strokeWidth);
1049       (*outputFunc)(outputStream, buf, strlen(buf));
1050     }
1051     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1052     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1053       sprintf(buf, "dup %d /c%02x put\n", j, j);
1054       (*outputFunc)(outputStream, buf, strlen(buf));
1055     }
1056     (*outputFunc)(outputStream, "readonly def\n", 13);
1057     (*outputFunc)(outputStream, "currentdict end\n", 16);
1058
1059     // start the binary section
1060     (*outputFunc)(outputStream, "currentfile eexec\n", 18);
1061     r1 = 55665;
1062     line = 0;
1063
1064     // start the private dictionary
1065     eexecWrite("\x83\xca\x73\xd5");
1066     eexecWrite("dup /Private 32 dict dup begin\n");
1067     eexecWrite("/RD {string currentfile exch readstring pop} executeonly def\n");
1068     eexecWrite("/ND {noaccess def} executeonly def\n");
1069     eexecWrite("/NP {noaccess put} executeonly def\n");
1070     eexecWrite("/MinFeature {16 16} ND\n");
1071     eexecWrite(privateDicts[fd].dictData->getCString());
1072     defaultWidthX = privateDicts[fd].defaultWidthX;
1073     defaultWidthXFP = privateDicts[fd].defaultWidthXFP;
1074     nominalWidthX = privateDicts[fd].nominalWidthX;
1075     nominalWidthXFP = privateDicts[fd].nominalWidthXFP;
1076
1077     // start the CharStrings
1078     sprintf(eBuf, "2 index /CharStrings 256 dict dup begin\n");
1079     eexecWrite(eBuf);
1080
1081     // write the .notdef CharString
1082     idxPtr0 = getIndexValPtr(charStringsIdxPtr, 0);
1083     idxPtr1 = getIndexValPtr(charStringsIdxPtr, 1);
1084     n = idxPtr1 - idxPtr0;
1085     eexecCvtGlyph(".notdef", idxPtr0, n);
1086
1087     // write the CharStrings
1088     for (j = 0; j < 256 && i+j < nCIDs; ++j) {
1089       if (cidMap[i+j] >= 0) {
1090         idxPtr0 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]);
1091         idxPtr1 = getIndexValPtr(charStringsIdxPtr, cidMap[i+j]+1);
1092         n = idxPtr1 - idxPtr0;
1093         sprintf(buf, "c%02x", j);
1094         eexecCvtGlyph(buf, idxPtr0, n);
1095       }
1096     }
1097     eexecWrite("end\n");
1098     eexecWrite("end\n");
1099     eexecWrite("readonly put\n");
1100     eexecWrite("noaccess put\n");
1101     eexecWrite("dup /FontName get exch definefont pop\n");
1102     eexecWrite("mark currentfile closefile\n");
1103
1104     // trailer
1105     if (line > 0) {
1106       (*outputFunc)(outputStream, "\n", 1);
1107     }
1108     for (j = 0; j < 8; ++j) {
1109       (*outputFunc)(outputStream, "0000000000000000000000000000000000000000000000000000000000000000\n", 65);
1110     }
1111     (*outputFunc)(outputStream, "cleartomark\n", 12);
1112   }
1113
1114   // write the Type 0 parent font
1115   (*outputFunc)(outputStream, "16 dict begin\n", 14);
1116   (*outputFunc)(outputStream, "/FontName /", 11);
1117   (*outputFunc)(outputStream, psName, strlen(psName));
1118   (*outputFunc)(outputStream, " def\n", 5);
1119   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
1120   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
1121   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
1122   (*outputFunc)(outputStream, "/Encoding [\n", 12);
1123   for (i = 0; i < nCIDs; i += 256) {
1124     sprintf(buf, "%d\n", i >> 8);
1125     (*outputFunc)(outputStream, buf, strlen(buf));
1126   }
1127   (*outputFunc)(outputStream, "] def\n", 6);
1128   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
1129   for (i = 0; i < nCIDs; i += 256) {
1130     (*outputFunc)(outputStream, "/", 1);
1131     (*outputFunc)(outputStream, psName, strlen(psName));
1132     sprintf(buf, "_%02x findfont\n", i >> 8);
1133     (*outputFunc)(outputStream, buf, strlen(buf));
1134   }
1135   (*outputFunc)(outputStream, "] def\n", 6);
1136   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
1137
1138   // clean up
1139   for (i = 0; i < nFDs; ++i) {
1140     delete privateDicts[i].dictData;
1141   }
1142   gfree(privateDicts);
1143   gfree(cidMap);
1144   gfree(charset);
1145   gfree(fdSelect);
1146 }
1147
1148 void Type1CFontFile::readTopDict(Type1CTopDict *dict) {
1149   Guchar *idxPtr0, *idxPtr1, *ptr;
1150   double x;
1151   GBool isFP;
1152   int key;
1153   int i;
1154
1155   idxPtr0 = getIndexValPtr(topDictIdxPtr, 0);
1156   idxPtr1 = getIndexValPtr(topDictIdxPtr, 1);
1157   dict->version = 0;
1158   dict->notice = 0;
1159   dict->copyright = 0;
1160   dict->fullName = 0;
1161   dict->familyName = 0;
1162   dict->weight = 0;
1163   dict->isFixedPitch = 0;
1164   dict->italicAngle = 0;
1165   dict->underlinePosition = -100;
1166   dict->underlineThickness = 50;
1167   dict->paintType = 0;
1168   dict->charstringType = 2;
1169   dict->fontMatrix[0] = 0.001;
1170   dict->fontMatrix[1] = 0;
1171   dict->fontMatrix[2] = 0;
1172   dict->fontMatrix[3] = 0.001;
1173   dict->fontMatrix[4] = 0;
1174   dict->fontMatrix[5] = 0;
1175   dict->uniqueID = 0;
1176   dict->fontBBox[0] = 0;
1177   dict->fontBBox[1] = 0;
1178   dict->fontBBox[2] = 0;
1179   dict->fontBBox[3] = 0;
1180   dict->strokeWidth = 0;
1181   dict->charset = 0;
1182   dict->encoding = 0;
1183   dict->charStrings = 0;
1184   dict->privateSize = 0;
1185   dict->privateOffset = 0;
1186   dict->registry = 0;
1187   dict->ordering = 0;
1188   dict->supplement = 0;
1189   dict->fdArrayOffset = 0;
1190   dict->fdSelectOffset = 0;
1191   i = 0;
1192   ptr = idxPtr0;
1193   while (ptr < idxPtr1) {
1194     if (*ptr <= 27 || *ptr == 31) {
1195       key = *ptr++;
1196       if (key == 0x0c) {
1197         key = (key << 8) | *ptr++;
1198       }
1199       switch (key) {
1200       case 0x0000: dict->version = (int)op[0]; break;
1201       case 0x0001: dict->notice = (int)op[0]; break;
1202       case 0x0c00: dict->copyright = (int)op[0]; break;
1203       case 0x0002: dict->fullName = (int)op[0]; break;
1204       case 0x0003: dict->familyName = (int)op[0]; break;
1205       case 0x0004: dict->weight = (int)op[0]; break;
1206       case 0x0c01: dict->isFixedPitch = (int)op[0]; break;
1207       case 0x0c02: dict->italicAngle = op[0]; break;
1208       case 0x0c03: dict->underlinePosition = op[0]; break;
1209       case 0x0c04: dict->underlineThickness = op[0]; break;
1210       case 0x0c05: dict->paintType = (int)op[0]; break;
1211       case 0x0c06: dict->charstringType = (int)op[0]; break;
1212       case 0x0c07: dict->fontMatrix[0] = op[0];
1213                    dict->fontMatrix[1] = op[1];
1214                    dict->fontMatrix[2] = op[2];
1215                    dict->fontMatrix[3] = op[3];
1216                    dict->fontMatrix[4] = op[4];
1217                    dict->fontMatrix[5] = op[5]; break;
1218       case 0x000d: dict->uniqueID = (int)op[0]; break;
1219       case 0x0005: dict->fontBBox[0] = op[0];
1220                    dict->fontBBox[1] = op[1];
1221                    dict->fontBBox[2] = op[2];
1222                    dict->fontBBox[3] = op[3]; break;
1223       case 0x0c08: dict->strokeWidth = op[0]; break;
1224       case 0x000f: dict->charset = (int)op[0]; break;
1225       case 0x0010: dict->encoding = (int)op[0]; break;
1226       case 0x0011: dict->charStrings = (int)op[0]; break;
1227       case 0x0012: dict->privateSize = (int)op[0];
1228                    dict->privateOffset = (int)op[1]; break;
1229       case 0x0c1e: dict->registry = (int)op[0];
1230                    dict->ordering = (int)op[1];
1231                    dict->supplement = (int)op[2]; break;
1232       case 0x0c24: dict->fdArrayOffset = (int)op[0]; break;
1233       case 0x0c25: dict->fdSelectOffset = (int)op[0]; break;
1234       }
1235       i = 0;
1236     } else {
1237       x = getNum(&ptr, &isFP);
1238       if (i < 48) {
1239         op[i] = x;
1240         fp[i++] = isFP;
1241       }
1242     }
1243   }
1244 }
1245
1246 void Type1CFontFile::readPrivateDict(Type1CPrivateDict *privateDict,
1247                                      int offset, int size) {
1248   Guchar *idxPtr0, *idxPtr1, *ptr;
1249   char eBuf[256];
1250   int key;
1251   double x;
1252   GBool isFP;
1253   int i;
1254
1255   privateDict->dictData = new GString();
1256   privateDict->subrsOffset = 0;
1257   privateDict->defaultWidthX = 0;
1258   privateDict->defaultWidthXFP = gFalse;
1259   privateDict->nominalWidthX = 0;
1260   privateDict->nominalWidthXFP = gFalse;
1261   idxPtr0 = (Guchar *)file + offset;
1262   idxPtr1 = idxPtr0 + size;
1263   ptr = idxPtr0;
1264   i = 0;
1265   while (ptr < idxPtr1) {
1266     if (*ptr <= 27 || *ptr == 31) {
1267       key = *ptr++;
1268       if (key == 0x0c) {
1269         key = (key << 8) | *ptr++;
1270       }
1271       switch (key) {
1272       case 0x0006:
1273         getDeltaInt(eBuf, "BlueValues", op, i);
1274         privateDict->dictData->append(eBuf);
1275         break;
1276       case 0x0007:
1277         getDeltaInt(eBuf, "OtherBlues", op, i);
1278         privateDict->dictData->append(eBuf);
1279         break;
1280       case 0x0008:
1281         getDeltaInt(eBuf, "FamilyBlues", op, i);
1282         privateDict->dictData->append(eBuf);
1283         break;
1284       case 0x0009:
1285         getDeltaInt(eBuf, "FamilyOtherBlues", op, i);
1286         privateDict->dictData->append(eBuf);
1287         break;
1288       case 0x0c09:
1289         sprintf(eBuf, "/BlueScale %g def\n", op[0]);
1290         privateDict->dictData->append(eBuf);
1291         break;
1292       case 0x0c0a:
1293         sprintf(eBuf, "/BlueShift %d def\n", (int)op[0]);
1294         privateDict->dictData->append(eBuf);
1295         break;
1296       case 0x0c0b:
1297         sprintf(eBuf, "/BlueFuzz %d def\n", (int)op[0]);
1298         privateDict->dictData->append(eBuf);
1299         break;
1300       case 0x000a:
1301         sprintf(eBuf, "/StdHW [%g] def\n", op[0]);
1302         privateDict->dictData->append(eBuf);
1303         break;
1304       case 0x000b:
1305         sprintf(eBuf, "/StdVW [%g] def\n", op[0]);
1306         privateDict->dictData->append(eBuf);
1307         break;
1308       case 0x0c0c:
1309         getDeltaReal(eBuf, "StemSnapH", op, i);
1310         privateDict->dictData->append(eBuf);
1311         break;
1312       case 0x0c0d:
1313         getDeltaReal(eBuf, "StemSnapV", op, i);
1314         privateDict->dictData->append(eBuf);
1315         break;
1316       case 0x0c0e:
1317         sprintf(eBuf, "/ForceBold %s def\n", op[0] ? "true" : "false");
1318         privateDict->dictData->append(eBuf);
1319         break;
1320       case 0x0c0f:
1321         sprintf(eBuf, "/ForceBoldThreshold %g def\n", op[0]);
1322         privateDict->dictData->append(eBuf);
1323         break;
1324       case 0x0c11:
1325         sprintf(eBuf, "/LanguageGroup %d def\n", (int)op[0]);
1326         privateDict->dictData->append(eBuf);
1327         break;
1328       case 0x0c12:
1329         sprintf(eBuf, "/ExpansionFactor %g def\n", op[0]);
1330         privateDict->dictData->append(eBuf);
1331         break;
1332       case 0x0c13:
1333         error(-1, "Got Type 1C InitialRandomSeed");
1334         break;
1335       case 0x0013:
1336         privateDict->subrsOffset = (int)op[0];
1337         break;
1338       case 0x0014:
1339         privateDict->defaultWidthX = op[0];
1340         privateDict->defaultWidthXFP = fp[0];
1341         break;
1342       case 0x0015:
1343         privateDict->nominalWidthX = op[0];
1344         privateDict->nominalWidthXFP = fp[0];
1345         break;
1346       default:
1347         error(-1, "Unknown Type 1C private dict entry %04x", key);
1348         break;
1349       }
1350       i = 0;
1351     } else {
1352       x = getNum(&ptr, &isFP);
1353       if (i < 48) {
1354         op[i] = x;
1355         fp[i++] = isFP;
1356       }
1357     }
1358   }
1359 }
1360
1361 Gushort *Type1CFontFile::readCharset(int charset, int nGlyphs) {
1362   Gushort *glyphNames;
1363   Guchar *ptr;
1364   int charsetFormat, c;
1365   int nLeft, i, j;
1366
1367   if (charset == 0) {
1368     glyphNames = type1CISOAdobeCharset;
1369   } else if (charset == 1) {
1370     glyphNames = type1CExpertCharset;
1371   } else if (charset == 2) {
1372     glyphNames = type1CExpertSubsetCharset;
1373   } else {
1374     glyphNames = (Gushort *)gmalloc(nGlyphs * sizeof(Gushort));
1375     glyphNames[0] = 0;
1376     ptr = (Guchar *)file + charset;
1377     charsetFormat = *ptr++;
1378     if (charsetFormat == 0) {
1379       for (i = 1; i < nGlyphs; ++i) {
1380         glyphNames[i] = getWord(ptr, 2);
1381         ptr += 2;
1382       }
1383     } else if (charsetFormat == 1) {
1384       i = 1;
1385       while (i < nGlyphs) {
1386         c = getWord(ptr, 2);
1387         ptr += 2;
1388         nLeft = *ptr++;
1389         for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1390           glyphNames[i++] = c++;
1391         }
1392       }
1393     } else if (charsetFormat == 2) {
1394       i = 1;
1395       while (i < nGlyphs) {
1396         c = getWord(ptr, 2);
1397         ptr += 2;
1398         nLeft = getWord(ptr, 2);
1399         ptr += 2;
1400         for (j = 0; j <= nLeft && i < nGlyphs; ++j) {
1401           glyphNames[i++] = c++;
1402         }
1403       }
1404     }
1405   }
1406   return glyphNames;
1407 }
1408
1409 void Type1CFontFile::eexecWrite(char *s) {
1410   Guchar *p;
1411   Guchar x;
1412
1413   for (p = (Guchar *)s; *p; ++p) {
1414     x = *p ^ (r1 >> 8);
1415     r1 = (x + r1) * 52845 + 22719;
1416     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
1417     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
1418     line += 2;
1419     if (line == 64) {
1420       (*outputFunc)(outputStream, "\n", 1);
1421       line = 0;
1422     }
1423   }
1424 }
1425
1426 void Type1CFontFile::eexecCvtGlyph(char *glyphName, Guchar *s, int n) {
1427   char eBuf[256];
1428
1429   cvtGlyph(s, n);
1430   sprintf(eBuf, "/%s %d RD ", glyphName, charBuf->getLength());
1431   eexecWrite(eBuf);
1432   eexecWriteCharstring((Guchar *)charBuf->getCString(), charBuf->getLength());
1433   eexecWrite(" ND\n");
1434   delete charBuf;
1435 }
1436
1437 void Type1CFontFile::cvtGlyph(Guchar *s, int n) {
1438   int nHints;
1439   int x;
1440   GBool first = gTrue;
1441   double d, dx, dy;
1442   GBool dFP;
1443   Gushort r2;
1444   Guchar byte;
1445   int i, k;
1446
1447   charBuf = new GString();
1448   charBuf->append((char)73);
1449   charBuf->append((char)58);
1450   charBuf->append((char)147);
1451   charBuf->append((char)134);
1452
1453   i = 0;
1454   nOps = 0;
1455   nHints = 0;
1456   while (i < n) {
1457     if (s[i] == 12) {
1458       switch (s[i+1]) {
1459       case 0:                   // dotsection (should be Type 1 only?)
1460         // ignored
1461         break;
1462       case 34:                  // hflex
1463         if (nOps != 7) {
1464           error(-1, "Wrong number of args (%d) to Type 2 hflex", nOps);
1465         }
1466         eexecDumpNum(op[0], fp[0]);
1467         eexecDumpNum(0, gFalse);
1468         eexecDumpNum(op[1], fp[1]);
1469         eexecDumpNum(op[2], fp[2]);
1470         eexecDumpNum(op[3], fp[3]);
1471         eexecDumpNum(0, gFalse);
1472         eexecDumpOp1(8);
1473         eexecDumpNum(op[4], fp[4]);
1474         eexecDumpNum(0, gFalse);
1475         eexecDumpNum(op[5], fp[5]);
1476         eexecDumpNum(-op[2], fp[2]);
1477         eexecDumpNum(op[6], fp[6]);
1478         eexecDumpNum(0, gFalse);
1479         eexecDumpOp1(8);
1480         break;
1481       case 35:                  // flex
1482         if (nOps != 13) {
1483           error(-1, "Wrong number of args (%d) to Type 2 flex", nOps);
1484         }
1485         eexecDumpNum(op[0], fp[0]);
1486         eexecDumpNum(op[1], fp[1]);
1487         eexecDumpNum(op[2], fp[2]);
1488         eexecDumpNum(op[3], fp[3]);
1489         eexecDumpNum(op[4], fp[4]);
1490         eexecDumpNum(op[5], fp[5]);
1491         eexecDumpOp1(8);
1492         eexecDumpNum(op[6], fp[6]);
1493         eexecDumpNum(op[7], fp[7]);
1494         eexecDumpNum(op[8], fp[8]);
1495         eexecDumpNum(op[9], fp[9]);
1496         eexecDumpNum(op[10], fp[10]);
1497         eexecDumpNum(op[11], fp[11]);
1498         eexecDumpOp1(8);
1499         break;
1500       case 36:                  // hflex1
1501         if (nOps != 9) {
1502           error(-1, "Wrong number of args (%d) to Type 2 hflex1", nOps);
1503         }
1504         eexecDumpNum(op[0], fp[0]);
1505         eexecDumpNum(op[1], fp[1]);
1506         eexecDumpNum(op[2], fp[2]);
1507         eexecDumpNum(op[3], fp[3]);
1508         eexecDumpNum(op[4], fp[4]);
1509         eexecDumpNum(0, gFalse);
1510         eexecDumpOp1(8);
1511         eexecDumpNum(op[5], fp[5]);
1512         eexecDumpNum(0, gFalse);
1513         eexecDumpNum(op[6], fp[6]);
1514         eexecDumpNum(op[7], fp[7]);
1515         eexecDumpNum(op[8], fp[8]);
1516         eexecDumpNum(-(op[1] + op[3] + op[7]), fp[1] | fp[3] | fp[7]);
1517         eexecDumpOp1(8);
1518         break;
1519       case 37:                  // flex1
1520         if (nOps != 11) {
1521           error(-1, "Wrong number of args (%d) to Type 2 flex1", nOps);
1522         }
1523         eexecDumpNum(op[0], fp[0]);
1524         eexecDumpNum(op[1], fp[1]);
1525         eexecDumpNum(op[2], fp[2]);
1526         eexecDumpNum(op[3], fp[3]);
1527         eexecDumpNum(op[4], fp[4]);
1528         eexecDumpNum(op[5], fp[5]);
1529         eexecDumpOp1(8);
1530         eexecDumpNum(op[6], fp[6]);
1531         eexecDumpNum(op[7], fp[7]);
1532         eexecDumpNum(op[8], fp[8]);
1533         eexecDumpNum(op[9], fp[9]);
1534         dx = op[0] + op[2] + op[4] + op[6] + op[8];
1535         dy = op[1] + op[3] + op[5] + op[7] + op[9];
1536         if (fabs(dx) > fabs(dy)) {
1537           eexecDumpNum(op[10], fp[10]);
1538           eexecDumpNum(-dy, fp[1] | fp[3] | fp[5] | fp[7] | fp[9]);
1539         } else {
1540           eexecDumpNum(-dx, fp[0] | fp[2] | fp[4] | fp[6] | fp[8]);
1541           eexecDumpNum(op[10], fp[10]);
1542         }
1543         eexecDumpOp1(8);
1544         break;
1545       case 3:                   // and
1546       case 4:                   // or
1547       case 5:                   // not
1548       case 8:                   // store
1549       case 9:                   // abs
1550       case 10:                  // add
1551       case 11:                  // sub
1552       case 12:                  // div
1553       case 13:                  // load
1554       case 14:                  // neg
1555       case 15:                  // eq
1556       case 18:                  // drop
1557       case 20:                  // put
1558       case 21:                  // get
1559       case 22:                  // ifelse
1560       case 23:                  // random
1561       case 24:                  // mul
1562       case 26:                  // sqrt
1563       case 27:                  // dup
1564       case 28:                  // exch
1565       case 29:                  // index
1566       case 30:                  // roll
1567         error(-1, "Unimplemented Type 2 charstring op: 12.%d", s[i+1]);
1568         break;
1569       default:
1570         error(-1, "Illegal Type 2 charstring op: 12.%d", s[i+1]);
1571         break;
1572       }
1573       i += 2;
1574       nOps = 0;
1575     } else if (s[i] == 19) {    // hintmask
1576       // ignored
1577       if (first) {
1578         cvtGlyphWidth(nOps == 1);
1579         first = gFalse;
1580       }
1581       if (nOps > 0) {
1582         if (nOps & 1) {
1583           error(-1, "Wrong number of args (%d) to Type 2 hintmask/vstemhm",
1584                 nOps);
1585         }
1586         nHints += nOps / 2;
1587       }
1588       i += 1 + ((nHints + 7) >> 3);
1589       nOps = 0;
1590     } else if (s[i] == 20) {    // cntrmask
1591       // ignored
1592       if (first) {
1593         cvtGlyphWidth(nOps == 1);
1594         first = gFalse;
1595       }
1596       if (nOps > 0) {
1597         if (nOps & 1) {
1598           error(-1, "Wrong number of args (%d) to Type 2 cntrmask/vstemhm",
1599                 nOps);
1600         }
1601         nHints += nOps / 2;
1602       }
1603       i += 1 + ((nHints + 7) >> 3);
1604       nOps = 0;
1605     } else if (s[i] == 28) {
1606       x = (s[i+1] << 8) + s[i+2];
1607       if (x & 0x8000) {
1608         x |= -1 << 15;
1609       }
1610       if (nOps < 48) {
1611         fp[nOps] = gFalse;
1612         op[nOps++] = x;
1613       }
1614       i += 3;
1615     } else if (s[i] <= 31) {
1616       switch (s[i]) {
1617       case 4:                   // vmoveto
1618         if (first) {
1619           cvtGlyphWidth(nOps == 2);
1620           first = gFalse;
1621         }
1622         if (nOps != 1) {
1623           error(-1, "Wrong number of args (%d) to Type 2 vmoveto", nOps);
1624         }
1625         eexecDumpNum(op[0], fp[0]);
1626         eexecDumpOp1(4);
1627         break;
1628       case 5:                   // rlineto
1629         if (nOps < 2 || nOps % 2 != 0) {
1630           error(-1, "Wrong number of args (%d) to Type 2 rlineto", nOps);
1631         }
1632         for (k = 0; k < nOps; k += 2) {
1633           eexecDumpNum(op[k], fp[k]);
1634           eexecDumpNum(op[k+1], fp[k+1]);
1635           eexecDumpOp1(5);
1636         }
1637         break;
1638       case 6:                   // hlineto
1639         if (nOps < 1) {
1640           error(-1, "Wrong number of args (%d) to Type 2 hlineto", nOps);
1641         }
1642         for (k = 0; k < nOps; ++k) {
1643           eexecDumpNum(op[k], fp[k]);
1644           eexecDumpOp1((k & 1) ? 7 : 6);
1645         }
1646         break;
1647       case 7:                   // vlineto
1648         if (nOps < 1) {
1649           error(-1, "Wrong number of args (%d) to Type 2 vlineto", nOps);
1650         }
1651         for (k = 0; k < nOps; ++k) {
1652           eexecDumpNum(op[k], fp[k]);
1653           eexecDumpOp1((k & 1) ? 6 : 7);
1654         }
1655         break;
1656       case 8:                   // rrcurveto
1657         if (nOps < 6 || nOps % 6 != 0) {
1658           error(-1, "Wrong number of args (%d) to Type 2 rrcurveto", nOps);
1659         }
1660         for (k = 0; k < nOps; k += 6) {
1661           eexecDumpNum(op[k], fp[k]);
1662           eexecDumpNum(op[k+1], fp[k+1]);
1663           eexecDumpNum(op[k+2], fp[k+2]);
1664           eexecDumpNum(op[k+3], fp[k+3]);
1665           eexecDumpNum(op[k+4], fp[k+4]);
1666           eexecDumpNum(op[k+5], fp[k+5]);
1667           eexecDumpOp1(8);
1668         }
1669         break;
1670       case 14:                  // endchar / seac
1671         if (first) {
1672           cvtGlyphWidth(nOps == 1 || nOps == 5);
1673           first = gFalse;
1674         }
1675         if (nOps == 4) {
1676           eexecDumpNum(0, 0);
1677           eexecDumpNum(op[0], fp[0]);
1678           eexecDumpNum(op[1], fp[1]);
1679           eexecDumpNum(op[2], fp[2]);
1680           eexecDumpNum(op[3], fp[3]);
1681           eexecDumpOp2(6);
1682         } else if (nOps == 0) {
1683           eexecDumpOp1(14);
1684         } else {
1685           error(-1, "Wrong number of args (%d) to Type 2 endchar", nOps);
1686         }
1687         break;
1688       case 21:                  // rmoveto
1689         if (first) {
1690           cvtGlyphWidth(nOps == 3);
1691           first = gFalse;
1692         }
1693         if (nOps != 2) {
1694           error(-1, "Wrong number of args (%d) to Type 2 rmoveto", nOps);
1695         }
1696         eexecDumpNum(op[0], fp[0]);
1697         eexecDumpNum(op[1], fp[1]);
1698         eexecDumpOp1(21);
1699         break;
1700       case 22:                  // hmoveto
1701         if (first) {
1702           cvtGlyphWidth(nOps == 2);
1703           first = gFalse;
1704         }
1705         if (nOps != 1) {
1706           error(-1, "Wrong number of args (%d) to Type 2 hmoveto", nOps);
1707         }
1708         eexecDumpNum(op[0], fp[0]);
1709         eexecDumpOp1(22);
1710         break;
1711       case 24:                  // rcurveline
1712         if (nOps < 8 || (nOps - 2) % 6 != 0) {
1713           error(-1, "Wrong number of args (%d) to Type 2 rcurveline", nOps);
1714         }
1715         for (k = 0; k < nOps - 2; k += 6) {
1716           eexecDumpNum(op[k], fp[k]);
1717           eexecDumpNum(op[k+1], fp[k+1]);
1718           eexecDumpNum(op[k+2], fp[k+2]);
1719           eexecDumpNum(op[k+3], fp[k+3]);
1720           eexecDumpNum(op[k+4], fp[k+4]);
1721           eexecDumpNum(op[k+5], fp[k+5]);
1722           eexecDumpOp1(8);
1723         }
1724         eexecDumpNum(op[k], fp[k]);
1725         eexecDumpNum(op[k+1], fp[k]);
1726         eexecDumpOp1(5);
1727         break;
1728       case 25:                  // rlinecurve
1729         if (nOps < 8 || (nOps - 6) % 2 != 0) {
1730           error(-1, "Wrong number of args (%d) to Type 2 rlinecurve", nOps);
1731         }
1732         for (k = 0; k < nOps - 6; k += 2) {
1733           eexecDumpNum(op[k], fp[k]);
1734           eexecDumpNum(op[k+1], fp[k]);
1735           eexecDumpOp1(5);
1736         }
1737         eexecDumpNum(op[k], fp[k]);
1738         eexecDumpNum(op[k+1], fp[k+1]);
1739         eexecDumpNum(op[k+2], fp[k+2]);
1740         eexecDumpNum(op[k+3], fp[k+3]);
1741         eexecDumpNum(op[k+4], fp[k+4]);
1742         eexecDumpNum(op[k+5], fp[k+5]);
1743         eexecDumpOp1(8);
1744         break;
1745       case 26:                  // vvcurveto
1746         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1747           error(-1, "Wrong number of args (%d) to Type 2 vvcurveto", nOps);
1748         }
1749         if (nOps % 2 == 1) {
1750           eexecDumpNum(op[0], fp[0]);
1751           eexecDumpNum(op[1], fp[1]);
1752           eexecDumpNum(op[2], fp[2]);
1753           eexecDumpNum(op[3], fp[3]);
1754           eexecDumpNum(0, gFalse);
1755           eexecDumpNum(op[4], fp[4]);
1756           eexecDumpOp1(8);
1757           k = 5;
1758         } else {
1759           k = 0;
1760         }
1761         for (; k < nOps; k += 4) {
1762           eexecDumpNum(0, gFalse);
1763           eexecDumpNum(op[k], fp[k]);
1764           eexecDumpNum(op[k+1], fp[k+1]);
1765           eexecDumpNum(op[k+2], fp[k+2]);
1766           eexecDumpNum(0, gFalse);
1767           eexecDumpNum(op[k+3], fp[k+3]);
1768           eexecDumpOp1(8);
1769         }
1770         break;
1771       case 27:                  // hhcurveto
1772         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1773           error(-1, "Wrong number of args (%d) to Type 2 hhcurveto", nOps);
1774         }
1775         if (nOps % 2 == 1) {
1776           eexecDumpNum(op[1], fp[1]);
1777           eexecDumpNum(op[0], fp[0]);
1778           eexecDumpNum(op[2], fp[2]);
1779           eexecDumpNum(op[3], fp[3]);
1780           eexecDumpNum(op[4], fp[4]);
1781           eexecDumpNum(0, gFalse);
1782           eexecDumpOp1(8);
1783           k = 5;
1784         } else {
1785           k = 0;
1786         }
1787         for (; k < nOps; k += 4) {
1788           eexecDumpNum(op[k], fp[k]);
1789           eexecDumpNum(0, gFalse);
1790           eexecDumpNum(op[k+1], fp[k+1]);
1791           eexecDumpNum(op[k+2], fp[k+2]);
1792           eexecDumpNum(op[k+3], fp[k+3]);
1793           eexecDumpNum(0, gFalse);
1794           eexecDumpOp1(8);
1795         }
1796         break;
1797       case 30:                  // vhcurveto
1798         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1799           error(-1, "Wrong number of args (%d) to Type 2 vhcurveto", nOps);
1800         }
1801         for (k = 0; k < nOps && k != nOps-5; k += 4) {
1802           if (k % 8 == 0) {
1803             eexecDumpNum(op[k], fp[k]);
1804             eexecDumpNum(op[k+1], fp[k+1]);
1805             eexecDumpNum(op[k+2], fp[k+2]);
1806             eexecDumpNum(op[k+3], fp[k+3]);
1807             eexecDumpOp1(30);
1808           } else {
1809             eexecDumpNum(op[k], fp[k]);
1810             eexecDumpNum(op[k+1], fp[k+1]);
1811             eexecDumpNum(op[k+2], fp[k+2]);
1812             eexecDumpNum(op[k+3], fp[k+3]);
1813             eexecDumpOp1(31);
1814           }
1815         }
1816         if (k == nOps-5) {
1817           if (k % 8 == 0) {
1818             eexecDumpNum(0, gFalse);
1819             eexecDumpNum(op[k], fp[k]);
1820             eexecDumpNum(op[k+1], fp[k+1]);
1821             eexecDumpNum(op[k+2], fp[k+2]);
1822             eexecDumpNum(op[k+3], fp[k+3]);
1823             eexecDumpNum(op[k+4], fp[k+4]);
1824           } else {
1825             eexecDumpNum(op[k], fp[k]);
1826             eexecDumpNum(0, gFalse);
1827             eexecDumpNum(op[k+1], fp[k+1]);
1828             eexecDumpNum(op[k+2], fp[k+2]);
1829             eexecDumpNum(op[k+4], fp[k+4]);
1830             eexecDumpNum(op[k+3], fp[k+3]);
1831           }
1832           eexecDumpOp1(8);
1833         }
1834         break;
1835       case 31:                  // hvcurveto
1836         if (nOps < 4 || !(nOps % 4 == 0 || (nOps-1) % 4 == 0)) {
1837           error(-1, "Wrong number of args (%d) to Type 2 hvcurveto", nOps);
1838         }
1839         for (k = 0; k < nOps && k != nOps-5; k += 4) {
1840           if (k % 8 == 0) {
1841             eexecDumpNum(op[k], fp[k]);
1842             eexecDumpNum(op[k+1], fp[k+1]);
1843             eexecDumpNum(op[k+2], fp[k+2]);
1844             eexecDumpNum(op[k+3], fp[k+3]);
1845             eexecDumpOp1(31);
1846           } else {
1847             eexecDumpNum(op[k], fp[k]);
1848             eexecDumpNum(op[k+1], fp[k+1]);
1849             eexecDumpNum(op[k+2], fp[k+2]);
1850             eexecDumpNum(op[k+3], fp[k+3]);
1851             eexecDumpOp1(30);
1852           }
1853         }
1854         if (k == nOps-5) {
1855           if (k % 8 == 0) {
1856             eexecDumpNum(op[k], fp[k]);
1857             eexecDumpNum(0, gFalse);
1858             eexecDumpNum(op[k+1], fp[k+1]);
1859             eexecDumpNum(op[k+2], fp[k+2]);
1860             eexecDumpNum(op[k+4], fp[k+4]);
1861             eexecDumpNum(op[k+3], fp[k+3]);
1862           } else {
1863             eexecDumpNum(0, gFalse);
1864             eexecDumpNum(op[k], fp[k]);
1865             eexecDumpNum(op[k+1], fp[k+1]);
1866             eexecDumpNum(op[k+2], fp[k+2]);
1867             eexecDumpNum(op[k+3], fp[k+3]);
1868             eexecDumpNum(op[k+4], fp[k+4]);
1869           }
1870           eexecDumpOp1(8);
1871         }
1872         break;
1873       case 1:                   // hstem
1874         if (first) {
1875           cvtGlyphWidth(nOps & 1);
1876           first = gFalse;
1877         }
1878         if (nOps & 1) {
1879           error(-1, "Wrong number of args (%d) to Type 2 hstem", nOps);
1880         }
1881         d = 0;
1882         dFP = gFalse;
1883         for (k = 0; k < nOps; k += 2) {
1884           if (op[k+1] < 0) {
1885             d += op[k] + op[k+1];
1886             dFP |= fp[k] | fp[k+1];
1887             eexecDumpNum(d, dFP);
1888             eexecDumpNum(-op[k+1], fp[k+1]);
1889           } else {
1890             d += op[k];
1891             dFP |= fp[k];
1892             eexecDumpNum(d, dFP);
1893             eexecDumpNum(op[k+1], fp[k+1]);
1894             d += op[k+1];
1895             dFP |= fp[k+1];
1896           }
1897           eexecDumpOp1(1);
1898         }
1899         nHints += nOps / 2;
1900         break;
1901       case 3:                   // vstem
1902         if (first) {
1903           cvtGlyphWidth(nOps & 1);
1904           first = gFalse;
1905         }
1906         if (nOps & 1) {
1907           error(-1, "Wrong number of args (%d) to Type 2 vstem", nOps);
1908         }
1909         d = 0;
1910         dFP = gFalse;
1911         for (k = 0; k < nOps; k += 2) {
1912           if (op[k+1] < 0) {
1913             d += op[k] + op[k+1];
1914             dFP |= fp[k] | fp[k+1];
1915             eexecDumpNum(d, dFP);
1916             eexecDumpNum(-op[k+1], fp[k+1]);
1917           } else {
1918             d += op[k];
1919             dFP |= fp[k];
1920             eexecDumpNum(d, dFP);
1921             eexecDumpNum(op[k+1], fp[k+1]);
1922             d += op[k+1];
1923             dFP |= fp[k+1];
1924           }
1925           eexecDumpOp1(3);
1926         }
1927         nHints += nOps / 2;
1928         break;
1929       case 18:                  // hstemhm
1930         // ignored
1931         if (first) {
1932           cvtGlyphWidth(nOps & 1);
1933           first = gFalse;
1934         }
1935         if (nOps & 1) {
1936           error(-1, "Wrong number of args (%d) to Type 2 hstemhm", nOps);
1937         }
1938         nHints += nOps / 2;
1939         break;
1940       case 23:                  // vstemhm
1941         // ignored
1942         if (first) {
1943           cvtGlyphWidth(nOps & 1);
1944           first = gFalse;
1945         }
1946         if (nOps & 1) {
1947           error(-1, "Wrong number of args (%d) to Type 2 vstemhm", nOps);
1948         }
1949         nHints += nOps / 2;
1950         break;
1951       case 10:                  // callsubr
1952       case 11:                  // return
1953       case 16:                  // blend
1954       case 29:                  // callgsubr
1955         error(-1, "Unimplemented Type 2 charstring op: %d", s[i]);
1956         break;
1957       default:
1958         error(-1, "Illegal Type 2 charstring op: %d", s[i]);
1959         break;
1960       }
1961       ++i;
1962       nOps = 0;
1963     } else if (s[i] <= 246) {
1964       if (nOps < 48) {
1965         fp[nOps] = gFalse;
1966         op[nOps++] = (int)s[i] - 139;
1967       }
1968       ++i;
1969     } else if (s[i] <= 250) {
1970       if (nOps < 48) {
1971         fp[nOps] = gFalse;
1972         op[nOps++] = (((int)s[i] - 247) << 8) + (int)s[i+1] + 108;
1973       }
1974       i += 2;
1975     } else if (s[i] <= 254) {
1976       if (nOps < 48) {
1977         fp[nOps] = gFalse;
1978         op[nOps++] = -(((int)s[i] - 251) << 8) - (int)s[i+1] - 108;
1979       }
1980       i += 2;
1981     } else {
1982       x = (s[i+1] << 24) | (s[i+2] << 16) | (s[i+3] << 8) | s[i+4];
1983       if (x & 0x80000000)
1984         x |= -1 << 31;
1985       if (nOps < 48) {
1986         fp[nOps] = gTrue;
1987         op[nOps++] = (double)x / 65536.0;
1988       }
1989       i += 5;
1990     }
1991   }
1992
1993   // charstring encryption
1994   r2 = 4330;
1995   for (i = 0; i < charBuf->getLength(); ++i) {
1996     byte = charBuf->getChar(i) ^ (r2 >> 8);
1997     charBuf->setChar(i, byte);
1998     r2 = (byte + r2) * 52845 + 22719;
1999   }
2000 }
2001
2002 void Type1CFontFile::cvtGlyphWidth(GBool useOp) {
2003   double w;
2004   GBool wFP;
2005   int i;
2006
2007   if (useOp) {
2008     w = nominalWidthX + op[0];
2009     wFP = nominalWidthXFP | fp[0];
2010     for (i = 1; i < nOps; ++i) {
2011       op[i-1] = op[i];
2012       fp[i-1] = fp[i];
2013     }
2014     --nOps;
2015   } else {
2016     w = defaultWidthX;
2017     wFP = defaultWidthXFP;
2018   }
2019   eexecDumpNum(0, gFalse);
2020   eexecDumpNum(w, wFP);
2021   eexecDumpOp1(13);
2022 }
2023
2024 void Type1CFontFile::eexecDumpNum(double x, GBool fpA) {
2025   Guchar buf[12];
2026   int y, n;
2027
2028   n = 0;
2029   if (fpA) {
2030     if (x >= -32768 && x < 32768) {
2031       y = (int)(x * 256.0);
2032       buf[0] = 255;
2033       buf[1] = (Guchar)(y >> 24);
2034       buf[2] = (Guchar)(y >> 16);
2035       buf[3] = (Guchar)(y >> 8);
2036       buf[4] = (Guchar)y;
2037       buf[5] = 255;
2038       buf[6] = 0;
2039       buf[7] = 0;
2040       buf[8] = 1;
2041       buf[9] = 0;
2042       buf[10] = 12;
2043       buf[11] = 12;
2044       n = 12;
2045     } else {
2046       error(-1, "Type 2 fixed point constant out of range");
2047     }
2048   } else {
2049     y = (int)x;
2050     if (y >= -107 && y <= 107) {
2051       buf[0] = (Guchar)(y + 139);
2052       n = 1;
2053     } else if (y > 107 && y <= 1131) {
2054       y -= 108;
2055       buf[0] = (Guchar)((y >> 8) + 247);
2056       buf[1] = (Guchar)(y & 0xff);
2057       n = 2;
2058     } else if (y < -107 && y >= -1131) {
2059       y = -y - 108;
2060       buf[0] = (Guchar)((y >> 8) + 251);
2061       buf[1] = (Guchar)(y & 0xff);
2062       n = 2;
2063     } else {
2064       buf[0] = 255;
2065       buf[1] = (Guchar)(y >> 24);
2066       buf[2] = (Guchar)(y >> 16);
2067       buf[3] = (Guchar)(y >> 8);
2068       buf[4] = (Guchar)y;
2069       n = 5;
2070     }
2071   }
2072   charBuf->append((char *)buf, n);
2073 }
2074
2075 void Type1CFontFile::eexecDumpOp1(int opA) {
2076   charBuf->append((char)opA);
2077 }
2078
2079 void Type1CFontFile::eexecDumpOp2(int opA) {
2080   charBuf->append((char)12);
2081   charBuf->append((char)opA);
2082 }
2083
2084 void Type1CFontFile::eexecWriteCharstring(Guchar *s, int n) {
2085   Guchar x;
2086   int i;
2087
2088   // eexec encryption
2089   for (i = 0; i < n; ++i) {
2090     x = s[i] ^ (r1 >> 8);
2091     r1 = (x + r1) * 52845 + 22719;
2092     (*outputFunc)(outputStream, &hexChars[x >> 4], 1);
2093     (*outputFunc)(outputStream, &hexChars[x & 0x0f], 1);
2094     line += 2;
2095     if (line == 64) {
2096       (*outputFunc)(outputStream, "\n", 1);
2097       line = 0;
2098     }
2099   }
2100 }
2101
2102 void Type1CFontFile::getDeltaInt(char *buf, char *key, double *opA,
2103                                  int n) {
2104   int x, i;
2105
2106   sprintf(buf, "/%s [", key);
2107   buf += strlen(buf);
2108   x = 0;
2109   for (i = 0; i < n; ++i) {
2110     x += (int)opA[i];
2111     sprintf(buf, "%s%d", i > 0 ? " " : "", x);
2112     buf += strlen(buf);
2113   }
2114   sprintf(buf, "] def\n");
2115 }
2116
2117 void Type1CFontFile::getDeltaReal(char *buf, char *key, double *opA,
2118                                   int n) {
2119   double x;
2120   int i;
2121
2122   sprintf(buf, "/%s [", key);
2123   buf += strlen(buf);
2124   x = 0;
2125   for (i = 0; i < n; ++i) {
2126     x += opA[i];
2127     sprintf(buf, "%s%g", i > 0 ? " " : "", x);
2128     buf += strlen(buf);
2129   }
2130   sprintf(buf, "] def\n");
2131 }
2132
2133 int Type1CFontFile::getIndexLen(Guchar *indexPtr) {
2134   return (int)getWord(indexPtr, 2);
2135 }
2136
2137 Guchar *Type1CFontFile::getIndexValPtr(Guchar *indexPtr, int i) {
2138   int n, offSize;
2139   Guchar *idxStartPtr;
2140
2141   n = (int)getWord(indexPtr, 2);
2142   offSize = indexPtr[2];
2143   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2144   return idxStartPtr + getWord(indexPtr + 3 + i * offSize, offSize);
2145 }
2146
2147 Guchar *Type1CFontFile::getIndexEnd(Guchar *indexPtr) {
2148   int n, offSize;
2149   Guchar *idxStartPtr;
2150
2151   n = (int)getWord(indexPtr, 2);
2152   offSize = indexPtr[2];
2153   idxStartPtr = indexPtr + 3 + (n + 1) * offSize - 1;
2154   return idxStartPtr + getWord(indexPtr + 3 + n * offSize, offSize);
2155 }
2156
2157 Guint Type1CFontFile::getWord(Guchar *ptr, int size) {
2158   Guint x;
2159   int i;
2160
2161   x = 0;
2162   for (i = 0; i < size; ++i) {
2163     x = (x << 8) + *ptr++;
2164   }
2165   return x;
2166 }
2167
2168 double Type1CFontFile::getNum(Guchar **ptr, GBool *isFP) {
2169   static char nybChars[16] = "0123456789.ee -";
2170   int b0, b, nyb0, nyb1;
2171   double x;
2172   char buf[65];
2173   int i;
2174
2175   x = 0;
2176   *isFP = gFalse;
2177   b0 = (*ptr)[0];
2178   if (b0 < 28) {
2179     x = 0;
2180   } else if (b0 == 28) {
2181     x = ((*ptr)[1] << 8) + (*ptr)[2];
2182     *ptr += 3;
2183   } else if (b0 == 29) {
2184     x = ((*ptr)[1] << 24) + ((*ptr)[2] << 16) + ((*ptr)[3] << 8) + (*ptr)[4];
2185     *ptr += 5;
2186   } else if (b0 == 30) {
2187     *ptr += 1;
2188     i = 0;
2189     do {
2190       b = *(*ptr)++;
2191       nyb0 = b >> 4;
2192       nyb1 = b & 0x0f;
2193       if (nyb0 == 0xf) {
2194         break;
2195       }
2196       buf[i++] = nybChars[nyb0];
2197       if (i == 64) {
2198         break;
2199       }
2200       if (nyb0 == 0xc) {
2201         buf[i++] = '-';
2202       }
2203       if (i == 64) {
2204         break;
2205       }
2206       if (nyb1 == 0xf) {
2207         break;
2208       }
2209       buf[i++] = nybChars[nyb1];
2210       if (i == 64) {
2211         break;
2212       }
2213       if (nyb1 == 0xc) {
2214         buf[i++] = '-';
2215       }
2216     } while (i < 64);
2217     buf[i] = '\0';
2218     {
2219       char *theLocale = setlocale(LC_NUMERIC, "C");
2220       x = atof(buf);
2221       setlocale(LC_NUMERIC, theLocale);
2222     }
2223     *isFP = gTrue;
2224   } else if (b0 == 31) {
2225     x = 0;
2226   } else if (b0 < 247) {
2227     x = b0 - 139;
2228     *ptr += 1;
2229   } else if (b0 < 251) {
2230     x = ((b0 - 247) << 8) + (*ptr)[1] + 108;
2231     *ptr += 2;
2232   } else {
2233     x = -((b0 - 251) << 8) - (*ptr)[1] - 108;
2234     *ptr += 2;
2235   }
2236   return x;
2237 }
2238
2239 char *Type1CFontFile::getString(int sid, char *buf) {
2240   Guchar *idxPtr0, *idxPtr1;
2241   int n;
2242
2243   if (sid < 391) {
2244     strcpy(buf, type1CStdStrings[sid]);
2245   } else {
2246     sid -= 391;
2247     idxPtr0 = getIndexValPtr(stringIdxPtr, sid);
2248     idxPtr1 = getIndexValPtr(stringIdxPtr, sid + 1);
2249     if ((n = idxPtr1 - idxPtr0) > 255) {
2250       n = 255;
2251     }
2252     strncpy(buf, (char *)idxPtr0, n);
2253     buf[n] = '\0';
2254   }
2255   return buf;
2256 }
2257
2258 //------------------------------------------------------------------------
2259 // TrueTypeFontFile
2260 //------------------------------------------------------------------------
2261
2262 //
2263 // Terminology
2264 // -----------
2265 //
2266 // character code = number used as an element of a text string
2267 //
2268 // character name = glyph name = name for a particular glyph within a
2269 //                  font
2270 //
2271 // glyph index = position (within some internal table in the font)
2272 //               where the instructions to draw a particular glyph are
2273 //               stored
2274 //
2275 // Type 1 fonts
2276 // ------------
2277 //
2278 // Type 1 fonts contain:
2279 //
2280 // Encoding: array of glyph names, maps char codes to glyph names
2281 //
2282 //           Encoding[charCode] = charName
2283 //
2284 // CharStrings: dictionary of instructions, keyed by character names,
2285 //              maps character name to glyph data
2286 //
2287 //              CharStrings[charName] = glyphData
2288 //
2289 // TrueType fonts
2290 // --------------
2291 //
2292 // TrueType fonts contain:
2293 //
2294 // 'cmap' table: mapping from character code to glyph index; there may
2295 //               be multiple cmaps in a TrueType font
2296 //
2297 //               cmap[charCode] = glyphIdx
2298 //
2299 // 'post' table: mapping from glyph index to glyph name
2300 //
2301 //               post[glyphIdx] = glyphName
2302 //
2303 // Type 42 fonts
2304 // -------------
2305 //
2306 // Type 42 fonts contain:
2307 //
2308 // Encoding: array of glyph names, maps char codes to glyph names
2309 //
2310 //           Encoding[charCode] = charName
2311 //
2312 // CharStrings: dictionary of glyph indexes, keyed by character names,
2313 //              maps character name to glyph index
2314 //
2315 //              CharStrings[charName] = glyphIdx
2316 //
2317
2318 struct TTFontTableHdr {
2319   char tag[4];
2320   Guint checksum;
2321   Guint offset;
2322   Guint length;
2323 };
2324
2325 struct T42Table {
2326   char *tag;                    // 4-byte tag
2327   GBool required;               // required by the TrueType spec?
2328 };
2329
2330 // TrueType tables to be embedded in Type 42 fonts.
2331 // NB: the table names must be in alphabetical order here.
2332 #define nT42Tables 11
2333 static T42Table t42Tables[nT42Tables] = {
2334   { "cvt ", gTrue  },
2335   { "fpgm", gTrue  },
2336   { "glyf", gTrue  },
2337   { "head", gTrue  },
2338   { "hhea", gTrue  },
2339   { "hmtx", gTrue  },
2340   { "loca", gTrue  },
2341   { "maxp", gTrue  },
2342   { "prep", gTrue  },
2343   { "vhea", gFalse },
2344   { "vmtx", gFalse }
2345 };
2346 #define t42HeadTable 3
2347 #define t42LocaTable 6
2348 #define t42GlyfTable 2
2349
2350 // Glyph names in some arbitrary standard that Apple uses for their
2351 // TrueType fonts.
2352 static char *macGlyphNames[258] = {
2353   ".notdef",
2354   "null",
2355   "CR",
2356   "space",
2357   "exclam",
2358   "quotedbl",
2359   "numbersign",
2360   "dollar",
2361   "percent",
2362   "ampersand",
2363   "quotesingle",
2364   "parenleft",
2365   "parenright",
2366   "asterisk",
2367   "plus",
2368   "comma",
2369   "hyphen",
2370   "period",
2371   "slash",
2372   "zero",
2373   "one",
2374   "two",
2375   "three",
2376   "four",
2377   "five",
2378   "six",
2379   "seven",
2380   "eight",
2381   "nine",
2382   "colon",
2383   "semicolon",
2384   "less",
2385   "equal",
2386   "greater",
2387   "question",
2388   "at",
2389   "A",
2390   "B",
2391   "C",
2392   "D",
2393   "E",
2394   "F",
2395   "G",
2396   "H",
2397   "I",
2398   "J",
2399   "K",
2400   "L",
2401   "M",
2402   "N",
2403   "O",
2404   "P",
2405   "Q",
2406   "R",
2407   "S",
2408   "T",
2409   "U",
2410   "V",
2411   "W",
2412   "X",
2413   "Y",
2414   "Z",
2415   "bracketleft",
2416   "backslash",
2417   "bracketright",
2418   "asciicircum",
2419   "underscore",
2420   "grave",
2421   "a",
2422   "b",
2423   "c",
2424   "d",
2425   "e",
2426   "f",
2427   "g",
2428   "h",
2429   "i",
2430   "j",
2431   "k",
2432   "l",
2433   "m",
2434   "n",
2435   "o",
2436   "p",
2437   "q",
2438   "r",
2439   "s",
2440   "t",
2441   "u",
2442   "v",
2443   "w",
2444   "x",
2445   "y",
2446   "z",
2447   "braceleft",
2448   "bar",
2449   "braceright",
2450   "asciitilde",
2451   "Adieresis",
2452   "Aring",
2453   "Ccedilla",
2454   "Eacute",
2455   "Ntilde",
2456   "Odieresis",
2457   "Udieresis",
2458   "aacute",
2459   "agrave",
2460   "acircumflex",
2461   "adieresis",
2462   "atilde",
2463   "aring",
2464   "ccedilla",
2465   "eacute",
2466   "egrave",
2467   "ecircumflex",
2468   "edieresis",
2469   "iacute",
2470   "igrave",
2471   "icircumflex",
2472   "idieresis",
2473   "ntilde",
2474   "oacute",
2475   "ograve",
2476   "ocircumflex",
2477   "odieresis",
2478   "otilde",
2479   "uacute",
2480   "ugrave",
2481   "ucircumflex",
2482   "udieresis",
2483   "dagger",
2484   "degree",
2485   "cent",
2486   "sterling",
2487   "section",
2488   "bullet",
2489   "paragraph",
2490   "germandbls",
2491   "registered",
2492   "copyright",
2493   "trademark",
2494   "acute",
2495   "dieresis",
2496   "notequal",
2497   "AE",
2498   "Oslash",
2499   "infinity",
2500   "plusminus",
2501   "lessequal",
2502   "greaterequal",
2503   "yen",
2504   "mu1",
2505   "partialdiff",
2506   "summation",
2507   "product",
2508   "pi",
2509   "integral",
2510   "ordfeminine",
2511   "ordmasculine",
2512   "Ohm",
2513   "ae",
2514   "oslash",
2515   "questiondown",
2516   "exclamdown",
2517   "logicalnot",
2518   "radical",
2519   "florin",
2520   "approxequal",
2521   "increment",
2522   "guillemotleft",
2523   "guillemotright",
2524   "ellipsis",
2525   "nbspace",
2526   "Agrave",
2527   "Atilde",
2528   "Otilde",
2529   "OE",
2530   "oe",
2531   "endash",
2532   "emdash",
2533   "quotedblleft",
2534   "quotedblright",
2535   "quoteleft",
2536   "quoteright",
2537   "divide",
2538   "lozenge",
2539   "ydieresis",
2540   "Ydieresis",
2541   "fraction",
2542   "currency",
2543   "guilsinglleft",
2544   "guilsinglright",
2545   "fi",
2546   "fl",
2547   "daggerdbl",
2548   "periodcentered",
2549   "quotesinglbase",
2550   "quotedblbase",
2551   "perthousand",
2552   "Acircumflex",
2553   "Ecircumflex",
2554   "Aacute",
2555   "Edieresis",
2556   "Egrave",
2557   "Iacute",
2558   "Icircumflex",
2559   "Idieresis",
2560   "Igrave",
2561   "Oacute",
2562   "Ocircumflex",
2563   "applelogo",
2564   "Ograve",
2565   "Uacute",
2566   "Ucircumflex",
2567   "Ugrave",
2568   "dotlessi",
2569   "circumflex",
2570   "tilde",
2571   "overscore",
2572   "breve",
2573   "dotaccent",
2574   "ring",
2575   "cedilla",
2576   "hungarumlaut",
2577   "ogonek",
2578   "caron",
2579   "Lslash",
2580   "lslash",
2581   "Scaron",
2582   "scaron",
2583   "Zcaron",
2584   "zcaron",
2585   "brokenbar",
2586   "Eth",
2587   "eth",
2588   "Yacute",
2589   "yacute",
2590   "Thorn",
2591   "thorn",
2592   "minus",
2593   "multiply",
2594   "onesuperior",
2595   "twosuperior",
2596   "threesuperior",
2597   "onehalf",
2598   "onequarter",
2599   "threequarters",
2600   "franc",
2601   "Gbreve",
2602   "gbreve",
2603   "Idot",
2604   "Scedilla",
2605   "scedilla",
2606   "Cacute",
2607   "cacute",
2608   "Ccaron",
2609   "ccaron",
2610   "dmacron"
2611 };
2612
2613 enum T42FontIndexMode {
2614   t42FontModeUnicode,
2615   t42FontModeCharCode,
2616   t42FontModeCharCodeOffset,
2617   t42FontModeMacRoman
2618 };
2619
2620 TrueTypeFontFile::TrueTypeFontFile(char *fileA, int lenA) {
2621   int pos, i, idx, n, length;
2622   Guint size, startPos, endPos;
2623
2624   file = fileA;
2625   len = lenA;
2626
2627   encoding = NULL;
2628
2629   // read table directory
2630   nTables = getUShort(4);
2631   tableHdrs = (TTFontTableHdr *)gmalloc(nTables * sizeof(TTFontTableHdr));
2632   pos = 12;
2633   for (i = 0; i < nTables; ++i) {
2634     tableHdrs[i].tag[0] = getByte(pos+0);
2635     tableHdrs[i].tag[1] = getByte(pos+1);
2636     tableHdrs[i].tag[2] = getByte(pos+2);
2637     tableHdrs[i].tag[3] = getByte(pos+3);
2638     tableHdrs[i].checksum = getULong(pos+4);
2639     tableHdrs[i].offset = getULong(pos+8);
2640     tableHdrs[i].length = getULong(pos+12);
2641     pos += 16;
2642   }
2643
2644   // check for tables that are required by both the TrueType spec
2645   // and the Type 42 spec
2646   if (seekTable("head") < 0 ||
2647       seekTable("hhea") < 0 ||
2648       seekTable("loca") < 0 ||
2649       seekTable("maxp") < 0 ||
2650       seekTable("glyf") < 0 ||
2651       seekTable("hmtx") < 0) {
2652     error(-1, "TrueType font file is missing a required table");
2653     return;
2654   }
2655
2656   // some embedded TrueType fonts have an incorrect (too small) cmap
2657   // table size
2658   idx = seekTableIdx("cmap");
2659   if (idx >= 0) {
2660     pos = tableHdrs[idx].offset;
2661     n = getUShort(pos + 2);
2662     size = (Guint)(4 + 8 * n);
2663     for (i = 0; i < n; ++i) {
2664       startPos = getULong(pos + 4 + 8*i + 4);
2665       length = getUShort(pos + startPos + 2);
2666       endPos = startPos + length;
2667       if (endPos > size) {
2668         size = endPos;
2669       }
2670     }
2671     if ((mungedCmapSize = size > tableHdrs[idx].length)) {
2672 #if 0 // don't bother printing this error message - it's too common
2673       error(-1, "Bad cmap table size in TrueType font");
2674 #endif
2675       tableHdrs[idx].length = size;
2676     }
2677   } else {
2678     mungedCmapSize = gFalse;
2679   }
2680
2681   // read the 'head' table
2682   pos = seekTable("head");
2683   bbox[0] = getShort(pos + 36);
2684   bbox[1] = getShort(pos + 38);
2685   bbox[2] = getShort(pos + 40);
2686   bbox[3] = getShort(pos + 42);
2687   locaFmt = getShort(pos + 50);
2688
2689   // read the 'maxp' table
2690   pos = seekTable("maxp");
2691   nGlyphs = getUShort(pos + 4);
2692 }
2693
2694 TrueTypeFontFile::~TrueTypeFontFile() {
2695   int i;
2696
2697   if (encoding) {
2698     for (i = 0; i < 256; ++i) {
2699       gfree(encoding[i]);
2700     }
2701     gfree(encoding);
2702   }
2703   gfree(tableHdrs);
2704 }
2705
2706 char *TrueTypeFontFile::getName() {
2707   return NULL;
2708 }
2709
2710 char **TrueTypeFontFile::getEncoding() {
2711   int cmap[256];
2712   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt;
2713   int cmapLen, cmapOffset, cmapFirst;
2714   int segCnt, segStart, segEnd, segDelta, segOffset;
2715   int pos, i, j, k;
2716   Guint fmt;
2717   GString *s;
2718   int stringIdx, stringPos, n;
2719
2720   if (encoding) {
2721     return encoding;
2722   }
2723
2724   //----- construct the (char code) -> (glyph idx) mapping
2725
2726   // map everything to the missing glyph
2727   for (i = 0; i < 256; ++i) {
2728     cmap[i] = 0;
2729   }
2730
2731   // look for the 'cmap' table
2732   if ((pos = seekTable("cmap")) >= 0) {
2733     nCmaps = getUShort(pos+2);
2734
2735     // if the font has a Windows-symbol cmap, use it;
2736     // otherwise, use the first cmap in the table
2737     for (i = 0; i < nCmaps; ++i) {
2738       cmapPlatform = getUShort(pos + 4 + 8*i);
2739       cmapEncoding = getUShort(pos + 4 + 8*i + 2);
2740       if (cmapPlatform == 3 && cmapEncoding == 0) {
2741         break;
2742       }
2743     }
2744     if (i >= nCmaps) {
2745       i = 0;
2746       cmapPlatform = getUShort(pos + 4);
2747       cmapEncoding = getUShort(pos + 4 + 2);
2748     }
2749     pos += getULong(pos + 4 + 8*i + 4);
2750
2751     // read the cmap
2752     cmapFmt = getUShort(pos);
2753     switch (cmapFmt) {
2754     case 0: // byte encoding table (Apple standard)
2755       cmapLen = getUShort(pos + 2);
2756       for (i = 0; i < cmapLen && i < 256; ++i) {
2757         cmap[i] = getByte(pos + 6 + i);
2758       }
2759       break;
2760     case 4: // segment mapping to delta values (Microsoft standard)
2761       if (cmapPlatform == 3 && cmapEncoding == 0) {
2762         // Windows-symbol uses char codes 0xf000 - 0xf0ff
2763         cmapOffset = 0xf000;
2764       } else {
2765         cmapOffset = 0;
2766       }
2767       segCnt = getUShort(pos + 6) / 2;
2768       for (i = 0; i < segCnt; ++i) {
2769         segEnd = getUShort(pos + 14 + 2*i);
2770         segStart = getUShort(pos + 16 + 2*segCnt + 2*i);
2771         segDelta = getUShort(pos + 16 + 4*segCnt + 2*i);
2772         segOffset = getUShort(pos + 16 + 6*segCnt + 2*i);
2773         if (segStart - cmapOffset <= 0xff &&
2774             segEnd - cmapOffset >= 0) {
2775           for (j = (segStart - cmapOffset >= 0) ? segStart : cmapOffset;
2776                j <= segEnd && j - cmapOffset <= 0xff;
2777                ++j) {
2778             if (segOffset == 0) {
2779               k = (j + segDelta) & 0xffff;
2780             } else {
2781               k = getUShort(pos + 16 + 6*segCnt + 2*i +
2782                             segOffset + 2 * (j - segStart));
2783               if (k != 0) {
2784                 k = (k + segDelta) & 0xffff;
2785               }
2786             }
2787             cmap[j - cmapOffset] = k;
2788           }
2789         }
2790       }
2791       break;
2792     case 6: // trimmed table mapping
2793       cmapFirst = getUShort(pos + 6);
2794       cmapLen = getUShort(pos + 8);
2795       for (i = cmapFirst; i < 256 && i < cmapFirst + cmapLen; ++i) {
2796         cmap[i] = getUShort(pos + 10 + 2*i);
2797       }
2798       break;
2799     default:
2800       error(-1, "Unimplemented cmap format (%d) in TrueType font file",
2801             cmapFmt);
2802       break;
2803     }
2804   }
2805
2806   //----- construct the (glyph idx) -> (glyph name) mapping
2807   //----- and compute the (char code) -> (glyph name) mapping
2808
2809   encoding = (char **)gmalloc(256 * sizeof(char *));
2810   for (i = 0; i < 256; ++i) {
2811     encoding[i] = NULL;
2812   }
2813
2814   if ((pos = seekTable("post")) >= 0) {
2815     fmt = getULong(pos);
2816
2817     // Apple font
2818     if (fmt == 0x00010000) {
2819       for (i = 0; i < 256; ++i) {
2820         j = (cmap[i] < 258) ? cmap[i] : 0;
2821         encoding[i] = copyString(macGlyphNames[j]);
2822       }
2823
2824     // Microsoft font
2825     } else if (fmt == 0x00020000) {
2826       stringIdx = 0;
2827       stringPos = pos + 34 + 2*nGlyphs;
2828       for (i = 0; i < 256; ++i) {
2829         if (cmap[i] < nGlyphs) {
2830           j = getUShort(pos + 34 + 2 * cmap[i]);
2831           if (j < 258) {
2832             encoding[i] = copyString(macGlyphNames[j]);
2833           } else {
2834             j -= 258;
2835             if (j != stringIdx) {
2836               for (stringIdx = 0, stringPos = pos + 34 + 2*nGlyphs;
2837                    stringIdx < j;
2838                    ++stringIdx, stringPos += 1 + getByte(stringPos)) ;
2839             }
2840             n = getByte(stringPos);
2841             s = new GString(file + stringPos + 1, n);
2842             encoding[i] = copyString(s->getCString());
2843             delete s;
2844             ++stringIdx;
2845             stringPos += 1 + n;
2846           }
2847         } else {
2848           encoding[i] = copyString(macGlyphNames[0]);
2849         }
2850       }
2851
2852     // Apple subset
2853     } else if (fmt == 0x000280000) {
2854       for (i = 0; i < 256; ++i) {
2855         if (cmap[i] < nGlyphs) {
2856           j = i + getChar(pos + 32 + cmap[i]);
2857         } else {
2858           j = 0;
2859         }
2860         encoding[i] = copyString(macGlyphNames[j]);
2861       }
2862
2863     // Ugh, just assume the Apple glyph set
2864     } else {
2865       for (i = 0; i < 256; ++i) {
2866         j = (cmap[i] < 258) ? cmap[i] : 0;
2867         encoding[i] = copyString(macGlyphNames[j]);
2868       }
2869     }
2870
2871   // no "post" table: assume the Apple glyph set
2872   } else {
2873     for (i = 0; i < 256; ++i) {
2874       j = (cmap[i] < 258) ? cmap[i] : 0;
2875       encoding[i] = copyString(macGlyphNames[j]);
2876     }
2877   }
2878
2879   return encoding;
2880 }
2881
2882 void TrueTypeFontFile::convertToType42(char *name, char **encodingA,
2883                                        CharCodeToUnicode *toUnicode,
2884                                        GBool pdfFontHasEncoding,
2885                                        FontFileOutputFunc outputFunc,
2886                                        void *outputStream) {
2887   char buf[512];
2888
2889   // write the header
2890   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2891   (*outputFunc)(outputStream, buf, strlen(buf));
2892
2893   // begin the font dictionary
2894   (*outputFunc)(outputStream, "10 dict begin\n", 14);
2895   (*outputFunc)(outputStream, "/FontName /", 11);
2896   (*outputFunc)(outputStream, name, strlen(name));
2897   (*outputFunc)(outputStream, " def\n", 5);
2898   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2899   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
2900   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
2901           bbox[0], bbox[1], bbox[2], bbox[3]);
2902   (*outputFunc)(outputStream, buf, strlen(buf));
2903   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
2904
2905   // write the guts of the dictionary
2906   cvtEncoding(encodingA, pdfFontHasEncoding, outputFunc, outputStream);
2907   cvtCharStrings(encodingA, toUnicode, pdfFontHasEncoding,
2908                  outputFunc, outputStream);
2909   cvtSfnts(outputFunc, outputStream, NULL);
2910
2911   // end the dictionary and define the font
2912   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
2913 }
2914
2915 void TrueTypeFontFile::convertToCIDType2(char *name, Gushort *cidMap,
2916                                          int nCIDs,
2917                                          FontFileOutputFunc outputFunc,
2918                                          void *outputStream) {
2919   char buf[512];
2920   Gushort cid;
2921   int i, j, k;
2922
2923   // write the header
2924   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", getFixed(0));
2925   (*outputFunc)(outputStream, buf, strlen(buf));
2926
2927   // begin the font dictionary
2928   (*outputFunc)(outputStream, "20 dict begin\n", 14);
2929   (*outputFunc)(outputStream, "/CIDFontName /", 14);
2930   (*outputFunc)(outputStream, name, strlen(name));
2931   (*outputFunc)(outputStream, " def\n", 5);
2932   (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
2933   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
2934   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
2935   (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
2936   (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
2937   (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
2938   (*outputFunc)(outputStream, "  end def\n", 10);
2939   (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
2940   if (cidMap) {
2941     sprintf(buf, "/CIDCount %d def\n", nCIDs);
2942     (*outputFunc)(outputStream, buf, strlen(buf));
2943     if (nCIDs > 32767) {
2944       (*outputFunc)(outputStream, "/CIDMap [", 9);
2945       for (i = 0; i < nCIDs; i += 32768 - 16) {
2946         (*outputFunc)(outputStream, "<\n", 2);
2947         for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
2948           (*outputFunc)(outputStream, "  ", 2);
2949           for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
2950             cid = cidMap[i+j+k];
2951             sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2952             (*outputFunc)(outputStream, buf, strlen(buf));
2953           }
2954           (*outputFunc)(outputStream, "\n", 1);
2955         }
2956         (*outputFunc)(outputStream, "  >", 3);
2957       }
2958       (*outputFunc)(outputStream, "\n", 1);
2959       (*outputFunc)(outputStream, "] def\n", 6);
2960     } else {
2961       (*outputFunc)(outputStream, "/CIDMap <\n", 10);
2962       for (i = 0; i < nCIDs; i += 16) {
2963         (*outputFunc)(outputStream, "  ", 2);
2964         for (j = 0; j < 16 && i+j < nCIDs; ++j) {
2965           cid = cidMap[i+j];
2966           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
2967           (*outputFunc)(outputStream, buf, strlen(buf));
2968         }
2969         (*outputFunc)(outputStream, "\n", 1);
2970       }
2971       (*outputFunc)(outputStream, "> def\n", 6);
2972     }
2973   } else {
2974     // direct mapping - just fill the string(s) with s[i]=i
2975     sprintf(buf, "/CIDCount %d def\n", nGlyphs);
2976     (*outputFunc)(outputStream, buf, strlen(buf));
2977     if (nGlyphs > 32767) {
2978       (*outputFunc)(outputStream, "/CIDMap [\n", 10);
2979       for (i = 0; i < nGlyphs; i += 32767) {
2980         j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
2981         sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
2982         (*outputFunc)(outputStream, buf, strlen(buf));
2983         sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
2984         (*outputFunc)(outputStream, buf, strlen(buf));
2985         sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
2986                 " 255 and put\n", i);
2987         (*outputFunc)(outputStream, buf, strlen(buf));
2988         (*outputFunc)(outputStream, "  } for\n", 8);
2989       }
2990       (*outputFunc)(outputStream, "] def\n", 6);
2991     } else {
2992       sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
2993       (*outputFunc)(outputStream, buf, strlen(buf));
2994       sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
2995       (*outputFunc)(outputStream, buf, strlen(buf));
2996       (*outputFunc)(outputStream,
2997                     "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
2998       (*outputFunc)(outputStream,
2999                     "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
3000       (*outputFunc)(outputStream, "  } for\n", 8);
3001       (*outputFunc)(outputStream, "def\n", 4);
3002     }
3003   }
3004   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3005   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3006           bbox[0], bbox[1], bbox[2], bbox[3]);
3007   (*outputFunc)(outputStream, buf, strlen(buf));
3008   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3009   (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
3010   (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
3011   (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
3012   (*outputFunc)(outputStream, "  end readonly def\n", 19);
3013
3014   // write the guts of the dictionary
3015   cvtSfnts(outputFunc, outputStream, NULL);
3016
3017   // end the dictionary and define the font
3018   (*outputFunc)(outputStream,
3019                 "CIDFontName currentdict end /CIDFont defineresource pop\n",
3020                 56);
3021 }
3022
3023 void TrueTypeFontFile::convertToType0(char *name, Gushort *cidMap,
3024                                       int nCIDs,
3025                                       FontFileOutputFunc outputFunc,
3026                                       void *outputStream) {
3027   char buf[512];
3028   GString *sfntsName;
3029   int n, i, j;
3030
3031   // write the Type 42 sfnts array
3032   sfntsName = (new GString(name))->append("_sfnts");
3033   cvtSfnts(outputFunc, outputStream, sfntsName);
3034   delete sfntsName;
3035
3036   // write the descendant Type 42 fonts
3037   n = cidMap ? nCIDs : nGlyphs;
3038   for (i = 0; i < n; i += 256) {
3039     (*outputFunc)(outputStream, "10 dict begin\n", 14);
3040     (*outputFunc)(outputStream, "/FontName /", 11);
3041     (*outputFunc)(outputStream, name, strlen(name));
3042     sprintf(buf, "_%02x def\n", i >> 8);
3043     (*outputFunc)(outputStream, buf, strlen(buf));
3044     (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
3045     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3046     sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
3047             bbox[0], bbox[1], bbox[2], bbox[3]);
3048     (*outputFunc)(outputStream, buf, strlen(buf));
3049     (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
3050     (*outputFunc)(outputStream, "/sfnts ", 7);
3051     (*outputFunc)(outputStream, name, strlen(name));
3052     (*outputFunc)(outputStream, "_sfnts def\n", 11);
3053     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3054     for (j = 0; j < 256 && i+j < n; ++j) {
3055       sprintf(buf, "dup %d /c%02x put\n", j, j);
3056       (*outputFunc)(outputStream, buf, strlen(buf));
3057     }
3058     (*outputFunc)(outputStream, "readonly def\n", 13);
3059     (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
3060     (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3061     for (j = 0; j < 256 && i+j < n; ++j) {
3062       sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
3063       (*outputFunc)(outputStream, buf, strlen(buf));
3064     }
3065     (*outputFunc)(outputStream, "end readonly def\n", 17);
3066     (*outputFunc)(outputStream,
3067                   "FontName currentdict end definefont pop\n", 40);
3068   }
3069
3070   // write the Type 0 parent font
3071   (*outputFunc)(outputStream, "16 dict begin\n", 14);
3072   (*outputFunc)(outputStream, "/FontName /", 11);
3073   (*outputFunc)(outputStream, name, strlen(name));
3074   (*outputFunc)(outputStream, " def\n", 5);
3075   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
3076   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
3077   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
3078   (*outputFunc)(outputStream, "/Encoding [\n", 12);
3079   for (i = 0; i < n; i += 256) {
3080     sprintf(buf, "%d\n", i >> 8);
3081     (*outputFunc)(outputStream, buf, strlen(buf));
3082   }
3083   (*outputFunc)(outputStream, "] def\n", 6);
3084   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
3085   for (i = 0; i < n; i += 256) {
3086     (*outputFunc)(outputStream, "/", 1);
3087     (*outputFunc)(outputStream, name, strlen(name));
3088     sprintf(buf, "_%02x findfont\n", i >> 8);
3089     (*outputFunc)(outputStream, buf, strlen(buf));
3090   }
3091   (*outputFunc)(outputStream, "] def\n", 6);
3092   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
3093 }
3094
3095 int TrueTypeFontFile::getByte(int pos) {
3096   if (pos < 0 || pos >= len) {
3097     return 0;
3098   }
3099   return file[pos] & 0xff;
3100 }
3101
3102 int TrueTypeFontFile::getChar(int pos) {
3103   int x;
3104
3105   if (pos < 0 || pos >= len) {
3106     return 0;
3107   }
3108   x = file[pos] & 0xff;
3109   if (x & 0x80)
3110     x |= 0xffffff00;
3111   return x;
3112 }
3113
3114 int TrueTypeFontFile::getUShort(int pos) {
3115   int x;
3116
3117   if (pos < 0 || pos+1 >= len) {
3118     return 0;
3119   }
3120   x = file[pos] & 0xff;
3121   x = (x << 8) + (file[pos+1] & 0xff);
3122   return x;
3123 }
3124
3125 int TrueTypeFontFile::getShort(int pos) {
3126   int x;
3127
3128   if (pos < 0 || pos+1 >= len) {
3129     return 0;
3130   }
3131   x = file[pos] & 0xff;
3132   x = (x << 8) + (file[pos+1] & 0xff);
3133   if (x & 0x8000)
3134     x |= 0xffff0000;
3135   return x;
3136 }
3137
3138 Guint TrueTypeFontFile::getULong(int pos) {
3139   int x;
3140
3141   if (pos < 0 || pos+3 >= len) {
3142     return 0;
3143   }
3144   x = file[pos] & 0xff;
3145   x = (x << 8) + (file[pos+1] & 0xff);
3146   x = (x << 8) + (file[pos+2] & 0xff);
3147   x = (x << 8) + (file[pos+3] & 0xff);
3148   return x;
3149 }
3150
3151 double TrueTypeFontFile::getFixed(int pos) {
3152   int x, y;
3153
3154   x = getShort(pos);
3155   y = getUShort(pos+2);
3156   return (double)x + (double)y / 65536;
3157 }
3158
3159 int TrueTypeFontFile::seekTable(char *tag) {
3160   int i;
3161
3162   for (i = 0; i < nTables; ++i) {
3163     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3164       return tableHdrs[i].offset;
3165     }
3166   }
3167   return -1;
3168 }
3169
3170 int TrueTypeFontFile::seekTableIdx(char *tag) {
3171   int i;
3172
3173   for (i = 0; i < nTables; ++i) {
3174     if (!strncmp(tableHdrs[i].tag, tag, 4)) {
3175       return i;
3176     }
3177   }
3178   return -1;
3179 }
3180
3181 void TrueTypeFontFile::cvtEncoding(char **encodingA, GBool pdfFontHasEncoding,
3182                                    FontFileOutputFunc outputFunc,
3183                                    void *outputStream) {
3184   char *name;
3185   char buf[64];
3186   int i;
3187
3188   (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
3189   if (pdfFontHasEncoding) {
3190     for (i = 0; i < 256; ++i) {
3191       if (!(name = encodingA[i])) {
3192         name = ".notdef";
3193       }
3194       sprintf(buf, "dup %d /", i);
3195       (*outputFunc)(outputStream, buf, strlen(buf));
3196       (*outputFunc)(outputStream, name, strlen(name));
3197       (*outputFunc)(outputStream, " put\n", 5);
3198     }
3199   } else {
3200     for (i = 0; i < 256; ++i) {
3201       sprintf(buf, "dup %d /c%02x put\n", i, i);
3202       (*outputFunc)(outputStream, buf, strlen(buf));
3203     }
3204   }
3205   (*outputFunc)(outputStream, "readonly def\n", 13);
3206 }
3207
3208 void TrueTypeFontFile::cvtCharStrings(char **encodingA,
3209                                       CharCodeToUnicode *toUnicode,
3210                                       GBool pdfFontHasEncoding,
3211                                       FontFileOutputFunc outputFunc,
3212                                       void *outputStream) {
3213   int unicodeCmap, macRomanCmap, msSymbolCmap;
3214   int nCmaps, cmapPlatform, cmapEncoding, cmapFmt, cmapOffset;
3215   T42FontIndexMode mode;
3216   char *name;
3217   char buf[64], buf2[16];
3218   Unicode u;
3219   int pos, i, j, k;
3220
3221   // always define '.notdef'
3222   (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
3223   (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
3224
3225   // if there's no 'cmap' table, punt
3226   if ((pos = seekTable("cmap")) < 0) {
3227     goto err;
3228   }
3229
3230   // To match up with the Adobe-defined behaviour, we choose a cmap
3231   // like this:
3232   // 1. If the PDF font has an encoding:
3233   //    1a. If the TrueType font has a Microsoft Unicode cmap, use it,
3234   //        and use the Unicode indexes, not the char codes.
3235   //    1b. If the TrueType font has a Macintosh Roman cmap, use it,
3236   //        and reverse map the char names through MacRomanEncoding to
3237   //        get char codes.
3238   // 2. If the PDF font does not have an encoding:
3239   //    2a. If the TrueType font has a Macintosh Roman cmap, use it,
3240   //        and use char codes directly.
3241   //    2b. If the TrueType font has a Microsoft Symbol cmap, use it,
3242   //        and use (0xf000 + char code).
3243   // 3. If none of these rules apply, use the first cmap and hope for
3244   //    the best (this shouldn't happen).
3245   nCmaps = getUShort(pos+2);
3246   unicodeCmap = macRomanCmap = msSymbolCmap = -1;
3247   cmapOffset = 0;
3248   for (i = 0; i < nCmaps; ++i) {
3249     cmapPlatform = getUShort(pos + 4 + 8*i);
3250     cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3251     if (cmapPlatform == 3 && cmapEncoding == 1) {
3252       unicodeCmap = i;
3253     } else if (cmapPlatform == 1 && cmapEncoding == 0) {
3254       macRomanCmap = i;
3255     } else if (cmapPlatform == 3 && cmapEncoding == 0) {
3256       msSymbolCmap = i;
3257     }
3258   }
3259   i = 0;
3260   mode = t42FontModeCharCode;
3261   if (pdfFontHasEncoding) {
3262     if (unicodeCmap >= 0) {
3263       i = unicodeCmap;
3264       mode = t42FontModeUnicode;
3265     } else if (macRomanCmap >= 0) {
3266       i = macRomanCmap;
3267       mode = t42FontModeMacRoman;
3268     }
3269   } else {
3270     if (macRomanCmap >= 0) {
3271       i = macRomanCmap;
3272       mode = t42FontModeCharCode;
3273     } else if (msSymbolCmap >= 0) {
3274       i = msSymbolCmap;
3275       mode = t42FontModeCharCodeOffset;
3276       cmapOffset = 0xf000;
3277     }
3278   }
3279   cmapPlatform = getUShort(pos + 4 + 8*i);
3280   cmapEncoding = getUShort(pos + 4 + 8*i + 2);
3281   pos += getULong(pos + 4 + 8*i + 4);
3282   cmapFmt = getUShort(pos);
3283   if (cmapFmt != 0 && cmapFmt != 4 && cmapFmt != 6) {
3284     error(-1, "Unimplemented cmap format (%d) in TrueType font file",
3285           cmapFmt);
3286     goto err;
3287   }
3288
3289   // map char name to glyph index:
3290   // 1. use encoding to map name to char code
3291   // 2. use cmap to map char code to glyph index
3292   j = 0; // make gcc happy
3293   for (i = 0; i < 256; ++i) {
3294     if (pdfFontHasEncoding) {
3295       name = encodingA[i];
3296     } else {
3297       sprintf(buf2, "c%02x", i);
3298       name = buf2;
3299     }
3300     if (name && strcmp(name, ".notdef")) {
3301       switch (mode) {
3302       case t42FontModeUnicode:
3303         toUnicode->mapToUnicode((CharCode)i, &u, 1);
3304         j = (int)u;
3305         break;
3306       case t42FontModeCharCode:
3307         j = i;
3308         break;
3309       case t42FontModeCharCodeOffset:
3310         j = cmapOffset + i;
3311         break;
3312       case t42FontModeMacRoman:
3313         j = globalParams->getMacRomanCharCode(name);
3314         break;
3315       }
3316       // note: Distiller (maybe Adobe's PS interpreter in general)
3317       // doesn't like TrueType fonts that have CharStrings entries
3318       // which point to nonexistent glyphs, hence the (k < nGlyphs)
3319       // test
3320       if ((k = getCmapEntry(cmapFmt, pos, j)) > 0 &&
3321           k < nGlyphs) {
3322         (*outputFunc)(outputStream, "/", 1);
3323         (*outputFunc)(outputStream, name, strlen(name));
3324         sprintf(buf, " %d def\n", k);
3325         (*outputFunc)(outputStream, buf, strlen(buf));
3326       }
3327     }
3328   }
3329
3330  err:
3331   (*outputFunc)(outputStream, "end readonly def\n", 17);
3332 }
3333
3334 int TrueTypeFontFile::getCmapEntry(int cmapFmt, int pos, int code) {
3335   int cmapLen, cmapFirst;
3336   int segCnt, segEnd, segStart, segDelta, segOffset;
3337   int a, b, m, i;
3338
3339   switch (cmapFmt) {
3340   case 0: // byte encoding table (Apple standard)
3341     cmapLen = getUShort(pos + 2);
3342     if (code >= cmapLen) {
3343       return 0;
3344     }
3345     return getByte(pos + 6 + code);
3346
3347   case 4: // segment mapping to delta values (Microsoft standard)
3348     segCnt = getUShort(pos + 6) / 2;
3349     a = -1;
3350     b = segCnt - 1;
3351     segEnd = getUShort(pos + 14 + 2*b);
3352     if (code > segEnd) {
3353       // malformed font -- the TrueType spec requires the last segEnd
3354       // to be 0xffff
3355       return 0;
3356     }
3357     // invariant: seg[a].end < code <= seg[b].end
3358     while (b - a > 1) {
3359       m = (a + b) / 2;
3360       segEnd = getUShort(pos + 14 + 2*m);
3361       if (segEnd < code) {
3362         a = m;
3363       } else {
3364         b = m;
3365       }
3366     }
3367     segStart = getUShort(pos + 16 + 2*segCnt + 2*b);
3368     segDelta = getUShort(pos + 16 + 4*segCnt + 2*b);
3369     segOffset = getUShort(pos + 16 + 6*segCnt + 2*b);
3370     if (segOffset == 0) {
3371       i = (code + segDelta) & 0xffff;
3372     } else {
3373       i = getUShort(pos + 16 + 6*segCnt + 2*b +
3374                     segOffset + 2 * (code - segStart));
3375       if (i != 0) {
3376         i = (i + segDelta) & 0xffff;
3377       }
3378     }
3379     return i;
3380
3381   case 6: // trimmed table mapping
3382     cmapFirst = getUShort(pos + 6);
3383     cmapLen = getUShort(pos + 8);
3384     if (code < cmapFirst || code >= cmapFirst + cmapLen) {
3385       return 0;
3386     }
3387     return getUShort(pos + 10 + 2*(code - cmapFirst));
3388
3389   default:
3390     // shouldn't happen - this is checked earlier
3391     break;
3392   }
3393   return 0;
3394 }
3395
3396 void TrueTypeFontFile::cvtSfnts(FontFileOutputFunc outputFunc,
3397                                 void *outputStream, GString *name) {
3398   TTFontTableHdr newTableHdrs[nT42Tables];
3399   char tableDir[12 + nT42Tables*16];
3400   char headTable[54];
3401   int *origLocaTable;
3402   char *locaTable;
3403   int nNewTables;
3404   Guint checksum;
3405   int pos, glyfPos, length, glyphLength, pad;
3406   int i, j, k;
3407
3408   // construct the 'head' table, zero out the font checksum
3409   memcpy(headTable, file + seekTable("head"), 54);
3410   headTable[8] = headTable[9] = headTable[10] = headTable[11] = (char)0;
3411
3412   // read the original 'loca' table and construct the new one
3413   // (pad each glyph out to a multiple of 4 bytes)
3414   origLocaTable = (int *)gmalloc((nGlyphs + 1) * sizeof(int));
3415   pos = seekTable("loca");
3416   for (i = 0; i <= nGlyphs; ++i) {
3417     if (locaFmt) {
3418       origLocaTable[i] = getULong(pos + 4*i);
3419     } else {
3420       origLocaTable[i] = 2 * getUShort(pos + 2*i);
3421     }
3422   }
3423   locaTable = (char *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
3424   if (locaFmt) {
3425     locaTable[0] = locaTable[1] = locaTable[2] = locaTable[3] = 0;
3426   } else {
3427     locaTable[0] = locaTable[1] = 0;
3428   }
3429   pos = 0;
3430   for (i = 1; i <= nGlyphs; ++i) {
3431     length = origLocaTable[i] - origLocaTable[i-1];
3432     if (length & 3) {
3433       length += 4 - (length & 3);
3434     }
3435     pos += length;
3436     if (locaFmt) {
3437       locaTable[4*i  ] = (char)(pos >> 24);
3438       locaTable[4*i+1] = (char)(pos >> 16);
3439       locaTable[4*i+2] = (char)(pos >>  8);
3440       locaTable[4*i+3] = (char) pos;
3441     } else {
3442       locaTable[2*i  ] = (char)(pos >> 9);
3443       locaTable[2*i+1] = (char)(pos >> 1);
3444     }
3445   }
3446
3447   // count the number of tables
3448   nNewTables = 0;
3449   for (i = 0; i < nT42Tables; ++i) {
3450     if (t42Tables[i].required ||
3451         seekTable(t42Tables[i].tag) >= 0) {
3452       ++nNewTables;
3453     }
3454   }
3455
3456   // construct the new table headers, including table checksums
3457   // (pad each table out to a multiple of 4 bytes)
3458   pos = 12 + nNewTables*16;
3459   k = 0;
3460   for (i = 0; i < nT42Tables; ++i) {
3461     length = -1;
3462     checksum = 0; // make gcc happy
3463     if (i == t42HeadTable) {
3464       length = 54;
3465       checksum = computeTableChecksum(headTable, 54);
3466     } else if (i == t42LocaTable) {
3467       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3468       checksum = computeTableChecksum(locaTable, length);
3469     } else if (i == t42GlyfTable) {
3470       length = 0;
3471       checksum = 0;
3472       glyfPos = seekTable("glyf");
3473       for (j = 0; j < nGlyphs; ++j) {
3474         glyphLength = origLocaTable[j+1] - origLocaTable[j];
3475         pad = (glyphLength & 3) ? 4 - (glyphLength & 3) : 0;
3476         length += glyphLength + pad;
3477         checksum += computeTableChecksum(file + glyfPos + origLocaTable[j],
3478                                          glyphLength);
3479       }
3480     } else {
3481       if ((j = seekTableIdx(t42Tables[i].tag)) >= 0) {
3482         length = tableHdrs[j].length;
3483         checksum = computeTableChecksum(file + tableHdrs[j].offset, length);
3484       } else if (t42Tables[i].required) {
3485         error(-1, "Embedded TrueType font is missing a required table ('%s')",
3486               t42Tables[i].tag);
3487         length = 0;
3488         checksum = 0;
3489       }
3490     }
3491     if (length >= 0) {
3492       strncpy(newTableHdrs[k].tag, t42Tables[i].tag, 4);
3493       newTableHdrs[k].checksum = checksum;
3494       newTableHdrs[k].offset = pos;
3495       newTableHdrs[k].length = length;
3496       pad = (length & 3) ? 4 - (length & 3) : 0;
3497       pos += length + pad;
3498       ++k;
3499     }
3500   }
3501
3502   // construct the table directory
3503   tableDir[0] = 0x00;           // sfnt version
3504   tableDir[1] = 0x01;
3505   tableDir[2] = 0x00;
3506   tableDir[3] = 0x00;
3507   tableDir[4] = 0;              // numTables
3508   tableDir[5] = nNewTables;
3509   tableDir[6] = 0;              // searchRange
3510   tableDir[7] = (char)128;
3511   tableDir[8] = 0;              // entrySelector
3512   tableDir[9] = 3;
3513   tableDir[10] = 0;             // rangeShift
3514   tableDir[11] = (char)(16 * nNewTables - 128);
3515   pos = 12;
3516   for (i = 0; i < nNewTables; ++i) {
3517     tableDir[pos   ] = newTableHdrs[i].tag[0];
3518     tableDir[pos+ 1] = newTableHdrs[i].tag[1];
3519     tableDir[pos+ 2] = newTableHdrs[i].tag[2];
3520     tableDir[pos+ 3] = newTableHdrs[i].tag[3];
3521     tableDir[pos+ 4] = (char)(newTableHdrs[i].checksum >> 24);
3522     tableDir[pos+ 5] = (char)(newTableHdrs[i].checksum >> 16);
3523     tableDir[pos+ 6] = (char)(newTableHdrs[i].checksum >>  8);
3524     tableDir[pos+ 7] = (char) newTableHdrs[i].checksum;
3525     tableDir[pos+ 8] = (char)(newTableHdrs[i].offset >> 24);
3526     tableDir[pos+ 9] = (char)(newTableHdrs[i].offset >> 16);
3527     tableDir[pos+10] = (char)(newTableHdrs[i].offset >>  8);
3528     tableDir[pos+11] = (char) newTableHdrs[i].offset;
3529     tableDir[pos+12] = (char)(newTableHdrs[i].length >> 24);
3530     tableDir[pos+13] = (char)(newTableHdrs[i].length >> 16);
3531     tableDir[pos+14] = (char)(newTableHdrs[i].length >>  8);
3532     tableDir[pos+15] = (char) newTableHdrs[i].length;
3533     pos += 16;
3534   }
3535
3536   // compute the font checksum and store it in the head table
3537   checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
3538   for (i = 0; i < nNewTables; ++i) {
3539     checksum += newTableHdrs[i].checksum;
3540   }
3541   checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
3542   headTable[ 8] = (char)(checksum >> 24);
3543   headTable[ 9] = (char)(checksum >> 16);
3544   headTable[10] = (char)(checksum >>  8);
3545   headTable[11] = (char) checksum;
3546
3547   // start the sfnts array
3548   if (name) {
3549     (*outputFunc)(outputStream, "/", 1);
3550     (*outputFunc)(outputStream, name->getCString(), name->getLength());
3551     (*outputFunc)(outputStream, " [\n", 3);
3552   } else {
3553     (*outputFunc)(outputStream, "/sfnts [\n", 9);
3554   }
3555
3556   // write the table directory
3557   dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
3558
3559   // write the tables
3560   for (i = 0; i < nNewTables; ++i) {
3561     if (i == t42HeadTable) {
3562       dumpString(headTable, 54, outputFunc, outputStream);
3563     } else if (i == t42LocaTable) {
3564       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
3565       dumpString(locaTable, length, outputFunc, outputStream);
3566     } else if (i == t42GlyfTable) {
3567       glyfPos = seekTable("glyf");
3568       for (j = 0; j < nGlyphs; ++j) {
3569         length = origLocaTable[j+1] - origLocaTable[j];
3570         if (length > 0) {
3571           dumpString(file + glyfPos + origLocaTable[j], length,
3572                      outputFunc, outputStream);
3573         }
3574       }
3575     } else {
3576       // length == 0 means the table is missing and the error was
3577       // already reported during the construction of the table
3578       // headers
3579       if ((length = newTableHdrs[i].length) > 0) {
3580         dumpString(file + seekTable(t42Tables[i].tag), length,
3581                    outputFunc, outputStream);
3582       }
3583     }
3584   }
3585
3586   // end the sfnts array
3587   (*outputFunc)(outputStream, "] def\n", 6);
3588
3589   gfree(origLocaTable);
3590   gfree(locaTable);
3591 }
3592
3593 void TrueTypeFontFile::dumpString(char *s, int length,
3594                                   FontFileOutputFunc outputFunc,
3595                                   void *outputStream) {
3596   char buf[64];
3597   int pad, i, j;
3598
3599   (*outputFunc)(outputStream, "<", 1);
3600   for (i = 0; i < length; i += 32) {
3601     for (j = 0; j < 32 && i+j < length; ++j) {
3602       sprintf(buf, "%02X", s[i+j] & 0xff);
3603       (*outputFunc)(outputStream, buf, strlen(buf));
3604     }
3605     if (i % (65536 - 32) == 65536 - 64) {
3606       (*outputFunc)(outputStream, ">\n<", 3);
3607     } else if (i+32 < length) {
3608       (*outputFunc)(outputStream, "\n", 1);
3609     }
3610   }
3611   if (length & 3) {
3612     pad = 4 - (length & 3);
3613     for (i = 0; i < pad; ++i) {
3614       (*outputFunc)(outputStream, "00", 2);
3615     }
3616   }
3617   // add an extra zero byte because the Adobe Type 42 spec says so
3618   (*outputFunc)(outputStream, "00>\n", 4);
3619 }
3620
3621 Guint TrueTypeFontFile::computeTableChecksum(char *data, int length) {
3622   Guint checksum, word;
3623   int i;
3624
3625   checksum = 0;
3626   for (i = 0; i+3 < length; i += 4) {
3627     word = ((data[i  ] & 0xff) << 24) +
3628            ((data[i+1] & 0xff) << 16) +
3629            ((data[i+2] & 0xff) <<  8) +
3630             (data[i+3] & 0xff);
3631     checksum += word;
3632   }
3633   if (length & 3) {
3634     word = 0;
3635     i = length & ~3;
3636     switch (length & 3) {
3637     case 3:
3638       word |= (data[i+2] & 0xff) <<  8;
3639     case 2:
3640       word |= (data[i+1] & 0xff) << 16;
3641     case 1:
3642       word |= (data[i  ] & 0xff) << 24;
3643       break;
3644     }
3645     checksum += word;
3646   }
3647   return checksum;
3648 }
3649
3650 void TrueTypeFontFile::writeTTF(FILE *out) {
3651   static char cmapTab[20] = {
3652     0, 0,                       // table version number
3653     0, 1,                       // number of encoding tables
3654     0, 1,                       // platform ID
3655     0, 0,                       // encoding ID
3656     0, 0, 0, 12,                // offset of subtable
3657     0, 0,                       // subtable format
3658     0, 1,                       // subtable length
3659     0, 1,                       // subtable version
3660     0,                          // map char 0 -> glyph 0
3661     0                           // pad to multiple of four bytes
3662   };
3663   static char nameTab[8] = {
3664     0, 0,                       // format
3665     0, 0,                       // number of name records
3666     0, 6,                       // offset to start of string storage
3667     0, 0                        // pad to multiple of four bytes
3668   };
3669   static char postTab[32] = {
3670     0, 1, 0, 0,                 // format
3671     0, 0, 0, 0,                 // italic angle
3672     0, 0,                       // underline position
3673     0, 0,                       // underline thickness
3674     0, 0, 0, 0,                 // fixed pitch
3675     0, 0, 0, 0,                 // min Type 42 memory
3676     0, 0, 0, 0,                 // max Type 42 memory
3677     0, 0, 0, 0,                 // min Type 1 memory
3678     0, 0, 0, 0                  // max Type 1 memory
3679   };
3680   GBool haveCmap, haveName, havePost;
3681   GBool dirCmap, dirName, dirPost;
3682   int nNewTables, nAllTables, pad;
3683   char *tableDir;
3684   Guint t, pos;
3685   int i, j;
3686
3687   // check for missing tables
3688   haveCmap = seekTable("cmap") >= 0;
3689   haveName = seekTable("name") >= 0;
3690   havePost = seekTable("post") >= 0;
3691   nNewTables = (haveCmap ? 0 : 1) + (haveName ? 0 : 1) + (havePost ? 0 : 1);
3692   if (!nNewTables && !mungedCmapSize) {
3693     // none are missing - write the TTF file as is
3694     fwrite(file, 1, len, out);
3695     return;
3696   }
3697
3698   // construct the new table directory
3699   nAllTables = nTables + nNewTables;
3700   tableDir = (char *)gmalloc(12 + nAllTables * 16);
3701   memcpy(tableDir, file, 12 + nTables * 16);
3702   tableDir[4] = (char)((nAllTables >> 8) & 0xff);
3703   tableDir[5] = (char)(nAllTables & 0xff);
3704   for (i = -1, t = (Guint)nAllTables; t; ++i, t >>= 1) ;
3705   t = 1 << (4 + i);
3706   tableDir[6] = (char)((t >> 8) & 0xff);
3707   tableDir[7] = (char)(t & 0xff);
3708   tableDir[8] = (char)((i >> 8) & 0xff);
3709   tableDir[9] = (char)(i & 0xff);
3710   t = nAllTables * 16 - t;
3711   tableDir[10] = (char)((t >> 8) & 0xff);
3712   tableDir[11] = (char)(t & 0xff);
3713   dirCmap = haveCmap;
3714   dirName = haveName;
3715   dirPost = havePost;
3716   j = 0;
3717   pad = (len & 3) ? 4 - (len & 3) : 0;
3718   pos = len + pad + 16 * nNewTables;
3719   for (i = 0; i < nTables; ++i) {
3720     if (!dirCmap && strncmp(tableHdrs[i].tag, "cmap", 4) > 0) {
3721       tableDir[12 + 16*j     ] = 'c';
3722       tableDir[12 + 16*j +  1] = 'm';
3723       tableDir[12 + 16*j +  2] = 'a';
3724       tableDir[12 + 16*j +  3] = 'p';
3725       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3726       tableDir[12 + 16*j +  5] = (char)0;
3727       tableDir[12 + 16*j +  6] = (char)0;
3728       tableDir[12 + 16*j +  7] = (char)0;
3729       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3730       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3731       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3732       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3733       tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3734       tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3735       tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
3736       tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
3737       pos += sizeof(cmapTab);
3738       ++j;
3739       dirCmap = gTrue;
3740     }
3741     if (!dirName && strncmp(tableHdrs[i].tag, "name", 4) > 0) {
3742       tableDir[12 + 16*j     ] = 'n';
3743       tableDir[12 + 16*j +  1] = 'a';
3744       tableDir[12 + 16*j +  2] = 'm';
3745       tableDir[12 + 16*j +  3] = 'e';
3746       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3747       tableDir[12 + 16*j +  5] = (char)0;
3748       tableDir[12 + 16*j +  6] = (char)0;
3749       tableDir[12 + 16*j +  7] = (char)0;
3750       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3751       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3752       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3753       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3754       tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3755       tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3756       tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
3757       tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
3758       pos += sizeof(nameTab);
3759       ++j;
3760       dirName = gTrue;
3761     }
3762     if (!dirName && strncmp(tableHdrs[i].tag, "post", 4) > 0) {
3763       tableDir[12 + 16*j     ] = 'p';
3764       tableDir[12 + 16*j +  1] = 'o';
3765       tableDir[12 + 16*j +  2] = 's';
3766       tableDir[12 + 16*j +  3] = 't';
3767       tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3768       tableDir[12 + 16*j +  5] = (char)0;
3769       tableDir[12 + 16*j +  6] = (char)0;
3770       tableDir[12 + 16*j +  7] = (char)0;
3771       tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3772       tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3773       tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3774       tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3775       tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3776       tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3777       tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
3778       tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
3779       pos += sizeof(postTab);
3780       ++j;
3781       dirPost = gTrue;
3782     }
3783     tableDir[12 + 16*j     ] = tableHdrs[i].tag[0];
3784     tableDir[12 + 16*j +  1] = tableHdrs[i].tag[1];
3785     tableDir[12 + 16*j +  2] = tableHdrs[i].tag[2];
3786     tableDir[12 + 16*j +  3] = tableHdrs[i].tag[3];
3787     tableDir[12 + 16*j +  4] = (char)((tableHdrs[i].checksum >> 24) & 0xff);
3788     tableDir[12 + 16*j +  5] = (char)((tableHdrs[i].checksum >> 16) & 0xff);
3789     tableDir[12 + 16*j +  6] = (char)((tableHdrs[i].checksum >>  8) & 0xff);
3790     tableDir[12 + 16*j +  7] = (char)( tableHdrs[i].checksum        & 0xff);
3791     t = tableHdrs[i].offset + nNewTables * 16;
3792     tableDir[12 + 16*j +  8] = (char)((t >> 24) & 0xff);
3793     tableDir[12 + 16*j +  9] = (char)((t >> 16) & 0xff);
3794     tableDir[12 + 16*j + 10] = (char)((t >>  8) & 0xff);
3795     tableDir[12 + 16*j + 11] = (char)( t        & 0xff);
3796     tableDir[12 + 16*j + 12] = (char)((tableHdrs[i].length >> 24) & 0xff);
3797     tableDir[12 + 16*j + 13] = (char)((tableHdrs[i].length >> 16) & 0xff);
3798     tableDir[12 + 16*j + 14] = (char)((tableHdrs[i].length >>  8) & 0xff);
3799     tableDir[12 + 16*j + 15] = (char)( tableHdrs[i].length        & 0xff);
3800     ++j;
3801   }
3802   if (!dirCmap) {
3803     tableDir[12 + 16*j     ] = 'c';
3804     tableDir[12 + 16*j +  1] = 'm';
3805     tableDir[12 + 16*j +  2] = 'a';
3806     tableDir[12 + 16*j +  3] = 'p';
3807     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3808     tableDir[12 + 16*j +  5] = (char)0;
3809     tableDir[12 + 16*j +  6] = (char)0;
3810     tableDir[12 + 16*j +  7] = (char)0;
3811     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3812     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3813     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3814     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3815     tableDir[12 + 16*j + 12] = (char)((sizeof(cmapTab) >> 24) & 0xff);
3816     tableDir[12 + 16*j + 13] = (char)((sizeof(cmapTab) >> 16) & 0xff);
3817     tableDir[12 + 16*j + 14] = (char)((sizeof(cmapTab) >>  8) & 0xff);
3818     tableDir[12 + 16*j + 15] = (char)( sizeof(cmapTab)        & 0xff);
3819     pos += sizeof(cmapTab);
3820     ++j;
3821     dirCmap = gTrue;
3822   }
3823   if (!dirName) {
3824     tableDir[12 + 16*j     ] = 'n';
3825     tableDir[12 + 16*j +  1] = 'a';
3826     tableDir[12 + 16*j +  2] = 'm';
3827     tableDir[12 + 16*j +  3] = 'e';
3828     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3829     tableDir[12 + 16*j +  5] = (char)0;
3830     tableDir[12 + 16*j +  6] = (char)0;
3831     tableDir[12 + 16*j +  7] = (char)0;
3832     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3833     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3834     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3835     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3836     tableDir[12 + 16*j + 12] = (char)((sizeof(nameTab) >> 24) & 0xff);
3837     tableDir[12 + 16*j + 13] = (char)((sizeof(nameTab) >> 16) & 0xff);
3838     tableDir[12 + 16*j + 14] = (char)((sizeof(nameTab) >>  8) & 0xff);
3839     tableDir[12 + 16*j + 15] = (char)( sizeof(nameTab)        & 0xff);
3840     pos += sizeof(nameTab);
3841     ++j;
3842     dirName = gTrue;
3843   }
3844   if (!dirPost) {
3845     tableDir[12 + 16*j     ] = 'p';
3846     tableDir[12 + 16*j +  1] = 'o';
3847     tableDir[12 + 16*j +  2] = 's';
3848     tableDir[12 + 16*j +  3] = 't';
3849     tableDir[12 + 16*j +  4] = (char)0; //~ should compute the checksum
3850     tableDir[12 + 16*j +  5] = (char)0;
3851     tableDir[12 + 16*j +  6] = (char)0;
3852     tableDir[12 + 16*j +  7] = (char)0;
3853     tableDir[12 + 16*j +  8] = (char)((pos >> 24) & 0xff);
3854     tableDir[12 + 16*j +  9] = (char)((pos >> 16) & 0xff);
3855     tableDir[12 + 16*j + 10] = (char)((pos >>  8) & 0xff);
3856     tableDir[12 + 16*j + 11] = (char)( pos        & 0xff);
3857     tableDir[12 + 16*j + 12] = (char)((sizeof(postTab) >> 24) & 0xff);
3858     tableDir[12 + 16*j + 13] = (char)((sizeof(postTab) >> 16) & 0xff);
3859     tableDir[12 + 16*j + 14] = (char)((sizeof(postTab) >>  8) & 0xff);
3860     tableDir[12 + 16*j + 15] = (char)( sizeof(postTab)        & 0xff);
3861     pos += sizeof(postTab);
3862     ++j;
3863     dirPost = gTrue;
3864   }
3865
3866   // write the table directory
3867   fwrite(tableDir, 1, 12 + 16 * nAllTables, out);
3868
3869   // write the original tables
3870   fwrite(file + 12 + 16*nTables, 1, len - (12 + 16*nTables), out);
3871
3872   // write the new tables
3873   for (i = 0; i < pad; ++i) {
3874     fputc((char)0, out);
3875   }
3876   if (!haveCmap) {
3877     fwrite(cmapTab, 1, sizeof(cmapTab), out);
3878   }
3879   if (!haveName) {
3880     fwrite(nameTab, 1, sizeof(nameTab), out);
3881   }
3882   if (!havePost) {
3883     fwrite(postTab, 1, sizeof(postTab), out);
3884   }
3885
3886   gfree(tableDir);
3887 }