a4cf43cb57e8aa640423b65f85e9161923315326
[swftools.git] / pdf2swf / xpdf / FoFiTrueType.cc
1 //========================================================================
2 //
3 // FoFiTrueType.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 <stdlib.h>
16 #include "gtypes.h"
17 #include "gmem.h"
18 #include "GString.h"
19 #include "GHash.h"
20 #include "FoFiTrueType.h"
21
22 //
23 // Terminology
24 // -----------
25 //
26 // character code = number used as an element of a text string
27 //
28 // character name = glyph name = name for a particular glyph within a
29 //                  font
30 //
31 // glyph index = GID = position (within some internal table in the font)
32 //               where the instructions to draw a particular glyph are
33 //               stored
34 //
35 // Type 1 fonts
36 // ------------
37 //
38 // Type 1 fonts contain:
39 //
40 // Encoding: array of glyph names, maps char codes to glyph names
41 //
42 //           Encoding[charCode] = charName
43 //
44 // CharStrings: dictionary of instructions, keyed by character names,
45 //              maps character name to glyph data
46 //
47 //              CharStrings[charName] = glyphData
48 //
49 // TrueType fonts
50 // --------------
51 //
52 // TrueType fonts contain:
53 //
54 // 'cmap' table: mapping from character code to glyph index; there may
55 //               be multiple cmaps in a TrueType font
56 //
57 //               cmap[charCode] = gid
58 //
59 // 'post' table: mapping from glyph index to glyph name
60 //
61 //               post[gid] = glyphName
62 //
63 // Type 42 fonts
64 // -------------
65 //
66 // Type 42 fonts contain:
67 //
68 // Encoding: array of glyph names, maps char codes to glyph names
69 //
70 //           Encoding[charCode] = charName
71 //
72 // CharStrings: dictionary of glyph indexes, keyed by character names,
73 //              maps character name to glyph index
74 //
75 //              CharStrings[charName] = gid
76 //
77
78 //------------------------------------------------------------------------
79
80 struct TrueTypeTable {
81   Guint tag;
82   Guint checksum;
83   int offset;
84   int origOffset;
85   int len;
86 };
87
88 struct TrueTypeCmap {
89   int platform;
90   int encoding;
91   int offset;
92   int len;
93   int fmt;
94 };
95
96 struct TrueTypeLoca {
97   int idx;
98   int origOffset;
99   int newOffset;
100   int len;
101 };
102
103 #define cmapTag 0x636d6170
104 #define glyfTag 0x676c7966
105 #define locaTag 0x6c6f6361
106 #define nameTag 0x6e616d65
107 #define postTag 0x706f7374
108
109 static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
110   TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
111   TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
112
113   if (loca1->origOffset == loca2->origOffset) {
114     return loca1->idx - loca2->idx;
115   }
116   return loca1->origOffset - loca2->origOffset;
117 }
118
119 static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
120   TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
121   TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
122
123   return loca1->idx - loca2->idx;
124 }
125
126 static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
127   TrueTypeTable *tab1 = (TrueTypeTable *)p1;
128   TrueTypeTable *tab2 = (TrueTypeTable *)p2;
129
130   return (int)tab1->tag - (int)tab2->tag;
131 }
132
133 //------------------------------------------------------------------------
134
135 struct T42Table {
136   char *tag;                    // 4-byte tag
137   GBool required;               // required by the TrueType spec?
138 };
139
140 // TrueType tables to be embedded in Type 42 fonts.
141 // NB: the table names must be in alphabetical order here.
142 #define nT42Tables 11
143 static T42Table t42Tables[nT42Tables] = {
144   { "cvt ", gTrue  },
145   { "fpgm", gTrue  },
146   { "glyf", gTrue  },
147   { "head", gTrue  },
148   { "hhea", gTrue  },
149   { "hmtx", gTrue  },
150   { "loca", gTrue  },
151   { "maxp", gTrue  },
152   { "prep", gTrue  },
153   { "vhea", gFalse },
154   { "vmtx", gFalse }
155 };
156 #define t42HeadTable 3
157 #define t42LocaTable 6
158 #define t42GlyfTable 2
159
160 //------------------------------------------------------------------------
161
162 // Glyph names in some arbitrary standard order that Apple uses for
163 // their TrueType fonts.
164 static char *macGlyphNames[258] = {
165   ".notdef",        "null",           "CR",             "space",
166   "exclam",         "quotedbl",       "numbersign",     "dollar",
167   "percent",        "ampersand",      "quotesingle",    "parenleft",
168   "parenright",     "asterisk",       "plus",           "comma",
169   "hyphen",         "period",         "slash",          "zero",
170   "one",            "two",            "three",          "four",
171   "five",           "six",            "seven",          "eight",
172   "nine",           "colon",          "semicolon",      "less",
173   "equal",          "greater",        "question",       "at",
174   "A",              "B",              "C",              "D",
175   "E",              "F",              "G",              "H",
176   "I",              "J",              "K",              "L",
177   "M",              "N",              "O",              "P",
178   "Q",              "R",              "S",              "T",
179   "U",              "V",              "W",              "X",
180   "Y",              "Z",              "bracketleft",    "backslash",
181   "bracketright",   "asciicircum",    "underscore",     "grave",
182   "a",              "b",              "c",              "d",
183   "e",              "f",              "g",              "h",
184   "i",              "j",              "k",              "l",
185   "m",              "n",              "o",              "p",
186   "q",              "r",              "s",              "t",
187   "u",              "v",              "w",              "x",
188   "y",              "z",              "braceleft",      "bar",
189   "braceright",     "asciitilde",     "Adieresis",      "Aring",
190   "Ccedilla",       "Eacute",         "Ntilde",         "Odieresis",
191   "Udieresis",      "aacute",         "agrave",         "acircumflex",
192   "adieresis",      "atilde",         "aring",          "ccedilla",
193   "eacute",         "egrave",         "ecircumflex",    "edieresis",
194   "iacute",         "igrave",         "icircumflex",    "idieresis",
195   "ntilde",         "oacute",         "ograve",         "ocircumflex",
196   "odieresis",      "otilde",         "uacute",         "ugrave",
197   "ucircumflex",    "udieresis",      "dagger",         "degree",
198   "cent",           "sterling",       "section",        "bullet",
199   "paragraph",      "germandbls",     "registered",     "copyright",
200   "trademark",      "acute",          "dieresis",       "notequal",
201   "AE",             "Oslash",         "infinity",       "plusminus",
202   "lessequal",      "greaterequal",   "yen",            "mu1",
203   "partialdiff",    "summation",      "product",        "pi",
204   "integral",       "ordfeminine",    "ordmasculine",   "Ohm",
205   "ae",             "oslash",         "questiondown",   "exclamdown",
206   "logicalnot",     "radical",        "florin",         "approxequal",
207   "increment",      "guillemotleft",  "guillemotright", "ellipsis",
208   "nbspace",        "Agrave",         "Atilde",         "Otilde",
209   "OE",             "oe",             "endash",         "emdash",
210   "quotedblleft",   "quotedblright",  "quoteleft",      "quoteright",
211   "divide",         "lozenge",        "ydieresis",      "Ydieresis",
212   "fraction",       "currency",       "guilsinglleft",  "guilsinglright",
213   "fi",             "fl",             "daggerdbl",      "periodcentered",
214   "quotesinglbase", "quotedblbase",   "perthousand",    "Acircumflex",
215   "Ecircumflex",    "Aacute",         "Edieresis",      "Egrave",
216   "Iacute",         "Icircumflex",    "Idieresis",      "Igrave",
217   "Oacute",         "Ocircumflex",    "applelogo",      "Ograve",
218   "Uacute",         "Ucircumflex",    "Ugrave",         "dotlessi",
219   "circumflex",     "tilde",          "overscore",      "breve",
220   "dotaccent",      "ring",           "cedilla",        "hungarumlaut",
221   "ogonek",         "caron",          "Lslash",         "lslash",
222   "Scaron",         "scaron",         "Zcaron",         "zcaron",
223   "brokenbar",      "Eth",            "eth",            "Yacute",
224   "yacute",         "Thorn",          "thorn",          "minus",
225   "multiply",       "onesuperior",    "twosuperior",    "threesuperior",
226   "onehalf",        "onequarter",     "threequarters",  "franc",
227   "Gbreve",         "gbreve",         "Idot",           "Scedilla",
228   "scedilla",       "Cacute",         "cacute",         "Ccaron",
229   "ccaron",         "dmacron"
230 };
231
232 //------------------------------------------------------------------------
233 // FoFiTrueType
234 //------------------------------------------------------------------------
235
236 FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA) {
237   FoFiTrueType *ff;
238
239   ff = new FoFiTrueType(fileA, lenA, gFalse);
240   if (!ff->parsedOk) {
241     delete ff;
242     return NULL;
243   }
244   return ff;
245 }
246
247 FoFiTrueType *FoFiTrueType::load(char *fileName) {
248   FoFiTrueType *ff;
249   char *fileA;
250   int lenA;
251
252   if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
253     return NULL;
254   }
255   ff = new FoFiTrueType(fileA, lenA, gTrue);
256   if (!ff->parsedOk) {
257     delete ff;
258     return NULL;
259   }
260   return ff;
261 }
262
263 FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA):
264   FoFiBase(fileA, lenA, freeFileDataA)
265 {
266   tables = NULL;
267   nTables = 0;
268   cmaps = NULL;
269   nCmaps = 0;
270   nameToGID = NULL;
271   parsedOk = gFalse;
272
273   parse();
274 }
275
276 FoFiTrueType::~FoFiTrueType() {
277   gfree(tables);
278   gfree(cmaps);
279   delete nameToGID;
280 }
281
282 int FoFiTrueType::getNumCmaps() {
283   return nCmaps;
284 }
285
286 int FoFiTrueType::getCmapPlatform(int i) {
287   return cmaps[i].platform;
288 }
289
290 int FoFiTrueType::getCmapEncoding(int i) {
291   return cmaps[i].encoding;
292 }
293
294 int FoFiTrueType::findCmap(int platform, int encoding) {
295   int i;
296
297   for (i = 0; i < nCmaps; ++i) {
298     if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
299       return i;
300     }
301   }
302   return -1;
303 }
304
305 Gushort FoFiTrueType::mapCodeToGID(int i, int c) {
306   Gushort gid;
307   int segCnt, segEnd, segStart, segDelta, segOffset;
308   int cmapFirst, cmapLen;
309   int pos, a, b, m;
310   GBool ok;
311
312   if (i < 0 || i >= nCmaps) {
313     return 0;
314   }
315   ok = gTrue;
316   pos = cmaps[i].offset;
317   switch (cmaps[i].fmt) {
318   case 0:
319     if (c < 0 || c >= cmaps[i].len - 6) {
320       return 0;
321     }
322     gid = getU8(cmaps[i].offset + 6 + c, &ok);
323     break;
324   case 4:
325     segCnt = getU16BE(pos + 6, &ok) / 2;
326     a = -1;
327     b = segCnt - 1;
328     segEnd = getU16BE(pos + 14 + 2*b, &ok);
329     if (c > segEnd) {
330       // malformed font -- the TrueType spec requires the last segEnd
331       // to be 0xffff
332       return 0;
333     }
334     // invariant: seg[a].end < code <= seg[b].end
335     while (b - a > 1 && ok) {
336       m = (a + b) / 2;
337       segEnd = getU16BE(pos + 14 + 2*m, &ok);
338       if (segEnd < c) {
339         a = m;
340       } else {
341         b = m;
342       }
343     }
344     segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
345     segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
346     segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
347     if (c < segStart) {
348       return 0;
349     }
350     if (segOffset == 0) {
351       gid = (c + segDelta) & 0xffff;
352     } else {
353       gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
354                        segOffset + 2 * (c - segStart), &ok);
355       if (gid != 0) {
356         gid = (gid + segDelta) & 0xffff;
357       }
358     }
359     break;
360   case 6:
361     cmapFirst = getU16BE(pos + 6, &ok);
362     cmapLen = getU16BE(pos + 8, &ok);
363     if (c < cmapFirst || c >= cmapFirst + cmapLen) {
364       return 0;
365     }
366     gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
367     break;
368   default:
369     return 0;
370   }
371   if (!ok) {
372     return 0;
373   }
374   return gid;
375 }
376
377 int FoFiTrueType::mapNameToGID(char *name) {
378   if (!nameToGID) {
379     return 0;
380   }
381   return nameToGID->lookupInt(name);
382 }
383
384 int FoFiTrueType::getEmbeddingRights() {
385   int i, fsType;
386   GBool ok;
387
388   if ((i = seekTable("OS/2")) < 0) {
389     return 4;
390   }
391   ok = gTrue;
392   fsType = getU16BE(tables[i].offset + 8, &ok);
393   if (!ok) {
394     return 4;
395   }
396   if (fsType & 0x0008) {
397     return 2;
398   }
399   if (fsType & 0x0004) {
400     return 1;
401   }
402   if (fsType & 0x0002) {
403     return 0;
404   }
405   return 3;
406 }
407
408 void FoFiTrueType::convertToType42(char *psName, char **encoding,
409                                    Gushort *codeToGID,
410                                    FoFiOutputFunc outputFunc,
411                                    void *outputStream) {
412   char buf[512];
413   GBool ok;
414
415   // write the header
416   ok = gTrue;
417   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
418   (*outputFunc)(outputStream, buf, strlen(buf));
419
420   // begin the font dictionary
421   (*outputFunc)(outputStream, "10 dict begin\n", 14);
422   (*outputFunc)(outputStream, "/FontName /", 11);
423   (*outputFunc)(outputStream, psName, strlen(psName));
424   (*outputFunc)(outputStream, " def\n", 5);
425   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
426   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
427   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
428           bbox[0], bbox[1], bbox[2], bbox[3]);
429   (*outputFunc)(outputStream, buf, strlen(buf));
430   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
431
432   // write the guts of the dictionary
433   cvtEncoding(encoding, outputFunc, outputStream);
434   cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
435   cvtSfnts(outputFunc, outputStream, NULL);
436
437   // end the dictionary and define the font
438   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
439 }
440
441 void FoFiTrueType::convertToCIDType2(char *psName,
442                                      Gushort *cidMap, int nCIDs,
443                                      FoFiOutputFunc outputFunc,
444                                      void *outputStream) {
445   char buf[512];
446   Gushort cid;
447   GBool ok;
448   int i, j, k;
449
450   // write the header
451   ok = gTrue;
452   sprintf(buf, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok) / 65536.0);
453   (*outputFunc)(outputStream, buf, strlen(buf));
454
455   // begin the font dictionary
456   (*outputFunc)(outputStream, "20 dict begin\n", 14);
457   (*outputFunc)(outputStream, "/CIDFontName /", 14);
458   (*outputFunc)(outputStream, psName, strlen(psName));
459   (*outputFunc)(outputStream, " def\n", 5);
460   (*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
461   (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
462   (*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
463   (*outputFunc)(outputStream, "  /Registry (Adobe) def\n", 24);
464   (*outputFunc)(outputStream, "  /Ordering (Identity) def\n", 27);
465   (*outputFunc)(outputStream, "  /Supplement 0 def\n", 20);
466   (*outputFunc)(outputStream, "  end def\n", 10);
467   (*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
468   if (cidMap) {
469     sprintf(buf, "/CIDCount %d def\n", nCIDs);
470     (*outputFunc)(outputStream, buf, strlen(buf));
471     if (nCIDs > 32767) {
472       (*outputFunc)(outputStream, "/CIDMap [", 9);
473       for (i = 0; i < nCIDs; i += 32768 - 16) {
474         (*outputFunc)(outputStream, "<\n", 2);
475         for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
476           (*outputFunc)(outputStream, "  ", 2);
477           for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
478             cid = cidMap[i+j+k];
479             sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
480             (*outputFunc)(outputStream, buf, strlen(buf));
481           }
482           (*outputFunc)(outputStream, "\n", 1);
483         }
484         (*outputFunc)(outputStream, "  >", 3);
485       }
486       (*outputFunc)(outputStream, "\n", 1);
487       (*outputFunc)(outputStream, "] def\n", 6);
488     } else {
489       (*outputFunc)(outputStream, "/CIDMap <\n", 10);
490       for (i = 0; i < nCIDs; i += 16) {
491         (*outputFunc)(outputStream, "  ", 2);
492         for (j = 0; j < 16 && i+j < nCIDs; ++j) {
493           cid = cidMap[i+j];
494           sprintf(buf, "%02x%02x", (cid >> 8) & 0xff, cid & 0xff);
495           (*outputFunc)(outputStream, buf, strlen(buf));
496         }
497         (*outputFunc)(outputStream, "\n", 1);
498       }
499       (*outputFunc)(outputStream, "> def\n", 6);
500     }
501   } else {
502     // direct mapping - just fill the string(s) with s[i]=i
503     sprintf(buf, "/CIDCount %d def\n", nGlyphs);
504     (*outputFunc)(outputStream, buf, strlen(buf));
505     if (nGlyphs > 32767) {
506       (*outputFunc)(outputStream, "/CIDMap [\n", 10);
507       for (i = 0; i < nGlyphs; i += 32767) {
508         j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
509         sprintf(buf, "  %d string 0 1 %d {\n", 2 * j, j - 1);
510         (*outputFunc)(outputStream, buf, strlen(buf));
511         sprintf(buf, "    2 copy dup 2 mul exch %d add -8 bitshift put\n", i);
512         (*outputFunc)(outputStream, buf, strlen(buf));
513         sprintf(buf, "    1 index exch dup 2 mul 1 add exch %d add"
514                 " 255 and put\n", i);
515         (*outputFunc)(outputStream, buf, strlen(buf));
516         (*outputFunc)(outputStream, "  } for\n", 8);
517       }
518       (*outputFunc)(outputStream, "] def\n", 6);
519     } else {
520       sprintf(buf, "/CIDMap %d string\n", 2 * nGlyphs);
521       (*outputFunc)(outputStream, buf, strlen(buf));
522       sprintf(buf, "  0 1 %d {\n", nGlyphs - 1);
523       (*outputFunc)(outputStream, buf, strlen(buf));
524       (*outputFunc)(outputStream,
525                     "    2 copy dup 2 mul exch -8 bitshift put\n", 42);
526       (*outputFunc)(outputStream,
527                     "    1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
528       (*outputFunc)(outputStream, "  } for\n", 8);
529       (*outputFunc)(outputStream, "def\n", 4);
530     }
531   }
532   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
533   sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
534           bbox[0], bbox[1], bbox[2], bbox[3]);
535   (*outputFunc)(outputStream, buf, strlen(buf));
536   (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
537   (*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
538   (*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
539   (*outputFunc)(outputStream, "  /.notdef 0 def\n", 17);
540   (*outputFunc)(outputStream, "  end readonly def\n", 19);
541
542   // write the guts of the dictionary
543   cvtSfnts(outputFunc, outputStream, NULL);
544
545   // end the dictionary and define the font
546   (*outputFunc)(outputStream,
547                 "CIDFontName currentdict end /CIDFont defineresource pop\n",
548                 56);
549 }
550
551 void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
552                                   FoFiOutputFunc outputFunc,
553                                   void *outputStream) {
554   char buf[512];
555   GString *sfntsName;
556   int n, i, j;
557
558   // write the Type 42 sfnts array
559   sfntsName = (new GString(psName))->append("_sfnts");
560   cvtSfnts(outputFunc, outputStream, sfntsName);
561   delete sfntsName;
562
563   // write the descendant Type 42 fonts
564   n = cidMap ? nCIDs : nGlyphs;
565   for (i = 0; i < n; i += 256) {
566     (*outputFunc)(outputStream, "10 dict begin\n", 14);
567     (*outputFunc)(outputStream, "/FontName /", 11);
568     (*outputFunc)(outputStream, psName, strlen(psName));
569     sprintf(buf, "_%02x def\n", i >> 8);
570     (*outputFunc)(outputStream, buf, strlen(buf));
571     (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
572     (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
573     sprintf(buf, "/FontBBox [%d %d %d %d] def\n",
574             bbox[0], bbox[1], bbox[2], bbox[3]);
575     (*outputFunc)(outputStream, buf, strlen(buf));
576     (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
577     (*outputFunc)(outputStream, "/sfnts ", 7);
578     (*outputFunc)(outputStream, psName, strlen(psName));
579     (*outputFunc)(outputStream, "_sfnts def\n", 11);
580     (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
581     for (j = 0; j < 256 && i+j < n; ++j) {
582       sprintf(buf, "dup %d /c%02x put\n", j, j);
583       (*outputFunc)(outputStream, buf, strlen(buf));
584     }
585     (*outputFunc)(outputStream, "readonly def\n", 13);
586     (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
587     (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
588     for (j = 0; j < 256 && i+j < n; ++j) {
589       sprintf(buf, "/c%02x %d def\n", j, cidMap ? cidMap[i+j] : i+j);
590       (*outputFunc)(outputStream, buf, strlen(buf));
591     }
592     (*outputFunc)(outputStream, "end readonly def\n", 17);
593     (*outputFunc)(outputStream,
594                   "FontName currentdict end definefont pop\n", 40);
595   }
596
597   // write the Type 0 parent font
598   (*outputFunc)(outputStream, "16 dict begin\n", 14);
599   (*outputFunc)(outputStream, "/FontName /", 11);
600   (*outputFunc)(outputStream, psName, strlen(psName));
601   (*outputFunc)(outputStream, " def\n", 5);
602   (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
603   (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
604   (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
605   (*outputFunc)(outputStream, "/Encoding [\n", 12);
606   for (i = 0; i < n; i += 256) {
607     sprintf(buf, "%d\n", i >> 8);
608     (*outputFunc)(outputStream, buf, strlen(buf));
609   }
610   (*outputFunc)(outputStream, "] def\n", 6);
611   (*outputFunc)(outputStream, "/FDepVector [\n", 14);
612   for (i = 0; i < n; i += 256) {
613     (*outputFunc)(outputStream, "/", 1);
614     (*outputFunc)(outputStream, psName, strlen(psName));
615     sprintf(buf, "_%02x findfont\n", i >> 8);
616     (*outputFunc)(outputStream, buf, strlen(buf));
617   }
618   (*outputFunc)(outputStream, "] def\n", 6);
619   (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
620 }
621
622 void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
623                             void *outputStream) {
624   static char cmapTab[20] = {
625     0, 0,                       // table version number
626     0, 1,                       // number of encoding tables
627     0, 1,                       // platform ID
628     0, 0,                       // encoding ID
629     0, 0, 0, 12,                // offset of subtable
630     0, 0,                       // subtable format
631     0, 1,                       // subtable length
632     0, 1,                       // subtable version
633     0,                          // map char 0 -> glyph 0
634     0                           // pad to multiple of four bytes
635   };
636   static char nameTab[8] = {
637     0, 0,                       // format
638     0, 0,                       // number of name records
639     0, 6,                       // offset to start of string storage
640     0, 0                        // pad to multiple of four bytes
641   };
642   static char postTab[32] = {
643     0, 1, 0, 0,                 // format
644     0, 0, 0, 0,                 // italic angle
645     0, 0,                       // underline position
646     0, 0,                       // underline thickness
647     0, 0, 0, 0,                 // fixed pitch
648     0, 0, 0, 0,                 // min Type 42 memory
649     0, 0, 0, 0,                 // max Type 42 memory
650     0, 0, 0, 0,                 // min Type 1 memory
651     0, 0, 0, 0                  // max Type 1 memory
652   };
653   GBool missingCmap, missingName, missingPost, unsortedLoca, badCmapLen;
654   int nZeroLengthTables;
655   TrueTypeLoca *locaTable;
656   TrueTypeTable *newTables;
657   int nNewTables, cmapIdx, cmapLen, glyfLen;
658   char *tableDir;
659   char locaBuf[4];
660   GBool ok;
661   Guint t;
662   int pos, i, j, k, n;
663
664   // check for missing tables
665   missingCmap = (cmapIdx = seekTable("cmap")) < 0;
666   missingName = seekTable("name") < 0;
667   missingPost = seekTable("post") < 0;
668
669   // read the loca table, check to see if it's sorted
670   locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
671   unsortedLoca = gFalse;
672   i = seekTable("loca");
673   pos = tables[i].offset;
674   ok = gTrue;
675   for (i = 0; i <= nGlyphs; ++i) {
676     if (locaFmt) {
677       locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
678     } else {
679       locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
680     }
681     if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
682       unsortedLoca = gTrue;
683     }
684     locaTable[i].idx = i;
685   }
686
687   // check for zero-length tables
688   nZeroLengthTables = 0;
689   for (i = 0; i < nTables; ++i) {
690     if (tables[i].len == 0) {
691       ++nZeroLengthTables;
692     }
693   }
694
695   // check for an incorrect cmap table length
696   badCmapLen = gFalse;
697   cmapLen = 0; // make gcc happy
698   if (!missingCmap) {
699     cmapLen = cmaps[0].offset + cmaps[0].len;
700     for (i = 1; i < nCmaps; ++i) {
701       if (cmaps[i].offset + cmaps[i].len > cmapLen) {
702         cmapLen = cmaps[i].offset + cmaps[i].len;
703       }
704     }
705     cmapLen -= tables[cmapIdx].offset;
706     if (cmapLen > tables[cmapIdx].len) {
707       badCmapLen = gTrue;
708     }
709   }
710
711   // if nothing is broken, just write the TTF file as is
712   if (!missingCmap && !missingName && !missingPost && !unsortedLoca &&
713       !badCmapLen && nZeroLengthTables == 0) {
714     (*outputFunc)(outputStream, (char *)file, len);
715     goto done1;
716   }
717
718   // sort the 'loca' table: some (non-compliant) fonts have
719   // out-of-order loca tables; in order to correctly handle the case
720   // where (compliant) fonts have empty entries in the middle of the
721   // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
722   // and idx as its secondary key (ensuring that adjacent entries with
723   // the same pos value remain in the same order)
724   glyfLen = 0; // make gcc happy
725   if (unsortedLoca) {
726     qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
727           &cmpTrueTypeLocaOffset);
728     for (i = 0; i < nGlyphs; ++i) {
729       locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
730     }
731     locaTable[nGlyphs].len = 0;
732     qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
733           &cmpTrueTypeLocaIdx);
734     pos = 0;
735     for (i = 0; i <= nGlyphs; ++i) {
736       locaTable[i].newOffset = pos;
737       pos += locaTable[i].len;
738       if (pos & 3) {
739         pos += 4 - (pos & 3);
740       }
741     }
742     glyfLen = pos;
743   }
744
745   // construct the new table directory:
746   // - keep all original tables with non-zero length
747   // - fix the cmap table's length, if necessary
748   // - add missing tables
749   // - sort the table by tag
750   // - compute new table positions, including 4-byte alignment
751   nNewTables = nTables - nZeroLengthTables +
752                (missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
753                (missingPost ? 1 : 0);
754   newTables = (TrueTypeTable *)gmalloc(nNewTables * sizeof(TrueTypeTable));
755   j = 0;
756   for (i = 0; i < nTables; ++i) {
757     if (tables[i].len > 0) {
758       newTables[j] = tables[i];
759       newTables[j].origOffset = tables[i].offset;
760       if (newTables[j].tag == cmapTag && badCmapLen) {
761         newTables[j].len = cmapLen;
762       } else if (newTables[j].tag == locaTag && unsortedLoca) {
763         newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
764       } else if (newTables[j].tag == glyfTag && unsortedLoca) {
765         newTables[j].len = glyfLen;
766       }
767       ++j;
768     }
769   }
770   if (missingCmap) {
771     newTables[j].tag = cmapTag;
772     newTables[j].checksum = 0; //~ should compute the checksum
773     newTables[j].len = sizeof(cmapTab);
774     ++j;
775   }
776   if (missingName) {
777     newTables[j].tag = nameTag;
778     newTables[j].checksum = 0; //~ should compute the checksum
779     newTables[j].len = sizeof(nameTab);
780     ++j;
781   }
782   if (missingPost) {
783     newTables[j].tag = postTag;
784     newTables[j].checksum = 0; //~ should compute the checksum
785     newTables[j].len = sizeof(postTab);
786     ++j;
787   }
788   qsort(newTables, nNewTables, sizeof(TrueTypeTable),
789         &cmpTrueTypeTableTag);
790   pos = 12 + nNewTables * 16;
791   for (i = 0; i < nNewTables; ++i) {
792     newTables[i].offset = pos;
793     pos += newTables[i].len;
794     if (pos & 3) {
795       pos += 4 - (pos & 3);
796     }
797   }
798
799   // write the table directory
800   tableDir = (char *)gmalloc(12 + nNewTables * 16);
801   tableDir[0] = 0x00;                                   // sfnt version
802   tableDir[1] = 0x01;
803   tableDir[2] = 0x00;
804   tableDir[3] = 0x00;
805   tableDir[4] = (char)((nNewTables >> 8) & 0xff);       // numTables
806   tableDir[5] = (char)(nNewTables & 0xff);
807   for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
808   t = 1 << (4 + i);
809   tableDir[6] = (char)((t >> 8) & 0xff);                // searchRange
810   tableDir[7] = (char)(t & 0xff);
811   tableDir[8] = (char)((i >> 8) & 0xff);                // entrySelector
812   tableDir[9] = (char)(i & 0xff);
813   t = nNewTables * 16 - t;
814   tableDir[10] = (char)((t >> 8) & 0xff);               // rangeShift
815   tableDir[11] = (char)(t & 0xff);
816   pos = 12;
817   for (i = 0; i < nNewTables; ++i) {
818     tableDir[pos   ] = (char)(newTables[i].tag >> 24);
819     tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
820     tableDir[pos+ 2] = (char)(newTables[i].tag >>  8);
821     tableDir[pos+ 3] = (char) newTables[i].tag;
822     tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
823     tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
824     tableDir[pos+ 6] = (char)(newTables[i].checksum >>  8);
825     tableDir[pos+ 7] = (char) newTables[i].checksum;
826     tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
827     tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
828     tableDir[pos+10] = (char)(newTables[i].offset >>  8);
829     tableDir[pos+11] = (char) newTables[i].offset;
830     tableDir[pos+12] = (char)(newTables[i].len >> 24);
831     tableDir[pos+13] = (char)(newTables[i].len >> 16);
832     tableDir[pos+14] = (char)(newTables[i].len >>  8);
833     tableDir[pos+15] = (char) newTables[i].len;
834     pos += 16;
835   }
836   (*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
837
838   // write the tables
839   for (i = 0; i < nNewTables; ++i) {
840     if (newTables[i].tag == cmapTag && missingCmap) {
841       (*outputFunc)(outputStream, cmapTab, newTables[i].len);
842     } else if (newTables[i].tag == nameTag && missingName) {
843       (*outputFunc)(outputStream, nameTab, newTables[i].len);
844     } else if (newTables[i].tag == postTag && missingPost) {
845       (*outputFunc)(outputStream, postTab, newTables[i].len);
846     } else if (newTables[i].tag == locaTag && unsortedLoca) {
847       for (j = 0; j <= nGlyphs; ++j) {
848         if (locaFmt) {
849           locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
850           locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
851           locaBuf[2] = (char)(locaTable[j].newOffset >>  8);
852           locaBuf[3] = (char) locaTable[j].newOffset;
853           (*outputFunc)(outputStream, locaBuf, 4);
854         } else {
855           locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
856           locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
857           (*outputFunc)(outputStream, locaBuf, 2);
858         }
859       }
860     } else if (newTables[i].tag == glyfTag && unsortedLoca) {
861       pos = tables[seekTable("glyf")].offset;
862       for (j = 0; j < nGlyphs; ++j) {
863         n = locaTable[j].len;
864         if (n > 0) {
865           k = locaTable[j].origOffset;
866           if (checkRegion(pos + k, n)) {
867             (*outputFunc)(outputStream, (char *)file + pos + k, n);
868           } else {
869             for (k = 0; k < n; ++k) {
870               (*outputFunc)(outputStream, "\0", 1);
871             }
872           }
873           if ((k = locaTable[j].len & 3)) {
874             (*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
875           }
876         }
877       }
878     } else {
879       if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
880         (*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
881                       newTables[i].len);
882       } else {
883         for (j = 0; j < newTables[i].len; ++j) {
884           (*outputFunc)(outputStream, "\0", 1);
885         }
886       }
887     }
888     if (newTables[i].len & 3) {
889       (*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
890     }
891   }
892
893   gfree(tableDir);
894   gfree(newTables);
895  done1:
896   gfree(locaTable);
897 }
898
899 void FoFiTrueType::cvtEncoding(char **encoding,
900                                FoFiOutputFunc outputFunc,
901                                void *outputStream) {
902   char *name;
903   char buf[64];
904   int i;
905
906   (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
907   if (encoding) {
908     for (i = 0; i < 256; ++i) {
909       if (!(name = encoding[i])) {
910         name = ".notdef";
911       }
912       sprintf(buf, "dup %d /", i);
913       (*outputFunc)(outputStream, buf, strlen(buf));
914       (*outputFunc)(outputStream, name, strlen(name));
915       (*outputFunc)(outputStream, " put\n", 5);
916     }
917   } else {
918     for (i = 0; i < 256; ++i) {
919       sprintf(buf, "dup %d /c%02x put\n", i, i);
920       (*outputFunc)(outputStream, buf, strlen(buf));
921     }
922   }
923   (*outputFunc)(outputStream, "readonly def\n", 13);
924 }
925
926 void FoFiTrueType::cvtCharStrings(char **encoding,
927                                   Gushort *codeToGID,
928                                   FoFiOutputFunc outputFunc,
929                                   void *outputStream) {
930   char *name;
931   char buf[64], buf2[16];
932   int i, k;
933
934   // always define '.notdef'
935   (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
936   (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
937
938   // if there's no 'cmap' table, punt
939   if (nCmaps == 0) {
940     goto err;
941   }
942
943   // map char name to glyph index:
944   // 1. use encoding to map name to char code
945   // 2. use codeToGID to map char code to glyph index
946   // N.B. We do this in reverse order because font subsets can have
947   //      weird encodings that use the same character name twice, and
948   //      the first definition is probably the one we want.
949   k = 0; // make gcc happy
950   for (i = 255; i >= 0; --i) {
951     if (encoding) {
952       name = encoding[i];
953     } else {
954       sprintf(buf2, "c%02x", i);
955       name = buf2;
956     }
957     if (name && strcmp(name, ".notdef")) {
958       k = codeToGID[i];
959       // note: Distiller (maybe Adobe's PS interpreter in general)
960       // doesn't like TrueType fonts that have CharStrings entries
961       // which point to nonexistent glyphs, hence the (k < nGlyphs)
962       // test
963       if (k > 0 && k < nGlyphs) {
964         (*outputFunc)(outputStream, "/", 1);
965         (*outputFunc)(outputStream, name, strlen(name));
966         sprintf(buf, " %d def\n", k);
967         (*outputFunc)(outputStream, buf, strlen(buf));
968       }
969     }
970   }
971
972  err:
973   (*outputFunc)(outputStream, "end readonly def\n", 17);
974 }
975
976 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
977                             void *outputStream, GString *name) {
978   Guchar headData[54];
979   TrueTypeLoca *locaTable;
980   Guchar *locaData;
981   TrueTypeTable newTables[nT42Tables];
982   Guchar tableDir[12 + nT42Tables*16];
983   GBool ok;
984   Guint checksum;
985   int nNewTables;
986   int length, pos, glyfPos, i, j, k;
987
988   // construct the 'head' table, zero out the font checksum
989   i = seekTable("head");
990   pos = tables[i].offset;
991   if (!checkRegion(pos, 54)) {
992     return;
993   }
994   memcpy(headData, file + pos, 54);
995   headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
996
997   // read the original 'loca' table, pad entries out to 4 bytes, and
998   // sort it into proper order -- some (non-compliant) fonts have
999   // out-of-order loca tables; in order to correctly handle the case
1000   // where (compliant) fonts have empty entries in the middle of the
1001   // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
1002   // and idx as its secondary key (ensuring that adjacent entries with
1003   // the same pos value remain in the same order)
1004   locaTable = (TrueTypeLoca *)gmalloc((nGlyphs + 1) * sizeof(TrueTypeLoca));
1005   i = seekTable("loca");
1006   pos = tables[i].offset;
1007   ok = gTrue;
1008   for (i = 0; i <= nGlyphs; ++i) {
1009     locaTable[i].idx = i;
1010     if (locaFmt) {
1011       locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
1012     } else {
1013       locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
1014     }
1015   }
1016   qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1017         &cmpTrueTypeLocaOffset);
1018   for (i = 0; i < nGlyphs; ++i) {
1019     locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
1020   }
1021   locaTable[nGlyphs].len = 0;
1022   qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1023         &cmpTrueTypeLocaIdx);
1024   pos = 0;
1025   for (i = 0; i <= nGlyphs; ++i) {
1026     locaTable[i].newOffset = pos;
1027     pos += locaTable[i].len;
1028     if (pos & 3) {
1029       pos += 4 - (pos & 3);
1030     }
1031   }
1032
1033   // construct the new 'loca' table
1034   locaData = (Guchar *)gmalloc((nGlyphs + 1) * (locaFmt ? 4 : 2));
1035   for (i = 0; i <= nGlyphs; ++i) {
1036     pos = locaTable[i].newOffset;
1037     if (locaFmt) {
1038       locaData[4*i  ] = (Guchar)(pos >> 24);
1039       locaData[4*i+1] = (Guchar)(pos >> 16);
1040       locaData[4*i+2] = (Guchar)(pos >>  8);
1041       locaData[4*i+3] = (Guchar) pos;
1042     } else {
1043       locaData[2*i  ] = (Guchar)(pos >> 9);
1044       locaData[2*i+1] = (Guchar)(pos >> 1);
1045     }
1046   }
1047
1048   // count the number of tables
1049   nNewTables = 0;
1050   for (i = 0; i < nT42Tables; ++i) {
1051     if (t42Tables[i].required ||
1052         seekTable(t42Tables[i].tag) >= 0) {
1053       ++nNewTables;
1054     }
1055   }
1056
1057   // construct the new table headers, including table checksums
1058   // (pad each table out to a multiple of 4 bytes)
1059   pos = 12 + nNewTables*16;
1060   k = 0;
1061   for (i = 0; i < nT42Tables; ++i) {
1062     length = -1;
1063     checksum = 0; // make gcc happy
1064     if (i == t42HeadTable) {
1065       length = 54;
1066       checksum = computeTableChecksum(headData, 54);
1067     } else if (i == t42LocaTable) {
1068       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1069       checksum = computeTableChecksum(locaData, length);
1070     } else if (i == t42GlyfTable) {
1071       length = 0;
1072       checksum = 0;
1073       glyfPos = tables[seekTable("glyf")].offset;
1074       for (j = 0; j < nGlyphs; ++j) {
1075         length += locaTable[j].len;
1076         if (length & 3) {
1077           length += 4 - (length & 3);
1078         }
1079         if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1080           checksum +=
1081               computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
1082                                    locaTable[j].len);
1083         }
1084       }
1085     } else {
1086       if ((j = seekTable(t42Tables[i].tag)) >= 0) {
1087         length = tables[j].len;
1088         if (checkRegion(tables[j].offset, length)) {
1089           checksum = computeTableChecksum(file + tables[j].offset, length);
1090         }
1091       } else if (t42Tables[i].required) {
1092         //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1093         //~       t42Tables[i].tag);
1094         length = 0;
1095         checksum = 0;
1096       }
1097     }
1098     if (length >= 0) {
1099       newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
1100                          ((t42Tables[i].tag[1] & 0xff) << 16) |
1101                          ((t42Tables[i].tag[2] & 0xff) <<  8) |
1102                           (t42Tables[i].tag[3] & 0xff);
1103       newTables[k].checksum = checksum;
1104       newTables[k].offset = pos;
1105       newTables[k].len = length;
1106       pos += length;
1107       if (pos & 3) {
1108         pos += 4 - (length & 3);
1109       }
1110       ++k;
1111     }
1112   }
1113
1114   // construct the table directory
1115   tableDir[0] = 0x00;           // sfnt version
1116   tableDir[1] = 0x01;
1117   tableDir[2] = 0x00;
1118   tableDir[3] = 0x00;
1119   tableDir[4] = 0;              // numTables
1120   tableDir[5] = nNewTables;
1121   tableDir[6] = 0;              // searchRange
1122   tableDir[7] = (Guchar)128;
1123   tableDir[8] = 0;              // entrySelector
1124   tableDir[9] = 3;
1125   tableDir[10] = 0;             // rangeShift
1126   tableDir[11] = (Guchar)(16 * nNewTables - 128);
1127   pos = 12;
1128   for (i = 0; i < nNewTables; ++i) {
1129     tableDir[pos   ] = (Guchar)(newTables[i].tag >> 24);
1130     tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
1131     tableDir[pos+ 2] = (Guchar)(newTables[i].tag >>  8);
1132     tableDir[pos+ 3] = (Guchar) newTables[i].tag;
1133     tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
1134     tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
1135     tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >>  8);
1136     tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
1137     tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
1138     tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
1139     tableDir[pos+10] = (Guchar)(newTables[i].offset >>  8);
1140     tableDir[pos+11] = (Guchar) newTables[i].offset;
1141     tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
1142     tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
1143     tableDir[pos+14] = (Guchar)(newTables[i].len >>  8);
1144     tableDir[pos+15] = (Guchar) newTables[i].len;
1145     pos += 16;
1146   }
1147
1148   // compute the font checksum and store it in the head table
1149   checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
1150   for (i = 0; i < nNewTables; ++i) {
1151     checksum += newTables[i].checksum;
1152   }
1153   checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
1154   headData[ 8] = (Guchar)(checksum >> 24);
1155   headData[ 9] = (Guchar)(checksum >> 16);
1156   headData[10] = (Guchar)(checksum >>  8);
1157   headData[11] = (Guchar) checksum;
1158
1159   // start the sfnts array
1160   if (name) {
1161     (*outputFunc)(outputStream, "/", 1);
1162     (*outputFunc)(outputStream, name->getCString(), name->getLength());
1163     (*outputFunc)(outputStream, " [\n", 3);
1164   } else {
1165     (*outputFunc)(outputStream, "/sfnts [\n", 9);
1166   }
1167
1168   // write the table directory
1169   dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
1170
1171   // write the tables
1172   for (i = 0; i < nNewTables; ++i) {
1173     if (i == t42HeadTable) {
1174       dumpString(headData, 54, outputFunc, outputStream);
1175     } else if (i == t42LocaTable) {
1176       length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1177       dumpString(locaData, length, outputFunc, outputStream);
1178     } else if (i == t42GlyfTable) {
1179       glyfPos = tables[seekTable("glyf")].offset;
1180       for (j = 0; j < nGlyphs; ++j) {
1181         if (locaTable[j].len > 0 &&
1182             checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1183           dumpString(file + glyfPos + locaTable[j].origOffset,
1184                      locaTable[j].len, outputFunc, outputStream);
1185         }
1186       }
1187     } else {
1188       // length == 0 means the table is missing and the error was
1189       // already reported during the construction of the table
1190       // headers
1191       if ((length = newTables[i].len) > 0) {
1192         if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
1193             checkRegion(tables[j].offset, tables[j].len)) {
1194           dumpString(file + tables[j].offset, tables[j].len,
1195                      outputFunc, outputStream);
1196         }
1197       }
1198     }
1199   }
1200
1201   // end the sfnts array
1202   (*outputFunc)(outputStream, "] def\n", 6);
1203
1204   gfree(locaData);
1205   gfree(locaTable);
1206 }
1207
1208 void FoFiTrueType::dumpString(Guchar *s, int length,
1209                               FoFiOutputFunc outputFunc,
1210                               void *outputStream) {
1211   char buf[64];
1212   int pad, i, j;
1213
1214   (*outputFunc)(outputStream, "<", 1);
1215   for (i = 0; i < length; i += 32) {
1216     for (j = 0; j < 32 && i+j < length; ++j) {
1217       sprintf(buf, "%02X", s[i+j] & 0xff);
1218       (*outputFunc)(outputStream, buf, strlen(buf));
1219     }
1220     if (i % (65536 - 32) == 65536 - 64) {
1221       (*outputFunc)(outputStream, ">\n<", 3);
1222     } else if (i+32 < length) {
1223       (*outputFunc)(outputStream, "\n", 1);
1224     }
1225   }
1226   if (length & 3) {
1227     pad = 4 - (length & 3);
1228     for (i = 0; i < pad; ++i) {
1229       (*outputFunc)(outputStream, "00", 2);
1230     }
1231   }
1232   // add an extra zero byte because the Adobe Type 42 spec says so
1233   (*outputFunc)(outputStream, "00>\n", 4);
1234 }
1235
1236 Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
1237   Guint checksum, word;
1238   int i;
1239
1240   checksum = 0;
1241   for (i = 0; i+3 < length; i += 4) {
1242     word = ((data[i  ] & 0xff) << 24) +
1243            ((data[i+1] & 0xff) << 16) +
1244            ((data[i+2] & 0xff) <<  8) +
1245             (data[i+3] & 0xff);
1246     checksum += word;
1247   }
1248   if (length & 3) {
1249     word = 0;
1250     i = length & ~3;
1251     switch (length & 3) {
1252     case 3:
1253       word |= (data[i+2] & 0xff) <<  8;
1254     case 2:
1255       word |= (data[i+1] & 0xff) << 16;
1256     case 1:
1257       word |= (data[i  ] & 0xff) << 24;
1258       break;
1259     }
1260     checksum += word;
1261   }
1262   return checksum;
1263 }
1264
1265 void FoFiTrueType::parse() {
1266   int pos, i, j;
1267
1268   parsedOk = gTrue;
1269
1270   // read the table directory
1271   nTables = getU16BE(4, &parsedOk);
1272   if (!parsedOk) {
1273     return;
1274   }
1275   tables = (TrueTypeTable *)gmalloc(nTables * sizeof(TrueTypeTable));
1276   pos = 12;
1277   for (i = 0; i < nTables; ++i) {
1278     tables[i].tag = getU32BE(pos, &parsedOk);
1279     tables[i].checksum = getU32BE(pos + 4, &parsedOk);
1280     tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
1281     tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
1282     if (tables[i].offset + tables[i].len < tables[i].offset ||
1283         tables[i].offset + tables[i].len > len) {
1284       parsedOk = gFalse;
1285     }
1286     pos += 16;
1287   }
1288   if (!parsedOk) {
1289     return;
1290   }
1291
1292   // check for tables that are required by both the TrueType spec and
1293   // the Type 42 spec
1294   if (seekTable("head") < 0 ||
1295       seekTable("hhea") < 0 ||
1296       seekTable("loca") < 0 ||
1297       seekTable("maxp") < 0 ||
1298       seekTable("glyf") < 0 ||
1299       seekTable("hmtx") < 0) {
1300     parsedOk = gFalse;
1301     return;
1302   }
1303
1304   // read the cmaps
1305   if ((i = seekTable("cmap")) >= 0) {
1306     pos = tables[i].offset + 2;
1307     nCmaps = getU16BE(pos, &parsedOk);
1308     pos += 2;
1309     if (!parsedOk) {
1310       return;
1311     }
1312     cmaps = (TrueTypeCmap *)gmalloc(nCmaps * sizeof(TrueTypeCmap));
1313     for (j = 0; j < nCmaps; ++j) {
1314       cmaps[j].platform = getU16BE(pos, &parsedOk);
1315       cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
1316       cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
1317       pos += 8;
1318       cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
1319       cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
1320     }
1321     if (!parsedOk) {
1322       return;
1323     }
1324   } else {
1325     nCmaps = 0;
1326   }
1327
1328   // get the number of glyphs from the maxp table
1329   i = seekTable("maxp");
1330   nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
1331   if (!parsedOk) {
1332     return;
1333   }
1334
1335   // get the bbox and loca table format from the head table
1336   i = seekTable("head");
1337   bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
1338   bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
1339   bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
1340   bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
1341   locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
1342   if (!parsedOk) {
1343     return;
1344   }
1345
1346   // read the post table
1347   readPostTable();
1348   if (!parsedOk) {
1349     return;
1350   }
1351 }
1352
1353 void FoFiTrueType::readPostTable() {
1354   GString *name;
1355   int tablePos, postFmt, stringIdx, stringPos;
1356   int i, j, n, m;
1357
1358   if ((i = seekTable("post")) < 0) {
1359     return;
1360   }
1361   tablePos = tables[i].offset;
1362   postFmt = getU32BE(tablePos, &parsedOk);
1363   if (!parsedOk) {
1364     return;
1365   }
1366   if (postFmt == 0x00010000) {
1367     nameToGID = new GHash(gTrue);
1368     for (i = 0; i < 258; ++i) {
1369       nameToGID->add(new GString(macGlyphNames[i]), i);
1370     }
1371   } else if (postFmt == 0x00020000) {
1372     nameToGID = new GHash(gTrue);
1373     n = getU16BE(tablePos + 32, &parsedOk);
1374     if (!parsedOk) {
1375       return;
1376     }
1377     if (n > nGlyphs) {
1378       n = nGlyphs;
1379     }
1380     stringIdx = 0;
1381     stringPos = tablePos + 34 + 2*n;
1382     for (i = 0; i < n; ++i) {
1383       j = getU16BE(tablePos + 34 + 2*i, &parsedOk);
1384       if (j < 258) {
1385         nameToGID->removeInt(macGlyphNames[j]);
1386         nameToGID->add(new GString(macGlyphNames[j]), i);
1387       } else {
1388         j -= 258;
1389         if (j != stringIdx) {
1390           for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
1391                stringIdx < j;
1392                ++stringIdx, stringPos += 1 + getU8(stringPos, &parsedOk)) ;
1393           if (!parsedOk) {
1394             return;
1395           }
1396         }
1397         m = getU8(stringPos, &parsedOk);
1398         if (!parsedOk || !checkRegion(stringPos + 1, m)) {
1399           parsedOk = gFalse;
1400           return;
1401         }
1402         name = new GString((char *)&file[stringPos + 1], m);
1403         nameToGID->removeInt(name);
1404         nameToGID->add(name, i);
1405         ++stringIdx;
1406         stringPos += 1 + m;
1407       }
1408     }
1409   } else if (postFmt == 0x00028000) {
1410     nameToGID = new GHash(gTrue);
1411     for (i = 0; i < nGlyphs; ++i) {
1412       j = getU8(tablePos + 32 + i, &parsedOk);
1413       if (!parsedOk) {
1414         return;
1415       }
1416       if (j < 258) {
1417         nameToGID->removeInt(macGlyphNames[j]);
1418         nameToGID->add(new GString(macGlyphNames[j]), i);
1419       }
1420     }
1421   }
1422 }
1423
1424 int FoFiTrueType::seekTable(char *tag) {
1425   Guint tagI;
1426   int i;
1427
1428   tagI = ((tag[0] & 0xff) << 24) |
1429          ((tag[1] & 0xff) << 16) |
1430          ((tag[2] & 0xff) << 8) |
1431           (tag[3] & 0xff);
1432   for (i = 0; i < nTables; ++i) {
1433     if (tables[i].tag == tagI) {
1434       return i;
1435     }
1436   }
1437   return -1;
1438 }