beta-0.89.2
[luatex.git] / source / libs / poppler / poppler-src / fofi / FoFiTrueType.cc
blob11699dd61197d12dd7f10d395b7db356ebf86a65
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, 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>
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 FoFiOutputFunc outputFunc,
731 void *outputStream) {
732 GooString *buf;
733 GooString *sfntsName;
734 int maxUsedGlyph, n, i, j;
736 if (openTypeCFF) {
737 return;
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;
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;
765 } else {
766 n = nGlyphs;
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;
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;
800 (*outputFunc)(outputStream, "end readonly def\n", 17);
801 (*outputFunc)(outputStream,
802 "FontName currentdict end definefont pop\n", 40);
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;
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;
828 (*outputFunc)(outputStream, "] def\n", 6);
829 (*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
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;
839 if (!getCFFBlock(&start, &length)) {
840 return;
842 if (!(ff = FoFiType1C::make(start, length))) {
843 return;
845 ff->convertToType0(psName, cidMap, nCIDs, outputFunc, outputStream);
846 delete ff;
849 void FoFiTrueType::cvtEncoding(char **encoding,
850 FoFiOutputFunc outputFunc,
851 void *outputStream) {
852 const char *name;
853 GooString *buf;
854 int i;
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";
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);
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;
875 (*outputFunc)(outputStream, "readonly def\n", 13);
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;
887 // always define '.notdef'
888 (*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
889 (*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
891 // if there's no 'cmap' table, punt
892 if (nCmaps == 0) {
893 goto err;
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;
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;
926 err:
927 (*outputFunc)(outputStream, "end readonly def\n", 17);
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
962 Guchar *vmtxTab;
963 GBool needVhea, needVmtx;
964 int advance;
966 // construct the 'head' table, zero out the font checksum
967 i = seekTable("head");
968 if (i < 0 || i >= nTables) {
969 return;
971 pos = tables[i].offset;
972 if (!checkRegion(pos, 54)) {
973 return;
975 memcpy(headData, file + pos, 54);
976 headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
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;
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);
1005 if (locaTable[i].origOffset > glyfTableLen) {
1006 locaTable[i].origOffset = glyfTableLen;
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;
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);
1024 if (locaTable[i].len > 0) {
1025 *maxUsedGlyph = i;
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);
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;
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;
1064 if (needVmtx) {
1065 ++nNewTables;
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);
1092 if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1093 checksum +=
1094 computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
1095 locaTable[j].len);
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);
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;
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;
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);
1139 ++k;
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;
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;
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;
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);
1197 // write the table directory
1198 dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
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);
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);
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;
1236 dumpString(vmtxTab, length, outputFunc, outputStream);
1242 // end the sfnts array
1243 (*outputFunc)(outputStream, "] def\n", 6);
1245 gfree(locaData);
1246 gfree(locaTable);
1247 if (vmtxTab) {
1248 gfree(vmtxTab);
1252 void FoFiTrueType::dumpString(Guchar *s, int length,
1253 FoFiOutputFunc outputFunc,
1254 void *outputStream) {
1255 GooString *buf;
1256 int pad, i, j;
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;
1265 if (i % (65536 - 32) == 65536 - 64) {
1266 (*outputFunc)(outputStream, ">\n<", 3);
1267 } else if (i+32 < length) {
1268 (*outputFunc)(outputStream, "\n", 1);
1271 if (length & 3) {
1272 pad = 4 - (length & 3);
1273 for (i = 0; i < pad; ++i) {
1274 (*outputFunc)(outputStream, "00", 2);
1277 // add an extra zero byte because the Adobe Type 42 spec says so
1278 (*outputFunc)(outputStream, "00>\n", 4);
1281 Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
1282 Guint checksum, word;
1283 int i;
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;
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 case 2:
1300 word |= (data[i+1] & 0xff) << 16;
1301 case 1:
1302 word |= (data[i ] & 0xff) << 24;
1303 break;
1305 checksum += word;
1307 return checksum;
1310 void FoFiTrueType::parse() {
1311 Guint topTag;
1312 int pos, ver, i, j;
1314 parsedOk = gTrue;
1316 // look for a collection (TTC)
1317 topTag = getU32BE(0, &parsedOk);
1318 if (!parsedOk) {
1319 return;
1321 if (topTag == ttcfTag) {
1322 /* TTC font */
1323 int dircount;
1325 dircount = getU32BE(8, &parsedOk);
1326 if (!parsedOk)
1327 return;
1328 if (! dircount) {
1329 parsedOk = gFalse;
1330 return;
1333 if (faceIndex >= dircount)
1334 faceIndex = 0;
1335 pos = getU32BE(12 + faceIndex * 4, &parsedOk);
1336 if (! parsedOk)
1337 return;
1338 } else {
1339 pos = 0;
1342 // check the sfnt version
1343 ver = getU32BE(pos, &parsedOk);
1344 if (!parsedOk) {
1345 return;
1347 openTypeCFF = ver == 0x4f54544f; // 'OTTO'
1349 // read the table directory
1350 nTables = getU16BE(pos + 4, &parsedOk);
1351 if (!parsedOk) {
1352 return;
1354 tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
1355 pos += 12;
1356 j = 0;
1357 for (i = 0; i < nTables; ++i) {
1358 tables[j].tag = getU32BE(pos, &parsedOk);
1359 tables[j].checksum = getU32BE(pos + 4, &parsedOk);
1360 tables[j].offset = (int)getU32BE(pos + 8, &parsedOk);
1361 tables[j].len = (int)getU32BE(pos + 12, &parsedOk);
1362 if (tables[j].offset + tables[j].len >= tables[j].offset &&
1363 tables[j].offset + tables[j].len <= len) {
1364 // ignore any bogus entries in the table directory
1365 ++j;
1367 pos += 16;
1369 if (nTables != j) {
1370 nTables = j;
1371 tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
1373 if (!parsedOk || tables == NULL) {
1374 return;
1377 // check for tables that are required by both the TrueType spec and
1378 // the Type 42 spec
1379 if (seekTable("head") < 0 ||
1380 seekTable("hhea") < 0 ||
1381 seekTable("maxp") < 0 ||
1382 (!openTypeCFF && seekTable("loca") < 0) ||
1383 (!openTypeCFF && seekTable("glyf") < 0) ||
1384 (openTypeCFF && seekTable("CFF ") < 0)) {
1385 parsedOk = gFalse;
1386 return;
1389 // read the cmaps
1390 if ((i = seekTable("cmap")) >= 0) {
1391 pos = tables[i].offset + 2;
1392 nCmaps = getU16BE(pos, &parsedOk);
1393 pos += 2;
1394 if (!parsedOk) {
1395 return;
1397 cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
1398 for (j = 0; j < nCmaps; ++j) {
1399 cmaps[j].platform = getU16BE(pos, &parsedOk);
1400 cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
1401 cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
1402 pos += 8;
1403 cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
1404 cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
1406 if (!parsedOk) {
1407 return;
1409 } else {
1410 nCmaps = 0;
1413 // get the number of glyphs from the maxp table
1414 i = seekTable("maxp");
1415 nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
1416 if (!parsedOk) {
1417 return;
1420 // get the bbox and loca table format from the head table
1421 i = seekTable("head");
1422 bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
1423 bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
1424 bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
1425 bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
1426 locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
1427 if (!parsedOk) {
1428 return;
1431 // read the post table
1432 readPostTable();
1435 void FoFiTrueType::readPostTable() {
1436 GooString *name;
1437 int tablePos, postFmt, stringIdx, stringPos, savedStringIdx;
1438 GBool ok;
1439 int i, j, n, m;
1441 ok = gTrue;
1442 if ((i = seekTable("post")) < 0) {
1443 return;
1445 tablePos = tables[i].offset;
1446 postFmt = getU32BE(tablePos, &ok);
1447 if (!ok) {
1448 goto err;
1450 if (postFmt == 0x00010000) {
1451 nameToGID = new GooHash(gTrue);
1452 for (i = 0; i < 258; ++i) {
1453 nameToGID->add(new GooString(macGlyphNames[i]), i);
1455 } else if (postFmt == 0x00020000) {
1456 nameToGID = new GooHash(gTrue);
1457 n = getU16BE(tablePos + 32, &ok);
1458 if (!ok) {
1459 goto err;
1461 if (n > nGlyphs) {
1462 n = nGlyphs;
1464 stringIdx = 0;
1465 stringPos = tablePos + 34 + 2*n;
1466 for (i = 0; i < n; ++i) {
1467 j = getU16BE(tablePos + 34 + 2*i, &ok);
1468 if (j < 258) {
1469 nameToGID->removeInt(macGlyphNames[j]);
1470 nameToGID->add(new GooString(macGlyphNames[j]), i);
1471 } else {
1472 savedStringIdx = stringIdx;
1473 j -= 258;
1474 if (j != stringIdx) {
1475 for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
1476 stringIdx < j;
1477 ++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
1478 if (!ok) {
1479 goto err;
1482 m = getU8(stringPos, &ok);
1483 if (!ok || !checkRegion(stringPos + 1, m)) {
1484 stringIdx = savedStringIdx;
1485 if (j < 258) {
1486 ok = gTrue;
1487 nameToGID->removeInt(macGlyphNames[j]);
1488 nameToGID->add(new GooString(macGlyphNames[0]), i);
1489 } else {
1490 goto err;
1492 } else {
1493 name = new GooString((char *)&file[stringPos + 1], m);
1494 nameToGID->removeInt(name);
1495 nameToGID->add(name, i);
1496 ++stringIdx;
1497 stringPos += 1 + m;
1501 } else if (postFmt == 0x00028000) {
1502 nameToGID = new GooHash(gTrue);
1503 for (i = 0; i < nGlyphs; ++i) {
1504 j = getU8(tablePos + 32 + i, &ok);
1505 if (!ok) {
1506 goto err;
1508 if (j < 258) {
1509 nameToGID->removeInt(macGlyphNames[j]);
1510 nameToGID->add(new GooString(macGlyphNames[j]), i);
1515 return;
1517 err:
1518 if (nameToGID) {
1519 delete nameToGID;
1520 nameToGID = NULL;
1524 int FoFiTrueType::seekTable(const char *tag) {
1525 Guint tagI;
1526 int i;
1528 tagI = ((tag[0] & 0xff) << 24) |
1529 ((tag[1] & 0xff) << 16) |
1530 ((tag[2] & 0xff) << 8) |
1531 (tag[3] & 0xff);
1532 for (i = 0; i < nTables; ++i) {
1533 if (tables[i].tag == tagI) {
1534 return i;
1537 return -1;
1540 Guint FoFiTrueType::charToTag(const char *tagName)
1542 int n = strlen(tagName);
1543 Guint tag = 0;
1544 int i;
1546 if (n > 4) n = 4;
1547 for (i = 0;i < n;i++) {
1548 tag <<= 8;
1549 tag |= tagName[i] & 0xff;
1551 for (;i < 4;i++) {
1552 tag <<= 8;
1553 tag |= ' ';
1555 return tag;
1559 setup GSUB table data
1560 Only supporting vertical text substitution.
1562 int FoFiTrueType::setupGSUB(const char *scriptName)
1564 return setupGSUB(scriptName, NULL);
1568 setup GSUB table data
1569 Only supporting vertical text substitution.
1571 int FoFiTrueType::setupGSUB(const char *scriptName,
1572 const char *languageName)
1574 Guint gsubTable;
1575 unsigned int i;
1576 Guint scriptList, featureList;
1577 Guint scriptCount;
1578 Guint tag;
1579 Guint scriptTable = 0;
1580 Guint langSys;
1581 Guint featureCount;
1582 Guint featureIndex;
1583 Guint ftable = 0;
1584 Guint llist;
1585 Guint scriptTag;
1586 int x;
1587 Guint pos;
1589 if (scriptName == 0) {
1590 gsubFeatureTable = 0;
1591 return 0;
1593 scriptTag = charToTag(scriptName);
1594 /* read GSUB Header */
1595 if ((x = seekTable("GSUB")) < 0) {
1596 return 0; /* GSUB table not found */
1598 gsubTable = tables[x].offset;
1599 pos = gsubTable+4;
1600 scriptList = getU16BE(pos,&parsedOk);
1601 pos += 2;
1602 featureList = getU16BE(pos,&parsedOk);
1603 pos += 2;
1604 llist = getU16BE(pos,&parsedOk);
1606 gsubLookupList = llist+gsubTable; /* change to offset from top of file */
1607 /* read script list table */
1608 pos = gsubTable+scriptList;
1609 scriptCount = getU16BE(pos,&parsedOk);
1610 pos += 2;
1611 /* find script */
1612 for (i = 0;i < scriptCount;i++) {
1613 tag = getU32BE(pos,&parsedOk);
1614 pos += 4;
1615 scriptTable = getU16BE(pos,&parsedOk);
1616 pos += 2;
1617 if (tag == scriptTag) {
1618 /* found */
1619 break;
1622 if (i >= scriptCount) {
1623 /* not found */
1624 return 0;
1627 /* read script table */
1628 /* use default language system */
1629 pos = gsubTable+scriptList+scriptTable;
1630 langSys = 0;
1631 if (languageName) {
1632 Guint langTag = charToTag(languageName);
1633 Guint langCount = getU16BE(pos+2,&parsedOk);
1634 for (i = 0;i < langCount && langSys == 0;i++) {
1635 tag = getU32BE(pos+4+i*(4+2),&parsedOk);
1636 if (tag == langTag) {
1637 langSys = getU16BE(pos+4+i*(4+2)+4,&parsedOk);
1641 if (langSys == 0) {
1642 /* default language system */
1643 langSys = getU16BE(pos,&parsedOk);
1646 /* read LangSys table */
1647 if (langSys == 0) {
1648 /* no default LangSys */
1649 return 0;
1652 pos = gsubTable+scriptList+scriptTable+langSys+2;
1653 featureIndex = getU16BE(pos,&parsedOk); /* ReqFeatureIndex */
1654 pos += 2;
1656 if (featureIndex != 0xffff) {
1657 Guint tpos;
1658 /* read feature record */
1659 tpos = gsubTable+featureList;
1660 featureCount = getU16BE(tpos,&parsedOk);
1661 tpos = gsubTable+featureList+2+featureIndex*(4+2);
1662 tag = getU32BE(tpos,&parsedOk);
1663 tpos += 4;
1664 if (tag == vrt2Tag) {
1665 /* vrt2 is preferred, overwrite vert */
1666 ftable = getU16BE(tpos,&parsedOk);
1667 /* convert to offset from file top */
1668 gsubFeatureTable = ftable+gsubTable+featureList;
1669 return 0;
1670 } else if (tag == vertTag) {
1671 ftable = getU16BE(tpos,&parsedOk);
1674 featureCount = getU16BE(pos,&parsedOk);
1675 pos += 2;
1676 /* find 'vrt2' or 'vert' feature */
1677 for (i = 0;i < featureCount;i++) {
1678 Guint oldPos;
1680 featureIndex = getU16BE(pos,&parsedOk);
1681 pos += 2;
1682 oldPos = pos; /* save position */
1683 /* read feature record */
1684 pos = gsubTable+featureList+2+featureIndex*(4+2);
1685 tag = getU32BE(pos,&parsedOk);
1686 pos += 4;
1687 if (tag == vrt2Tag) {
1688 /* vrt2 is preferred, overwrite vert */
1689 ftable = getU16BE(pos,&parsedOk);
1690 break;
1691 } else if (ftable == 0 && tag == vertTag) {
1692 ftable = getU16BE(pos,&parsedOk);
1694 pos = oldPos; /* restore old position */
1696 if (ftable == 0) {
1697 /* vert nor vrt2 are not found */
1698 return 0;
1700 /* convert to offset from file top */
1701 gsubFeatureTable = ftable+gsubTable+featureList;
1702 return 0;
1705 Guint FoFiTrueType::doMapToVertGID(Guint orgGID)
1707 Guint lookupCount;
1708 Guint lookupListIndex;
1709 Guint i;
1710 Guint gid = 0;
1711 Guint pos;
1713 pos = gsubFeatureTable+2;
1714 lookupCount = getU16BE(pos,&parsedOk);
1715 pos += 2;
1716 for (i = 0;i < lookupCount;i++) {
1717 lookupListIndex = getU16BE(pos,&parsedOk);
1718 pos += 2;
1719 if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
1720 break;
1723 return gid;
1726 Guint FoFiTrueType::mapToVertGID(Guint orgGID)
1728 Guint mapped;
1730 if (gsubFeatureTable == 0) return orgGID;
1731 if ((mapped = doMapToVertGID(orgGID)) != 0) {
1732 return mapped;
1734 return orgGID;
1737 Guint FoFiTrueType::scanLookupList(Guint listIndex, Guint orgGID)
1739 Guint lookupTable;
1740 Guint subTableCount;
1741 Guint subTable;
1742 Guint i;
1743 Guint gid = 0;
1744 Guint pos;
1746 if (gsubLookupList == 0) return 0; /* no lookup list */
1747 pos = gsubLookupList+2+listIndex*2;
1748 lookupTable = getU16BE(pos,&parsedOk);
1749 /* read lookup table */
1750 pos = gsubLookupList+lookupTable+4;
1751 subTableCount = getU16BE(pos,&parsedOk);
1752 pos += 2;;
1753 for (i = 0;i < subTableCount;i++) {
1754 subTable = getU16BE(pos,&parsedOk);
1755 pos += 2;
1756 if ((gid = scanLookupSubTable(gsubLookupList+lookupTable+subTable,orgGID))
1757 != 0) break;
1759 return gid;
1762 Guint FoFiTrueType::scanLookupSubTable(Guint subTable, Guint orgGID)
1764 Guint format;
1765 Guint coverage;
1766 int delta;
1767 int glyphCount;
1768 Guint substitute;
1769 Guint gid = 0;
1770 int coverageIndex;
1771 int pos;
1773 pos = subTable;
1774 format = getU16BE(pos,&parsedOk);
1775 pos += 2;
1776 coverage = getU16BE(pos,&parsedOk);
1777 pos += 2;
1778 if ((coverageIndex =
1779 checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
1780 switch (format) {
1781 case 1:
1782 /* format 1 */
1783 delta = getS16BE(pos,&parsedOk);
1784 pos += 2;
1785 gid = orgGID+delta;
1786 break;
1787 case 2:
1788 /* format 2 */
1789 glyphCount = getS16BE(pos,&parsedOk);
1790 pos += 2;
1791 if (glyphCount > coverageIndex) {
1792 pos += coverageIndex*2;
1793 substitute = getU16BE(pos,&parsedOk);
1794 gid = substitute;
1796 break;
1797 default:
1798 /* unknown format */
1799 break;
1802 return gid;
1805 int FoFiTrueType::checkGIDInCoverage(Guint coverage, Guint orgGID)
1807 int index = -1;
1808 Guint format;
1809 Guint count;
1810 Guint i;
1811 Guint pos;
1813 pos = coverage;
1814 format = getU16BE(pos,&parsedOk);
1815 pos += 2;
1816 switch (format) {
1817 case 1:
1818 count = getU16BE(pos,&parsedOk);
1819 pos += 2;
1820 // In some poor CJK fonts, key GIDs are not sorted,
1821 // thus we cannot finish checking even when the range
1822 // including orgGID seems to have already passed.
1823 for (i = 0;i < count;i++) {
1824 Guint gid;
1826 gid = getU16BE(pos,&parsedOk);
1827 pos += 2;
1828 if (gid == orgGID) {
1829 /* found */
1830 index = i;
1831 break;
1834 break;
1835 case 2:
1836 count = getU16BE(pos,&parsedOk);
1837 pos += 2;
1838 for (i = 0;i < count;i++) {
1839 Guint startGID, endGID;
1840 Guint startIndex;
1842 startGID = getU16BE(pos,&parsedOk);
1843 pos += 2;
1844 endGID = getU16BE(pos,&parsedOk);
1845 pos += 2;
1846 startIndex = getU16BE(pos,&parsedOk);
1847 pos += 2;
1848 // In some poor CJK fonts, key GIDs are not sorted,
1849 // thus we cannot finish checking even when the range
1850 // including orgGID seems to have already passed.
1851 if (startGID <= orgGID && orgGID <= endGID) {
1852 /* found */
1853 index = startIndex+orgGID-startGID;
1854 break;
1857 break;
1858 default:
1859 break;
1861 return index;