~oif-team/ubuntu/natty/qt4-x11/xi2.1

« back to all changes in this revision

Viewing changes to src/3rdparty/freetype/src/otlayout/otlcommn.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2005-08-24 04:09:09 UTC
  • Revision ID: james.westby@ubuntu.com-20050824040909-xmxe9jfr4a0w5671
Tags: upstream-4.0.0
ImportĀ upstreamĀ versionĀ 4.0.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/***************************************************************************/
 
2
/*                                                                         */
 
3
/*  otlcommn.c                                                             */
 
4
/*                                                                         */
 
5
/*    OpenType layout support, common tables (body).                       */
 
6
/*                                                                         */
 
7
/*  Copyright 2002 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 "otlayout.h"
 
20
 
 
21
 
 
22
 /*************************************************************************/
 
23
 /*************************************************************************/
 
24
 /*****                                                               *****/
 
25
 /*****                       COVERAGE TABLE                          *****/
 
26
 /*****                                                               *****/
 
27
 /*************************************************************************/
 
28
 /*************************************************************************/
 
29
 
 
30
  OTL_LOCALDEF( void )
 
31
  otl_coverage_validate( OTL_Bytes      table,
 
32
                         OTL_Validator  valid )
 
33
  {
 
34
    OTL_Bytes  p;
 
35
    OTL_UInt   format;
 
36
 
 
37
 
 
38
    if ( table + 4 > valid->limit )
 
39
      OTL_INVALID_TOO_SHORT;
 
40
 
 
41
    format = OTL_NEXT_USHORT( p );
 
42
    switch ( format )
 
43
    {
 
44
    case 1:
 
45
      {
 
46
        OTL_UInt  count = OTL_NEXT_USHORT( p );
 
47
 
 
48
 
 
49
        if ( p + count * 2 >= valid->limit )
 
50
          OTL_INVALID_TOO_SHORT;
 
51
 
 
52
        /* XXX: check glyph indices */
 
53
      }
 
54
      break;
 
55
 
 
56
    case 2:
 
57
      {
 
58
        OTL_UInt  n, num_ranges = OTL_NEXT_USHORT( p );
 
59
        OTL_UInt  start, end, start_cover, total = 0, last = 0;
 
60
 
 
61
 
 
62
        if ( p + num_ranges * 6 >= valid->limit )
 
63
          OTL_INVALID_TOO_SHORT;
 
64
 
 
65
        for ( n = 0; n < num_ranges; n++ )
 
66
        {
 
67
          start       = OTL_NEXT_USHORT( p );
 
68
          end         = OTL_NEXT_USHORT( p );
 
69
          start_cover = OTL_NEXT_USHORT( p );
 
70
 
 
71
          if ( start > end || start_cover != total )
 
72
            OTL_INVALID_DATA;
 
73
 
 
74
          if ( n > 0 && start <= last )
 
75
            OTL_INVALID_DATA;
 
76
 
 
77
          total += end - start + 1;
 
78
          last   = end;
 
79
        }
 
80
      }
 
81
      break;
 
82
 
 
83
    default:
 
84
      OTL_INVALID_FORMAT;
 
85
    }
 
86
  }
 
87
 
 
88
 
 
89
  OTL_LOCALDEF( OTL_UInt )
 
90
  otl_coverage_get_count( OTL_Bytes  table )
 
91
  {
 
92
    OTL_Bytes  p      = table;
 
93
    OTL_UInt   format = OTL_NEXT_USHORT( p );
 
94
    OTL_UInt   count  = OTL_NEXT_USHORT( p );
 
95
    OTL_UInt   result = 0;
 
96
 
 
97
 
 
98
    switch ( format )
 
99
    {
 
100
    case 1:
 
101
      return count;
 
102
 
 
103
    case 2:
 
104
      {
 
105
        OTL_UInt  start, end;
 
106
 
 
107
 
 
108
        for ( ; count > 0; count-- )
 
109
        {
 
110
          start = OTL_NEXT_USHORT( p );
 
111
          end   = OTL_NEXT_USHORT( p );
 
112
          p    += 2;                    /* skip start_index */
 
113
 
 
114
          result += end - start + 1;
 
115
        }
 
116
      }
 
117
      break;
 
118
 
 
119
    default:
 
120
      ;
 
121
    }
 
122
 
 
123
    return result;
 
124
  }
 
