1 /****************************************************************************
5 * TrueTypeGX/AAT mort table validation
6 * body for type1 (Contextual Substitution) subtable.
8 * Copyright (C) 2005-2020 by
9 * suzuki toshiya, Masatake YAMATO, Red Hat K.K.,
10 * David Turner, Robert Wilhelm, and Werner Lemberg.
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.
20 /****************************************************************************
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.
32 /**************************************************************************
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.
39 #define FT_COMPONENT gxvmort
42 typedef struct GXV_mort_subtable_type1_StateOptRec_
44 FT_UShort substitutionTable;
45 FT_UShort substitutionTable_length;
47 } GXV_mort_subtable_type1_StateOptRec,
48 *GXV_mort_subtable_type1_StateOptRecData;
50 #define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \
51 ( GXV_STATETABLE_HEADER_SIZE + 2 )
55 gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table,
57 GXV_Validator gxvalid )
61 GXV_mort_subtable_type1_StateOptRecData optdata =
62 (GXV_mort_subtable_type1_StateOptRecData)gxvalid->statetable.optdata;
66 optdata->substitutionTable = FT_NEXT_USHORT( p );
71 gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size,
75 FT_UShort* classTable_length_p,
76 FT_UShort* stateArray_length_p,
77 FT_UShort* entryTable_length_p,
78 GXV_Validator gxvalid )
84 GXV_mort_subtable_type1_StateOptRecData optdata =
85 (GXV_mort_subtable_type1_StateOptRecData)gxvalid->statetable.optdata;
91 o[3] = optdata->substitutionTable;
92 l[0] = classTable_length_p;
93 l[1] = stateArray_length_p;
94 l[2] = entryTable_length_p;
95 l[3] = &( optdata->substitutionTable_length );
97 gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, gxvalid );
102 gxv_mort_subtable_type1_offset_to_subst_validate(
104 const FT_String* tag,
106 GXV_Validator gxvalid )
108 FT_UShort substTable;
109 FT_UShort substTable_limit;
116 ((GXV_mort_subtable_type1_StateOptRec *)
117 (gxvalid->statetable.optdata))->substitutionTable;
119 (FT_UShort)( substTable +
120 ((GXV_mort_subtable_type1_StateOptRec *)
121 (gxvalid->statetable.optdata))->substitutionTable_length );
123 gxvalid->min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
124 gxvalid->max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
125 gxvalid->max_gid = (FT_UShort)( FT_MAX( gxvalid->max_gid,
126 gxvalid->face->num_glyphs ) );
128 /* XXX: check range? */
130 /* TODO: min_gid & max_gid comparison with ClassTable contents */
135 gxv_mort_subtable_type1_entry_validate(
138 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
141 GXV_Validator gxvalid )
143 #ifdef GXV_LOAD_UNUSED_VARS
145 FT_UShort dontAdvance;
149 FT_Short currentOffset;
155 #ifdef GXV_LOAD_UNUSED_VARS
156 setMark = (FT_UShort)( flags >> 15 );
157 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
159 reserved = (FT_UShort)( flags & 0x3FFF );
161 markOffset = (FT_Short)( glyphOffset_p->ul >> 16 );
162 currentOffset = (FT_Short)( glyphOffset_p->ul );
166 GXV_TRACE(( " non-zero bits found in reserved range\n" ));
167 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
170 gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
175 gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
183 gxv_mort_subtable_type1_substTable_validate( FT_Bytes table,
185 GXV_Validator gxvalid )
188 FT_UShort num_gids = (FT_UShort)(
189 ((GXV_mort_subtable_type1_StateOptRec *)
190 (gxvalid->statetable.optdata))->substitutionTable_length / 2 );
194 GXV_NAME_ENTER( "validating contents of substitutionTable" );
195 for ( i = 0; i < num_gids; i++ )
200 GXV_LIMIT_CHECK( 2 );
201 dst_gid = FT_NEXT_USHORT( p );
203 if ( dst_gid >= 0xFFFFU )
206 if ( dst_gid < gxvalid->min_gid || gxvalid->max_gid < dst_gid )
208 GXV_TRACE(( "substTable include a strange gid[%d]=%d >"
209 " out of define range (%d..%d)\n",
210 i, dst_gid, gxvalid->min_gid, gxvalid->max_gid ));
211 GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
220 * subtable for Contextual glyph substitution is a modified StateTable.
221 * In addition to classTable, stateArray, and entryTable, the field
222 * `substitutionTable' is added.
225 gxv_mort_subtable_type1_validate( FT_Bytes table,
227 GXV_Validator gxvalid )
231 GXV_mort_subtable_type1_StateOptRec st_rec;
234 GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
236 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
238 gxvalid->statetable.optdata =
240 gxvalid->statetable.optdata_load_func =
241 gxv_mort_subtable_type1_substitutionTable_load;
242 gxvalid->statetable.subtable_setup_func =
243 gxv_mort_subtable_type1_subtable_setup;
244 gxvalid->statetable.entry_glyphoffset_fmt =
245 GXV_GLYPHOFFSET_ULONG;
246 gxvalid->statetable.entry_validate_func =
248 gxv_mort_subtable_type1_entry_validate;
249 gxv_StateTable_validate( p, limit, gxvalid );
251 gxv_mort_subtable_type1_substTable_validate(
252 table + st_rec.substitutionTable,
253 table + st_rec.substitutionTable + st_rec.substitutionTable_length,