1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* gxvprop.c */ |
|
4 /* */ |
|
5 /* TrueTypeGX/AAT prop table validation (body). */ |
|
6 /* */ |
|
7 /* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ |
|
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
9 /* */ |
|
10 /* This file is part of the FreeType project, and may only be used, */ |
|
11 /* modified, and distributed under the terms of the FreeType project */ |
|
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
13 /* this file you indicate that you have read the license and */ |
|
14 /* understand and accept it fully. */ |
|
15 /* */ |
|
16 /***************************************************************************/ |
|
17 |
|
18 /***************************************************************************/ |
|
19 /* */ |
|
20 /* gxvalid is derived from both gxlayout module and otvalid module. */ |
|
21 /* Development of gxlayout is supported by the Information-technology */ |
|
22 /* Promotion Agency(IPA), Japan. */ |
|
23 /* */ |
|
24 /***************************************************************************/ |
|
25 |
|
26 |
|
27 #include "gxvalid.h" |
|
28 #include "gxvcommn.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_gxvprop |
|
39 |
|
40 |
|
41 /*************************************************************************/ |
|
42 /*************************************************************************/ |
|
43 /***** *****/ |
|
44 /***** Data and Types *****/ |
|
45 /***** *****/ |
|
46 /*************************************************************************/ |
|
47 /*************************************************************************/ |
|
48 |
|
49 #define GXV_PROP_HEADER_SIZE ( 4 + 2 + 2 ) |
|
50 #define GXV_PROP_SIZE_MIN GXV_PROP_HEADER_SIZE |
|
51 |
|
52 typedef struct GXV_prop_DataRec_ |
|
53 { |
|
54 FT_Fixed version; |
|
55 |
|
56 } GXV_prop_DataRec, *GXV_prop_Data; |
|
57 |
|
58 #define GXV_PROP_DATA( field ) GXV_TABLE_DATA( prop, field ) |
|
59 |
|
60 #define GXV_PROP_FLOATER 0x8000U |
|
61 #define GXV_PROP_USE_COMPLEMENTARY_BRACKET 0x1000U |
|
62 #define GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET 0x0F00U |
|
63 #define GXV_PROP_ATTACHING_TO_RIGHT 0x0080U |
|
64 #define GXV_PROP_RESERVED 0x0060U |
|
65 #define GXV_PROP_DIRECTIONALITY_CLASS 0x001FU |
|
66 |
|
67 |
|
68 /*************************************************************************/ |
|
69 /*************************************************************************/ |
|
70 /***** *****/ |
|
71 /***** UTILITY FUNCTIONS *****/ |
|
72 /***** *****/ |
|
73 /*************************************************************************/ |
|
74 /*************************************************************************/ |
|
75 |
|
76 static void |
|
77 gxv_prop_zero_advance_validate( FT_UShort gid, |
|
78 GXV_Validator valid ) |
|
79 { |
|
80 FT_Face face; |
|
81 FT_Error error; |
|
82 FT_GlyphSlot glyph; |
|
83 |
|
84 |
|
85 GXV_NAME_ENTER( "zero advance" ); |
|
86 |
|
87 face = valid->face; |
|
88 |
|
89 error = FT_Load_Glyph( face, |
|
90 gid, |
|
91 FT_LOAD_IGNORE_TRANSFORM ); |
|
92 if ( error ) |
|
93 FT_INVALID_GLYPH_ID; |
|
94 |
|
95 glyph = face->glyph; |
|
96 |
|
97 if ( glyph->advance.x != (FT_Pos)0 || |
|
98 glyph->advance.y != (FT_Pos)0 ) |
|
99 FT_INVALID_DATA; |
|
100 |
|
101 GXV_EXIT; |
|
102 } |
|
103 |
|
104 |
|
105 /* Pass 0 as GLYPH to check the default property */ |
|
106 static void |
|
107 gxv_prop_property_validate( FT_UShort property, |
|
108 FT_UShort glyph, |
|
109 GXV_Validator valid ) |
|
110 { |
|
111 if ( glyph != 0 && ( property & GXV_PROP_FLOATER ) ) |
|
112 gxv_prop_zero_advance_validate( glyph, valid ); |
|
113 |
|
114 if ( property & GXV_PROP_USE_COMPLEMENTARY_BRACKET ) |
|
115 { |
|
116 FT_UShort offset; |
|
117 char complement; |
|
118 |
|
119 |
|
120 offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET ); |
|
121 if ( offset == 0 ) |
|
122 FT_INVALID_DATA; |
|
123 |
|
124 complement = (char)( offset >> 8 ); |
|
125 if ( complement & 0x08 ) |
|
126 { |
|
127 /* Top bit is set: negative */ |
|
128 |
|
129 /* Calculate the absolute offset */ |
|
130 complement = (char)( ( complement & 0x07 ) + 1 ); |
|
131 |
|
132 /* The gid for complement must be greater than 0 */ |
|
133 if ( glyph <= complement ) |
|
134 FT_INVALID_DATA; |
|
135 } |
|
136 else |
|
137 { |
|
138 /* The gid for complement must be the face. */ |
|
139 gxv_glyphid_validate( (FT_UShort)( glyph + complement ), valid ); |
|
140 } |
|
141 } |
|
142 else |
|
143 { |
|
144 if ( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET ) |
|
145 GXV_TRACE(( "glyph %d cannot have complementary bracketing\n", |
|
146 glyph )); |
|
147 } |
|
148 |
|
149 /* this is introduced in version 2.0 */ |
|
150 if ( property & GXV_PROP_ATTACHING_TO_RIGHT ) |
|
151 { |
|
152 if ( GXV_PROP_DATA( version ) == 0x00010000UL ) |
|
153 FT_INVALID_DATA; |
|
154 } |
|
155 |
|
156 if ( property & GXV_PROP_RESERVED ) |
|
157 FT_INVALID_DATA; |
|
158 |
|
159 if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 ) |
|
160 { |
|
161 /* TODO: Too restricted. Use the validation level. */ |
|
162 if ( GXV_PROP_DATA( version ) == 0x00010000UL || |
|
163 GXV_PROP_DATA( version ) == 0x00020000UL ) |
|
164 FT_INVALID_DATA; |
|
165 } |
|
166 } |
|
167 |
|
168 |
|
169 static void |
|
170 gxv_prop_LookupValue_validate( FT_UShort glyph, |
|
171 GXV_LookupValueCPtr value_p, |
|
172 GXV_Validator valid ) |
|
173 { |
|
174 gxv_prop_property_validate( value_p->u, glyph, valid ); |
|
175 } |
|
176 |
|
177 |
|
178 /* |
|
179 +===============+ --------+ |
|
180 | lookup header | | |
|
181 +===============+ | |
|
182 | BinSrchHeader | | |
|
183 +===============+ | |
|
184 | lastGlyph[0] | | |
|
185 +---------------+ | |
|
186 | firstGlyph[0] | | head of lookup table |
|
187 +---------------+ | + |
|
188 | offset[0] | -> | offset [byte] |
|
189 +===============+ | + |
|
190 | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte] |
|
191 +---------------+ | |
|
192 | firstGlyph[1] | | |
|
193 +---------------+ | |
|
194 | offset[1] | | |
|
195 +===============+ | |
|
196 | |
|
197 ... | |
|
198 | |
|
199 16bit value array | |
|
200 +===============+ | |
|
201 | value | <-------+ |
|
202 ... |
|
203 */ |
|
204 |
|
205 static GXV_LookupValueDesc |
|
206 gxv_prop_LookupFmt4_transit( FT_UShort relative_gindex, |
|
207 GXV_LookupValueCPtr base_value_p, |
|
208 FT_Bytes lookuptbl_limit, |
|
209 GXV_Validator valid ) |
|
210 { |
|
211 FT_Bytes p; |
|
212 FT_Bytes limit; |
|
213 FT_UShort offset; |
|
214 GXV_LookupValueDesc value; |
|
215 |
|
216 /* XXX: check range? */ |
|
217 offset = (FT_UShort)( base_value_p->u + |
|
218 relative_gindex * sizeof( FT_UShort ) ); |
|
219 p = valid->lookuptbl_head + offset; |
|
220 limit = lookuptbl_limit; |
|
221 |
|
222 GXV_LIMIT_CHECK ( 2 ); |
|
223 value.u = FT_NEXT_USHORT( p ); |
|
224 |
|
225 return value; |
|
226 } |
|
227 |
|
228 |
|
229 /*************************************************************************/ |
|
230 /*************************************************************************/ |
|
231 /***** *****/ |
|
232 /***** prop TABLE *****/ |
|
233 /***** *****/ |
|
234 /*************************************************************************/ |
|
235 /*************************************************************************/ |
|
236 |
|
237 FT_LOCAL_DEF( void ) |
|
238 gxv_prop_validate( FT_Bytes table, |
|
239 FT_Face face, |
|
240 FT_Validator ftvalid ) |
|
241 { |
|
242 FT_Bytes p = table; |
|
243 FT_Bytes limit = 0; |
|
244 GXV_ValidatorRec validrec; |
|
245 GXV_Validator valid = &validrec; |
|
246 |
|
247 GXV_prop_DataRec proprec; |
|
248 GXV_prop_Data prop = &proprec; |
|
249 |
|
250 FT_Fixed version; |
|
251 FT_UShort format; |
|
252 FT_UShort defaultProp; |
|
253 |
|
254 |
|
255 valid->root = ftvalid; |
|
256 valid->table_data = prop; |
|
257 valid->face = face; |
|
258 |
|
259 FT_TRACE3(( "validating `prop' table\n" )); |
|
260 GXV_INIT; |
|
261 |
|
262 GXV_LIMIT_CHECK( 4 + 2 + 2 ); |
|
263 version = FT_NEXT_ULONG( p ); |
|
264 format = FT_NEXT_USHORT( p ); |
|
265 defaultProp = FT_NEXT_USHORT( p ); |
|
266 |
|
267 /* only versions 1.0, 2.0, 3.0 are defined (1996) */ |
|
268 if ( version != 0x00010000UL && |
|
269 version != 0x00020000UL && |
|
270 version != 0x00030000UL ) |
|
271 FT_INVALID_FORMAT; |
|
272 |
|
273 |
|
274 /* only formats 0x0000, 0x0001 are defined (1996) */ |
|
275 if ( format > 1 ) |
|
276 FT_INVALID_FORMAT; |
|
277 |
|
278 gxv_prop_property_validate( defaultProp, 0, valid ); |
|
279 |
|
280 if ( format == 0 ) |
|
281 { |
|
282 FT_TRACE3(( "(format 0, no per-glyph properties, " |
|
283 "remaining %d bytes are skipped)", limit - p )); |
|
284 goto Exit; |
|
285 } |
|
286 |
|
287 /* format == 1 */ |
|
288 GXV_PROP_DATA( version ) = version; |
|
289 |
|
290 valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED; |
|
291 valid->lookupval_func = gxv_prop_LookupValue_validate; |
|
292 valid->lookupfmt4_trans = gxv_prop_LookupFmt4_transit; |
|
293 |
|
294 gxv_LookupTable_validate( p, limit, valid ); |
|
295 |
|
296 Exit: |
|
297 FT_TRACE4(( "\n" )); |
|
298 } |
|
299 |
|
300 |
|
301 /* END */ |
|