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