125
 
 
126
 
 
127
  OTL_LOCALDEF( OTL_Int )
 
128
  otl_coverage_get_index( OTL_Bytes  table,
 
129
                          OTL_UInt   glyph_index )
 
130
  {
 
131
    OTL_Bytes  p      = table;
 
132
    OTL_UInt   format = OTL_NEXT_USHORT( p );
 
133
    OTL_UInt   count  = OTL_NEXT_USHORT( p );
 
134
 
 
135
 
 
136
    switch ( format )
 
137
    {
 
138
    case 1:
 
139
      {
 
140
        OTL_UInt  min = 0, max = count, mid, gindex;
 
141
 
 
142
 
 
143
        table += 4;
 
144
        while ( min < max )
 
145
        {
 
146
          mid    = ( min + max ) >> 1;
 
147
          p      = table + 2 * mid;
 
148
          gindex = OTL_PEEK_USHORT( p );
 
149
 
 
150
          if ( glyph_index == gindex )
 
151
            return (OTL_Int)mid;
 
152
 
 
153
          if ( glyph_index < gindex )
 
154
            max = mid;
 
155
          else
 
156
            min = mid + 1;
 
157
        }
 
158
      }
 
159
      break;
 
160
 
 
161
    case 2:
 
162
      {
 
163
        OTL_UInt  min = 0, max = count, mid;
 
164
        OTL_UInt  start, end, delta, start_cover;
 
165
 
 
166
 
 
167
        table += 4;
 
168
        while ( min < max )
 
169
        {
 
170
          mid    = ( min + max ) >> 1;
 
171
          p      = table + 6 * mid;
 
172
          start  = OTL_NEXT_USHORT( p );
 
173
          end    = OTL_NEXT_USHORT( p );
 
174
 
 
175
          if ( glyph_index < start )
 
176
            max = mid;
 
177
          else if ( glyph_index > end )
 
178
            min = mid + 1;
 
179
          else
 
180
            return (OTL_Int)( glyph_index + OTL_NEXT_USHORT( p ) - start );
 
181
        }
 
182
      }
 
183
      break;
 
184
 
 
185
    default:
 
186
      ;
 
187
    }
 
188
 
 
189
    return -1;
 
190
  }
 
191
 
 
192
 
 
193
  /*************************************************************************/
 
194
  /*************************************************************************/
 
195
  /*****                                                               *****/
 
196
  /*****                  CLASS DEFINITION TABLE                       *****/
 
197
  /*****                                                               *****/
 
198
  /*************************************************************************/
 
199
  /*************************************************************************/
 
200
 
 
201
  OTL_LOCALDEF( void )
 
202
  otl_class_definition_validate( OTL_Bytes      table,
 
203
                                 OTL_Validator  valid )
 
204
  {
 
205
    OTL_Bytes  p = table;
 
206
    OTL_UInt   format;
 
207
 
 
208
 
 
209
    if ( p + 4 > valid->limit )
 
210
      OTL_INVALID_TOO_SHORT;
 
211
 
 
212
    format = OTL_NEXT_USHORT( p );
 
213
    switch ( format )
 
214
    {
 
215
    case 1:
 
216
      {
 
217
        OTL_UInt  count, start = OTL_NEXT_USHORT( p );
 
218
 
 
219
 
 
220
        if ( p + 2 > valid->limit )
 
221
          OTL_INVALID_TOO_SHORT;
 
222
 
 
223
        count = OTL_NEXT_USHORT( p );
 
224
 
 
225
        if ( p + count * 2 > valid->limit )
 
226
          OTL_INVALID_TOO_SHORT;
 
227
 
 
228
        /* XXX: check glyph indices */
 
229
      }
 
230
      break;
 
231
 
 
232
    case 2:
 
233
      {
 
234
        OTL_UInt  n, num_ranges = OTL_NEXT_USHORT( p );
 
235
        OTL_UInt  start, end, value, last = 0;
 
236
 
 
237
 
 
238
        if ( p + num_ranges * 6 > valid->limit )
 
239
          OTL_INVALID_TOO_SHORT;
 
240
 
 
241
        for ( n = 0; n < num_ranges; n++ )
 
242
        {
 
243
          start = OTL_NEXT_USHORT( p );
 
244
          end   = OTL_NEXT_USHORT( p );
 
245
          value = OTL_NEXT_USHORT( p );  /* ignored */
 
246
 
 
247
          if ( start > end || ( n > 0 && start <= last ) )
 
248
            OTL_INVALID_DATA;
 
249
 
 
250
          last = end;
 
251
        }
 
252
      }
 
253
      break;
 
254
 
 
255
    default:
 
256
      OTL_INVALID_FORMAT;
 
257
    }
 
258
  }
 
