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