1 /***************************************************************************/
5 /* TrueTypeGX/AAT mort table validation */
6 /* body for type1 (Contextual Substitution) subtable. */
8 /* Copyright 2005, 2007 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
9 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
17 /***************************************************************************/
19 /***************************************************************************/
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. */
25 /***************************************************************************/
31 /*************************************************************************/
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. */
38 #define FT_COMPONENT trace_gxvmort
41 typedef struct GXV_mort_subtable_type1_StateOptRec_
43 FT_UShort substitutionTable;
44 FT_UShort substitutionTable_length;
46 } GXV_mort_subtable_type1_StateOptRec,
47 *GXV_mort_subtable_type1_StateOptRecData;
49 #define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \
50 ( GXV_STATETABLE_HEADER_SIZE + 2 )
54 gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table,
60 GXV_mort_subtable_type1_StateOptRecData optdata =
61 (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
65 optdata->substitutionTable = FT_NEXT_USHORT( p );
70 gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size,
74 FT_UShort* classTable_length_p,
75 FT_UShort* stateArray_length_p,
76 FT_UShort* entryTable_length_p,
83 GXV_mort_subtable_type1_StateOptRecData optdata =
84 (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
90 o[3] = optdata->substitutionTable;
91 l[0] = classTable_length_p;
92 l[1] = stateArray_length_p;
93 l[2] = entryTable_length_p;
94 l[3] = &( optdata->substitutionTable_length );
96 gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
101 gxv_mort_subtable_type1_offset_to_subst_validate(
103 const FT_String* tag,
105 GXV_Validator valid )
107 FT_UShort substTable;
108 FT_UShort substTable_limit;
115 ((GXV_mort_subtable_type1_StateOptRec *)
116 (valid->statetable.optdata))->substitutionTable;
118 (FT_UShort)( substTable +
119 ((GXV_mort_subtable_type1_StateOptRec *)
120 (valid->statetable.optdata))->substitutionTable_length );
122 valid->min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
123 valid->max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
124 valid->max_gid = (FT_UShort)( FT_MAX( valid->max_gid,
125 valid->face->num_glyphs ) );
127 /* XXX: check range? */
129 /* TODO: min_gid & max_gid comparison with ClassTable contents */
134 gxv_mort_subtable_type1_entry_validate(
137 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
140 GXV_Validator valid )
142 #ifdef GXV_LOAD_UNUSED_VARS
144 FT_UShort dontAdvance;
148 FT_Short currentOffset;
154 #ifdef GXV_LOAD_UNUSED_VARS
155 setMark = (FT_UShort)( flags >> 15 );
156 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
158 reserved = (FT_Short)( flags & 0x3FFF );
160 markOffset = (FT_Short)( glyphOffset_p->ul >> 16 );
161 currentOffset = (FT_Short)( glyphOffset_p->ul );
165 GXV_TRACE(( " non-zero bits found in reserved range\n" ));
166 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
169 gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
174 gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
182 gxv_mort_subtable_type1_substTable_validate( FT_Bytes table,
184 GXV_Validator valid )
187 FT_UShort num_gids = (FT_UShort)(
188 ((GXV_mort_subtable_type1_StateOptRec *)
189 (valid->statetable.optdata))->substitutionTable_length / 2 );
193 GXV_NAME_ENTER( "validating contents of substitutionTable" );
194 for ( i = 0; i < num_gids ; i ++ )
199 GXV_LIMIT_CHECK( 2 );
200 dst_gid = FT_NEXT_USHORT( p );
202 if ( dst_gid >= 0xFFFFU )
205 if ( dst_gid < valid->min_gid || valid->max_gid < dst_gid )
207 GXV_TRACE(( "substTable include a strange gid[%d]=%d >"
208 " out of define range (%d..%d)\n",
209 i, dst_gid, valid->min_gid, valid->max_gid ));
210 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
219 * subtable for Contextual glyph substitution is a modified StateTable.
220 * In addition to classTable, stateArray, and entryTable, the field
221 * `substitutionTable' is added.
224 gxv_mort_subtable_type1_validate( FT_Bytes table,
226 GXV_Validator valid )
230 GXV_mort_subtable_type1_StateOptRec st_rec;
233 GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
235 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
237 valid->statetable.optdata =
239 valid->statetable.optdata_load_func =
240 gxv_mort_subtable_type1_substitutionTable_load;
241 valid->statetable.subtable_setup_func =
242 gxv_mort_subtable_type1_subtable_setup;
243 valid->statetable.entry_glyphoffset_fmt =
244 GXV_GLYPHOFFSET_ULONG;
245 valid->statetable.entry_validate_func =
247 gxv_mort_subtable_type1_entry_validate;
248 gxv_StateTable_validate( p, limit, valid );
250 gxv_mort_subtable_type1_substTable_validate(
251 table + st_rec.substitutionTable,
252 table + st_rec.substitutionTable + st_rec.substitutionTable_length,