259
 
 
260
 
 
261
  OTL_LOCALDEF( OTL_UInt )
 
262
  otl_class_definition_get_value( OTL_Bytes  table,
 
263
                                  OTL_UInt   glyph_index )
 
264
  {
 
265
    OTL_Bytes  p      = table;
 
266
    OTL_UInt   format = OTL_NEXT_USHORT( p );
 
267
 
 
268
 
 
269
    switch ( format )
 
270
    {
 
271
    case 1:
 
272
      {
 
273
        OTL_UInt  start = OTL_NEXT_USHORT( p );
 
274
        OTL_UInt  count = OTL_NEXT_USHORT( p );
 
275
        OTL_UInt  idx   = (OTL_UInt)( glyph_index - start );
 
276
 
 
277
 
 
278
        if ( idx < count )
 
279
        {
 
280
          p += 2 * idx;
 
281
          return OTL_PEEK_USHORT( p );
 
282
        }
 
283
      }
 
284
      break;
 
285
 
 
286
    case 2:
 
287
      {
 
288
        OTL_UInt  count = OTL_NEXT_USHORT( p );
 
289
        OTL_UInt  min = 0, max = count, mid, gindex;
 
290
 
 
291
 
 
292
        table += 4;
 
293
        while ( min < max )
 
294
        {
 
295
          mid   = ( min + max ) >> 1;
 
296
          p     = table + 6 * mid;
 
297
          start = OTL_NEXT_USHORT( p );
 
298
          end   = OTL_NEXT_USHORT( p );
 
299
 
 
300
          if ( glyph_index < start )
 
301
            max = mid;
 
302
          else if ( glyph_index > end )
 
303
            min = mid + 1;
 
304
          else
 
305
            return OTL_PEEK_USHORT( p );
 
306
        }
 
307
      }
 
308
      break;
 
309
 
 
310
    default:
 
311
      ;
 
312
    }
 
313
 
 
314
    return 0;
 
315
  }
 
316
 
 
317
 
 
318
  /*************************************************************************/
 
319
  /*************************************************************************/
 
320
  /*****                                                               *****/
 
321
  /*****                      DEVICE TABLE                             *****/
 
322
  /*****                                                               *****/
 
323
  /*************************************************************************/
 
324
  /*************************************************************************/
 
325
 
 
326
  OTL_LOCALDEF( void )
 
327
  otl_device_table_validate( OTL_Bytes      table,
 
328
                             OTL_Validator  valid )
 
329
  {
 
330
    OTL_Bytes  p = table;
 
331
    OTL_UInt   start, end, count, format, count;
 
332
 
 
333
 
 
334
    if ( p + 8 > valid->limit )
 
335
      OTL_INVALID_TOO_SHORT;
 
336
 
 
337
    start  = OTL_NEXT_USHORT( p );
 
338
    end    = OTL_NEXT_USHORT( p );
 
339
    format = OTL_NEXT_USHORT( p );
 
340
 
 
341
    if ( format < 1 || format > 3 || end < start )
 
342
      OTL_INVALID_DATA;
 
343
 
 
344
    count = (OTL_UInt)( end - start + 1 );
 
345
 
 
346
    if ( p + ( ( 1 << format ) * count ) / 8 > valid->limit )
 
347
      OTL_INVALID_TOO_SHORT;
 
348
  }
 
349
 
 
350
 
 
351
  OTL_LOCALDEF( OTL_UInt )
 
352
  otl_device_table_get_start( OTL_Bytes  table )
 
353
  {
 
354
    OTL_Bytes  p = table;
 
355
 
 
356
 
 
357
    return OTL_PEEK_USHORT( p );
 
358
  }
 
359
 
 
360
 
 
361
  OTL_LOCALDEF( OTL_UInt )
 
362
  otl_device_table_get_end( OTL_Bytes  table )
 
