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