1 //========================================================================
5 // Copyright 1999-2003 Glyph & Cog, LLC
7 //========================================================================
11 #ifdef USE_GCC_PRAGMAS
12 #pragma implementation
20 #include "FoFiTrueType.h"
26 // character code = number used as an element of a text string
28 // character name = glyph name = name for a particular glyph within a
31 // glyph index = GID = position (within some internal table in the font)
32 // where the instructions to draw a particular glyph are
38 // Type 1 fonts contain:
40 // Encoding: array of glyph names, maps char codes to glyph names
42 // Encoding[charCode] = charName
44 // CharStrings: dictionary of instructions, keyed by character names,
45 // maps character name to glyph data
47 // CharStrings[charName] = glyphData
52 // TrueType fonts contain:
54 // 'cmap' table: mapping from character code to glyph index; there may
55 // be multiple cmaps in a TrueType font
57 // cmap[charCode] = gid
59 // 'post' table: mapping from glyph index to glyph name
61 // post[gid] = glyphName
66 // Type 42 fonts contain:
68 // Encoding: array of glyph names, maps char codes to glyph names
70 // Encoding[charCode] = charName
72 // CharStrings: dictionary of glyph indexes, keyed by character names,
73 // maps character name to glyph index
75 // CharStrings[charName] = gid
78 //------------------------------------------------------------------------
80 struct TrueTypeTable
{
103 #define cmapTag 0x636d6170
104 #define glyfTag 0x676c7966
105 #define locaTag 0x6c6f6361
106 #define nameTag 0x6e616d65
107 #define postTag 0x706f7374
109 static int cmpTrueTypeLocaOffset(const void *p1
, const void *p2
) {
110 TrueTypeLoca
*loca1
= (TrueTypeLoca
*)p1
;
111 TrueTypeLoca
*loca2
= (TrueTypeLoca
*)p2
;
113 if (loca1
->origOffset
== loca2
->origOffset
) {
114 return loca1
->idx
- loca2
->idx
;
116 return loca1
->origOffset
- loca2
->origOffset
;
119 static int cmpTrueTypeLocaIdx(const void *p1
, const void *p2
) {
120 TrueTypeLoca
*loca1
= (TrueTypeLoca
*)p1
;
121 TrueTypeLoca
*loca2
= (TrueTypeLoca
*)p2
;
123 return loca1
->idx
- loca2
->idx
;
126 static int cmpTrueTypeTableTag(const void *p1
, const void *p2
) {
127 TrueTypeTable
*tab1
= (TrueTypeTable
*)p1
;
128 TrueTypeTable
*tab2
= (TrueTypeTable
*)p2
;
130 return (int)tab1
->tag
- (int)tab2
->tag
;
133 //------------------------------------------------------------------------
136 char *tag
; // 4-byte tag
137 GBool required
; // required by the TrueType spec?
140 // TrueType tables to be embedded in Type 42 fonts.
141 // NB: the table names must be in alphabetical order here.
142 #define nT42Tables 11
143 static T42Table t42Tables
[nT42Tables
] = {
156 #define t42HeadTable 3
157 #define t42LocaTable 6
158 #define t42GlyfTable 2
160 //------------------------------------------------------------------------
162 // Glyph names in some arbitrary standard order that Apple uses for
163 // their TrueType fonts.
164 static char *macGlyphNames
[258] = {
165 ".notdef", "null", "CR", "space",
166 "exclam", "quotedbl", "numbersign", "dollar",
167 "percent", "ampersand", "quotesingle", "parenleft",
168 "parenright", "asterisk", "plus", "comma",
169 "hyphen", "period", "slash", "zero",
170 "one", "two", "three", "four",
171 "five", "six", "seven", "eight",
172 "nine", "colon", "semicolon", "less",
173 "equal", "greater", "question", "at",
180 "Y", "Z", "bracketleft", "backslash",
181 "bracketright", "asciicircum", "underscore", "grave",
188 "y", "z", "braceleft", "bar",
189 "braceright", "asciitilde", "Adieresis", "Aring",
190 "Ccedilla", "Eacute", "Ntilde", "Odieresis",
191 "Udieresis", "aacute", "agrave", "acircumflex",
192 "adieresis", "atilde", "aring", "ccedilla",
193 "eacute", "egrave", "ecircumflex", "edieresis",
194 "iacute", "igrave", "icircumflex", "idieresis",
195 "ntilde", "oacute", "ograve", "ocircumflex",
196 "odieresis", "otilde", "uacute", "ugrave",
197 "ucircumflex", "udieresis", "dagger", "degree",
198 "cent", "sterling", "section", "bullet",
199 "paragraph", "germandbls", "registered", "copyright",
200 "trademark", "acute", "dieresis", "notequal",
201 "AE", "Oslash", "infinity", "plusminus",
202 "lessequal", "greaterequal", "yen", "mu1",
203 "partialdiff", "summation", "product", "pi",
204 "integral", "ordfeminine", "ordmasculine", "Ohm",
205 "ae", "oslash", "questiondown", "exclamdown",
206 "logicalnot", "radical", "florin", "approxequal",
207 "increment", "guillemotleft", "guillemotright", "ellipsis",
208 "nbspace", "Agrave", "Atilde", "Otilde",
209 "OE", "oe", "endash", "emdash",
210 "quotedblleft", "quotedblright", "quoteleft", "quoteright",
211 "divide", "lozenge", "ydieresis", "Ydieresis",
212 "fraction", "currency", "guilsinglleft", "guilsinglright",
213 "fi", "fl", "daggerdbl", "periodcentered",
214 "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
215 "Ecircumflex", "Aacute", "Edieresis", "Egrave",
216 "Iacute", "Icircumflex", "Idieresis", "Igrave",
217 "Oacute", "Ocircumflex", "applelogo", "Ograve",
218 "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
219 "circumflex", "tilde", "overscore", "breve",
220 "dotaccent", "ring", "cedilla", "hungarumlaut",
221 "ogonek", "caron", "Lslash", "lslash",
222 "Scaron", "scaron", "Zcaron", "zcaron",
223 "brokenbar", "Eth", "eth", "Yacute",
224 "yacute", "Thorn", "thorn", "minus",
225 "multiply", "onesuperior", "twosuperior", "threesuperior",
226 "onehalf", "onequarter", "threequarters", "franc",
227 "Gbreve", "gbreve", "Idot", "Scedilla",
228 "scedilla", "Cacute", "cacute", "Ccaron",
232 //------------------------------------------------------------------------
234 //------------------------------------------------------------------------
236 FoFiTrueType
*FoFiTrueType::make(char *fileA
, int lenA
) {
239 ff
= new FoFiTrueType(fileA
, lenA
, gFalse
);
247 FoFiTrueType
*FoFiTrueType::load(char *fileName
) {
252 if (!(fileA
= FoFiBase::readFile(fileName
, &lenA
))) {
255 ff
= new FoFiTrueType(fileA
, lenA
, gTrue
);
263 FoFiTrueType::FoFiTrueType(char *fileA
, int lenA
, GBool freeFileDataA
):
264 FoFiBase(fileA
, lenA
, freeFileDataA
)
276 FoFiTrueType::~FoFiTrueType() {
282 int FoFiTrueType::getNumCmaps() {
286 int FoFiTrueType::getCmapPlatform(int i
) {
287 return cmaps
[i
].platform
;
290 int FoFiTrueType::getCmapEncoding(int i
) {
291 return cmaps
[i
].encoding
;
294 int FoFiTrueType::findCmap(int platform
, int encoding
) {
297 for (i
= 0; i
< nCmaps
; ++i
) {
298 if (cmaps
[i
].platform
== platform
&& cmaps
[i
].encoding
== encoding
) {
305 Gushort
FoFiTrueType::mapCodeToGID(int i
, int c
) {
307 int segCnt
, segEnd
, segStart
, segDelta
, segOffset
;
308 int cmapFirst
, cmapLen
;
312 if (i
< 0 || i
>= nCmaps
) {
316 pos
= cmaps
[i
].offset
;
317 switch (cmaps
[i
].fmt
) {
319 if (c
< 0 || c
>= cmaps
[i
].len
- 6) {
322 gid
= getU8(cmaps
[i
].offset
+ 6 + c
, &ok
);
325 segCnt
= getU16BE(pos
+ 6, &ok
) / 2;
328 segEnd
= getU16BE(pos
+ 14 + 2*b
, &ok
);
330 // malformed font -- the TrueType spec requires the last segEnd
334 // invariant: seg[a].end < code <= seg[b].end
335 while (b
- a
> 1 && ok
) {
337 segEnd
= getU16BE(pos
+ 14 + 2*m
, &ok
);
344 segStart
= getU16BE(pos
+ 16 + 2*segCnt
+ 2*b
, &ok
);
345 segDelta
= getU16BE(pos
+ 16 + 4*segCnt
+ 2*b
, &ok
);
346 segOffset
= getU16BE(pos
+ 16 + 6*segCnt
+ 2*b
, &ok
);
350 if (segOffset
== 0) {
351 gid
= (c
+ segDelta
) & 0xffff;
353 gid
= getU16BE(pos
+ 16 + 6*segCnt
+ 2*b
+
354 segOffset
+ 2 * (c
- segStart
), &ok
);
356 gid
= (gid
+ segDelta
) & 0xffff;
361 cmapFirst
= getU16BE(pos
+ 6, &ok
);
362 cmapLen
= getU16BE(pos
+ 8, &ok
);
363 if (c
< cmapFirst
|| c
>= cmapFirst
+ cmapLen
) {
366 gid
= getU16BE(pos
+ 10 + 2 * (c
- cmapFirst
), &ok
);
377 int FoFiTrueType::mapNameToGID(char *name
) {
381 return nameToGID
->lookupInt(name
);
384 int FoFiTrueType::getEmbeddingRights() {
388 if ((i
= seekTable("OS/2")) < 0) {
392 fsType
= getU16BE(tables
[i
].offset
+ 8, &ok
);
396 if (fsType
& 0x0008) {
399 if (fsType
& 0x0004) {
402 if (fsType
& 0x0002) {
408 void FoFiTrueType::convertToType42(char *psName
, char **encoding
,
410 FoFiOutputFunc outputFunc
,
411 void *outputStream
) {
417 sprintf(buf
, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok
) / 65536.0);
418 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
420 // begin the font dictionary
421 (*outputFunc
)(outputStream
, "10 dict begin\n", 14);
422 (*outputFunc
)(outputStream
, "/FontName /", 11);
423 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
424 (*outputFunc
)(outputStream
, " def\n", 5);
425 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
426 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
427 sprintf(buf
, "/FontBBox [%d %d %d %d] def\n",
428 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
429 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
430 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
432 // write the guts of the dictionary
433 cvtEncoding(encoding
, outputFunc
, outputStream
);
434 cvtCharStrings(encoding
, codeToGID
, outputFunc
, outputStream
);
435 cvtSfnts(outputFunc
, outputStream
, NULL
);
437 // end the dictionary and define the font
438 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
441 void FoFiTrueType::convertToCIDType2(char *psName
,
442 Gushort
*cidMap
, int nCIDs
,
443 FoFiOutputFunc outputFunc
,
444 void *outputStream
) {
452 sprintf(buf
, "%%!PS-TrueTypeFont-%g\n", (double)getS32BE(0, &ok
) / 65536.0);
453 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
455 // begin the font dictionary
456 (*outputFunc
)(outputStream
, "20 dict begin\n", 14);
457 (*outputFunc
)(outputStream
, "/CIDFontName /", 14);
458 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
459 (*outputFunc
)(outputStream
, " def\n", 5);
460 (*outputFunc
)(outputStream
, "/CIDFontType 2 def\n", 19);
461 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
462 (*outputFunc
)(outputStream
, "/CIDSystemInfo 3 dict dup begin\n", 32);
463 (*outputFunc
)(outputStream
, " /Registry (Adobe) def\n", 24);
464 (*outputFunc
)(outputStream
, " /Ordering (Identity) def\n", 27);
465 (*outputFunc
)(outputStream
, " /Supplement 0 def\n", 20);
466 (*outputFunc
)(outputStream
, " end def\n", 10);
467 (*outputFunc
)(outputStream
, "/GDBytes 2 def\n", 15);
469 sprintf(buf
, "/CIDCount %d def\n", nCIDs
);
470 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
472 (*outputFunc
)(outputStream
, "/CIDMap [", 9);
473 for (i
= 0; i
< nCIDs
; i
+= 32768 - 16) {
474 (*outputFunc
)(outputStream
, "<\n", 2);
475 for (j
= 0; j
< 32768 - 16 && i
+j
< nCIDs
; j
+= 16) {
476 (*outputFunc
)(outputStream
, " ", 2);
477 for (k
= 0; k
< 16 && i
+j
+k
< nCIDs
; ++k
) {
479 sprintf(buf
, "%02x%02x", (cid
>> 8) & 0xff, cid
& 0xff);
480 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
482 (*outputFunc
)(outputStream
, "\n", 1);
484 (*outputFunc
)(outputStream
, " >", 3);
486 (*outputFunc
)(outputStream
, "\n", 1);
487 (*outputFunc
)(outputStream
, "] def\n", 6);
489 (*outputFunc
)(outputStream
, "/CIDMap <\n", 10);
490 for (i
= 0; i
< nCIDs
; i
+= 16) {
491 (*outputFunc
)(outputStream
, " ", 2);
492 for (j
= 0; j
< 16 && i
+j
< nCIDs
; ++j
) {
494 sprintf(buf
, "%02x%02x", (cid
>> 8) & 0xff, cid
& 0xff);
495 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
497 (*outputFunc
)(outputStream
, "\n", 1);
499 (*outputFunc
)(outputStream
, "> def\n", 6);
502 // direct mapping - just fill the string(s) with s[i]=i
503 sprintf(buf
, "/CIDCount %d def\n", nGlyphs
);
504 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
505 if (nGlyphs
> 32767) {
506 (*outputFunc
)(outputStream
, "/CIDMap [\n", 10);
507 for (i
= 0; i
< nGlyphs
; i
+= 32767) {
508 j
= nGlyphs
- i
< 32767 ? nGlyphs
- i
: 32767;
509 sprintf(buf
, " %d string 0 1 %d {\n", 2 * j
, j
- 1);
510 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
511 sprintf(buf
, " 2 copy dup 2 mul exch %d add -8 bitshift put\n", i
);
512 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
513 sprintf(buf
, " 1 index exch dup 2 mul 1 add exch %d add"
514 " 255 and put\n", i
);
515 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
516 (*outputFunc
)(outputStream
, " } for\n", 8);
518 (*outputFunc
)(outputStream
, "] def\n", 6);
520 sprintf(buf
, "/CIDMap %d string\n", 2 * nGlyphs
);
521 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
522 sprintf(buf
, " 0 1 %d {\n", nGlyphs
- 1);
523 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
524 (*outputFunc
)(outputStream
,
525 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
526 (*outputFunc
)(outputStream
,
527 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
528 (*outputFunc
)(outputStream
, " } for\n", 8);
529 (*outputFunc
)(outputStream
, "def\n", 4);
532 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
533 sprintf(buf
, "/FontBBox [%d %d %d %d] def\n",
534 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
535 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
536 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
537 (*outputFunc
)(outputStream
, "/Encoding [] readonly def\n", 26);
538 (*outputFunc
)(outputStream
, "/CharStrings 1 dict dup begin\n", 30);
539 (*outputFunc
)(outputStream
, " /.notdef 0 def\n", 17);
540 (*outputFunc
)(outputStream
, " end readonly def\n", 19);
542 // write the guts of the dictionary
543 cvtSfnts(outputFunc
, outputStream
, NULL
);
545 // end the dictionary and define the font
546 (*outputFunc
)(outputStream
,
547 "CIDFontName currentdict end /CIDFont defineresource pop\n",
551 void FoFiTrueType::convertToType0(char *psName
, Gushort
*cidMap
, int nCIDs
,
552 FoFiOutputFunc outputFunc
,
553 void *outputStream
) {
558 // write the Type 42 sfnts array
559 sfntsName
= (new GString(psName
))->append("_sfnts");
560 cvtSfnts(outputFunc
, outputStream
, sfntsName
);
563 // write the descendant Type 42 fonts
564 n
= cidMap
? nCIDs
: nGlyphs
;
565 for (i
= 0; i
< n
; i
+= 256) {
566 (*outputFunc
)(outputStream
, "10 dict begin\n", 14);
567 (*outputFunc
)(outputStream
, "/FontName /", 11);
568 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
569 sprintf(buf
, "_%02x def\n", i
>> 8);
570 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
571 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
572 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
573 sprintf(buf
, "/FontBBox [%d %d %d %d] def\n",
574 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
575 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
576 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
577 (*outputFunc
)(outputStream
, "/sfnts ", 7);
578 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
579 (*outputFunc
)(outputStream
, "_sfnts def\n", 11);
580 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
581 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
582 sprintf(buf
, "dup %d /c%02x put\n", j
, j
);
583 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
585 (*outputFunc
)(outputStream
, "readonly def\n", 13);
586 (*outputFunc
)(outputStream
, "/CharStrings 257 dict dup begin\n", 32);
587 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
588 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
589 sprintf(buf
, "/c%02x %d def\n", j
, cidMap
? cidMap
[i
+j
] : i
+j
);
590 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
592 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
593 (*outputFunc
)(outputStream
,
594 "FontName currentdict end definefont pop\n", 40);
597 // write the Type 0 parent font
598 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
599 (*outputFunc
)(outputStream
, "/FontName /", 11);
600 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
601 (*outputFunc
)(outputStream
, " def\n", 5);
602 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
603 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
604 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
605 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
606 for (i
= 0; i
< n
; i
+= 256) {
607 sprintf(buf
, "%d\n", i
>> 8);
608 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
610 (*outputFunc
)(outputStream
, "] def\n", 6);
611 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
612 for (i
= 0; i
< n
; i
+= 256) {
613 (*outputFunc
)(outputStream
, "/", 1);
614 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
615 sprintf(buf
, "_%02x findfont\n", i
>> 8);
616 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
618 (*outputFunc
)(outputStream
, "] def\n", 6);
619 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
622 void FoFiTrueType::writeTTF(FoFiOutputFunc outputFunc
,
623 void *outputStream
) {
624 static char cmapTab
[20] = {
625 0, 0, // table version number
626 0, 1, // number of encoding tables
629 0, 0, 0, 12, // offset of subtable
630 0, 0, // subtable format
631 0, 1, // subtable length
632 0, 1, // subtable version
633 0, // map char 0 -> glyph 0
634 0 // pad to multiple of four bytes
636 static char nameTab
[8] = {
638 0, 0, // number of name records
639 0, 6, // offset to start of string storage
640 0, 0 // pad to multiple of four bytes
642 static char postTab
[32] = {
643 0, 1, 0, 0, // format
644 0, 0, 0, 0, // italic angle
645 0, 0, // underline position
646 0, 0, // underline thickness
647 0, 0, 0, 0, // fixed pitch
648 0, 0, 0, 0, // min Type 42 memory
649 0, 0, 0, 0, // max Type 42 memory
650 0, 0, 0, 0, // min Type 1 memory
651 0, 0, 0, 0 // max Type 1 memory
653 GBool missingCmap
, missingName
, missingPost
, unsortedLoca
, badCmapLen
;
654 int nZeroLengthTables
;
655 TrueTypeLoca
*locaTable
;
656 TrueTypeTable
*newTables
;
657 int nNewTables
, cmapIdx
, cmapLen
, glyfLen
;
664 // check for missing tables
665 missingCmap
= (cmapIdx
= seekTable("cmap")) < 0;
666 missingName
= seekTable("name") < 0;
667 missingPost
= seekTable("post") < 0;
669 // read the loca table, check to see if it's sorted
670 locaTable
= (TrueTypeLoca
*)gmalloc((nGlyphs
+ 1) * sizeof(TrueTypeLoca
));
671 unsortedLoca
= gFalse
;
672 i
= seekTable("loca");
673 pos
= tables
[i
].offset
;
675 for (i
= 0; i
<= nGlyphs
; ++i
) {
677 locaTable
[i
].origOffset
= (int)getU32BE(pos
+ i
*4, &ok
);
679 locaTable
[i
].origOffset
= 2 * getU16BE(pos
+ i
*2, &ok
);
681 if (i
> 0 && locaTable
[i
].origOffset
< locaTable
[i
-1].origOffset
) {
682 unsortedLoca
= gTrue
;
684 locaTable
[i
].idx
= i
;
687 // check for zero-length tables
688 nZeroLengthTables
= 0;
689 for (i
= 0; i
< nTables
; ++i
) {
690 if (tables
[i
].len
== 0) {
695 // check for an incorrect cmap table length
697 cmapLen
= 0; // make gcc happy
699 cmapLen
= cmaps
[0].offset
+ cmaps
[0].len
;
700 for (i
= 1; i
< nCmaps
; ++i
) {
701 if (cmaps
[i
].offset
+ cmaps
[i
].len
> cmapLen
) {
702 cmapLen
= cmaps
[i
].offset
+ cmaps
[i
].len
;
705 cmapLen
-= tables
[cmapIdx
].offset
;
706 if (cmapLen
> tables
[cmapIdx
].len
) {
711 // if nothing is broken, just write the TTF file as is
712 if (!missingCmap
&& !missingName
&& !missingPost
&& !unsortedLoca
&&
713 !badCmapLen
&& nZeroLengthTables
== 0) {
714 (*outputFunc
)(outputStream
, (char *)file
, len
);
718 // sort the 'loca' table: some (non-compliant) fonts have
719 // out-of-order loca tables; in order to correctly handle the case
720 // where (compliant) fonts have empty entries in the middle of the
721 // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
722 // and idx as its secondary key (ensuring that adjacent entries with
723 // the same pos value remain in the same order)
724 glyfLen
= 0; // make gcc happy
726 qsort(locaTable
, nGlyphs
+ 1, sizeof(TrueTypeLoca
),
727 &cmpTrueTypeLocaOffset
);
728 for (i
= 0; i
< nGlyphs
; ++i
) {
729 locaTable
[i
].len
= locaTable
[i
+1].origOffset
- locaTable
[i
].origOffset
;
731 locaTable
[nGlyphs
].len
= 0;
732 qsort(locaTable
, nGlyphs
+ 1, sizeof(TrueTypeLoca
),
733 &cmpTrueTypeLocaIdx
);
735 for (i
= 0; i
<= nGlyphs
; ++i
) {
736 locaTable
[i
].newOffset
= pos
;
737 pos
+= locaTable
[i
].len
;
739 pos
+= 4 - (pos
& 3);
745 // construct the new table directory:
746 // - keep all original tables with non-zero length
747 // - fix the cmap table's length, if necessary
748 // - add missing tables
749 // - sort the table by tag
750 // - compute new table positions, including 4-byte alignment
751 nNewTables
= nTables
- nZeroLengthTables
+
752 (missingCmap
? 1 : 0) + (missingName
? 1 : 0) +
753 (missingPost
? 1 : 0);
754 newTables
= (TrueTypeTable
*)gmalloc(nNewTables
* sizeof(TrueTypeTable
));
756 for (i
= 0; i
< nTables
; ++i
) {
757 if (tables
[i
].len
> 0) {
758 newTables
[j
] = tables
[i
];
759 newTables
[j
].origOffset
= tables
[i
].offset
;
760 if (newTables
[j
].tag
== cmapTag
&& badCmapLen
) {
761 newTables
[j
].len
= cmapLen
;
762 } else if (newTables
[j
].tag
== locaTag
&& unsortedLoca
) {
763 newTables
[j
].len
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
764 } else if (newTables
[j
].tag
== glyfTag
&& unsortedLoca
) {
765 newTables
[j
].len
= glyfLen
;
771 newTables
[j
].tag
= cmapTag
;
772 newTables
[j
].checksum
= 0; //~ should compute the checksum
773 newTables
[j
].len
= sizeof(cmapTab
);
777 newTables
[j
].tag
= nameTag
;
778 newTables
[j
].checksum
= 0; //~ should compute the checksum
779 newTables
[j
].len
= sizeof(nameTab
);
783 newTables
[j
].tag
= postTag
;
784 newTables
[j
].checksum
= 0; //~ should compute the checksum
785 newTables
[j
].len
= sizeof(postTab
);
788 qsort(newTables
, nNewTables
, sizeof(TrueTypeTable
),
789 &cmpTrueTypeTableTag
);
790 pos
= 12 + nNewTables
* 16;
791 for (i
= 0; i
< nNewTables
; ++i
) {
792 newTables
[i
].offset
= pos
;
793 pos
+= newTables
[i
].len
;
795 pos
+= 4 - (pos
& 3);
799 // write the table directory
800 tableDir
= (char *)gmalloc(12 + nNewTables
* 16);
801 tableDir
[0] = 0x00; // sfnt version
805 tableDir
[4] = (char)((nNewTables
>> 8) & 0xff); // numTables
806 tableDir
[5] = (char)(nNewTables
& 0xff);
807 for (i
= -1, t
= (Guint
)nNewTables
; t
; ++i
, t
>>= 1) ;
809 tableDir
[6] = (char)((t
>> 8) & 0xff); // searchRange
810 tableDir
[7] = (char)(t
& 0xff);
811 tableDir
[8] = (char)((i
>> 8) & 0xff); // entrySelector
812 tableDir
[9] = (char)(i
& 0xff);
813 t
= nNewTables
* 16 - t
;
814 tableDir
[10] = (char)((t
>> 8) & 0xff); // rangeShift
815 tableDir
[11] = (char)(t
& 0xff);
817 for (i
= 0; i
< nNewTables
; ++i
) {
818 tableDir
[pos
] = (char)(newTables
[i
].tag
>> 24);
819 tableDir
[pos
+ 1] = (char)(newTables
[i
].tag
>> 16);
820 tableDir
[pos
+ 2] = (char)(newTables
[i
].tag
>> 8);
821 tableDir
[pos
+ 3] = (char) newTables
[i
].tag
;
822 tableDir
[pos
+ 4] = (char)(newTables
[i
].checksum
>> 24);
823 tableDir
[pos
+ 5] = (char)(newTables
[i
].checksum
>> 16);
824 tableDir
[pos
+ 6] = (char)(newTables
[i
].checksum
>> 8);
825 tableDir
[pos
+ 7] = (char) newTables
[i
].checksum
;
826 tableDir
[pos
+ 8] = (char)(newTables
[i
].offset
>> 24);
827 tableDir
[pos
+ 9] = (char)(newTables
[i
].offset
>> 16);
828 tableDir
[pos
+10] = (char)(newTables
[i
].offset
>> 8);
829 tableDir
[pos
+11] = (char) newTables
[i
].offset
;
830 tableDir
[pos
+12] = (char)(newTables
[i
].len
>> 24);
831 tableDir
[pos
+13] = (char)(newTables
[i
].len
>> 16);
832 tableDir
[pos
+14] = (char)(newTables
[i
].len
>> 8);
833 tableDir
[pos
+15] = (char) newTables
[i
].len
;
836 (*outputFunc
)(outputStream
, tableDir
, 12 + nNewTables
* 16);
839 for (i
= 0; i
< nNewTables
; ++i
) {
840 if (newTables
[i
].tag
== cmapTag
&& missingCmap
) {
841 (*outputFunc
)(outputStream
, cmapTab
, newTables
[i
].len
);
842 } else if (newTables
[i
].tag
== nameTag
&& missingName
) {
843 (*outputFunc
)(outputStream
, nameTab
, newTables
[i
].len
);
844 } else if (newTables
[i
].tag
== postTag
&& missingPost
) {
845 (*outputFunc
)(outputStream
, postTab
, newTables
[i
].len
);
846 } else if (newTables
[i
].tag
== locaTag
&& unsortedLoca
) {
847 for (j
= 0; j
<= nGlyphs
; ++j
) {
849 locaBuf
[0] = (char)(locaTable
[j
].newOffset
>> 24);
850 locaBuf
[1] = (char)(locaTable
[j
].newOffset
>> 16);
851 locaBuf
[2] = (char)(locaTable
[j
].newOffset
>> 8);
852 locaBuf
[3] = (char) locaTable
[j
].newOffset
;
853 (*outputFunc
)(outputStream
, locaBuf
, 4);
855 locaBuf
[0] = (char)(locaTable
[j
].newOffset
>> 9);
856 locaBuf
[1] = (char)(locaTable
[j
].newOffset
>> 1);
857 (*outputFunc
)(outputStream
, locaBuf
, 2);
860 } else if (newTables
[i
].tag
== glyfTag
&& unsortedLoca
) {
861 pos
= tables
[seekTable("glyf")].offset
;
862 for (j
= 0; j
< nGlyphs
; ++j
) {
863 n
= locaTable
[j
].len
;
865 k
= locaTable
[j
].origOffset
;
866 if (checkRegion(pos
+ k
, n
)) {
867 (*outputFunc
)(outputStream
, (char *)file
+ pos
+ k
, n
);
869 for (k
= 0; k
< n
; ++k
) {
870 (*outputFunc
)(outputStream
, "\0", 1);
873 if ((k
= locaTable
[j
].len
& 3)) {
874 (*outputFunc
)(outputStream
, "\0\0\0\0", 4 - k
);
879 if (checkRegion(newTables
[i
].origOffset
, newTables
[i
].len
)) {
880 (*outputFunc
)(outputStream
, (char *)file
+ newTables
[i
].origOffset
,
883 for (j
= 0; j
< newTables
[i
].len
; ++j
) {
884 (*outputFunc
)(outputStream
, "\0", 1);
888 if (newTables
[i
].len
& 3) {
889 (*outputFunc
)(outputStream
, "\0\0\0", 4 - (newTables
[i
].len
& 3));
899 void FoFiTrueType::cvtEncoding(char **encoding
,
900 FoFiOutputFunc outputFunc
,
901 void *outputStream
) {
906 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
908 for (i
= 0; i
< 256; ++i
) {
909 if (!(name
= encoding
[i
])) {
912 sprintf(buf
, "dup %d /", i
);
913 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
914 (*outputFunc
)(outputStream
, name
, strlen(name
));
915 (*outputFunc
)(outputStream
, " put\n", 5);
918 for (i
= 0; i
< 256; ++i
) {
919 sprintf(buf
, "dup %d /c%02x put\n", i
, i
);
920 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
923 (*outputFunc
)(outputStream
, "readonly def\n", 13);
926 void FoFiTrueType::cvtCharStrings(char **encoding
,
928 FoFiOutputFunc outputFunc
,
929 void *outputStream
) {
931 char buf
[64], buf2
[16];
934 // always define '.notdef'
935 (*outputFunc
)(outputStream
, "/CharStrings 256 dict dup begin\n", 32);
936 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
938 // if there's no 'cmap' table, punt
943 // map char name to glyph index:
944 // 1. use encoding to map name to char code
945 // 2. use codeToGID to map char code to glyph index
946 // N.B. We do this in reverse order because font subsets can have
947 // weird encodings that use the same character name twice, and
948 // the first definition is probably the one we want.
949 k
= 0; // make gcc happy
950 for (i
= 255; i
>= 0; --i
) {
954 sprintf(buf2
, "c%02x", i
);
957 if (name
&& strcmp(name
, ".notdef")) {
959 // note: Distiller (maybe Adobe's PS interpreter in general)
960 // doesn't like TrueType fonts that have CharStrings entries
961 // which point to nonexistent glyphs, hence the (k < nGlyphs)
963 if (k
> 0 && k
< nGlyphs
) {
964 (*outputFunc
)(outputStream
, "/", 1);
965 (*outputFunc
)(outputStream
, name
, strlen(name
));
966 sprintf(buf
, " %d def\n", k
);
967 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
973 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
976 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc
,
977 void *outputStream
, GString
*name
) {
979 TrueTypeLoca
*locaTable
;
981 TrueTypeTable newTables
[nT42Tables
];
982 Guchar tableDir
[12 + nT42Tables
*16];
986 int length
, pos
, glyfPos
, i
, j
, k
;
988 // construct the 'head' table, zero out the font checksum
989 i
= seekTable("head");
990 pos
= tables
[i
].offset
;
991 if (!checkRegion(pos
, 54)) {
994 memcpy(headData
, file
+ pos
, 54);
995 headData
[8] = headData
[9] = headData
[10] = headData
[11] = (Guchar
)0;
997 // read the original 'loca' table, pad entries out to 4 bytes, and
998 // sort it into proper order -- some (non-compliant) fonts have
999 // out-of-order loca tables; in order to correctly handle the case
1000 // where (compliant) fonts have empty entries in the middle of the
1001 // table, cmpTrueTypeLocaPos uses offset as its primary sort key,
1002 // and idx as its secondary key (ensuring that adjacent entries with
1003 // the same pos value remain in the same order)
1004 locaTable
= (TrueTypeLoca
*)gmalloc((nGlyphs
+ 1) * sizeof(TrueTypeLoca
));
1005 i
= seekTable("loca");
1006 pos
= tables
[i
].offset
;
1008 for (i
= 0; i
<= nGlyphs
; ++i
) {
1009 locaTable
[i
].idx
= i
;
1011 locaTable
[i
].origOffset
= (int)getU32BE(pos
+ i
*4, &ok
);
1013 locaTable
[i
].origOffset
= 2 * getU16BE(pos
+ i
*2, &ok
);
1016 qsort(locaTable
, nGlyphs
+ 1, sizeof(TrueTypeLoca
),
1017 &cmpTrueTypeLocaOffset
);
1018 for (i
= 0; i
< nGlyphs
; ++i
) {
1019 locaTable
[i
].len
= locaTable
[i
+1].origOffset
- locaTable
[i
].origOffset
;
1021 locaTable
[nGlyphs
].len
= 0;
1022 qsort(locaTable
, nGlyphs
+ 1, sizeof(TrueTypeLoca
),
1023 &cmpTrueTypeLocaIdx
);
1025 for (i
= 0; i
<= nGlyphs
; ++i
) {
1026 locaTable
[i
].newOffset
= pos
;
1027 pos
+= locaTable
[i
].len
;
1029 pos
+= 4 - (pos
& 3);
1033 // construct the new 'loca' table
1034 locaData
= (Guchar
*)gmalloc((nGlyphs
+ 1) * (locaFmt
? 4 : 2));
1035 for (i
= 0; i
<= nGlyphs
; ++i
) {
1036 pos
= locaTable
[i
].newOffset
;
1038 locaData
[4*i
] = (Guchar
)(pos
>> 24);
1039 locaData
[4*i
+1] = (Guchar
)(pos
>> 16);
1040 locaData
[4*i
+2] = (Guchar
)(pos
>> 8);
1041 locaData
[4*i
+3] = (Guchar
) pos
;
1043 locaData
[2*i
] = (Guchar
)(pos
>> 9);
1044 locaData
[2*i
+1] = (Guchar
)(pos
>> 1);
1048 // count the number of tables
1050 for (i
= 0; i
< nT42Tables
; ++i
) {
1051 if (t42Tables
[i
].required
||
1052 seekTable(t42Tables
[i
].tag
) >= 0) {
1057 // construct the new table headers, including table checksums
1058 // (pad each table out to a multiple of 4 bytes)
1059 pos
= 12 + nNewTables
*16;
1061 for (i
= 0; i
< nT42Tables
; ++i
) {
1063 checksum
= 0; // make gcc happy
1064 if (i
== t42HeadTable
) {
1066 checksum
= computeTableChecksum(headData
, 54);
1067 } else if (i
== t42LocaTable
) {
1068 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1069 checksum
= computeTableChecksum(locaData
, length
);
1070 } else if (i
== t42GlyfTable
) {
1073 glyfPos
= tables
[seekTable("glyf")].offset
;
1074 for (j
= 0; j
< nGlyphs
; ++j
) {
1075 length
+= locaTable
[j
].len
;
1077 length
+= 4 - (length
& 3);
1079 if (checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1081 computeTableChecksum(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1086 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0) {
1087 length
= tables
[j
].len
;
1088 if (checkRegion(tables
[j
].offset
, length
)) {
1089 checksum
= computeTableChecksum(file
+ tables
[j
].offset
, length
);
1091 } else if (t42Tables
[i
].required
) {
1092 //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1093 //~ t42Tables[i].tag);
1099 newTables
[k
].tag
= ((t42Tables
[i
].tag
[0] & 0xff) << 24) |
1100 ((t42Tables
[i
].tag
[1] & 0xff) << 16) |
1101 ((t42Tables
[i
].tag
[2] & 0xff) << 8) |
1102 (t42Tables
[i
].tag
[3] & 0xff);
1103 newTables
[k
].checksum
= checksum
;
1104 newTables
[k
].offset
= pos
;
1105 newTables
[k
].len
= length
;
1108 pos
+= 4 - (length
& 3);
1114 // construct the table directory
1115 tableDir
[0] = 0x00; // sfnt version
1119 tableDir
[4] = 0; // numTables
1120 tableDir
[5] = nNewTables
;
1121 tableDir
[6] = 0; // searchRange
1122 tableDir
[7] = (Guchar
)128;
1123 tableDir
[8] = 0; // entrySelector
1125 tableDir
[10] = 0; // rangeShift
1126 tableDir
[11] = (Guchar
)(16 * nNewTables
- 128);
1128 for (i
= 0; i
< nNewTables
; ++i
) {
1129 tableDir
[pos
] = (Guchar
)(newTables
[i
].tag
>> 24);
1130 tableDir
[pos
+ 1] = (Guchar
)(newTables
[i
].tag
>> 16);
1131 tableDir
[pos
+ 2] = (Guchar
)(newTables
[i
].tag
>> 8);
1132 tableDir
[pos
+ 3] = (Guchar
) newTables
[i
].tag
;
1133 tableDir
[pos
+ 4] = (Guchar
)(newTables
[i
].checksum
>> 24);
1134 tableDir
[pos
+ 5] = (Guchar
)(newTables
[i
].checksum
>> 16);
1135 tableDir
[pos
+ 6] = (Guchar
)(newTables
[i
].checksum
>> 8);
1136 tableDir
[pos
+ 7] = (Guchar
) newTables
[i
].checksum
;
1137 tableDir
[pos
+ 8] = (Guchar
)(newTables
[i
].offset
>> 24);
1138 tableDir
[pos
+ 9] = (Guchar
)(newTables
[i
].offset
>> 16);
1139 tableDir
[pos
+10] = (Guchar
)(newTables
[i
].offset
>> 8);
1140 tableDir
[pos
+11] = (Guchar
) newTables
[i
].offset
;
1141 tableDir
[pos
+12] = (Guchar
)(newTables
[i
].len
>> 24);
1142 tableDir
[pos
+13] = (Guchar
)(newTables
[i
].len
>> 16);
1143 tableDir
[pos
+14] = (Guchar
)(newTables
[i
].len
>> 8);
1144 tableDir
[pos
+15] = (Guchar
) newTables
[i
].len
;
1148 // compute the font checksum and store it in the head table
1149 checksum
= computeTableChecksum(tableDir
, 12 + nNewTables
*16);
1150 for (i
= 0; i
< nNewTables
; ++i
) {
1151 checksum
+= newTables
[i
].checksum
;
1153 checksum
= 0xb1b0afba - checksum
; // because the TrueType spec says so
1154 headData
[ 8] = (Guchar
)(checksum
>> 24);
1155 headData
[ 9] = (Guchar
)(checksum
>> 16);
1156 headData
[10] = (Guchar
)(checksum
>> 8);
1157 headData
[11] = (Guchar
) checksum
;
1159 // start the sfnts array
1161 (*outputFunc
)(outputStream
, "/", 1);
1162 (*outputFunc
)(outputStream
, name
->getCString(), name
->getLength());
1163 (*outputFunc
)(outputStream
, " [\n", 3);
1165 (*outputFunc
)(outputStream
, "/sfnts [\n", 9);
1168 // write the table directory
1169 dumpString(tableDir
, 12 + nNewTables
*16, outputFunc
, outputStream
);
1172 for (i
= 0; i
< nNewTables
; ++i
) {
1173 if (i
== t42HeadTable
) {
1174 dumpString(headData
, 54, outputFunc
, outputStream
);
1175 } else if (i
== t42LocaTable
) {
1176 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1177 dumpString(locaData
, length
, outputFunc
, outputStream
);
1178 } else if (i
== t42GlyfTable
) {
1179 glyfPos
= tables
[seekTable("glyf")].offset
;
1180 for (j
= 0; j
< nGlyphs
; ++j
) {
1181 if (locaTable
[j
].len
> 0 &&
1182 checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1183 dumpString(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1184 locaTable
[j
].len
, outputFunc
, outputStream
);
1188 // length == 0 means the table is missing and the error was
1189 // already reported during the construction of the table
1191 if ((length
= newTables
[i
].len
) > 0) {
1192 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0 &&
1193 checkRegion(tables
[j
].offset
, tables
[j
].len
)) {
1194 dumpString(file
+ tables
[j
].offset
, tables
[j
].len
,
1195 outputFunc
, outputStream
);
1201 // end the sfnts array
1202 (*outputFunc
)(outputStream
, "] def\n", 6);
1208 void FoFiTrueType::dumpString(Guchar
*s
, int length
,
1209 FoFiOutputFunc outputFunc
,
1210 void *outputStream
) {
1214 (*outputFunc
)(outputStream
, "<", 1);
1215 for (i
= 0; i
< length
; i
+= 32) {
1216 for (j
= 0; j
< 32 && i
+j
< length
; ++j
) {
1217 sprintf(buf
, "%02X", s
[i
+j
] & 0xff);
1218 (*outputFunc
)(outputStream
, buf
, strlen(buf
));
1220 if (i
% (65536 - 32) == 65536 - 64) {
1221 (*outputFunc
)(outputStream
, ">\n<", 3);
1222 } else if (i
+32 < length
) {
1223 (*outputFunc
)(outputStream
, "\n", 1);
1227 pad
= 4 - (length
& 3);
1228 for (i
= 0; i
< pad
; ++i
) {
1229 (*outputFunc
)(outputStream
, "00", 2);
1232 // add an extra zero byte because the Adobe Type 42 spec says so
1233 (*outputFunc
)(outputStream
, "00>\n", 4);
1236 Guint
FoFiTrueType::computeTableChecksum(Guchar
*data
, int length
) {
1237 Guint checksum
, word
;
1241 for (i
= 0; i
+3 < length
; i
+= 4) {
1242 word
= ((data
[i
] & 0xff) << 24) +
1243 ((data
[i
+1] & 0xff) << 16) +
1244 ((data
[i
+2] & 0xff) << 8) +
1251 switch (length
& 3) {
1253 word
|= (data
[i
+2] & 0xff) << 8;
1255 word
|= (data
[i
+1] & 0xff) << 16;
1257 word
|= (data
[i
] & 0xff) << 24;
1265 void FoFiTrueType::parse() {
1270 // read the table directory
1271 nTables
= getU16BE(4, &parsedOk
);
1275 tables
= (TrueTypeTable
*)gmalloc(nTables
* sizeof(TrueTypeTable
));
1277 for (i
= 0; i
< nTables
; ++i
) {
1278 tables
[i
].tag
= getU32BE(pos
, &parsedOk
);
1279 tables
[i
].checksum
= getU32BE(pos
+ 4, &parsedOk
);
1280 tables
[i
].offset
= (int)getU32BE(pos
+ 8, &parsedOk
);
1281 tables
[i
].len
= (int)getU32BE(pos
+ 12, &parsedOk
);
1282 if (tables
[i
].offset
+ tables
[i
].len
< tables
[i
].offset
||
1283 tables
[i
].offset
+ tables
[i
].len
> len
) {
1292 // check for tables that are required by both the TrueType spec and
1294 if (seekTable("head") < 0 ||
1295 seekTable("hhea") < 0 ||
1296 seekTable("loca") < 0 ||
1297 seekTable("maxp") < 0 ||
1298 seekTable("glyf") < 0 ||
1299 seekTable("hmtx") < 0) {
1305 if ((i
= seekTable("cmap")) >= 0) {
1306 pos
= tables
[i
].offset
+ 2;
1307 nCmaps
= getU16BE(pos
, &parsedOk
);
1312 cmaps
= (TrueTypeCmap
*)gmalloc(nCmaps
* sizeof(TrueTypeCmap
));
1313 for (j
= 0; j
< nCmaps
; ++j
) {
1314 cmaps
[j
].platform
= getU16BE(pos
, &parsedOk
);
1315 cmaps
[j
].encoding
= getU16BE(pos
+ 2, &parsedOk
);
1316 cmaps
[j
].offset
= tables
[i
].offset
+ getU32BE(pos
+ 4, &parsedOk
);
1318 cmaps
[j
].fmt
= getU16BE(cmaps
[j
].offset
, &parsedOk
);
1319 cmaps
[j
].len
= getU16BE(cmaps
[j
].offset
+ 2, &parsedOk
);
1328 // get the number of glyphs from the maxp table
1329 i
= seekTable("maxp");
1330 nGlyphs
= getU16BE(tables
[i
].offset
+ 4, &parsedOk
);
1335 // get the bbox and loca table format from the head table
1336 i
= seekTable("head");
1337 bbox
[0] = getS16BE(tables
[i
].offset
+ 36, &parsedOk
);
1338 bbox
[1] = getS16BE(tables
[i
].offset
+ 38, &parsedOk
);
1339 bbox
[2] = getS16BE(tables
[i
].offset
+ 40, &parsedOk
);
1340 bbox
[3] = getS16BE(tables
[i
].offset
+ 42, &parsedOk
);
1341 locaFmt
= getS16BE(tables
[i
].offset
+ 50, &parsedOk
);
1346 // read the post table
1353 void FoFiTrueType::readPostTable() {
1355 int tablePos
, postFmt
, stringIdx
, stringPos
;
1358 if ((i
= seekTable("post")) < 0) {
1361 tablePos
= tables
[i
].offset
;
1362 postFmt
= getU32BE(tablePos
, &parsedOk
);
1366 if (postFmt
== 0x00010000) {
1367 nameToGID
= new GHash(gTrue
);
1368 for (i
= 0; i
< 258; ++i
) {
1369 nameToGID
->add(new GString(macGlyphNames
[i
]), i
);
1371 } else if (postFmt
== 0x00020000) {
1372 nameToGID
= new GHash(gTrue
);
1373 n
= getU16BE(tablePos
+ 32, &parsedOk
);
1381 stringPos
= tablePos
+ 34 + 2*n
;
1382 for (i
= 0; i
< n
; ++i
) {
1383 j
= getU16BE(tablePos
+ 34 + 2*i
, &parsedOk
);
1385 nameToGID
->removeInt(macGlyphNames
[j
]);
1386 nameToGID
->add(new GString(macGlyphNames
[j
]), i
);
1389 if (j
!= stringIdx
) {
1390 for (stringIdx
= 0, stringPos
= tablePos
+ 34 + 2*n
;
1392 ++stringIdx
, stringPos
+= 1 + getU8(stringPos
, &parsedOk
)) ;
1397 m
= getU8(stringPos
, &parsedOk
);
1398 if (!parsedOk
|| !checkRegion(stringPos
+ 1, m
)) {
1402 name
= new GString((char *)&file
[stringPos
+ 1], m
);
1403 nameToGID
->removeInt(name
);
1404 nameToGID
->add(name
, i
);
1409 } else if (postFmt
== 0x00028000) {
1410 nameToGID
= new GHash(gTrue
);
1411 for (i
= 0; i
< nGlyphs
; ++i
) {
1412 j
= getU8(tablePos
+ 32 + i
, &parsedOk
);
1417 nameToGID
->removeInt(macGlyphNames
[j
]);
1418 nameToGID
->add(new GString(macGlyphNames
[j
]), i
);
1424 int FoFiTrueType::seekTable(char *tag
) {
1428 tagI
= ((tag
[0] & 0xff) << 24) |
1429 ((tag
[1] & 0xff) << 16) |
1430 ((tag
[2] & 0xff) << 8) |
1432 for (i
= 0; i
< nTables
; ++i
) {
1433 if (tables
[i
].tag
== tagI
) {