363
  {
 
364
    OTL_Bytes  p = table + 2;
 
365
 
 
366
 
 
367
    return OTL_PEEK_USHORT( p );
 
368
  }
 
369
 
 
370
 
 
371
  OTL_LOCALDEF( OTL_Int )
 
372
  otl_device_table_get_delta( OTL_Bytes  table,
 
373
                              OTL_UInt   size )
 
374
  {
 
375
    OTL_Bytes  p = table;
 
376
    OTL_Int    result = 0;
 
377
    OTL_UInt   start, end, format, idx, value;
 
378
 
 
379
 
 
380
    start  = OTL_NEXT_USHORT( p );
 
381
    end    = OTL_NEXT_USHORT( p );
 
382
    format = OTL_NEXT_USHORT( p );
 
383
 
 
384
    if ( size >= start && size <= end )
 
385
    {
 
386
      /* we could do that with clever bit operations, but a switch is */
 
387
      /* much simpler to understand and maintain                      */
 
388
      /*                                                              */
 
389
      switch ( format )
 
390
      {
 
391
      case 1:
 
392
        idx    = (OTL_UInt)( ( size - start ) * 2 );
 
393
        p     += idx / 16;
 
394
        value  = OTL_PEEK_USHORT( p );
 
395
        shift  = idx & 15;
 
396
        result = (OTL_Short)( value << shift ) >> ( 14 - shift );
 
397
 
 
398
        break;
 
399
 
 
400
      case 2:
 
401
        idx    = (OTL_UInt)( ( size - start ) * 4 );
 
402
        p     += idx / 16;
 
403
        value  = OTL_PEEK_USHORT( p );
 
404
        shift  = idx & 15;
 
405
        result = (OTL_Short)( value << shift ) >> ( 12 - shift );
 
406
 
 
407
        break;
 
408
 
 
409
      case 3:
 
410
        idx    = (OTL_UInt)( ( size - start ) * 8 );
 
411
        p     += idx / 16;
 
412
        value  = OTL_PEEK_USHORT( p );
 
413
        shift  = idx & 15;
 
414
        result = (OTL_Short)( value << shift ) >> ( 8 - shift );
 
415
 
 
416
        break;
 
417
 
 
418
      default:
 
419
        ;
 
420
      }
 
421
    }
 
422
 
 
423
    return result;
 
424
  }
 
425
 
 
426
 
 
427
  /*************************************************************************/
 
428
  /*************************************************************************/
 
429
  /*****                                                               *****/
 
430
  /*****                      LOOKUP LISTS                             *****/
 
431
  /*****                                                               *****/
 
432
  /*************************************************************************/
 
433
  /*************************************************************************/
 
434
 
 
435
  OTL_LOCALDEF( void )
 
436
  otl_lookup_validate( OTL_Bytes      table,
 
437
                       OTL_Validator  valid )
 
438
  {
 
439
    OTL_Bytes  p = table;
 
440
    OTL_UInt   num_tables;
 
441
 
 
442
 
 
443
    if ( table + 6 > valid->limit )
 
444
      OTL_INVALID_TOO_SHORT;
 
445
 
 
446
    p += 4;
 
447
    num_tables = OTL_NEXT_USHORT( p );
 
448
 
 
449
    if ( p + num_tables * 2 > valid->limit )
 
450
      OTL_INVALID_TOO_SHORT;
 
451
 
 
452
    for ( ; num_tables > 0; num_tables-- )
 
453
    {
 
454
      offset = OTL_NEXT_USHORT( p );
 
455
 
 
456
      if ( table + offset >= valid->limit )
 
457
        OTL_INVALID_OFFSET;
 
458
    }
 
459
 
 
460
    /* XXX: check sub-tables? */
 
461
  }
 
462
 
 
463
 
 
464
  OTL_LOCALDEF( OTL_UInt )
 
465
  otl_lookup_get_count( OTL_Bytes  table )
 
466
  {
 
467
    OTL_Bytes  p = table + 4;
 
468
 
 
469
 
 
470
    return OTL_PEEK_USHORT( p );
 
471
  }
 
472
 
 
473
 
 
474
  OTL_LOCALDEF( OTL_Bytes )
 
475
  otl_lookup_get_table( OTL_Bytes  table,
 
476
                        OTL_UInt   idx )
 
