00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include "gxvalid.h"
00028 #include "gxvcommn.h"
00029
00030
00031
00032
00033
00034
00035
00036
00037 #undef FT_COMPONENT
00038 #define FT_COMPONENT trace_gxvprop
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049 #define GXV_PROP_HEADER_SIZE ( 4 + 2 + 2 )
00050 #define GXV_PROP_SIZE_MIN GXV_PROP_HEADER_SIZE
00051
00052 typedef struct GXV_prop_DataRec_
00053 {
00054 FT_Fixed version;
00055
00056 } GXV_prop_DataRec, *GXV_prop_Data;
00057
00058 #define GXV_PROP_DATA( field ) GXV_TABLE_DATA( prop, field )
00059
00060 #define GXV_PROP_FLOATER 0x8000U
00061 #define GXV_PROP_USE_COMPLEMENTARY_BRACKET 0x1000U
00062 #define GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET 0x0F00U
00063 #define GXV_PROP_ATTACHING_TO_RIGHT 0x0080U
00064 #define GXV_PROP_RESERVED 0x0060U
00065 #define GXV_PROP_DIRECTIONALITY_CLASS 0x001FU
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 static void
00077 gxv_prop_zero_advance_validate( FT_UShort gid,
00078 GXV_Validator valid )
00079 {
00080 FT_Face face;
00081 FT_Error error;
00082 FT_GlyphSlot glyph;
00083
00084
00085 GXV_NAME_ENTER( "zero advance" );
00086
00087 face = valid->face;
00088
00089 error = FT_Load_Glyph( face,
00090 gid,
00091 FT_LOAD_IGNORE_TRANSFORM );
00092 if ( error )
00093 FT_INVALID_GLYPH_ID;
00094
00095 glyph = face->glyph;
00096
00097 if ( glyph->advance.x != (FT_Pos)0 ||
00098 glyph->advance.y != (FT_Pos)0 )
00099 FT_INVALID_DATA;
00100
00101 GXV_EXIT;
00102 }
00103
00104
00105
00106 static void
00107 gxv_prop_property_validate( FT_UShort property,
00108 FT_UShort glyph,
00109 GXV_Validator valid )
00110 {
00111 if ( glyph != 0 && ( property & GXV_PROP_FLOATER ) )
00112 gxv_prop_zero_advance_validate( glyph, valid );
00113
00114 if ( property & GXV_PROP_USE_COMPLEMENTARY_BRACKET )
00115 {
00116 FT_UShort offset;
00117 char complement;
00118
00119
00120 offset = (FT_UShort)( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET );
00121 if ( offset == 0 )
00122 FT_INVALID_DATA;
00123
00124 complement = (char)( offset >> 8 );
00125 if ( complement & 0x08 )
00126 {
00127
00128
00129
00130 complement = (char)( ( complement & 0x07 ) + 1 );
00131
00132
00133 if ( glyph <= complement )
00134 FT_INVALID_DATA;
00135 }
00136 else
00137 {
00138
00139 gxv_glyphid_validate( (FT_UShort)( glyph + complement ), valid );
00140 }
00141 }
00142 else
00143 {
00144 if ( property & GXV_PROP_COMPLEMENTARY_BRACKET_OFFSET )
00145 GXV_TRACE(( "glyph %d cannot have complementary bracketing\n",
00146 glyph ));
00147 }
00148
00149
00150 if ( property & GXV_PROP_ATTACHING_TO_RIGHT )
00151 {
00152 if ( GXV_PROP_DATA( version ) == 0x00010000UL )
00153 FT_INVALID_DATA;
00154 }
00155
00156 if ( property & GXV_PROP_RESERVED )
00157 FT_INVALID_DATA;
00158
00159 if ( ( property & GXV_PROP_DIRECTIONALITY_CLASS ) > 11 )
00160 {
00161
00162 if ( GXV_PROP_DATA( version ) == 0x00010000UL ||
00163 GXV_PROP_DATA( version ) == 0x00020000UL )
00164 FT_INVALID_DATA;
00165 }
00166 }
00167
00168
00169 static void
00170 gxv_prop_LookupValue_validate( FT_UShort glyph,
00171 GXV_LookupValueCPtr value_p,
00172 GXV_Validator valid )
00173 {
00174 gxv_prop_property_validate( value_p->u, glyph, valid );
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 static GXV_LookupValueDesc
00206 gxv_prop_LookupFmt4_transit( FT_UShort relative_gindex,
00207 GXV_LookupValueCPtr base_value_p,
00208 FT_Bytes lookuptbl_limit,
00209 GXV_Validator valid )
00210 {
00211 FT_Bytes p;
00212 FT_Bytes limit;
00213 FT_UShort offset;
00214 GXV_LookupValueDesc value;
00215
00216
00217 offset = (FT_UShort)( base_value_p->u +
00218 relative_gindex * sizeof( FT_UShort ) );
00219 p = valid->lookuptbl_head + offset;
00220 limit = lookuptbl_limit;
00221
00222 GXV_LIMIT_CHECK ( 2 );
00223 value.u = FT_NEXT_USHORT( p );
00224
00225 return value;
00226 }
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237 FT_LOCAL_DEF( void )
00238 gxv_prop_validate( FT_Bytes table,
00239 FT_Face face,
00240 FT_Validator ftvalid )
00241 {
00242 FT_Bytes p = table;
00243 FT_Bytes limit = 0;
00244 GXV_ValidatorRec validrec;
00245 GXV_Validator valid = &validrec;
00246
00247 GXV_prop_DataRec proprec;
00248 GXV_prop_Data prop = &proprec;
00249
00250 FT_Fixed version;
00251 FT_UShort format;
00252 FT_UShort defaultProp;
00253
00254
00255 valid->root = ftvalid;
00256 valid->table_data = prop;
00257 valid->face = face;
00258
00259 FT_TRACE3(( "validating `prop' table\n" ));
00260 GXV_INIT;
00261
00262 GXV_LIMIT_CHECK( 4 + 2 + 2 );
00263 version = FT_NEXT_ULONG( p );
00264 format = FT_NEXT_USHORT( p );
00265 defaultProp = FT_NEXT_USHORT( p );
00266
00267
00268 if ( version != 0x00010000UL &&
00269 version != 0x00020000UL &&
00270 version != 0x00030000UL )
00271 FT_INVALID_FORMAT;
00272
00273
00274
00275 if ( format > 1 )
00276 FT_INVALID_FORMAT;
00277
00278 gxv_prop_property_validate( defaultProp, 0, valid );
00279
00280 if ( format == 0 )
00281 {
00282 FT_TRACE3(( "(format 0, no per-glyph properties, "
00283 "remaining %d bytes are skipped)", limit - p ));
00284 goto Exit;
00285 }
00286
00287
00288 GXV_PROP_DATA( version ) = version;
00289
00290 valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
00291 valid->lookupval_func = gxv_prop_LookupValue_validate;
00292 valid->lookupfmt4_trans = gxv_prop_LookupFmt4_transit;
00293
00294 gxv_LookupTable_validate( p, limit, valid );
00295
00296 Exit:
00297 FT_TRACE4(( "\n" ));
00298 }
00299
00300
00301