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