/src/freetype/src/gxvalid/gxvmorx1.c
C | 277 lines | 168 code | 67 blank | 42 comment | 5 complexity | ef339d3ca1810f5bd45bd9b6bce2bae0 MD5 | raw file
1/***************************************************************************/ 2/* */ 3/* gxvmorx1.c */ 4/* */ 5/* TrueTypeGX/AAT morx table validation */ 6/* body for type1 (Contextual Substitution) subtable. */ 7/* */ 8/* Copyright 2005, 2007 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 "gxvmorx.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_gxvmorx 39 40 41 typedef struct GXV_morx_subtable_type1_StateOptRec_ 42 { 43 FT_ULong substitutionTable; 44 FT_ULong substitutionTable_length; 45 FT_UShort substitutionTable_num_lookupTables; 46 47 } GXV_morx_subtable_type1_StateOptRec, 48 *GXV_morx_subtable_type1_StateOptRecData; 49 50 51#define GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE \ 52 ( GXV_STATETABLE_HEADER_SIZE + 2 ) 53 54 55 static void 56 gxv_morx_subtable_type1_substitutionTable_load( FT_Bytes table, 57 FT_Bytes limit, 58 GXV_Validator valid ) 59 { 60 FT_Bytes p = table; 61 62 GXV_morx_subtable_type1_StateOptRecData optdata = 63 (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata; 64 65 66 GXV_LIMIT_CHECK( 2 ); 67 optdata->substitutionTable = FT_NEXT_USHORT( p ); 68 } 69 70 71 static void 72 gxv_morx_subtable_type1_subtable_setup( FT_ULong table_size, 73 FT_ULong classTable, 74 FT_ULong stateArray, 75 FT_ULong entryTable, 76 FT_ULong* classTable_length_p, 77 FT_ULong* stateArray_length_p, 78 FT_ULong* entryTable_length_p, 79 GXV_Validator valid ) 80 { 81 FT_ULong o[4]; 82 FT_ULong *l[4]; 83 FT_ULong buff[5]; 84 85 GXV_morx_subtable_type1_StateOptRecData optdata = 86 (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata; 87 88 89 o[0] = classTable; 90 o[1] = stateArray; 91 o[2] = entryTable; 92 o[3] = optdata->substitutionTable; 93 l[0] = classTable_length_p; 94 l[1] = stateArray_length_p; 95 l[2] = entryTable_length_p; 96 l[3] = &(optdata->substitutionTable_length); 97 98 gxv_set_length_by_ulong_offset( o, l, buff, 4, table_size, valid ); 99 } 100 101 102 static void 103 gxv_morx_subtable_type1_entry_validate( 104 FT_UShort state, 105 FT_UShort flags, 106 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p, 107 FT_Bytes table, 108 FT_Bytes limit, 109 GXV_Validator valid ) 110 { 111#ifdef GXV_LOAD_TRACE_VARS 112 FT_UShort setMark; 113 FT_UShort dontAdvance; 114#endif 115 FT_UShort reserved; 116 FT_Short markIndex; 117 FT_Short currentIndex; 118 119 GXV_morx_subtable_type1_StateOptRecData optdata = 120 (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata; 121 122 FT_UNUSED( state ); 123 FT_UNUSED( table ); 124 FT_UNUSED( limit ); 125 126 127#ifdef GXV_LOAD_TRACE_VARS 128 setMark = (FT_UShort)( ( flags >> 15 ) & 1 ); 129 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 ); 130#endif 131 132 reserved = (FT_UShort)( flags & 0x3FFF ); 133 134 markIndex = (FT_Short)( glyphOffset_p->ul >> 16 ); 135 currentIndex = (FT_Short)( glyphOffset_p->ul ); 136 137 GXV_TRACE(( " setMark=%01d dontAdvance=%01d\n", 138 setMark, dontAdvance )); 139 140 if ( 0 < reserved ) 141 { 142 GXV_TRACE(( " non-zero bits found in reserved range\n" )); 143 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA ); 144 } 145 146 GXV_TRACE(( "markIndex = %d, currentIndex = %d\n", 147 markIndex, currentIndex )); 148 149 if ( optdata->substitutionTable_num_lookupTables < markIndex + 1 ) 150 optdata->substitutionTable_num_lookupTables = 151 (FT_Short)( markIndex + 1 ); 152 153 if ( optdata->substitutionTable_num_lookupTables < currentIndex + 1 ) 154 optdata->substitutionTable_num_lookupTables = 155 (FT_Short)( currentIndex + 1 ); 156 } 157 158 159 static void 160 gxv_morx_subtable_type1_LookupValue_validate( FT_UShort glyph, 161 GXV_LookupValueCPtr value_p, 162 GXV_Validator valid ) 163 { 164 FT_UNUSED( glyph ); /* for the non-debugging case */ 165 166 GXV_TRACE(( "morx subtable type1 subst.: %d -> %d\n", glyph, value_p->u )); 167 168 if ( value_p->u > valid->face->num_glyphs ) 169 FT_INVALID_GLYPH_ID; 170 } 171 172 173 static GXV_LookupValueDesc 174 gxv_morx_subtable_type1_LookupFmt4_transit( 175 FT_UShort relative_gindex, 176 GXV_LookupValueCPtr base_value_p, 177 FT_Bytes lookuptbl_limit, 178 GXV_Validator valid ) 179 { 180 FT_Bytes p; 181 FT_Bytes limit; 182 FT_UShort offset; 183 GXV_LookupValueDesc value; 184 185 /* XXX: check range? */ 186 offset = (FT_UShort)( base_value_p->u + 187 relative_gindex * sizeof ( FT_UShort ) ); 188 189 p = valid->lookuptbl_head + offset; 190 limit = lookuptbl_limit; 191 192 GXV_LIMIT_CHECK ( 2 ); 193 value.u = FT_NEXT_USHORT( p ); 194 195 return value; 196 } 197 198 199 /* 200 * TODO: length should be limit? 201 **/ 202 static void 203 gxv_morx_subtable_type1_substitutionTable_validate( FT_Bytes table, 204 FT_Bytes limit, 205 GXV_Validator valid ) 206 { 207 FT_Bytes p = table; 208 FT_UShort i; 209 210 GXV_morx_subtable_type1_StateOptRecData optdata = 211 (GXV_morx_subtable_type1_StateOptRecData)valid->xstatetable.optdata; 212 213 214 /* TODO: calculate offset/length for each lookupTables */ 215 valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED; 216 valid->lookupval_func = gxv_morx_subtable_type1_LookupValue_validate; 217 valid->lookupfmt4_trans = gxv_morx_subtable_type1_LookupFmt4_transit; 218 219 for ( i = 0; i < optdata->substitutionTable_num_lookupTables; i++ ) 220 { 221 FT_ULong offset; 222 223 224 GXV_LIMIT_CHECK( 4 ); 225 offset = FT_NEXT_ULONG( p ); 226 227 gxv_LookupTable_validate( table + offset, limit, valid ); 228 } 229 230 /* TODO: overlapping of lookupTables in substitutionTable */ 231 } 232 233 234 /* 235 * subtable for Contextual glyph substitution is a modified StateTable. 236 * In addition to classTable, stateArray, entryTable, the field 237 * `substitutionTable' is added. 238 */ 239 FT_LOCAL_DEF( void ) 240 gxv_morx_subtable_type1_validate( FT_Bytes table, 241 FT_Bytes limit, 242 GXV_Validator valid ) 243 { 244 FT_Bytes p = table; 245 246 GXV_morx_subtable_type1_StateOptRec st_rec; 247 248 249 GXV_NAME_ENTER( "morx chain subtable type1 (Contextual Glyph Subst)" ); 250 251 GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE ); 252 253 st_rec.substitutionTable_num_lookupTables = 0; 254 255 valid->xstatetable.optdata = 256 &st_rec; 257 valid->xstatetable.optdata_load_func = 258 gxv_morx_subtable_type1_substitutionTable_load; 259 valid->xstatetable.subtable_setup_func = 260 gxv_morx_subtable_type1_subtable_setup; 261 valid->xstatetable.entry_glyphoffset_fmt = 262 GXV_GLYPHOFFSET_ULONG; 263 valid->xstatetable.entry_validate_func = 264 gxv_morx_subtable_type1_entry_validate; 265 266 gxv_XStateTable_validate( p, limit, valid ); 267 268 gxv_morx_subtable_type1_substitutionTable_validate( 269 table + st_rec.substitutionTable, 270 table + st_rec.substitutionTable + st_rec.substitutionTable_length, 271 valid ); 272 273 GXV_EXIT; 274 } 275 276 277/* END */