fix getsup (HH)
[luatex.git] / source / libs / poppler / poppler-src / fofi / FoFiTrueType.cc
blobf1a15e004da0cc55a488fb58850abf6794e3aac9
1 //========================================================================
2 //
3 // FoFiTrueType.cc
4 //
5 // Copyright 1999-2003 Glyph & Cog, LLC
6 //
7 //========================================================================
9 //========================================================================
11 // Modified under the Poppler project - http://poppler.freedesktop.org
13 // All changes made under the Poppler project to this file are licensed
14 // under GPL version 2 or later
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-2016 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, 2016 William Bader <williambader@hotmail.com>
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
30 //========================================================================
32 #include <config.h>
34 #ifdef USE_GCC_PRAGMAS
35 #pragma implementation
36 #endif
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"
51 // Terminology
52 // -----------
54 // character code = number used as an element of a text string
56 // character name = glyph name = name for a particular glyph within a
57 // font
59 // glyph index = GID = position (within some internal table in the font)
60 // where the instructions to draw a particular glyph are
61 // stored
63 // Type 1 fonts
64 // ------------
66 // Type 1 fonts contain:
68 // Encoding: array of glyph names, maps char codes to glyph names
70 // Encoding[charCode] = charName
72 // CharStrings: dictionary of instructions, keyed by character names,
73 // maps character name to glyph data
75 // CharStrings[charName] = glyphData
77 // TrueType fonts
78 // --------------
80 // TrueType fonts contain:
82 // 'cmap' table: mapping from character code to glyph index; there may
83 // be multiple cmaps in a TrueType font
85 // cmap[charCode] = gid
87 // 'post' table: mapping from glyph index to glyph name
89 // post[gid] = glyphName
91 // Type 42 fonts
92 // -------------
94 // Type 42 fonts contain:
96 // Encoding: array of glyph names, maps char codes to glyph names
98 // Encoding[charCode] = charName
100 // CharStrings: dictionary of glyph indexes, keyed by character names,
101 // maps character name to glyph index
103 // CharStrings[charName] = gid
106 //------------------------------------------------------------------------
108 #define ttcfTag 0x74746366
110 //------------------------------------------------------------------------
112 struct TrueTypeTable {
113 Guint tag;
114 Guint checksum;
115 int offset;
116 int origOffset;
117 int len;
120 struct TrueTypeCmap {
121 int platform;
122 int encoding;
123 int offset;
124 int len;
125 int fmt;
128 struct TrueTypeLoca {
129 int idx;
130 int origOffset;
131 int newOffset;
132 int len;
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
147 struct cmpTrueTypeLocaOffsetFunctor {
148 bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
149 if (loca1.origOffset == loca2.origOffset) {
150 return loca1.idx < loca2.idx;
152 return loca1.origOffset < loca2.origOffset;
156 struct cmpTrueTypeLocaIdxFunctor {
157 bool operator()(const TrueTypeLoca &loca1, const TrueTypeLoca &loca2) {
158 return loca1.idx < loca2.idx;
162 struct cmpTrueTypeTableTagFunctor {
163 bool operator()(const TrueTypeTable &tab1, const TrueTypeTable &tab2) {
164 return tab1.tag < tab2.tag;
168 //------------------------------------------------------------------------
170 struct T42Table {
171 const char *tag; // 4-byte tag
172 GBool required; // required by the TrueType spec?
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 }
191 #define t42HeadTable 3
192 #define t42LocaTable 6
193 #define t42GlyfTable 2
194 #define t42VheaTable 9
195 #define t42VmtxTable 10
197 //------------------------------------------------------------------------
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"
269 //------------------------------------------------------------------------
270 // FoFiTrueType
271 //------------------------------------------------------------------------
273 FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA, int faceIndexA) {
274 FoFiTrueType *ff;
276 ff = new FoFiTrueType(fileA, lenA, gFalse, faceIndexA);
277 if (!ff->parsedOk) {
278 delete ff;
279 return NULL;
281 return ff;
284 FoFiTrueType *FoFiTrueType::load(char *fileName, int faceIndexA) {
285 FoFiTrueType *ff;
286 char *fileA;
287 int lenA;
289 if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
290 return NULL;
292 ff = new FoFiTrueType(fileA, lenA, gTrue, faceIndexA);
293 if (!ff->parsedOk) {
294 delete ff;
295 return NULL;
297 return ff;
300 FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA):
301 FoFiBase(fileA, lenA, freeFileDataA)
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;
313 parse();
316 FoFiTrueType::~FoFiTrueType() {
317 gfree(tables);
318 gfree(cmaps);
319 if (nameToGID) {
320 delete nameToGID;
324 int FoFiTrueType::getNumCmaps() {
325 return nCmaps;
328 int FoFiTrueType::getCmapPlatform(int i) {
329 return cmaps[i].platform;
332 int FoFiTrueType::getCmapEncoding(int i) {
333 return cmaps[i].encoding;
336 int FoFiTrueType::findCmap(int platform, int encoding) {
337 int i;
339 for (i = 0; i < nCmaps; ++i) {
340 if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
341 return i;
344 return -1;
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;
354 if (i < 0 || i >= nCmaps) {
355 return 0;
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;
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;
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;
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;
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;
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;
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;
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;
428 segStart = getU32BE(pos + 16 + 12*b, &ok);
429 segDelta = getU32BE(pos + 16 + 12*b+8, &ok);
430 if (c < segStart) {
431 return 0;
433 gid = segDelta + (c-segStart);
434 break;
435 default:
436 return 0;
438 if (!ok) {
439 return 0;
441 return gid;
444 int FoFiTrueType::mapNameToGID(char *name) {
445 if (!nameToGID) {
446 return 0;
448 return nameToGID->lookupInt(name);
451 GBool FoFiTrueType::getCFFBlock(char **start, int *length) {
452 int i;
454 if (!openTypeCFF) {
455 return gFalse;
457 i = seekTable("CFF ");
458 if (!checkRegion(tables[i].offset, tables[i].len)) {
459 return gFalse;
461 *start = (char *)file + tables[i].offset;
462 *length = tables[i].len;
463 return gTrue;
466 int *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
467 char *start;
468 int length;
469 FoFiType1C *ff;
470 int *map;
472 *nCIDs = 0;
473 if (!getCFFBlock(&start, &length)) {
474 return NULL;
476 if (!(ff = FoFiType1C::make(start, length))) {
477 return NULL;
479 map = ff->getCIDToGIDMap(nCIDs);
480 delete ff;
481 return map;
484 int FoFiTrueType::getEmbeddingRights() {
485 int i, fsType;
486 GBool ok;
488 if ((i = seekTable("OS/2")) < 0) {
489 return 4;
491 ok = gTrue;
492 fsType = getU16BE(tables[i].offset + 8, &ok);
493 if (!ok) {
494 return 4;
496 if (fsType & 0x0008) {
497 return 2;
499 if (fsType & 0x0004) {
500 return 1;
502 if (fsType & 0x0002) {
503 return 0;
505 return 3;
508 void FoFiTrueType::getFontMatrix(double *mat) {
509 char *start;
510 int length;
511 FoFiType1C *ff;
513 if (!getCFFBlock(&start, &length)) {
514 return;
516 if (!(ff = FoFiType1C::make(start, length))) {
517 return;
519 ff->getFontMatrix(mat);
520 delete ff;
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;
531 if (openTypeCFF) {
532 return;
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;
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);
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);
560 // end the dictionary and define the font
561 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
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;
571 if (!getCFFBlock(&start, &length)) {
572 return;
574 if (!(ff = FoFiType1C::make(start, length))) {
575 return;
577 ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
578 delete ff;
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;
591 if (openTypeCFF) {
592 return;
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;
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;
632 (*outputFunc)(outputStream, "\n", 1);
634 (*outputFunc)(outputStream, " >", 3);
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;
649 (*outputFunc)(outputStream, "\n", 1);
651 (*outputFunc)(outputStream, "> def\n", 6);
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",
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);
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);
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);
702 // write the guts of the dictionary
703 cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics, &maxUsedGlyph);
705 // end the dictionary and define the font
706 (*outputFunc)(outputStream,
707 "CIDFontName currentdict end /CIDFont defineresource pop\n",
708 56);
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;
718 if (!getCFFBlock(&start, &length)) {
719 return;
721 if (!(ff = FoFiType1C::make(start, length))) {
722 return;
724 ff->convertToCIDType0(psName, cidMap, nCIDs, outputFunc, outputStream);
725 delete ff;
728 void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
729 GBool needVerticalMetrics,
730 int *maxValidGlyph,
731 FoFiOutputFunc outputFunc,
732 void *outputStream) {
733 GooString *buf;
734 GooString *sfntsName;
735 int maxUsedGlyph, n, i, j;
737 *maxValidGlyph = -1;
739 if (openTypeCFF) {
740 return;
743 // write the Type 42 sfnts array
744 sfntsName = (new GooString(psName))->append("_sfnts");
745 cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics,
746 &maxUsedGlyph);
747 delete sfntsName;
749 // write the descendant Type 42 fonts
750 // (The following is a kludge: nGlyphs is the glyph count from the
751 // maxp table; maxUsedGlyph is the max glyph number that has a
752 // non-zero-length description, from the loca table. The problem is
753 // that some TrueType font subsets fail to change the glyph count,
754 // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
755 // in an unnecessarily huge Type 0 font. But some other PDF files
756 // have fonts with only zero or one used glyph, and a content stream
757 // that refers to one of the unused glyphs -- this results in PS
758 // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
759 // we compromise by always defining at least 256 glyphs.)
760 // Some fonts have a large nGlyphs but maxUsedGlyph of 0.
761 // These fonts might reference any glyph.
762 // Return the last written glyph number in maxValidGlyph.
763 // PSOutputDev::drawString() can use maxValidGlyph to avoid
764 // referencing zero-length glyphs that we trimmed.
765 // This allows pdftops to avoid writing huge files while still
766 // handling the rare PDF that uses a zero-length glyph.
767 if (cidMap) {
768 n = nCIDs;
769 } else if (nGlyphs > maxUsedGlyph + 256) {
770 if (maxUsedGlyph <= 255) {
771 n = 256;
772 } else {
773 n = maxUsedGlyph + 1;
775 } else {
776 n = nGlyphs;
778 *maxValidGlyph = n-1;
779 for (i = 0; i < n; i += 256) {
780 (*outputFunc)(outputStream, "10 dict begin\n", 14);
781 (*outputFunc)(outputStream, "/FontName /", 11);
782 (*outputFunc)(outputStream, psName, strlen(psName));
783 buf = GooString::format("_{0:02x} def\n", i >> 8);
784 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
785 delete buf;
786 (*outputFunc)(outputStream, "/FontType 42 def\n", 17);
787 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
788 buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
789 bbox[0], bbox[1], bbox[2], bbox[3]);
790 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
791 delete buf;
792 (*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
793 (*outputFunc)(outputStream, "/sfnts ", 7);
794 (*outputFunc)(outputStream, psName, strlen(psName));
795 (*outputFunc)(outputStream, "_sfnts def\n", 11);
796 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
797 for (j = 0; j < 256 && i+j < n; ++j) {
798 buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
799 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
800 delete buf;
802 (*outputFunc)(outputStream, "readonly def\n", 13);
803 (*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
804 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
805 for (j = 0; j < 256 && i+j < n; ++j) {
806 buf = GooString::format("/c{0:02x} {1:d} def\n",
807 j, cidMap ? cidMap[i+j] : i+j);
808 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
809 delete buf;
811 (*outputFunc)(outputStream, "end readonly def\n", 17);
812 (*outputFunc)(outputStream,
813 "FontName currentdict end definefont pop\n", 40);
816 // write the Type 0 parent font
817 (*outputFunc)(outputStream, "16 dict begin\n", 14);
818 (*outputFunc)(outputStream, "/FontName /", 11);
819 (*outputFunc)(outputStream, psName, strlen(psName));
820 (*outputFunc)(outputStream, " def\n", 5);
821 (*outputFunc)(outputStream, "/FontType 0 def\n", 16);
822 (*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
823 (*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
824 (*outputFunc)(outputStream, "/Encoding [\n", 12);
825 for (i = 0; i < n; i += 256) {
826 buf = GooString::format("{0:d}\n", i >> 8);
827 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
828 delete buf;
830 (*outputFunc)(outputStream, "] def\n", 6);
831 (*outputFunc)(outputStream, "/FDepVector [\n", 14);
832 for (i = 0; i < n; i += 256) {
833 (*outputFunc)(outputStream, "/", 1);
834 (*outputFunc)(outputStream, psName, strlen(psName));
835 buf = GooString::format("_{0:02x} findfont\n", i >> 8);
836 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
837 delete buf;
839 (*outputFunc)(outputStream, "] def\n", 6);
840 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
843 void FoFiTrueType::convertToType0(char *psName, int *cidMap, int nCIDs,
844 FoFiOutputFunc outputFunc,
845 void *outputStream) {
846 char *start;
847 int length;
848 FoFiType1C *ff;
850 if (!getCFFBlock(&start, &length)) {
851 return;
853 if (!(ff = FoFiType1C::make(start, length))) {
854 return;
856 ff->convertToType0(psName, cidMap, nCIDs, outputFunc, outputStream);
857 delete ff;
860 void FoFiTrueType::cvtEncoding(char **encoding,
861 FoFiOutputFunc outputFunc,
862 void *outputStream) {
863 const char *name;
864 GooString *buf;
865 int i;
867 (*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
868 if (encoding) {
869 for (i = 0; i < 256; ++i) {
870 if (!(name = encoding[i])) {
871 name = ".notdef";
873 buf = GooString::format("dup {0:d} /", i);
874 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
875 delete buf;
876 (*outputFunc)(outputStream, name, strlen(name));
877 (*outputFunc)(outputStream, " put\n", 5);
879 } else {
880 for (i = 0; i < 256; ++i) {
881 buf = GooString::format("dup {0:d} /c{1:02x} put\n", i, i);
882 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
883 delete buf;
886 (*outputFunc)(outputStream, "readonly def\n", 13);
889 void FoFiTrueType::cvtCharStrings(char **encoding,
890 int *codeToGID,
891 FoFiOutputFunc outputFunc,
892 void *outputStream) {
893 char *name;
894 GooString *buf;
895 char buf2[16];
896 int i, k;
898 // always define '.notdef'
899 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
900 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
902 // if there's no 'cmap' table, punt
903 if (nCmaps == 0) {
904 goto err;
907 // map char name to glyph index:
908 // 1. use encoding to map name to char code
909 // 2. use codeToGID to map char code to glyph index
910 // N.B. We do this in reverse order because font subsets can have
911 // weird encodings that use the same character name twice, and
912 // the first definition is probably the one we want.
913 k = 0; // make gcc happy
914 for (i = 255; i >= 0; --i) {
915 if (encoding) {
916 name = encoding[i];
917 } else {
918 sprintf(buf2, "c%02x", i);
919 name = buf2;
921 if (name && strcmp(name, ".notdef")) {
922 k = codeToGID[i];
923 // note: Distiller (maybe Adobe's PS interpreter in general)
924 // doesn't like TrueType fonts that have CharStrings entries
925 // which point to nonexistent glyphs, hence the (k < nGlyphs)
926 // test
927 if (k > 0 && k < nGlyphs) {
928 (*outputFunc)(outputStream, "/", 1);
929 (*outputFunc)(outputStream, name, strlen(name));
930 buf = GooString::format(" {0:d} def\n", k);
931 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
932 delete buf;
937 err:
938 (*outputFunc)(outputStream, "end readonly def\n", 17);
941 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
942 void *outputStream, GooString *name,
943 GBool needVerticalMetrics,
944 int *maxUsedGlyph) {
945 Guchar headData[54];
946 TrueTypeLoca *locaTable;
947 Guchar *locaData;
948 TrueTypeTable newTables[nT42Tables];
949 Guchar tableDir[12 + nT42Tables*16];
950 GBool ok;
951 Guint checksum;
952 int nNewTables;
953 int glyfTableLen, length, pos, glyfPos, i, j, k, vmtxTabLength;
954 Guchar vheaTab[36] = {
955 0, 1, 0, 0, // table version number
956 0, 0, // ascent
957 0, 0, // descent
958 0, 0, // reserved
959 0, 0, // max advance height
960 0, 0, // min top side bearing
961 0, 0, // min bottom side bearing
962 0, 0, // y max extent
963 0, 0, // caret slope rise
964 0, 1, // caret slope run
965 0, 0, // caret offset
966 0, 0, // reserved
967 0, 0, // reserved
968 0, 0, // reserved
969 0, 0, // reserved
970 0, 0, // metric data format
971 0, 1 // number of advance heights in vmtx table
973 Guchar *vmtxTab;
974 GBool needVhea, needVmtx;
975 int advance;
977 // construct the 'head' table, zero out the font checksum
978 i = seekTable("head");
979 if (i < 0 || i >= nTables) {
980 return;
982 pos = tables[i].offset;
983 if (!checkRegion(pos, 54)) {
984 return;
986 memcpy(headData, file + pos, 54);
987 headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
989 // check for a bogus loca format field in the 'head' table
990 // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
991 if (locaFmt != 0 && locaFmt != 1) {
992 headData[50] = 0;
993 headData[51] = 1;
996 // read the original 'loca' table, pad entries out to 4 bytes, and
997 // sort it into proper order -- some (non-compliant) fonts have
998 // out-of-order loca tables; in order to correctly handle the case
999 // where (compliant) fonts have empty entries in the middle of the
1000 // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
1001 // and idx as its secondary key (ensuring that adjacent entries with
1002 // the same pos value remain in the same order)
1003 locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
1004 i = seekTable("loca");
1005 pos = tables[i].offset;
1006 i = seekTable("glyf");
1007 glyfTableLen = tables[i].len;
1008 ok = gTrue;
1009 for (i = 0; i <= nGlyphs; ++i) {
1010 locaTable[i].idx = i;
1011 if (locaFmt) {
1012 locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
1013 } else {
1014 locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
1016 if (locaTable[i].origOffset > glyfTableLen) {
1017 locaTable[i].origOffset = glyfTableLen;
1020 std::sort(locaTable, locaTable + nGlyphs + 1,
1021 cmpTrueTypeLocaOffsetFunctor());
1022 for (i = 0; i < nGlyphs; ++i) {
1023 locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
1025 locaTable[nGlyphs].len = 0;
1026 std::sort(locaTable, locaTable + nGlyphs + 1, cmpTrueTypeLocaIdxFunctor());
1027 pos = 0;
1028 *maxUsedGlyph = -1;
1029 for (i = 0; i <= nGlyphs; ++i) {
1030 locaTable[i].newOffset = pos;
1031 pos += locaTable[i].len;
1032 if (pos & 3) {
1033 pos += 4 - (pos & 3);
1035 if (locaTable[i].len > 0) {
1036 *maxUsedGlyph = i;
1040 // construct the new 'loca' table
1041 locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2));
1042 for (i = 0; i <= nGlyphs; ++i) {
1043 pos = locaTable[i].newOffset;
1044 if (locaFmt) {
1045 locaData[4*i ] = (Guchar)(pos >> 24);
1046 locaData[4*i+1] = (Guchar)(pos >> 16);
1047 locaData[4*i+2] = (Guchar)(pos >> 8);
1048 locaData[4*i+3] = (Guchar) pos;
1049 } else {
1050 locaData[2*i ] = (Guchar)(pos >> 9);
1051 locaData[2*i+1] = (Guchar)(pos >> 1);
1055 // count the number of tables
1056 nNewTables = 0;
1057 for (i = 0; i < nT42Tables; ++i) {
1058 if (t42Tables[i].required ||
1059 seekTable(t42Tables[i].tag) >= 0) {
1060 ++nNewTables;
1063 vmtxTab = NULL; // make gcc happy
1064 vmtxTabLength = 0;
1065 advance = 0; // make gcc happy
1066 if (needVerticalMetrics) {
1067 needVhea = seekTable("vhea") < 0;
1068 needVmtx = seekTable("vmtx") < 0;
1069 if (needVhea || needVmtx) {
1070 i = seekTable("head");
1071 advance = getU16BE(tables[i].offset + 18, &ok); // units per em
1072 if (needVhea) {
1073 ++nNewTables;
1075 if (needVmtx) {
1076 ++nNewTables;
1081 // construct the new table headers, including table checksums
1082 // (pad each table out to a multiple of 4 bytes)
1083 pos = 12 + nNewTables*16;
1084 k = 0;
1085 for (i = 0; i < nT42Tables; ++i) {
1086 length = -1;
1087 checksum = 0; // make gcc happy
1088 if (i == t42HeadTable) {
1089 length = 54;
1090 checksum = computeTableChecksum(headData, 54);
1091 } else if (i == t42LocaTable) {
1092 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1093 checksum = computeTableChecksum(locaData, length);
1094 } else if (i == t42GlyfTable) {
1095 length = 0;
1096 checksum = 0;
1097 glyfPos = tables[seekTable("glyf")].offset;
1098 for (j = 0; j < nGlyphs; ++j) {
1099 length += locaTable[j].len;
1100 if (length & 3) {
1101 length += 4 - (length & 3);
1103 if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1104 checksum +=
1105 computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
1106 locaTable[j].len);
1109 } else {
1110 if ((j = seekTable(t42Tables[i].tag)) >= 0) {
1111 length = tables[j].len;
1112 if (checkRegion(tables[j].offset, length)) {
1113 checksum = computeTableChecksum(file + tables[j].offset, length);
1115 } else if (needVerticalMetrics && i == t42VheaTable) {
1116 vheaTab[10] = advance / 256; // max advance height
1117 vheaTab[11] = advance % 256;
1118 length = sizeof(vheaTab);
1119 checksum = computeTableChecksum(vheaTab, length);
1120 } else if (needVerticalMetrics && i == t42VmtxTable) {
1121 length = 4 + (nGlyphs - 1) * 2;
1122 vmtxTabLength = length;
1123 vmtxTab = (Guchar *)gmalloc(length);
1124 vmtxTab[0] = advance / 256;
1125 vmtxTab[1] = advance % 256;
1126 for (j = 2; j < length; j += 2) {
1127 vmtxTab[j] = 0;
1128 vmtxTab[j+1] = 0;
1130 checksum = computeTableChecksum(vmtxTab, length);
1131 } else if (t42Tables[i].required) {
1132 //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1133 //~ t42Tables[i].tag);
1134 length = 0;
1135 checksum = 0;
1138 if (length >= 0) {
1139 newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
1140 ((t42Tables[i].tag[1] & 0xff) << 16) |
1141 ((t42Tables[i].tag[2] & 0xff) << 8) |
1142 (t42Tables[i].tag[3] & 0xff);
1143 newTables[k].checksum = checksum;
1144 newTables[k].offset = pos;
1145 newTables[k].len = length;
1146 pos += length;
1147 if (pos & 3) {
1148 pos += 4 - (length & 3);
1150 ++k;
1154 // construct the table directory
1155 tableDir[0] = 0x00; // sfnt version
1156 tableDir[1] = 0x01;
1157 tableDir[2] = 0x00;
1158 tableDir[3] = 0x00;
1159 tableDir[4] = 0; // numTables
1160 tableDir[5] = nNewTables;
1161 tableDir[6] = 0; // searchRange
1162 tableDir[7] = (Guchar)128;
1163 tableDir[8] = 0; // entrySelector
1164 tableDir[9] = 3;
1165 tableDir[10] = 0; // rangeShift
1166 tableDir[11] = (Guchar)(16 * nNewTables - 128);
1167 pos = 12;
1168 for (i = 0; i < nNewTables; ++i) {
1169 tableDir[pos ] = (Guchar)(newTables[i].tag >> 24);
1170 tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
1171 tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8);
1172 tableDir[pos+ 3] = (Guchar) newTables[i].tag;
1173 tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
1174 tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
1175 tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8);
1176 tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
1177 tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
1178 tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
1179 tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8);
1180 tableDir[pos+11] = (Guchar) newTables[i].offset;
1181 tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
1182 tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
1183 tableDir[pos+14] = (Guchar)(newTables[i].len >> 8);
1184 tableDir[pos+15] = (Guchar) newTables[i].len;
1185 pos += 16;
1188 // compute the font checksum and store it in the head table
1189 checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
1190 for (i = 0; i < nNewTables; ++i) {
1191 checksum += newTables[i].checksum;
1193 checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
1194 headData[ 8] = (Guchar)(checksum >> 24);
1195 headData[ 9] = (Guchar)(checksum >> 16);
1196 headData[10] = (Guchar)(checksum >> 8);
1197 headData[11] = (Guchar) checksum;
1199 // start the sfnts array
1200 if (name) {
1201 (*outputFunc)(outputStream, "/", 1);
1202 (*outputFunc)(outputStream, name->getCString(), name->getLength());
1203 (*outputFunc)(outputStream, " [\n", 3);
1204 } else {
1205 (*outputFunc)(outputStream, "/sfnts [\n", 9);
1208 // write the table directory
1209 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
1211 // write the tables
1212 for (i = 0; i < nNewTables; ++i) {
1213 if (i == t42HeadTable) {
1214 dumpString(headData, 54, outputFunc, outputStream);
1215 } else if (i == t42LocaTable) {
1216 length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1217 dumpString(locaData, length, outputFunc, outputStream);
1218 } else if (i == t42GlyfTable) {
1219 glyfPos = tables[seekTable("glyf")].offset;
1220 for (j = 0; j < nGlyphs; ++j) {
1221 if (locaTable[j].len > 0 &&
1222 checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1223 dumpString(file + glyfPos + locaTable[j].origOffset,
1224 locaTable[j].len, outputFunc, outputStream);
1227 } else {
1228 // length == 0 means the table is missing and the error was
1229 // already reported during the construction of the table
1230 // headers
1231 if ((length = newTables[i].len) > 0) {
1232 if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
1233 checkRegion(tables[j].offset, tables[j].len)) {
1234 dumpString(file + tables[j].offset, tables[j].len,
1235 outputFunc, outputStream);
1236 } else if (needVerticalMetrics && i == t42VheaTable) {
1237 if (unlikely(length > (int)sizeof(vheaTab))) {
1238 error(errSyntaxWarning, -1, "length bigger than vheaTab size");
1239 length = sizeof(vheaTab);
1241 dumpString(vheaTab, length, outputFunc, outputStream);
1242 } else if (needVerticalMetrics && i == t42VmtxTable) {
1243 if (unlikely(length > vmtxTabLength)) {
1244 error(errSyntaxWarning, -1, "length bigger than vmtxTab size");
1245 length = vmtxTabLength;
1247 dumpString(vmtxTab, length, outputFunc, outputStream);
1253 // end the sfnts array
1254 (*outputFunc)(outputStream, "] def\n", 6);
1256 gfree(locaData);
1257 gfree(locaTable);
1258 if (vmtxTab) {
1259 gfree(vmtxTab);
1263 void FoFiTrueType::dumpString(Guchar *s, int length,
1264 FoFiOutputFunc outputFunc,
1265 void *outputStream) {
1266 GooString *buf;
1267 int pad, i, j;
1269 (*outputFunc)(outputStream, "<", 1);
1270 for (i = 0; i < length; i += 32) {
1271 for (j = 0; j < 32 && i+j < length; ++j) {
1272 buf = GooString::format("{0:02x}", s[i+j] & 0xff);
1273 (*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1274 delete buf;
1276 if (i % (65536 - 32) == 65536 - 64) {
1277 (*outputFunc)(outputStream, ">\n<", 3);
1278 } else if (i+32 < length) {
1279 (*outputFunc)(outputStream, "\n", 1);
1282 if (length & 3) {
1283 pad = 4 - (length & 3);
1284 for (i = 0; i < pad; ++i) {
1285 (*outputFunc)(outputStream, "00", 2);
1288 // add an extra zero byte because the Adobe Type 42 spec says so
1289 (*outputFunc)(outputStream, "00>\n", 4);
1292 Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
1293 Guint checksum, word;
1294 int i;
1296 checksum = 0;
1297 for (i = 0; i+3 < length; i += 4) {
1298 word = ((data[i ] & 0xff) << 24) +
1299 ((data[i+1] & 0xff) << 16) +
1300 ((data[i+2] & 0xff) << 8) +
1301 (data[i+3] & 0xff);
1302 checksum += word;
1304 if (length & 3) {
1305 word = 0;
1306 i = length & ~3;
1307 switch (length & 3) {
1308 case 3:
1309 word |= (data[i+2] & 0xff) << 8;
1310 case 2:
1311 word |= (data[i+1] & 0xff) << 16;
1312 case 1:
1313 word |= (data[i ] & 0xff) << 24;
1314 break;
1316 checksum += word;
1318 return checksum;
1321 void FoFiTrueType::parse() {
1322 Guint topTag;
1323 int pos, ver, i, j;
1325 parsedOk = gTrue;
1327 // look for a collection (TTC)
1328 topTag = getU32BE(0, &parsedOk);
1329 if (!parsedOk) {
1330 return;
1332 if (topTag == ttcfTag) {
1333 /* TTC font */
1334 int dircount;
1336 dircount = getU32BE(8, &parsedOk);
1337 if (!parsedOk)
1338 return;
1339 if (! dircount) {
1340 parsedOk = gFalse;
1341 return;
1344 if (faceIndex >= dircount)
1345 faceIndex = 0;
1346 pos = getU32BE(12 + faceIndex * 4, &parsedOk);
1347 if (! parsedOk)
1348 return;
1349 } else {
1350 pos = 0;
1353 // check the sfnt version
1354 ver = getU32BE(pos, &parsedOk);
1355 if (!parsedOk) {
1356 return;
1358 openTypeCFF = ver == 0x4f54544f; // 'OTTO'
1360 // read the table directory
1361 nTables = getU16BE(pos + 4, &parsedOk);
1362 if (!parsedOk) {
1363 return;
1365 tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
1366 pos += 12;
1367 j = 0;
1368 for (i = 0; i < nTables; ++i) {
1369 tables[j].tag = getU32BE(pos, &parsedOk);
1370 tables[j].checksum = getU32BE(pos + 4, &parsedOk);
1371 tables[j].offset = (int)getU32BE(pos + 8, &parsedOk);
1372 tables[j].len = (int)getU32BE(pos + 12, &parsedOk);
1373 if (unlikely((tables[j].offset < 0) ||
1374 (tables[j].len < 0) ||
1375 (tables[j].offset < INT_MAX - tables[j].len) ||
1376 (tables[j].len > INT_MAX - tables[j].offset) ||
1377 (tables[j].offset + tables[j].len >= tables[j].offset && tables[j].offset + tables[j].len <= len))) {
1378 // ignore any bogus entries in the table directory
1379 ++j;
1381 pos += 16;
1383 if (nTables != j) {
1384 nTables = j;
1385 tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
1387 if (!parsedOk || tables == NULL) {
1388 return;
1391 // check for tables that are required by both the TrueType spec and
1392 // the Type 42 spec
1393 if (seekTable("head") < 0 ||
1394 seekTable("hhea") < 0 ||
1395 seekTable("maxp") < 0 ||
1396 (!openTypeCFF && seekTable("loca") < 0) ||
1397 (!openTypeCFF && seekTable("glyf") < 0) ||
1398 (openTypeCFF && seekTable("CFF ") < 0)) {
1399 parsedOk = gFalse;
1400 return;
1403 // read the cmaps
1404 if ((i = seekTable("cmap")) >= 0) {
1405 pos = tables[i].offset + 2;
1406 nCmaps = getU16BE(pos, &parsedOk);
1407 pos += 2;
1408 if (!parsedOk) {
1409 return;
1411 cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
1412 for (j = 0; j < nCmaps; ++j) {
1413 cmaps[j].platform = getU16BE(pos, &parsedOk);
1414 cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
1415 cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
1416 pos += 8;
1417 cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
1418 cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
1420 if (!parsedOk) {
1421 return;
1423 } else {
1424 nCmaps = 0;
1427 // get the number of glyphs from the maxp table
1428 i = seekTable("maxp");
1429 nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
1430 if (!parsedOk) {
1431 return;
1434 // get the bbox and loca table format from the head table
1435 i = seekTable("head");
1436 bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
1437 bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
1438 bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
1439 bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
1440 locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
1441 if (!parsedOk) {
1442 return;
1445 // read the post table
1446 readPostTable();
1449 void FoFiTrueType::readPostTable() {
1450 GooString *name;
1451 int tablePos, postFmt, stringIdx, stringPos, savedStringIdx;
1452 GBool ok;
1453 int i, j, n, m;
1455 ok = gTrue;
1456 if ((i = seekTable("post")) < 0) {
1457 return;
1459 tablePos = tables[i].offset;
1460 postFmt = getU32BE(tablePos, &ok);
1461 if (!ok) {
1462 goto err;
1464 if (postFmt == 0x00010000) {
1465 nameToGID = new GooHash(gTrue);
1466 for (i = 0; i < 258; ++i) {
1467 nameToGID->add(new GooString(macGlyphNames[i]), i);
1469 } else if (postFmt == 0x00020000) {
1470 nameToGID = new GooHash(gTrue);
1471 n = getU16BE(tablePos + 32, &ok);
1472 if (!ok) {
1473 goto err;
1475 if (n > nGlyphs) {
1476 n = nGlyphs;
1478 stringIdx = 0;
1479 stringPos = tablePos + 34 + 2*n;
1480 for (i = 0; i < n; ++i) {
1481 j = getU16BE(tablePos + 34 + 2*i, &ok);
1482 if (j < 258) {
1483 nameToGID->removeInt(macGlyphNames[j]);
1484 nameToGID->add(new GooString(macGlyphNames[j]), i);
1485 } else {
1486 savedStringIdx = stringIdx;
1487 j -= 258;
1488 if (j != stringIdx) {
1489 for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
1490 stringIdx < j;
1491 ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
1492 if (!ok) {
1493 goto err;
1496 m = getU8(stringPos, &ok);
1497 if (!ok || !checkRegion(stringPos + 1, m)) {
1498 stringIdx = savedStringIdx;
1499 if (j < 258) {
1500 ok = gTrue;
1501 nameToGID->removeInt(macGlyphNames[j]);
1502 nameToGID->add(new GooString(macGlyphNames[0]), i);
1503 } else {
1504 goto err;
1506 } else {
1507 name = new GooString((char *)&file[stringPos + 1], m);
1508 nameToGID->removeInt(name);
1509 nameToGID->add(name, i);
1510 ++stringIdx;
1511 stringPos += 1 + m;
1515 } else if (postFmt == 0x00028000) {
1516 nameToGID = new GooHash(gTrue);
1517 for (i = 0; i < nGlyphs; ++i) {
1518 j = getU8(tablePos + 32 + i, &ok);
1519 if (!ok) {
1520 goto err;
1522 if (j < 258) {
1523 nameToGID->removeInt(macGlyphNames[j]);
1524 nameToGID->add(new GooString(macGlyphNames[j]), i);
1529 return;
1531 err:
1532 if (nameToGID) {
1533 delete nameToGID;
1534 nameToGID = NULL;
1538 int FoFiTrueType::seekTable(const char *tag) {
1539 Guint tagI;
1540 int i;
1542 tagI = ((tag[0] & 0xff) << 24) |
1543 ((tag[1] & 0xff) << 16) |
1544 ((tag[2] & 0xff) << 8) |
1545 (tag[3] & 0xff);
1546 for (i = 0; i < nTables; ++i) {
1547 if (tables[i].tag == tagI) {
1548 return i;
1551 return -1;
1554 Guint FoFiTrueType::charToTag(const char *tagName)
1556 int n = strlen(tagName);
1557 Guint tag = 0;
1558 int i;
1560 if (n > 4) n = 4;
1561 for (i = 0;i < n;i++) {
1562 tag <<= 8;
1563 tag |= tagName[i] & 0xff;
1565 for (;i < 4;i++) {
1566 tag <<= 8;
1567 tag |= ' ';
1569 return tag;
1573 setup GSUB table data
1574 Only supporting vertical text substitution.
1576 int FoFiTrueType::setupGSUB(const char *scriptName)
1578 return setupGSUB(scriptName, NULL);
1582 setup GSUB table data
1583 Only supporting vertical text substitution.
1585 int FoFiTrueType::setupGSUB(const char *scriptName,
1586 const char *languageName)
1588 Guint gsubTable;
1589 unsigned int i;
1590 Guint scriptList, featureList;
1591 Guint scriptCount;
1592 Guint tag;
1593 Guint scriptTable = 0;
1594 Guint langSys;
1595 Guint featureCount;
1596 Guint featureIndex;
1597 Guint ftable = 0;
1598 Guint llist;
1599 Guint scriptTag;
1600 int x;
1601 Guint pos;
1603 if (scriptName == 0) {
1604 gsubFeatureTable = 0;
1605 return 0;
1607 scriptTag = charToTag(scriptName);
1608 /* read GSUB Header */
1609 if ((x = seekTable("GSUB")) < 0) {
1610 return 0; /* GSUB table not found */
1612 gsubTable = tables[x].offset;
1613 pos = gsubTable+4;
1614 scriptList = getU16BE(pos,&parsedOk);
1615 pos += 2;
1616 featureList = getU16BE(pos,&parsedOk);
1617 pos += 2;
1618 llist = getU16BE(pos,&parsedOk);
1620 gsubLookupList = llist+gsubTable; /* change to offset from top of file */
1621 /* read script list table */
1622 pos = gsubTable+scriptList;
1623 scriptCount = getU16BE(pos,&parsedOk);
1624 pos += 2;
1625 /* find script */
1626 for (i = 0;i < scriptCount;i++) {
1627 tag = getU32BE(pos,&parsedOk);
1628 pos += 4;
1629 scriptTable = getU16BE(pos,&parsedOk);
1630 pos += 2;
1631 if (tag == scriptTag) {
1632 /* found */
1633 break;
1636 if (i >= scriptCount) {
1637 /* not found */
1638 return 0;
1641 /* read script table */
1642 /* use default language system */
1643 pos = gsubTable+scriptList+scriptTable;
1644 langSys = 0;
1645 if (languageName) {
1646 Guint langTag = charToTag(languageName);
1647 Guint langCount = getU16BE(pos+2,&parsedOk);
1648 for (i = 0;i < langCount && langSys == 0;i++) {
1649 tag = getU32BE(pos+4+i*(4+2),&parsedOk);
1650 if (tag == langTag) {
1651 langSys = getU16BE(pos+4+i*(4+2)+4,&parsedOk);
1655 if (langSys == 0) {
1656 /* default language system */
1657 langSys = getU16BE(pos,&parsedOk);
1660 /* read LangSys table */
1661 if (langSys == 0) {
1662 /* no default LangSys */
1663 return 0;
1666 pos = gsubTable+scriptList+scriptTable+langSys+2;
1667 featureIndex = getU16BE(pos,&parsedOk); /* ReqFeatureIndex */
1668 pos += 2;
1670 if (featureIndex != 0xffff) {
1671 Guint tpos;
1672 /* read feature record */
1673 tpos = gsubTable+featureList;
1674 featureCount = getU16BE(tpos,&parsedOk);
1675 tpos = gsubTable+featureList+2+featureIndex*(4+2);
1676 tag = getU32BE(tpos,&parsedOk);
1677 tpos += 4;
1678 if (tag == vrt2Tag) {
1679 /* vrt2 is preferred, overwrite vert */
1680 ftable = getU16BE(tpos,&parsedOk);
1681 /* convert to offset from file top */
1682 gsubFeatureTable = ftable+gsubTable+featureList;
1683 return 0;
1684 } else if (tag == vertTag) {
1685 ftable = getU16BE(tpos,&parsedOk);
1688 featureCount = getU16BE(pos,&parsedOk);
1689 pos += 2;
1690 /* find 'vrt2' or 'vert' feature */
1691 for (i = 0;i < featureCount;i++) {
1692 Guint oldPos;
1694 featureIndex = getU16BE(pos,&parsedOk);
1695 pos += 2;
1696 oldPos = pos; /* save position */
1697 /* read feature record */
1698 pos = gsubTable+featureList+2+featureIndex*(4+2);
1699 tag = getU32BE(pos,&parsedOk);
1700 pos += 4;
1701 if (tag == vrt2Tag) {
1702 /* vrt2 is preferred, overwrite vert */
1703 ftable = getU16BE(pos,&parsedOk);
1704 break;
1705 } else if (ftable == 0 && tag == vertTag) {
1706 ftable = getU16BE(pos,&parsedOk);
1708 pos = oldPos; /* restore old position */
1710 if (ftable == 0) {
1711 /* vert nor vrt2 are not found */
1712 return 0;
1714 /* convert to offset from file top */
1715 gsubFeatureTable = ftable+gsubTable+featureList;
1716 return 0;
1719 Guint FoFiTrueType::doMapToVertGID(Guint orgGID)
1721 Guint lookupCount;
1722 Guint lookupListIndex;
1723 Guint i;
1724 Guint gid = 0;
1725 Guint pos;
1727 pos = gsubFeatureTable+2;
1728 lookupCount = getU16BE(pos,&parsedOk);
1729 pos += 2;
1730 for (i = 0;i < lookupCount;i++) {
1731 lookupListIndex = getU16BE(pos,&parsedOk);
1732 pos += 2;
1733 if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
1734 break;
1737 return gid;
1740 Guint FoFiTrueType::mapToVertGID(Guint orgGID)
1742 Guint mapped;
1744 if (gsubFeatureTable == 0) return orgGID;
1745 if ((mapped = doMapToVertGID(orgGID)) != 0) {
1746 return mapped;
1748 return orgGID;
1751 Guint FoFiTrueType::scanLookupList(Guint listIndex, Guint orgGID)
1753 Guint lookupTable;
1754 Guint subTableCount;
1755 Guint subTable;
1756 Guint i;
1757 Guint gid = 0;
1758 Guint pos;
1760 if (gsubLookupList == 0) return 0; /* no lookup list */
1761 pos = gsubLookupList+2+listIndex*2;
1762 lookupTable = getU16BE(pos,&parsedOk);
1763 /* read lookup table */
1764 pos = gsubLookupList+lookupTable+4;
1765 subTableCount = getU16BE(pos,&parsedOk);
1766 pos += 2;;
1767 for (i = 0;i < subTableCount;i++) {
1768 subTable = getU16BE(pos,&parsedOk);
1769 pos += 2;
1770 if ((gid = scanLookupSubTable(gsubLookupList+lookupTable+subTable,orgGID))
1771 != 0) break;
1773 return gid;
1776 Guint FoFiTrueType::scanLookupSubTable(Guint subTable, Guint orgGID)
1778 Guint format;
1779 Guint coverage;
1780 int delta;
1781 int glyphCount;
1782 Guint substitute;
1783 Guint gid = 0;
1784 int coverageIndex;
1785 int pos;
1787 pos = subTable;
1788 format = getU16BE(pos,&parsedOk);
1789 pos += 2;
1790 coverage = getU16BE(pos,&parsedOk);
1791 pos += 2;
1792 if ((coverageIndex =
1793 checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
1794 switch (format) {
1795 case 1:
1796 /* format 1 */
1797 delta = getS16BE(pos,&parsedOk);
1798 pos += 2;
1799 gid = orgGID+delta;
1800 break;
1801 case 2:
1802 /* format 2 */
1803 glyphCount = getS16BE(pos,&parsedOk);
1804 pos += 2;
1805 if (glyphCount > coverageIndex) {
1806 pos += coverageIndex*2;
1807 substitute = getU16BE(pos,&parsedOk);
1808 gid = substitute;
1810 break;
1811 default:
1812 /* unknown format */
1813 break;
1816 return gid;
1819 int FoFiTrueType::checkGIDInCoverage(Guint coverage, Guint orgGID)
1821 int index = -1;
1822 Guint format;
1823 Guint count;
1824 Guint i;
1825 Guint pos;
1827 pos = coverage;
1828 format = getU16BE(pos,&parsedOk);
1829 pos += 2;
1830 switch (format) {
1831 case 1:
1832 count = getU16BE(pos,&parsedOk);
1833 pos += 2;
1834 // In some poor CJK fonts, key GIDs are not sorted,
1835 // thus we cannot finish checking even when the range
1836 // including orgGID seems to have already passed.
1837 for (i = 0;i < count;i++) {
1838 Guint gid;
1840 gid = getU16BE(pos,&parsedOk);
1841 pos += 2;
1842 if (gid == orgGID) {
1843 /* found */
1844 index = i;
1845 break;
1848 break;
1849 case 2:
1850 count = getU16BE(pos,&parsedOk);
1851 pos += 2;
1852 for (i = 0;i < count;i++) {
1853 Guint startGID, endGID;
1854 Guint startIndex;
1856 startGID = getU16BE(pos,&parsedOk);
1857 pos += 2;
1858 endGID = getU16BE(pos,&parsedOk);
1859 pos += 2;
1860 startIndex = getU16BE(pos,&parsedOk);
1861 pos += 2;
1862 // In some poor CJK fonts, key GIDs are not sorted,
1863 // thus we cannot finish checking even when the range
1864 // including orgGID seems to have already passed.
1865 if (startGID <= orgGID && orgGID <= endGID) {
1866 /* found */
1867 index = startIndex+orgGID-startGID;
1868 break;
1871 break;
1872 default:
1873 break;
1875 return index;