477
  {
 
478
    OTL_Bytes  p, result = NULL;
 
479
    OTL_UInt   count;
 
480
 
 
481
 
 
482
    p     = table + 4;
 
483
    count = OTL_NEXT_USHORT( p );
 
484
    if ( idx < count )
 
485
    {
 
486
      p     += idx * 2;
 
487
      result = table + OTL_PEEK_USHORT( p );
 
488
    }
 
489
 
 
490
    return result;
 
491
  }
 
492
 
 
493
 
 
494
  /*************************************************************************/
 
495
  /*************************************************************************/
 
496
  /*****                                                               *****/
 
497
  /*****                      LOOKUP LISTS                             *****/
 
498
  /*****                                                               *****/
 
499
  /*************************************************************************/
 
500
  /*************************************************************************/
 
501
 
 
502
  OTL_LOCALDEF( void )
 
503
  otl_lookup_list_validate( OTL_Bytes      table,
 
504
                            OTL_Validator  valid )
 
505
  {
 
506
    OTL_Bytes  p = table, q;
 
507
    OTL_UInt   num_lookups, offset;
 
508
 
 
509
 
 
510
    if ( p + 2 > valid->limit )
 
511
      OTL_INVALID_TOO_SHORT;
 
512
 
 
513
    num_lookups = OTL_NEXT_USHORT( p );
 
514
 
 
515
    if ( p + num_lookups * 2 > valid->limit )
 
516
      OTL_INVALID_TOO_SHORT;
 
517
 
 
518
    for ( ; num_lookups > 0; num_lookups-- )
 
519
    {
 
520
      offset = OTL_NEXT_USHORT( p );
 
521
 
 
522
      otl_lookup_validate( table + offset, valid );
 
523
    }
 
524
  }
 
525
 
 
526
 
 
527
  OTL_LOCALDEF( OTL_UInt )
 
528
  otl_lookup_list_get_count( OTL_Bytes  table )
 
529
  {
 
530
    OTL_Bytes  p = table;
 
531
 
 
532
 
 
533
    return OTL_PEEK_USHORT( p );
 
534
  }
 
535
 
 
536
 
 
537
  OTL_LOCALDEF( OTL_Bytes )
 
538
  otl_lookup_list_get_lookup( OTL_Bytes  table,
 
539
                              OTL_UInt   idx )
 
540
  {
 
541
    OTL_Bytes  p, result = 0;
 
542
    OTL_UInt   count;
 
543
 
 
544
 
 
545
    p     = table;
 
546
    count = OTL_NEXT_USHORT( p );
 
547
    if ( idx < count )
 
548
    {
 
549
      p     += idx * 2;
 
550
      result = table + OTL_PEEK_USHORT( p );
 
551
    }
 
552
 
 
553
    return result;
 
554
  }
 
555
 
 
556
 
 
557
  OTL_LOCALDEF( OTL_Bytes )
 
558
  otl_lookup_list_get_table( OTL_Bytes  table,
 
559
                             OTL_UInt   lookup_index,
 
560
                             OTL_UInt   table_index )
 
561
  {
 
562
    OTL_Bytes  result = NULL;
 
563
 
 
564
 
 
565
    result = otl_lookup_list_get_lookup( table, lookup_index );
 
566
    if ( result )
 
567
      result = otl_lookup_get_table( result, table_index );
 
568
 
 
569
    return result;
 
570
  }
 
571
 
 
572
 
 
573
  OTL_LOCALDEF( void )
 
574
  otl_lookup_list_foreach( OTL_Bytes        table,
 
575
                           OTL_ForeachFunc  func,
 
576
                           OTL_Pointer      func_data )
 
577
  {
 
578
    OTL_Bytes  p     = table;
 
579
    OTL_UInt   count = OTL_NEXT_USHORT( p );
 
580
 
 
581
 
 
582
    for ( ; count > 0; count-- )
 
583
      func( table + OTL_NEXT_USHORT( p ), func_data );
 
584
  }
 
585
 
 
586
 
 
587
  /*************************************************************************/
 
588
  /*************************************************************************/
 
589
  /*****                                                               *****/
 
590
  /*****                        FEATURES                               *****/
 
591
  /*****                                                               *****/
 
592
  /*************************************************************************/
 
593
  /*************************************************************************/
 
594
 
 
595
  OTL_LOCALDEF( void )
 
596
  otl_feature_validate( OTL_Bytes      table,
 
597
                        OTL_Validator  valid )
 
