1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* gxvmort1.c */ |
|
4 /* */ |
|
5 /* TrueTypeGX/AAT mort table validation */ |
|
6 /* body for type1 (Contextual Substitution) subtable. */ |
|
7 /* */ |
|
8 /* Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ |
|
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
10 /* */ |
|
11 /* This file is part of the FreeType project, and may only be used, */ |
|
12 /* modified, and distributed under the terms of the FreeType project */ |
|
13 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
14 /* this file you indicate that you have read the license and */ |
|
15 /* understand and accept it fully. */ |
|
16 /* */ |
|
17 /***************************************************************************/ |
|
18 |
|
19 /***************************************************************************/ |
|
20 /* */ |
|
21 /* gxvalid is derived from both gxlayout module and otvalid module. */ |
|
22 /* Development of gxlayout is supported by the Information-technology */ |
|
23 /* Promotion Agency(IPA), Japan. */ |
|
24 /* */ |
|
25 /***************************************************************************/ |
|
26 |
|
27 |
|
28 #include "gxvmort.h" |
|
29 |
|
30 |
|
31 /*************************************************************************/ |
|
32 /* */ |
|
33 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
34 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
35 /* messages during execution. */ |
|
36 /* */ |
|
37 #undef FT_COMPONENT |
|
38 #define FT_COMPONENT trace_gxvmort |
|
39 |
|
40 |
|
41 typedef struct GXV_mort_subtable_type1_StateOptRec_ |
|
42 { |
|
43 FT_UShort substitutionTable; |
|
44 FT_UShort substitutionTable_length; |
|
45 |
|
46 } GXV_mort_subtable_type1_StateOptRec, |
|
47 *GXV_mort_subtable_type1_StateOptRecData; |
|
48 |
|
49 #define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \ |
|
50 ( GXV_STATETABLE_HEADER_SIZE + 2 ) |
|
51 |
|
52 |
|
53 static void |
|
54 gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table, |
|
55 FT_Bytes limit, |
|
56 GXV_Validator valid ) |
|
57 { |
|
58 FT_Bytes p = table; |
|
59 |
|
60 GXV_mort_subtable_type1_StateOptRecData optdata = |
|
61 (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata; |
|
62 |
|
63 |
|
64 GXV_LIMIT_CHECK( 2 ); |
|
65 optdata->substitutionTable = FT_NEXT_USHORT( p ); |
|
66 } |
|
67 |
|
68 |
|
69 static void |
|
70 gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size, |
|
71 FT_UShort classTable, |
|
72 FT_UShort stateArray, |
|
73 FT_UShort entryTable, |
|
74 FT_UShort* classTable_length_p, |
|
75 FT_UShort* stateArray_length_p, |
|
76 FT_UShort* entryTable_length_p, |
|
77 GXV_Validator valid ) |
|
78 { |
|
79 FT_UShort o[4]; |
|
80 FT_UShort *l[4]; |
|
81 FT_UShort buff[5]; |
|
82 |
|
83 GXV_mort_subtable_type1_StateOptRecData optdata = |
|
84 (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata; |
|
85 |
|
86 |
|
87 o[0] = classTable; |
|
88 o[1] = stateArray; |
|
89 o[2] = entryTable; |
|
90 o[3] = optdata->substitutionTable; |
|
91 l[0] = classTable_length_p; |
|
92 l[1] = stateArray_length_p; |
|
93 l[2] = entryTable_length_p; |
|
94 l[3] = &( optdata->substitutionTable_length ); |
|
95 |
|
96 gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid ); |
|
97 } |
|
98 |
|
99 |
|
100 static void |
|
101 gxv_mort_subtable_type1_offset_to_subst_validate( |
|
102 FT_Short wordOffset, |
|
103 const FT_String* tag, |
|
104 FT_Byte state, |
|
105 GXV_Validator valid ) |
|
106 { |
|
107 FT_UShort substTable; |
|
108 FT_UShort substTable_limit; |
|
109 FT_UShort min_gid; |
|
110 FT_UShort max_gid; |
|
111 |
|
112 FT_UNUSED( tag ); |
|
113 FT_UNUSED( state ); |
|
114 |
|
115 |
|
116 substTable = |
|
117 ((GXV_mort_subtable_type1_StateOptRec *) |
|
118 (valid->statetable.optdata))->substitutionTable; |
|
119 substTable_limit = |
|
120 (FT_UShort)( substTable + |
|
121 ((GXV_mort_subtable_type1_StateOptRec *) |
|
122 (valid->statetable.optdata))->substitutionTable_length ); |
|
123 |
|
124 min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 ); |
|
125 max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 ); |
|
126 max_gid = (FT_UShort)( FT_MAX( max_gid, valid->face->num_glyphs ) ); |
|
127 |
|
128 /* XXX: check range? */ |
|
129 |
|
130 /* TODO: min_gid & max_gid comparison with ClassTable contents */ |
|
131 } |
|
132 |
|
133 |
|
134 static void |
|
135 gxv_mort_subtable_type1_entry_validate( |
|
136 FT_Byte state, |
|
137 FT_UShort flags, |
|
138 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p, |
|
139 FT_Bytes table, |
|
140 FT_Bytes limit, |
|
141 GXV_Validator valid ) |
|
142 { |
|
143 FT_UShort setMark; |
|
144 FT_UShort dontAdvance; |
|
145 FT_UShort reserved; |
|
146 FT_Short markOffset; |
|
147 FT_Short currentOffset; |
|
148 |
|
149 FT_UNUSED( table ); |
|
150 FT_UNUSED( limit ); |
|
151 |
|
152 |
|
153 setMark = (FT_UShort)( flags >> 15 ); |
|
154 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 ); |
|
155 reserved = (FT_Short)( flags & 0x3FFF ); |
|
156 |
|
157 markOffset = (FT_Short)( glyphOffset_p->ul >> 16 ); |
|
158 currentOffset = (FT_Short)( glyphOffset_p->ul ); |
|
159 |
|
160 if ( 0 < reserved ) |
|
161 { |
|
162 GXV_TRACE(( " non-zero bits found in reserved range\n" )); |
|
163 if ( valid->root->level >= FT_VALIDATE_PARANOID ) |
|
164 FT_INVALID_DATA; |
|
165 } |
|
166 |
|
167 gxv_mort_subtable_type1_offset_to_subst_validate( markOffset, |
|
168 "markOffset", |
|
169 state, |
|
170 valid ); |
|
171 |
|
172 gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset, |
|
173 "currentOffset", |
|
174 state, |
|
175 valid ); |
|
176 } |
|
177 |
|
178 |
|
179 static void |
|
180 gxv_mort_subtable_type1_substTable_validate( FT_Bytes table, |
|
181 FT_Bytes limit, |
|
182 GXV_Validator valid ) |
|
183 { |
|
184 FT_Bytes p = table; |
|
185 FT_UShort num_gids = (FT_UShort)( |
|
186 ((GXV_mort_subtable_type1_StateOptRec *) |
|
187 (valid->statetable.optdata))->substitutionTable_length / 2 ); |
|
188 FT_UShort i; |
|
189 |
|
190 |
|
191 GXV_NAME_ENTER( "validating contents of substitutionTable" ); |
|
192 for ( i = 0; i < num_gids ; i ++ ) |
|
193 { |
|
194 FT_UShort dst_gid; |
|
195 |
|
196 |
|
197 GXV_LIMIT_CHECK( 2 ); |
|
198 dst_gid = FT_NEXT_USHORT( p ); |
|
199 |
|
200 if ( dst_gid >= 0xFFFFU ) |
|
201 continue; |
|
202 |
|
203 if ( dst_gid > valid->face->num_glyphs ) |
|
204 { |
|
205 GXV_TRACE(( "substTable include too large gid[%d]=%d >" |
|
206 " max defined gid #%d\n", |
|
207 i, dst_gid, valid->face->num_glyphs )); |
|
208 if ( valid->root->level >= FT_VALIDATE_PARANOID ) |
|
209 FT_INVALID_GLYPH_ID; |
|
210 } |
|
211 } |
|
212 |
|
213 GXV_EXIT; |
|
214 } |
|
215 |
|
216 |
|
217 /* |
|
218 * subtable for Contextual glyph substitution is a modified StateTable. |
|
219 * In addition to classTable, stateArray, and entryTable, the field |
|
220 * `substitutionTable' is added. |
|
221 */ |
|
222 FT_LOCAL_DEF( void ) |
|
223 gxv_mort_subtable_type1_validate( FT_Bytes table, |
|
224 FT_Bytes limit, |
|
225 GXV_Validator valid ) |
|
226 { |
|
227 FT_Bytes p = table; |
|
228 |
|
229 GXV_mort_subtable_type1_StateOptRec st_rec; |
|
230 |
|
231 |
|
232 GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" ); |
|
233 |
|
234 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE ); |
|
235 |
|
236 valid->statetable.optdata = |
|
237 &st_rec; |
|
238 valid->statetable.optdata_load_func = |
|
239 gxv_mort_subtable_type1_substitutionTable_load; |
|
240 valid->statetable.subtable_setup_func = |
|
241 gxv_mort_subtable_type1_subtable_setup; |
|
242 valid->statetable.entry_glyphoffset_fmt = |
|
243 GXV_GLYPHOFFSET_ULONG; |
|
244 valid->statetable.entry_validate_func = |
|
245 |
|
246 gxv_mort_subtable_type1_entry_validate; |
|
247 gxv_StateTable_validate( p, limit, valid ); |
|
248 |
|
249 gxv_mort_subtable_type1_substTable_validate( |
|
250 table + st_rec.substitutionTable, |
|
251 table + st_rec.substitutionTable + st_rec.substitutionTable_length, |
|
252 valid ); |
|
253 |
|
254 GXV_EXIT; |
|
255 } |
|
256 |
|
257 |
|
258 /* END */ |
|