1
//========================================================================
5
// Copyright 1999-2003 Glyph & Cog, LLC
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 Albert Astals Cid <aacid@kde.org>
20
// Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
22
// To see a description of the changes please see the Changelog file that
23
// came with your tarball or type make ChangeLog if you are building from git
25
//========================================================================
29
#ifdef USE_GCC_PRAGMAS
30
#pragma implementation
35
#include "goo/gtypes.h"
37
#include "goo/GooString.h"
38
#include "goo/GooHash.h"
39
#include "FoFiType1C.h"
40
#include "FoFiTrueType.h"
41
#include "poppler/Error.h"
47
// character code = number used as an element of a text string
49
// character name = glyph name = name for a particular glyph within a
52
// glyph index = GID = position (within some internal table in the font)
53
// where the instructions to draw a particular glyph are
59
// Type 1 fonts contain:
61
// Encoding: array of glyph names, maps char codes to glyph names
63
// Encoding[charCode] = charName
65
// CharStrings: dictionary of instructions, keyed by character names,
66
// maps character name to glyph data
68
// CharStrings[charName] = glyphData
73
// TrueType fonts contain:
75
// 'cmap' table: mapping from character code to glyph index; there may
76
// be multiple cmaps in a TrueType font
78
// cmap[charCode] = gid
80
// 'post' table: mapping from glyph index to glyph name
82
// post[gid] = glyphName
87
// Type 42 fonts contain:
89
// Encoding: array of glyph names, maps char codes to glyph names
91
// Encoding[charCode] = charName
93
// CharStrings: dictionary of glyph indexes, keyed by character names,
94
// maps character name to glyph index
96
// CharStrings[charName] = gid
99
//------------------------------------------------------------------------
101
#define ttcfTag 0x74746366
103
//------------------------------------------------------------------------
105
struct TrueTypeTable {
113
struct TrueTypeCmap {
121
struct TrueTypeLoca {
128
#define cmapTag 0x636d6170
129
#define glyfTag 0x676c7966
130
#define headTag 0x68656164
131
#define hheaTag 0x68686561
132
#define hmtxTag 0x686d7478
133
#define locaTag 0x6c6f6361
134
#define nameTag 0x6e616d65
135
#define os2Tag 0x4f532f32
136
#define postTag 0x706f7374
137
#define vrt2Tag 0x76727432
138
#define vertTag 0x76657274
140
static int cmpTrueTypeLocaOffset(const void *p1, const void *p2) {
141
TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
142
TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
144
if (loca1->origOffset == loca2->origOffset) {
145
return loca1->idx - loca2->idx;
147
return loca1->origOffset - loca2->origOffset;
150
static int cmpTrueTypeLocaIdx(const void *p1, const void *p2) {
151
TrueTypeLoca *loca1 = (TrueTypeLoca *)p1;
152
TrueTypeLoca *loca2 = (TrueTypeLoca *)p2;
154
return loca1->idx - loca2->idx;
157
static int cmpTrueTypeTableTag(const void *p1, const void *p2) {
158
TrueTypeTable *tab1 = (TrueTypeTable *)p1;
159
TrueTypeTable *tab2 = (TrueTypeTable *)p2;
161
return (int)tab1->tag - (int)tab2->tag;
164
//------------------------------------------------------------------------
167
char *tag; // 4-byte tag
168
GBool required; // required by the TrueType spec?
171
// TrueType tables to be embedded in Type 42 fonts.
172
// NB: the table names must be in alphabetical order here.
173
#define nT42Tables 11
174
static T42Table t42Tables[nT42Tables] = {
187
#define t42HeadTable 3
188
#define t42LocaTable 6
189
#define t42GlyfTable 2
190
#define t42VheaTable 9
191
#define t42VmtxTable 10
193
//------------------------------------------------------------------------
195
// Glyph names in some arbitrary standard order that Apple uses for
196
// their TrueType fonts.
197
static char *macGlyphNames[258] = {
198
".notdef", "null", "CR", "space",
199
"exclam", "quotedbl", "numbersign", "dollar",
200
"percent", "ampersand", "quotesingle", "parenleft",
201
"parenright", "asterisk", "plus", "comma",
202
"hyphen", "period", "slash", "zero",
203
"one", "two", "three", "four",
204
"five", "six", "seven", "eight",
205
"nine", "colon", "semicolon", "less",
206
"equal", "greater", "question", "at",
213
"Y", "Z", "bracketleft", "backslash",
214
"bracketright", "asciicircum", "underscore", "grave",
221
"y", "z", "braceleft", "bar",
222
"braceright", "asciitilde", "Adieresis", "Aring",
223
"Ccedilla", "Eacute", "Ntilde", "Odieresis",
224
"Udieresis", "aacute", "agrave", "acircumflex",
225
"adieresis", "atilde", "aring", "ccedilla",
226
"eacute", "egrave", "ecircumflex", "edieresis",
227
"iacute", "igrave", "icircumflex", "idieresis",
228
"ntilde", "oacute", "ograve", "ocircumflex",
229
"odieresis", "otilde", "uacute", "ugrave",
230
"ucircumflex", "udieresis", "dagger", "degree",
231
"cent", "sterling", "section", "bullet",
232
"paragraph", "germandbls", "registered", "copyright",
233
"trademark", "acute", "dieresis", "notequal",
234
"AE", "Oslash", "infinity", "plusminus",
235
"lessequal", "greaterequal", "yen", "mu1",
236
"partialdiff", "summation", "product", "pi",
237
"integral", "ordfeminine", "ordmasculine", "Ohm",
238
"ae", "oslash", "questiondown", "exclamdown",
239
"logicalnot", "radical", "florin", "approxequal",
240
"increment", "guillemotleft", "guillemotright", "ellipsis",
241
"nbspace", "Agrave", "Atilde", "Otilde",
242
"OE", "oe", "endash", "emdash",
243
"quotedblleft", "quotedblright", "quoteleft", "quoteright",
244
"divide", "lozenge", "ydieresis", "Ydieresis",
245
"fraction", "currency", "guilsinglleft", "guilsinglright",
246
"fi", "fl", "daggerdbl", "periodcentered",
247
"quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
248
"Ecircumflex", "Aacute", "Edieresis", "Egrave",
249
"Iacute", "Icircumflex", "Idieresis", "Igrave",
250
"Oacute", "Ocircumflex", "applelogo", "Ograve",
251
"Uacute", "Ucircumflex", "Ugrave", "dotlessi",
252
"circumflex", "tilde", "overscore", "breve",
253
"dotaccent", "ring", "cedilla", "hungarumlaut",
254
"ogonek", "caron", "Lslash", "lslash",
255
"Scaron", "scaron", "Zcaron", "zcaron",
256
"brokenbar", "Eth", "eth", "Yacute",
257
"yacute", "Thorn", "thorn", "minus",
258
"multiply", "onesuperior", "twosuperior", "threesuperior",
259
"onehalf", "onequarter", "threequarters", "franc",
260
"Gbreve", "gbreve", "Idot", "Scedilla",
261
"scedilla", "Cacute", "cacute", "Ccaron",
265
//------------------------------------------------------------------------
267
//------------------------------------------------------------------------
269
FoFiTrueType *FoFiTrueType::make(char *fileA, int lenA, int faceIndexA) {
272
ff = new FoFiTrueType(fileA, lenA, gFalse, faceIndexA);
280
FoFiTrueType *FoFiTrueType::load(char *fileName, int faceIndexA) {
285
if (!(fileA = FoFiBase::readFile(fileName, &lenA))) {
288
ff = new FoFiTrueType(fileA, lenA, gTrue, faceIndexA);
296
FoFiTrueType::FoFiTrueType(char *fileA, int lenA, GBool freeFileDataA, int faceIndexA):
297
FoFiBase(fileA, lenA, freeFileDataA)
305
faceIndex = faceIndexA;
306
gsubFeatureTable = 0;
312
FoFiTrueType::~FoFiTrueType() {
320
int FoFiTrueType::getNumCmaps() {
324
int FoFiTrueType::getCmapPlatform(int i) {
325
return cmaps[i].platform;
328
int FoFiTrueType::getCmapEncoding(int i) {
329
return cmaps[i].encoding;
332
int FoFiTrueType::findCmap(int platform, int encoding) {
335
for (i = 0; i < nCmaps; ++i) {
336
if (cmaps[i].platform == platform && cmaps[i].encoding == encoding) {
343
Gushort FoFiTrueType::mapCodeToGID(int i, Guint c) {
345
Guint segCnt, segEnd, segStart, segDelta, segOffset;
346
Guint cmapFirst, cmapLen;
350
if (i < 0 || i >= nCmaps) {
354
pos = cmaps[i].offset;
355
switch (cmaps[i].fmt) {
357
if (c + 6 >= (Guint)cmaps[i].len) {
360
gid = getU8(cmaps[i].offset + 6 + c, &ok);
363
segCnt = getU16BE(pos + 6, &ok) / 2;
366
segEnd = getU16BE(pos + 14 + 2*b, &ok);
368
// malformed font -- the TrueType spec requires the last segEnd
372
// invariant: seg[a].end < code <= seg[b].end
373
while (b - a > 1 && ok) {
375
segEnd = getU16BE(pos + 14 + 2*m, &ok);
382
segStart = getU16BE(pos + 16 + 2*segCnt + 2*b, &ok);
383
segDelta = getU16BE(pos + 16 + 4*segCnt + 2*b, &ok);
384
segOffset = getU16BE(pos + 16 + 6*segCnt + 2*b, &ok);
388
if (segOffset == 0) {
389
gid = (c + segDelta) & 0xffff;
391
gid = getU16BE(pos + 16 + 6*segCnt + 2*b +
392
segOffset + 2 * (c - segStart), &ok);
394
gid = (gid + segDelta) & 0xffff;
399
cmapFirst = getU16BE(pos + 6, &ok);
400
cmapLen = getU16BE(pos + 8, &ok);
401
if (c < cmapFirst || c >= cmapFirst + cmapLen) {
404
gid = getU16BE(pos + 10 + 2 * (c - cmapFirst), &ok);
407
segCnt = getU32BE(pos + 12, &ok);
410
segEnd = getU32BE(pos + 16 + 12*b+4, &ok);
414
// invariant: seg[a].end < code <= seg[b].end
415
while (b - a > 1 && ok) {
417
segEnd = getU32BE(pos + 16 + 12*m+4, &ok);
424
segStart = getU32BE(pos + 16 + 12*b, &ok);
425
segDelta = getU32BE(pos + 16 + 12*b+8, &ok);
429
gid = segDelta + (c-segStart);
440
int FoFiTrueType::mapNameToGID(char *name) {
444
return nameToGID->lookupInt(name);
447
Gushort *FoFiTrueType::getCIDToGIDMap(int *nCIDs) {
456
i = seekTable("CFF ");
457
if (!checkRegion(tables[i].offset, tables[i].len)) {
460
if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
464
map = ff->getCIDToGIDMap(nCIDs);
469
int FoFiTrueType::getEmbeddingRights() {
473
if ((i = seekTable("OS/2")) < 0) {
477
fsType = getU16BE(tables[i].offset + 8, &ok);
481
if (fsType & 0x0008) {
484
if (fsType & 0x0004) {
487
if (fsType & 0x0002) {
493
void FoFiTrueType::convertToType42(char *psName, char **encoding,
495
FoFiOutputFunc outputFunc,
496
void *outputStream) {
506
buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
507
(double)getS32BE(0, &ok) / 65536.0);
508
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
511
// begin the font dictionary
512
(*outputFunc)(outputStream, "10 dict begin\n", 14);
513
(*outputFunc)(outputStream, "/FontName /", 11);
514
(*outputFunc)(outputStream, psName, strlen(psName));
515
(*outputFunc)(outputStream, " def\n", 5);
516
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
517
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
518
buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
519
bbox[0], bbox[1], bbox[2], bbox[3]);
520
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
522
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
524
// write the guts of the dictionary
525
cvtEncoding(encoding, outputFunc, outputStream);
526
cvtCharStrings(encoding, codeToGID, outputFunc, outputStream);
527
cvtSfnts(outputFunc, outputStream, NULL, gFalse);
529
// end the dictionary and define the font
530
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
533
void FoFiTrueType::convertToType1(char *psName, char **newEncoding,
534
GBool ascii, FoFiOutputFunc outputFunc,
535
void *outputStream) {
542
i = seekTable("CFF ");
543
if (!checkRegion(tables[i].offset, tables[i].len)) {
546
if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
550
ff->convertToType1(psName, newEncoding, ascii, outputFunc, outputStream);
554
void FoFiTrueType::convertToCIDType2(char *psName,
555
Gushort *cidMap, int nCIDs,
556
GBool needVerticalMetrics,
557
FoFiOutputFunc outputFunc,
558
void *outputStream) {
570
buf = GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
571
(double)getS32BE(0, &ok) / 65536.0);
572
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
575
// begin the font dictionary
576
(*outputFunc)(outputStream, "20 dict begin\n", 14);
577
(*outputFunc)(outputStream, "/CIDFontName /", 14);
578
(*outputFunc)(outputStream, psName, strlen(psName));
579
(*outputFunc)(outputStream, " def\n", 5);
580
(*outputFunc)(outputStream, "/CIDFontType 2 def\n", 19);
581
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
582
(*outputFunc)(outputStream, "/CIDSystemInfo 3 dict dup begin\n", 32);
583
(*outputFunc)(outputStream, " /Registry (Adobe) def\n", 24);
584
(*outputFunc)(outputStream, " /Ordering (Identity) def\n", 27);
585
(*outputFunc)(outputStream, " /Supplement 0 def\n", 20);
586
(*outputFunc)(outputStream, " end def\n", 10);
587
(*outputFunc)(outputStream, "/GDBytes 2 def\n", 15);
589
buf = GooString::format("/CIDCount {0:d} def\n", nCIDs);
590
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
593
(*outputFunc)(outputStream, "/CIDMap [", 9);
594
for (i = 0; i < nCIDs; i += 32768 - 16) {
595
(*outputFunc)(outputStream, "<\n", 2);
596
for (j = 0; j < 32768 - 16 && i+j < nCIDs; j += 16) {
597
(*outputFunc)(outputStream, " ", 2);
598
for (k = 0; k < 16 && i+j+k < nCIDs; ++k) {
600
buf = GooString::format("{0:02x}{1:02x}",
601
(cid >> 8) & 0xff, cid & 0xff);
602
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
605
(*outputFunc)(outputStream, "\n", 1);
607
(*outputFunc)(outputStream, " >", 3);
609
(*outputFunc)(outputStream, "\n", 1);
610
(*outputFunc)(outputStream, "] def\n", 6);
612
(*outputFunc)(outputStream, "/CIDMap <\n", 10);
613
for (i = 0; i < nCIDs; i += 16) {
614
(*outputFunc)(outputStream, " ", 2);
615
for (j = 0; j < 16 && i+j < nCIDs; ++j) {
617
buf = GooString::format("{0:02x}{1:02x}",
618
(cid >> 8) & 0xff, cid & 0xff);
619
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
622
(*outputFunc)(outputStream, "\n", 1);
624
(*outputFunc)(outputStream, "> def\n", 6);
627
// direct mapping - just fill the string(s) with s[i]=i
628
buf = GooString::format("/CIDCount {0:d} def\n", nGlyphs);
629
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
631
if (nGlyphs > 32767) {
632
(*outputFunc)(outputStream, "/CIDMap [\n", 10);
633
for (i = 0; i < nGlyphs; i += 32767) {
634
j = nGlyphs - i < 32767 ? nGlyphs - i : 32767;
635
buf = GooString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j, j - 1);
636
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
638
buf = GooString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
640
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
642
buf = GooString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add"
643
" 255 and put\n", i);
644
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
646
(*outputFunc)(outputStream, " } for\n", 8);
648
(*outputFunc)(outputStream, "] def\n", 6);
650
buf = GooString::format("/CIDMap {0:d} string\n", 2 * nGlyphs);
651
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
653
buf = GooString::format(" 0 1 {0:d} {{\n", nGlyphs - 1);
654
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
656
(*outputFunc)(outputStream,
657
" 2 copy dup 2 mul exch -8 bitshift put\n", 42);
658
(*outputFunc)(outputStream,
659
" 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
660
(*outputFunc)(outputStream, " } for\n", 8);
661
(*outputFunc)(outputStream, "def\n", 4);
664
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
665
buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
666
bbox[0], bbox[1], bbox[2], bbox[3]);
667
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
669
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
670
(*outputFunc)(outputStream, "/Encoding [] readonly def\n", 26);
671
(*outputFunc)(outputStream, "/CharStrings 1 dict dup begin\n", 30);
672
(*outputFunc)(outputStream, " /.notdef 0 def\n", 17);
673
(*outputFunc)(outputStream, " end readonly def\n", 19);
675
// write the guts of the dictionary
676
cvtSfnts(outputFunc, outputStream, NULL, needVerticalMetrics);
678
// end the dictionary and define the font
679
(*outputFunc)(outputStream,
680
"CIDFontName currentdict end /CIDFont defineresource pop\n",
684
void FoFiTrueType::convertToCIDType0(char *psName,
685
FoFiOutputFunc outputFunc,
686
void *outputStream) {
693
i = seekTable("CFF ");
694
if (!checkRegion(tables[i].offset, tables[i].len)) {
697
if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
701
ff->convertToCIDType0(psName, outputFunc, outputStream);
705
void FoFiTrueType::convertToType0(char *psName, Gushort *cidMap, int nCIDs,
706
GBool needVerticalMetrics,
707
FoFiOutputFunc outputFunc,
708
void *outputStream) {
710
GooString *sfntsName;
717
// write the Type 42 sfnts array
718
sfntsName = (new GooString(psName))->append("_sfnts");
719
cvtSfnts(outputFunc, outputStream, sfntsName, needVerticalMetrics);
722
// write the descendant Type 42 fonts
723
n = cidMap ? nCIDs : nGlyphs;
724
for (i = 0; i < n; i += 256) {
725
(*outputFunc)(outputStream, "10 dict begin\n", 14);
726
(*outputFunc)(outputStream, "/FontName /", 11);
727
(*outputFunc)(outputStream, psName, strlen(psName));
728
buf = GooString::format("_{0:02x} def\n", i >> 8);
729
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
731
(*outputFunc)(outputStream, "/FontType 42 def\n", 17);
732
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
733
buf = GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
734
bbox[0], bbox[1], bbox[2], bbox[3]);
735
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
737
(*outputFunc)(outputStream, "/PaintType 0 def\n", 17);
738
(*outputFunc)(outputStream, "/sfnts ", 7);
739
(*outputFunc)(outputStream, psName, strlen(psName));
740
(*outputFunc)(outputStream, "_sfnts def\n", 11);
741
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
742
for (j = 0; j < 256 && i+j < n; ++j) {
743
buf = GooString::format("dup {0:d} /c{1:02x} put\n", j, j);
744
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
747
(*outputFunc)(outputStream, "readonly def\n", 13);
748
(*outputFunc)(outputStream, "/CharStrings 257 dict dup begin\n", 32);
749
(*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
750
for (j = 0; j < 256 && i+j < n; ++j) {
751
buf = GooString::format("/c{0:02x} {1:d} def\n",
752
j, cidMap ? cidMap[i+j] : i+j);
753
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
756
(*outputFunc)(outputStream, "end readonly def\n", 17);
757
(*outputFunc)(outputStream,
758
"FontName currentdict end definefont pop\n", 40);
761
// write the Type 0 parent font
762
(*outputFunc)(outputStream, "16 dict begin\n", 14);
763
(*outputFunc)(outputStream, "/FontName /", 11);
764
(*outputFunc)(outputStream, psName, strlen(psName));
765
(*outputFunc)(outputStream, " def\n", 5);
766
(*outputFunc)(outputStream, "/FontType 0 def\n", 16);
767
(*outputFunc)(outputStream, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
768
(*outputFunc)(outputStream, "/FMapType 2 def\n", 16);
769
(*outputFunc)(outputStream, "/Encoding [\n", 12);
770
for (i = 0; i < n; i += 256) {
771
buf = GooString::format("{0:d}\n", i >> 8);
772
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
775
(*outputFunc)(outputStream, "] def\n", 6);
776
(*outputFunc)(outputStream, "/FDepVector [\n", 14);
777
for (i = 0; i < n; i += 256) {
778
(*outputFunc)(outputStream, "/", 1);
779
(*outputFunc)(outputStream, psName, strlen(psName));
780
buf = GooString::format("_{0:02x} findfont\n", i >> 8);
781
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
784
(*outputFunc)(outputStream, "] def\n", 6);
785
(*outputFunc)(outputStream, "FontName currentdict end definefont pop\n", 40);
788
void FoFiTrueType::convertToType0(char *psName,
789
FoFiOutputFunc outputFunc,
790
void *outputStream) {
797
i = seekTable("CFF ");
798
if (!checkRegion(tables[i].offset, tables[i].len)) {
801
if (!(ff = FoFiType1C::make((char *)file + tables[i].offset,
805
ff->convertToType0(psName, outputFunc, outputStream);
809
void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc,
810
void *outputStream, char *name,
811
Gushort *codeToGID) {
812
// this substitute cmap table maps char codes 0000-ffff directly to
814
static char cmapTab[36] = {
815
0, 0, // table version number
816
0, 1, // number of encoding tables
819
0, 0, 0, 12, // offset of subtable
820
0, 4, // subtable format
821
0, 24, // subtable length
822
0, 0, // subtable version
823
0, 2, // segment count * 2
824
0, 2, // 2 * 2 ^ floor(log2(segCount))
825
0, 0, // floor(log2(segCount))
826
0, 0, // 2*segCount - 2*2^floor(log2(segCount))
827
(char)0xff, (char)0xff, // endCount[0]
829
0, 0, // startCount[0]
831
0, 0 // pad to a mulitple of four bytes
833
static char nameTab[8] = {
835
0, 0, // number of name records
836
0, 6, // offset to start of string storage
837
0, 0 // pad to multiple of four bytes
839
static char postTab[32] = {
840
0, 1, 0, 0, // format
841
0, 0, 0, 0, // italic angle
842
0, 0, // underline position
843
0, 0, // underline thickness
844
0, 0, 0, 0, // fixed pitch
845
0, 0, 0, 0, // min Type 42 memory
846
0, 0, 0, 0, // max Type 42 memory
847
0, 0, 0, 0, // min Type 1 memory
848
0, 0, 0, 0 // max Type 1 memory
850
static char os2Tab[86] = {
852
0, 1, // xAvgCharWidth
853
0, 0, // usWeightClass
854
0, 0, // usWidthClass
856
0, 0, // ySubscriptXSize
857
0, 0, // ySubscriptYSize
858
0, 0, // ySubscriptXOffset
859
0, 0, // ySubscriptYOffset
860
0, 0, // ySuperscriptXSize
861
0, 0, // ySuperscriptYSize
862
0, 0, // ySuperscriptXOffset
863
0, 0, // ySuperscriptYOffset
864
0, 0, // yStrikeoutSize
865
0, 0, // yStrikeoutPosition
866
0, 0, // sFamilyClass
867
0, 0, 0, 0, 0, // panose
869
0, 0, 0, 0, // ulUnicodeRange1
870
0, 0, 0, 0, // ulUnicodeRange2
871
0, 0, 0, 0, // ulUnicodeRange3
872
0, 0, 0, 0, // ulUnicodeRange4
873
0, 0, 0, 0, // achVendID
875
0, 0, // usFirstCharIndex
876
0, 0, // usLastCharIndex
877
0, 0, // sTypoAscender
878
0, 0, // sTypoDescender
879
0, 0, // sTypoLineGap
881
0, 0, // usWinDescent
882
0, 0, 0, 0, // ulCodePageRange1
883
0, 0, 0, 0 // ulCodePageRange2
885
GBool missingCmap, missingName, missingPost, missingOS2;
886
GBool unsortedLoca, badCmapLen, abbrevHMTX;
887
int nZeroLengthTables;
888
int nHMetrics, advWidth, lsb;
889
TrueTypeLoca *locaTable;
890
TrueTypeTable *newTables;
891
char *newNameTab, *newCmapTab, *newHHEATab, *newHMTXTab;
892
int nNewTables, cmapIdx, cmapLen, glyfLen, newNameLen, newCmapLen, next;
893
int newHHEALen, newHMTXLen;
894
Guint locaChecksum, glyfChecksum, fileChecksum;
896
char locaBuf[4], checksumBuf[4];
905
if (tables == NULL) {
909
// check for missing tables
910
// (Note: if the OS/2 table is missing, the Microsoft PCL5 driver
911
// will embed a PCL TrueType font with the pitch field set to zero,
912
// which apparently causes divide-by-zero errors. As far as I can
913
// tell, the only important field in the OS/2 table is
915
missingCmap = (cmapIdx = seekTable("cmap")) < 0;
916
missingName = seekTable("name") < 0;
917
missingPost = seekTable("post") < 0;
918
missingOS2 = seekTable("OS/2") < 0;
920
// read the loca table, check to see if it's sorted
921
locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
922
unsortedLoca = gFalse;
923
i = seekTable("loca");
924
pos = tables[i].offset;
926
for (i = 0; i <= nGlyphs; ++i) {
928
locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
930
locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
932
if (i > 0 && locaTable[i].origOffset < locaTable[i-1].origOffset) {
933
unsortedLoca = gTrue;
935
// glyph descriptions must be at least 12 bytes long (nContours,
936
// xMin, yMin, xMax, yMax, instructionLength - two bytes each);
937
// invalid glyph descriptions (even if they're never used) make
938
// Windows choke, so we work around that problem here (ideally,
939
// this would parse the glyph descriptions in the glyf table and
940
// remove any that were invalid, but this quick test is a decent
943
locaTable[i].origOffset - locaTable[i-1].origOffset > 0 &&
944
locaTable[i].origOffset - locaTable[i-1].origOffset < 12) {
945
locaTable[i-1].origOffset = locaTable[i].origOffset;
946
unsortedLoca = gTrue;
948
locaTable[i].idx = i;
951
// check for zero-length tables
952
nZeroLengthTables = 0;
953
for (i = 0; i < nTables; ++i) {
954
if (tables[i].len == 0) {
959
// check for an incorrect cmap table length
961
cmapLen = 0; // make gcc happy
964
cmapLen = cmaps[0].offset + cmaps[0].len;
965
for (i = 1; i < nCmaps; ++i) {
966
if (cmaps[i].offset + cmaps[i].len > cmapLen) {
967
cmapLen = cmaps[i].offset + cmaps[i].len;
971
cmapLen -= tables[cmapIdx].offset;
972
if (cmapLen > tables[cmapIdx].len) {
977
// check for an abbreviated hmtx table (this is completely legal,
978
// but confuses the Microsoft PCL5 printer driver, which generates
979
// embedded fonts with the pitch field set to zero)
980
i = seekTable("hhea");
981
nHMetrics = getU16BE(tables[i].offset + 34, &ok);
982
abbrevHMTX = nHMetrics < nGlyphs;
984
// if nothing is broken, just write the TTF file as is
985
if (!missingCmap && !missingName && !missingPost && !missingOS2 &&
986
!unsortedLoca && !badCmapLen && !abbrevHMTX && nZeroLengthTables == 0 &&
987
!name && !codeToGID) {
988
(*outputFunc)(outputStream, (char *)file, len);
992
// sort the 'loca' table: some (non-compliant) fonts have
993
// out-of-order loca tables; in order to correctly handle the case
994
// where (compliant) fonts have empty entries in the middle of the
995
// table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
996
// and idx as its secondary key (ensuring that adjacent entries with
997
// the same pos value remain in the same order)
998
glyfLen = 0; // make gcc happy
1000
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1001
&cmpTrueTypeLocaOffset);
1002
for (i = 0; i < nGlyphs; ++i) {
1003
locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
1005
locaTable[nGlyphs].len = 0;
1006
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1007
&cmpTrueTypeLocaIdx);
1009
for (i = 0; i <= nGlyphs; ++i) {
1010
locaTable[i].newOffset = pos;
1011
pos += locaTable[i].len;
1013
pos += 4 - (pos & 3);
1019
// compute checksums for the loca and glyf tables
1020
locaChecksum = glyfChecksum = 0;
1023
for (j = 0; j <= nGlyphs; ++j) {
1024
locaChecksum += locaTable[j].newOffset;
1027
for (j = 0; j <= nGlyphs; j += 2) {
1028
locaChecksum += locaTable[j].newOffset << 16;
1029
if (j + 1 <= nGlyphs) {
1030
locaChecksum += locaTable[j+1].newOffset;
1034
pos = tables[seekTable("glyf")].offset;
1035
for (j = 0; j < nGlyphs; ++j) {
1036
n = locaTable[j].len;
1038
k = locaTable[j].origOffset;
1039
if (checkRegion(pos + k, n)) {
1040
glyfChecksum += computeTableChecksum(file + pos + k, n);
1046
// construct the new name table
1049
newNameLen = (6 + 4*12 + 2 * (3*n + 7) + 3) & ~3;
1050
newNameTab = (char *)gmalloc(newNameLen);
1051
memset(newNameTab, 0, newNameLen);
1052
newNameTab[0] = 0; // format selector
1054
newNameTab[2] = 0; // number of name records
1056
newNameTab[4] = 0; // offset to start of string storage
1057
newNameTab[5] = 6 + 4*12;
1059
for (i = 0; i < 4; ++i) {
1060
newNameTab[6 + i*12 + 0] = 0; // platform ID = Microsoft
1061
newNameTab[6 + i*12 + 1] = 3;
1062
newNameTab[6 + i*12 + 2] = 0; // encoding ID = Unicode
1063
newNameTab[6 + i*12 + 3] = 1;
1064
newNameTab[6 + i*12 + 4] = 0x04; // language ID = American English
1065
newNameTab[6 + i*12 + 5] = 0x09;
1066
newNameTab[6 + i*12 + 6] = 0; // name ID
1067
newNameTab[6 + i*12 + 7] = i + 1;
1068
newNameTab[6 + i*12 + 8] = i+1 == 2 ? 0 : ((2*n) >> 8); // string length
1069
newNameTab[6 + i*12 + 9] = i+1 == 2 ? 14 : ((2*n) & 0xff);
1070
newNameTab[6 + i*12 + 10] = next >> 8; // string offset
1071
newNameTab[6 + i*12 + 11] = next & 0xff;
1073
memcpy(newNameTab + 6 + 4*12 + next, "\0R\0e\0g\0u\0l\0a\0r", 14);
1076
for (j = 0; j < n; ++j) {
1077
newNameTab[6 + 4*12 + next + 2*j] = 0;
1078
newNameTab[6 + 4*12 + next + 2*j + 1] = name[j];
1088
// construct the new cmap table
1090
newCmapLen = 44 + 256 * 2;
1091
newCmapTab = (char *)gmalloc(newCmapLen);
1092
newCmapTab[0] = 0; // table version number = 0
1094
newCmapTab[2] = 0; // number of encoding tables = 1
1096
newCmapTab[4] = 0; // platform ID = Microsoft
1098
newCmapTab[6] = 0; // encoding ID = Unicode
1100
newCmapTab[8] = 0; // offset of subtable
1103
newCmapTab[11] = 12;
1104
newCmapTab[12] = 0; // subtable format = 4
1106
newCmapTab[14] = 0x02; // subtable length
1107
newCmapTab[15] = 0x20;
1108
newCmapTab[16] = 0; // subtable version = 0
1110
newCmapTab[18] = 0; // segment count * 2
1112
newCmapTab[20] = 0; // 2 * 2 ^ floor(log2(segCount))
1114
newCmapTab[22] = 0; // floor(log2(segCount))
1116
newCmapTab[24] = 0; // 2*segCount - 2*2^floor(log2(segCount))
1118
newCmapTab[26] = 0x00; // endCount[0]
1119
newCmapTab[27] = (char)0xff;
1120
newCmapTab[28] = (char)0xff; // endCount[1]
1121
newCmapTab[29] = (char)0xff;
1122
newCmapTab[30] = 0; // reserved
1124
newCmapTab[32] = 0x00; // startCount[0]
1125
newCmapTab[33] = 0x00;
1126
newCmapTab[34] = (char)0xff; // startCount[1]
1127
newCmapTab[35] = (char)0xff;
1128
newCmapTab[36] = 0; // idDelta[0]
1130
newCmapTab[38] = 0; // idDelta[1]
1132
newCmapTab[40] = 0; // idRangeOffset[0]
1134
newCmapTab[42] = 0; // idRangeOffset[1]
1136
for (i = 0; i < 256; ++i) {
1137
newCmapTab[44 + 2*i] = codeToGID[i] >> 8;
1138
newCmapTab[44 + 2*i + 1] = codeToGID[i] & 0xff;
1145
// generate the new hmtx table and the updated hhea table
1147
i = seekTable("hhea");
1148
pos = tables[i].offset;
1150
newHHEATab = (char *)gmalloc(newHHEALen);
1151
for (i = 0; i < newHHEALen; ++i) {
1152
newHHEATab[i] = getU8(pos++, &ok);
1154
newHHEATab[34] = nGlyphs >> 8;
1155
newHHEATab[35] = nGlyphs & 0xff;
1156
i = seekTable("hmtx");
1157
pos = tables[i].offset;
1158
newHMTXLen = 4 * nGlyphs;
1159
newHMTXTab = (char *)gmalloc(newHMTXLen);
1161
for (i = 0; i < nHMetrics; ++i) {
1162
advWidth = getU16BE(pos, &ok);
1163
lsb = getU16BE(pos + 2, &ok);
1165
newHMTXTab[4*i ] = advWidth >> 8;
1166
newHMTXTab[4*i + 1] = advWidth & 0xff;
1167
newHMTXTab[4*i + 2] = lsb >> 8;
1168
newHMTXTab[4*i + 3] = lsb & 0xff;
1170
for (; i < nGlyphs; ++i) {
1171
lsb = getU16BE(pos, &ok);
1173
newHMTXTab[4*i ] = advWidth >> 8;
1174
newHMTXTab[4*i + 1] = advWidth & 0xff;
1175
newHMTXTab[4*i + 2] = lsb >> 8;
1176
newHMTXTab[4*i + 3] = lsb & 0xff;
1179
newHHEATab = newHMTXTab = NULL;
1180
newHHEALen = newHMTXLen = 0; // make gcc happy
1183
// construct the new table directory:
1184
// - keep all original tables with non-zero length
1185
// - fix the cmap table's length, if necessary
1186
// - add missing tables
1187
// - sort the table by tag
1188
// - compute new table positions, including 4-byte alignment
1189
// - (re)compute table checksums
1190
nNewTables = nTables - nZeroLengthTables +
1191
(missingCmap ? 1 : 0) + (missingName ? 1 : 0) +
1192
(missingPost ? 1 : 0) + (missingOS2 ? 1 : 0);
1193
newTables = (TrueTypeTable *)gmallocn(nNewTables, sizeof(TrueTypeTable));
1195
for (i = 0; i < nTables; ++i) {
1196
if (tables[i].len > 0) {
1197
newTables[j] = tables[i];
1198
newTables[j].origOffset = tables[i].offset;
1199
if (checkRegion(tables[i].offset, newTables[i].len)) {
1200
newTables[j].checksum =
1201
computeTableChecksum(file + tables[i].offset, tables[i].len);
1202
if (tables[i].tag == headTag) {
1203
// don't include the file checksum
1204
newTables[j].checksum -= getU32BE(tables[i].offset + 8, &ok);
1207
if (newTables[j].tag == cmapTag && codeToGID) {
1208
newTables[j].len = newCmapLen;
1209
newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
1211
} else if (newTables[j].tag == cmapTag && badCmapLen) {
1212
newTables[j].len = cmapLen;
1213
} else if (newTables[j].tag == locaTag && unsortedLoca) {
1214
newTables[j].len = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1215
newTables[j].checksum = locaChecksum;
1216
} else if (newTables[j].tag == glyfTag && unsortedLoca) {
1217
newTables[j].len = glyfLen;
1218
newTables[j].checksum = glyfChecksum;
1219
} else if (newTables[j].tag == nameTag && name) {
1220
newTables[j].len = newNameLen;
1221
newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
1223
} else if (newTables[j].tag == hheaTag && abbrevHMTX) {
1224
newTables[j].len = newHHEALen;
1225
newTables[j].checksum = computeTableChecksum((Guchar *)newHHEATab,
1227
} else if (newTables[j].tag == hmtxTag && abbrevHMTX) {
1228
newTables[j].len = newHMTXLen;
1229
newTables[j].checksum = computeTableChecksum((Guchar *)newHMTXTab,
1236
newTables[j].tag = cmapTag;
1238
newTables[j].checksum = computeTableChecksum((Guchar *)newCmapTab,
1240
newTables[j].len = newCmapLen;
1242
newTables[j].checksum = computeTableChecksum((Guchar *)cmapTab,
1244
newTables[j].len = sizeof(cmapTab);
1249
newTables[j].tag = nameTag;
1251
newTables[j].checksum = computeTableChecksum((Guchar *)newNameTab,
1253
newTables[j].len = newNameLen;
1255
newTables[j].checksum = computeTableChecksum((Guchar *)nameTab,
1257
newTables[j].len = sizeof(nameTab);
1262
newTables[j].tag = postTag;
1263
newTables[j].checksum = computeTableChecksum((Guchar *)postTab,
1265
newTables[j].len = sizeof(postTab);
1269
newTables[j].tag = os2Tag;
1270
newTables[j].checksum = computeTableChecksum((Guchar *)os2Tab,
1272
newTables[j].len = sizeof(os2Tab);
1275
qsort(newTables, nNewTables, sizeof(TrueTypeTable),
1276
&cmpTrueTypeTableTag);
1277
pos = 12 + nNewTables * 16;
1278
for (i = 0; i < nNewTables; ++i) {
1279
newTables[i].offset = pos;
1280
pos += newTables[i].len;
1282
pos += 4 - (pos & 3);
1286
// write the table directory
1287
tableDir = (char *)gmalloc(12 + nNewTables * 16);
1288
tableDir[0] = 0x00; // sfnt version
1292
tableDir[4] = (char)((nNewTables >> 8) & 0xff); // numTables
1293
tableDir[5] = (char)(nNewTables & 0xff);
1294
for (i = -1, t = (Guint)nNewTables; t; ++i, t >>= 1) ;
1296
tableDir[6] = (char)((t >> 8) & 0xff); // searchRange
1297
tableDir[7] = (char)(t & 0xff);
1298
tableDir[8] = (char)((i >> 8) & 0xff); // entrySelector
1299
tableDir[9] = (char)(i & 0xff);
1300
t = nNewTables * 16 - t;
1301
tableDir[10] = (char)((t >> 8) & 0xff); // rangeShift
1302
tableDir[11] = (char)(t & 0xff);
1304
for (i = 0; i < nNewTables; ++i) {
1305
tableDir[pos ] = (char)(newTables[i].tag >> 24);
1306
tableDir[pos+ 1] = (char)(newTables[i].tag >> 16);
1307
tableDir[pos+ 2] = (char)(newTables[i].tag >> 8);
1308
tableDir[pos+ 3] = (char) newTables[i].tag;
1309
tableDir[pos+ 4] = (char)(newTables[i].checksum >> 24);
1310
tableDir[pos+ 5] = (char)(newTables[i].checksum >> 16);
1311
tableDir[pos+ 6] = (char)(newTables[i].checksum >> 8);
1312
tableDir[pos+ 7] = (char) newTables[i].checksum;
1313
tableDir[pos+ 8] = (char)(newTables[i].offset >> 24);
1314
tableDir[pos+ 9] = (char)(newTables[i].offset >> 16);
1315
tableDir[pos+10] = (char)(newTables[i].offset >> 8);
1316
tableDir[pos+11] = (char) newTables[i].offset;
1317
tableDir[pos+12] = (char)(newTables[i].len >> 24);
1318
tableDir[pos+13] = (char)(newTables[i].len >> 16);
1319
tableDir[pos+14] = (char)(newTables[i].len >> 8);
1320
tableDir[pos+15] = (char) newTables[i].len;
1323
(*outputFunc)(outputStream, tableDir, 12 + nNewTables * 16);
1325
// compute the file checksum
1326
fileChecksum = computeTableChecksum((Guchar *)tableDir,
1327
12 + nNewTables * 16);
1328
for (i = 0; i < nNewTables; ++i) {
1329
fileChecksum += newTables[i].checksum;
1331
fileChecksum = 0xb1b0afba - fileChecksum;
1334
for (i = 0; i < nNewTables; ++i) {
1335
if (newTables[i].tag == headTag) {
1336
if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
1337
(*outputFunc)(outputStream, (char *)file + newTables[i].origOffset, 8);
1338
checksumBuf[0] = fileChecksum >> 24;
1339
checksumBuf[1] = fileChecksum >> 16;
1340
checksumBuf[2] = fileChecksum >> 8;
1341
checksumBuf[3] = fileChecksum;
1342
(*outputFunc)(outputStream, checksumBuf, 4);
1343
(*outputFunc)(outputStream,
1344
(char *)file + newTables[i].origOffset + 12,
1345
newTables[i].len - 12);
1347
for (j = 0; j < newTables[i].len; ++j) {
1348
(*outputFunc)(outputStream, "\0", 1);
1351
} else if (newTables[i].tag == cmapTag && codeToGID) {
1352
(*outputFunc)(outputStream, newCmapTab, newTables[i].len);
1353
} else if (newTables[i].tag == cmapTag && missingCmap) {
1354
(*outputFunc)(outputStream, cmapTab, newTables[i].len);
1355
} else if (newTables[i].tag == nameTag && name) {
1356
(*outputFunc)(outputStream, newNameTab, newTables[i].len);
1357
} else if (newTables[i].tag == nameTag && missingName) {
1358
(*outputFunc)(outputStream, nameTab, newTables[i].len);
1359
} else if (newTables[i].tag == postTag && missingPost) {
1360
(*outputFunc)(outputStream, postTab, newTables[i].len);
1361
} else if (newTables[i].tag == os2Tag && missingOS2) {
1362
(*outputFunc)(outputStream, os2Tab, newTables[i].len);
1363
} else if (newTables[i].tag == hheaTag && abbrevHMTX) {
1364
(*outputFunc)(outputStream, newHHEATab, newTables[i].len);
1365
} else if (newTables[i].tag == hmtxTag && abbrevHMTX) {
1366
(*outputFunc)(outputStream, newHMTXTab, newTables[i].len);
1367
} else if (newTables[i].tag == locaTag && unsortedLoca) {
1368
for (j = 0; j <= nGlyphs; ++j) {
1370
locaBuf[0] = (char)(locaTable[j].newOffset >> 24);
1371
locaBuf[1] = (char)(locaTable[j].newOffset >> 16);
1372
locaBuf[2] = (char)(locaTable[j].newOffset >> 8);
1373
locaBuf[3] = (char) locaTable[j].newOffset;
1374
(*outputFunc)(outputStream, locaBuf, 4);
1376
locaBuf[0] = (char)(locaTable[j].newOffset >> 9);
1377
locaBuf[1] = (char)(locaTable[j].newOffset >> 1);
1378
(*outputFunc)(outputStream, locaBuf, 2);
1381
} else if (newTables[i].tag == glyfTag && unsortedLoca) {
1382
pos = tables[seekTable("glyf")].offset;
1383
for (j = 0; j < nGlyphs; ++j) {
1384
n = locaTable[j].len;
1386
k = locaTable[j].origOffset;
1387
if (checkRegion(pos + k, n)) {
1388
(*outputFunc)(outputStream, (char *)file + pos + k, n);
1390
for (k = 0; k < n; ++k) {
1391
(*outputFunc)(outputStream, "\0", 1);
1394
if ((k = locaTable[j].len & 3)) {
1395
(*outputFunc)(outputStream, "\0\0\0\0", 4 - k);
1400
if (checkRegion(newTables[i].origOffset, newTables[i].len)) {
1401
(*outputFunc)(outputStream, (char *)file + newTables[i].origOffset,
1404
for (j = 0; j < newTables[i].len; ++j) {
1405
(*outputFunc)(outputStream, "\0", 1);
1409
if (newTables[i].len & 3) {
1410
(*outputFunc)(outputStream, "\0\0\0", 4 - (newTables[i].len & 3));
1424
void FoFiTrueType::cvtEncoding(char **encoding,
1425
FoFiOutputFunc outputFunc,
1426
void *outputStream) {
1431
(*outputFunc)(outputStream, "/Encoding 256 array\n", 20);
1433
for (i = 0; i < 256; ++i) {
1434
if (!(name = encoding[i])) {
1437
buf = GooString::format("dup {0:d} /", i);
1438
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1440
(*outputFunc)(outputStream, name, strlen(name));
1441
(*outputFunc)(outputStream, " put\n", 5);
1444
for (i = 0; i < 256; ++i) {
1445
buf = GooString::format("dup {0:d} /c{1:02x} put\n", i, i);
1446
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1450
(*outputFunc)(outputStream, "readonly def\n", 13);
1453
void FoFiTrueType::cvtCharStrings(char **encoding,
1455
FoFiOutputFunc outputFunc,
1456
void *outputStream) {
1462
// always define '.notdef'
1463
(*outputFunc)(outputStream, "/CharStrings 256 dict dup begin\n", 32);
1464
(*outputFunc)(outputStream, "/.notdef 0 def\n", 15);
1466
// if there's no 'cmap' table, punt
1471
// map char name to glyph index:
1472
// 1. use encoding to map name to char code
1473
// 2. use codeToGID to map char code to glyph index
1474
// N.B. We do this in reverse order because font subsets can have
1475
// weird encodings that use the same character name twice, and
1476
// the first definition is probably the one we want.
1477
k = 0; // make gcc happy
1478
for (i = 255; i >= 0; --i) {
1482
sprintf(buf2, "c%02x", i);
1485
if (name && strcmp(name, ".notdef")) {
1487
// note: Distiller (maybe Adobe's PS interpreter in general)
1488
// doesn't like TrueType fonts that have CharStrings entries
1489
// which point to nonexistent glyphs, hence the (k < nGlyphs)
1491
if (k > 0 && k < nGlyphs) {
1492
(*outputFunc)(outputStream, "/", 1);
1493
(*outputFunc)(outputStream, name, strlen(name));
1494
buf = GooString::format(" {0:d} def\n", k);
1495
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1502
(*outputFunc)(outputStream, "end readonly def\n", 17);
1505
void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc,
1506
void *outputStream, GooString *name,
1507
GBool needVerticalMetrics) {
1508
Guchar headData[54];
1509
TrueTypeLoca *locaTable;
1511
TrueTypeTable newTables[nT42Tables];
1512
Guchar tableDir[12 + nT42Tables*16];
1516
int length, pos, glyfPos, i, j, k;
1517
Guchar vheaTab[36] = {
1518
0, 1, 0, 0, // table version number
1522
0, 0, // max advance height
1523
0, 0, // min top side bearing
1524
0, 0, // min bottom side bearing
1525
0, 0, // y max extent
1526
0, 0, // caret slope rise
1527
0, 1, // caret slope run
1528
0, 0, // caret offset
1533
0, 0, // metric data format
1534
0, 1 // number of advance heights in vmtx table
1537
GBool needVhea, needVmtx;
1540
// construct the 'head' table, zero out the font checksum
1541
i = seekTable("head");
1542
if (i < 0 || i >= nTables) {
1545
pos = tables[i].offset;
1546
if (!checkRegion(pos, 54)) {
1549
memcpy(headData, file + pos, 54);
1550
headData[8] = headData[9] = headData[10] = headData[11] = (Guchar)0;
1552
// read the original 'loca' table, pad entries out to 4 bytes, and
1553
// sort it into proper order -- some (non-compliant) fonts have
1554
// out-of-order loca tables; in order to correctly handle the case
1555
// where (compliant) fonts have empty entries in the middle of the
1556
// table, cmpTrueTypeLocaPos uses offset as its primary sort key,
1557
// and idx as its secondary key (ensuring that adjacent entries with
1558
// the same pos value remain in the same order)
1559
locaTable = (TrueTypeLoca *)gmallocn(nGlyphs + 1, sizeof(TrueTypeLoca));
1560
i = seekTable("loca");
1561
pos = tables[i].offset;
1563
for (i = 0; i <= nGlyphs; ++i) {
1564
locaTable[i].idx = i;
1566
locaTable[i].origOffset = (int)getU32BE(pos + i*4, &ok);
1568
locaTable[i].origOffset = 2 * getU16BE(pos + i*2, &ok);
1571
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1572
&cmpTrueTypeLocaOffset);
1573
for (i = 0; i < nGlyphs; ++i) {
1574
locaTable[i].len = locaTable[i+1].origOffset - locaTable[i].origOffset;
1576
locaTable[nGlyphs].len = 0;
1577
qsort(locaTable, nGlyphs + 1, sizeof(TrueTypeLoca),
1578
&cmpTrueTypeLocaIdx);
1580
for (i = 0; i <= nGlyphs; ++i) {
1581
locaTable[i].newOffset = pos;
1582
pos += locaTable[i].len;
1584
pos += 4 - (pos & 3);
1588
// construct the new 'loca' table
1589
locaData = (Guchar *)gmallocn(nGlyphs + 1, (locaFmt ? 4 : 2));
1590
for (i = 0; i <= nGlyphs; ++i) {
1591
pos = locaTable[i].newOffset;
1593
locaData[4*i ] = (Guchar)(pos >> 24);
1594
locaData[4*i+1] = (Guchar)(pos >> 16);
1595
locaData[4*i+2] = (Guchar)(pos >> 8);
1596
locaData[4*i+3] = (Guchar) pos;
1598
locaData[2*i ] = (Guchar)(pos >> 9);
1599
locaData[2*i+1] = (Guchar)(pos >> 1);
1603
// count the number of tables
1605
for (i = 0; i < nT42Tables; ++i) {
1606
if (t42Tables[i].required ||
1607
seekTable(t42Tables[i].tag) >= 0) {
1611
vmtxTab = NULL; // make gcc happy
1612
advance = 0; // make gcc happy
1613
if (needVerticalMetrics) {
1614
needVhea = seekTable("vhea") < 0;
1615
needVmtx = seekTable("vmtx") < 0;
1616
if (needVhea || needVmtx) {
1617
i = seekTable("head");
1618
advance = getU16BE(tables[i].offset + 18, &ok); // units per em
1628
// construct the new table headers, including table checksums
1629
// (pad each table out to a multiple of 4 bytes)
1630
pos = 12 + nNewTables*16;
1632
for (i = 0; i < nT42Tables; ++i) {
1634
checksum = 0; // make gcc happy
1635
if (i == t42HeadTable) {
1637
checksum = computeTableChecksum(headData, 54);
1638
} else if (i == t42LocaTable) {
1639
length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1640
checksum = computeTableChecksum(locaData, length);
1641
} else if (i == t42GlyfTable) {
1644
glyfPos = tables[seekTable("glyf")].offset;
1645
for (j = 0; j < nGlyphs; ++j) {
1646
length += locaTable[j].len;
1648
length += 4 - (length & 3);
1650
if (checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1652
computeTableChecksum(file + glyfPos + locaTable[j].origOffset,
1657
if ((j = seekTable(t42Tables[i].tag)) >= 0) {
1658
length = tables[j].len;
1659
if (checkRegion(tables[j].offset, length)) {
1660
checksum = computeTableChecksum(file + tables[j].offset, length);
1662
} else if (needVerticalMetrics && i == t42VheaTable) {
1663
vheaTab[10] = advance / 256; // max advance height
1664
vheaTab[11] = advance % 256;
1665
length = sizeof(vheaTab);
1666
checksum = computeTableChecksum(vheaTab, length);
1667
} else if (needVerticalMetrics && i == t42VmtxTable) {
1668
length = 4 + (nGlyphs - 1) * 4;
1669
vmtxTab = (Guchar *)gmalloc(length);
1670
vmtxTab[0] = advance / 256;
1671
vmtxTab[1] = advance % 256;
1672
for (j = 2; j < length; j += 2) {
1676
checksum = computeTableChecksum(vmtxTab, length);
1677
} else if (t42Tables[i].required) {
1678
//~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1679
//~ t42Tables[i].tag);
1685
newTables[k].tag = ((t42Tables[i].tag[0] & 0xff) << 24) |
1686
((t42Tables[i].tag[1] & 0xff) << 16) |
1687
((t42Tables[i].tag[2] & 0xff) << 8) |
1688
(t42Tables[i].tag[3] & 0xff);
1689
newTables[k].checksum = checksum;
1690
newTables[k].offset = pos;
1691
newTables[k].len = length;
1694
pos += 4 - (length & 3);
1700
// construct the table directory
1701
tableDir[0] = 0x00; // sfnt version
1705
tableDir[4] = 0; // numTables
1706
tableDir[5] = nNewTables;
1707
tableDir[6] = 0; // searchRange
1708
tableDir[7] = (Guchar)128;
1709
tableDir[8] = 0; // entrySelector
1711
tableDir[10] = 0; // rangeShift
1712
tableDir[11] = (Guchar)(16 * nNewTables - 128);
1714
for (i = 0; i < nNewTables; ++i) {
1715
tableDir[pos ] = (Guchar)(newTables[i].tag >> 24);
1716
tableDir[pos+ 1] = (Guchar)(newTables[i].tag >> 16);
1717
tableDir[pos+ 2] = (Guchar)(newTables[i].tag >> 8);
1718
tableDir[pos+ 3] = (Guchar) newTables[i].tag;
1719
tableDir[pos+ 4] = (Guchar)(newTables[i].checksum >> 24);
1720
tableDir[pos+ 5] = (Guchar)(newTables[i].checksum >> 16);
1721
tableDir[pos+ 6] = (Guchar)(newTables[i].checksum >> 8);
1722
tableDir[pos+ 7] = (Guchar) newTables[i].checksum;
1723
tableDir[pos+ 8] = (Guchar)(newTables[i].offset >> 24);
1724
tableDir[pos+ 9] = (Guchar)(newTables[i].offset >> 16);
1725
tableDir[pos+10] = (Guchar)(newTables[i].offset >> 8);
1726
tableDir[pos+11] = (Guchar) newTables[i].offset;
1727
tableDir[pos+12] = (Guchar)(newTables[i].len >> 24);
1728
tableDir[pos+13] = (Guchar)(newTables[i].len >> 16);
1729
tableDir[pos+14] = (Guchar)(newTables[i].len >> 8);
1730
tableDir[pos+15] = (Guchar) newTables[i].len;
1734
// compute the font checksum and store it in the head table
1735
checksum = computeTableChecksum(tableDir, 12 + nNewTables*16);
1736
for (i = 0; i < nNewTables; ++i) {
1737
checksum += newTables[i].checksum;
1739
checksum = 0xb1b0afba - checksum; // because the TrueType spec says so
1740
headData[ 8] = (Guchar)(checksum >> 24);
1741
headData[ 9] = (Guchar)(checksum >> 16);
1742
headData[10] = (Guchar)(checksum >> 8);
1743
headData[11] = (Guchar) checksum;
1745
// start the sfnts array
1747
(*outputFunc)(outputStream, "/", 1);
1748
(*outputFunc)(outputStream, name->getCString(), name->getLength());
1749
(*outputFunc)(outputStream, " [\n", 3);
1751
(*outputFunc)(outputStream, "/sfnts [\n", 9);
1754
// write the table directory
1755
dumpString(tableDir, 12 + nNewTables*16, outputFunc, outputStream);
1758
for (i = 0; i < nNewTables; ++i) {
1759
if (i == t42HeadTable) {
1760
dumpString(headData, 54, outputFunc, outputStream);
1761
} else if (i == t42LocaTable) {
1762
length = (nGlyphs + 1) * (locaFmt ? 4 : 2);
1763
dumpString(locaData, length, outputFunc, outputStream);
1764
} else if (i == t42GlyfTable) {
1765
glyfPos = tables[seekTable("glyf")].offset;
1766
for (j = 0; j < nGlyphs; ++j) {
1767
if (locaTable[j].len > 0 &&
1768
checkRegion(glyfPos + locaTable[j].origOffset, locaTable[j].len)) {
1769
dumpString(file + glyfPos + locaTable[j].origOffset,
1770
locaTable[j].len, outputFunc, outputStream);
1774
// length == 0 means the table is missing and the error was
1775
// already reported during the construction of the table
1777
if ((length = newTables[i].len) > 0) {
1778
if ((j = seekTable(t42Tables[i].tag)) >= 0 &&
1779
checkRegion(tables[j].offset, tables[j].len)) {
1780
dumpString(file + tables[j].offset, tables[j].len,
1781
outputFunc, outputStream);
1782
} else if (needVerticalMetrics && i == t42VheaTable) {
1783
dumpString(vheaTab, length, outputFunc, outputStream);
1784
} else if (needVerticalMetrics && i == t42VmtxTable) {
1785
dumpString(vmtxTab, length, outputFunc, outputStream);
1792
// end the sfnts array
1793
(*outputFunc)(outputStream, "] def\n", 6);
1799
void FoFiTrueType::dumpString(Guchar *s, int length,
1800
FoFiOutputFunc outputFunc,
1801
void *outputStream) {
1805
(*outputFunc)(outputStream, "<", 1);
1806
for (i = 0; i < length; i += 32) {
1807
for (j = 0; j < 32 && i+j < length; ++j) {
1808
buf = GooString::format("{0:02x}", s[i+j] & 0xff);
1809
(*outputFunc)(outputStream, buf->getCString(), buf->getLength());
1812
if (i % (65536 - 32) == 65536 - 64) {
1813
(*outputFunc)(outputStream, ">\n<", 3);
1814
} else if (i+32 < length) {
1815
(*outputFunc)(outputStream, "\n", 1);
1819
pad = 4 - (length & 3);
1820
for (i = 0; i < pad; ++i) {
1821
(*outputFunc)(outputStream, "00", 2);
1824
// add an extra zero byte because the Adobe Type 42 spec says so
1825
(*outputFunc)(outputStream, "00>\n", 4);
1828
Guint FoFiTrueType::computeTableChecksum(Guchar *data, int length) {
1829
Guint checksum, word;
1833
for (i = 0; i+3 < length; i += 4) {
1834
word = ((data[i ] & 0xff) << 24) +
1835
((data[i+1] & 0xff) << 16) +
1836
((data[i+2] & 0xff) << 8) +
1843
switch (length & 3) {
1845
word |= (data[i+2] & 0xff) << 8;
1847
word |= (data[i+1] & 0xff) << 16;
1849
word |= (data[i ] & 0xff) << 24;
1857
void FoFiTrueType::parse() {
1863
// look for a collection (TTC)
1864
topTag = getU32BE(0, &parsedOk);
1868
if (topTag == ttcfTag) {
1872
dircount = getU32BE(8, &parsedOk);
1880
if (faceIndex >= dircount)
1882
pos = getU32BE(12 + faceIndex * 4, &parsedOk);
1889
// check the sfnt version
1890
ver = getU32BE(pos, &parsedOk);
1894
openTypeCFF = ver == 0x4f54544f; // 'OTTO'
1896
// read the table directory
1897
nTables = getU16BE(pos + 4, &parsedOk);
1901
tables = (TrueTypeTable *)gmallocn(nTables, sizeof(TrueTypeTable));
1903
int wrongTables = 0;
1904
for (i = 0; i < nTables; ++i) {
1905
tables[i].tag = getU32BE(pos, &parsedOk);
1906
tables[i].checksum = getU32BE(pos + 4, &parsedOk);
1907
tables[i].offset = (int)getU32BE(pos + 8, &parsedOk);
1908
tables[i].len = (int)getU32BE(pos + 12, &parsedOk);
1909
if (tables[i].offset + tables[i].len < tables[i].offset ||
1910
tables[i].offset + tables[i].len > len) {
1913
error(-1, "Found a bad table definition on true type definition, trying to continue...");
1917
nTables -= wrongTables;
1918
tables = (TrueTypeTable *)greallocn_checkoverflow(tables, nTables, sizeof(TrueTypeTable));
1919
if (!parsedOk || tables == NULL) {
1923
// check for tables that are required by both the TrueType spec and
1925
if (seekTable("head") < 0 ||
1926
seekTable("hhea") < 0 ||
1927
seekTable("maxp") < 0 ||
1928
seekTable("hmtx") < 0 ||
1929
(!openTypeCFF && seekTable("loca") < 0) ||
1930
(!openTypeCFF && seekTable("glyf") < 0) ||
1931
(openTypeCFF && seekTable("CFF ") < 0)) {
1937
if ((i = seekTable("cmap")) >= 0) {
1938
pos = tables[i].offset + 2;
1939
nCmaps = getU16BE(pos, &parsedOk);
1944
cmaps = (TrueTypeCmap *)gmallocn(nCmaps, sizeof(TrueTypeCmap));
1945
for (j = 0; j < nCmaps; ++j) {
1946
cmaps[j].platform = getU16BE(pos, &parsedOk);
1947
cmaps[j].encoding = getU16BE(pos + 2, &parsedOk);
1948
cmaps[j].offset = tables[i].offset + getU32BE(pos + 4, &parsedOk);
1950
cmaps[j].fmt = getU16BE(cmaps[j].offset, &parsedOk);
1951
cmaps[j].len = getU16BE(cmaps[j].offset + 2, &parsedOk);
1960
// get the number of glyphs from the maxp table
1961
i = seekTable("maxp");
1962
nGlyphs = getU16BE(tables[i].offset + 4, &parsedOk);
1967
// get the bbox and loca table format from the head table
1968
i = seekTable("head");
1969
bbox[0] = getS16BE(tables[i].offset + 36, &parsedOk);
1970
bbox[1] = getS16BE(tables[i].offset + 38, &parsedOk);
1971
bbox[2] = getS16BE(tables[i].offset + 40, &parsedOk);
1972
bbox[3] = getS16BE(tables[i].offset + 42, &parsedOk);
1973
locaFmt = getS16BE(tables[i].offset + 50, &parsedOk);
1978
// make sure the loca table is sane (correct length and entries are
1981
i = seekTable("loca");
1982
if (tables[i].len < 0) {
1986
if (tables[i].len < (nGlyphs + 1) * (locaFmt ? 4 : 2)) {
1987
nGlyphs = tables[i].len / (locaFmt ? 4 : 2) - 1;
1989
for (j = 0; j <= nGlyphs; ++j) {
1991
pos = (int)getU32BE(tables[i].offset + j*4, &parsedOk);
1993
pos = getU16BE(tables[i].offset + j*2, &parsedOk);
1995
if (pos < 0 || pos > len) {
2004
// read the post table
2008
void FoFiTrueType::readPostTable() {
2010
int tablePos, postFmt, stringIdx, stringPos;
2015
if ((i = seekTable("post")) < 0) {
2018
tablePos = tables[i].offset;
2019
postFmt = getU32BE(tablePos, &ok);
2023
if (postFmt == 0x00010000) {
2024
nameToGID = new GooHash(gTrue);
2025
for (i = 0; i < 258; ++i) {
2026
nameToGID->add(new GooString(macGlyphNames[i]), i);
2028
} else if (postFmt == 0x00020000) {
2029
nameToGID = new GooHash(gTrue);
2030
n = getU16BE(tablePos + 32, &ok);
2038
stringPos = tablePos + 34 + 2*n;
2039
for (i = 0; i < n; ++i) {
2040
j = getU16BE(tablePos + 34 + 2*i, &ok);
2042
nameToGID->removeInt(macGlyphNames[j]);
2043
nameToGID->add(new GooString(macGlyphNames[j]), i);
2046
if (j != stringIdx) {
2047
for (stringIdx = 0, stringPos = tablePos + 34 + 2*n;
2049
++stringIdx, stringPos += 1 + getU8(stringPos, &ok)) ;
2054
m = getU8(stringPos, &ok);
2055
if (!ok || !checkRegion(stringPos + 1, m)) {
2058
name = new GooString((char *)&file[stringPos + 1], m);
2059
nameToGID->removeInt(name);
2060
nameToGID->add(name, i);
2065
} else if (postFmt == 0x00028000) {
2066
nameToGID = new GooHash(gTrue);
2067
for (i = 0; i < nGlyphs; ++i) {
2068
j = getU8(tablePos + 32 + i, &ok);
2073
nameToGID->removeInt(macGlyphNames[j]);
2074
nameToGID->add(new GooString(macGlyphNames[j]), i);
2088
int FoFiTrueType::seekTable(char *tag) {
2092
tagI = ((tag[0] & 0xff) << 24) |
2093
((tag[1] & 0xff) << 16) |
2094
((tag[2] & 0xff) << 8) |
2096
for (i = 0; i < nTables; ++i) {
2097
if (tables[i].tag == tagI) {
2104
Guint FoFiTrueType::charToTag(const char *tagName)
2106
int n = strlen(tagName);
2111
for (i = 0;i < n;i++) {
2113
tag |= tagName[i] & 0xff;
2123
setup GSUB table data
2124
Only supporting vertical text substitution.
2126
int FoFiTrueType::setupGSUB(const char *tagName)
2130
Guint scriptList, featureList;
2133
Guint scriptTable = 0;
2144
gsubFeatureTable = 0;
2147
scriptTag = charToTag(tagName);
2148
/* read GSUB Header */
2149
if ((x = seekTable("GSUB")) < 0) {
2150
return 0; /* GSUB table not found */
2152
gsubTable = tables[x].offset;
2154
scriptList = getU16BE(pos,&parsedOk);
2156
featureList = getU16BE(pos,&parsedOk);
2158
llist = getU16BE(pos,&parsedOk);
2160
gsubLookupList = llist+gsubTable; /* change to offset from top of file */
2161
/* read script list table */
2162
pos = gsubTable+scriptList;
2163
scriptCount = getU16BE(pos,&parsedOk);
2166
for (i = 0;i < scriptCount;i++) {
2167
tag = getU32BE(pos,&parsedOk);
2169
scriptTable = getU16BE(pos,&parsedOk);
2171
if (tag == scriptTag) {
2176
if (i >= scriptCount) {
2181
/* read script table */
2182
/* use default language system */
2183
pos = gsubTable+scriptList+scriptTable;
2184
langSys = getU16BE(pos,&parsedOk);/* default language system */
2186
/* read LangSys table */
2188
/* no ldefault LangSys */
2192
pos = gsubTable+scriptList+scriptTable+langSys+2;
2193
featureIndex = getU16BE(pos,&parsedOk); /* ReqFeatureIndex */
2196
if (featureIndex != 0xffff) {
2198
/* read feature record */
2199
tpos = gsubTable+featureList;
2200
featureCount = getU16BE(tpos,&parsedOk);
2201
tpos = gsubTable+featureList+2+featureIndex*(4+2);
2202
tag = getU32BE(tpos,&parsedOk);
2204
if (tag == vrt2Tag) {
2205
/* vrt2 is preferred, overwrite vert */
2206
ftable = getU16BE(tpos,&parsedOk);
2207
/* convert to offset from file top */
2208
gsubFeatureTable = ftable+gsubTable+featureList;
2210
} else if (tag == vertTag) {
2211
ftable = getU16BE(tpos,&parsedOk);
2214
featureCount = getU16BE(pos,&parsedOk);
2216
/* find 'vrt2' or 'vert' feature */
2217
for (i = 0;i < featureCount;i++) {
2220
featureIndex = getU16BE(pos,&parsedOk);
2222
oldPos = pos; /* save position */
2223
/* read feature record */
2224
pos = gsubTable+featureList+2+featureIndex*(4+2);
2225
tag = getU32BE(pos,&parsedOk);
2227
if (tag == vrt2Tag) {
2228
/* vrt2 is preferred, overwrite vert */
2229
ftable = getU16BE(pos,&parsedOk);
2231
} else if (ftable == 0 && tag == vertTag) {
2232
ftable = getU16BE(pos,&parsedOk);
2234
pos = oldPos; /* restore old position */
2237
/* vert nor vrt2 are not found */
2240
/* convert to offset from file top */
2241
gsubFeatureTable = ftable+gsubTable+featureList;
2245
Guint FoFiTrueType::doMapToVertGID(Guint orgGID)
2248
Guint lookupListIndex;
2253
pos = gsubFeatureTable+2;
2254
lookupCount = getU16BE(pos,&parsedOk);
2256
for (i = 0;i < lookupCount;i++) {
2257
lookupListIndex = getU16BE(pos,&parsedOk);
2259
if ((gid = scanLookupList(lookupListIndex,orgGID)) != 0) {
2266
Guint FoFiTrueType::mapToVertGID(Guint orgGID)
2270
if (gsubFeatureTable == 0) return orgGID;
2271
if ((mapped = doMapToVertGID(orgGID)) != 0) {
2277
Guint FoFiTrueType::scanLookupList(Guint listIndex, Guint orgGID)
2280
Guint subTableCount;
2286
if (gsubLookupList == 0) return 0; /* no lookup list */
2287
pos = gsubLookupList+2+listIndex*2;
2288
lookupTable = getU16BE(pos,&parsedOk);
2289
/* read lookup table */
2290
pos = gsubLookupList+lookupTable+4;
2291
subTableCount = getU16BE(pos,&parsedOk);
2293
for (i = 0;i < subTableCount;i++) {
2294
subTable = getU16BE(pos,&parsedOk);
2296
if ((gid = scanLookupSubTable(gsubLookupList+lookupTable+subTable,orgGID))
2302
Guint FoFiTrueType::scanLookupSubTable(Guint subTable, Guint orgGID)
2314
format = getU16BE(pos,&parsedOk);
2316
coverage = getU16BE(pos,&parsedOk);
2318
if ((coverageIndex =
2319
checkGIDInCoverage(subTable+coverage,orgGID)) >= 0) {
2323
delta = getS16BE(pos,&parsedOk);
2329
glyphCount = getS16BE(pos,&parsedOk);
2331
if (glyphCount > coverageIndex) {
2332
pos += coverageIndex*2;
2333
substitute = getU16BE(pos,&parsedOk);
2338
/* unknown format */
2345
int FoFiTrueType::checkGIDInCoverage(Guint coverage, Guint orgGID)
2354
format = getU16BE(pos,&parsedOk);
2358
count = getU16BE(pos,&parsedOk);
2360
for (i = 0;i < count;i++) {
2363
gid = getU16BE(pos,&parsedOk);
2365
if (gid == orgGID) {
2369
} else if (gid > orgGID) {
2376
count = getU16BE(pos,&parsedOk);
2378
for (i = 0;i < count;i++) {
2379
Guint startGID, endGID;
2382
startGID = getU16BE(pos,&parsedOk);
2384
endGID = getU16BE(pos,&parsedOk);
2386
startIndex = getU16BE(pos,&parsedOk);
2388
if (startGID <= orgGID && orgGID <= endGID) {
2390
index = startIndex+orgGID-startGID;
2392
} else if (orgGID <= endGID) {