1 /***************************************************************************/
5 /* TrueTypeGX/AAT feat table validation (body). */
7 /* Copyright 2004, 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
18 /***************************************************************************/
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. */
24 /***************************************************************************/
32 /*************************************************************************/
34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
36 /* messages during execution. */
39 #define FT_COMPONENT trace_gxvfeat
42 /*************************************************************************/
43 /*************************************************************************/
45 /***** Data and Types *****/
47 /*************************************************************************/
48 /*************************************************************************/
50 typedef struct GXV_feat_DataRec_
52 FT_UInt reserved_size
;
56 } GXV_feat_DataRec
, *GXV_feat_Data
;
59 #define GXV_FEAT_DATA( field ) GXV_TABLE_DATA( feat, field )
64 GXV_FEAT_MASK_EXCLUSIVE_SETTINGS
= 0x8000U
,
65 GXV_FEAT_MASK_DYNAMIC_DEFAULT
= 0x4000,
66 GXV_FEAT_MASK_UNUSED
= 0x3F00,
67 GXV_FEAT_MASK_DEFAULT_SETTING
= 0x00FF
69 } GXV_FeatureFlagsMask
;
72 /*************************************************************************/
73 /*************************************************************************/
75 /***** UTILITY FUNCTIONS *****/
77 /*************************************************************************/
78 /*************************************************************************/
81 gxv_feat_registry_validate( FT_UShort feature
,
86 GXV_NAME_ENTER( "feature in registry" );
88 GXV_TRACE(( " (feature = %u)\n", feature
));
90 if ( feature
>= gxv_feat_registry_length
)
92 GXV_TRACE(( "feature number %d is out of range %d\n",
93 feature
, gxv_feat_registry_length
));
94 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
)
99 if ( gxv_feat_registry
[feature
].existence
== 0 )
101 GXV_TRACE(( "feature number %d is in defined range but doesn't exist\n",
103 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
)
108 if ( gxv_feat_registry
[feature
].apple_reserved
)
110 /* Don't use here. Apple is reserved. */
111 GXV_TRACE(( "feature number %d is reserved by Apple\n", feature
));
112 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
116 if ( nSettings
!= gxv_feat_registry
[feature
].nSettings
)
118 GXV_TRACE(( "feature %d: nSettings %d != defined nSettings %d\n",
120 gxv_feat_registry
[feature
].nSettings
));
121 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
125 if ( exclusive
!= gxv_feat_registry
[feature
].exclusive
)
127 GXV_TRACE(( "exclusive flag %d differs from predefined value\n",
129 if ( valid
->root
->level
>= FT_VALIDATE_TIGHT
)
139 gxv_feat_name_index_validate( FT_Bytes table
,
141 GXV_Validator valid
)
148 GXV_NAME_ENTER( "nameIndex" );
150 GXV_LIMIT_CHECK( 2 );
151 nameIndex
= FT_NEXT_SHORT ( p
);
152 GXV_TRACE(( " (nameIndex = %d)\n", nameIndex
));
154 gxv_sfntName_validate( (FT_UShort
)nameIndex
,
164 gxv_feat_setting_validate( FT_Bytes table
,
167 GXV_Validator valid
)
173 GXV_NAME_ENTER( "setting" );
175 GXV_LIMIT_CHECK( 2 );
177 setting
= FT_NEXT_USHORT( p
);
179 /* If we have exclusive setting, the setting should be odd. */
180 if ( exclusive
&& ( setting
% 2 ) == 0 )
183 gxv_feat_name_index_validate( p
, limit
, valid
);
185 GXV_FEAT_DATA( setting
) = setting
;
192 gxv_feat_name_validate( FT_Bytes table
,
194 GXV_Validator valid
)
197 FT_UInt reserved_size
= GXV_FEAT_DATA( reserved_size
);
201 FT_UInt settingTable
;
202 FT_UShort featureFlags
;
209 GXV_NAME_ENTER( "name" );
211 /* feature + nSettings + settingTable + featureFlags */
212 GXV_LIMIT_CHECK( 2 + 2 + 4 + 2 );
214 feature
= FT_NEXT_USHORT( p
);
215 GXV_FEAT_DATA( feature
) = feature
;
217 nSettings
= FT_NEXT_USHORT( p
);
218 settingTable
= FT_NEXT_ULONG ( p
);
219 featureFlags
= FT_NEXT_USHORT( p
);
221 if ( settingTable
< reserved_size
)
224 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
225 ( featureFlags
& GXV_FEAT_MASK_UNUSED
) == 0 )
228 exclusive
= FT_BOOL( featureFlags
& GXV_FEAT_MASK_EXCLUSIVE_SETTINGS
);
231 FT_Byte dynamic_default
;
234 if ( featureFlags
& GXV_FEAT_MASK_DYNAMIC_DEFAULT
)
235 dynamic_default
= (FT_Byte
)( featureFlags
&
236 GXV_FEAT_MASK_DEFAULT_SETTING
);
240 /* If exclusive, check whether default setting is in the range. */
241 if ( !( dynamic_default
< nSettings
) )
245 gxv_feat_registry_validate( feature
, nSettings
, exclusive
, valid
);
247 gxv_feat_name_index_validate( p
, limit
, valid
);
249 p
= valid
->root
->base
+ settingTable
;
250 for ( last_setting
= -1, i
= 0; i
< nSettings
; i
++ )
252 gxv_feat_setting_validate( p
, limit
, exclusive
, valid
);
254 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
255 (FT_Int
)GXV_FEAT_DATA( setting
) <= last_setting
)
258 last_setting
= (FT_Int
)GXV_FEAT_DATA( setting
);
259 /* setting + nameIndex */
267 /*************************************************************************/
268 /*************************************************************************/
270 /***** feat TABLE *****/
272 /*************************************************************************/
273 /*************************************************************************/
276 gxv_feat_validate( FT_Bytes table
,
278 FT_Validator ftvalid
)
280 GXV_ValidatorRec validrec
;
281 GXV_Validator valid
= &validrec
;
283 GXV_feat_DataRec featrec
;
284 GXV_feat_Data feat
= &featrec
;
289 FT_UInt featureNameCount
;
295 valid
->root
= ftvalid
;
296 valid
->table_data
= feat
;
299 FT_TRACE3(( "validating `feat' table\n" ));
302 feat
->reserved_size
= 0;
304 /* version + featureNameCount + none_0 + none_1 */
305 GXV_LIMIT_CHECK( 4 + 2 + 2 + 4 );
306 feat
->reserved_size
+= 4 + 2 + 2 + 4;
308 if ( FT_NEXT_ULONG( p
) != 0x00010000UL
) /* Version */
311 featureNameCount
= FT_NEXT_USHORT( p
);
312 GXV_TRACE(( " (featureNameCount = %d)\n", featureNameCount
));
314 if ( valid
->root
->level
!= FT_VALIDATE_PARANOID
)
315 p
+= 6; /* skip (none) and (none) */
318 if ( FT_NEXT_USHORT( p
) != 0 )
321 if ( FT_NEXT_ULONG( p
) != 0 )
325 feat
->reserved_size
+= featureNameCount
* ( 2 + 2 + 4 + 2 + 2 );
327 for ( last_feature
= -1, i
= 0; i
< featureNameCount
; i
++ )
329 gxv_feat_name_validate( p
, limit
, valid
);
331 if ( valid
->root
->level
== FT_VALIDATE_PARANOID
&&
332 (FT_Int
)GXV_FEAT_DATA( feature
) <= last_feature
)
335 last_feature
= GXV_FEAT_DATA( feature
);
336 p
+= 2 + 2 + 4 + 2 + 2;