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