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