1 /***************************************************************************/ 2 /* */ 3 /* gxvmod.c */ 4 /* */ 5 /* FreeType's TrueTypeGX/AAT validation module implementation (body). */ 6 /* */ 7 /* Copyright 2004-2018 by */ 8 /* 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 <ft2build.h> 29 #include FT_TRUETYPE_TABLES_H 30 #include FT_TRUETYPE_TAGS_H 31 #include FT_GX_VALIDATE_H 32 #include FT_INTERNAL_OBJECTS_H 33 #include FT_SERVICE_GX_VALIDATE_H 34 35 #include "gxvmod.h" 36 #include "gxvalid.h" 37 #include "gxvcommn.h" 38 39 40 /*************************************************************************/ 41 /* */ 42 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 43 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 44 /* messages during execution. */ 45 /* */ 46 #undef FT_COMPONENT 47 #define FT_COMPONENT trace_gxvmodule 48 49 50 static FT_Error gxv_load_table(FT_Face face,FT_Tag tag,FT_Byte * volatile * table,FT_ULong * table_len)51 gxv_load_table( FT_Face face, 52 FT_Tag tag, 53 FT_Byte* volatile* table, 54 FT_ULong* table_len ) 55 { 56 FT_Error error; 57 FT_Memory memory = FT_FACE_MEMORY( face ); 58 59 60 error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len ); 61 if ( FT_ERR_EQ( error, Table_Missing ) ) 62 return FT_Err_Ok; 63 if ( error ) 64 goto Exit; 65 66 if ( FT_ALLOC( *table, *table_len ) ) 67 goto Exit; 68 69 error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); 70 71 Exit: 72 return error; 73 } 74 75 76 #define GXV_TABLE_DECL( _sfnt ) \ 77 FT_Byte* volatile _sfnt = NULL; \ 78 FT_ULong len_ ## _sfnt = 0 79 80 #define GXV_TABLE_LOAD( _sfnt ) \ 81 if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \ 82 ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \ 83 { \ 84 error = gxv_load_table( face, TTAG_ ## _sfnt, \ 85 &_sfnt, &len_ ## _sfnt ); \ 86 if ( error ) \ 87 goto Exit; \ 88 } 89 90 #define GXV_TABLE_VALIDATE( _sfnt ) \ 91 if ( _sfnt ) \ 92 { \ 93 ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \ 94 FT_VALIDATE_DEFAULT ); \ 95 if ( ft_setjmp( valid.jump_buffer ) == 0 ) \ 96 gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \ 97 error = valid.error; \ 98 if ( error ) \ 99 goto Exit; \ 100 } 101 102 #define GXV_TABLE_SET( _sfnt ) \ 103 if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) \ 104 tables[FT_VALIDATE_ ## _sfnt ## _INDEX] = (FT_Bytes)_sfnt 105 106 107 static FT_Error gxv_validate(FT_Face face,FT_UInt gx_flags,FT_Bytes tables[FT_VALIDATE_GX_LENGTH],FT_UInt table_count)108 gxv_validate( FT_Face face, 109 FT_UInt gx_flags, 110 FT_Bytes tables[FT_VALIDATE_GX_LENGTH], 111 FT_UInt table_count ) 112 { 113 FT_Memory volatile memory = FT_FACE_MEMORY( face ); 114 115 FT_Error error = FT_Err_Ok; 116 FT_ValidatorRec volatile valid; 117 118 FT_UInt i; 119 120 121 GXV_TABLE_DECL( feat ); 122 GXV_TABLE_DECL( bsln ); 123 GXV_TABLE_DECL( trak ); 124 GXV_TABLE_DECL( just ); 125 GXV_TABLE_DECL( mort ); 126 GXV_TABLE_DECL( morx ); 127 GXV_TABLE_DECL( kern ); 128 GXV_TABLE_DECL( opbd ); 129 GXV_TABLE_DECL( prop ); 130 GXV_TABLE_DECL( lcar ); 131 132 for ( i = 0; i < table_count; i++ ) 133 tables[i] = 0; 134 135 /* load tables */ 136 GXV_TABLE_LOAD( feat ); 137 GXV_TABLE_LOAD( bsln ); 138 GXV_TABLE_LOAD( trak ); 139 GXV_TABLE_LOAD( just ); 140 GXV_TABLE_LOAD( mort ); 141 GXV_TABLE_LOAD( morx ); 142 GXV_TABLE_LOAD( kern ); 143 GXV_TABLE_LOAD( opbd ); 144 GXV_TABLE_LOAD( prop ); 145 GXV_TABLE_LOAD( lcar ); 146 147 /* validate tables */ 148 GXV_TABLE_VALIDATE( feat ); 149 GXV_TABLE_VALIDATE( bsln ); 150 GXV_TABLE_VALIDATE( trak ); 151 GXV_TABLE_VALIDATE( just ); 152 GXV_TABLE_VALIDATE( mort ); 153 GXV_TABLE_VALIDATE( morx ); 154 GXV_TABLE_VALIDATE( kern ); 155 GXV_TABLE_VALIDATE( opbd ); 156 GXV_TABLE_VALIDATE( prop ); 157 GXV_TABLE_VALIDATE( lcar ); 158 159 /* Set results */ 160 GXV_TABLE_SET( feat ); 161 GXV_TABLE_SET( mort ); 162 GXV_TABLE_SET( morx ); 163 GXV_TABLE_SET( bsln ); 164 GXV_TABLE_SET( just ); 165 GXV_TABLE_SET( kern ); 166 GXV_TABLE_SET( opbd ); 167 GXV_TABLE_SET( trak ); 168 GXV_TABLE_SET( prop ); 169 GXV_TABLE_SET( lcar ); 170 171 Exit: 172 if ( error ) 173 { 174 FT_FREE( feat ); 175 FT_FREE( bsln ); 176 FT_FREE( trak ); 177 FT_FREE( just ); 178 FT_FREE( mort ); 179 FT_FREE( morx ); 180 FT_FREE( kern ); 181 FT_FREE( opbd ); 182 FT_FREE( prop ); 183 FT_FREE( lcar ); 184 } 185 186 return error; 187 } 188 189 190 static FT_Error classic_kern_validate(FT_Face face,FT_UInt ckern_flags,FT_Bytes * ckern_table)191 classic_kern_validate( FT_Face face, 192 FT_UInt ckern_flags, 193 FT_Bytes* ckern_table ) 194 { 195 FT_Memory volatile memory = FT_FACE_MEMORY( face ); 196 197 FT_Byte* volatile ckern = NULL; 198 FT_ULong len_ckern = 0; 199 200 /* without volatile on `error' GCC 4.1.1. emits: */ 201 /* warning: variable 'error' might be clobbered by 'longjmp' or 'vfork' */ 202 /* this warning seems spurious but --- */ 203 FT_Error volatile error; 204 FT_ValidatorRec volatile valid; 205 206 207 *ckern_table = NULL; 208 209 error = gxv_load_table( face, TTAG_kern, &ckern, &len_ckern ); 210 if ( error ) 211 goto Exit; 212 213 if ( ckern ) 214 { 215 ft_validator_init( &valid, ckern, ckern + len_ckern, 216 FT_VALIDATE_DEFAULT ); 217 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 218 gxv_kern_validate_classic( ckern, face, 219 ckern_flags & FT_VALIDATE_CKERN, &valid ); 220 error = valid.error; 221 if ( error ) 222 goto Exit; 223 } 224 225 *ckern_table = ckern; 226 227 Exit: 228 if ( error ) 229 FT_FREE( ckern ); 230 231 return error; 232 } 233 234 235 static 236 const FT_Service_GXvalidateRec gxvalid_interface = 237 { 238 gxv_validate /* validate */ 239 }; 240 241 242 static 243 const FT_Service_CKERNvalidateRec ckernvalid_interface = 244 { 245 classic_kern_validate /* validate */ 246 }; 247 248 249 static 250 const FT_ServiceDescRec gxvalid_services[] = 251 { 252 { FT_SERVICE_ID_GX_VALIDATE, &gxvalid_interface }, 253 { FT_SERVICE_ID_CLASSICKERN_VALIDATE, &ckernvalid_interface }, 254 { NULL, NULL } 255 }; 256 257 258 static FT_Pointer gxvalid_get_service(FT_Module module,const char * service_id)259 gxvalid_get_service( FT_Module module, 260 const char* service_id ) 261 { 262 FT_UNUSED( module ); 263 264 return ft_service_list_lookup( gxvalid_services, service_id ); 265 } 266 267 268 FT_CALLBACK_TABLE_DEF 269 const FT_Module_Class gxv_module_class = 270 { 271 0, 272 sizeof ( FT_ModuleRec ), 273 "gxvalid", 274 0x10000L, 275 0x20000L, 276 277 NULL, /* module-specific interface */ 278 279 (FT_Module_Constructor)NULL, /* module_init */ 280 (FT_Module_Destructor) NULL, /* module_done */ 281 (FT_Module_Requester) gxvalid_get_service /* get_interface */ 282 }; 283 284 285 /* END */ 286