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
;
117 ((GXV_mort_subtable_type1_StateOptRec
*)
118 (valid
->statetable
.optdata
))->substitutionTable
;
120 (FT_UShort
)( substTable
+
121 ((GXV_mort_subtable_type1_StateOptRec
*)
122 (valid
->statetable
.optdata
))->substitutionTable_length
);
124 min_gid
= (FT_UShort
)( ( substTable
- wordOffset
* 2 ) / 2 );
125 max_gid
= (FT_UShort
)( ( substTable_limit
- wordOffset
* 2 ) / 2 );
126 max_gid
= (FT_UShort
)( FT_MAX( max_gid
, valid
->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 valid
)
144 FT_UShort dontAdvance
;
147 FT_Short currentOffset
;
153 setMark
= (FT_UShort
)( flags
>> 15 );
154 dontAdvance
= (FT_UShort
)( ( flags
>> 14 ) & 1 );
155 reserved
= (FT_Short
)( flags
& 0x3FFF );
157 markOffset
= (FT_Short
)( glyphOffset_p
->ul
>> 16 );
158 currentOffset
= (FT_Short
)( glyphOffset_p
->ul
);
162 GXV_TRACE(( " non-zero bits found in reserved range\n" ));
163 if ( valid
->root
->level
>= FT_VALIDATE_PARANOID
)
167 gxv_mort_subtable_type1_offset_to_subst_validate( markOffset
,
172 gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset
,
180 gxv_mort_subtable_type1_substTable_validate( FT_Bytes table
,
182 GXV_Validator valid
)
185 FT_UShort num_gids
= (FT_UShort
)(
186 ((GXV_mort_subtable_type1_StateOptRec
*)
187 (valid
->statetable
.optdata
))->substitutionTable_length
/ 2 );
191 GXV_NAME_ENTER( "validating contents of substitutionTable" );
192 for ( i
= 0; i
< num_gids
; i
++ )
197 GXV_LIMIT_CHECK( 2 );
198 dst_gid
= FT_NEXT_USHORT( p
);
200 if ( dst_gid
>= 0xFFFFU
)
203 if ( dst_gid
> valid
->face
->num_glyphs
)
205 GXV_TRACE(( "substTable include too large gid[%d]=%d >"
206 " max defined gid #%d\n",
207 i
, dst_gid
, valid
->face
->num_glyphs
));
208 if ( valid
->root
->level
>= FT_VALIDATE_PARANOID
)
218 * subtable for Contextual glyph substitution is a modified StateTable.
219 * In addition to classTable, stateArray, and entryTable, the field
220 * `substitutionTable' is added.
223 gxv_mort_subtable_type1_validate( FT_Bytes table
,
225 GXV_Validator valid
)
229 GXV_mort_subtable_type1_StateOptRec st_rec
;
232 GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
234 GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE
);
236 valid
->statetable
.optdata
=
238 valid
->statetable
.optdata_load_func
=
239 gxv_mort_subtable_type1_substitutionTable_load
;
240 valid
->statetable
.subtable_setup_func
=
241 gxv_mort_subtable_type1_subtable_setup
;
242 valid
->statetable
.entry_glyphoffset_fmt
=
243 GXV_GLYPHOFFSET_ULONG
;
244 valid
->statetable
.entry_validate_func
=
246 gxv_mort_subtable_type1_entry_validate
;
247 gxv_StateTable_validate( p
, limit
, valid
);
249 gxv_mort_subtable_type1_substTable_validate(
250 table
+ st_rec
.substitutionTable
,
251 table
+ st_rec
.substitutionTable
+ st_rec
.substitutionTable_length
,