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