| 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 |
| 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 |
| 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 |
| 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 |
| 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 | |