1 /***************************************************************************/
5 /* TrueTypeGX/AAT feat table validation (body). */
7 /* Copyright 2004, 2005, 2008 by */
8 /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
17 /***************************************************************************/
19 /***************************************************************************/
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. */
25 /***************************************************************************/
33 /*************************************************************************/
35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
37 /* messages during execution. */
40 #define FT_COMPONENT trace_gxvfeat
43 /*************************************************************************/
44 /*************************************************************************/
46 /***** Data and Types *****/
48 /*************************************************************************/
49 /*************************************************************************/
51 typedef struct GXV_feat_DataRec_
53 FT_UInt reserved_size
;
57 } GXV_feat_DataRec
, *GXV_feat_Data
;
60 #define GXV_FEAT_DATA( field ) GXV_TABLE_DATA( feat, field )
63 typedef enum GXV_FeatureFlagsMask_
65 GXV_FEAT_MASK_EXCLUSIVE_SETTINGS
= 0x8000U
,
66 GXV_FEAT_MASK_DYNAMIC_DEFAULT
= 0x4000,
67 GXV_FEAT_MASK_UNUSED
= 0x3F00,
68 GXV_FEAT_MASK_DEFAULT_SETTING
= 0x00FF
70 } GXV_FeatureFlagsMask
;
73 /*************************************************************************/
74 /*************************************************************************/
76 /***** UTILITY FUNCTIONS *****/
78 /*************************************************************************/
79 /*************************************************************************/
82 gxv_feat_registry_validate( FT_UShort feature
,
87 GXV_NAME_ENTER( "feature in registry" );
89 GXV_TRACE(( " (feature = %u)\n", feature
));
91 if ( feature
>= gxv_feat_registry_length
)
93 GXV_TRACE(( "feature number %d is out of range %d\n",
94 feature
, gxv_feat_registry_length
));
95 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
)
100 if ( gxv_feat_registry
[feature
].existence
== 0 )
102 GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
104 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
)
109 if ( gxv_feat_registry
[feature
].apple_reserved
)
111 /* Don't use here. Apple is reserved. */
112 GXV_TRACE(( "feature number %d is reserved by Apple\n", feature
));
113 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
117 if ( nSettings
!= gxv_feat_registry
[feature
].nSettings
)
119 GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n",
121 gxv_feat_registry
[feature
].nSettings
));
122 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
126 if ( exclusive
!= gxv_feat_registry
[feature
].exclusive
)
128 GXV_TRACE(( "exclusive flag %d differs from predefined value\n",
130 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
140 gxv_feat_name_index_validate( FT_Bytes table
,
142 GXV_Validator valid
)
149 GXV_NAME_ENTER( "nameIndex" );
151 GXV_LIMIT_CHECK( 2 );
152 nameIndex
= FT_NEXT_SHORT ( p
);
153 GXV_TRACE(( " (nameIndex = %d)\n", nameIndex
));
155 gxv_sfntName_validate( (FT_UShort
)nameIndex
,
165 gxv_feat_setting_validate( FT_Bytes table
,
168 GXV_Validator valid
)
174 GXV_NAME_ENTER( "setting" );
176 GXV_LIMIT_CHECK( 2 );
178 setting
= FT_NEXT_USHORT( p
);
180 /* If we have exclusive setting, the setting should be odd. */
181 if ( exclusive
&& ( setting
% 2 ) == 0 )
184 gxv_feat_name_index_validate( p
, limit
, valid
);
186 GXV_FEAT_DATA( setting
) = setting
;
193 gxv_feat_name_validate( FT_Bytes table
,
195 GXV_Validator valid
)
198 FT_UInt reserved_size
= GXV_FEAT_DATA( reserved_size
);
202 FT_ULong settingTable
;
203 FT_UShort featureFlags
;
210 GXV_NAME_ENTER( "name" );
212 /* feature + nSettings + settingTable + featureFlags */
213 GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );
215 feature
= FT_NEXT_USHORT( p
);
216 GXV_FEAT_DATA( feature
) = feature
;
218 nSettings
= FT_NEXT_USHORT( p
);
219 settingTable
= FT_NEXT_ULONG ( p
);
220 featureFlags
= FT_NEXT_USHORT( p
);
222 if ( settingTable
< reserved_size
)
225 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
226 ( featureFlags
& GXV_FEAT_MASK_UNUSED
) == 0 )
229 exclusive
= FT_BOOL( featureFlags
& GXV_FEAT_MASK_EXCLUSIVE_SETTINGS
);
232 FT_Byte dynamic_default
;
235 if ( featureFlags
& GXV_FEAT_MASK_DYNAMIC_DEFAULT
)
236 dynamic_default
= (FT_Byte
)( featureFlags
&
237 GXV_FEAT_MASK_DEFAULT_SETTING
);
241 /* If exclusive, check whether default setting is in the range. */
242 if ( !( dynamic_default
< nSettings
) )
246 gxv_feat_registry_validate( feature
, nSettings
, exclusive
, valid
);
248 gxv_feat_name_index_validate( p
, limit
, valid
);
250 p
= valid
->root
->base
+ settingTable
;
251 for ( last_setting
= -1, i
= 0; i
< nSettings
; i
++ )
253 gxv_feat_setting_validate( p
, limit
, exclusive
, valid
);
255 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
256 (FT_Int
)GXV_FEAT_DATA( setting
) <= last_setting
)
259 last_setting
= (FT_Int
)GXV_FEAT_DATA( setting
);
260 /* setting + nameIndex */
268 /*************************************************************************/
269 /*************************************************************************/
271 /***** feat TABLE *****/
273 /*************************************************************************/
274 /*************************************************************************/
277 gxv_feat_validate( FT_Bytes table
,
279 FT_Validator ftvalid
)
281 GXV_ValidatorRec validrec
;
282 GXV_Validator valid
= &validrec
;
284 GXV_feat_DataRec featrec
;
285 GXV_feat_Data feat
= &featrec
;
290 FT_UInt featureNameCount
;
296 valid
->root
= ftvalid
;
297 valid
->table_data
= feat
;
300 FT_TRACE3(( "validating `feat' table\n" ));
303 feat
->reserved_size
= 0;
305 /* version + featureNameCount + none_0 + none_1 */
306 GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
307 feat
->reserved_size
+= 4 + 2 + 2 + 4;
309 if ( FT_NEXT_ULONG( p
) != 0x00010000UL
) /* Version */
312 featureNameCount
= FT_NEXT_USHORT( p
);
313 GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount
));
315 if ( valid
->root
->level
!= FT_VALIDATE_PARANOID
)
316 p
+= 6; /* skip (none) and (none) */
319 if ( FT_NEXT_USHORT( p
) != 0 )
322 if ( FT_NEXT_ULONG( p
) != 0 )
326 feat
->reserved_size
+= featureNameCount
* ( 2 + 2 + 4 + 2 + 2 );
328 for ( last_feature
= -1, i
= 0; i
< featureNameCount
; i
++ )
330 gxv_feat_name_validate( p
, limit
, valid
);
332 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
333 (FT_Int
)GXV_FEAT_DATA( feature
) <= last_feature
)
336 last_feature
= GXV_FEAT_DATA( feature
);
337 p
+= 2 + 2 + 4 + 2 + 2;