| /***************************************************************************/ |
| /* */ |
| /* gxvmod.c */ |
| /* */ |
| /* FreeType's TrueTypeGX/AAT validation module implementation (body). */ |
| /* */ |
| /* Copyright 2004-2015 by */ |
| /* suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ |
| /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
| /* */ |
| /* This file is part of the FreeType project, and may only be used, */ |
| /* modified, and distributed under the terms of the FreeType project */ |
| /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
| /* this file you indicate that you have read the license and */ |
| /* understand and accept it fully. */ |
| /* */ |
| /***************************************************************************/ |
| |
| /***************************************************************************/ |
| /* */ |
| /* gxvalid is derived from both gxlayout module and otvalid module. */ |
| /* Development of gxlayout is supported by the Information-technology */ |
| /* Promotion Agency(IPA), Japan. */ |
| /* */ |
| /***************************************************************************/ |
| |
| |
| #include <ft2build.h> |
| #include FT_TRUETYPE_TABLES_H |
| #include FT_TRUETYPE_TAGS_H |
| #include FT_GX_VALIDATE_H |
| #include FT_INTERNAL_OBJECTS_H |
| #include FT_SERVICE_GX_VALIDATE_H |
| |
| #include "gxvmod.h" |
| #include "gxvalid.h" |
| #include "gxvcommn.h" |
| |
| |
| /*************************************************************************/ |
| /* */ |
| /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
| /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
| /* messages during execution. */ |
| /* */ |
| #undef FT_COMPONENT |
| #define FT_COMPONENT trace_gxvmodule |
| |
| |
| static FT_Error |
| gxv_load_table( FT_Face face, |
| FT_Tag tag, |
| FT_Byte* volatile* table, |
| FT_ULong* table_len ) |
| { |
| FT_Error error; |
| FT_Memory memory = FT_FACE_MEMORY( face ); |
| |
| |
| error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len ); |
| if ( FT_ERR_EQ( error, Table_Missing ) ) |
| return FT_Err_Ok; |
| if ( error ) |
| goto Exit; |
| |
| if ( FT_ALLOC( *table, *table_len ) ) |
| goto Exit; |
| |
| error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); |
| |
| Exit: |
| return error; |
| } |
| |
| |
| #define GXV_TABLE_DECL( _sfnt ) \ |
| FT_Byte* volatile _sfnt = NULL; \ |
| FT_ULong len_ ## _sfnt = 0 |
| |
| #define GXV_TABLE_LOAD( _sfnt ) \ |
| if ( ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) && \ |
| ( gx_flags & FT_VALIDATE_ ## _sfnt ) ) \ |
| { \ |
| error = gxv_load_table( face, TTAG_ ## _sfnt, \ |
| &_sfnt, &len_ ## _sfnt ); \ |
| if ( error ) \ |
| goto Exit; \ |
| } |
| |
| #define GXV_TABLE_VALIDATE( _sfnt ) \ |
| if ( _sfnt ) \ |
| { \ |
| ft_validator_init( &valid, _sfnt, _sfnt + len_ ## _sfnt, \ |
| FT_VALIDATE_DEFAULT ); \ |
| if ( ft_setjmp( valid.jump_buffer ) == 0 ) \ |
| gxv_ ## _sfnt ## _validate( _sfnt, face, &valid ); \ |
| error = valid.error; \ |
| if ( error ) \ |
| goto Exit; \ |
| } |
| |
| #define GXV_TABLE_SET( _sfnt ) \ |
| if ( FT_VALIDATE_ ## _sfnt ## _INDEX < table_count ) \ |
| tables[FT_VALIDATE_ ## _sfnt ## _INDEX] = (FT_Bytes)_sfnt |
| |
| |
| static FT_Error |
| gxv_validate( FT_Face face, |
| FT_UInt gx_flags, |
| FT_Bytes tables[FT_VALIDATE_GX_LENGTH], |
| FT_UInt table_count ) |
| { |
| FT_Memory volatile memory = FT_FACE_MEMORY( face ); |
| |
| FT_Error error = FT_Err_Ok; |
| FT_ValidatorRec volatile valid; |
| |
| FT_UInt i; |
| |
| |
| GXV_TABLE_DECL( feat ); |
| GXV_TABLE_DECL( bsln ); |
| GXV_TABLE_DECL( trak ); |
| GXV_TABLE_DECL( just ); |
| GXV_TABLE_DECL( mort ); |
| GXV_TABLE_DECL( morx ); |
| GXV_TABLE_DECL( kern ); |
| GXV_TABLE_DECL( opbd ); |
| GXV_TABLE_DECL( prop ); |
| GXV_TABLE_DECL( lcar ); |
| |
| for ( i = 0; i < table_count; i++ ) |
| tables[i] = 0; |
| |
| /* load tables */ |
| GXV_TABLE_LOAD( feat ); |
| GXV_TABLE_LOAD( bsln ); |
| GXV_TABLE_LOAD( trak ); |
| GXV_TABLE_LOAD( just ); |
| GXV_TABLE_LOAD( mort ); |
| GXV_TABLE_LOAD( morx ); |
| GXV_TABLE_LOAD( kern ); |
| GXV_TABLE_LOAD( opbd ); |
| GXV_TABLE_LOAD( prop ); |
| GXV_TABLE_LOAD( lcar ); |
| |
| /* validate tables */ |
| GXV_TABLE_VALIDATE( feat ); |
| GXV_TABLE_VALIDATE( bsln ); |
| GXV_TABLE_VALIDATE( trak ); |
| GXV_TABLE_VALIDATE( just ); |
| GXV_TABLE_VALIDATE( mort ); |
| GXV_TABLE_VALIDATE( morx ); |
| GXV_TABLE_VALIDATE( kern ); |
| GXV_TABLE_VALIDATE( opbd ); |
| GXV_TABLE_VALIDATE( prop ); |
| GXV_TABLE_VALIDATE( lcar ); |
| |
| /* Set results */ |
| GXV_TABLE_SET( feat ); |
| GXV_TABLE_SET( mort ); |
| GXV_TABLE_SET( morx ); |
| GXV_TABLE_SET( bsln ); |
| GXV_TABLE_SET( just ); |
| GXV_TABLE_SET( kern ); |
| GXV_TABLE_SET( opbd ); |
| GXV_TABLE_SET( trak ); |
| GXV_TABLE_SET( prop ); |
| GXV_TABLE_SET( lcar ); |
| |
| Exit: |
| if ( error ) |
| { |
| FT_FREE( feat ); |
| FT_FREE( bsln ); |
| FT_FREE( trak ); |
| FT_FREE( just ); |
| FT_FREE( mort ); |
| FT_FREE( morx ); |
| FT_FREE( kern ); |
| FT_FREE( opbd ); |
| FT_FREE( prop ); |
| FT_FREE( lcar ); |
| } |
| |
| return error; |
| } |
| |
| |
| static FT_Error |
| classic_kern_validate( FT_Face face, |
| FT_UInt ckern_flags, |
| FT_Bytes* ckern_table ) |
| { |
| FT_Memory volatile memory = FT_FACE_MEMORY( face ); |
| |
| FT_Byte* volatile ckern = NULL; |
| FT_ULong len_ckern = 0; |
| |
| /* without volatile on `error' GCC 4.1.1. emits: */ |
| /* warning: variable 'error' might be clobbered by 'longjmp' or 'vfork' */ |
| /* this warning seems spurious but --- */ |
| FT_Error volatile error; |
| FT_ValidatorRec volatile valid; |
| |
| |
| *ckern_table = NULL; |
| |
| error = gxv_load_table( face, TTAG_kern, &ckern, &len_ckern ); |
| if ( error ) |
| goto Exit; |
| |
| if ( ckern ) |
| { |
| ft_validator_init( &valid, ckern, ckern + len_ckern, |
| FT_VALIDATE_DEFAULT ); |
| if ( ft_setjmp( valid.jump_buffer ) == 0 ) |
| gxv_kern_validate_classic( ckern, face, |
| ckern_flags & FT_VALIDATE_CKERN, &valid ); |
| error = valid.error; |
| if ( error ) |
| goto Exit; |
| } |
| |
| *ckern_table = ckern; |
| |
| Exit: |
| if ( error ) |
| FT_FREE( ckern ); |
| |
| return error; |
| } |
| |
| |
| static |
| const FT_Service_GXvalidateRec gxvalid_interface = |
| { |
| gxv_validate |
| }; |
| |
| |
| static |
| const FT_Service_CKERNvalidateRec ckernvalid_interface = |
| { |
| classic_kern_validate |
| }; |
| |
| |
| static |
| const FT_ServiceDescRec gxvalid_services[] = |
| { |
| { FT_SERVICE_ID_GX_VALIDATE, &gxvalid_interface }, |
| { FT_SERVICE_ID_CLASSICKERN_VALIDATE, &ckernvalid_interface }, |
| { NULL, NULL } |
| }; |
| |
| |
| static FT_Pointer |
| gxvalid_get_service( FT_Module module, |
| const char* service_id ) |
| { |
| FT_UNUSED( module ); |
| |
| return ft_service_list_lookup( gxvalid_services, service_id ); |
| } |
| |
| |
| FT_CALLBACK_TABLE_DEF |
| const FT_Module_Class gxv_module_class = |
| { |
| 0, |
| sizeof ( FT_ModuleRec ), |
| "gxvalid", |
| 0x10000L, |
| 0x20000L, |
| |
| 0, /* module-specific interface */ |
| |
| (FT_Module_Constructor)0, |
| (FT_Module_Destructor) 0, |
| (FT_Module_Requester) gxvalid_get_service |
| }; |
| |
| |
| /* END */ |