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