|
1 /***************************************************************************/ |
|
2 /* */ |
|
3 /* otvjstf.c */ |
|
4 /* */ |
|
5 /* OpenType JSTF table validation (body). */ |
|
6 /* */ |
|
7 /* Copyright 2004, 2007 by */ |
|
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
|
9 /* */ |
|
10 /* This file is part of the FreeType project, and may only be used, */ |
|
11 /* modified, and distributed under the terms of the FreeType project */ |
|
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
|
13 /* this file you indicate that you have read the license and */ |
|
14 /* understand and accept it fully. */ |
|
15 /* */ |
|
16 /***************************************************************************/ |
|
17 |
|
18 |
|
19 #include "otvalid.h" |
|
20 #include "otvcommn.h" |
|
21 #include "otvgpos.h" |
|
22 |
|
23 |
|
24 /*************************************************************************/ |
|
25 /* */ |
|
26 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
|
27 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ |
|
28 /* messages during execution. */ |
|
29 /* */ |
|
30 #undef FT_COMPONENT |
|
31 #define FT_COMPONENT trace_otvjstf |
|
32 |
|
33 |
|
34 #define JstfPriorityFunc otv_JstfPriority_validate |
|
35 #define JstfLookupFunc otv_GPOS_subtable_validate |
|
36 |
|
37 /* uses valid->extra1 (GSUB lookup count) */ |
|
38 /* uses valid->extra2 (GPOS lookup count) */ |
|
39 /* sets valid->extra1 (counter) */ |
|
40 |
|
41 static void |
|
42 otv_JstfPriority_validate( FT_Bytes table, |
|
43 OTV_Validator valid ) |
|
44 { |
|
45 FT_Bytes p = table; |
|
46 FT_UInt table_size; |
|
47 FT_UInt gsub_lookup_count, gpos_lookup_count; |
|
48 |
|
49 OTV_OPTIONAL_TABLE( ShrinkageEnableGSUB ); |
|
50 OTV_OPTIONAL_TABLE( ShrinkageDisableGSUB ); |
|
51 OTV_OPTIONAL_TABLE( ShrinkageEnableGPOS ); |
|
52 OTV_OPTIONAL_TABLE( ShrinkageDisableGPOS ); |
|
53 OTV_OPTIONAL_TABLE( ExtensionEnableGSUB ); |
|
54 OTV_OPTIONAL_TABLE( ExtensionDisableGSUB ); |
|
55 OTV_OPTIONAL_TABLE( ExtensionEnableGPOS ); |
|
56 OTV_OPTIONAL_TABLE( ExtensionDisableGPOS ); |
|
57 OTV_OPTIONAL_TABLE( ShrinkageJstfMax ); |
|
58 OTV_OPTIONAL_TABLE( ExtensionJstfMax ); |
|
59 |
|
60 |
|
61 OTV_ENTER; |
|
62 OTV_TRACE(( "JstfPriority table\n" )); |
|
63 |
|
64 OTV_LIMIT_CHECK( 20 ); |
|
65 |
|
66 gsub_lookup_count = valid->extra1; |
|
67 gpos_lookup_count = valid->extra2; |
|
68 |
|
69 table_size = 20; |
|
70 |
|
71 valid->extra1 = gsub_lookup_count; |
|
72 |
|
73 OTV_OPTIONAL_OFFSET( ShrinkageEnableGSUB ); |
|
74 OTV_SIZE_CHECK( ShrinkageEnableGSUB ); |
|
75 if ( ShrinkageEnableGSUB ) |
|
76 otv_x_ux( table + ShrinkageEnableGSUB, valid ); |
|
77 |
|
78 OTV_OPTIONAL_OFFSET( ShrinkageDisableGSUB ); |
|
79 OTV_SIZE_CHECK( ShrinkageDisableGSUB ); |
|
80 if ( ShrinkageDisableGSUB ) |
|
81 otv_x_ux( table + ShrinkageDisableGSUB, valid ); |
|
82 |
|
83 valid->extra1 = gpos_lookup_count; |
|
84 |
|
85 OTV_OPTIONAL_OFFSET( ShrinkageEnableGPOS ); |
|
86 OTV_SIZE_CHECK( ShrinkageEnableGPOS ); |
|
87 if ( ShrinkageEnableGPOS ) |
|
88 otv_x_ux( table + ShrinkageEnableGPOS, valid ); |
|
89 |
|
90 OTV_OPTIONAL_OFFSET( ShrinkageDisableGPOS ); |
|
91 OTV_SIZE_CHECK( ShrinkageDisableGPOS ); |
|
92 if ( ShrinkageDisableGPOS ) |
|
93 otv_x_ux( table + ShrinkageDisableGPOS, valid ); |
|
94 |
|
95 OTV_OPTIONAL_OFFSET( ShrinkageJstfMax ); |
|
96 OTV_SIZE_CHECK( ShrinkageJstfMax ); |
|
97 if ( ShrinkageJstfMax ) |
|
98 { |
|
99 /* XXX: check lookup types? */ |
|
100 OTV_NEST2( JstfMax, JstfLookup ); |
|
101 OTV_RUN( table + ShrinkageJstfMax, valid ); |
|
102 } |
|
103 |
|
104 valid->extra1 = gsub_lookup_count; |
|
105 |
|
106 OTV_OPTIONAL_OFFSET( ExtensionEnableGSUB ); |
|
107 OTV_SIZE_CHECK( ExtensionEnableGSUB ); |
|
108 if ( ExtensionEnableGSUB ) |
|
109 otv_x_ux( table + ExtensionEnableGSUB, valid ); |
|
110 |
|
111 OTV_OPTIONAL_OFFSET( ExtensionDisableGSUB ); |
|
112 OTV_SIZE_CHECK( ExtensionDisableGSUB ); |
|
113 if ( ExtensionDisableGSUB ) |
|
114 otv_x_ux( table + ExtensionDisableGSUB, valid ); |
|
115 |
|
116 valid->extra1 = gpos_lookup_count; |
|
117 |
|
118 OTV_OPTIONAL_OFFSET( ExtensionEnableGPOS ); |
|
119 OTV_SIZE_CHECK( ExtensionEnableGPOS ); |
|
120 if ( ExtensionEnableGPOS ) |
|
121 otv_x_ux( table + ExtensionEnableGPOS, valid ); |
|
122 |
|
123 OTV_OPTIONAL_OFFSET( ExtensionDisableGPOS ); |
|
124 OTV_SIZE_CHECK( ExtensionDisableGPOS ); |
|
125 if ( ExtensionDisableGPOS ) |
|
126 otv_x_ux( table + ExtensionDisableGPOS, valid ); |
|
127 |
|
128 OTV_OPTIONAL_OFFSET( ExtensionJstfMax ); |
|
129 OTV_SIZE_CHECK( ExtensionJstfMax ); |
|
130 if ( ExtensionJstfMax ) |
|
131 { |
|
132 /* XXX: check lookup types? */ |
|
133 OTV_NEST2( JstfMax, JstfLookup ); |
|
134 OTV_RUN( table + ExtensionJstfMax, valid ); |
|
135 } |
|
136 |
|
137 valid->extra1 = gsub_lookup_count; |
|
138 valid->extra2 = gpos_lookup_count; |
|
139 |
|
140 OTV_EXIT; |
|
141 } |
|
142 |
|
143 |
|
144 /* sets valid->extra (glyph count) */ |
|
145 /* sets valid->func1 (otv_JstfPriority_validate) */ |
|
146 |
|
147 static void |
|
148 otv_JstfScript_validate( FT_Bytes table, |
|
149 OTV_Validator valid ) |
|
150 { |
|
151 FT_Bytes p = table; |
|
152 FT_UInt table_size; |
|
153 FT_UInt JstfLangSysCount; |
|
154 |
|
155 OTV_OPTIONAL_TABLE( ExtGlyph ); |
|
156 OTV_OPTIONAL_TABLE( DefJstfLangSys ); |
|
157 |
|
158 |
|
159 OTV_NAME_ENTER( "JstfScript" ); |
|
160 |
|
161 OTV_LIMIT_CHECK( 6 ); |
|
162 OTV_OPTIONAL_OFFSET( ExtGlyph ); |
|
163 OTV_OPTIONAL_OFFSET( DefJstfLangSys ); |
|
164 JstfLangSysCount = FT_NEXT_USHORT( p ); |
|
165 |
|
166 OTV_TRACE(( " (JstfLangSysCount = %d)\n", JstfLangSysCount )); |
|
167 |
|
168 table_size = JstfLangSysCount * 6 + 6; |
|
169 |
|
170 OTV_SIZE_CHECK( ExtGlyph ); |
|
171 if ( ExtGlyph ) |
|
172 { |
|
173 valid->extra1 = valid->glyph_count; |
|
174 OTV_NEST1( ExtenderGlyph ); |
|
175 OTV_RUN( table + ExtGlyph, valid ); |
|
176 } |
|
177 |
|
178 OTV_SIZE_CHECK( DefJstfLangSys ); |
|
179 if ( DefJstfLangSys ) |
|
180 { |
|
181 OTV_NEST2( JstfLangSys, JstfPriority ); |
|
182 OTV_RUN( table + DefJstfLangSys, valid ); |
|
183 } |
|
184 |
|
185 OTV_LIMIT_CHECK( 6 * JstfLangSysCount ); |
|
186 |
|
187 /* JstfLangSysRecord */ |
|
188 OTV_NEST2( JstfLangSys, JstfPriority ); |
|
189 for ( ; JstfLangSysCount > 0; JstfLangSysCount-- ) |
|
190 { |
|
191 p += 4; /* skip JstfLangSysTag */ |
|
192 |
|
193 OTV_RUN( table + FT_NEXT_USHORT( p ), valid ); |
|
194 } |
|
195 |
|
196 OTV_EXIT; |
|
197 } |
|
198 |
|
199 |
|
200 /* sets valid->extra1 (GSUB lookup count) */ |
|
201 /* sets valid->extra2 (GPOS lookup count) */ |
|
202 /* sets valid->glyph_count */ |
|
203 |
|
204 FT_LOCAL_DEF( void ) |
|
205 otv_JSTF_validate( FT_Bytes table, |
|
206 FT_Bytes gsub, |
|
207 FT_Bytes gpos, |
|
208 FT_UInt glyph_count, |
|
209 FT_Validator ftvalid ) |
|
210 { |
|
211 OTV_ValidatorRec validrec; |
|
212 OTV_Validator valid = &validrec; |
|
213 FT_Bytes p = table; |
|
214 FT_UInt JstfScriptCount; |
|
215 |
|
216 |
|
217 valid->root = ftvalid; |
|
218 |
|
219 FT_TRACE3(( "validating JSTF table\n" )); |
|
220 OTV_INIT; |
|
221 |
|
222 OTV_LIMIT_CHECK( 6 ); |
|
223 |
|
224 if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ |
|
225 FT_INVALID_FORMAT; |
|
226 |
|
227 JstfScriptCount = FT_NEXT_USHORT( p ); |
|
228 |
|
229 FT_TRACE3(( " (JstfScriptCount = %d)\n", JstfScriptCount )); |
|
230 |
|
231 OTV_LIMIT_CHECK( JstfScriptCount * 6 ); |
|
232 |
|
233 if ( gsub ) |
|
234 valid->extra1 = otv_GSUBGPOS_get_Lookup_count( gsub ); |
|
235 else |
|
236 valid->extra1 = 0; |
|
237 |
|
238 if ( gpos ) |
|
239 valid->extra2 = otv_GSUBGPOS_get_Lookup_count( gpos ); |
|
240 else |
|
241 valid->extra2 = 0; |
|
242 |
|
243 valid->glyph_count = glyph_count; |
|
244 |
|
245 /* JstfScriptRecord */ |
|
246 for ( ; JstfScriptCount > 0; JstfScriptCount-- ) |
|
247 { |
|
248 p += 4; /* skip JstfScriptTag */ |
|
249 |
|
250 /* JstfScript */ |
|
251 otv_JstfScript_validate( table + FT_NEXT_USHORT( p ), valid ); |
|
252 } |
|
253 |
|
254 FT_TRACE4(( "\n" )); |
|
255 } |
|
256 |
|
257 |
|
258 /* END */ |