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