1 /***************************************************************************/
5 /* TrueTypeGX/AAT morx 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_gxvmorx
41 typedef struct GXV_morx_subtable_type1_StateOptRec_
43 FT_ULong substitutionTable
;
44 FT_ULong substitutionTable_length
;
45 FT_UShort substitutionTable_num_lookupTables
;
47 } GXV_morx_subtable_type1_StateOptRec
,
48 *GXV_morx_subtable_type1_StateOptRecData
;
51 #define GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE \
52 ( GXV_STATETABLE_HEADER_SIZE + 2 )
56 gxv_morx_subtable_type1_substitutionTable_load( FT_Bytes table
,
58 GXV_Validator gxvalid
)
62 GXV_morx_subtable_type1_StateOptRecData optdata
=
63 (GXV_morx_subtable_type1_StateOptRecData
)gxvalid
->xstatetable
.optdata
;
67 optdata
->substitutionTable
= FT_NEXT_USHORT( p
);
72 gxv_morx_subtable_type1_subtable_setup( FT_ULong table_size
,
76 FT_ULong
* classTable_length_p
,
77 FT_ULong
* stateArray_length_p
,
78 FT_ULong
* entryTable_length_p
,
79 GXV_Validator gxvalid
)
85 GXV_morx_subtable_type1_StateOptRecData optdata
=
86 (GXV_morx_subtable_type1_StateOptRecData
)gxvalid
->xstatetable
.optdata
;
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
);
98 gxv_set_length_by_ulong_offset( o
, l
, buff
, 4, table_size
, gxvalid
);
103 gxv_morx_subtable_type1_entry_validate(
106 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p
,
109 GXV_Validator gxvalid
)
111 #ifdef GXV_LOAD_TRACE_VARS
113 FT_UShort dontAdvance
;
117 FT_Short currentIndex
;
119 GXV_morx_subtable_type1_StateOptRecData optdata
=
120 (GXV_morx_subtable_type1_StateOptRecData
)gxvalid
->xstatetable
.optdata
;
127 #ifdef GXV_LOAD_TRACE_VARS
128 setMark
= (FT_UShort
)( ( flags
>> 15 ) & 1 );
129 dontAdvance
= (FT_UShort
)( ( flags
>> 14 ) & 1 );
132 reserved
= (FT_UShort
)( flags
& 0x3FFF );
134 markIndex
= (FT_Short
)( glyphOffset_p
->ul
>> 16 );
135 currentIndex
= (FT_Short
)( glyphOffset_p
->ul
);
137 GXV_TRACE(( " setMark=%01d dontAdvance=%01d\n",
138 setMark
, dontAdvance
));
142 GXV_TRACE(( " non-zero bits found in reserved range\n" ));
143 GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA
);
146 GXV_TRACE(( "markIndex = %d, currentIndex = %d\n",
147 markIndex
, currentIndex
));
149 if ( optdata
->substitutionTable_num_lookupTables
< markIndex
+ 1 )
150 optdata
->substitutionTable_num_lookupTables
=
151 (FT_Short
)( markIndex
+ 1 );
153 if ( optdata
->substitutionTable_num_lookupTables
< currentIndex
+ 1 )
154 optdata
->substitutionTable_num_lookupTables
=
155 (FT_Short
)( currentIndex
+ 1 );
160 gxv_morx_subtable_type1_LookupValue_validate( FT_UShort glyph
,
161 GXV_LookupValueCPtr value_p
,
162 GXV_Validator gxvalid
)
164 FT_UNUSED( glyph
); /* for the non-debugging case */
166 GXV_TRACE(( "morx subtable type1 subst.: %d -> %d\n", glyph
, value_p
->u
));
168 if ( value_p
->u
> gxvalid
->face
->num_glyphs
)
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 gxvalid
)
183 GXV_LookupValueDesc value
;
185 /* XXX: check range? */
186 offset
= (FT_UShort
)( base_value_p
->u
+
187 relative_gindex
* sizeof ( FT_UShort
) );
189 p
= gxvalid
->lookuptbl_head
+ offset
;
190 limit
= lookuptbl_limit
;
192 GXV_LIMIT_CHECK ( 2 );
193 value
.u
= FT_NEXT_USHORT( p
);
200 * TODO: length should be limit?
203 gxv_morx_subtable_type1_substitutionTable_validate( FT_Bytes table
,
205 GXV_Validator gxvalid
)
210 GXV_morx_subtable_type1_StateOptRecData optdata
=
211 (GXV_morx_subtable_type1_StateOptRecData
)gxvalid
->xstatetable
.optdata
;
214 /* TODO: calculate offset/length for each lookupTables */
215 gxvalid
->lookupval_sign
= GXV_LOOKUPVALUE_UNSIGNED
;
216 gxvalid
->lookupval_func
= gxv_morx_subtable_type1_LookupValue_validate
;
217 gxvalid
->lookupfmt4_trans
= gxv_morx_subtable_type1_LookupFmt4_transit
;
219 for ( i
= 0; i
< optdata
->substitutionTable_num_lookupTables
; i
++ )
224 GXV_LIMIT_CHECK( 4 );
225 offset
= FT_NEXT_ULONG( p
);
227 gxv_LookupTable_validate( table
+ offset
, limit
, gxvalid
);
230 /* TODO: overlapping of lookupTables in substitutionTable */
235 * subtable for Contextual glyph substitution is a modified StateTable.
236 * In addition to classTable, stateArray, entryTable, the field
237 * `substitutionTable' is added.
240 gxv_morx_subtable_type1_validate( FT_Bytes table
,
242 GXV_Validator gxvalid
)
246 GXV_morx_subtable_type1_StateOptRec st_rec
;
249 GXV_NAME_ENTER( "morx chain subtable type1 (Contextual Glyph Subst)" );
251 GXV_LIMIT_CHECK( GXV_MORX_SUBTABLE_TYPE1_HEADER_SIZE
);
253 st_rec
.substitutionTable_num_lookupTables
= 0;
255 gxvalid
->xstatetable
.optdata
=
257 gxvalid
->xstatetable
.optdata_load_func
=
258 gxv_morx_subtable_type1_substitutionTable_load
;
259 gxvalid
->xstatetable
.subtable_setup_func
=
260 gxv_morx_subtable_type1_subtable_setup
;
261 gxvalid
->xstatetable
.entry_glyphoffset_fmt
=
262 GXV_GLYPHOFFSET_ULONG
;
263 gxvalid
->xstatetable
.entry_validate_func
=
264 gxv_morx_subtable_type1_entry_validate
;
266 gxv_XStateTable_validate( p
, limit
, gxvalid
);
268 gxv_morx_subtable_type1_substitutionTable_validate(
269 table
+ st_rec
.substitutionTable
,
270 table
+ st_rec
.substitutionTable
+ st_rec
.substitutionTable_length
,