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