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