598
  {
 
599
    OTL_Bytes  p = table;
 
600
    OTL_UInt   feat_params, num_lookups;
 
601
 
 
602
 
 
603
    if ( p + 4 > valid->limit )
 
604
      OTL_INVALID_TOO_SHORT;
 
605
 
 
606
    feat_params = OTL_NEXT_USHORT( p );  /* ignored */
 
607
    num_lookups = OTL_NEXT_USHORT( p );
 
608
 
 
609
    if ( p + num_lookups * 2 > valid->limit )
 
610
      OTL_INVALID_TOO_SHORT;
 
611
 
 
612
    /* XXX: check lookup indices */
 
613
  }
 
614
 
 
615
 
 
616
  OTL_LOCALDEF( OTL_UInt )
 
617
  otl_feature_get_count( OTL_Bytes  table )
 
618
  {
 
619
    OTL_Bytes  p = table + 4;
 
620
 
 
621
 
 
622
    return OTL_PEEK_USHORT( p );
 
623
  }
 
624
 
 
625
 
 
626
  OTL_LOCALDEF( OTL_UInt )
 
627
  otl_feature_get_lookups( OTL_Bytes  table,
 
628
                           OTL_UInt   start,
 
629
                           OTL_UInt   count,
 
630
                           OTL_UInt  *lookups )
 
631
  {
 
632
    OTL_Bytes  p;
 
633
    OTL_UInt   num_features, result = 0;
 
634
 
 
635
 
 
636
    p            = table + 4;
 
637
    num_features = OTL_NEXT_USHORT( p );
 
638
 
 
639
    p += start * 2;
 
640
 
 
641
    for ( ; count > 0 && start < num_features; count--, start++ )
 
642
    {
 
643
      lookups[0] = OTL_NEXT_USHORT(p);
 
644
      lookups++;
 
645
      result++;
 
646
    }
 
647
 
 
648
    return result;
 
649
  }
 
650
 
 
651
 
 
652
  /*************************************************************************/
 
653
  /*************************************************************************/
 
654
  /*****                                                               *****/
 
655
  /*****                        FEATURE LIST                           *****/
 
656
  /*****                                                               *****/
 
657
  /*************************************************************************/
 
658
  /*************************************************************************/
 
659
 
 
660
  OTL_LOCALDEF( void )
 
661
  otl_feature_list_validate( OTL_Bytes      table,
 
662
                             OTL_Validator  valid )
 
663
  {
 
664
    OTL_Bytes  p = table;
 
665
    OTL_UInt   num_features, offset;
 
666
 
 
667
 
 
668
    if ( table + 2 > valid->limit )
 
669
      OTL_INVALID_TOO_SHORT;
 
670
 
 
671
    num_features = OTL_NEXT_USHORT( p );
 
672
 
 
673
    if ( p + num_features * 2 > valid->limit )
 
674
      OTL_INVALID_TOO_SHORT;
 
675
 
 
676
    for ( ; num_features > 0; num_features-- )
 
677
    {
 
678
      p     += 4;                       /* skip tag */
 
679
      offset = OTL_NEXT_USHORT( p );
 
680
 
 
681
      otl_feature_table_validate( table + offset, valid );
 
682
    }
 
683
  }
 
684
 
 
685
 
 
686
  OTL_LOCALDEF( OTL_UInt )
 
687
  otl_feature_list_get_count( OTL_Bytes  table )
 
688
  {
 
689
    OTL_Bytes  p = table;
 
690
 
 
691
 
 
692
    return OTL_PEEK_USHORT( p );
 
693
  }
 
694
 
 
695
 
 
696
  OTL_LOCALDEF( OTL_Bytes )
 
697
  otl_feature_list_get_feature( OTL_Bytes  table,
 
698
                                OTL_UInt   idx )
 
699
  {
 
700
    OTL_Bytes  p, result = NULL;
 
701
    OTL_UInt   count;
 
702
 
 
703
 
 
704
    p     = table;
 
705
    count = OTL_NEXT_USHORT( p );
 
706
 
 
707
    if ( idx < count )
 
708
    {
 
709
      p     += idx * 2;
 
710
      result = table + OTL_PEEK_USHORT( p );
 
711
    }
 
712
 
 
713
    return result;
 
714
  }
 
