@@ -35,6 +35,12 @@ class cmap extends Table {
3535 "rangeShift " => self ::uint16,
3636 );
3737
38+ private static $ subtable_v12_format = array (
39+ "length " => self ::uint32,
40+ "language " => self ::uint32,
41+ "ngroups " => self ::uint32
42+ );
43+
3844 protected function _parse () {
3945 $ font = $ this ->getFont ();
4046
@@ -46,74 +52,108 @@ protected function _parse() {
4652 for ($ i = 0 ; $ i < $ data ["numberSubtables " ]; $ i ++) {
4753 $ subtables [] = $ font ->unpack (self ::$ subtable_header_format );
4854 }
55+
4956 $ data ["subtables " ] = $ subtables ;
5057
5158 foreach ($ data ["subtables " ] as $ i => &$ subtable ) {
5259 $ font ->seek ($ cmap_offset + $ subtable ["offset " ]);
5360
5461 $ subtable ["format " ] = $ font ->readUInt16 ();
5562
56- // @todo Only CMAP version 4
57- if ($ subtable ["format " ] != 4 ) {
63+ // @todo Only CMAP version 4 and 12
64+ if (( $ subtable ["format " ] != 4 ) && ( $ subtable [ " format " ] != 12 ) ) {
5865 unset($ data ["subtables " ][$ i ]);
5966 $ data ["numberSubtables " ]--;
6067 continue ;
6168 }
6269
63- $ subtable += $ font ->unpack (self ::$ subtable_v4_format );
64- $ segCount = $ subtable ["segCountX2 " ] / 2 ;
65- $ subtable ["segCount " ] = $ segCount ;
70+ if ($ subtable ["format " ] == 12 ) {
6671
67- $ endCode = $ font ->readUInt16Many ( $ segCount );
72+ $ font ->readUInt16 ( );
6873
69- $ font ->readUInt16 (); // reservedPad
74+ $ subtable += $ font ->unpack ( self :: $ subtable_v12_format );
7075
71- $ startCode = $ font ->readUInt16Many ($ segCount );
72- $ idDelta = $ font ->readInt16Many ($ segCount );
76+ $ glyphIndexArray = array ();
77+ $ endCodes = array ();
78+ $ startCodes = array ();
7379
74- $ ro_start = $ font ->pos ();
75- $ idRangeOffset = $ font ->readUInt16Many ($ segCount );
80+ for ($ p = 0 ; $ p < $ subtable ['ngroups ' ]; $ p ++) {
7681
77- $ glyphIndexArray = array ();
78- for ($ i = 0 ; $ i < $ segCount ; $ i ++) {
79- $ c1 = $ startCode [$ i ];
80- $ c2 = $ endCode [$ i ];
81- $ d = $ idDelta [$ i ];
82- $ ro = $ idRangeOffset [$ i ];
82+ $ startCode = $ startCodes [] = $ font ->readUInt32 ();
83+ $ endCode = $ endCodes [] = $ font ->readUInt32 ();
84+ $ startGlyphCode = $ font ->readUInt32 ();
8385
84- if ($ ro > 0 ) {
85- $ font ->seek ($ subtable ["offset " ] + 2 * $ i + $ ro );
86+ for ($ c = $ startCode ; $ c <= $ endCode ; $ c ++) {
87+ $ glyphIndexArray [$ c ] = $ startGlyphCode ;
88+ $ startGlyphCode ++;
89+ }
8690 }
8791
88- for ($ c = $ c1 ; $ c <= $ c2 ; $ c ++) {
89- if ($ ro == 0 ) {
90- $ gid = ($ c + $ d ) & 0xFFFF ;
92+ $ subtable += array (
93+ "startCode " => $ startCodes ,
94+ "endCode " => $ endCodes ,
95+ "glyphIndexArray " => $ glyphIndexArray ,
96+ );
97+
98+ }
99+ else if ($ subtable ["format " ] == 4 ) {
100+
101+ $ subtable += $ font ->unpack (self ::$ subtable_v4_format );
102+
103+ $ segCount = $ subtable ["segCountX2 " ] / 2 ;
104+ $ subtable ["segCount " ] = $ segCount ;
105+
106+ $ endCode = $ font ->readUInt16Many ($ segCount );
107+
108+ $ font ->readUInt16 (); // reservedPad
109+
110+ $ startCode = $ font ->readUInt16Many ($ segCount );
111+ $ idDelta = $ font ->readInt16Many ($ segCount );
112+
113+ $ ro_start = $ font ->pos ();
114+ $ idRangeOffset = $ font ->readUInt16Many ($ segCount );
115+
116+ $ glyphIndexArray = array ();
117+ for ($ i = 0 ; $ i < $ segCount ; $ i ++) {
118+ $ c1 = $ startCode [$ i ];
119+ $ c2 = $ endCode [$ i ];
120+ $ d = $ idDelta [$ i ];
121+ $ ro = $ idRangeOffset [$ i ];
122+
123+ if ($ ro > 0 ) {
124+ $ font ->seek ($ subtable ["offset " ] + 2 * $ i + $ ro );
91125 }
92- else {
93- $ offset = ($ c - $ c1 ) * 2 + $ ro ;
94- $ offset = $ ro_start + 2 * $ i + $ offset ;
95126
96- $ font ->seek ($ offset );
97- $ gid = $ font ->readUInt16 ();
127+ for ($ c = $ c1 ; $ c <= $ c2 ; $ c ++) {
128+ if ($ ro == 0 ) {
129+ $ gid = ($ c + $ d ) & 0xFFFF ;
130+ }
131+ else {
132+ $ offset = ($ c - $ c1 ) * 2 + $ ro ;
133+ $ offset = $ ro_start + 2 * $ i + $ offset ;
134+
135+ $ font ->seek ($ offset );
136+ $ gid = $ font ->readUInt16 ();
98137
99- if ($ gid != 0 ) {
100- $ gid = ($ gid + $ d ) & 0xFFFF ;
138+ if ($ gid != 0 ) {
139+ $ gid = ($ gid + $ d ) & 0xFFFF ;
140+ }
101141 }
102- }
103142
104- if ($ gid > 0 ) {
105- $ glyphIndexArray [$ c ] = $ gid ;
143+ if ($ gid > 0 ) {
144+ $ glyphIndexArray [$ c ] = $ gid ;
145+ }
106146 }
107147 }
108- }
109148
110- $ subtable += array (
111- "endCode " => $ endCode ,
112- "startCode " => $ startCode ,
113- "idDelta " => $ idDelta ,
114- "idRangeOffset " => $ idRangeOffset ,
115- "glyphIndexArray " => $ glyphIndexArray ,
116- );
149+ $ subtable += array (
150+ "endCode " => $ endCode ,
151+ "startCode " => $ startCode ,
152+ "idDelta " => $ idDelta ,
153+ "idRangeOffset " => $ idRangeOffset ,
154+ "glyphIndexArray " => $ glyphIndexArray ,
155+ );
156+ }
117157 }
118158
119159 $ this ->data = $ data ;
0 commit comments