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