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, 2012, 2014-2016 Albert Astals Cid <aacid@kde.org>
20 // Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
21 // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
22 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
23 // Copyright (C) 2014 Thomas Freitag <Thomas.Freitag@alfa.de>
24 // Copyright (C) 2015 Aleksei Volkov <Aleksei Volkov>
25 // Copyright (C) 2015, 2016 William Bader <williambader@hotmail.com>
27 // To see a description of the changes please see the Changelog file that
28 // came with your tarball or type make ChangeLog if you are building from git
30 //========================================================================
34 #ifdef USE_GCC_PRAGMAS
35 #pragma implementation
41 #include "goo/gtypes.h"
43 #include "goo/GooLikely.h"
44 #include "goo/GooString.h"
45 #include "goo/GooHash.h"
46 #include "FoFiType1C.h"
47 #include "FoFiTrueType.h"
48 #include "poppler/Error.h"
54 // character code = number used as an element of a text string
56 // character name = glyph name = name for a particular glyph within a
59 // glyph index = GID = position (within some internal table in the font)
60 // where the instructions to draw a particular glyph are
66 // Type 1 fonts contain:
68 // Encoding: array of glyph names, maps char codes to glyph names
70 // Encoding[charCode] = charName
72 // CharStrings: dictionary of instructions, keyed by character names,
73 // maps character name to glyph data
75 // CharStrings[charName] = glyphData
80 // TrueType fonts contain:
82 // 'cmap' table: mapping from character code to glyph index; there may
83 // be multiple cmaps in a TrueType font
85 // cmap[charCode] = gid
87 // 'post' table: mapping from glyph index to glyph name
89 // post[gid] = glyphName
94 // Type 42 fonts contain:
96 // Encoding: array of glyph names, maps char codes to glyph names
98 // Encoding[charCode] = charName
100 // CharStrings: dictionary of glyph indexes, keyed by character names,
101 // maps character name to glyph index
103 // CharStrings[charName] = gid
106 //------------------------------------------------------------------------
108 #define ttcfTag 0x74746366
110 //------------------------------------------------------------------------
112 struct TrueTypeTable
{
120 struct TrueTypeCmap
{
128 struct TrueTypeLoca
{
135 #define cmapTag 0x636d6170
136 #define glyfTag 0x676c7966
137 #define headTag 0x68656164
138 #define hheaTag 0x68686561
139 #define hmtxTag 0x686d7478
140 #define locaTag 0x6c6f6361
141 #define nameTag 0x6e616d65
142 #define os2Tag 0x4f532f32
143 #define postTag 0x706f7374
144 #define vrt2Tag 0x76727432
145 #define vertTag 0x76657274
147 struct cmpTrueTypeLocaOffsetFunctor
{
148 bool operator()(const TrueTypeLoca
&loca1
, const TrueTypeLoca
&loca2
) {
149 if (loca1
.origOffset
== loca2
.origOffset
) {
150 return loca1
.idx
< loca2
.idx
;
152 return loca1
.origOffset
< loca2
.origOffset
;
156 struct cmpTrueTypeLocaIdxFunctor
{
157 bool operator()(const TrueTypeLoca
&loca1
, const TrueTypeLoca
&loca2
) {
158 return loca1
.idx
< loca2
.idx
;
162 struct cmpTrueTypeTableTagFunctor
{
163 bool operator()(const TrueTypeTable
&tab1
, const TrueTypeTable
&tab2
) {
164 return tab1
.tag
< tab2
.tag
;
168 //------------------------------------------------------------------------
171 const char *tag
; // 4-byte tag
172 GBool required
; // required by the TrueType spec?
175 // TrueType tables to be embedded in Type 42 fonts.
176 // NB: the table names must be in alphabetical order here.
177 #define nT42Tables 11
178 static T42Table t42Tables
[nT42Tables
] = {
191 #define t42HeadTable 3
192 #define t42LocaTable 6
193 #define t42GlyfTable 2
194 #define t42VheaTable 9
195 #define t42VmtxTable 10
197 //------------------------------------------------------------------------
199 // Glyph names in some arbitrary standard order that Apple uses for
200 // their TrueType fonts.
201 static const char *macGlyphNames
[258] = {
202 ".notdef", "null", "CR", "space",
203 "exclam", "quotedbl", "numbersign", "dollar",
204 "percent", "ampersand", "quotesingle", "parenleft",
205 "parenright", "asterisk", "plus", "comma",
206 "hyphen", "period", "slash", "zero",
207 "one", "two", "three", "four",
208 "five", "six", "seven", "eight",
209 "nine", "colon", "semicolon", "less",
210 "equal", "greater", "question", "at",
217 "Y", "Z", "bracketleft", "backslash",
218 "bracketright", "asciicircum", "underscore", "grave",
225 "y", "z", "braceleft", "bar",
226 "braceright", "asciitilde", "Adieresis", "Aring",
227 "Ccedilla", "Eacute", "Ntilde", "Odieresis",
228 "Udieresis", "aacute", "agrave", "acircumflex",
229 "adieresis", "atilde", "aring", "ccedilla",
230 "eacute", "egrave", "ecircumflex", "edieresis",
231 "iacute", "igrave", "icircumflex", "idieresis",
232 "ntilde", "oacute", "ograve", "ocircumflex",
233 "odieresis", "otilde", "uacute", "ugrave",
234 "ucircumflex", "udieresis", "dagger", "degree",
235 "cent", "sterling", "section", "bullet",
236 "paragraph", "germandbls", "registered", "copyright",
237 "trademark", "acute", "dieresis", "notequal",
238 "AE", "Oslash", "infinity", "plusminus",
239 "lessequal", "greaterequal", "yen", "mu",
240 "partialdiff", "summation", "product", "pi",
241 "integral", "ordfeminine", "ordmasculine", "Omega",
242 "ae", "oslash", "questiondown", "exclamdown",
243 "logicalnot", "radical", "florin", "approxequal",
244 "increment", "guillemotleft", "guillemotright", "ellipsis",
245 "nbspace", "Agrave", "Atilde", "Otilde",
246 "OE", "oe", "endash", "emdash",
247 "quotedblleft", "quotedblright", "quoteleft", "quoteright",
248 "divide", "lozenge", "ydieresis", "Ydieresis",
249 "fraction", "currency", "guilsinglleft", "guilsinglright",
250 "fi", "fl", "daggerdbl", "periodcentered",
251 "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex",
252 "Ecircumflex", "Aacute", "Edieresis", "Egrave",
253 "Iacute", "Icircumflex", "Idieresis", "Igrave",
254 "Oacute", "Ocircumflex", "applelogo", "Ograve",
255 "Uacute", "Ucircumflex", "Ugrave", "dotlessi",
256 "circumflex", "tilde", "overscore", "breve",
257 "dotaccent", "ring", "cedilla", "hungarumlaut",
258 "ogonek", "caron", "Lslash", "lslash",
259 "Scaron", "scaron", "Zcaron", "zcaron",
260 "brokenbar", "Eth", "eth", "Yacute",
261 "yacute", "Thorn", "thorn", "minus",
262 "multiply", "onesuperior", "twosuperior", "threesuperior",
263 "onehalf", "onequarter", "threequarters", "franc",
264 "Gbreve", "gbreve", "Idot", "Scedilla",
265 "scedilla", "Cacute", "cacute", "Ccaron",
269 //------------------------------------------------------------------------
271 //------------------------------------------------------------------------
273 FoFiTrueType
*FoFiTrueType::make(char *fileA
, int lenA
, int faceIndexA
) {
276 ff
= new FoFiTrueType(fileA
, lenA
, gFalse
, faceIndexA
);
284 FoFiTrueType
*FoFiTrueType::load(char *fileName
, int faceIndexA
) {
289 if (!(fileA
= FoFiBase::readFile(fileName
, &lenA
))) {
292 ff
= new FoFiTrueType(fileA
, lenA
, gTrue
, faceIndexA
);
300 FoFiTrueType::FoFiTrueType(char *fileA
, int lenA
, GBool freeFileDataA
, int faceIndexA
):
301 FoFiBase(fileA
, lenA
, freeFileDataA
)
309 faceIndex
= faceIndexA
;
310 gsubFeatureTable
= 0;
316 FoFiTrueType::~FoFiTrueType() {
324 int FoFiTrueType::getNumCmaps() {
328 int FoFiTrueType::getCmapPlatform(int i
) {
329 return cmaps
[i
].platform
;
332 int FoFiTrueType::getCmapEncoding(int i
) {
333 return cmaps
[i
].encoding
;
336 int FoFiTrueType::findCmap(int platform
, int encoding
) {
339 for (i
= 0; i
< nCmaps
; ++i
) {
340 if (cmaps
[i
].platform
== platform
&& cmaps
[i
].encoding
== encoding
) {
347 int FoFiTrueType::mapCodeToGID(int i
, Guint c
) {
349 Guint segCnt
, segEnd
, segStart
, segDelta
, segOffset
;
350 Guint cmapFirst
, cmapLen
;
354 if (i
< 0 || i
>= nCmaps
) {
358 pos
= cmaps
[i
].offset
;
359 switch (cmaps
[i
].fmt
) {
361 if (c
+ 6 >= (Guint
)cmaps
[i
].len
) {
364 gid
= getU8(cmaps
[i
].offset
+ 6 + c
, &ok
);
367 segCnt
= getU16BE(pos
+ 6, &ok
) / 2;
370 segEnd
= getU16BE(pos
+ 14 + 2*b
, &ok
);
372 // malformed font -- the TrueType spec requires the last segEnd
376 // invariant: seg[a].end < code <= seg[b].end
377 while (b
- a
> 1 && ok
) {
379 segEnd
= getU16BE(pos
+ 14 + 2*m
, &ok
);
386 segStart
= getU16BE(pos
+ 16 + 2*segCnt
+ 2*b
, &ok
);
387 segDelta
= getU16BE(pos
+ 16 + 4*segCnt
+ 2*b
, &ok
);
388 segOffset
= getU16BE(pos
+ 16 + 6*segCnt
+ 2*b
, &ok
);
392 if (segOffset
== 0) {
393 gid
= (c
+ segDelta
) & 0xffff;
395 gid
= getU16BE(pos
+ 16 + 6*segCnt
+ 2*b
+
396 segOffset
+ 2 * (c
- segStart
), &ok
);
398 gid
= (gid
+ segDelta
) & 0xffff;
403 cmapFirst
= getU16BE(pos
+ 6, &ok
);
404 cmapLen
= getU16BE(pos
+ 8, &ok
);
405 if (c
< cmapFirst
|| c
>= cmapFirst
+ cmapLen
) {
408 gid
= getU16BE(pos
+ 10 + 2 * (c
- cmapFirst
), &ok
);
411 segCnt
= getU32BE(pos
+ 12, &ok
);
414 segEnd
= getU32BE(pos
+ 16 + 12*b
+4, &ok
);
418 // invariant: seg[a].end < code <= seg[b].end
419 while (b
- a
> 1 && ok
) {
421 segEnd
= getU32BE(pos
+ 16 + 12*m
+4, &ok
);
428 segStart
= getU32BE(pos
+ 16 + 12*b
, &ok
);
429 segDelta
= getU32BE(pos
+ 16 + 12*b
+8, &ok
);
433 gid
= segDelta
+ (c
-segStart
);
444 int FoFiTrueType::mapNameToGID(char *name
) {
448 return nameToGID
->lookupInt(name
);
451 GBool
FoFiTrueType::getCFFBlock(char **start
, int *length
) {
457 i
= seekTable("CFF ");
458 if (!checkRegion(tables
[i
].offset
, tables
[i
].len
)) {
461 *start
= (char *)file
+ tables
[i
].offset
;
462 *length
= tables
[i
].len
;
466 int *FoFiTrueType::getCIDToGIDMap(int *nCIDs
) {
473 if (!getCFFBlock(&start
, &length
)) {
476 if (!(ff
= FoFiType1C::make(start
, length
))) {
479 map
= ff
->getCIDToGIDMap(nCIDs
);
484 int FoFiTrueType::getEmbeddingRights() {
488 if ((i
= seekTable("OS/2")) < 0) {
492 fsType
= getU16BE(tables
[i
].offset
+ 8, &ok
);
496 if (fsType
& 0x0008) {
499 if (fsType
& 0x0004) {
502 if (fsType
& 0x0002) {
508 void FoFiTrueType::getFontMatrix(double *mat
) {
513 if (!getCFFBlock(&start
, &length
)) {
516 if (!(ff
= FoFiType1C::make(start
, length
))) {
519 ff
->getFontMatrix(mat
);
523 void FoFiTrueType::convertToType42(char *psName
, char **encoding
,
525 FoFiOutputFunc outputFunc
,
526 void *outputStream
) {
537 buf
= GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
538 (double)getS32BE(0, &ok
) / 65536.0);
539 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
542 // begin the font dictionary
543 (*outputFunc
)(outputStream
, "10 dict begin\n", 14);
544 (*outputFunc
)(outputStream
, "/FontName /", 11);
545 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
546 (*outputFunc
)(outputStream
, " def\n", 5);
547 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
548 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
549 buf
= GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
550 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
551 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
553 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
555 // write the guts of the dictionary
556 cvtEncoding(encoding
, outputFunc
, outputStream
);
557 cvtCharStrings(encoding
, codeToGID
, outputFunc
, outputStream
);
558 cvtSfnts(outputFunc
, outputStream
, NULL
, gFalse
, &maxUsedGlyph
);
560 // end the dictionary and define the font
561 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
564 void FoFiTrueType::convertToType1(char *psName
, const char **newEncoding
,
565 GBool ascii
, FoFiOutputFunc outputFunc
,
566 void *outputStream
) {
571 if (!getCFFBlock(&start
, &length
)) {
574 if (!(ff
= FoFiType1C::make(start
, length
))) {
577 ff
->convertToType1(psName
, newEncoding
, ascii
, outputFunc
, outputStream
);
581 void FoFiTrueType::convertToCIDType2(char *psName
,
582 int *cidMap
, int nCIDs
,
583 GBool needVerticalMetrics
,
584 FoFiOutputFunc outputFunc
,
585 void *outputStream
) {
587 int cid
, maxUsedGlyph
;
597 buf
= GooString::format("%!PS-TrueTypeFont-{0:2g}\n",
598 (double)getS32BE(0, &ok
) / 65536.0);
599 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
602 // begin the font dictionary
603 (*outputFunc
)(outputStream
, "20 dict begin\n", 14);
604 (*outputFunc
)(outputStream
, "/CIDFontName /", 14);
605 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
606 (*outputFunc
)(outputStream
, " def\n", 5);
607 (*outputFunc
)(outputStream
, "/CIDFontType 2 def\n", 19);
608 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
609 (*outputFunc
)(outputStream
, "/CIDSystemInfo 3 dict dup begin\n", 32);
610 (*outputFunc
)(outputStream
, " /Registry (Adobe) def\n", 24);
611 (*outputFunc
)(outputStream
, " /Ordering (Identity) def\n", 27);
612 (*outputFunc
)(outputStream
, " /Supplement 0 def\n", 20);
613 (*outputFunc
)(outputStream
, " end def\n", 10);
614 (*outputFunc
)(outputStream
, "/GDBytes 2 def\n", 15);
616 buf
= GooString::format("/CIDCount {0:d} def\n", nCIDs
);
617 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
620 (*outputFunc
)(outputStream
, "/CIDMap [", 9);
621 for (i
= 0; i
< nCIDs
; i
+= 32768 - 16) {
622 (*outputFunc
)(outputStream
, "<\n", 2);
623 for (j
= 0; j
< 32768 - 16 && i
+j
< nCIDs
; j
+= 16) {
624 (*outputFunc
)(outputStream
, " ", 2);
625 for (k
= 0; k
< 16 && i
+j
+k
< nCIDs
; ++k
) {
627 buf
= GooString::format("{0:02x}{1:02x}",
628 (cid
>> 8) & 0xff, cid
& 0xff);
629 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
632 (*outputFunc
)(outputStream
, "\n", 1);
634 (*outputFunc
)(outputStream
, " >", 3);
636 (*outputFunc
)(outputStream
, "\n", 1);
637 (*outputFunc
)(outputStream
, "] def\n", 6);
639 (*outputFunc
)(outputStream
, "/CIDMap <\n", 10);
640 for (i
= 0; i
< nCIDs
; i
+= 16) {
641 (*outputFunc
)(outputStream
, " ", 2);
642 for (j
= 0; j
< 16 && i
+j
< nCIDs
; ++j
) {
644 buf
= GooString::format("{0:02x}{1:02x}",
645 (cid
>> 8) & 0xff, cid
& 0xff);
646 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
649 (*outputFunc
)(outputStream
, "\n", 1);
651 (*outputFunc
)(outputStream
, "> def\n", 6);
654 // direct mapping - just fill the string(s) with s[i]=i
655 buf
= GooString::format("/CIDCount {0:d} def\n", nGlyphs
);
656 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
658 if (nGlyphs
> 32767) {
659 (*outputFunc
)(outputStream
, "/CIDMap [\n", 10);
660 for (i
= 0; i
< nGlyphs
; i
+= 32767) {
661 j
= nGlyphs
- i
< 32767 ? nGlyphs
- i
: 32767;
662 buf
= GooString::format(" {0:d} string 0 1 {1:d} {{\n", 2 * j
, j
- 1);
663 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
665 buf
= GooString::format(" 2 copy dup 2 mul exch {0:d} add -8 bitshift put\n",
667 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
669 buf
= GooString::format(" 1 index exch dup 2 mul 1 add exch {0:d} add"
670 " 255 and put\n", i
);
671 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
673 (*outputFunc
)(outputStream
, " } for\n", 8);
675 (*outputFunc
)(outputStream
, "] def\n", 6);
677 buf
= GooString::format("/CIDMap {0:d} string\n", 2 * nGlyphs
);
678 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
680 buf
= GooString::format(" 0 1 {0:d} {{\n", nGlyphs
- 1);
681 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
683 (*outputFunc
)(outputStream
,
684 " 2 copy dup 2 mul exch -8 bitshift put\n", 42);
685 (*outputFunc
)(outputStream
,
686 " 1 index exch dup 2 mul 1 add exch 255 and put\n", 50);
687 (*outputFunc
)(outputStream
, " } for\n", 8);
688 (*outputFunc
)(outputStream
, "def\n", 4);
691 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
692 buf
= GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
693 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
694 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
696 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
697 (*outputFunc
)(outputStream
, "/Encoding [] readonly def\n", 26);
698 (*outputFunc
)(outputStream
, "/CharStrings 1 dict dup begin\n", 30);
699 (*outputFunc
)(outputStream
, " /.notdef 0 def\n", 17);
700 (*outputFunc
)(outputStream
, " end readonly def\n", 19);
702 // write the guts of the dictionary
703 cvtSfnts(outputFunc
, outputStream
, NULL
, needVerticalMetrics
, &maxUsedGlyph
);
705 // end the dictionary and define the font
706 (*outputFunc
)(outputStream
,
707 "CIDFontName currentdict end /CIDFont defineresource pop\n",
711 void FoFiTrueType::convertToCIDType0(char *psName
, int *cidMap
, int nCIDs
,
712 FoFiOutputFunc outputFunc
,
713 void *outputStream
) {
718 if (!getCFFBlock(&start
, &length
)) {
721 if (!(ff
= FoFiType1C::make(start
, length
))) {
724 ff
->convertToCIDType0(psName
, cidMap
, nCIDs
, outputFunc
, outputStream
);
728 void FoFiTrueType::convertToType0(char *psName
, int *cidMap
, int nCIDs
,
729 GBool needVerticalMetrics
,
731 FoFiOutputFunc outputFunc
,
732 void *outputStream
) {
734 GooString
*sfntsName
;
735 int maxUsedGlyph
, n
, i
, j
;
743 // write the Type 42 sfnts array
744 sfntsName
= (new GooString(psName
))->append("_sfnts");
745 cvtSfnts(outputFunc
, outputStream
, sfntsName
, needVerticalMetrics
,
749 // write the descendant Type 42 fonts
750 // (The following is a kludge: nGlyphs is the glyph count from the
751 // maxp table; maxUsedGlyph is the max glyph number that has a
752 // non-zero-length description, from the loca table. The problem is
753 // that some TrueType font subsets fail to change the glyph count,
754 // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
755 // in an unnecessarily huge Type 0 font. But some other PDF files
756 // have fonts with only zero or one used glyph, and a content stream
757 // that refers to one of the unused glyphs -- this results in PS
758 // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
759 // we compromise by always defining at least 256 glyphs.)
760 // Some fonts have a large nGlyphs but maxUsedGlyph of 0.
761 // These fonts might reference any glyph.
762 // Return the last written glyph number in maxValidGlyph.
763 // PSOutputDev::drawString() can use maxValidGlyph to avoid
764 // referencing zero-length glyphs that we trimmed.
765 // This allows pdftops to avoid writing huge files while still
766 // handling the rare PDF that uses a zero-length glyph.
769 } else if (nGlyphs
> maxUsedGlyph
+ 256) {
770 if (maxUsedGlyph
<= 255) {
773 n
= maxUsedGlyph
+ 1;
778 *maxValidGlyph
= n
-1;
779 for (i
= 0; i
< n
; i
+= 256) {
780 (*outputFunc
)(outputStream
, "10 dict begin\n", 14);
781 (*outputFunc
)(outputStream
, "/FontName /", 11);
782 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
783 buf
= GooString::format("_{0:02x} def\n", i
>> 8);
784 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
786 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
787 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
788 buf
= GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
789 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
790 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
792 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
793 (*outputFunc
)(outputStream
, "/sfnts ", 7);
794 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
795 (*outputFunc
)(outputStream
, "_sfnts def\n", 11);
796 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
797 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
798 buf
= GooString::format("dup {0:d} /c{1:02x} put\n", j
, j
);
799 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
802 (*outputFunc
)(outputStream
, "readonly def\n", 13);
803 (*outputFunc
)(outputStream
, "/CharStrings 257 dict dup begin\n", 32);
804 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
805 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
806 buf
= GooString::format("/c{0:02x} {1:d} def\n",
807 j
, cidMap
? cidMap
[i
+j
] : i
+j
);
808 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
811 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
812 (*outputFunc
)(outputStream
,
813 "FontName currentdict end definefont pop\n", 40);
816 // write the Type 0 parent font
817 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
818 (*outputFunc
)(outputStream
, "/FontName /", 11);
819 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
820 (*outputFunc
)(outputStream
, " def\n", 5);
821 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
822 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
823 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
824 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
825 for (i
= 0; i
< n
; i
+= 256) {
826 buf
= GooString::format("{0:d}\n", i
>> 8);
827 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
830 (*outputFunc
)(outputStream
, "] def\n", 6);
831 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
832 for (i
= 0; i
< n
; i
+= 256) {
833 (*outputFunc
)(outputStream
, "/", 1);
834 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
835 buf
= GooString::format("_{0:02x} findfont\n", i
>> 8);
836 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
839 (*outputFunc
)(outputStream
, "] def\n", 6);
840 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
843 void FoFiTrueType::convertToType0(char *psName
, int *cidMap
, int nCIDs
,
844 FoFiOutputFunc outputFunc
,
845 void *outputStream
) {
850 if (!getCFFBlock(&start
, &length
)) {
853 if (!(ff
= FoFiType1C::make(start
, length
))) {
856 ff
->convertToType0(psName
, cidMap
, nCIDs
, outputFunc
, outputStream
);
860 void FoFiTrueType::cvtEncoding(char **encoding
,
861 FoFiOutputFunc outputFunc
,
862 void *outputStream
) {
867 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
869 for (i
= 0; i
< 256; ++i
) {
870 if (!(name
= encoding
[i
])) {
873 buf
= GooString::format("dup {0:d} /", i
);
874 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
876 (*outputFunc
)(outputStream
, name
, strlen(name
));
877 (*outputFunc
)(outputStream
, " put\n", 5);
880 for (i
= 0; i
< 256; ++i
) {
881 buf
= GooString::format("dup {0:d} /c{1:02x} put\n", i
, i
);
882 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
886 (*outputFunc
)(outputStream
, "readonly def\n", 13);
889 void FoFiTrueType::cvtCharStrings(char **encoding
,
891 FoFiOutputFunc outputFunc
,
892 void *outputStream
) {
898 // always define '.notdef'
899 (*outputFunc
)(outputStream
, "/CharStrings 256 dict dup begin\n", 32);
900 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
902 // if there's no 'cmap' table, punt
907 // map char name to glyph index:
908 // 1. use encoding to map name to char code
909 // 2. use codeToGID to map char code to glyph index
910 // N.B. We do this in reverse order because font subsets can have
911 // weird encodings that use the same character name twice, and
912 // the first definition is probably the one we want.
913 k
= 0; // make gcc happy
914 for (i
= 255; i
>= 0; --i
) {
918 sprintf(buf2
, "c%02x", i
);
921 if (name
&& strcmp(name
, ".notdef")) {
923 // note: Distiller (maybe Adobe's PS interpreter in general)
924 // doesn't like TrueType fonts that have CharStrings entries
925 // which point to nonexistent glyphs, hence the (k < nGlyphs)
927 if (k
> 0 && k
< nGlyphs
) {
928 (*outputFunc
)(outputStream
, "/", 1);
929 (*outputFunc
)(outputStream
, name
, strlen(name
));
930 buf
= GooString::format(" {0:d} def\n", k
);
931 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
938 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
941 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc
,
942 void *outputStream
, GooString
*name
,
943 GBool needVerticalMetrics
,
946 TrueTypeLoca
*locaTable
;
948 TrueTypeTable newTables
[nT42Tables
];
949 Guchar tableDir
[12 + nT42Tables
*16];
953 int glyfTableLen
, length
, pos
, glyfPos
, i
, j
, k
, vmtxTabLength
;
954 Guchar vheaTab
[36] = {
955 0, 1, 0, 0, // table version number
959 0, 0, // max advance height
960 0, 0, // min top side bearing
961 0, 0, // min bottom side bearing
962 0, 0, // y max extent
963 0, 0, // caret slope rise
964 0, 1, // caret slope run
965 0, 0, // caret offset
970 0, 0, // metric data format
971 0, 1 // number of advance heights in vmtx table
974 GBool needVhea
, needVmtx
;
977 // construct the 'head' table, zero out the font checksum
978 i
= seekTable("head");
979 if (i
< 0 || i
>= nTables
) {
982 pos
= tables
[i
].offset
;
983 if (!checkRegion(pos
, 54)) {
986 memcpy(headData
, file
+ pos
, 54);
987 headData
[8] = headData
[9] = headData
[10] = headData
[11] = (Guchar
)0;
989 // check for a bogus loca format field in the 'head' table
990 // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
991 if (locaFmt
!= 0 && locaFmt
!= 1) {
996 // read the original 'loca' table, pad entries out to 4 bytes, and
997 // sort it into proper order -- some (non-compliant) fonts have
998 // out-of-order loca tables; in order to correctly handle the case
999 // where (compliant) fonts have empty entries in the middle of the
1000 // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
1001 // and idx as its secondary key (ensuring that adjacent entries with
1002 // the same pos value remain in the same order)
1003 locaTable
= (TrueTypeLoca
*)gmallocn(nGlyphs
+ 1, sizeof(TrueTypeLoca
));
1004 i
= seekTable("loca");
1005 pos
= tables
[i
].offset
;
1006 i
= seekTable("glyf");
1007 glyfTableLen
= tables
[i
].len
;
1009 for (i
= 0; i
<= nGlyphs
; ++i
) {
1010 locaTable
[i
].idx
= i
;
1012 locaTable
[i
].origOffset
= (int)getU32BE(pos
+ i
*4, &ok
);
1014 locaTable
[i
].origOffset
= 2 * getU16BE(pos
+ i
*2, &ok
);
1016 if (locaTable
[i
].origOffset
> glyfTableLen
) {
1017 locaTable
[i
].origOffset
= glyfTableLen
;
1020 std::sort(locaTable
, locaTable
+ nGlyphs
+ 1,
1021 cmpTrueTypeLocaOffsetFunctor());
1022 for (i
= 0; i
< nGlyphs
; ++i
) {
1023 locaTable
[i
].len
= locaTable
[i
+1].origOffset
- locaTable
[i
].origOffset
;
1025 locaTable
[nGlyphs
].len
= 0;
1026 std::sort(locaTable
, locaTable
+ nGlyphs
+ 1, cmpTrueTypeLocaIdxFunctor());
1029 for (i
= 0; i
<= nGlyphs
; ++i
) {
1030 locaTable
[i
].newOffset
= pos
;
1031 pos
+= locaTable
[i
].len
;
1033 pos
+= 4 - (pos
& 3);
1035 if (locaTable
[i
].len
> 0) {
1040 // construct the new 'loca' table
1041 locaData
= (Guchar
*)gmallocn(nGlyphs
+ 1, (locaFmt
? 4 : 2));
1042 for (i
= 0; i
<= nGlyphs
; ++i
) {
1043 pos
= locaTable
[i
].newOffset
;
1045 locaData
[4*i
] = (Guchar
)(pos
>> 24);
1046 locaData
[4*i
+1] = (Guchar
)(pos
>> 16);
1047 locaData
[4*i
+2] = (Guchar
)(pos
>> 8);
1048 locaData
[4*i
+3] = (Guchar
) pos
;
1050 locaData
[2*i
] = (Guchar
)(pos
>> 9);
1051 locaData
[2*i
+1] = (Guchar
)(pos
>> 1);
1055 // count the number of tables
1057 for (i
= 0; i
< nT42Tables
; ++i
) {
1058 if (t42Tables
[i
].required
||
1059 seekTable(t42Tables
[i
].tag
) >= 0) {
1063 vmtxTab
= NULL
; // make gcc happy
1065 advance
= 0; // make gcc happy
1066 if (needVerticalMetrics
) {
1067 needVhea
= seekTable("vhea") < 0;
1068 needVmtx
= seekTable("vmtx") < 0;
1069 if (needVhea
|| needVmtx
) {
1070 i
= seekTable("head");
1071 advance
= getU16BE(tables
[i
].offset
+ 18, &ok
); // units per em
1081 // construct the new table headers, including table checksums
1082 // (pad each table out to a multiple of 4 bytes)
1083 pos
= 12 + nNewTables
*16;
1085 for (i
= 0; i
< nT42Tables
; ++i
) {
1087 checksum
= 0; // make gcc happy
1088 if (i
== t42HeadTable
) {
1090 checksum
= computeTableChecksum(headData
, 54);
1091 } else if (i
== t42LocaTable
) {
1092 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1093 checksum
= computeTableChecksum(locaData
, length
);
1094 } else if (i
== t42GlyfTable
) {
1097 glyfPos
= tables
[seekTable("glyf")].offset
;
1098 for (j
= 0; j
< nGlyphs
; ++j
) {
1099 length
+= locaTable
[j
].len
;
1101 length
+= 4 - (length
& 3);
1103 if (checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1105 computeTableChecksum(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1110 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0) {
1111 length
= tables
[j
].len
;
1112 if (checkRegion(tables
[j
].offset
, length
)) {
1113 checksum
= computeTableChecksum(file
+ tables
[j
].offset
, length
);
1115 } else if (needVerticalMetrics
&& i
== t42VheaTable
) {
1116 vheaTab
[10] = advance
/ 256; // max advance height
1117 vheaTab
[11] = advance
% 256;
1118 length
= sizeof(vheaTab
);
1119 checksum
= computeTableChecksum(vheaTab
, length
);
1120 } else if (needVerticalMetrics
&& i
== t42VmtxTable
) {
1121 length
= 4 + (nGlyphs
- 1) * 2;
1122 vmtxTabLength
= length
;
1123 vmtxTab
= (Guchar
*)gmalloc(length
);
1124 vmtxTab
[0] = advance
/ 256;
1125 vmtxTab
[1] = advance
% 256;
1126 for (j
= 2; j
< length
; j
+= 2) {
1130 checksum
= computeTableChecksum(vmtxTab
, length
);
1131 } else if (t42Tables
[i
].required
) {
1132 //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1133 //~ t42Tables[i].tag);
1139 newTables
[k
].tag
= ((t42Tables
[i
].tag
[0] & 0xff) << 24) |
1140 ((t42Tables
[i
].tag
[1] & 0xff) << 16) |
1141 ((t42Tables
[i
].tag
[2] & 0xff) << 8) |
1142 (t42Tables
[i
].tag
[3] & 0xff);
1143 newTables
[k
].checksum
= checksum
;
1144 newTables
[k
].offset
= pos
;
1145 newTables
[k
].len
= length
;
1148 pos
+= 4 - (length
& 3);
1154 // construct the table directory
1155 tableDir
[0] = 0x00; // sfnt version
1159 tableDir
[4] = 0; // numTables
1160 tableDir
[5] = nNewTables
;
1161 tableDir
[6] = 0; // searchRange
1162 tableDir
[7] = (Guchar
)128;
1163 tableDir
[8] = 0; // entrySelector
1165 tableDir
[10] = 0; // rangeShift
1166 tableDir
[11] = (Guchar
)(16 * nNewTables
- 128);
1168 for (i
= 0; i
< nNewTables
; ++i
) {
1169 tableDir
[pos
] = (Guchar
)(newTables
[i
].tag
>> 24);
1170 tableDir
[pos
+ 1] = (Guchar
)(newTables
[i
].tag
>> 16);
1171 tableDir
[pos
+ 2] = (Guchar
)(newTables
[i
].tag
>> 8);
1172 tableDir
[pos
+ 3] = (Guchar
) newTables
[i
].tag
;
1173 tableDir
[pos
+ 4] = (Guchar
)(newTables
[i
].checksum
>> 24);
1174 tableDir
[pos
+ 5] = (Guchar
)(newTables
[i
].checksum
>> 16);
1175 tableDir
[pos
+ 6] = (Guchar
)(newTables
[i
].checksum
>> 8);
1176 tableDir
[pos
+ 7] = (Guchar
) newTables
[i
].checksum
;
1177 tableDir
[pos
+ 8] = (Guchar
)(newTables
[i
].offset
>> 24);
1178 tableDir
[pos
+ 9] = (Guchar
)(newTables
[i
].offset
>> 16);
1179 tableDir
[pos
+10] = (Guchar
)(newTables
[i
].offset
>> 8);
1180 tableDir
[pos
+11] = (Guchar
) newTables
[i
].offset
;
1181 tableDir
[pos
+12] = (Guchar
)(newTables
[i
].len
>> 24);
1182 tableDir
[pos
+13] = (Guchar
)(newTables
[i
].len
>> 16);
1183 tableDir
[pos
+14] = (Guchar
)(newTables
[i
].len
>> 8);
1184 tableDir
[pos
+15] = (Guchar
) newTables
[i
].len
;
1188 // compute the font checksum and store it in the head table
1189 checksum
= computeTableChecksum(tableDir
, 12 + nNewTables
*16);
1190 for (i
= 0; i
< nNewTables
; ++i
) {
1191 checksum
+= newTables
[i
].checksum
;
1193 checksum
= 0xb1b0afba - checksum
; // because the TrueType spec says so
1194 headData
[ 8] = (Guchar
)(checksum
>> 24);
1195 headData
[ 9] = (Guchar
)(checksum
>> 16);
1196 headData
[10] = (Guchar
)(checksum
>> 8);
1197 headData
[11] = (Guchar
) checksum
;
1199 // start the sfnts array
1201 (*outputFunc
)(outputStream
, "/", 1);
1202 (*outputFunc
)(outputStream
, name
->getCString(), name
->getLength());
1203 (*outputFunc
)(outputStream
, " [\n", 3);
1205 (*outputFunc
)(outputStream
, "/sfnts [\n", 9);
1208 // write the table directory
1209 dumpString(tableDir
, 12 + nNewTables
*16, outputFunc
, outputStream
);
1212 for (i
= 0; i
< nNewTables
; ++i
) {
1213 if (i
== t42HeadTable
) {
1214 dumpString(headData
, 54, outputFunc
, outputStream
);
1215 } else if (i
== t42LocaTable
) {
1216 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1217 dumpString(locaData
, length
, outputFunc
, outputStream
);
1218 } else if (i
== t42GlyfTable
) {
1219 glyfPos
= tables
[seekTable("glyf")].offset
;
1220 for (j
= 0; j
< nGlyphs
; ++j
) {
1221 if (locaTable
[j
].len
> 0 &&
1222 checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1223 dumpString(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1224 locaTable
[j
].len
, outputFunc
, outputStream
);
1228 // length == 0 means the table is missing and the error was
1229 // already reported during the construction of the table
1231 if ((length
= newTables
[i
].len
) > 0) {
1232 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0 &&
1233 checkRegion(tables
[j
].offset
, tables
[j
].len
)) {
1234 dumpString(file
+ tables
[j
].offset
, tables
[j
].len
,
1235 outputFunc
, outputStream
);
1236 } else if (needVerticalMetrics
&& i
== t42VheaTable
) {
1237 if (unlikely(length
> (int)sizeof(vheaTab
))) {
1238 error(errSyntaxWarning
, -1, "length bigger than vheaTab size");
1239 length
= sizeof(vheaTab
);
1241 dumpString(vheaTab
, length
, outputFunc
, outputStream
);
1242 } else if (needVerticalMetrics
&& i
== t42VmtxTable
) {
1243 if (unlikely(length
> vmtxTabLength
)) {
1244 error(errSyntaxWarning
, -1, "length bigger than vmtxTab size");
1245 length
= vmtxTabLength
;
1247 dumpString(vmtxTab
, length
, outputFunc
, outputStream
);
1253 // end the sfnts array
1254 (*outputFunc
)(outputStream
, "] def\n", 6);
1263 void FoFiTrueType::dumpString(Guchar
*s
, int length
,
1264 FoFiOutputFunc outputFunc
,
1265 void *outputStream
) {
1269 (*outputFunc
)(outputStream
, "<", 1);
1270 for (i
= 0; i
< length
; i
+= 32) {
1271 for (j
= 0; j
< 32 && i
+j
< length
; ++j
) {
1272 buf
= GooString::format("{0:02x}", s
[i
+j
] & 0xff);
1273 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1276 if (i
% (65536 - 32) == 65536 - 64) {
1277 (*outputFunc
)(outputStream
, ">\n<", 3);
1278 } else if (i
+32 < length
) {
1279 (*outputFunc
)(outputStream
, "\n", 1);
1283 pad
= 4 - (length
& 3);
1284 for (i
= 0; i
< pad
; ++i
) {
1285 (*outputFunc
)(outputStream
, "00", 2);
1288 // add an extra zero byte because the Adobe Type 42 spec says so
1289 (*outputFunc
)(outputStream
, "00>\n", 4);
1292 Guint
FoFiTrueType::computeTableChecksum(Guchar
*data
, int length
) {
1293 Guint checksum
, word
;
1297 for (i
= 0; i
+3 < length
; i
+= 4) {
1298 word
= ((data
[i
] & 0xff) << 24) +
1299 ((data
[i
+1] & 0xff) << 16) +
1300 ((data
[i
+2] & 0xff) << 8) +
1307 switch (length
& 3) {
1309 word
|= (data
[i
+2] & 0xff) << 8;
1311 word
|= (data
[i
+1] & 0xff) << 16;
1313 word
|= (data
[i
] & 0xff) << 24;
1321 void FoFiTrueType::parse() {
1327 // look for a collection (TTC)
1328 topTag
= getU32BE(0, &parsedOk
);
1332 if (topTag
== ttcfTag
) {
1336 dircount
= getU32BE(8, &parsedOk
);
1344 if (faceIndex
>= dircount
)
1346 pos
= getU32BE(12 + faceIndex
* 4, &parsedOk
);
1353 // check the sfnt version
1354 ver
= getU32BE(pos
, &parsedOk
);
1358 openTypeCFF
= ver
== 0x4f54544f; // 'OTTO'
1360 // read the table directory
1361 nTables
= getU16BE(pos
+ 4, &parsedOk
);
1365 tables
= (TrueTypeTable
*)gmallocn(nTables
, sizeof(TrueTypeTable
));
1368 for (i
= 0; i
< nTables
; ++i
) {
1369 tables
[j
].tag
= getU32BE(pos
, &parsedOk
);
1370 tables
[j
].checksum
= getU32BE(pos
+ 4, &parsedOk
);
1371 tables
[j
].offset
= (int)getU32BE(pos
+ 8, &parsedOk
);
1372 tables
[j
].len
= (int)getU32BE(pos
+ 12, &parsedOk
);
1373 if (unlikely((tables
[j
].offset
< 0) ||
1374 (tables
[j
].len
< 0) ||
1375 (tables
[j
].offset
< INT_MAX
- tables
[j
].len
) ||
1376 (tables
[j
].len
> INT_MAX
- tables
[j
].offset
) ||
1377 (tables
[j
].offset
+ tables
[j
].len
>= tables
[j
].offset
&& tables
[j
].offset
+ tables
[j
].len
<= len
))) {
1378 // ignore any bogus entries in the table directory
1385 tables
= (TrueTypeTable
*)greallocn_checkoverflow(tables
, nTables
, sizeof(TrueTypeTable
));
1387 if (!parsedOk
|| tables
== NULL
) {
1391 // check for tables that are required by both the TrueType spec and
1393 if (seekTable("head") < 0 ||
1394 seekTable("hhea") < 0 ||
1395 seekTable("maxp") < 0 ||
1396 (!openTypeCFF
&& seekTable("loca") < 0) ||
1397 (!openTypeCFF
&& seekTable("glyf") < 0) ||
1398 (openTypeCFF
&& seekTable("CFF ") < 0)) {
1404 if ((i
= seekTable("cmap")) >= 0) {
1405 pos
= tables
[i
].offset
+ 2;
1406 nCmaps
= getU16BE(pos
, &parsedOk
);
1411 cmaps
= (TrueTypeCmap
*)gmallocn(nCmaps
, sizeof(TrueTypeCmap
));
1412 for (j
= 0; j
< nCmaps
; ++j
) {
1413 cmaps
[j
].platform
= getU16BE(pos
, &parsedOk
);
1414 cmaps
[j
].encoding
= getU16BE(pos
+ 2, &parsedOk
);
1415 cmaps
[j
].offset
= tables
[i
].offset
+ getU32BE(pos
+ 4, &parsedOk
);
1417 cmaps
[j
].fmt
= getU16BE(cmaps
[j
].offset
, &parsedOk
);
1418 cmaps
[j
].len
= getU16BE(cmaps
[j
].offset
+ 2, &parsedOk
);
1427 // get the number of glyphs from the maxp table
1428 i
= seekTable("maxp");
1429 nGlyphs
= getU16BE(tables
[i
].offset
+ 4, &parsedOk
);
1434 // get the bbox and loca table format from the head table
1435 i
= seekTable("head");
1436 bbox
[0] = getS16BE(tables
[i
].offset
+ 36, &parsedOk
);
1437 bbox
[1] = getS16BE(tables
[i
].offset
+ 38, &parsedOk
);
1438 bbox
[2] = getS16BE(tables
[i
].offset
+ 40, &parsedOk
);
1439 bbox
[3] = getS16BE(tables
[i
].offset
+ 42, &parsedOk
);
1440 locaFmt
= getS16BE(tables
[i
].offset
+ 50, &parsedOk
);
1445 // read the post table
1449 void FoFiTrueType::readPostTable() {
1451 int tablePos
, postFmt
, stringIdx
, stringPos
, savedStringIdx
;
1456 if ((i
= seekTable("post")) < 0) {
1459 tablePos
= tables
[i
].offset
;
1460 postFmt
= getU32BE(tablePos
, &ok
);
1464 if (postFmt
== 0x00010000) {
1465 nameToGID
= new GooHash(gTrue
);
1466 for (i
= 0; i
< 258; ++i
) {
1467 nameToGID
->add(new GooString(macGlyphNames
[i
]), i
);
1469 } else if (postFmt
== 0x00020000) {
1470 nameToGID
= new GooHash(gTrue
);
1471 n
= getU16BE(tablePos
+ 32, &ok
);
1479 stringPos
= tablePos
+ 34 + 2*n
;
1480 for (i
= 0; i
< n
; ++i
) {
1481 j
= getU16BE(tablePos
+ 34 + 2*i
, &ok
);
1483 nameToGID
->removeInt(macGlyphNames
[j
]);
1484 nameToGID
->add(new GooString(macGlyphNames
[j
]), i
);
1486 savedStringIdx
= stringIdx
;
1488 if (j
!= stringIdx
) {
1489 for (stringIdx
= 0, stringPos
= tablePos
+ 34 + 2*n
;
1491 ++stringIdx
, stringPos
+= 1 + getU8(stringPos
, &ok
)) ;
1496 m
= getU8(stringPos
, &ok
);
1497 if (!ok
|| !checkRegion(stringPos
+ 1, m
)) {
1498 stringIdx
= savedStringIdx
;
1501 nameToGID
->removeInt(macGlyphNames
[j
]);
1502 nameToGID
->add(new GooString(macGlyphNames
[0]), i
);
1507 name
= new GooString((char *)&file
[stringPos
+ 1], m
);
1508 nameToGID
->removeInt(name
);
1509 nameToGID
->add(name
, i
);
1515 } else if (postFmt
== 0x00028000) {
1516 nameToGID
= new GooHash(gTrue
);
1517 for (i
= 0; i
< nGlyphs
; ++i
) {
1518 j
= getU8(tablePos
+ 32 + i
, &ok
);
1523 nameToGID
->removeInt(macGlyphNames
[j
]);
1524 nameToGID
->add(new GooString(macGlyphNames
[j
]), i
);
1538 int FoFiTrueType::seekTable(const char *tag
) {
1542 tagI
= ((tag
[0] & 0xff) << 24) |
1543 ((tag
[1] & 0xff) << 16) |
1544 ((tag
[2] & 0xff) << 8) |
1546 for (i
= 0; i
< nTables
; ++i
) {
1547 if (tables
[i
].tag
== tagI
) {
1554 Guint
FoFiTrueType::charToTag(const char *tagName
)
1556 int n
= strlen(tagName
);
1561 for (i
= 0;i
< n
;i
++) {
1563 tag
|= tagName
[i
] & 0xff;
1573 setup GSUB table data
1574 Only supporting vertical text substitution.
1576 int FoFiTrueType::setupGSUB(const char *scriptName
)
1578 return setupGSUB(scriptName
, NULL
);
1582 setup GSUB table data
1583 Only supporting vertical text substitution.
1585 int FoFiTrueType::setupGSUB(const char *scriptName
,
1586 const char *languageName
)
1590 Guint scriptList
, featureList
;
1593 Guint scriptTable
= 0;
1603 if (scriptName
== 0) {
1604 gsubFeatureTable
= 0;
1607 scriptTag
= charToTag(scriptName
);
1608 /* read GSUB Header */
1609 if ((x
= seekTable("GSUB")) < 0) {
1610 return 0; /* GSUB table not found */
1612 gsubTable
= tables
[x
].offset
;
1614 scriptList
= getU16BE(pos
,&parsedOk
);
1616 featureList
= getU16BE(pos
,&parsedOk
);
1618 llist
= getU16BE(pos
,&parsedOk
);
1620 gsubLookupList
= llist
+gsubTable
; /* change to offset from top of file */
1621 /* read script list table */
1622 pos
= gsubTable
+scriptList
;
1623 scriptCount
= getU16BE(pos
,&parsedOk
);
1626 for (i
= 0;i
< scriptCount
;i
++) {
1627 tag
= getU32BE(pos
,&parsedOk
);
1629 scriptTable
= getU16BE(pos
,&parsedOk
);
1631 if (tag
== scriptTag
) {
1636 if (i
>= scriptCount
) {
1641 /* read script table */
1642 /* use default language system */
1643 pos
= gsubTable
+scriptList
+scriptTable
;
1646 Guint langTag
= charToTag(languageName
);
1647 Guint langCount
= getU16BE(pos
+2,&parsedOk
);
1648 for (i
= 0;i
< langCount
&& langSys
== 0;i
++) {
1649 tag
= getU32BE(pos
+4+i
*(4+2),&parsedOk
);
1650 if (tag
== langTag
) {
1651 langSys
= getU16BE(pos
+4+i
*(4+2)+4,&parsedOk
);
1656 /* default language system */
1657 langSys
= getU16BE(pos
,&parsedOk
);
1660 /* read LangSys table */
1662 /* no default LangSys */
1666 pos
= gsubTable
+scriptList
+scriptTable
+langSys
+2;
1667 featureIndex
= getU16BE(pos
,&parsedOk
); /* ReqFeatureIndex */
1670 if (featureIndex
!= 0xffff) {
1672 /* read feature record */
1673 tpos
= gsubTable
+featureList
;
1674 featureCount
= getU16BE(tpos
,&parsedOk
);
1675 tpos
= gsubTable
+featureList
+2+featureIndex
*(4+2);
1676 tag
= getU32BE(tpos
,&parsedOk
);
1678 if (tag
== vrt2Tag
) {
1679 /* vrt2 is preferred, overwrite vert */
1680 ftable
= getU16BE(tpos
,&parsedOk
);
1681 /* convert to offset from file top */
1682 gsubFeatureTable
= ftable
+gsubTable
+featureList
;
1684 } else if (tag
== vertTag
) {
1685 ftable
= getU16BE(tpos
,&parsedOk
);
1688 featureCount
= getU16BE(pos
,&parsedOk
);
1690 /* find 'vrt2' or 'vert' feature */
1691 for (i
= 0;i
< featureCount
;i
++) {
1694 featureIndex
= getU16BE(pos
,&parsedOk
);
1696 oldPos
= pos
; /* save position */
1697 /* read feature record */
1698 pos
= gsubTable
+featureList
+2+featureIndex
*(4+2);
1699 tag
= getU32BE(pos
,&parsedOk
);
1701 if (tag
== vrt2Tag
) {
1702 /* vrt2 is preferred, overwrite vert */
1703 ftable
= getU16BE(pos
,&parsedOk
);
1705 } else if (ftable
== 0 && tag
== vertTag
) {
1706 ftable
= getU16BE(pos
,&parsedOk
);
1708 pos
= oldPos
; /* restore old position */
1711 /* vert nor vrt2 are not found */
1714 /* convert to offset from file top */
1715 gsubFeatureTable
= ftable
+gsubTable
+featureList
;
1719 Guint
FoFiTrueType::doMapToVertGID(Guint orgGID
)
1722 Guint lookupListIndex
;
1727 pos
= gsubFeatureTable
+2;
1728 lookupCount
= getU16BE(pos
,&parsedOk
);
1730 for (i
= 0;i
< lookupCount
;i
++) {
1731 lookupListIndex
= getU16BE(pos
,&parsedOk
);
1733 if ((gid
= scanLookupList(lookupListIndex
,orgGID
)) != 0) {
1740 Guint
FoFiTrueType::mapToVertGID(Guint orgGID
)
1744 if (gsubFeatureTable
== 0) return orgGID
;
1745 if ((mapped
= doMapToVertGID(orgGID
)) != 0) {
1751 Guint
FoFiTrueType::scanLookupList(Guint listIndex
, Guint orgGID
)
1754 Guint subTableCount
;
1760 if (gsubLookupList
== 0) return 0; /* no lookup list */
1761 pos
= gsubLookupList
+2+listIndex
*2;
1762 lookupTable
= getU16BE(pos
,&parsedOk
);
1763 /* read lookup table */
1764 pos
= gsubLookupList
+lookupTable
+4;
1765 subTableCount
= getU16BE(pos
,&parsedOk
);
1767 for (i
= 0;i
< subTableCount
;i
++) {
1768 subTable
= getU16BE(pos
,&parsedOk
);
1770 if ((gid
= scanLookupSubTable(gsubLookupList
+lookupTable
+subTable
,orgGID
))
1776 Guint
FoFiTrueType::scanLookupSubTable(Guint subTable
, Guint orgGID
)
1788 format
= getU16BE(pos
,&parsedOk
);
1790 coverage
= getU16BE(pos
,&parsedOk
);
1792 if ((coverageIndex
=
1793 checkGIDInCoverage(subTable
+coverage
,orgGID
)) >= 0) {
1797 delta
= getS16BE(pos
,&parsedOk
);
1803 glyphCount
= getS16BE(pos
,&parsedOk
);
1805 if (glyphCount
> coverageIndex
) {
1806 pos
+= coverageIndex
*2;
1807 substitute
= getU16BE(pos
,&parsedOk
);
1812 /* unknown format */
1819 int FoFiTrueType::checkGIDInCoverage(Guint coverage
, Guint orgGID
)
1828 format
= getU16BE(pos
,&parsedOk
);
1832 count
= getU16BE(pos
,&parsedOk
);
1834 // In some poor CJK fonts, key GIDs are not sorted,
1835 // thus we cannot finish checking even when the range
1836 // including orgGID seems to have already passed.
1837 for (i
= 0;i
< count
;i
++) {
1840 gid
= getU16BE(pos
,&parsedOk
);
1842 if (gid
== orgGID
) {
1850 count
= getU16BE(pos
,&parsedOk
);
1852 for (i
= 0;i
< count
;i
++) {
1853 Guint startGID
, endGID
;
1856 startGID
= getU16BE(pos
,&parsedOk
);
1858 endGID
= getU16BE(pos
,&parsedOk
);
1860 startIndex
= getU16BE(pos
,&parsedOk
);
1862 // In some poor CJK fonts, key GIDs are not sorted,
1863 // thus we cannot finish checking even when the range
1864 // including orgGID seems to have already passed.
1865 if (startGID
<= orgGID
&& orgGID
<= endGID
) {
1867 index
= startIndex
+orgGID
-startGID
;