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, 2015 Albert Astals Cid <aacid@kde.org>
20 // Copyright (C) 2008 Tomas Are Haavet <tomasare@gmail.com>
21 // Copyright (C) 2012 Suzuki Toshiya <mpsuzuki@hiroshima-u.ac.jp>
22 // Copyright (C) 2012 Adrian Johnson <ajohnson@redneon.com>
23 // Copyright (C) 2014 Thomas Freitag <Thomas.Freitag@alfa.de>
24 // Copyright (C) 2015 Aleksei Volkov <Aleksei Volkov>
25 // Copyright (C) 2015 William Bader <williambader@hotmail.com>
27 // To see a description of the changes please see the Changelog file that
28 // came with your tarball or type make ChangeLog if you are building from git
30 //========================================================================
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
,
730 FoFiOutputFunc outputFunc
,
731 void *outputStream
) {
733 GooString
*sfntsName
;
734 int maxUsedGlyph
, n
, i
, j
;
740 // write the Type 42 sfnts array
741 sfntsName
= (new GooString(psName
))->append("_sfnts");
742 cvtSfnts(outputFunc
, outputStream
, sfntsName
, needVerticalMetrics
,
746 // write the descendant Type 42 fonts
747 // (The following is a kludge: nGlyphs is the glyph count from the
748 // maxp table; maxUsedGlyph is the max glyph number that has a
749 // non-zero-length description, from the loca table. The problem is
750 // that some TrueType font subsets fail to change the glyph count,
751 // i.e., nGlyphs is much larger than maxUsedGlyph+1, which results
752 // in an unnecessarily huge Type 0 font. But some other PDF files
753 // have fonts with only zero or one used glyph, and a content stream
754 // that refers to one of the unused glyphs -- this results in PS
755 // errors if we simply use maxUsedGlyph+1 for the Type 0 font. So
756 // we compromise by always defining at least 256 glyphs.)
759 } else if (nGlyphs
> maxUsedGlyph
+ 256) {
760 if (maxUsedGlyph
<= 255) {
763 n
= maxUsedGlyph
+ 1;
768 for (i
= 0; i
< n
; i
+= 256) {
769 (*outputFunc
)(outputStream
, "10 dict begin\n", 14);
770 (*outputFunc
)(outputStream
, "/FontName /", 11);
771 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
772 buf
= GooString::format("_{0:02x} def\n", i
>> 8);
773 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
775 (*outputFunc
)(outputStream
, "/FontType 42 def\n", 17);
776 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
777 buf
= GooString::format("/FontBBox [{0:d} {1:d} {2:d} {3:d}] def\n",
778 bbox
[0], bbox
[1], bbox
[2], bbox
[3]);
779 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
781 (*outputFunc
)(outputStream
, "/PaintType 0 def\n", 17);
782 (*outputFunc
)(outputStream
, "/sfnts ", 7);
783 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
784 (*outputFunc
)(outputStream
, "_sfnts def\n", 11);
785 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
786 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
787 buf
= GooString::format("dup {0:d} /c{1:02x} put\n", j
, j
);
788 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
791 (*outputFunc
)(outputStream
, "readonly def\n", 13);
792 (*outputFunc
)(outputStream
, "/CharStrings 257 dict dup begin\n", 32);
793 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
794 for (j
= 0; j
< 256 && i
+j
< n
; ++j
) {
795 buf
= GooString::format("/c{0:02x} {1:d} def\n",
796 j
, cidMap
? cidMap
[i
+j
] : i
+j
);
797 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
800 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
801 (*outputFunc
)(outputStream
,
802 "FontName currentdict end definefont pop\n", 40);
805 // write the Type 0 parent font
806 (*outputFunc
)(outputStream
, "16 dict begin\n", 14);
807 (*outputFunc
)(outputStream
, "/FontName /", 11);
808 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
809 (*outputFunc
)(outputStream
, " def\n", 5);
810 (*outputFunc
)(outputStream
, "/FontType 0 def\n", 16);
811 (*outputFunc
)(outputStream
, "/FontMatrix [1 0 0 1 0 0] def\n", 30);
812 (*outputFunc
)(outputStream
, "/FMapType 2 def\n", 16);
813 (*outputFunc
)(outputStream
, "/Encoding [\n", 12);
814 for (i
= 0; i
< n
; i
+= 256) {
815 buf
= GooString::format("{0:d}\n", i
>> 8);
816 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
819 (*outputFunc
)(outputStream
, "] def\n", 6);
820 (*outputFunc
)(outputStream
, "/FDepVector [\n", 14);
821 for (i
= 0; i
< n
; i
+= 256) {
822 (*outputFunc
)(outputStream
, "/", 1);
823 (*outputFunc
)(outputStream
, psName
, strlen(psName
));
824 buf
= GooString::format("_{0:02x} findfont\n", i
>> 8);
825 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
828 (*outputFunc
)(outputStream
, "] def\n", 6);
829 (*outputFunc
)(outputStream
, "FontName currentdict end definefont pop\n", 40);
832 void FoFiTrueType::convertToType0(char *psName
, int *cidMap
, int nCIDs
,
833 FoFiOutputFunc outputFunc
,
834 void *outputStream
) {
839 if (!getCFFBlock(&start
, &length
)) {
842 if (!(ff
= FoFiType1C::make(start
, length
))) {
845 ff
->convertToType0(psName
, cidMap
, nCIDs
, outputFunc
, outputStream
);
849 void FoFiTrueType::cvtEncoding(char **encoding
,
850 FoFiOutputFunc outputFunc
,
851 void *outputStream
) {
856 (*outputFunc
)(outputStream
, "/Encoding 256 array\n", 20);
858 for (i
= 0; i
< 256; ++i
) {
859 if (!(name
= encoding
[i
])) {
862 buf
= GooString::format("dup {0:d} /", i
);
863 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
865 (*outputFunc
)(outputStream
, name
, strlen(name
));
866 (*outputFunc
)(outputStream
, " put\n", 5);
869 for (i
= 0; i
< 256; ++i
) {
870 buf
= GooString::format("dup {0:d} /c{1:02x} put\n", i
, i
);
871 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
875 (*outputFunc
)(outputStream
, "readonly def\n", 13);
878 void FoFiTrueType::cvtCharStrings(char **encoding
,
880 FoFiOutputFunc outputFunc
,
881 void *outputStream
) {
887 // always define '.notdef'
888 (*outputFunc
)(outputStream
, "/CharStrings 256 dict dup begin\n", 32);
889 (*outputFunc
)(outputStream
, "/.notdef 0 def\n", 15);
891 // if there's no 'cmap' table, punt
896 // map char name to glyph index:
897 // 1. use encoding to map name to char code
898 // 2. use codeToGID to map char code to glyph index
899 // N.B. We do this in reverse order because font subsets can have
900 // weird encodings that use the same character name twice, and
901 // the first definition is probably the one we want.
902 k
= 0; // make gcc happy
903 for (i
= 255; i
>= 0; --i
) {
907 sprintf(buf2
, "c%02x", i
);
910 if (name
&& strcmp(name
, ".notdef")) {
912 // note: Distiller (maybe Adobe's PS interpreter in general)
913 // doesn't like TrueType fonts that have CharStrings entries
914 // which point to nonexistent glyphs, hence the (k < nGlyphs)
916 if (k
> 0 && k
< nGlyphs
) {
917 (*outputFunc
)(outputStream
, "/", 1);
918 (*outputFunc
)(outputStream
, name
, strlen(name
));
919 buf
= GooString::format(" {0:d} def\n", k
);
920 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
927 (*outputFunc
)(outputStream
, "end readonly def\n", 17);
930 void FoFiTrueType::cvtSfnts(FoFiOutputFunc outputFunc
,
931 void *outputStream
, GooString
*name
,
932 GBool needVerticalMetrics
,
935 TrueTypeLoca
*locaTable
;
937 TrueTypeTable newTables
[nT42Tables
];
938 Guchar tableDir
[12 + nT42Tables
*16];
942 int glyfTableLen
, length
, pos
, glyfPos
, i
, j
, k
, vmtxTabLength
;
943 Guchar vheaTab
[36] = {
944 0, 1, 0, 0, // table version number
948 0, 0, // max advance height
949 0, 0, // min top side bearing
950 0, 0, // min bottom side bearing
951 0, 0, // y max extent
952 0, 0, // caret slope rise
953 0, 1, // caret slope run
954 0, 0, // caret offset
959 0, 0, // metric data format
960 0, 1 // number of advance heights in vmtx table
963 GBool needVhea
, needVmtx
;
966 // construct the 'head' table, zero out the font checksum
967 i
= seekTable("head");
968 if (i
< 0 || i
>= nTables
) {
971 pos
= tables
[i
].offset
;
972 if (!checkRegion(pos
, 54)) {
975 memcpy(headData
, file
+ pos
, 54);
976 headData
[8] = headData
[9] = headData
[10] = headData
[11] = (Guchar
)0;
978 // check for a bogus loca format field in the 'head' table
979 // (I've encountered fonts with loca format set to 0x0100 instead of 0x0001)
980 if (locaFmt
!= 0 && locaFmt
!= 1) {
985 // read the original 'loca' table, pad entries out to 4 bytes, and
986 // sort it into proper order -- some (non-compliant) fonts have
987 // out-of-order loca tables; in order to correctly handle the case
988 // where (compliant) fonts have empty entries in the middle of the
989 // table, cmpTrueTypeLocaOffset uses offset as its primary sort key,
990 // and idx as its secondary key (ensuring that adjacent entries with
991 // the same pos value remain in the same order)
992 locaTable
= (TrueTypeLoca
*)gmallocn(nGlyphs
+ 1, sizeof(TrueTypeLoca
));
993 i
= seekTable("loca");
994 pos
= tables
[i
].offset
;
995 i
= seekTable("glyf");
996 glyfTableLen
= tables
[i
].len
;
998 for (i
= 0; i
<= nGlyphs
; ++i
) {
999 locaTable
[i
].idx
= i
;
1001 locaTable
[i
].origOffset
= (int)getU32BE(pos
+ i
*4, &ok
);
1003 locaTable
[i
].origOffset
= 2 * getU16BE(pos
+ i
*2, &ok
);
1005 if (locaTable
[i
].origOffset
> glyfTableLen
) {
1006 locaTable
[i
].origOffset
= glyfTableLen
;
1009 std::sort(locaTable
, locaTable
+ nGlyphs
+ 1,
1010 cmpTrueTypeLocaOffsetFunctor());
1011 for (i
= 0; i
< nGlyphs
; ++i
) {
1012 locaTable
[i
].len
= locaTable
[i
+1].origOffset
- locaTable
[i
].origOffset
;
1014 locaTable
[nGlyphs
].len
= 0;
1015 std::sort(locaTable
, locaTable
+ nGlyphs
+ 1, cmpTrueTypeLocaIdxFunctor());
1018 for (i
= 0; i
<= nGlyphs
; ++i
) {
1019 locaTable
[i
].newOffset
= pos
;
1020 pos
+= locaTable
[i
].len
;
1022 pos
+= 4 - (pos
& 3);
1024 if (locaTable
[i
].len
> 0) {
1029 // construct the new 'loca' table
1030 locaData
= (Guchar
*)gmallocn(nGlyphs
+ 1, (locaFmt
? 4 : 2));
1031 for (i
= 0; i
<= nGlyphs
; ++i
) {
1032 pos
= locaTable
[i
].newOffset
;
1034 locaData
[4*i
] = (Guchar
)(pos
>> 24);
1035 locaData
[4*i
+1] = (Guchar
)(pos
>> 16);
1036 locaData
[4*i
+2] = (Guchar
)(pos
>> 8);
1037 locaData
[4*i
+3] = (Guchar
) pos
;
1039 locaData
[2*i
] = (Guchar
)(pos
>> 9);
1040 locaData
[2*i
+1] = (Guchar
)(pos
>> 1);
1044 // count the number of tables
1046 for (i
= 0; i
< nT42Tables
; ++i
) {
1047 if (t42Tables
[i
].required
||
1048 seekTable(t42Tables
[i
].tag
) >= 0) {
1052 vmtxTab
= NULL
; // make gcc happy
1054 advance
= 0; // make gcc happy
1055 if (needVerticalMetrics
) {
1056 needVhea
= seekTable("vhea") < 0;
1057 needVmtx
= seekTable("vmtx") < 0;
1058 if (needVhea
|| needVmtx
) {
1059 i
= seekTable("head");
1060 advance
= getU16BE(tables
[i
].offset
+ 18, &ok
); // units per em
1070 // construct the new table headers, including table checksums
1071 // (pad each table out to a multiple of 4 bytes)
1072 pos
= 12 + nNewTables
*16;
1074 for (i
= 0; i
< nT42Tables
; ++i
) {
1076 checksum
= 0; // make gcc happy
1077 if (i
== t42HeadTable
) {
1079 checksum
= computeTableChecksum(headData
, 54);
1080 } else if (i
== t42LocaTable
) {
1081 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1082 checksum
= computeTableChecksum(locaData
, length
);
1083 } else if (i
== t42GlyfTable
) {
1086 glyfPos
= tables
[seekTable("glyf")].offset
;
1087 for (j
= 0; j
< nGlyphs
; ++j
) {
1088 length
+= locaTable
[j
].len
;
1090 length
+= 4 - (length
& 3);
1092 if (checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1094 computeTableChecksum(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1099 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0) {
1100 length
= tables
[j
].len
;
1101 if (checkRegion(tables
[j
].offset
, length
)) {
1102 checksum
= computeTableChecksum(file
+ tables
[j
].offset
, length
);
1104 } else if (needVerticalMetrics
&& i
== t42VheaTable
) {
1105 vheaTab
[10] = advance
/ 256; // max advance height
1106 vheaTab
[11] = advance
% 256;
1107 length
= sizeof(vheaTab
);
1108 checksum
= computeTableChecksum(vheaTab
, length
);
1109 } else if (needVerticalMetrics
&& i
== t42VmtxTable
) {
1110 length
= 4 + (nGlyphs
- 1) * 2;
1111 vmtxTabLength
= length
;
1112 vmtxTab
= (Guchar
*)gmalloc(length
);
1113 vmtxTab
[0] = advance
/ 256;
1114 vmtxTab
[1] = advance
% 256;
1115 for (j
= 2; j
< length
; j
+= 2) {
1119 checksum
= computeTableChecksum(vmtxTab
, length
);
1120 } else if (t42Tables
[i
].required
) {
1121 //~ error(-1, "Embedded TrueType font is missing a required table ('%s')",
1122 //~ t42Tables[i].tag);
1128 newTables
[k
].tag
= ((t42Tables
[i
].tag
[0] & 0xff) << 24) |
1129 ((t42Tables
[i
].tag
[1] & 0xff) << 16) |
1130 ((t42Tables
[i
].tag
[2] & 0xff) << 8) |
1131 (t42Tables
[i
].tag
[3] & 0xff);
1132 newTables
[k
].checksum
= checksum
;
1133 newTables
[k
].offset
= pos
;
1134 newTables
[k
].len
= length
;
1137 pos
+= 4 - (length
& 3);
1143 // construct the table directory
1144 tableDir
[0] = 0x00; // sfnt version
1148 tableDir
[4] = 0; // numTables
1149 tableDir
[5] = nNewTables
;
1150 tableDir
[6] = 0; // searchRange
1151 tableDir
[7] = (Guchar
)128;
1152 tableDir
[8] = 0; // entrySelector
1154 tableDir
[10] = 0; // rangeShift
1155 tableDir
[11] = (Guchar
)(16 * nNewTables
- 128);
1157 for (i
= 0; i
< nNewTables
; ++i
) {
1158 tableDir
[pos
] = (Guchar
)(newTables
[i
].tag
>> 24);
1159 tableDir
[pos
+ 1] = (Guchar
)(newTables
[i
].tag
>> 16);
1160 tableDir
[pos
+ 2] = (Guchar
)(newTables
[i
].tag
>> 8);
1161 tableDir
[pos
+ 3] = (Guchar
) newTables
[i
].tag
;
1162 tableDir
[pos
+ 4] = (Guchar
)(newTables
[i
].checksum
>> 24);
1163 tableDir
[pos
+ 5] = (Guchar
)(newTables
[i
].checksum
>> 16);
1164 tableDir
[pos
+ 6] = (Guchar
)(newTables
[i
].checksum
>> 8);
1165 tableDir
[pos
+ 7] = (Guchar
) newTables
[i
].checksum
;
1166 tableDir
[pos
+ 8] = (Guchar
)(newTables
[i
].offset
>> 24);
1167 tableDir
[pos
+ 9] = (Guchar
)(newTables
[i
].offset
>> 16);
1168 tableDir
[pos
+10] = (Guchar
)(newTables
[i
].offset
>> 8);
1169 tableDir
[pos
+11] = (Guchar
) newTables
[i
].offset
;
1170 tableDir
[pos
+12] = (Guchar
)(newTables
[i
].len
>> 24);
1171 tableDir
[pos
+13] = (Guchar
)(newTables
[i
].len
>> 16);
1172 tableDir
[pos
+14] = (Guchar
)(newTables
[i
].len
>> 8);
1173 tableDir
[pos
+15] = (Guchar
) newTables
[i
].len
;
1177 // compute the font checksum and store it in the head table
1178 checksum
= computeTableChecksum(tableDir
, 12 + nNewTables
*16);
1179 for (i
= 0; i
< nNewTables
; ++i
) {
1180 checksum
+= newTables
[i
].checksum
;
1182 checksum
= 0xb1b0afba - checksum
; // because the TrueType spec says so
1183 headData
[ 8] = (Guchar
)(checksum
>> 24);
1184 headData
[ 9] = (Guchar
)(checksum
>> 16);
1185 headData
[10] = (Guchar
)(checksum
>> 8);
1186 headData
[11] = (Guchar
) checksum
;
1188 // start the sfnts array
1190 (*outputFunc
)(outputStream
, "/", 1);
1191 (*outputFunc
)(outputStream
, name
->getCString(), name
->getLength());
1192 (*outputFunc
)(outputStream
, " [\n", 3);
1194 (*outputFunc
)(outputStream
, "/sfnts [\n", 9);
1197 // write the table directory
1198 dumpString(tableDir
, 12 + nNewTables
*16, outputFunc
, outputStream
);
1201 for (i
= 0; i
< nNewTables
; ++i
) {
1202 if (i
== t42HeadTable
) {
1203 dumpString(headData
, 54, outputFunc
, outputStream
);
1204 } else if (i
== t42LocaTable
) {
1205 length
= (nGlyphs
+ 1) * (locaFmt
? 4 : 2);
1206 dumpString(locaData
, length
, outputFunc
, outputStream
);
1207 } else if (i
== t42GlyfTable
) {
1208 glyfPos
= tables
[seekTable("glyf")].offset
;
1209 for (j
= 0; j
< nGlyphs
; ++j
) {
1210 if (locaTable
[j
].len
> 0 &&
1211 checkRegion(glyfPos
+ locaTable
[j
].origOffset
, locaTable
[j
].len
)) {
1212 dumpString(file
+ glyfPos
+ locaTable
[j
].origOffset
,
1213 locaTable
[j
].len
, outputFunc
, outputStream
);
1217 // length == 0 means the table is missing and the error was
1218 // already reported during the construction of the table
1220 if ((length
= newTables
[i
].len
) > 0) {
1221 if ((j
= seekTable(t42Tables
[i
].tag
)) >= 0 &&
1222 checkRegion(tables
[j
].offset
, tables
[j
].len
)) {
1223 dumpString(file
+ tables
[j
].offset
, tables
[j
].len
,
1224 outputFunc
, outputStream
);
1225 } else if (needVerticalMetrics
&& i
== t42VheaTable
) {
1226 if (unlikely(length
> (int)sizeof(vheaTab
))) {
1227 error(errSyntaxWarning
, -1, "length bigger than vheaTab size");
1228 length
= sizeof(vheaTab
);
1230 dumpString(vheaTab
, length
, outputFunc
, outputStream
);
1231 } else if (needVerticalMetrics
&& i
== t42VmtxTable
) {
1232 if (unlikely(length
> vmtxTabLength
)) {
1233 error(errSyntaxWarning
, -1, "length bigger than vmtxTab size");
1234 length
= vmtxTabLength
;
1236 dumpString(vmtxTab
, length
, outputFunc
, outputStream
);
1242 // end the sfnts array
1243 (*outputFunc
)(outputStream
, "] def\n", 6);
1252 void FoFiTrueType::dumpString(Guchar
*s
, int length
,
1253 FoFiOutputFunc outputFunc
,
1254 void *outputStream
) {
1258 (*outputFunc
)(outputStream
, "<", 1);
1259 for (i
= 0; i
< length
; i
+= 32) {
1260 for (j
= 0; j
< 32 && i
+j
< length
; ++j
) {
1261 buf
= GooString::format("{0:02x}", s
[i
+j
] & 0xff);
1262 (*outputFunc
)(outputStream
, buf
->getCString(), buf
->getLength());
1265 if (i
% (65536 - 32) == 65536 - 64) {
1266 (*outputFunc
)(outputStream
, ">\n<", 3);
1267 } else if (i
+32 < length
) {
1268 (*outputFunc
)(outputStream
, "\n", 1);
1272 pad
= 4 - (length
& 3);
1273 for (i
= 0; i
< pad
; ++i
) {
1274 (*outputFunc
)(outputStream
, "00", 2);
1277 // add an extra zero byte because the Adobe Type 42 spec says so
1278 (*outputFunc
)(outputStream
, "00>\n", 4);
1281 Guint
FoFiTrueType::computeTableChecksum(Guchar
*data
, int length
) {
1282 Guint checksum
, word
;
1286 for (i
= 0; i
+3 < length
; i
+= 4) {
1287 word
= ((data
[i
] & 0xff) << 24) +
1288 ((data
[i
+1] & 0xff) << 16) +
1289 ((data
[i
+2] & 0xff) << 8) +
1296 switch (length
& 3) {
1298 word
|= (data
[i
+2] & 0xff) << 8;
1300 word
|= (data
[i
+1] & 0xff) << 16;
1302 word
|= (data
[i
] & 0xff) << 24;
1310 void FoFiTrueType::parse() {
1316 // look for a collection (TTC)
1317 topTag
= getU32BE(0, &parsedOk
);
1321 if (topTag
== ttcfTag
) {
1325 dircount
= getU32BE(8, &parsedOk
);
1333 if (faceIndex
>= dircount
)
1335 pos
= getU32BE(12 + faceIndex
* 4, &parsedOk
);
1342 // check the sfnt version
1343 ver
= getU32BE(pos
, &parsedOk
);
1347 openTypeCFF
= ver
== 0x4f54544f; // 'OTTO'
1349 // read the table directory
1350 nTables
= getU16BE(pos
+ 4, &parsedOk
);
1354 tables
= (TrueTypeTable
*)gmallocn(nTables
, sizeof(TrueTypeTable
));
1357 for (i
= 0; i
< nTables
; ++i
) {
1358 tables
[j
].tag
= getU32BE(pos
, &parsedOk
);
1359 tables
[j
].checksum
= getU32BE(pos
+ 4, &parsedOk
);
1360 tables
[j
].offset
= (int)getU32BE(pos
+ 8, &parsedOk
);
1361 tables
[j
].len
= (int)getU32BE(pos
+ 12, &parsedOk
);
1362 if (tables
[j
].offset
+ tables
[j
].len
>= tables
[j
].offset
&&
1363 tables
[j
].offset
+ tables
[j
].len
<= len
) {
1364 // ignore any bogus entries in the table directory
1371 tables
= (TrueTypeTable
*)greallocn_checkoverflow(tables
, nTables
, sizeof(TrueTypeTable
));
1373 if (!parsedOk
|| tables
== NULL
) {
1377 // check for tables that are required by both the TrueType spec and
1379 if (seekTable("head") < 0 ||
1380 seekTable("hhea") < 0 ||
1381 seekTable("maxp") < 0 ||
1382 (!openTypeCFF
&& seekTable("loca") < 0) ||
1383 (!openTypeCFF
&& seekTable("glyf") < 0) ||
1384 (openTypeCFF
&& seekTable("CFF ") < 0)) {
1390 if ((i
= seekTable("cmap")) >= 0) {
1391 pos
= tables
[i
].offset
+ 2;
1392 nCmaps
= getU16BE(pos
, &parsedOk
);
1397 cmaps
= (TrueTypeCmap
*)gmallocn(nCmaps
, sizeof(TrueTypeCmap
));
1398 for (j
= 0; j
< nCmaps
; ++j
) {
1399 cmaps
[j
].platform
= getU16BE(pos
, &parsedOk
);
1400 cmaps
[j
].encoding
= getU16BE(pos
+ 2, &parsedOk
);
1401 cmaps
[j
].offset
= tables
[i
].offset
+ getU32BE(pos
+ 4, &parsedOk
);
1403 cmaps
[j
].fmt
= getU16BE(cmaps
[j
].offset
, &parsedOk
);
1404 cmaps
[j
].len
= getU16BE(cmaps
[j
].offset
+ 2, &parsedOk
);
1413 // get the number of glyphs from the maxp table
1414 i
= seekTable("maxp");
1415 nGlyphs
= getU16BE(tables
[i
].offset
+ 4, &parsedOk
);
1420 // get the bbox and loca table format from the head table
1421 i
= seekTable("head");
1422 bbox
[0] = getS16BE(tables
[i
].offset
+ 36, &parsedOk
);
1423 bbox
[1] = getS16BE(tables
[i
].offset
+ 38, &parsedOk
);
1424 bbox
[2] = getS16BE(tables
[i
].offset
+ 40, &parsedOk
);
1425 bbox
[3] = getS16BE(tables
[i
].offset
+ 42, &parsedOk
);
1426 locaFmt
= getS16BE(tables
[i
].offset
+ 50, &parsedOk
);
1431 // read the post table
1435 void FoFiTrueType::readPostTable() {
1437 int tablePos
, postFmt
, stringIdx
, stringPos
, savedStringIdx
;
1442 if ((i
= seekTable("post")) < 0) {
1445 tablePos
= tables
[i
].offset
;
1446 postFmt
= getU32BE(tablePos
, &ok
);
1450 if (postFmt
== 0x00010000) {
1451 nameToGID
= new GooHash(gTrue
);
1452 for (i
= 0; i
< 258; ++i
) {
1453 nameToGID
->add(new GooString(macGlyphNames
[i
]), i
);
1455 } else if (postFmt
== 0x00020000) {
1456 nameToGID
= new GooHash(gTrue
);
1457 n
= getU16BE(tablePos
+ 32, &ok
);
1465 stringPos
= tablePos
+ 34 + 2*n
;
1466 for (i
= 0; i
< n
; ++i
) {
1467 j
= getU16BE(tablePos
+ 34 + 2*i
, &ok
);
1469 nameToGID
->removeInt(macGlyphNames
[j
]);
1470 nameToGID
->add(new GooString(macGlyphNames
[j
]), i
);
1472 savedStringIdx
= stringIdx
;
1474 if (j
!= stringIdx
) {
1475 for (stringIdx
= 0, stringPos
= tablePos
+ 34 + 2*n
;
1477 ++stringIdx
, stringPos
+= 1 + getU8(stringPos
, &ok
)) ;
1482 m
= getU8(stringPos
, &ok
);
1483 if (!ok
|| !checkRegion(stringPos
+ 1, m
)) {
1484 stringIdx
= savedStringIdx
;
1487 nameToGID
->removeInt(macGlyphNames
[j
]);
1488 nameToGID
->add(new GooString(macGlyphNames
[0]), i
);
1493 name
= new GooString((char *)&file
[stringPos
+ 1], m
);
1494 nameToGID
->removeInt(name
);
1495 nameToGID
->add(name
, i
);
1501 } else if (postFmt
== 0x00028000) {
1502 nameToGID
= new GooHash(gTrue
);
1503 for (i
= 0; i
< nGlyphs
; ++i
) {
1504 j
= getU8(tablePos
+ 32 + i
, &ok
);
1509 nameToGID
->removeInt(macGlyphNames
[j
]);
1510 nameToGID
->add(new GooString(macGlyphNames
[j
]), i
);
1524 int FoFiTrueType::seekTable(const char *tag
) {
1528 tagI
= ((tag
[0] & 0xff) << 24) |
1529 ((tag
[1] & 0xff) << 16) |
1530 ((tag
[2] & 0xff) << 8) |
1532 for (i
= 0; i
< nTables
; ++i
) {
1533 if (tables
[i
].tag
== tagI
) {
1540 Guint
FoFiTrueType::charToTag(const char *tagName
)
1542 int n
= strlen(tagName
);
1547 for (i
= 0;i
< n
;i
++) {
1549 tag
|= tagName
[i
] & 0xff;
1559 setup GSUB table data
1560 Only supporting vertical text substitution.
1562 int FoFiTrueType::setupGSUB(const char *scriptName
)
1564 return setupGSUB(scriptName
, NULL
);
1568 setup GSUB table data
1569 Only supporting vertical text substitution.
1571 int FoFiTrueType::setupGSUB(const char *scriptName
,
1572 const char *languageName
)
1576 Guint scriptList
, featureList
;
1579 Guint scriptTable
= 0;
1589 if (scriptName
== 0) {
1590 gsubFeatureTable
= 0;
1593 scriptTag
= charToTag(scriptName
);
1594 /* read GSUB Header */
1595 if ((x
= seekTable("GSUB")) < 0) {
1596 return 0; /* GSUB table not found */
1598 gsubTable
= tables
[x
].offset
;
1600 scriptList
= getU16BE(pos
,&parsedOk
);
1602 featureList
= getU16BE(pos
,&parsedOk
);
1604 llist
= getU16BE(pos
,&parsedOk
);
1606 gsubLookupList
= llist
+gsubTable
; /* change to offset from top of file */
1607 /* read script list table */
1608 pos
= gsubTable
+scriptList
;
1609 scriptCount
= getU16BE(pos
,&parsedOk
);
1612 for (i
= 0;i
< scriptCount
;i
++) {
1613 tag
= getU32BE(pos
,&parsedOk
);
1615 scriptTable
= getU16BE(pos
,&parsedOk
);
1617 if (tag
== scriptTag
) {
1622 if (i
>= scriptCount
) {
1627 /* read script table */
1628 /* use default language system */
1629 pos
= gsubTable
+scriptList
+scriptTable
;
1632 Guint langTag
= charToTag(languageName
);
1633 Guint langCount
= getU16BE(pos
+2,&parsedOk
);
1634 for (i
= 0;i
< langCount
&& langSys
== 0;i
++) {
1635 tag
= getU32BE(pos
+4+i
*(4+2),&parsedOk
);
1636 if (tag
== langTag
) {
1637 langSys
= getU16BE(pos
+4+i
*(4+2)+4,&parsedOk
);
1642 /* default language system */
1643 langSys
= getU16BE(pos
,&parsedOk
);
1646 /* read LangSys table */
1648 /* no default LangSys */
1652 pos
= gsubTable
+scriptList
+scriptTable
+langSys
+2;
1653 featureIndex
= getU16BE(pos
,&parsedOk
); /* ReqFeatureIndex */
1656 if (featureIndex
!= 0xffff) {
1658 /* read feature record */
1659 tpos
= gsubTable
+featureList
;
1660 featureCount
= getU16BE(tpos
,&parsedOk
);
1661 tpos
= gsubTable
+featureList
+2+featureIndex
*(4+2);
1662 tag
= getU32BE(tpos
,&parsedOk
);
1664 if (tag
== vrt2Tag
) {
1665 /* vrt2 is preferred, overwrite vert */
1666 ftable
= getU16BE(tpos
,&parsedOk
);
1667 /* convert to offset from file top */
1668 gsubFeatureTable
= ftable
+gsubTable
+featureList
;
1670 } else if (tag
== vertTag
) {
1671 ftable
= getU16BE(tpos
,&parsedOk
);
1674 featureCount
= getU16BE(pos
,&parsedOk
);
1676 /* find 'vrt2' or 'vert' feature */
1677 for (i
= 0;i
< featureCount
;i
++) {
1680 featureIndex
= getU16BE(pos
,&parsedOk
);
1682 oldPos
= pos
; /* save position */
1683 /* read feature record */
1684 pos
= gsubTable
+featureList
+2+featureIndex
*(4+2);
1685 tag
= getU32BE(pos
,&parsedOk
);
1687 if (tag
== vrt2Tag
) {
1688 /* vrt2 is preferred, overwrite vert */
1689 ftable
= getU16BE(pos
,&parsedOk
);
1691 } else if (ftable
== 0 && tag
== vertTag
) {
1692 ftable
= getU16BE(pos
,&parsedOk
);
1694 pos
= oldPos
; /* restore old position */
1697 /* vert nor vrt2 are not found */
1700 /* convert to offset from file top */
1701 gsubFeatureTable
= ftable
+gsubTable
+featureList
;
1705 Guint
FoFiTrueType::doMapToVertGID(Guint orgGID
)
1708 Guint lookupListIndex
;
1713 pos
= gsubFeatureTable
+2;
1714 lookupCount
= getU16BE(pos
,&parsedOk
);
1716 for (i
= 0;i
< lookupCount
;i
++) {
1717 lookupListIndex
= getU16BE(pos
,&parsedOk
);
1719 if ((gid
= scanLookupList(lookupListIndex
,orgGID
)) != 0) {
1726 Guint
FoFiTrueType::mapToVertGID(Guint orgGID
)
1730 if (gsubFeatureTable
== 0) return orgGID
;
1731 if ((mapped
= doMapToVertGID(orgGID
)) != 0) {
1737 Guint
FoFiTrueType::scanLookupList(Guint listIndex
, Guint orgGID
)
1740 Guint subTableCount
;
1746 if (gsubLookupList
== 0) return 0; /* no lookup list */
1747 pos
= gsubLookupList
+2+listIndex
*2;
1748 lookupTable
= getU16BE(pos
,&parsedOk
);
1749 /* read lookup table */
1750 pos
= gsubLookupList
+lookupTable
+4;
1751 subTableCount
= getU16BE(pos
,&parsedOk
);
1753 for (i
= 0;i
< subTableCount
;i
++) {
1754 subTable
= getU16BE(pos
,&parsedOk
);
1756 if ((gid
= scanLookupSubTable(gsubLookupList
+lookupTable
+subTable
,orgGID
))
1762 Guint
FoFiTrueType::scanLookupSubTable(Guint subTable
, Guint orgGID
)
1774 format
= getU16BE(pos
,&parsedOk
);
1776 coverage
= getU16BE(pos
,&parsedOk
);
1778 if ((coverageIndex
=
1779 checkGIDInCoverage(subTable
+coverage
,orgGID
)) >= 0) {
1783 delta
= getS16BE(pos
,&parsedOk
);
1789 glyphCount
= getS16BE(pos
,&parsedOk
);
1791 if (glyphCount
> coverageIndex
) {
1792 pos
+= coverageIndex
*2;
1793 substitute
= getU16BE(pos
,&parsedOk
);
1798 /* unknown format */
1805 int FoFiTrueType::checkGIDInCoverage(Guint coverage
, Guint orgGID
)
1814 format
= getU16BE(pos
,&parsedOk
);
1818 count
= getU16BE(pos
,&parsedOk
);
1820 // In some poor CJK fonts, key GIDs are not sorted,
1821 // thus we cannot finish checking even when the range
1822 // including orgGID seems to have already passed.
1823 for (i
= 0;i
< count
;i
++) {
1826 gid
= getU16BE(pos
,&parsedOk
);
1828 if (gid
== orgGID
) {
1836 count
= getU16BE(pos
,&parsedOk
);
1838 for (i
= 0;i
< count
;i
++) {
1839 Guint startGID
, endGID
;
1842 startGID
= getU16BE(pos
,&parsedOk
);
1844 endGID
= getU16BE(pos
,&parsedOk
);
1846 startIndex
= getU16BE(pos
,&parsedOk
);
1848 // In some poor CJK fonts, key GIDs are not sorted,
1849 // thus we cannot finish checking even when the range
1850 // including orgGID seems to have already passed.
1851 if (startGID
<= orgGID
&& orgGID
<= endGID
) {
1853 index
= startIndex
+orgGID
-startGID
;