715
 
 
716
 
 
717
  OTL_LOCALDEF( void )
 
718
  otl_feature_list_foreach( OTL_Bytes        table,
 
719
                            OTL_ForeachFunc  func,
 
720
                            OTL_Pointer      func_data )
 
721
  {
 
722
    OTL_Bytes  p;
 
723
    OTL_UInt   count;
 
724
 
 
725
 
 
726
    p = table;
 
727
    count = OTL_NEXT_USHORT( p );
 
728
 
 
729
    for ( ; count > 0; count-- )
 
730
      func( table + OTL_NEXT_USHORT( p ), func_data );
 
731
  }
 
732
 
 
733
 
 
734
  /*************************************************************************/
 
735
  /*************************************************************************/
 
736
  /*****                                                               *****/
 
737
  /*****                       LANGUAGE SYSTEM                         *****/
 
738
  /*****                                                               *****/
 
739
  /*************************************************************************/
 
740
  /*************************************************************************/
 
741
 
 
742
 
 
743
  OTL_LOCALDEF( void )
 
744
  otl_lang_validate( OTL_Bytes      table,
 
745
                     OTL_Validator  valid )
 
746
  {
 
747
    OTL_Bytes  p = table;
 
748
    OTL_UInt   lookup_order;
 
749
    OTL_UInt   req_feature;
 
750
    OTL_UInt   num_features;
 
751
 
 
752
 
 
753
    if ( table + 6 >= valid->limit )
 
754
      OTL_INVALID_TOO_SHORT;
 
755
 
 
756
    lookup_order = OTL_NEXT_USHORT( p );
 
757
    req_feature  = OTL_NEXT_USHORT( p );
 
758
    num_features = OTL_NEXT_USHORT( p );
 
759
 
 
760
    /* XXX: check req_feature if not 0xFFFFU */
 
761
 
 
762
    if ( p + 2 * num_features >= valid->limit )
 
763
      OTL_INVALID_TOO_SHORT;
 
764
 
 
765
    /* XXX: check features indices! */
 
766
  }
 
767
 
 
768
 
 
769
  OTL_LOCALDEF( OTL_UInt )
 
770
  otl_lang_get_count( OTL_Bytes  table )
 
771
  {
 
772
    OTL_Bytes  p = table + 4;
 
773
 
 
774
    return OTL_PEEK_USHORT( p );
 
775
  }
 
776
 
 
777
 
 
778
  OTL_LOCALDEF( OTL_UInt )
 
779
  otl_lang_get_req_feature( OTL_Bytes  table )
 
780
  {
 
781
    OTL_Bytes  p = table + 2;
 
782
 
 
783
 
 
784
    return OTL_PEEK_USHORT( p );
 
785
  }
 
786
 
 
787
 
 
788
  OTL_LOCALDEF( OTL_UInt )
 
789
  otl_lang_get_features( OTL_Bytes  table,
 
790
                         OTL_UInt   start,
 
791
                         OTL_UInt   count,
 
792
                         OTL_UInt  *features )
 
793
  {
 
794
    OTL_Bytes  p            = table + 4;
 
795
    OTL_UInt   num_features = OTL_NEXT_USHORT( p );
 
796
    OTL_UInt   result       = 0;
 
797
 
 
798
 
 
799
    p += start * 2;
 
800
 
 
801
    for ( ; count > 0 && start < num_features; start++, count-- )
 
802
    {
 
803
      features[0] = OTL_NEXT_USHORT( p );
 
804
      features++;
 
805
      result++;
 
806
    }
 
807
 
 
808
    return result;
 
809
  }
 
810
 
 
811
 
 
812
 
 
813
 
 
814
  /*************************************************************************/
 
815
  /*************************************************************************/
 
816
  /*****                                                               *****/
 
817
  /*****                           SCRIPTS                             *****/
 
818
  /*****                                                               *****/
 
819
  /*************************************************************************/
 
820
  /*************************************************************************/
 
821
 
 
822
 
 
823
  OTL_LOCALDEF( void )
 
824
  otl_script_validate( OTL_Bytes      table,
 
825
                       OTL_Validator  valid )
 
