update for HEAD-2003050101
[reactos.git] / lib / freetype / src / otlayout / otlgpos.c
1 #include "otlgpos.h"
2 #include "otlcommn.h"
3
4  /* forward declaration */
5   static OTL_ValidateFunc  otl_gpos_validate_funcs[];
6
7
8  /************************************************************************/
9  /************************************************************************/
10  /*****                                                              *****/
11  /*****                         VALUE RECORDS                        *****/
12  /*****                                                              *****/
13  /************************************************************************/
14  /************************************************************************/
15
16   static OTL_UInt
17   otl_value_length( OTL_UInt  format )
18   {
19     FT_UInt  count;
20
21     count = (( format & 0xAA ) >> 1) + ( format & 0x55 );
22     count = (( count  & 0xCC ) >> 2) + ( count  & 0x33 );
23     count = (( count  & 0xF0 ) >> 4) + ( count  & 0x0F );
24
25     return count;
26   }
27
28
29   static void
30   otl_value_validate( OTL_Bytes      table,
31                       OTL_Bytes      pos_table,
32                       OTL_UInt       format,
33                       OTL_Validator  valid )
34   {
35     OTL_Bytes  p = table;
36     OTL_UInt   count, device;
37
38     if ( format >= 0x100U )
39       OTL_INVALID_DATA;
40
41     for ( count = 4; count > 0; count-- )
42     {
43       if ( format & 1 )
44       {
45         OTL_CHECK( 2 );
46         p += 2;
47       }
48
49       format >>= 1;
50     }
51
52     for ( count = 4; count > 0; count-- )
53     {
54       if ( format & 1 )
55       {
56         OTL_CHECK( 2 );
57         device = OTL_NEXT_USHORT( p );
58         if ( device )
59           otl_device_table_validate( pos_table + device, valid );
60       }
61       format >>= 1;
62     }
63   }
64
65
66  /************************************************************************/
67  /************************************************************************/
68  /*****                                                              *****/
69  /*****                          ANCHORS                             *****/
70  /*****                                                              *****/
71  /************************************************************************/
72  /************************************************************************/
73
74   static void
75   otl_anchor_validate( OTL_Bytes      table,
76                        OTL_Validator  valid )
77   {
78     OTL_Bytes  p = table;
79     OTL_UInt   format;
80
81     OTL_CHECK( 6 );
82     format = OTL_NEXT_USHORT( p );
83     p += 4;
84
85     switch ( format )
86     {
87       case 1:
88         break;
89
90       case 2:
91         OTL_CHECK( 2 );  /* anchor point */
92         break;
93
94       case 3:
95         {
96           OTL_UInt  x_device, y_device;
97
98           OTL_CHECK( 4 );
99           x_device = OTL_NEXT_USHORT( p );
100           y_device = OTL_NEXT_USHORT( p );
101
102           if ( x_device )
103             otl_device_table_validate( table + x_device, valid );
104
105           if ( y_device )
106             otl_device_table_validate( table + y_device, valid );
107         }
108         break;
109
110       default:
111         OTL_INVALID_DATA;
112     }
113   }
114
115
116  /************************************************************************/
117  /************************************************************************/
118  /*****                                                              *****/
119  /*****                           MARK ARRAY                         *****/
120  /*****                                                              *****/
121  /************************************************************************/
122  /************************************************************************/
123
124   static void
125   otl_mark_array_validate( OTL_Bytes      table,
126                            OTL_Validator  valid )
127   {
128     OTL_Bytes  p = table;
129     OTL_UInt   count;
130
131     OTL_CHECK( 2 );
132
133     count = OTL_NEXT_USHORT( p );
134     OTL_CHECK( count * 4 );
135     for ( ; count > 0; count-- )
136     {
137       p += 2;  /* ignore class index */
138       otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid );
139     }
140   }
141
142
143  /************************************************************************/
144  /************************************************************************/
145  /*****                                                              *****/
146  /*****                 GPOS LOOKUP TYPE 1                           *****/
147  /*****                                                              *****/
148  /************************************************************************/
149  /************************************************************************/
150
151   static void
152   otl_gpos_lookup1_validate( OTL_Bytes      table,
153                              OTL_Validator  valid )
154   {
155     OTL_Bytes  p = table;
156     OTL_UInt   format;
157
158     OTL_CHECK( 2 );
159     format = OTL_NEXT_USHORT( p );
160     switch ( format )
161     {
162       case 1:
163         {
164           FT_UInt  coverage, value_format;
165
166           OTL_CHECK( 4 );
167           coverage     = OTL_NEXT_USHORT( p );
168           value_format = OTL_NEXT_USHORT( p );
169
170           otl_coverage_validate( table + coverage, valid );
171           otl_value_validate( p, table, value_format, valid );
172         }
173         break;
174
175       case 2:
176         {
177           FT_UInt  coverage, value_format, count, len;
178
179           OTL_CHECK( 6 );
180           coverage     = OTL_NEXT_USHORT( p );
181           value_format = OTL_NEXT_USHORT( p );
182           count        = OTL_NEXT_USHORT( p );
183           len          = otl_value_length( value_format );
184
185           otl_coverage_validate( table + coverage, valid );
186
187           OTL_CHECK( count * len );
188           for ( ; count > 0; count-- )
189           {
190             otl_value_validate( p, table, value_format, valid );
191             p += len;
192           }
193         }
194         break;
195
196       default:
197         OTL_INVALID_DATA;
198     }
199   }
200
201
202  /************************************************************************/
203  /************************************************************************/
204  /*****                                                              *****/
205  /*****                 GPOS LOOKUP TYPE 2                           *****/
206  /*****                                                              *****/
207  /************************************************************************/
208  /************************************************************************/
209
210   static otl_gpos_pairset_validate( OTL_Bytes      table,
211                                     OTL_Bytes      pos_table,
212                                     OTL_UInt       format1,
213                                     OTL_UInt       format2,
214                                     OTL_Validator  valid )
215   {
216     OTL_Bytes  p = table;
217     OTL_UInt   len1, len2, count;
218
219     OTL_CHECK( 2 );
220     count = OTL_NEXT_USHORT( p );
221     len1  = otl_value_length( format1 );
222     len2  = otl_value_length( format2 );
223
224     OTL_CHECK( count * (len1+len2+2) );
225     for ( ; count > 0; count-- )
226     {
227       p += 2;  /* ignore glyph id */
228       otl_value_validate( p, pos_table, format1, valid );
229       p += len1;
230
231       otl_value_validate( p, pos_table, format2, valid );
232       p += len2;
233     }
234   }
235
236   static void
237   otl_gpos_lookup2_validate( OTL_Bytes      table,
238                              OTL_Validator  valid )
239   {
240     OTL_Bytes  p = table;
241     OTL_UInt   format;
242
243     OTL_CHECK( 2 );
244     format = OTL_NEXT_USHORT( p );
245     switch (format)
246     {
247       case 1:
248         {
249           OTL_UInt  coverage, value1, value2, count;
250
251           OTL_CHECK( 8 );
252           coverage = OTL_NEXT_USHORT( p );
253           value1   = OTL_NEXT_USHORT( p );
254           value2   = OTL_NEXT_USHORT( p );
255           count    = OTL_NEXT_USHORT( p );
256
257           otl_coverage_validate( table + coverage, valid );
258
259           OTL_CHECK( count*2 );
260           for ( ; count > 0; count-- )
261           {
262             otl_gpos_pairset_validate( table + OTL_NEXT_USHORT( p ),
263                                        table, value1, value2, valid );
264           }
265         }
266         break;
267
268       case 2:
269         {
270           OTL_UInt  coverage, value1, value2, class1, class2, count1, count2;
271           OTL_UInt  len1, len2;
272
273           OTL_CHECK( 14 );
274           coverage = OTL_NEXT_USHORT( p );
275           value1   = OTL_NEXT_USHORT( p );
276           value2   = OTL_NEXT_USHORT( p );
277           class1   = OTL_NEXT_USHORT( p );
278           class2   = OTL_NEXT_USHORT( p );
279           count1   = OTL_NEXT_USHORT( p );
280           count2   = OTL_NEXT_USHORT( p );
281
282           len1 = otl_value_length( value1 );
283           len2 = otl_value_length( value2 );
284
285           otl_coverage_validate( table + coverage, valid );
286
287           OTL_CHECK( count1*count2*(len1+len2) );
288           for ( ; count1 > 0; count1-- )
289           {
290             for ( ; count2 > 0; count2-- )
291             {
292               otl_value_validate( p, table, value1, valid );
293               p += len1;
294
295               otl_value_validate( p, table, value2, valid );
296               p += len2;
297             }
298           }
299         }
300         break;
301
302       default:
303         OTL_INVALID_DATA;
304     }
305   }
306
307
308  /************************************************************************/
309  /************************************************************************/
310  /*****                                                              *****/
311  /*****                 GPOS LOOKUP TYPE 3                           *****/
312  /*****                                                              *****/
313  /************************************************************************/
314  /************************************************************************/
315
316   static void
317   otl_gpos_lookup3_validate( OTL_Bytes  table,
318                              OTL_Valid  valid )
319   {
320     OTL_Bytes  p = table;
321     OTL_UInt   format;
322
323     OTL_CHECK( 2 );
324     format = OTL_NEXT_USHORT( p );
325     switch (format)
326     {
327       case 1:
328         {
329           OTL_UInt  coverage, count, anchor1, anchor2;
330
331           OTL_CHECK( 4 );
332           coverage = OTL_NEXT_USHORT( p );
333           count    = OTL_NEXT_USHORT( p );
334
335           otl_coverage_validate( table + coverage, valid );
336
337           OTL_CHECK( count*4 );
338           for ( ; count > 0; count-- )
339           {
340             anchor1 = OTL_NEXT_USHORT( p );
341             anchor2 = OTL_NEXT_USHORT( p );
342
343             if ( anchor1 )
344               otl_anchor_validate( table + anchor1, valid );
345
346             if ( anchor2 )
347               otl_anchor_validate( table + anchor2, valid );
348           }
349         }
350         break;
351
352       default:
353         OTL_INVALID_DATA;
354     }
355   }
356
357
358  /************************************************************************/
359  /************************************************************************/
360  /*****                                                              *****/
361  /*****                 GPOS LOOKUP TYPE 4                           *****/
362  /*****                                                              *****/
363  /************************************************************************/
364  /************************************************************************/
365
366   static void
367   otl_base_array_validate( OTL_Bytes      table,
368                            OTL_UInt       class_count,
369                            OTL_Validator  valid )
370   {
371     OTL_Bytes  p = table;
372     OTL_UInt   count, count2;
373
374     OTL_CHECK( 2 );
375     count = OTL_NEXT_USHORT( p );
376
377     OTL_CHECK( count*class_count*2 );
378     for ( ; count > 0; count-- )
379       for ( count2 = class_count; count2 > 0; count2-- )
380         otl_anchor_validate( table + OTL_NEXT_USHORT( p ) );
381   }
382
383
384   static void
385   otl_gpos_lookup4_validate( OTL_Bytes  table,
386                              OTL_Valid  valid )
387   {
388     OTL_Bytes  p = table;
389     OTL_UInt   format;
390
391     OTL_CHECK( 2 );
392     format = OTL_NEXT_USHORT( p );
393     switch (format)
394     {
395       case 1:
396         {
397           OTL_UInt  mark_coverage, base_coverage, class_count;
398           OTL_UInt  mark_array, base_array;
399
400           OTL_CHECK( 10 );
401           mark_coverage = OTL_NEXT_USHORT( p );
402           base_coverage = OTL_NEXT_USHORT( p );
403           class_count   = OTL_NEXT_USHORT( p );
404           mark_array    = OTL_NEXT_USHORT( p );
405           base_array    = OTL_NEXT_USHORT( p );
406
407           otl_coverage_validate( table + mark_coverage, valid );
408           otl_coverage_validate( table + base_coverage, valid );
409
410           otl_mark_array_validate( table + mark_array, valid );
411           otl_base_array_validate( table, class_count, valid );
412         }
413         break;
414
415       default:
416         OTL_INVALID_DATA;
417     }
418   }
419
420  /************************************************************************/
421  /************************************************************************/
422  /*****                                                              *****/
423  /*****                 GPOS LOOKUP TYPE 5                           *****/
424  /*****                                                              *****/
425  /************************************************************************/
426  /************************************************************************/
427
428   static void
429   otl_liga_attach_validate( OTL_Bytes      table,
430                             OTL_UInt       class_count,
431                             OTL_Validator  valid )
432   {
433     OTL_Bytes  p = table;
434     OTL_UInt   count, count2;
435
436     OTL_CHECK( 2 );
437     count = OTL_NEXT_USHORT( p );
438
439     OTL_CHECK( count*class_count*2 );
440     for ( ; count > 0; count-- )
441       for ( count2 = class_count; class_count > 0; class_count-- )
442         otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid );
443   }
444
445
446   static void
447   otl_liga_array_validate( OTL_Bytes      table,
448                            OTL_UInt       class_count,
449                            OTL_Validator  valid )
450   {
451     OTL_Bytes  p = table;
452     OTL_UInt   count, count2;
453
454     OTL_CHECK( 2 );
455     count = OTL_NEXT_USHORT( p );
456
457     OTL_CHECK( count*2 );
458     for ( ; count > 0; count-- )
459       otl_liga_attach_validate( table + OTL_NEXT_USHORT( p ), valid );
460   }
461
462
463   static void
464   otl_gpos_lookup5_validate( OTL_Bytes  table,
465                              OTL_Valid  valid )
466   {
467     OTL_Bytes  p = table;
468     OTL_UInt   format;
469
470     OTL_CHECK( 2 );
471     format = OTL_NEXT_USHORT( p );
472     switch (format)
473     {
474       case 1:
475         {
476           OTL_UInt  mark_coverage, lig_coverage, class_count;
477           OTL_UInt  mar_array, lig_array;
478
479           OTL_CHECK( 10 );
480           mark_coverage = OTL_NEXT_USHORT( p );
481           liga_coverage = OTL_NEXT_USHORT( p );
482           class_count   = OTL_NEXT_USHORT( p );
483           mark_array    = OTL_NEXT_USHORT( p );
484           liga_array    = OTL_NEXT_USHORT( p );
485
486           otl_coverage_validate( table + mark_coverage, valid );
487           otl_coverage_validate( table + liga_coverage, valid );
488
489           otl_mark_array_validate( table + mark_array, valid );
490           otl_liga_array_validate( table + liga_array, class_count, valid );
491         }
492         break;
493
494       default:
495         OTL_INVALID_DATA;
496     }
497   }
498
499  /************************************************************************/
500  /************************************************************************/
501  /*****                                                              *****/
502  /*****                 GPOS LOOKUP TYPE 6                           *****/
503  /*****                                                              *****/
504  /************************************************************************/
505  /************************************************************************/
506
507
508   static void
509   otl_mark2_array_validate( OTL_Bytes      table,
510                             OTL_UInt       class_count,
511                             OTL_Validator  valid )
512   {
513     OTL_Bytes  p = table;
514     OTL_UInt   count, count2;
515
516     OTL_CHECK( 2 );
517     count = OTL_NEXT_USHORT( p );
518
519     OTL_CHECK( count*class_count*2 );
520     for ( ; count > 0; count-- )
521       for ( count2 = class_count; class_count > 0; class_count-- )
522         otl_anchor_validate( table + OTL_NEXT_USHORT( p ), valid );
523   }
524
525
526   static void
527   otl_gpos_lookup6_validate( OTL_Bytes  table,
528                              OTL_Valid  valid )
529   {
530     OTL_Bytes  p = table;
531     OTL_UInt   format;
532
533     OTL_CHECK( 2 );
534     format = OTL_NEXT_USHORT( p );
535     switch (format)
536     {
537       case 1:
538         {
539           OTL_UInt  coverage1, coverage2, class_count, array1, array2;
540
541           OTL_CHECK( 10 );
542           coverage1   = OTL_NEXT_USHORT( p );
543           coverage2   = OTL_NEXT_USHORT( p );
544           class_count = OTL_NEXT_USHORT( p );
545           array1      = OTL_NEXT_USHORT( p );
546           array2      = OTL_NEXT_USHORT( p );
547
548           otl_coverage_validate( table + coverage1, valid );
549           otl_coverage_validate( table + coverage2, valid );
550
551           otl_mark_array_validate( table + array1, valid );
552           otl_mark2_array_validate( table + array2, valid );
553         }
554         break;
555
556       default:
557         OTL_INVALID_DATA;
558     }
559   }
560
561
562  /************************************************************************/
563  /************************************************************************/
564  /*****                                                              *****/
565  /*****                 GPOS LOOKUP TYPE 7                           *****/
566  /*****                                                              *****/
567  /************************************************************************/
568  /************************************************************************/
569
570   static void
571   otl_pos_rule_validate( OTL_Bytes      table,
572                          OTL_Validator  valid )
573   {
574     OTL_Bytes  p = table;
575     OTL_UInt   glyph_count, pos_count;
576
577     OTL_CHECK( 4 );
578     glyph_count = OTL_NEXT_USHORT( p );
579     pos_count   = OTL_NEXT_USHORT( p );
580
581     if ( glyph_count == 0 )
582       OTL_INVALID_DATA;
583
584     OTL_CHECK( (glyph_count-1)*2 + pos_count*4 );
585
586     /* XXX: check glyph indices and pos lookups */
587   }
588
589
590   static void
591   otl_pos_rule_set_validate( OTL_Bytes      table,
592                              OTL_Validator  valid )
593   {
594     OTL_Bytes  p = table;
595     OTL_UInt   count;
596
597     OTL_CHECK( 2 );
598     count = OTL_NEXT_USHORT( p );
599
600     OTL_CHECK( count*2 );
601     for ( ; count > 0; count-- )
602       otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid );
603   }
604
605
606
607   static void
608   otl_pos_class_rule_validate( OTL_Bytes      table,
609                                OTL_Validator  valid )
610   {
611     OTL_Bytes  p = table;
612     OTL_UInt   glyph_count, pos_count;
613
614     OTL_CHECK( 4 );
615     glyph_count = OTL_NEXT_USHORT( p );
616     pos_count   = OTL_NEXT_USHORT( p );
617
618     if ( glyph_count == 0 )
619       OTL_INVALID_DATA;
620
621     OTL_CHECK( (glyph_count-1)*2 + pos_count*4 );
622
623     /* XXX: check glyph indices and pos lookups */
624   }
625
626
627   static void
628   otl_pos_class_set_validate( OTL_Bytes      table,
629                               OTL_Validator  valid )
630   {
631     OTL_Bytes  p = table;
632     OTL_UInt   count;
633
634     OTL_CHECK( 2 );
635     count = OTL_NEXT_USHORT( p );
636
637     OTL_CHECK( count*2 );
638     for ( ; count > 0; count-- )
639       otl_pos_rule_validate( table + OTL_NEXT_USHORT(p), valid );
640   }
641
642
643   static void
644   otl_gpos_lookup7_validate( OTL_Bytes      table,
645                              OTL_Validator  valid )
646   {
647     OTL_Bytes  p = table;
648     OTL_UInt   format;
649
650     OTL_CHECK( 2 );
651     format = OTL_NEXT_USHORT( p );
652     switch (format)
653     {
654       case 1:
655         {
656           OTL_UInt  coverage, count;
657
658           OTL_CHECK( 4 );
659           coverage = OTL_NEXT_USHORT( p );
660           count    = OTL_NEXT_USHORT( p );
661
662           otl_coverage_validate( table + coverage, valid );
663
664           OTL_CHECK( count*2 );
665           for ( ; count > 0; count-- )
666             otl_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ), valid );
667         }
668         break;
669
670       case 2:
671         {
672           OTL_UInt  coverage, class_def, count;
673
674           OTL_CHECK( 6 );
675           coverage  = OTL_NEXT_USHORT( p );
676           class_def = OTL_NEXT_USHORT( p );
677           count     = OTL_NEXT_USHORT( p );
678
679           otl_coverage_validate        ( table + coverage, valid );
680           otl_class_definition_validate( table + class_def, valid );
681
682           OTL_CHECK( count*2 );
683           for ( ; count > 0; count-- )
684             otl_
685         }
686         break;
687
688       case 3:
689         {
690           OTL_UInt  glyph_count, pos_count;
691
692           OTL_CHECK( 4 );
693           glyph_count = OTL_NEXT_USHORT( p );
694           pos_count   = OTL_NEXT_USHORT( p );
695
696           OTL_CHECK( glyph_count*2 + pos_count*4 );
697           for ( ; glyph_count > 0; glyph_count )
698             otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
699
700           /* XXX: check pos lookups */
701         }
702         break;
703
704       default:
705         OTL_INVALID_DATA;
706     }
707   }
708
709
710  /************************************************************************/
711  /************************************************************************/
712  /*****                                                              *****/
713  /*****                 GPOS LOOKUP TYPE 8                           *****/
714  /*****                                                              *****/
715  /************************************************************************/
716  /************************************************************************/
717
718   static void
719   otl_chain_pos_rule_validate( OTL_Bytes      table,
720                                OTL_Validator  valid )
721   {
722     OTL_Bytes  p = table;
723     OTL_UInt   back_count, input_count, ahead_count, pos_count;
724
725     OTL_CHECK( 2 );
726     back_count = OTL_NEXT_USHORT( p );
727
728     OTL_CHECK( back_count*2 + 2 );
729     p += back_count*2;
730
731     input_count = OTL_NEXT_USHORT( p );
732     if ( input_count == 0 )
733       OTL_INVALID_DATA;
734
735     OTL_CHECK( input_count*2 );
736     p += (input_count-1)*2;
737
738     ahead_count = OTL_NEXT_USHORT( p );
739     OTL_CHECK( ahead_count*2 + 2 );
740     p += ahead_count*2;
741
742     pos_count = OTL_NEXT_USHORT( p );
743     OTL_CHECK( pos_count*4 );
744   }
745
746
747   static void
748   otl_chain_pos_rule_set_validate( OTL_Bytes      table,
749                                    OTL_Validator  valid )
750   {
751     OTL_Bytes  p = table;
752     OTL_UInt   count;
753
754     OTL_CHECK( 2 );
755     count = OTL_NEXT_USHORT( p );
756
757     OTL_CHECK( 2*count );
758     for ( ; count > 0; count-- )
759       otl_chain_pos_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
760   }
761
762
763
764   static void
765   otl_chain_pos_class_rule_validate( OTL_Bytes      table,
766                                      OTL_Validator  valid )
767   {
768     OTL_Bytes  p = table;
769     OTL_UInt   back_count, input_count, ahead_count, pos_count;
770
771     OTL_CHECK( 2 );
772     back_count = OTL_NEXT_USHORT( p );
773
774     OTL_CHECK( back_count*2 + 2 );
775     p += back_count*2;
776
777     input_count = OTL_NEXT_USHORT( p );
778     if ( input_count == 0 )
779       OTL_INVALID_DATA;
780
781     OTL_CHECK( input_count*2 );
782     p += (input_count-1)*2;
783
784     ahead_count = OTL_NEXT_USHORT( p );
785     OTL_CHECK( ahead_count*2 + 2 );
786     p += ahead_count*2;
787
788     pos_count = OTL_NEXT_USHORT( p );
789     OTL_CHECK( pos_count*4 );
790   }
791
792
793   static void
794   otl_chain_pos_class_set_validate( OTL_Bytes      table,
795                                    OTL_Validator  valid )
796   {
797     OTL_Bytes  p = table;
798     OTL_UInt   count;
799
800     OTL_CHECK( 2 );
801     count = OTL_NEXT_USHORT( p );
802
803     OTL_CHECK( 2*count );
804     for ( ; count > 0; count-- )
805       otl_chain_pos_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid );
806   }
807
808
809   static void
810   otl_gpos_lookup8_validate( OTL_Bytes      table,
811                              OTL_Validator  valid )
812   {
813     OTL_Bytes  p = table;
814     OTL_UInt   format;
815
816     OTL_CHECK( 2 );
817     format = OTL_NEXT_USHORT( p );
818     switch (format)
819     {
820       case 1:
821         {
822           OTL_UInt  coverage, count;
823
824           OTL_CHECK( 4 );
825           coverage = OTL_NEXT_USHORT( p );
826           count    = OTL_NEXT_USHORT( p );
827
828           otl_coverage_validate( table + coverage, valid );
829
830           OTL_CHECK( count*2 );
831           for ( ; count > 0; count-- )
832             otl_chain_pos_rule_set_validate( table + OTL_NEXT_USHORT( p ),
833                                              valid );
834         }
835         break;
836
837       case 2:
838         {
839           OTL_UInt  coverage, back_class, input_class, ahead_class, count;
840
841           OTL_CHECK( 10 );
842           coverage    = OTL_NEXT_USHORT( p );
843           back_class  = OTL_NEXT_USHORT( p );
844           input_class = OTL_NEXT_USHORT( p );
845           ahead_class = OTL_NEXT_USHORT( p );
846           count       = OTL_NEXT_USHORT( p );
847
848           otl_coverage_validate( table + coverage, valid );
849
850           otl_class_definition_validate( table + back_class,  valid );
851           otl_class_definition_validate( table + input_class, valid );
852           otl_class_definition_validate( table + ahead_class, valid );
853
854           OTL_CHECK( count*2 );
855           for ( ; count > 0; count-- )
856             otl_chain_pos_class_set_validate( table + OTL_NEXT_USHORT( p ),
857                                               valid );
858         }
859         break;
860
861       case 3:
862         {
863           OTL_UInt  back_count, input_count, ahead_count, pos_count, count;
864
865           OTL_CHECK( 2 );
866           back_count = OTL_NEXT_USHORT( p );
867
868           OTL_CHECK( 2*back_count+2 );
869           for ( count = back_count; count > 0; count-- )
870             otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
871
872           input_count = OTL_NEXT_USHORT( p );
873
874           OTL_CHECK( 2*input_count+2 );
875           for ( count = input_count; count > 0; count-- )
876             otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
877
878           ahead_count = OTL_NEXT_USHORT( p );
879
880           OTL_CHECK( 2*ahead_count+2 );
881           for ( count = ahead_count; count > 0; count-- )
882             otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid );
883
884           pos_count = OTL_NEXT_USHORT( p );
885           OTL_CHECK( pos_count*4 );
886         }
887         break;
888
889       default:
890         OTL_INVALID_DATA;
891     }
892   }
893
894  /************************************************************************/
895  /************************************************************************/
896  /*****                                                              *****/
897  /*****                 GPOS LOOKUP TYPE 9                           *****/
898  /*****                                                              *****/
899  /************************************************************************/
900  /************************************************************************/
901
902   static void
903   otl_gpos_lookup9_validate( OTL_Bytes  table,
904                              OTL_Valid  valid )
905   {
906     OTL_Bytes  p = table;
907     OTL_UInt   format;
908
909     OTL_CHECK( 2 );
910     format = OTL_NEXT_USHORT( p );
911     switch (format)
912     {
913       case 1:
914         {
915           OTL_UInt          lookup_type, lookup_offset;
916           OTL_ValidateFunc  validate;
917
918           OTL_CHECK( 6 );
919           lookup_type   = OTL_NEXT_USHORT( p );
920           lookup_offset = OTL_NEXT_ULONG( p );
921
922           if ( lookup_type == 0 || lookup_type >= 9 )
923             OTL_INVALID_DATA;
924
925           validate = otl_gpos_validate_funcs[ lookup_type-1 ];
926           validate( table + lookup_offset, valid );
927         }
928         break;
929
930       default:
931         OTL_INVALID_DATA;
932     }
933   }
934
935   static OTL_ValidateFunc  otl_gpos_validate_funcs[ 9 ] =
936   {
937     otl_gpos_lookup1_validate,
938     otl_gpos_lookup2_validate,
939     otl_gpos_lookup3_validate,
940     otl_gpos_lookup4_validate,
941     otl_gpos_lookup5_validate,
942     otl_gpos_lookup6_validate,
943     otl_gpos_lookup7_validate,
944     otl_gpos_lookup8_validate,
945     otl_gpos_lookup9_validate,
946   };
947
948
949  /************************************************************************/
950  /************************************************************************/
951  /*****                                                              *****/
952  /*****                         GPOS TABLE                           *****/
953  /*****                                                              *****/
954  /************************************************************************/
955  /************************************************************************/
956
957
958   OTL_LOCALDEF( void )
959   otl_gpos_validate( OTL_Bytes      table,
960                      OTL_Validator  valid )
961   {
962     OTL_Bytes  p = table;
963     OTL_UInt   scripts, features, lookups;
964
965     OTL_CHECK( 10 );
966
967     if ( OTL_NEXT_USHORT( p ) != 0x10000UL )
968       OTL_INVALID_DATA;
969
970     scripts  = OTL_NEXT_USHORT( p );
971     features = OTL_NEXT_USHORT( p );
972     lookups  = OTL_NEXT_USHORT( p );
973
974     otl_script_list_validate ( table + scripts, valid );
975     otl_feature_list_validate( table + features, valid );
976
977     otl_lookup_list_validate( table + lookups, 9, otl_gpos_validate_funcs,
978                               valid );
979   }
980