1 /**************************************************************************** 2 * 3 * gxvmort5.c 4 * 5 * TrueTypeGX/AAT mort table validation 6 * body for type5 (Contextual Glyph Insertion) subtable. 7 * 8 * Copyright 2005-2018 by 9 * suzuki toshiya, Masatake YAMATO, Red Hat K.K., 10 * David Turner, Robert Wilhelm, and Werner Lemberg. 11 * 12 * This file is part of the FreeType project, and may only be used, 13 * modified, and distributed under the terms of the FreeType project 14 * license, LICENSE.TXT. By continuing to use, modify, or distribute 15 * this file you indicate that you have read the license and 16 * understand and accept it fully. 17 * 18 */ 19 20 /**************************************************************************** 21 * 22 * gxvalid is derived from both gxlayout module and otvalid module. 23 * Development of gxlayout is supported by the Information-technology 24 * Promotion Agency(IPA), Japan. 25 * 26 */ 27 28 29 #include "gxvmort.h" 30 31 32 /************************************************************************** 33 * 34 * The macro FT_COMPONENT is used in trace mode. It is an implicit 35 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 36 * messages during execution. 37 */ 38 #undef FT_COMPONENT 39 #define FT_COMPONENT trace_gxvmort 40 41 42 /* 43 * mort subtable type5 (Contextual Glyph Insertion) 44 * has the format of StateTable with insertion-glyph-list, 45 * but without name. The offset is given by glyphOffset in 46 * entryTable. There is no table location declaration 47 * like xxxTable. 48 */ 49 50 typedef struct GXV_mort_subtable_type5_StateOptRec_ 51 { 52 FT_UShort classTable; 53 FT_UShort stateArray; 54 FT_UShort entryTable; 55 56 #define GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE GXV_STATETABLE_HEADER_SIZE 57 58 FT_UShort* classTable_length_p; 59 FT_UShort* stateArray_length_p; 60 FT_UShort* entryTable_length_p; 61 62 } GXV_mort_subtable_type5_StateOptRec, 63 *GXV_mort_subtable_type5_StateOptRecData; 64 65 66 FT_LOCAL_DEF( void ) gxv_mort_subtable_type5_subtable_setup(FT_UShort table_size,FT_UShort classTable,FT_UShort stateArray,FT_UShort entryTable,FT_UShort * classTable_length_p,FT_UShort * stateArray_length_p,FT_UShort * entryTable_length_p,GXV_Validator gxvalid)67 gxv_mort_subtable_type5_subtable_setup( FT_UShort table_size, 68 FT_UShort classTable, 69 FT_UShort stateArray, 70 FT_UShort entryTable, 71 FT_UShort* classTable_length_p, 72 FT_UShort* stateArray_length_p, 73 FT_UShort* entryTable_length_p, 74 GXV_Validator gxvalid ) 75 { 76 GXV_mort_subtable_type5_StateOptRecData optdata = 77 (GXV_mort_subtable_type5_StateOptRecData)gxvalid->statetable.optdata; 78 79 80 gxv_StateTable_subtable_setup( table_size, 81 classTable, 82 stateArray, 83 entryTable, 84 classTable_length_p, 85 stateArray_length_p, 86 entryTable_length_p, 87 gxvalid ); 88 89 optdata->classTable = classTable; 90 optdata->stateArray = stateArray; 91 optdata->entryTable = entryTable; 92 93 optdata->classTable_length_p = classTable_length_p; 94 optdata->stateArray_length_p = stateArray_length_p; 95 optdata->entryTable_length_p = entryTable_length_p; 96 } 97 98 99 static void gxv_mort_subtable_type5_InsertList_validate(FT_UShort offset,FT_UShort count,FT_Bytes table,FT_Bytes limit,GXV_Validator gxvalid)100 gxv_mort_subtable_type5_InsertList_validate( FT_UShort offset, 101 FT_UShort count, 102 FT_Bytes table, 103 FT_Bytes limit, 104 GXV_Validator gxvalid ) 105 { 106 /* 107 * We don't know the range of insertion-glyph-list. 108 * Set range by whole of state table. 109 */ 110 FT_Bytes p = table + offset; 111 112 GXV_mort_subtable_type5_StateOptRecData optdata = 113 (GXV_mort_subtable_type5_StateOptRecData)gxvalid->statetable.optdata; 114 115 if ( optdata->classTable < offset && 116 offset < optdata->classTable + *(optdata->classTable_length_p) ) 117 GXV_TRACE(( " offset runs into ClassTable" )); 118 if ( optdata->stateArray < offset && 119 offset < optdata->stateArray + *(optdata->stateArray_length_p) ) 120 GXV_TRACE(( " offset runs into StateArray" )); 121 if ( optdata->entryTable < offset && 122 offset < optdata->entryTable + *(optdata->entryTable_length_p) ) 123 GXV_TRACE(( " offset runs into EntryTable" )); 124 125 #ifndef GXV_LOAD_TRACE_VARS 126 GXV_LIMIT_CHECK( count * 2 ); 127 #else 128 while ( p < table + offset + ( count * 2 ) ) 129 { 130 FT_UShort insert_glyphID; 131 132 133 GXV_LIMIT_CHECK( 2 ); 134 insert_glyphID = FT_NEXT_USHORT( p ); 135 GXV_TRACE(( " 0x%04x", insert_glyphID )); 136 } 137 GXV_TRACE(( "\n" )); 138 #endif 139 } 140 141 142 static void gxv_mort_subtable_type5_entry_validate(FT_Byte state,FT_UShort flags,GXV_StateTable_GlyphOffsetCPtr glyphOffset,FT_Bytes table,FT_Bytes limit,GXV_Validator gxvalid)143 gxv_mort_subtable_type5_entry_validate( 144 FT_Byte state, 145 FT_UShort flags, 146 GXV_StateTable_GlyphOffsetCPtr glyphOffset, 147 FT_Bytes table, 148 FT_Bytes limit, 149 GXV_Validator gxvalid ) 150 { 151 #ifdef GXV_LOAD_UNUSED_VARS 152 FT_Bool setMark; 153 FT_Bool dontAdvance; 154 FT_Bool currentIsKashidaLike; 155 FT_Bool markedIsKashidaLike; 156 FT_Bool currentInsertBefore; 157 FT_Bool markedInsertBefore; 158 #endif 159 FT_Byte currentInsertCount; 160 FT_Byte markedInsertCount; 161 FT_UShort currentInsertList; 162 FT_UShort markedInsertList; 163 164 FT_UNUSED( state ); 165 166 167 #ifdef GXV_LOAD_UNUSED_VARS 168 setMark = FT_BOOL( ( flags >> 15 ) & 1 ); 169 dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 ); 170 currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 ); 171 markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 ); 172 currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 ); 173 markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 ); 174 #endif 175 176 currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F ); 177 markedInsertCount = (FT_Byte)( flags & 0x001F ); 178 179 currentInsertList = (FT_UShort)( glyphOffset->ul >> 16 ); 180 markedInsertList = (FT_UShort)( glyphOffset->ul ); 181 182 if ( 0 != currentInsertList && 0 != currentInsertCount ) 183 { 184 gxv_mort_subtable_type5_InsertList_validate( currentInsertList, 185 currentInsertCount, 186 table, 187 limit, 188 gxvalid ); 189 } 190 191 if ( 0 != markedInsertList && 0 != markedInsertCount ) 192 { 193 gxv_mort_subtable_type5_InsertList_validate( markedInsertList, 194 markedInsertCount, 195 table, 196 limit, 197 gxvalid ); 198 } 199 } 200 201 202 FT_LOCAL_DEF( void ) gxv_mort_subtable_type5_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator gxvalid)203 gxv_mort_subtable_type5_validate( FT_Bytes table, 204 FT_Bytes limit, 205 GXV_Validator gxvalid ) 206 { 207 FT_Bytes p = table; 208 209 GXV_mort_subtable_type5_StateOptRec et_rec; 210 GXV_mort_subtable_type5_StateOptRecData et = &et_rec; 211 212 213 GXV_NAME_ENTER( "mort chain subtable type5 (Glyph Insertion)" ); 214 215 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE ); 216 217 gxvalid->statetable.optdata = 218 et; 219 gxvalid->statetable.optdata_load_func = 220 NULL; 221 gxvalid->statetable.subtable_setup_func = 222 gxv_mort_subtable_type5_subtable_setup; 223 gxvalid->statetable.entry_glyphoffset_fmt = 224 GXV_GLYPHOFFSET_ULONG; 225 gxvalid->statetable.entry_validate_func = 226 gxv_mort_subtable_type5_entry_validate; 227 228 gxv_StateTable_validate( p, limit, gxvalid ); 229 230 GXV_EXIT; 231 } 232 233 234 /* END */ 235