826
  {
 
827
    OTL_UInt   default_lang;
 
828
    OTL_Bytes  p = table;
 
829
 
 
830
 
 
831
    if ( table + 4 > valid->limit )
 
832
      OTL_INVALID_TOO_SHORT;
 
833
 
 
834
    default_lang = OTL_NEXT_USHORT( p );
 
835
    num_langs    = OTL_NEXT_USHORT( p );
 
836
 
 
837
    if ( default_lang != 0 )
 
838
    {
 
839
      if ( table + default_lang >= valid->limit )
 
840
        OTL_INVALID_OFFSET;
 
841
    }
 
842
 
 
843
    if ( p + num_langs * 6 >= valid->limit )
 
844
      OTL_INVALID_OFFSET;
 
845
 
 
846
    for ( ; num_langs > 0; num_langs-- )
 
847
    {
 
848
      OTL_UInt  offset;
 
849
 
 
850
 
 
851
      p     += 4;  /* skip tag */
 
852
      offset = OTL_NEXT_USHORT( p );
 
853
 
 
854
      otl_lang_validate( table + offset, valid );
 
855
    }
 
856
  }
 
857
 
 
858
 
 
859
  OTL_LOCALDEF( void )
 
860
  otl_script_list_validate( OTL_Bytes      list,
 
861
                            OTL_Validator  valid )
 
862
  {
 
863
    OTL_UInt   num_scripts;
 
864
    OTL_Bytes  p = list;
 
865
 
 
866
 
 
867
    if ( list + 2 > valid->limit )
 
868
      OTL_INVALID_TOO_SHORT;
 
869
 
 
870
    num_scripts = OTL_NEXT_USHORT( p );
 
871
 
 
872
    if ( p + num_scripts * 6 > valid->limit )
 
873
      OTL_INVALID_TOO_SHORT;
 
874
 
 
875
    for ( ; num_scripts > 0; num_scripts-- )
 
876
    {
 
877
      OTL_UInt  offset;
 
878
 
 
879
 
 
880
      p     += 4;                       /* skip tag */
 
881
      offset = OTL_NEXT_USHORT( p );
 
882
 
 
883
      otl_script_table_validate( list + offset, valid );
 
884
    }
 
885
  }
 
886
 
 
887
 
 
888
  /*************************************************************************/
 
889
  /*************************************************************************/
 
890
  /*****                                                               *****/
 
891
  /*****                         LOOKUP LISTS                          *****/
 
892
  /*****                                                               *****/
 
893
  /*************************************************************************/
 
894
  /*************************************************************************/
 
895
 
 
896
  static void
 
897
  otl_lookup_table_validate( OTL_Bytes          table,
 
898
                             OTL_UInt           type_count,
 
899
                             OTL_ValidateFunc*  type_funcs,
 
900
                             OTL_Validator      valid )
 
901
  {
 
902
    OTL_Bytes         p = table;
 
903
    OTL_UInt          lookup_type, lookup_flag, count;
 
904
    OTL_ValidateFunc  validate;
 
905
 
 
906
    OTL_CHECK( 6 );
 
907
    lookup_type = OTL_NEXT_USHORT( p );
 
908
    lookup_flag = OTL_NEXT_USHORT( p );
 
909
    count       = OTL_NEXT_USHORT( p );
 
910
 
 
911
    if ( lookup_type == 0 || lookup_type >= type_count )
 
912
      OTL_INVALID_DATA;
 
913
 
 
914
    validate = type_funcs[ lookup_type - 1 ];
 
915
 
 
916
    OTL_CHECK( 2*count );
 
917
    for ( ; count > 0; count-- )
 
918
      validate( table + OTL_NEXT_USHORT( p ), valid );
 
919
  }
 
920
 
 
921
 
 
922
  OTL_LOCALDEF( void )
 
923
  otl_lookup_list_validate( OTL_Bytes          table,
 
924
                            OTL_UInt           type_count,
 
925
                            OTL_ValidateFunc*  type_funcs,
 
926
                            OTL_Validator      valid )
 
927
  {
 
928
    OTL_Bytes  p = table;
 
929
    OTL_UInt   count;
 
930
 
 
931
    OTL_CHECK( 2 );
 
932
    count = OTL_NEXT_USHORT( p );
 
933
 
 
934
    OTL_CHECK( 2*count );
 
935
    for ( ; count > 0; count-- )
 
936
      otl_lookup_table_validate( table + OTL_NEXT_USHORT( p ),
 
937
                                 type_count, type_funcs, valid );
 
938
  }
 
939
 
 
940
/* END */