1 /**************************************************************************** 2 * 3 * otvmod.c 4 * 5 * FreeType's OpenType validation module implementation (body). 6 * 7 * Copyright (C) 2004-2020 by 8 * David Turner, Robert Wilhelm, and Werner Lemberg. 9 * 10 * This file is part of the FreeType project, and may only be used, 11 * modified, and distributed under the terms of the FreeType project 12 * license, LICENSE.TXT. By continuing to use, modify, or distribute 13 * this file you indicate that you have read the license and 14 * understand and accept it fully. 15 * 16 */ 17 18 19 #include <freetype/tttables.h> 20 #include <freetype/tttags.h> 21 #include <freetype/ftotval.h> 22 #include <freetype/internal/ftobjs.h> 23 #include <freetype/internal/services/svotval.h> 24 25 #include "otvmod.h" 26 #include "otvalid.h" 27 #include "otvcommn.h" 28 29 30 /************************************************************************** 31 * 32 * The macro FT_COMPONENT is used in trace mode. It is an implicit 33 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 34 * messages during execution. 35 */ 36 #undef FT_COMPONENT 37 #define FT_COMPONENT otvmodule 38 39 40 static FT_Error otv_load_table(FT_Face face,FT_Tag tag,FT_Byte * volatile * table,FT_ULong * table_len)41 otv_load_table( FT_Face face, 42 FT_Tag tag, 43 FT_Byte* volatile* table, 44 FT_ULong* table_len ) 45 { 46 FT_Error error; 47 FT_Memory memory = FT_FACE_MEMORY( face ); 48 49 50 error = FT_Load_Sfnt_Table( face, tag, 0, NULL, table_len ); 51 if ( FT_ERR_EQ( error, Table_Missing ) ) 52 return FT_Err_Ok; 53 if ( error ) 54 goto Exit; 55 56 if ( FT_ALLOC( *table, *table_len ) ) 57 goto Exit; 58 59 error = FT_Load_Sfnt_Table( face, tag, 0, *table, table_len ); 60 61 Exit: 62 return error; 63 } 64 65 66 static FT_Error otv_validate(FT_Face volatile face,FT_UInt ot_flags,FT_Bytes * ot_base,FT_Bytes * ot_gdef,FT_Bytes * ot_gpos,FT_Bytes * ot_gsub,FT_Bytes * ot_jstf)67 otv_validate( FT_Face volatile face, 68 FT_UInt ot_flags, 69 FT_Bytes *ot_base, 70 FT_Bytes *ot_gdef, 71 FT_Bytes *ot_gpos, 72 FT_Bytes *ot_gsub, 73 FT_Bytes *ot_jstf ) 74 { 75 FT_Error error = FT_Err_Ok; 76 FT_Byte* volatile base; 77 FT_Byte* volatile gdef; 78 FT_Byte* volatile gpos; 79 FT_Byte* volatile gsub; 80 FT_Byte* volatile jstf; 81 FT_Byte* volatile math; 82 FT_ULong len_base, len_gdef, len_gpos, len_gsub, len_jstf; 83 FT_ULong len_math; 84 FT_UInt num_glyphs = (FT_UInt)face->num_glyphs; 85 FT_ValidatorRec volatile valid; 86 87 88 base = gdef = gpos = gsub = jstf = math = NULL; 89 len_base = len_gdef = len_gpos = len_gsub = len_jstf = len_math = 0; 90 91 /* 92 * XXX: OpenType tables cannot handle 32-bit glyph index, 93 * although broken TrueType can have 32-bit glyph index. 94 */ 95 if ( face->num_glyphs > 0xFFFFL ) 96 { 97 FT_TRACE1(( "otv_validate: Invalid glyphs index (0x0000FFFF - 0x%08x) ", 98 face->num_glyphs )); 99 FT_TRACE1(( "are not handled by OpenType tables\n" )); 100 num_glyphs = 0xFFFF; 101 } 102 103 /* load tables */ 104 105 if ( ot_flags & FT_VALIDATE_BASE ) 106 { 107 error = otv_load_table( face, TTAG_BASE, &base, &len_base ); 108 if ( error ) 109 goto Exit; 110 } 111 112 if ( ot_flags & FT_VALIDATE_GDEF ) 113 { 114 error = otv_load_table( face, TTAG_GDEF, &gdef, &len_gdef ); 115 if ( error ) 116 goto Exit; 117 } 118 119 if ( ot_flags & FT_VALIDATE_GPOS ) 120 { 121 error = otv_load_table( face, TTAG_GPOS, &gpos, &len_gpos ); 122 if ( error ) 123 goto Exit; 124 } 125 126 if ( ot_flags & FT_VALIDATE_GSUB ) 127 { 128 error = otv_load_table( face, TTAG_GSUB, &gsub, &len_gsub ); 129 if ( error ) 130 goto Exit; 131 } 132 133 if ( ot_flags & FT_VALIDATE_JSTF ) 134 { 135 error = otv_load_table( face, TTAG_JSTF, &jstf, &len_jstf ); 136 if ( error ) 137 goto Exit; 138 } 139 140 if ( ot_flags & FT_VALIDATE_MATH ) 141 { 142 error = otv_load_table( face, TTAG_MATH, &math, &len_math ); 143 if ( error ) 144 goto Exit; 145 } 146 147 /* validate tables */ 148 149 if ( base ) 150 { 151 ft_validator_init( &valid, base, base + len_base, FT_VALIDATE_DEFAULT ); 152 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 153 otv_BASE_validate( base, &valid ); 154 error = valid.error; 155 if ( error ) 156 goto Exit; 157 } 158 159 if ( gpos ) 160 { 161 ft_validator_init( &valid, gpos, gpos + len_gpos, FT_VALIDATE_DEFAULT ); 162 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 163 otv_GPOS_validate( gpos, num_glyphs, &valid ); 164 error = valid.error; 165 if ( error ) 166 goto Exit; 167 } 168 169 if ( gsub ) 170 { 171 ft_validator_init( &valid, gsub, gsub + len_gsub, FT_VALIDATE_DEFAULT ); 172 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 173 otv_GSUB_validate( gsub, num_glyphs, &valid ); 174 error = valid.error; 175 if ( error ) 176 goto Exit; 177 } 178 179 if ( gdef ) 180 { 181 ft_validator_init( &valid, gdef, gdef + len_gdef, FT_VALIDATE_DEFAULT ); 182 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 183 otv_GDEF_validate( gdef, gsub, gpos, num_glyphs, &valid ); 184 error = valid.error; 185 if ( error ) 186 goto Exit; 187 } 188 189 if ( jstf ) 190 { 191 ft_validator_init( &valid, jstf, jstf + len_jstf, FT_VALIDATE_DEFAULT ); 192 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 193 otv_JSTF_validate( jstf, gsub, gpos, num_glyphs, &valid ); 194 error = valid.error; 195 if ( error ) 196 goto Exit; 197 } 198 199 if ( math ) 200 { 201 ft_validator_init( &valid, math, math + len_math, FT_VALIDATE_DEFAULT ); 202 if ( ft_setjmp( valid.jump_buffer ) == 0 ) 203 otv_MATH_validate( math, num_glyphs, &valid ); 204 error = valid.error; 205 if ( error ) 206 goto Exit; 207 } 208 209 *ot_base = (FT_Bytes)base; 210 *ot_gdef = (FT_Bytes)gdef; 211 *ot_gpos = (FT_Bytes)gpos; 212 *ot_gsub = (FT_Bytes)gsub; 213 *ot_jstf = (FT_Bytes)jstf; 214 215 Exit: 216 if ( error ) 217 { 218 FT_Memory memory = FT_FACE_MEMORY( face ); 219 220 221 FT_FREE( base ); 222 FT_FREE( gdef ); 223 FT_FREE( gpos ); 224 FT_FREE( gsub ); 225 FT_FREE( jstf ); 226 } 227 228 { 229 FT_Memory memory = FT_FACE_MEMORY( face ); 230 231 232 FT_FREE( math ); /* Can't return this as API is frozen */ 233 } 234 235 return error; 236 } 237 238 239 static 240 const FT_Service_OTvalidateRec otvalid_interface = 241 { 242 otv_validate /* validate */ 243 }; 244 245 246 static 247 const FT_ServiceDescRec otvalid_services[] = 248 { 249 { FT_SERVICE_ID_OPENTYPE_VALIDATE, &otvalid_interface }, 250 { NULL, NULL } 251 }; 252 253 254 static FT_Pointer otvalid_get_service(FT_Module module,const char * service_id)255 otvalid_get_service( FT_Module module, 256 const char* service_id ) 257 { 258 FT_UNUSED( module ); 259 260 return ft_service_list_lookup( otvalid_services, service_id ); 261 } 262 263 264 FT_CALLBACK_TABLE_DEF 265 const FT_Module_Class otv_module_class = 266 { 267 0, 268 sizeof ( FT_ModuleRec ), 269 "otvalid", 270 0x10000L, 271 0x20000L, 272 273 NULL, /* module-specific interface */ 274 275 (FT_Module_Constructor)NULL, /* module_init */ 276 (FT_Module_Destructor) NULL, /* module_done */ 277 (FT_Module_Requester) otvalid_get_service /* get_interface */ 278 }; 279 280 281 /* END */ 282