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