1 /***************************************************************************/ 2 /* */ 3 /* gxvmort5.c */ 4 /* */ 5 /* TrueTypeGX/AAT mort table validation */ 6 /* body for type5 (Contextual Glyph Insertion) subtable. */ 7 /* */ 8 /* Copyright 2005 by 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 "gxvmort.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 trace_gxvmort 39 40 41 /* 42 * mort subtable type5 (Contextual Glyph Insertion) 43 * has the format of StateTable with insertion-glyph-list, 44 * but without name. The offset is given by glyphOffset in 45 * entryTable. There is no table location declaration 46 * like xxxTable. 47 */ 48 49 typedef struct GXV_mort_subtable_type5_StateOptRec_ 50 { 51 FT_UShort classTable; 52 FT_UShort stateArray; 53 FT_UShort entryTable; 54 55 #define GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE GXV_STATETABLE_HEADER_SIZE 56 57 FT_UShort* classTable_length_p; 58 FT_UShort* stateArray_length_p; 59 FT_UShort* entryTable_length_p; 60 61 } GXV_mort_subtable_type5_StateOptRec, 62 *GXV_mort_subtable_type5_StateOptRecData; 63 64 65 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 valid)66 gxv_mort_subtable_type5_subtable_setup( FT_UShort table_size, 67 FT_UShort classTable, 68 FT_UShort stateArray, 69 FT_UShort entryTable, 70 FT_UShort* classTable_length_p, 71 FT_UShort* stateArray_length_p, 72 FT_UShort* entryTable_length_p, 73 GXV_Validator valid ) 74 { 75 GXV_mort_subtable_type5_StateOptRecData optdata = 76 (GXV_mort_subtable_type5_StateOptRecData)valid->statetable.optdata; 77 78 79 gxv_StateTable_subtable_setup( table_size, 80 classTable, 81 stateArray, 82 entryTable, 83 classTable_length_p, 84 stateArray_length_p, 85 entryTable_length_p, 86 valid ); 87 88 optdata->classTable = classTable; 89 optdata->stateArray = stateArray; 90 optdata->entryTable = entryTable; 91 92 optdata->classTable_length_p = classTable_length_p; 93 optdata->stateArray_length_p = stateArray_length_p; 94 optdata->entryTable_length_p = entryTable_length_p; 95 } 96 97 98 static void gxv_mort_subtable_type5_InsertList_validate(FT_UShort offset,FT_UShort count,FT_Bytes table,FT_Bytes limit,GXV_Validator valid)99 gxv_mort_subtable_type5_InsertList_validate( FT_UShort offset, 100 FT_UShort count, 101 FT_Bytes table, 102 FT_Bytes limit, 103 GXV_Validator valid ) 104 { 105 /* 106 * We don't know the range of insertion-glyph-list. 107 * Set range by whole of state table. 108 */ 109 FT_Bytes p = table + offset; 110 111 GXV_mort_subtable_type5_StateOptRecData optdata = 112 (GXV_mort_subtable_type5_StateOptRecData)valid->statetable.optdata; 113 114 if ( optdata->classTable < offset && 115 offset < optdata->classTable + *(optdata->classTable_length_p) ) 116 GXV_TRACE(( " offset runs into ClassTable" )); 117 if ( optdata->stateArray < offset && 118 offset < optdata->stateArray + *(optdata->stateArray_length_p) ) 119 GXV_TRACE(( " offset runs into StateArray" )); 120 if ( optdata->entryTable < offset && 121 offset < optdata->entryTable + *(optdata->entryTable_length_p) ) 122 GXV_TRACE(( " offset runs into EntryTable" )); 123 124 #ifndef GXV_LOAD_TRACE_VARS 125 GXV_LIMIT_CHECK( count * 2 ); 126 #else 127 while ( p < table + offset + ( count * 2 ) ) 128 { 129 FT_UShort insert_glyphID; 130 131 132 GXV_LIMIT_CHECK( 2 ); 133 insert_glyphID = FT_NEXT_USHORT( p ); 134 GXV_TRACE(( " 0x%04x", insert_glyphID )); 135 } 136 GXV_TRACE(( "\n" )); 137 #endif 138 } 139 140 141 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 valid)142 gxv_mort_subtable_type5_entry_validate( 143 FT_Byte state, 144 FT_UShort flags, 145 GXV_StateTable_GlyphOffsetCPtr glyphOffset, 146 FT_Bytes table, 147 FT_Bytes limit, 148 GXV_Validator valid ) 149 { 150 #ifdef GXV_LOAD_UNUSED_VARS 151 FT_Bool setMark; 152 FT_Bool dontAdvance; 153 FT_Bool currentIsKashidaLike; 154 FT_Bool markedIsKashidaLike; 155 FT_Bool currentInsertBefore; 156 FT_Bool markedInsertBefore; 157 #endif 158 FT_Byte currentInsertCount; 159 FT_Byte markedInsertCount; 160 FT_UShort currentInsertList; 161 FT_UShort markedInsertList; 162 163 FT_UNUSED( state ); 164 165 166 #ifdef GXV_LOAD_UNUSED_VARS 167 setMark = FT_BOOL( ( flags >> 15 ) & 1 ); 168 dontAdvance = FT_BOOL( ( flags >> 14 ) & 1 ); 169 currentIsKashidaLike = FT_BOOL( ( flags >> 13 ) & 1 ); 170 markedIsKashidaLike = FT_BOOL( ( flags >> 12 ) & 1 ); 171 currentInsertBefore = FT_BOOL( ( flags >> 11 ) & 1 ); 172 markedInsertBefore = FT_BOOL( ( flags >> 10 ) & 1 ); 173 #endif 174 175 currentInsertCount = (FT_Byte)( ( flags >> 5 ) & 0x1F ); 176 markedInsertCount = (FT_Byte)( flags & 0x001F ); 177 178 currentInsertList = (FT_UShort)( glyphOffset->ul >> 16 ); 179 markedInsertList = (FT_UShort)( glyphOffset->ul ); 180 181 if ( 0 != currentInsertList && 0 != currentInsertCount ) 182 { 183 gxv_mort_subtable_type5_InsertList_validate( currentInsertList, 184 currentInsertCount, 185 table, 186 limit, 187 valid ); 188 } 189 190 if ( 0 != markedInsertList && 0 != markedInsertCount ) 191 { 192 gxv_mort_subtable_type5_InsertList_validate( markedInsertList, 193 markedInsertCount, 194 table, 195 limit, 196 valid ); 197 } 198 } 199 200 201 FT_LOCAL_DEF( void ) gxv_mort_subtable_type5_validate(FT_Bytes table,FT_Bytes limit,GXV_Validator valid)202 gxv_mort_subtable_type5_validate( FT_Bytes table, 203 FT_Bytes limit, 204 GXV_Validator valid ) 205 { 206 FT_Bytes p = table; 207 208 GXV_mort_subtable_type5_StateOptRec et_rec; 209 GXV_mort_subtable_type5_StateOptRecData et = &et_rec; 210 211 212 GXV_NAME_ENTER( "mort chain subtable type5 (Glyph Insertion)" ); 213 214 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE5_HEADER_SIZE ); 215 216 valid->statetable.optdata = 217 et; 218 valid->statetable.optdata_load_func = 219 NULL; 220 valid->statetable.subtable_setup_func = 221 gxv_mort_subtable_type5_subtable_setup; 222 valid->statetable.entry_glyphoffset_fmt = 223 GXV_GLYPHOFFSET_ULONG; 224 valid->statetable.entry_validate_func = 225 gxv_mort_subtable_type5_entry_validate; 226 227 gxv_StateTable_validate( p, limit, valid ); 228 229 GXV_EXIT; 230 } 231 232 233 /* END */ 234