1 | /**************************************************************************** |
2 | * |
3 | * gxvbsln.c |
4 | * |
5 | * TrueTypeGX/AAT bsln table validation (body). |
6 | * |
7 | * Copyright (C) 2004-2023 by |
8 | * suzuki toshiya, Masatake YAMATO, Red Hat K.K., |
9 | * David Turner, Robert Wilhelm, and Werner Lemberg. |
10 | * |
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. |
16 | * |
17 | */ |
18 | |
19 | /**************************************************************************** |
20 | * |
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. |
24 | * |
25 | */ |
26 | |
27 | |
28 | #include "gxvalid.h" |
29 | #include "gxvcommn.h" |
30 | |
31 | |
32 | /************************************************************************** |
33 | * |
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. |
37 | */ |
38 | #undef FT_COMPONENT |
39 | #define FT_COMPONENT gxvbsln |
40 | |
41 | |
42 | /*************************************************************************/ |
43 | /*************************************************************************/ |
44 | /***** *****/ |
45 | /***** Data and Types *****/ |
46 | /***** *****/ |
47 | /*************************************************************************/ |
48 | /*************************************************************************/ |
49 | |
50 | #define GXV_BSLN_VALUE_COUNT 32 |
51 | #define GXV_BSLN_VALUE_EMPTY 0xFFFFU |
52 | |
53 | |
54 | typedef struct GXV_bsln_DataRec_ |
55 | { |
56 | FT_Bytes ctlPoints_p; |
57 | FT_UShort defaultBaseline; |
58 | |
59 | } GXV_bsln_DataRec, *GXV_bsln_Data; |
60 | |
61 | |
62 | #define GXV_BSLN_DATA( field ) GXV_TABLE_DATA( bsln, field ) |
63 | |
64 | |
65 | /*************************************************************************/ |
66 | /*************************************************************************/ |
67 | /***** *****/ |
68 | /***** UTILITY FUNCTIONS *****/ |
69 | /***** *****/ |
70 | /*************************************************************************/ |
71 | /*************************************************************************/ |
72 | |
73 | static void |
74 | gxv_bsln_LookupValue_validate( FT_UShort glyph, |
75 | GXV_LookupValueCPtr value_p, |
76 | GXV_Validator gxvalid ) |
77 | { |
78 | FT_UShort v = value_p->u; |
79 | FT_UShort* ctlPoints; |
80 | |
81 | FT_UNUSED( glyph ); |
82 | |
83 | |
84 | GXV_NAME_ENTER( "lookup value" ); |
85 | |
86 | if ( v >= GXV_BSLN_VALUE_COUNT ) |
87 | FT_INVALID_DATA; |
88 | |
89 | ctlPoints = (FT_UShort*)GXV_BSLN_DATA( ctlPoints_p ); |
90 | if ( ctlPoints && ctlPoints[v] == GXV_BSLN_VALUE_EMPTY ) |
91 | FT_INVALID_DATA; |
92 | |
93 | GXV_EXIT; |
94 | } |
95 | |
96 | |
97 | /* |
98 | +===============+ --------+ |
99 | | lookup header | | |
100 | +===============+ | |
101 | | BinSrchHeader | | |
102 | +===============+ | |
103 | | lastGlyph[0] | | |
104 | +---------------+ | |
105 | | firstGlyph[0] | | head of lookup table |
106 | +---------------+ | + |
107 | | offset[0] | -> | offset [byte] |
108 | +===============+ | + |
109 | | lastGlyph[1] | | (glyphID - firstGlyph) * 2 [byte] |
110 | +---------------+ | |
111 | | firstGlyph[1] | | |
112 | +---------------+ | |
113 | | offset[1] | | |
114 | +===============+ | |
115 | | |
116 | ... | |
117 | | |
118 | 16bit value array | |
119 | +===============+ | |
120 | | value | <-------+ |
121 | ... |
122 | */ |
123 | |
124 | static GXV_LookupValueDesc |
125 | gxv_bsln_LookupFmt4_transit( FT_UShort relative_gindex, |
126 | GXV_LookupValueCPtr base_value_p, |
127 | FT_Bytes lookuptbl_limit, |
128 | GXV_Validator gxvalid ) |
129 | { |
130 | FT_Bytes p; |
131 | FT_Bytes limit; |
132 | FT_UShort offset; |
133 | GXV_LookupValueDesc value; |
134 | |
135 | /* XXX: check range ? */ |
136 | offset = (FT_UShort)( base_value_p->u + |
137 | ( relative_gindex * sizeof ( FT_UShort ) ) ); |
138 | |
139 | p = gxvalid->lookuptbl_head + offset; |
140 | limit = lookuptbl_limit; |
141 | GXV_LIMIT_CHECK( 2 ); |
142 | |
143 | value.u = FT_NEXT_USHORT( p ); |
144 | |
145 | return value; |
146 | } |
147 | |
148 | |
149 | static void |
150 | gxv_bsln_parts_fmt0_validate( FT_Bytes tables, |
151 | FT_Bytes limit, |
152 | GXV_Validator gxvalid ) |
153 | { |
154 | FT_Bytes p = tables; |
155 | |
156 | |
157 | GXV_NAME_ENTER( "parts format 0" ); |
158 | |
159 | /* deltas */ |
160 | GXV_LIMIT_CHECK( 2 * GXV_BSLN_VALUE_COUNT ); |
161 | |
162 | gxvalid->table_data = NULL; /* No ctlPoints here. */ |
163 | |
164 | GXV_EXIT; |
165 | } |
166 | |
167 | |
168 | static void |
169 | gxv_bsln_parts_fmt1_validate( FT_Bytes tables, |
170 | FT_Bytes limit, |
171 | GXV_Validator gxvalid ) |
172 | { |
173 | FT_Bytes p = tables; |
174 | |
175 | |
176 | GXV_NAME_ENTER( "parts format 1" ); |
177 | |
178 | /* deltas */ |
179 | gxv_bsln_parts_fmt0_validate( p, limit, gxvalid ); |
180 | |
181 | /* mappingData */ |
182 | gxvalid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED; |
183 | gxvalid->lookupval_func = gxv_bsln_LookupValue_validate; |
184 | gxvalid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit; |
185 | gxv_LookupTable_validate( p + 2 * GXV_BSLN_VALUE_COUNT, |
186 | limit, |
187 | gxvalid ); |
188 | |
189 | GXV_EXIT; |
190 | } |
191 | |
192 | |
193 | static void |
194 | gxv_bsln_parts_fmt2_validate( FT_Bytes tables, |
195 | FT_Bytes limit, |
196 | GXV_Validator gxvalid ) |
197 | { |
198 | FT_Bytes p = tables; |
199 | |
200 | FT_UShort stdGlyph; |
201 | FT_UShort ctlPoint; |
202 | FT_Int i; |
203 | |
204 | FT_UShort defaultBaseline = GXV_BSLN_DATA( defaultBaseline ); |
205 | |
206 | |
207 | GXV_NAME_ENTER( "parts format 2" ); |
208 | |
209 | GXV_LIMIT_CHECK( 2 + ( 2 * GXV_BSLN_VALUE_COUNT ) ); |
210 | |
211 | /* stdGlyph */ |
212 | stdGlyph = FT_NEXT_USHORT( p ); |
213 | GXV_TRACE(( " (stdGlyph = %u)\n" , stdGlyph )); |
214 | |
215 | gxv_glyphid_validate( stdGlyph, gxvalid ); |
216 | |
217 | /* Record the position of ctlPoints */ |
218 | GXV_BSLN_DATA( ctlPoints_p ) = p; |
219 | |
220 | /* ctlPoints */ |
221 | for ( i = 0; i < GXV_BSLN_VALUE_COUNT; i++ ) |
222 | { |
223 | ctlPoint = FT_NEXT_USHORT( p ); |
224 | if ( ctlPoint == GXV_BSLN_VALUE_EMPTY ) |
225 | { |
226 | if ( i == defaultBaseline ) |
227 | FT_INVALID_DATA; |
228 | } |
229 | else |
230 | gxv_ctlPoint_validate( stdGlyph, ctlPoint, gxvalid ); |
231 | } |
232 | |
233 | GXV_EXIT; |
234 | } |
235 | |
236 | |
237 | static void |
238 | gxv_bsln_parts_fmt3_validate( FT_Bytes tables, |
239 | FT_Bytes limit, |
240 | GXV_Validator gxvalid) |
241 | { |
242 | FT_Bytes p = tables; |
243 | |
244 | |
245 | GXV_NAME_ENTER( "parts format 3" ); |
246 | |
247 | /* stdGlyph + ctlPoints */ |
248 | gxv_bsln_parts_fmt2_validate( p, limit, gxvalid ); |
249 | |
250 | /* mappingData */ |
251 | gxvalid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED; |
252 | gxvalid->lookupval_func = gxv_bsln_LookupValue_validate; |
253 | gxvalid->lookupfmt4_trans = gxv_bsln_LookupFmt4_transit; |
254 | gxv_LookupTable_validate( p + ( 2 + 2 * GXV_BSLN_VALUE_COUNT ), |
255 | limit, |
256 | gxvalid ); |
257 | |
258 | GXV_EXIT; |
259 | } |
260 | |
261 | |
262 | /*************************************************************************/ |
263 | /*************************************************************************/ |
264 | /***** *****/ |
265 | /***** bsln TABLE *****/ |
266 | /***** *****/ |
267 | /*************************************************************************/ |
268 | /*************************************************************************/ |
269 | |
270 | FT_LOCAL_DEF( void ) |
271 | gxv_bsln_validate( FT_Bytes table, |
272 | FT_Face face, |
273 | FT_Validator ftvalid ) |
274 | { |
275 | GXV_ValidatorRec gxvalidrec; |
276 | GXV_Validator gxvalid = &gxvalidrec; |
277 | |
278 | GXV_bsln_DataRec bslnrec; |
279 | GXV_bsln_Data bsln = &bslnrec; |
280 | |
281 | FT_Bytes p = table; |
282 | FT_Bytes limit = 0; |
283 | |
284 | FT_ULong version; |
285 | FT_UShort format; |
286 | FT_UShort defaultBaseline; |
287 | |
288 | GXV_Validate_Func fmt_funcs_table [] = |
289 | { |
290 | gxv_bsln_parts_fmt0_validate, |
291 | gxv_bsln_parts_fmt1_validate, |
292 | gxv_bsln_parts_fmt2_validate, |
293 | gxv_bsln_parts_fmt3_validate, |
294 | }; |
295 | |
296 | |
297 | gxvalid->root = ftvalid; |
298 | gxvalid->table_data = bsln; |
299 | gxvalid->face = face; |
300 | |
301 | FT_TRACE3(( "validating `bsln' table\n" )); |
302 | GXV_INIT; |
303 | |
304 | |
305 | GXV_LIMIT_CHECK( 4 + 2 + 2 ); |
306 | version = FT_NEXT_ULONG( p ); |
307 | format = FT_NEXT_USHORT( p ); |
308 | defaultBaseline = FT_NEXT_USHORT( p ); |
309 | |
310 | /* only version 1.0 is defined (1996) */ |
311 | if ( version != 0x00010000UL ) |
312 | FT_INVALID_FORMAT; |
313 | |
314 | /* only format 1, 2, 3 are defined (1996) */ |
315 | GXV_TRACE(( " (format = %d)\n" , format )); |
316 | if ( format > 3 ) |
317 | FT_INVALID_FORMAT; |
318 | |
319 | if ( defaultBaseline > 31 ) |
320 | FT_INVALID_FORMAT; |
321 | |
322 | bsln->defaultBaseline = defaultBaseline; |
323 | |
324 | fmt_funcs_table[format]( p, limit, gxvalid ); |
325 | |
326 | FT_TRACE4(( "\n" )); |
327 | } |
328 | |
329 | |
330 | /* arch-tag: ebe81143-fdaa-4c68-a4d1-b57227daa3bc |
331 | (do not change this comment) */ |
332 | |
333 | |
334 | /* END */ |
335 | |