Sync trunk.
[reactos.git] / lib / 3rdparty / freetype / src / gxvalid / gxvmort1.c
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 */