1 #include "otlgsub.h" 2 #include "otlcommn.h" 3 4 /************************************************************************/ 5 /************************************************************************/ 6 /***** *****/ 7 /***** GSUB LOOKUP TYPE 1 *****/ 8 /***** *****/ 9 /************************************************************************/ 10 /************************************************************************/ 11 12 /* 13 * 1: Single Substitution - Table format(s) 14 * 15 * This table is used to substiture individual glyph indices 16 * with another one. There are only two sub-formats: 17 * 18 * Name Offset Size Description 19 * ------------------------------------------ 20 * format 0 2 sub-table format (1) 21 * offset 2 2 offset to coverage table 22 * delta 4 2 16-bit delta to apply on all 23 * covered glyph indices 24 * 25 * Name Offset Size Description 26 * ------------------------------------------ 27 * format 0 2 sub-table format (2) 28 * offset 2 2 offset to coverage table 29 * count 4 2 coverage table count 30 * substs[] 6 2*count substituted glyph indices, 31 * 32 */ 33 34 static void otl_gsub_lookup1_validate(OTL_Bytes table,OTL_Validator valid)35 otl_gsub_lookup1_validate( OTL_Bytes table, 36 OTL_Validator valid ) 37 { 38 OTL_Bytes p = table; 39 OTL_UInt format; 40 41 OTL_CHECK( 2 ); 42 format = OTL_NEXT_USHORT( p ); 43 switch ( format ) 44 { 45 case 1: 46 { 47 OTL_UInt coverage; 48 49 OTL_CHECK( 4 ); 50 coverage = OTL_NEXT_USHORT( p ); 51 52 otl_coverage_validate( table + coverage, valid ); 53 } 54 break; 55 56 case 2: 57 { 58 OTL_UInt coverage, count; 59 60 OTL_CHECK( 4 ); 61 coverage = OTL_NEXT_USHORT( p ); 62 count = OTL_NEXT_USHORT( p ); 63 64 otl_coverage_validate( table + coverage, valid ); 65 66 OTL_CHECK( 2*count ); 67 68 /* NB: we don't check that there are at most 'count' */ 69 /* elements in the coverage table. This is delayed */ 70 /* to the lookup function... */ 71 } 72 break; 73 74 default: 75 OTL_INVALID_DATA; 76 } 77 } 78 79 80 static OTL_Bool otl_gsub_lookup1_apply(OTL_Bytes table,OTL_Parser parser)81 otl_gsub_lookup1_apply( OTL_Bytes table, 82 OTL_Parser parser ) 83 { 84 OTL_Bytes p = table; 85 OTL_Bytes coverage; 86 OTL_UInt format, gindex, property; 87 OTL_Int index; 88 OTL_Bool subst = 0; 89 90 if ( parser->context_len != 0xFFFF && parser->context_len < 1 ) 91 goto Exit; 92 93 gindex = otl_parser_get_gindex( parser ); 94 95 if ( !otl_parser_check_property( parser, gindex, &property ) ) 96 goto Exit; 97 98 format = OTL_NEXT_USHORT(p); 99 coverage = table + OTL_NEXT_USHORT(p); 100 index = otl_coverage_lookup( coverage, gindex ); 101 102 if ( index >= 0 ) 103 { 104 switch ( format ) 105 { 106 case 1: 107 { 108 OTL_Int delta = OTL_NEXT_SHORT(p); 109 110 gindex = ( gindex + delta ) & 0xFFFF; 111 otl_parser_replace_1( parser, gindex ); 112 subst = 1; 113 } 114 break; 115 116 case 2: 117 { 118 OTL_UInt count = OTL_NEXT_USHORT(p); 119 120 if ( (OTL_UInt) index < count ) 121 { 122 p += index*2; 123 otl_parser_replace_1( parser, OTL_PEEK_USHORT(p) ); 124 subst = 1; 125 } 126 } 127 break; 128 129 default: 130 ; 131 } 132 } 133 Exit: 134 return subst; 135 } 136 137 /************************************************************************/ 138 /************************************************************************/ 139 /***** *****/ 140 /***** GSUB LOOKUP TYPE 2 *****/ 141 /***** *****/ 142 /************************************************************************/ 143 /************************************************************************/ 144 145 /* 146 * 2: Multiple Substitution - Table format(s) 147 * 148 * Replaces a single glyph with one or more glyphs. 149 * 150 * Name Offset Size Description 151 * ----------------------------------------------------------- 152 * format 0 2 sub-table format (1) 153 * offset 2 2 offset to coverage table 154 * count 4 2 coverage table count 155 * sequencess[] 6 2*count offsets to sequence items 156 * 157 * each sequence item has the following format: 158 * 159 * Name Offset Size Description 160 * ----------------------------------------------------------- 161 * count 0 2 number of replacement glyphs 162 * gindices[] 2 2*count string of glyph indices 163 */ 164 165 static void otl_seq_validate(OTL_Bytes table,OTL_Validator valid)166 otl_seq_validate( OTL_Bytes table, 167 OTL_Validator valid ) 168 { 169 OTL_Bytes p = table; 170 OTL_UInt count; 171 172 OTL_CHECK( 2 ); 173 count = OTL_NEXT_USHORT( p ); 174 175 /* XXX: according to the spec, 'count' should be > 0 */ 176 /* we can deal with these cases pretty well however */ 177 178 OTL_CHECK( 2*count ); 179 /* check glyph indices */ 180 } 181 182 183 static void otl_gsub_lookup2_validate(OTL_Bytes table,OTL_Validator valid)184 otl_gsub_lookup2_validate( OTL_Bytes table, 185 OTL_Validator valid ) 186 { 187 OTL_Bytes p = table; 188 OTL_UInt format, coverage; 189 190 OTL_CHECK( 2 ); 191 format = OTL_NEXT_USHORT( p ); 192 switch ( format ) 193 { 194 case 1: 195 { 196 OTL_UInt coverage, seq_count; 197 198 OTL_CHECK( 4 ); 199 coverage = OTL_NEXT_USHORT( p ); 200 seq_count = OTL_NEXT_USHORT( p ); 201 202 otl_coverage_validate( table + coverage, valid ); 203 204 OTL_CHECK( seq_count*2 ); 205 for ( ; seq_count > 0; seq_count-- ) 206 otl_seq_validate( table + OTL_NEXT_USHORT( p ), valid ); 207 } 208 break; 209 210 default: 211 OTL_INVALID_DATA; 212 } 213 } 214 215 216 static OTL_Bool otl_gsub_lookup2_apply(OTL_Bytes table,OTL_Parser parser)217 otl_gsub_lookup2_apply( OTL_Bytes table, 218 OTL_Parser parser ) 219 { 220 OTL_Bytes p = table; 221 OTL_Bytes coverage, sequence; 222 OTL_UInt format, gindex, index, property; 223 OTL_Int index; 224 OTL_Bool subst = 0; 225 226 if ( context_len != 0xFFFF && context_len < 1 ) 227 goto Exit; 228 229 gindex = otl_parser_get_gindex( parser ); 230 231 if ( !otl_parser_check_property( parser, gindex, &property ) ) 232 goto Exit; 233 234 p += 2; /* skip format */ 235 coverage = table + OTL_NEXT_USHORT(p); 236 seq_count = OTL_NEXT_USHORT(p); 237 index = otl_coverage_lookup( coverage, gindex ); 238 239 if ( (OTL_UInt) index >= seq_count ) 240 goto Exit; 241 242 p += index*2; 243 sequence = table + OTL_PEEK_USHORT(p); 244 p = sequence; 245 count = OTL_NEXT_USHORT(p); 246 247 otl_parser_replace_n( parser, count, p ); 248 subst = 1; 249 250 Exit: 251 return subst; 252 } 253 254 /************************************************************************/ 255 /************************************************************************/ 256 /***** *****/ 257 /***** GSUB LOOKUP TYPE 3 *****/ 258 /***** *****/ 259 /************************************************************************/ 260 /************************************************************************/ 261 262 /* 263 * 3: Alternate Substitution - Table format(s) 264 * 265 * Replaces a single glyph by another one taken liberally 266 * in a list of alternatives 267 * 268 * Name Offset Size Description 269 * ----------------------------------------------------------- 270 * format 0 2 sub-table format (1) 271 * offset 2 2 offset to coverage table 272 * count 4 2 coverage table count 273 * alternates[] 6 2*count offsets to alternate items 274 * 275 * each alternate item has the following format: 276 * 277 * Name Offset Size Description 278 * ----------------------------------------------------------- 279 * count 0 2 number of replacement glyphs 280 * gindices[] 2 2*count string of glyph indices, each one 281 * is a valid alternative 282 */ 283 284 static void otl_alternate_set_validate(OTL_Bytes table,OTL_Validator valid)285 otl_alternate_set_validate( OTL_Bytes table, 286 OTL_Validator valid ) 287 { 288 OTL_Bytes p = table; 289 OTL_UInt count; 290 291 OTL_CHECK( 2 ); 292 count = OTL_NEXT_USHORT( p ); 293 294 OTL_CHECK( 2*count ); 295 /* XXX: check glyph indices */ 296 } 297 298 299 static void otl_gsub_lookup3_validate(OTL_Bytes table,OTL_Validator valid)300 otl_gsub_lookup3_validate( OTL_Bytes table, 301 OTL_Validator valid ) 302 { 303 OTL_Bytes p = table; 304 OTL_UInt format, coverage; 305 306 OTL_CHECK( 2 ); 307 format = OTL_NEXT_USHORT( p ); 308 switch ( format ) 309 { 310 case 1: 311 { 312 OTL_UInt coverage, count; 313 314 OTL_CHECK( 4 ); 315 coverage = OTL_NEXT_USHORT( p ); 316 count = OTL_NEXT_USHORT( p ); 317 318 otl_coverage_validate( table + coverage, valid ); 319 320 OTL_CHECK( 2*count ); 321 for ( ; count > 0; count-- ) 322 otl_alternate_set_validate( table + OTL_NEXT_USHORT( p ), valid ); 323 } 324 break; 325 326 default: 327 OTL_INVALID_DATA; 328 } 329 } 330 331 332 static OTL_Bool otl_gsub_lookup3_apply(OTL_Bytes table,OTL_Parser parser)333 otl_gsub_lookup3_apply( OTL_Bytes table, 334 OTL_Parser parser ) 335 { 336 OTL_Bytes p = table; 337 OTL_Bytes coverage, alternates; 338 OTL_UInt format, gindex, index, property; 339 OTL_Int index; 340 OTL_Bool subst = 0; 341 342 OTL_GSUB_Alternate alternate = parser->alternate; 343 344 if ( context_len != 0xFFFF && context_len < 1 ) 345 goto Exit; 346 347 if ( alternate == NULL ) 348 goto Exit; 349 350 gindex = otl_parser_get_gindex( parser ); 351 352 if ( !otl_parser_check_property( parser, gindex, &property ) ) 353 goto Exit; 354 355 p += 2; /* skip format */ 356 coverage = table + OTL_NEXT_USHORT(p); 357 seq_count = OTL_NEXT_USHORT(p); 358 index = otl_coverage_lookup( coverage, gindex ); 359 360 if ( (OTL_UInt) index >= seq_count ) 361 goto Exit; 362 363 p += index*2; 364 alternates = table + OTL_PEEK_USHORT(p); 365 p = alternates; 366 count = OTL_NEXT_USHORT(p); 367 368 gindex = alternate->handler_func( 369 gindex, count, p, alternate->handler_data ); 370 371 otl_parser_replace_1( parser, gindex ); 372 subst = 1; 373 374 Exit: 375 return subst; 376 } 377 378 /************************************************************************/ 379 /************************************************************************/ 380 /***** *****/ 381 /***** GSUB LOOKUP TYPE 4 *****/ 382 /***** *****/ 383 /************************************************************************/ 384 /************************************************************************/ 385 386 static void otl_ligature_validate(OTL_Bytes table,OTL_Validator valid)387 otl_ligature_validate( OTL_Bytes table, 388 OTL_Validator valid ) 389 { 390 OTL_UInt glyph_id, count; 391 392 OTL_CHECK( 4 ); 393 glyph_id = OTL_NEXT_USHORT( p ); 394 count = OTL_NEXT_USHORT( p ); 395 396 if ( count == 0 ) 397 OTL_INVALID_DATA; 398 399 OTL_CHECK( 2*(count-1) ); 400 /* XXX: check glyph indices */ 401 } 402 403 404 static void otl_ligature_set_validate(OTL_Bytes table,OTL_Validator valid)405 otl_ligature_set_validate( OTL_Bytes table, 406 OTL_Validator valid ) 407 { 408 OTL_Bytes p = table; 409 OTL_UInt count; 410 411 OTL_CHECK( 2 ); 412 count = OTL_NEXT_USHORT( p ); 413 414 OTL_CHECK( 2*count ); 415 for ( ; count > 0; count-- ) 416 otl_ligature_validate( table + OTL_NEXT_USHORT( p ), valid ); 417 } 418 419 420 static void otl_gsub_lookup4_validate(OTL_Bytes table,OTL_Validator valid)421 otl_gsub_lookup4_validate( OTL_Bytes table, 422 OTL_Validator valid ) 423 { 424 OTL_Bytes p = table; 425 OTL_UInt format, coverage; 426 427 OTL_CHECK( 2 ); 428 format = OTL_NEXT_USHORT( p ); 429 switch ( format ) 430 { 431 case 1: 432 { 433 OTL_UInt coverage, count; 434 435 OTL_CHECK( 4 ); 436 coverage = OTL_NEXT_USHORT( p ); 437 count = OTL_NEXT_USHORT( p ); 438 439 otl_coverage_validate( table + coverage, valid ); 440 441 OTL_CHECK( 2*count ); 442 for ( ; count > 0; count-- ) 443 otl_ligature_set_validate( table + OTL_NEXT_USHORT( p ), valid ); 444 } 445 break; 446 447 default: 448 OTL_INVALID_DATA; 449 } 450 } 451 452 453 /************************************************************************/ 454 /************************************************************************/ 455 /***** *****/ 456 /***** GSUB LOOKUP TYPE 5 *****/ 457 /***** *****/ 458 /************************************************************************/ 459 /************************************************************************/ 460 461 462 static void otl_sub_rule_validate(OTL_Bytes table,OTL_Validator valid)463 otl_sub_rule_validate( OTL_Bytes table, 464 OTL_Validator valid ) 465 { 466 OTL_Bytes p = table; 467 OTL_UInt glyph_count, subst_count; 468 469 OTL_CHECK( 4 ); 470 glyph_count = OTL_NEXT_USHORT( p ); 471 subst_count = OTL_NEXT_USHORT( p ); 472 473 if ( glyph_count == 0 ) 474 OTL_INVALID_DATA; 475 476 OTL_CHECK( (glyph_count-1)*2 + substcount*4 ); 477 478 /* XXX: check glyph indices and subst lookups */ 479 } 480 481 482 static void otl_sub_rule_set_validate(OTL_Bytes table,OTL_Validator valid)483 otl_sub_rule_set_validate( OTL_Bytes table, 484 OTL_Validator valid ) 485 { 486 OTL_Bytes p = table; 487 OTL_UInt count; 488 489 OTL_CHECK( 2 ); 490 count = OTL_NEXT_USHORT( p ); 491 492 OTL_CHECK( 2*count ); 493 for ( ; count > 0; count-- ) 494 otl_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 495 } 496 497 498 static void otl_sub_class_rule_validate(OTL_Bytes table,OTL_Validator valid)499 otl_sub_class_rule_validate( OTL_Bytes table, 500 OTL_Validator valid ) 501 { 502 OTL_UInt glyph_count, subst_count; 503 504 OTL_CHECK( 4 ); 505 glyph_count = OTL_NEXT_USHORT( p ); 506 subst_count = OTL_NEXT_USHORT( p ); 507 508 if ( glyph_count == 0 ) 509 OTL_INVALID_DATA; 510 511 OTL_CHECK( (glyph_count-1)*2 + substcount*4 ); 512 513 /* XXX: check glyph indices and subst lookups */ 514 } 515 516 517 static void otl_sub_class_rule_set_validate(OTL_Bytes table,OTL_Validator valid)518 otl_sub_class_rule_set_validate( OTL_Bytes table, 519 OTL_Validator valid ) 520 { 521 OTL_Bytes p = table; 522 OTL_UInt count; 523 524 OTL_CHECK( 2 ); 525 count = OTL_NEXT_USHORT( p ); 526 527 OTL_CHECK( 2*count ); 528 for ( ; count > 0; count-- ) 529 otl_sub_class_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 530 } 531 532 533 static void otl_gsub_lookup5_validate(OTL_Bytes table,OTL_Validator valid)534 otl_gsub_lookup5_validate( OTL_Bytes table, 535 OTL_Validator valid ) 536 { 537 OTL_Bytes p = table; 538 OTL_UInt format, coverage; 539 540 OTL_CHECK( 2 ); 541 format = OTL_NEXT_USHORT( p ); 542 switch ( format ) 543 { 544 case 1: 545 { 546 OTL_UInt coverage, count; 547 548 OTL_CHECK( 4 ); 549 coverage = OTL_NEXT_USHORT( p ); 550 count = OTL_NEXT_USHORT( p ); 551 552 otl_coverage_validate( table + coverage, valid ); 553 554 OTL_CHECK( 2*count ); 555 for ( ; count > 0; count-- ) 556 otl_sub_rule_set_validate( table + coverage, valid ); 557 } 558 break; 559 560 case 2: 561 { 562 OTL_UInt coverage, class_def, count; 563 564 OTL_CHECK( 6 ); 565 coverage = OTL_NEXT_USHORT( p ); 566 class_def = OTL_NEXT_USHORT( p ); 567 count = OTL_NEXT_USHORT( p ); 568 569 otl_coverage_validate ( table + coverage, valid ); 570 otl_class_definition_validate( table + class_def, valid ); 571 572 OTL_CHECK( 2*count ); 573 for ( ; count > 0; count-- ) 574 otl_sub_class_rule_set_validate( table + coveragen valid ); 575 } 576 break; 577 578 case 3: 579 { 580 OTL_UInt glyph_count, subst_count, count; 581 582 OTL_CHECK( 4 ); 583 glyph_count = OTL_NEXT_USHORT( p ); 584 subst_count = OTL_NEXT_USHORT( p ); 585 586 OTL_CHECK( 2*glyph_count + 4*subst_count ); 587 for ( count = glyph_count; count > 0; count-- ) 588 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 589 } 590 break; 591 592 default: 593 OTL_INVALID_DATA; 594 } 595 } 596 597 598 /************************************************************************/ 599 /************************************************************************/ 600 /***** *****/ 601 /***** GSUB LOOKUP TYPE 6 *****/ 602 /***** *****/ 603 /************************************************************************/ 604 /************************************************************************/ 605 606 607 static void otl_chain_sub_rule_validate(OTL_Bytes table,OTL_Validator valid)608 otl_chain_sub_rule_validate( OTL_Bytes table, 609 OTL_Validator valid ) 610 { 611 OTL_Bytes p = table; 612 OTL_UInt back_count, input_count, ahead_count, subst_count, count; 613 614 OTL_CHECK( 2 ); 615 back_count = OTL_NEXT_USHORT( p ); 616 617 OTL_CHECK( 2*back_count+2 ); 618 p += 2*back_count; 619 620 input_count = OTL_NEXT_USHORT( p ); 621 if ( input_count == 0 ) 622 OTL_INVALID_DATA; 623 624 OTL_CHECK( 2*input_count ); 625 p += 2*(input_count-1); 626 627 ahead_count = OTL_NEXT_USHORT( p ); 628 OTL_CHECK( 2*ahead_count + 2 ); 629 p += 2*ahead_count; 630 631 count = OTL_NEXT_USHORT( p ); 632 OTL_CHECK( 4*count ); 633 634 /* XXX: check glyph indices and subst lookups */ 635 } 636 637 638 static void otl_chain_sub_rule_set_validate(OTL_Bytes table,OTL_Validator valid)639 otl_chain_sub_rule_set_validate( OTL_Bytes table, 640 OTL_Validator valid ) 641 { 642 OTL_Bytes p = table; 643 OTL_UInt count; 644 645 OTL_CHECK( 2 ); 646 count = OTL_NEXT_USHORT( p ); 647 648 OTL_CHECK( 2*count ); 649 for ( ; count > 0; count-- ) 650 otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 651 } 652 653 654 static void otl_chain_sub_class_rule_validate(OTL_Bytes table,OTL_Validator valid)655 otl_chain_sub_class_rule_validate( OTL_Bytes table, 656 OTL_Validator valid ) 657 { 658 OTL_Bytes p = table; 659 OTL_UInt back_count, input_count, ahead_count, subst_count, count; 660 661 OTL_CHECK( 2 ); 662 back_count = OTL_NEXT_USHORT( p ); 663 664 OTL_CHECK( 2*back_count+2 ); 665 p += 2*back_count; 666 667 input_count = OTL_NEXT_USHORT( p ); 668 if ( input_count == 0 ) 669 OTL_INVALID_DATA; 670 671 OTL_CHECK( 2*input_count ); 672 p += 2*(input_count-1); 673 674 ahead_count = OTL_NEXT_USHORT( p ); 675 OTL_CHECK( 2*ahead_count + 2 ); 676 p += 2*ahead_count; 677 678 count = OTL_NEXT_USHORT( p ); 679 OTL_CHECK( 4*count ); 680 681 /* XXX: check class indices and subst lookups */ 682 } 683 684 685 686 static void otl_chain_sub_class_set_validate(OTL_Bytes table,OTL_Validator valid)687 otl_chain_sub_class_set_validate( OTL_Bytes table, 688 OTL_Validator valid ) 689 { 690 OTL_Bytes p = table; 691 OTL_UInt count; 692 693 OTL_CHECK( 2 ); 694 count = OTL_NEXT_USHORT( p ); 695 696 OTL_CHECK( 2*count ); 697 for ( ; count > 0; count-- ) 698 otl_chain_sub_rule_validate( table + OTL_NEXT_USHORT( p ), valid ); 699 } 700 701 702 static void otl_gsub_lookup6_validate(OTL_Bytes table,OTL_Validator valid)703 otl_gsub_lookup6_validate( OTL_Bytes table, 704 OTL_Validator valid ) 705 { 706 OTL_Bytes p = table; 707 OTL_UInt format, coverage; 708 709 OTL_CHECK( 2 ); 710 format = OTL_NEXT_USHORT( p ); 711 switch ( format ) 712 { 713 case 1: 714 { 715 OTL_UInt coverage, count; 716 717 OTL_CHECK( 4 ); 718 coverage = OTL_NEXT_USHORT( p ); 719 count = OTL_NEXT_USHORT( p ); 720 721 otl_coverage_validate( table + coverage, valid ); 722 723 OTL_CHECK( 2*count ); 724 for ( ; count > 0; count-- ) 725 otl_chain_sub_rule_set_validate( table + coverage, valid ); 726 } 727 break; 728 729 case 2: 730 { 731 OTL_UInt coverage, back_class, input_class, ahead_class, count; 732 733 OTL_CHECK( 10 ); 734 coverage = OTL_NEXT_USHORT( p ); 735 back_class = OTL_NEXT_USHORT( p ); 736 input_class = OTL_NEXT_USHORT( p ); 737 ahead_class = OTL_NEXT_USHORT( p ); 738 count = OTL_NEXT_USHORT( p ); 739 740 otl_coverage_validate( table + coverage, valid ); 741 742 otl_class_definition_validate( table + back_class, valid ); 743 otl_class_definition_validate( table + input_class, valid ); 744 otl_class_definition_validate( table + ahead_class, valid ); 745 746 OTL_CHECK( 2*count ); 747 for ( ; count > 0; count-- ) 748 otl_chain_sub_class_set( table + OTL_NEXT_USHORT( p ), valid ); 749 } 750 break; 751 752 case 3: 753 { 754 OTL_UInt back_count, input_count, ahead_count, subst_count, count; 755 756 OTL_CHECK( 2 ); 757 back_count = OTL_NEXT_USHORT( p ); 758 759 OTL_CHECK( 2*back_count+2 ); 760 for ( count = back_count; count > 0; count-- ) 761 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 762 763 input_count = OTL_NEXT_USHORT( p ); 764 765 OTL_CHECK( 2*input_count+2 ); 766 for ( count = input_count; count > 0; count-- ) 767 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 768 769 ahead_count = OTL_NEXT_USHORT( p ); 770 771 OTL_CHECK( 2*ahead_count+2 ); 772 for ( count = ahead_count; count > 0; count-- ) 773 otl_coverage_validate( table + OTL_NEXT_USHORT( p ), valid ); 774 775 subst_count = OTL_NEXT_USHORT( p ); 776 OTL_CHECK( subst_count*4 ); 777 } 778 break; 779 780 default: 781 OTL_INVALID_DATA; 782 } 783 } 784 785 /************************************************************************/ 786 /************************************************************************/ 787 /***** *****/ 788 /***** GSUB LOOKUP TYPE 6 *****/ 789 /***** *****/ 790 /************************************************************************/ 791 /************************************************************************/ 792 793 static void otl_gsub_lookup7_validate(OTL_Bytes table,OTL_Validator valid)794 otl_gsub_lookup7_validate( OTL_Bytes table, 795 OTL_Validator valid ) 796 { 797 OTL_Bytes p = table; 798 OTL_UInt format, coverage; 799 800 OTL_CHECK( 2 ); 801 format = OTL_NEXT_USHORT( p ); 802 switch ( format ) 803 { 804 case 1: 805 { 806 OTL_UInt lookup_type, lookup_offset; 807 OTL_ValidateFunc validate; 808 809 OTL_CHECK( 6 ); 810 lookup_type = OTL_NEXT_USHORT( p ); 811 lookup_offset = OTL_NEXT_ULONG( p ); 812 813 if ( lookup_type == 0 || lookup_type >= 7 ) 814 OTL_INVALID_DATA; 815 816 validate = otl_gsub_validate_funcs[ lookup_type-1 ]; 817 validate( table + lookup_offset, valid ); 818 } 819 break; 820 821 default: 822 OTL_INVALID_DATA; 823 } 824 } 825 826 827 static const OTL_ValidateFunc otl_gsub_validate_funcs[ 7 ] = 828 { 829 otl_gsub_lookup1_validate, 830 otl_gsub_lookup2_validate, 831 otl_gsub_lookup3_validate, 832 otl_gsub_lookup4_validate, 833 otl_gsub_lookup5_validate, 834 otl_gsub_lookup6_validate 835 }; 836 837 /************************************************************************/ 838 /************************************************************************/ 839 /***** *****/ 840 /***** GSUB TABLE *****/ 841 /***** *****/ 842 /************************************************************************/ 843 /************************************************************************/ 844 845 846 OTL_LOCALDEF( void ) otl_gsub_validate(OTL_Bytes table,OTL_Validator valid)847 otl_gsub_validate( OTL_Bytes table, 848 OTL_Validator valid ) 849 { 850 OTL_Bytes p = table; 851 OTL_UInt scripts, features, lookups; 852 853 OTL_CHECK( 10 ); 854 855 if ( OTL_NEXT_USHORT( p ) != 0x10000UL ) 856 OTL_INVALID_DATA; 857 858 scripts = OTL_NEXT_USHORT( p ); 859 features = OTL_NEXT_USHORT( p ); 860 lookups = OTL_NEXT_USHORT( p ); 861 862 otl_script_list_validate ( table + scripts, valid ); 863 otl_feature_list_validate( table + features, valid ); 864 865 otl_lookup_list_validate( table + lookups, 7, otl_gsub_validate_funcs, 866 valid ); 867 } 868