Sync with trunk r47367
[reactos.git] / lib / 3rdparty / freetype / src / otvalid / otvgsub.c
1 /***************************************************************************/
2 /* */
3 /* otvgsub.c */
4 /* */
5 /* OpenType GSUB table validation (body). */
6 /* */
7 /* Copyright 2004, 2005, 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
22
23 /*************************************************************************/
24 /* */
25 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
26 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
27 /* messages during execution. */
28 /* */
29 #undef FT_COMPONENT
30 #define FT_COMPONENT trace_otvgsub
31
32
33 /*************************************************************************/
34 /*************************************************************************/
35 /***** *****/
36 /***** GSUB LOOKUP TYPE 1 *****/
37 /***** *****/
38 /*************************************************************************/
39 /*************************************************************************/
40
41 /* uses valid->glyph_count */
42
43 static void
44 otv_SingleSubst_validate( FT_Bytes table,
45 OTV_Validator valid )
46 {
47 FT_Bytes p = table;
48 FT_UInt SubstFormat;
49
50
51 OTV_NAME_ENTER( "SingleSubst" );
52
53 OTV_LIMIT_CHECK( 2 );
54 SubstFormat = FT_NEXT_USHORT( p );
55
56 OTV_TRACE(( " (format %d)\n", SubstFormat ));
57
58 switch ( SubstFormat )
59 {
60 case 1: /* SingleSubstFormat1 */
61 {
62 FT_Bytes Coverage;
63 FT_Int DeltaGlyphID;
64 FT_Long idx;
65
66
67 OTV_LIMIT_CHECK( 4 );
68 Coverage = table + FT_NEXT_USHORT( p );
69 DeltaGlyphID = FT_NEXT_SHORT( p );
70
71 otv_Coverage_validate( Coverage, valid, -1 );
72
73 idx = otv_Coverage_get_first( Coverage ) + DeltaGlyphID;
74 if ( idx < 0 )
75 FT_INVALID_DATA;
76
77 idx = otv_Coverage_get_last( Coverage ) + DeltaGlyphID;
78 if ( (FT_UInt)idx >= valid->glyph_count )
79 FT_INVALID_DATA;
80 }
81 break;
82
83 case 2: /* SingleSubstFormat2 */
84 {
85 FT_UInt Coverage, GlyphCount;
86
87
88 OTV_LIMIT_CHECK( 4 );
89 Coverage = FT_NEXT_USHORT( p );
90 GlyphCount = FT_NEXT_USHORT( p );
91
92 OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
93
94 otv_Coverage_validate( table + Coverage, valid, GlyphCount );
95
96 OTV_LIMIT_CHECK( GlyphCount * 2 );
97
98 /* Substitute */
99 for ( ; GlyphCount > 0; GlyphCount-- )
100 if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
101 FT_INVALID_GLYPH_ID;
102 }
103 break;
104
105 default:
106 FT_INVALID_FORMAT;
107 }
108
109 OTV_EXIT;
110 }
111
112
113 /*************************************************************************/
114 /*************************************************************************/
115 /***** *****/
116 /***** GSUB LOOKUP TYPE 2 *****/
117 /***** *****/
118 /*************************************************************************/
119 /*************************************************************************/
120
121 /* sets valid->extra1 (glyph count) */
122
123 static void
124 otv_MultipleSubst_validate( FT_Bytes table,
125 OTV_Validator valid )
126 {
127 FT_Bytes p = table;
128 FT_UInt SubstFormat;
129
130
131 OTV_NAME_ENTER( "MultipleSubst" );
132
133 OTV_LIMIT_CHECK( 2 );
134 SubstFormat = FT_NEXT_USHORT( p );
135
136 OTV_TRACE(( " (format %d)\n", SubstFormat ));
137
138 switch ( SubstFormat )
139 {
140 case 1:
141 valid->extra1 = valid->glyph_count;
142 OTV_NEST2( MultipleSubstFormat1, Sequence );
143 OTV_RUN( table, valid );
144 break;
145
146 default:
147 FT_INVALID_FORMAT;
148 }
149
150 OTV_EXIT;
151 }
152
153
154 /*************************************************************************/
155 /*************************************************************************/
156 /***** *****/
157 /***** GSUB LOOKUP TYPE 3 *****/
158 /***** *****/
159 /*************************************************************************/
160 /*************************************************************************/
161
162 /* sets valid->extra1 (glyph count) */
163
164 static void
165 otv_AlternateSubst_validate( FT_Bytes table,
166 OTV_Validator valid )
167 {
168 FT_Bytes p = table;
169 FT_UInt SubstFormat;
170
171
172 OTV_NAME_ENTER( "AlternateSubst" );
173
174 OTV_LIMIT_CHECK( 2 );
175 SubstFormat = FT_NEXT_USHORT( p );
176
177 OTV_TRACE(( " (format %d)\n", SubstFormat ));
178
179 switch ( SubstFormat )
180 {
181 case 1:
182 valid->extra1 = valid->glyph_count;
183 OTV_NEST2( AlternateSubstFormat1, AlternateSet );
184 OTV_RUN( table, valid );
185 break;
186
187 default:
188 FT_INVALID_FORMAT;
189 }
190
191 OTV_EXIT;
192 }
193
194
195 /*************************************************************************/
196 /*************************************************************************/
197 /***** *****/
198 /***** GSUB LOOKUP TYPE 4 *****/
199 /***** *****/
200 /*************************************************************************/
201 /*************************************************************************/
202
203 #define LigatureFunc otv_Ligature_validate
204
205 /* uses valid->glyph_count */
206
207 static void
208 otv_Ligature_validate( FT_Bytes table,
209 OTV_Validator valid )
210 {
211 FT_Bytes p = table;
212 FT_UInt LigatureGlyph, CompCount;
213
214
215 OTV_ENTER;
216
217 OTV_LIMIT_CHECK( 4 );
218 LigatureGlyph = FT_NEXT_USHORT( p );
219 if ( LigatureGlyph >= valid->glyph_count )
220 FT_INVALID_DATA;
221
222 CompCount = FT_NEXT_USHORT( p );
223
224 OTV_TRACE(( " (CompCount = %d)\n", CompCount ));
225
226 if ( CompCount == 0 )
227 FT_INVALID_DATA;
228
229 CompCount--;
230
231 OTV_LIMIT_CHECK( CompCount * 2 ); /* Component */
232
233 /* no need to check the Component glyph indices */
234
235 OTV_EXIT;
236 }
237
238
239 static void
240 otv_LigatureSubst_validate( FT_Bytes table,
241 OTV_Validator valid )
242 {
243 FT_Bytes p = table;
244 FT_UInt SubstFormat;
245
246
247 OTV_NAME_ENTER( "LigatureSubst" );
248
249 OTV_LIMIT_CHECK( 2 );
250 SubstFormat = FT_NEXT_USHORT( p );
251
252 OTV_TRACE(( " (format %d)\n", SubstFormat ));
253
254 switch ( SubstFormat )
255 {
256 case 1:
257 OTV_NEST3( LigatureSubstFormat1, LigatureSet, Ligature );
258 OTV_RUN( table, valid );
259 break;
260
261 default:
262 FT_INVALID_FORMAT;
263 }
264
265 OTV_EXIT;
266 }
267
268
269 /*************************************************************************/
270 /*************************************************************************/
271 /***** *****/
272 /***** GSUB LOOKUP TYPE 5 *****/
273 /***** *****/
274 /*************************************************************************/
275 /*************************************************************************/
276
277 /* sets valid->extra1 (lookup count) */
278
279 static void
280 otv_ContextSubst_validate( FT_Bytes table,
281 OTV_Validator valid )
282 {
283 FT_Bytes p = table;
284 FT_UInt SubstFormat;
285
286
287 OTV_NAME_ENTER( "ContextSubst" );
288
289 OTV_LIMIT_CHECK( 2 );
290 SubstFormat = FT_NEXT_USHORT( p );
291
292 OTV_TRACE(( " (format %d)\n", SubstFormat ));
293
294 switch ( SubstFormat )
295 {
296 case 1:
297 /* no need to check glyph indices/classes used as input for these */
298 /* context rules since even invalid glyph indices/classes return */
299 /* meaningful results */
300
301 valid->extra1 = valid->lookup_count;
302 OTV_NEST3( ContextSubstFormat1, SubRuleSet, SubRule );
303 OTV_RUN( table, valid );
304 break;
305
306 case 2:
307 /* no need to check glyph indices/classes used as input for these */
308 /* context rules since even invalid glyph indices/classes return */
309 /* meaningful results */
310
311 OTV_NEST3( ContextSubstFormat2, SubClassSet, SubClassRule );
312 OTV_RUN( table, valid );
313 break;
314
315 case 3:
316 OTV_NEST1( ContextSubstFormat3 );
317 OTV_RUN( table, valid );
318 break;
319
320 default:
321 FT_INVALID_FORMAT;
322 }
323
324 OTV_EXIT;
325 }
326
327
328 /*************************************************************************/
329 /*************************************************************************/
330 /***** *****/
331 /***** GSUB LOOKUP TYPE 6 *****/
332 /***** *****/
333 /*************************************************************************/
334 /*************************************************************************/
335
336 /* sets valid->extra1 (lookup count) */
337
338 static void
339 otv_ChainContextSubst_validate( FT_Bytes table,
340 OTV_Validator valid )
341 {
342 FT_Bytes p = table;
343 FT_UInt SubstFormat;
344
345
346 OTV_NAME_ENTER( "ChainContextSubst" );
347
348 OTV_LIMIT_CHECK( 2 );
349 SubstFormat = FT_NEXT_USHORT( p );
350
351 OTV_TRACE(( " (format %d)\n", SubstFormat ));
352
353 switch ( SubstFormat )
354 {
355 case 1:
356 /* no need to check glyph indices/classes used as input for these */
357 /* context rules since even invalid glyph indices/classes return */
358 /* meaningful results */
359
360 valid->extra1 = valid->lookup_count;
361 OTV_NEST3( ChainContextSubstFormat1,
362 ChainSubRuleSet, ChainSubRule );
363 OTV_RUN( table, valid );
364 break;
365
366 case 2:
367 /* no need to check glyph indices/classes used as input for these */
368 /* context rules since even invalid glyph indices/classes return */
369 /* meaningful results */
370
371 OTV_NEST3( ChainContextSubstFormat2,
372 ChainSubClassSet, ChainSubClassRule );
373 OTV_RUN( table, valid );
374 break;
375
376 case 3:
377 OTV_NEST1( ChainContextSubstFormat3 );
378 OTV_RUN( table, valid );
379 break;
380
381 default:
382 FT_INVALID_FORMAT;
383 }
384
385 OTV_EXIT;
386 }
387
388
389 /*************************************************************************/
390 /*************************************************************************/
391 /***** *****/
392 /***** GSUB LOOKUP TYPE 7 *****/
393 /***** *****/
394 /*************************************************************************/
395 /*************************************************************************/
396
397 /* uses valid->type_funcs */
398
399 static void
400 otv_ExtensionSubst_validate( FT_Bytes table,
401 OTV_Validator valid )
402 {
403 FT_Bytes p = table;
404 FT_UInt SubstFormat;
405
406
407 OTV_NAME_ENTER( "ExtensionSubst" );
408
409 OTV_LIMIT_CHECK( 2 );
410 SubstFormat = FT_NEXT_USHORT( p );
411
412 OTV_TRACE(( " (format %d)\n", SubstFormat ));
413
414 switch ( SubstFormat )
415 {
416 case 1: /* ExtensionSubstFormat1 */
417 {
418 FT_UInt ExtensionLookupType;
419 FT_ULong ExtensionOffset;
420 OTV_Validate_Func validate;
421
422
423 OTV_LIMIT_CHECK( 6 );
424 ExtensionLookupType = FT_NEXT_USHORT( p );
425 ExtensionOffset = FT_NEXT_ULONG( p );
426
427 if ( ExtensionLookupType == 0 ||
428 ExtensionLookupType == 7 ||
429 ExtensionLookupType > 8 )
430 FT_INVALID_DATA;
431
432 validate = valid->type_funcs[ExtensionLookupType - 1];
433 validate( table + ExtensionOffset, valid );
434 }
435 break;
436
437 default:
438 FT_INVALID_FORMAT;
439 }
440
441 OTV_EXIT;
442 }
443
444
445 /*************************************************************************/
446 /*************************************************************************/
447 /***** *****/
448 /***** GSUB LOOKUP TYPE 8 *****/
449 /***** *****/
450 /*************************************************************************/
451 /*************************************************************************/
452
453 /* uses valid->glyph_count */
454
455 static void
456 otv_ReverseChainSingleSubst_validate( FT_Bytes table,
457 OTV_Validator valid )
458 {
459 FT_Bytes p = table, Coverage;
460 FT_UInt SubstFormat;
461 FT_UInt BacktrackGlyphCount, LookaheadGlyphCount, GlyphCount;
462
463
464 OTV_NAME_ENTER( "ReverseChainSingleSubst" );
465
466 OTV_LIMIT_CHECK( 2 );
467 SubstFormat = FT_NEXT_USHORT( p );
468
469 OTV_TRACE(( " (format %d)\n", SubstFormat ));
470
471 switch ( SubstFormat )
472 {
473 case 1: /* ReverseChainSingleSubstFormat1 */
474 OTV_LIMIT_CHECK( 4 );
475 Coverage = table + FT_NEXT_USHORT( p );
476 BacktrackGlyphCount = FT_NEXT_USHORT( p );
477
478 OTV_TRACE(( " (BacktrackGlyphCount = %d)\n", BacktrackGlyphCount ));
479
480 otv_Coverage_validate( Coverage, valid, -1 );
481
482 OTV_LIMIT_CHECK( BacktrackGlyphCount * 2 + 2 );
483
484 for ( ; BacktrackGlyphCount > 0; BacktrackGlyphCount-- )
485 otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
486
487 LookaheadGlyphCount = FT_NEXT_USHORT( p );
488
489 OTV_TRACE(( " (LookaheadGlyphCount = %d)\n", LookaheadGlyphCount ));
490
491 OTV_LIMIT_CHECK( LookaheadGlyphCount * 2 + 2 );
492
493 for ( ; LookaheadGlyphCount > 0; LookaheadGlyphCount-- )
494 otv_Coverage_validate( table + FT_NEXT_USHORT( p ), valid, -1 );
495
496 GlyphCount = FT_NEXT_USHORT( p );
497
498 OTV_TRACE(( " (GlyphCount = %d)\n", GlyphCount ));
499
500 if ( GlyphCount != otv_Coverage_get_count( Coverage ) )
501 FT_INVALID_DATA;
502
503 OTV_LIMIT_CHECK( GlyphCount * 2 );
504
505 /* Substitute */
506 for ( ; GlyphCount > 0; GlyphCount-- )
507 if ( FT_NEXT_USHORT( p ) >= valid->glyph_count )
508 FT_INVALID_DATA;
509
510 break;
511
512 default:
513 FT_INVALID_FORMAT;
514 }
515
516 OTV_EXIT;
517 }
518
519
520 static const OTV_Validate_Func otv_gsub_validate_funcs[8] =
521 {
522 otv_SingleSubst_validate,
523 otv_MultipleSubst_validate,
524 otv_AlternateSubst_validate,
525 otv_LigatureSubst_validate,
526 otv_ContextSubst_validate,
527 otv_ChainContextSubst_validate,
528 otv_ExtensionSubst_validate,
529 otv_ReverseChainSingleSubst_validate
530 };
531
532
533 /*************************************************************************/
534 /*************************************************************************/
535 /***** *****/
536 /***** GSUB TABLE *****/
537 /***** *****/
538 /*************************************************************************/
539 /*************************************************************************/
540
541 /* sets valid->type_count */
542 /* sets valid->type_funcs */
543 /* sets valid->glyph_count */
544
545 FT_LOCAL_DEF( void )
546 otv_GSUB_validate( FT_Bytes table,
547 FT_UInt glyph_count,
548 FT_Validator ftvalid )
549 {
550 OTV_ValidatorRec validrec;
551 OTV_Validator valid = &validrec;
552 FT_Bytes p = table;
553 FT_UInt ScriptList, FeatureList, LookupList;
554
555
556 valid->root = ftvalid;
557
558 FT_TRACE3(( "validating GSUB table\n" ));
559 OTV_INIT;
560
561 OTV_LIMIT_CHECK( 10 );
562
563 if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */
564 FT_INVALID_FORMAT;
565
566 ScriptList = FT_NEXT_USHORT( p );
567 FeatureList = FT_NEXT_USHORT( p );
568 LookupList = FT_NEXT_USHORT( p );
569
570 valid->type_count = 8;
571 valid->type_funcs = (OTV_Validate_Func*)otv_gsub_validate_funcs;
572 valid->glyph_count = glyph_count;
573
574 otv_LookupList_validate( table + LookupList,
575 valid );
576 otv_FeatureList_validate( table + FeatureList, table + LookupList,
577 valid );
578 otv_ScriptList_validate( table + ScriptList, table + FeatureList,
579 valid );
580
581 FT_TRACE4(( "\n" ));
582 }
583
584
585 /* END */