1 /* 2 * Copyright (C) 1998-2004 David Turner and Werner Lemberg 3 * Copyright (C) 2006 Behdad Esfahbod 4 * 5 * This is part of HarfBuzz, an OpenType Layout engine library. 6 * 7 * Permission is hereby granted, without written agreement and without 8 * license or royalty fees, to use, copy, modify, and distribute this 9 * software and its documentation for any purpose, provided that the 10 * above copyright notice and the following two paragraphs appear in 11 * all copies of this software. 12 * 13 * IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE TO ANY PARTY FOR 14 * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES 15 * ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN 16 * IF THE COPYRIGHT HOLDER HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH 17 * DAMAGE. 18 * 19 * THE COPYRIGHT HOLDER SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, 20 * BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND 21 * FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS 22 * ON AN "AS IS" BASIS, AND THE COPYRIGHT HOLDER HAS NO OBLIGATION TO 23 * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. 24 */ 25 26 #include "harfbuzz-impl.h" 27 #include "harfbuzz-open-private.h" 28 29 30 /*************************** 31 * Script related functions 32 ***************************/ 33 34 35 /* LangSys */ 36 37 static HB_Error Load_LangSys( HB_LangSys* ls, 38 HB_Stream stream ) 39 { 40 HB_Error error; 41 HB_UShort n, count; 42 HB_UShort* fi; 43 44 45 if ( ACCESS_Frame( 6L ) ) 46 return error; 47 48 ls->LookupOrderOffset = GET_UShort(); /* should be 0 */ 49 ls->ReqFeatureIndex = GET_UShort(); 50 count = ls->FeatureCount = GET_UShort(); 51 52 FORGET_Frame(); 53 54 ls->FeatureIndex = NULL; 55 56 if ( ALLOC_ARRAY( ls->FeatureIndex, count, HB_UShort ) ) 57 return error; 58 59 if ( ACCESS_Frame( count * 2L ) ) 60 { 61 FREE( ls->FeatureIndex ); 62 return error; 63 } 64 65 fi = ls->FeatureIndex; 66 67 for ( n = 0; n < count; n++ ) 68 fi[n] = GET_UShort(); 69 70 FORGET_Frame(); 71 72 return HB_Err_Ok; 73 } 74 75 76 static void Free_LangSys( HB_LangSys* ls ) 77 { 78 FREE( ls->FeatureIndex ); 79 } 80 81 82 /* Script */ 83 84 static HB_Error Load_Script( HB_ScriptTable* s, 85 HB_Stream stream ) 86 { 87 HB_Error error; 88 HB_UShort n, m, count; 89 HB_UInt cur_offset, new_offset, base_offset; 90 91 HB_LangSysRecord* lsr; 92 93 94 base_offset = FILE_Pos(); 95 96 if ( ACCESS_Frame( 2L ) ) 97 return error; 98 99 new_offset = GET_UShort() + base_offset; 100 101 FORGET_Frame(); 102 103 if ( new_offset != base_offset ) /* not a NULL offset */ 104 { 105 cur_offset = FILE_Pos(); 106 if ( FILE_Seek( new_offset ) || 107 ( error = Load_LangSys( &s->DefaultLangSys, 108 stream ) ) != HB_Err_Ok ) 109 return error; 110 (void)FILE_Seek( cur_offset ); 111 } 112 else 113 { 114 /* we create a DefaultLangSys table with no entries */ 115 116 s->DefaultLangSys.LookupOrderOffset = 0; 117 s->DefaultLangSys.ReqFeatureIndex = 0xFFFF; 118 s->DefaultLangSys.FeatureCount = 0; 119 s->DefaultLangSys.FeatureIndex = NULL; 120 } 121 122 if ( ACCESS_Frame( 2L ) ) 123 goto Fail2; 124 125 count = s->LangSysCount = GET_UShort(); 126 127 /* safety check; otherwise the official handling of TrueType Open 128 fonts won't work */ 129 130 if ( s->LangSysCount == 0 && s->DefaultLangSys.FeatureCount == 0 ) 131 { 132 error = HB_Err_Not_Covered; 133 goto Fail2; 134 } 135 136 FORGET_Frame(); 137 138 s->LangSysRecord = NULL; 139 140 if ( ALLOC_ARRAY( s->LangSysRecord, count, HB_LangSysRecord ) ) 141 goto Fail2; 142 143 lsr = s->LangSysRecord; 144 145 for ( n = 0; n < count; n++ ) 146 { 147 if ( ACCESS_Frame( 6L ) ) 148 goto Fail1; 149 150 lsr[n].LangSysTag = GET_ULong(); 151 new_offset = GET_UShort() + base_offset; 152 153 FORGET_Frame(); 154 155 cur_offset = FILE_Pos(); 156 if ( FILE_Seek( new_offset ) || 157 ( error = Load_LangSys( &lsr[n].LangSys, stream ) ) != HB_Err_Ok ) 158 goto Fail1; 159 (void)FILE_Seek( cur_offset ); 160 } 161 162 return HB_Err_Ok; 163 164 Fail1: 165 for ( m = 0; m < n; m++ ) 166 Free_LangSys( &lsr[m].LangSys ); 167 168 FREE( s->LangSysRecord ); 169 170 Fail2: 171 Free_LangSys( &s->DefaultLangSys ); 172 return error; 173 } 174 175 176 static void Free_Script( HB_ScriptTable* s ) 177 { 178 HB_UShort n, count; 179 180 HB_LangSysRecord* lsr; 181 182 183 Free_LangSys( &s->DefaultLangSys ); 184 185 if ( s->LangSysRecord ) 186 { 187 count = s->LangSysCount; 188 lsr = s->LangSysRecord; 189 190 for ( n = 0; n < count; n++ ) 191 Free_LangSys( &lsr[n].LangSys ); 192 193 FREE( lsr ); 194 } 195 } 196 197 198 /* ScriptList */ 199 200 HB_INTERNAL HB_Error 201 _HB_OPEN_Load_ScriptList( HB_ScriptList* sl, 202 HB_Stream stream ) 203 { 204 HB_Error error; 205 206 HB_UShort n, script_count; 207 HB_UInt cur_offset, new_offset, base_offset; 208 209 HB_ScriptRecord* sr; 210 211 212 base_offset = FILE_Pos(); 213 214 if ( ACCESS_Frame( 2L ) ) 215 return error; 216 217 script_count = GET_UShort(); 218 219 FORGET_Frame(); 220 221 sl->ScriptRecord = NULL; 222 223 if ( ALLOC_ARRAY( sl->ScriptRecord, script_count, HB_ScriptRecord ) ) 224 return error; 225 226 sr = sl->ScriptRecord; 227 228 sl->ScriptCount= 0; 229 for ( n = 0; n < script_count; n++ ) 230 { 231 if ( ACCESS_Frame( 6L ) ) 232 goto Fail; 233 234 sr[sl->ScriptCount].ScriptTag = GET_ULong(); 235 new_offset = GET_UShort() + base_offset; 236 237 FORGET_Frame(); 238 239 cur_offset = FILE_Pos(); 240 241 if ( FILE_Seek( new_offset ) ) 242 goto Fail; 243 244 error = Load_Script( &sr[sl->ScriptCount].Script, stream ); 245 if ( error == HB_Err_Ok ) 246 sl->ScriptCount += 1; 247 else if ( error != HB_Err_Not_Covered ) 248 goto Fail; 249 250 (void)FILE_Seek( cur_offset ); 251 } 252 253 /* Empty tables are harmless and generated by fontforge. 254 * See http://bugzilla.gnome.org/show_bug.cgi?id=347073 255 */ 256 #if 0 257 if ( sl->ScriptCount == 0 ) 258 { 259 error = ERR(HB_Err_Invalid_SubTable); 260 goto Fail; 261 } 262 #endif 263 264 return HB_Err_Ok; 265 266 Fail: 267 for ( n = 0; n < sl->ScriptCount; n++ ) 268 Free_Script( &sr[n].Script ); 269 270 FREE( sl->ScriptRecord ); 271 return error; 272 } 273 274 275 HB_INTERNAL void 276 _HB_OPEN_Free_ScriptList( HB_ScriptList* sl ) 277 { 278 HB_UShort n, count; 279 280 HB_ScriptRecord* sr; 281 282 283 if ( sl->ScriptRecord ) 284 { 285 count = sl->ScriptCount; 286 sr = sl->ScriptRecord; 287 288 for ( n = 0; n < count; n++ ) 289 Free_Script( &sr[n].Script ); 290 291 FREE( sr ); 292 } 293 } 294 295 296 297 /********************************* 298 * Feature List related functions 299 *********************************/ 300 301 302 /* Feature */ 303 304 static HB_Error Load_Feature( HB_Feature* f, 305 HB_Stream stream ) 306 { 307 HB_Error error; 308 309 HB_UShort n, count; 310 311 HB_UShort* lli; 312 313 314 if ( ACCESS_Frame( 4L ) ) 315 return error; 316 317 f->FeatureParams = GET_UShort(); /* should be 0 */ 318 count = f->LookupListCount = GET_UShort(); 319 320 FORGET_Frame(); 321 322 f->LookupListIndex = NULL; 323 324 if ( ALLOC_ARRAY( f->LookupListIndex, count, HB_UShort ) ) 325 return error; 326 327 lli = f->LookupListIndex; 328 329 if ( ACCESS_Frame( count * 2L ) ) 330 { 331 FREE( f->LookupListIndex ); 332 return error; 333 } 334 335 for ( n = 0; n < count; n++ ) 336 lli[n] = GET_UShort(); 337 338 FORGET_Frame(); 339 340 return HB_Err_Ok; 341 } 342 343 344 static void Free_Feature( HB_Feature* f ) 345 { 346 FREE( f->LookupListIndex ); 347 } 348 349 350 /* FeatureList */ 351 352 HB_INTERNAL HB_Error 353 _HB_OPEN_Load_FeatureList( HB_FeatureList* fl, 354 HB_Stream stream ) 355 { 356 HB_Error error; 357 358 HB_UShort n, m, count; 359 HB_UInt cur_offset, new_offset, base_offset; 360 361 HB_FeatureRecord* fr; 362 363 364 base_offset = FILE_Pos(); 365 366 if ( ACCESS_Frame( 2L ) ) 367 return error; 368 369 count = fl->FeatureCount = GET_UShort(); 370 371 FORGET_Frame(); 372 373 fl->FeatureRecord = NULL; 374 375 if ( ALLOC_ARRAY( fl->FeatureRecord, count, HB_FeatureRecord ) ) 376 return error; 377 if ( ALLOC_ARRAY( fl->ApplyOrder, count, HB_UShort ) ) 378 goto Fail2; 379 380 fl->ApplyCount = 0; 381 382 fr = fl->FeatureRecord; 383 384 for ( n = 0; n < count; n++ ) 385 { 386 if ( ACCESS_Frame( 6L ) ) 387 goto Fail1; 388 389 fr[n].FeatureTag = GET_ULong(); 390 new_offset = GET_UShort() + base_offset; 391 392 FORGET_Frame(); 393 394 cur_offset = FILE_Pos(); 395 if ( FILE_Seek( new_offset ) || 396 ( error = Load_Feature( &fr[n].Feature, stream ) ) != HB_Err_Ok ) 397 goto Fail1; 398 (void)FILE_Seek( cur_offset ); 399 } 400 401 return HB_Err_Ok; 402 403 Fail1: 404 for ( m = 0; m < n; m++ ) 405 Free_Feature( &fr[m].Feature ); 406 407 FREE( fl->ApplyOrder ); 408 409 Fail2: 410 FREE( fl->FeatureRecord ); 411 412 return error; 413 } 414 415 416 HB_INTERNAL void 417 _HB_OPEN_Free_FeatureList( HB_FeatureList* fl ) 418 { 419 HB_UShort n, count; 420 421 HB_FeatureRecord* fr; 422 423 424 if ( fl->FeatureRecord ) 425 { 426 count = fl->FeatureCount; 427 fr = fl->FeatureRecord; 428 429 for ( n = 0; n < count; n++ ) 430 Free_Feature( &fr[n].Feature ); 431 432 FREE( fr ); 433 } 434 435 FREE( fl->ApplyOrder ); 436 } 437 438 439 440 /******************************** 441 * Lookup List related functions 442 ********************************/ 443 444 /* the subroutines of the following two functions are defined in 445 ftxgsub.c and ftxgpos.c respectively */ 446 447 448 /* SubTable */ 449 450 static HB_Error Load_SubTable( HB_SubTable* st, 451 HB_Stream stream, 452 HB_Type table_type, 453 HB_UShort lookup_type ) 454 { 455 if ( table_type == HB_Type_GSUB ) 456 return _HB_GSUB_Load_SubTable ( &st->st.gsub, stream, lookup_type ); 457 else 458 return _HB_GPOS_Load_SubTable ( &st->st.gpos, stream, lookup_type ); 459 } 460 461 462 static void Free_SubTable( HB_SubTable* st, 463 HB_Type table_type, 464 HB_UShort lookup_type ) 465 { 466 if ( table_type == HB_Type_GSUB ) 467 _HB_GSUB_Free_SubTable ( &st->st.gsub, lookup_type ); 468 else 469 _HB_GPOS_Free_SubTable ( &st->st.gpos, lookup_type ); 470 } 471 472 473 /* Lookup */ 474 475 static HB_Error Load_Lookup( HB_Lookup* l, 476 HB_Stream stream, 477 HB_Type type ) 478 { 479 HB_Error error; 480 481 HB_UShort n, m, count; 482 HB_UInt cur_offset, new_offset, base_offset; 483 484 HB_SubTable* st; 485 486 HB_Bool is_extension = FALSE; 487 488 489 base_offset = FILE_Pos(); 490 491 if ( ACCESS_Frame( 6L ) ) 492 return error; 493 494 l->LookupType = GET_UShort(); 495 l->LookupFlag = GET_UShort(); 496 count = l->SubTableCount = GET_UShort(); 497 498 FORGET_Frame(); 499 500 l->SubTable = NULL; 501 502 if ( ALLOC_ARRAY( l->SubTable, count, HB_SubTable ) ) 503 return error; 504 505 st = l->SubTable; 506 507 if ( ( type == HB_Type_GSUB && l->LookupType == HB_GSUB_LOOKUP_EXTENSION ) || 508 ( type == HB_Type_GPOS && l->LookupType == HB_GPOS_LOOKUP_EXTENSION ) ) 509 is_extension = TRUE; 510 511 for ( n = 0; n < count; n++ ) 512 { 513 if ( ACCESS_Frame( 2L ) ) 514 goto Fail; 515 516 new_offset = GET_UShort() + base_offset; 517 518 FORGET_Frame(); 519 520 cur_offset = FILE_Pos(); 521 522 if ( is_extension ) 523 { 524 if ( FILE_Seek( new_offset ) || ACCESS_Frame( 8L ) ) 525 goto Fail; 526 527 if (GET_UShort() != 1) /* format should be 1 */ 528 goto Fail; 529 530 l->LookupType = GET_UShort(); 531 new_offset += GET_ULong(); 532 533 FORGET_Frame(); 534 } 535 536 if ( FILE_Seek( new_offset ) || 537 ( error = Load_SubTable( &st[n], stream, 538 type, l->LookupType ) ) != HB_Err_Ok ) 539 goto Fail; 540 (void)FILE_Seek( cur_offset ); 541 } 542 543 return HB_Err_Ok; 544 545 Fail: 546 for ( m = 0; m < n; m++ ) 547 Free_SubTable( &st[m], type, l->LookupType ); 548 549 FREE( l->SubTable ); 550 return error; 551 } 552 553 554 static void Free_Lookup( HB_Lookup* l, 555 HB_Type type) 556 { 557 HB_UShort n, count; 558 559 HB_SubTable* st; 560 561 562 if ( l->SubTable ) 563 { 564 count = l->SubTableCount; 565 st = l->SubTable; 566 567 for ( n = 0; n < count; n++ ) 568 Free_SubTable( &st[n], type, l->LookupType ); 569 570 FREE( st ); 571 } 572 } 573 574 575 /* LookupList */ 576 577 HB_INTERNAL HB_Error 578 _HB_OPEN_Load_LookupList( HB_LookupList* ll, 579 HB_Stream stream, 580 HB_Type type ) 581 { 582 HB_Error error; 583 584 HB_UShort n, m, count; 585 HB_UInt cur_offset, new_offset, base_offset; 586 587 HB_Lookup* l; 588 589 590 base_offset = FILE_Pos(); 591 592 if ( ACCESS_Frame( 2L ) ) 593 return error; 594 595 count = ll->LookupCount = GET_UShort(); 596 597 FORGET_Frame(); 598 599 ll->Lookup = NULL; 600 601 if ( ALLOC_ARRAY( ll->Lookup, count, HB_Lookup ) ) 602 return error; 603 if ( ALLOC_ARRAY( ll->Properties, count, HB_UInt ) ) 604 goto Fail2; 605 606 l = ll->Lookup; 607 608 for ( n = 0; n < count; n++ ) 609 { 610 if ( ACCESS_Frame( 2L ) ) 611 goto Fail1; 612 613 new_offset = GET_UShort() + base_offset; 614 615 FORGET_Frame(); 616 617 cur_offset = FILE_Pos(); 618 if ( FILE_Seek( new_offset ) || 619 ( error = Load_Lookup( &l[n], stream, type ) ) != HB_Err_Ok ) 620 goto Fail1; 621 (void)FILE_Seek( cur_offset ); 622 } 623 624 return HB_Err_Ok; 625 626 Fail1: 627 FREE( ll->Properties ); 628 629 for ( m = 0; m < n; m++ ) 630 Free_Lookup( &l[m], type ); 631 632 Fail2: 633 FREE( ll->Lookup ); 634 return error; 635 } 636 637 638 HB_INTERNAL void 639 _HB_OPEN_Free_LookupList( HB_LookupList* ll, 640 HB_Type type ) 641 { 642 HB_UShort n, count; 643 644 HB_Lookup* l; 645 646 647 FREE( ll->Properties ); 648 649 if ( ll->Lookup ) 650 { 651 count = ll->LookupCount; 652 l = ll->Lookup; 653 654 for ( n = 0; n < count; n++ ) 655 Free_Lookup( &l[n], type ); 656 657 FREE( l ); 658 } 659 } 660 661 662 663 /***************************** 664 * Coverage related functions 665 *****************************/ 666 667 668 /* CoverageFormat1 */ 669 670 static HB_Error Load_Coverage1( HB_CoverageFormat1* cf1, 671 HB_Stream stream ) 672 { 673 HB_Error error; 674 675 HB_UShort n, count; 676 677 HB_UShort* ga; 678 679 680 if ( ACCESS_Frame( 2L ) ) 681 return error; 682 683 count = cf1->GlyphCount = GET_UShort(); 684 685 FORGET_Frame(); 686 687 cf1->GlyphArray = NULL; 688 689 if ( ALLOC_ARRAY( cf1->GlyphArray, count, HB_UShort ) ) 690 return error; 691 692 ga = cf1->GlyphArray; 693 694 if ( ACCESS_Frame( count * 2L ) ) 695 { 696 FREE( cf1->GlyphArray ); 697 return error; 698 } 699 700 for ( n = 0; n < count; n++ ) 701 ga[n] = GET_UShort(); 702 703 FORGET_Frame(); 704 705 return HB_Err_Ok; 706 } 707 708 709 static void Free_Coverage1( HB_CoverageFormat1* cf1) 710 { 711 FREE( cf1->GlyphArray ); 712 } 713 714 715 /* CoverageFormat2 */ 716 717 static HB_Error Load_Coverage2( HB_CoverageFormat2* cf2, 718 HB_Stream stream ) 719 { 720 HB_Error error; 721 722 HB_UShort n, count; 723 724 HB_RangeRecord* rr; 725 726 727 if ( ACCESS_Frame( 2L ) ) 728 return error; 729 730 count = cf2->RangeCount = GET_UShort(); 731 732 FORGET_Frame(); 733 734 cf2->RangeRecord = NULL; 735 736 if ( ALLOC_ARRAY( cf2->RangeRecord, count, HB_RangeRecord ) ) 737 return error; 738 739 rr = cf2->RangeRecord; 740 741 if ( ACCESS_Frame( count * 6L ) ) 742 goto Fail; 743 744 for ( n = 0; n < count; n++ ) 745 { 746 rr[n].Start = GET_UShort(); 747 rr[n].End = GET_UShort(); 748 rr[n].StartCoverageIndex = GET_UShort(); 749 750 /* sanity check; we are limited to 16bit integers */ 751 if ( rr[n].Start > rr[n].End || 752 ( rr[n].End - rr[n].Start + (long)rr[n].StartCoverageIndex ) >= 753 0x10000L ) 754 { 755 error = ERR(HB_Err_Invalid_SubTable); 756 goto Fail; 757 } 758 } 759 760 FORGET_Frame(); 761 762 return HB_Err_Ok; 763 764 Fail: 765 FREE( cf2->RangeRecord ); 766 return error; 767 } 768 769 770 static void Free_Coverage2( HB_CoverageFormat2* cf2 ) 771 { 772 FREE( cf2->RangeRecord ); 773 } 774 775 776 HB_INTERNAL HB_Error 777 _HB_OPEN_Load_Coverage( HB_Coverage* c, 778 HB_Stream stream ) 779 { 780 HB_Error error; 781 782 if ( ACCESS_Frame( 2L ) ) 783 return error; 784 785 c->CoverageFormat = GET_UShort(); 786 787 FORGET_Frame(); 788 789 switch ( c->CoverageFormat ) 790 { 791 case 1: return Load_Coverage1( &c->cf.cf1, stream ); 792 case 2: return Load_Coverage2( &c->cf.cf2, stream ); 793 default: return ERR(HB_Err_Invalid_SubTable_Format); 794 } 795 796 return HB_Err_Ok; /* never reached */ 797 } 798 799 800 HB_INTERNAL void 801 _HB_OPEN_Free_Coverage( HB_Coverage* c ) 802 { 803 switch ( c->CoverageFormat ) 804 { 805 case 1: Free_Coverage1( &c->cf.cf1 ); break; 806 case 2: Free_Coverage2( &c->cf.cf2 ); break; 807 default: break; 808 } 809 } 810 811 812 static HB_Error Coverage_Index1( HB_CoverageFormat1* cf1, 813 HB_UShort glyphID, 814 HB_UShort* index ) 815 { 816 HB_UShort min, max, new_min, new_max, middle; 817 818 HB_UShort* array = cf1->GlyphArray; 819 820 821 /* binary search */ 822 823 if ( cf1->GlyphCount == 0 ) 824 return HB_Err_Not_Covered; 825 826 new_min = 0; 827 new_max = cf1->GlyphCount - 1; 828 829 do 830 { 831 min = new_min; 832 max = new_max; 833 834 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid 835 overflow and rounding errors */ 836 837 middle = max - ( ( max - min ) >> 1 ); 838 839 if ( glyphID == array[middle] ) 840 { 841 *index = middle; 842 return HB_Err_Ok; 843 } 844 else if ( glyphID < array[middle] ) 845 { 846 if ( middle == min ) 847 break; 848 new_max = middle - 1; 849 } 850 else 851 { 852 if ( middle == max ) 853 break; 854 new_min = middle + 1; 855 } 856 } while ( min < max ); 857 858 return HB_Err_Not_Covered; 859 } 860 861 862 static HB_Error Coverage_Index2( HB_CoverageFormat2* cf2, 863 HB_UShort glyphID, 864 HB_UShort* index ) 865 { 866 HB_UShort min, max, new_min, new_max, middle; 867 868 HB_RangeRecord* rr = cf2->RangeRecord; 869 870 871 /* binary search */ 872 873 if ( cf2->RangeCount == 0 ) 874 return HB_Err_Not_Covered; 875 876 new_min = 0; 877 new_max = cf2->RangeCount - 1; 878 879 do 880 { 881 min = new_min; 882 max = new_max; 883 884 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid 885 overflow and rounding errors */ 886 887 middle = max - ( ( max - min ) >> 1 ); 888 889 if ( glyphID >= rr[middle].Start && glyphID <= rr[middle].End ) 890 { 891 *index = rr[middle].StartCoverageIndex + glyphID - rr[middle].Start; 892 return HB_Err_Ok; 893 } 894 else if ( glyphID < rr[middle].Start ) 895 { 896 if ( middle == min ) 897 break; 898 new_max = middle - 1; 899 } 900 else 901 { 902 if ( middle == max ) 903 break; 904 new_min = middle + 1; 905 } 906 } while ( min < max ); 907 908 return HB_Err_Not_Covered; 909 } 910 911 912 HB_INTERNAL HB_Error 913 _HB_OPEN_Coverage_Index( HB_Coverage* c, 914 HB_UShort glyphID, 915 HB_UShort* index ) 916 { 917 switch ( c->CoverageFormat ) 918 { 919 case 1: return Coverage_Index1( &c->cf.cf1, glyphID, index ); 920 case 2: return Coverage_Index2( &c->cf.cf2, glyphID, index ); 921 default: return ERR(HB_Err_Invalid_SubTable_Format); 922 } 923 924 return HB_Err_Ok; /* never reached */ 925 } 926 927 928 929 /************************************* 930 * Class Definition related functions 931 *************************************/ 932 933 934 /* ClassDefFormat1 */ 935 936 static HB_Error Load_ClassDef1( HB_ClassDefinition* cd, 937 HB_UShort limit, 938 HB_Stream stream ) 939 { 940 HB_Error error; 941 942 HB_UShort n, count; 943 944 HB_UShort* cva; 945 946 HB_ClassDefFormat1* cdf1; 947 948 949 cdf1 = &cd->cd.cd1; 950 951 if ( ACCESS_Frame( 4L ) ) 952 return error; 953 954 cdf1->StartGlyph = GET_UShort(); 955 count = cdf1->GlyphCount = GET_UShort(); 956 957 FORGET_Frame(); 958 959 /* sanity check; we are limited to 16bit integers */ 960 961 if ( cdf1->StartGlyph + (long)count >= 0x10000L ) 962 return ERR(HB_Err_Invalid_SubTable); 963 964 cdf1->ClassValueArray = NULL; 965 966 if ( ALLOC_ARRAY( cdf1->ClassValueArray, count, HB_UShort ) ) 967 return error; 968 969 cva = cdf1->ClassValueArray; 970 971 if ( ACCESS_Frame( count * 2L ) ) 972 goto Fail; 973 974 for ( n = 0; n < count; n++ ) 975 { 976 cva[n] = GET_UShort(); 977 if ( cva[n] >= limit ) 978 { 979 error = ERR(HB_Err_Invalid_SubTable); 980 goto Fail; 981 } 982 } 983 984 FORGET_Frame(); 985 986 return HB_Err_Ok; 987 988 Fail: 989 FREE( cva ); 990 991 return error; 992 } 993 994 995 static void Free_ClassDef1( HB_ClassDefFormat1* cdf1 ) 996 { 997 FREE( cdf1->ClassValueArray ); 998 } 999 1000 1001 /* ClassDefFormat2 */ 1002 1003 static HB_Error Load_ClassDef2( HB_ClassDefinition* cd, 1004 HB_UShort limit, 1005 HB_Stream stream ) 1006 { 1007 HB_Error error; 1008 1009 HB_UShort n, count; 1010 1011 HB_ClassRangeRecord* crr; 1012 1013 HB_ClassDefFormat2* cdf2; 1014 1015 1016 cdf2 = &cd->cd.cd2; 1017 1018 if ( ACCESS_Frame( 2L ) ) 1019 return error; 1020 1021 count = GET_UShort(); 1022 cdf2->ClassRangeCount = 0; /* zero for now. we fill with the number of good entries later */ 1023 1024 FORGET_Frame(); 1025 1026 cdf2->ClassRangeRecord = NULL; 1027 1028 if ( ALLOC_ARRAY( cdf2->ClassRangeRecord, count, HB_ClassRangeRecord ) ) 1029 return error; 1030 1031 crr = cdf2->ClassRangeRecord; 1032 1033 if ( ACCESS_Frame( count * 6L ) ) 1034 goto Fail; 1035 1036 for ( n = 0; n < count; n++ ) 1037 { 1038 crr[n].Start = GET_UShort(); 1039 crr[n].End = GET_UShort(); 1040 crr[n].Class = GET_UShort(); 1041 1042 /* sanity check */ 1043 1044 if ( crr[n].Start > crr[n].End || 1045 crr[n].Class >= limit ) 1046 { 1047 /* XXX 1048 * Corrupt entry. Skip it. 1049 * This is hit by Nafees Nastaliq font for example 1050 */ 1051 n--; 1052 count--; 1053 } 1054 } 1055 1056 FORGET_Frame(); 1057 1058 cdf2->ClassRangeCount = count; 1059 1060 return HB_Err_Ok; 1061 1062 Fail: 1063 FREE( crr ); 1064 1065 return error; 1066 } 1067 1068 1069 static void Free_ClassDef2( HB_ClassDefFormat2* cdf2 ) 1070 { 1071 FREE( cdf2->ClassRangeRecord ); 1072 } 1073 1074 1075 /* ClassDefinition */ 1076 1077 HB_INTERNAL HB_Error 1078 _HB_OPEN_Load_ClassDefinition( HB_ClassDefinition* cd, 1079 HB_UShort limit, 1080 HB_Stream stream ) 1081 { 1082 HB_Error error; 1083 1084 if ( ACCESS_Frame( 2L ) ) 1085 return error; 1086 1087 cd->ClassFormat = GET_UShort(); 1088 1089 FORGET_Frame(); 1090 1091 switch ( cd->ClassFormat ) 1092 { 1093 case 1: error = Load_ClassDef1( cd, limit, stream ); break; 1094 case 2: error = Load_ClassDef2( cd, limit, stream ); break; 1095 default: error = ERR(HB_Err_Invalid_SubTable_Format); break; 1096 } 1097 1098 if ( error ) 1099 return error; 1100 1101 cd->loaded = TRUE; 1102 1103 return HB_Err_Ok; 1104 } 1105 1106 1107 static HB_Error 1108 _HB_OPEN_Load_EmptyClassDefinition( HB_ClassDefinition* cd ) 1109 { 1110 HB_Error error; 1111 1112 cd->ClassFormat = 1; /* Meaningless */ 1113 1114 if ( ALLOC_ARRAY( cd->cd.cd1.ClassValueArray, 1, HB_UShort ) ) 1115 return error; 1116 1117 cd->loaded = TRUE; 1118 1119 return HB_Err_Ok; 1120 } 1121 1122 HB_INTERNAL HB_Error 1123 _HB_OPEN_Load_EmptyOrClassDefinition( HB_ClassDefinition* cd, 1124 HB_UShort limit, 1125 HB_UInt class_offset, 1126 HB_UInt base_offset, 1127 HB_Stream stream ) 1128 { 1129 HB_Error error; 1130 HB_UInt cur_offset; 1131 1132 cur_offset = FILE_Pos(); 1133 1134 if ( class_offset ) 1135 { 1136 if ( !FILE_Seek( class_offset + base_offset ) ) 1137 error = _HB_OPEN_Load_ClassDefinition( cd, limit, stream ); 1138 } 1139 else 1140 error = _HB_OPEN_Load_EmptyClassDefinition ( cd ); 1141 1142 if (error == HB_Err_Ok) 1143 (void)FILE_Seek( cur_offset ); /* Changes error as a side-effect */ 1144 1145 return error; 1146 } 1147 1148 HB_INTERNAL void 1149 _HB_OPEN_Free_ClassDefinition( HB_ClassDefinition* cd ) 1150 { 1151 if ( !cd->loaded ) 1152 return; 1153 1154 switch ( cd->ClassFormat ) 1155 { 1156 case 1: Free_ClassDef1( &cd->cd.cd1 ); break; 1157 case 2: Free_ClassDef2( &cd->cd.cd2 ); break; 1158 default: break; 1159 } 1160 } 1161 1162 1163 static HB_Error Get_Class1( HB_ClassDefFormat1* cdf1, 1164 HB_UShort glyphID, 1165 HB_UShort* klass, 1166 HB_UShort* index ) 1167 { 1168 HB_UShort* cva = cdf1->ClassValueArray; 1169 1170 1171 if ( index ) 1172 *index = 0; 1173 1174 if ( glyphID >= cdf1->StartGlyph && 1175 glyphID < cdf1->StartGlyph + cdf1->GlyphCount ) 1176 { 1177 *klass = cva[glyphID - cdf1->StartGlyph]; 1178 return HB_Err_Ok; 1179 } 1180 else 1181 { 1182 *klass = 0; 1183 return HB_Err_Not_Covered; 1184 } 1185 } 1186 1187 1188 /* we need the index value of the last searched class range record 1189 in case of failure for constructed GDEF tables */ 1190 1191 static HB_Error Get_Class2( HB_ClassDefFormat2* cdf2, 1192 HB_UShort glyphID, 1193 HB_UShort* klass, 1194 HB_UShort* index ) 1195 { 1196 HB_Error error = HB_Err_Ok; 1197 HB_UShort min, max, new_min, new_max, middle; 1198 1199 HB_ClassRangeRecord* crr = cdf2->ClassRangeRecord; 1200 1201 1202 /* binary search */ 1203 1204 if ( cdf2->ClassRangeCount == 0 ) 1205 { 1206 *klass = 0; 1207 if ( index ) 1208 *index = 0; 1209 1210 return HB_Err_Not_Covered; 1211 } 1212 1213 new_min = 0; 1214 new_max = cdf2->ClassRangeCount - 1; 1215 1216 do 1217 { 1218 min = new_min; 1219 max = new_max; 1220 1221 /* we use (min + max) / 2 = max - (max - min) / 2 to avoid 1222 overflow and rounding errors */ 1223 1224 middle = max - ( ( max - min ) >> 1 ); 1225 1226 if ( glyphID >= crr[middle].Start && glyphID <= crr[middle].End ) 1227 { 1228 *klass = crr[middle].Class; 1229 error = HB_Err_Ok; 1230 break; 1231 } 1232 else if ( glyphID < crr[middle].Start ) 1233 { 1234 if ( middle == min ) 1235 { 1236 *klass = 0; 1237 error = HB_Err_Not_Covered; 1238 break; 1239 } 1240 new_max = middle - 1; 1241 } 1242 else 1243 { 1244 if ( middle == max ) 1245 { 1246 *klass = 0; 1247 error = HB_Err_Not_Covered; 1248 break; 1249 } 1250 new_min = middle + 1; 1251 } 1252 } while ( min < max ); 1253 1254 if ( index ) 1255 *index = middle; 1256 1257 return error; 1258 } 1259 1260 1261 HB_INTERNAL HB_Error 1262 _HB_OPEN_Get_Class( HB_ClassDefinition* cd, 1263 HB_UShort glyphID, 1264 HB_UShort* klass, 1265 HB_UShort* index ) 1266 { 1267 switch ( cd->ClassFormat ) 1268 { 1269 case 1: return Get_Class1( &cd->cd.cd1, glyphID, klass, index ); 1270 case 2: return Get_Class2( &cd->cd.cd2, glyphID, klass, index ); 1271 default: return ERR(HB_Err_Invalid_SubTable_Format); 1272 } 1273 1274 return HB_Err_Ok; /* never reached */ 1275 } 1276 1277 1278 1279 /*************************** 1280 * Device related functions 1281 ***************************/ 1282 1283 1284 HB_INTERNAL HB_Error 1285 _HB_OPEN_Load_Device( HB_Device** device, 1286 HB_Stream stream ) 1287 { 1288 HB_Device* d; 1289 HB_Error error; 1290 1291 HB_UShort n, count; 1292 1293 HB_UShort* dv; 1294 1295 1296 if ( ACCESS_Frame( 6L ) ) 1297 return error; 1298 1299 if ( ALLOC( *device, sizeof(HB_Device)) ) 1300 { 1301 *device = 0; 1302 return error; 1303 } 1304 1305 d = *device; 1306 1307 d->StartSize = GET_UShort(); 1308 d->EndSize = GET_UShort(); 1309 d->DeltaFormat = GET_UShort(); 1310 1311 FORGET_Frame(); 1312 1313 d->DeltaValue = NULL; 1314 1315 if ( d->StartSize > d->EndSize || 1316 d->DeltaFormat == 0 || d->DeltaFormat > 3 ) 1317 { 1318 /* XXX 1319 * I've seen fontforge generate DeltaFormat == 0. 1320 * Just return Ok and let the NULL DeltaValue disable 1321 * this table. 1322 */ 1323 return HB_Err_Ok; 1324 } 1325 1326 count = ( ( d->EndSize - d->StartSize + 1 ) >> 1327 ( 4 - d->DeltaFormat ) ) + 1; 1328 1329 if ( ALLOC_ARRAY( d->DeltaValue, count, HB_UShort ) ) 1330 { 1331 FREE( *device ); 1332 *device = 0; 1333 return error; 1334 } 1335 1336 if ( ACCESS_Frame( count * 2L ) ) 1337 { 1338 FREE( d->DeltaValue ); 1339 FREE( *device ); 1340 *device = 0; 1341 return error; 1342 } 1343 1344 dv = d->DeltaValue; 1345 1346 for ( n = 0; n < count; n++ ) 1347 dv[n] = GET_UShort(); 1348 1349 FORGET_Frame(); 1350 1351 return HB_Err_Ok; 1352 } 1353 1354 1355 HB_INTERNAL void 1356 _HB_OPEN_Free_Device( HB_Device* d ) 1357 { 1358 if ( d ) 1359 { 1360 FREE( d->DeltaValue ); 1361 FREE( d ); 1362 } 1363 } 1364 1365 1366 /* Since we have the delta values stored in compressed form, we must 1367 uncompress it now. To simplify the interface, the function always 1368 returns a meaningful value in `value'; the error is just for 1369 information. 1370 | | 1371 format = 1: 0011223344556677|8899101112131415|... 1372 | | 1373 byte 1 byte 2 1374 1375 00: (byte >> 14) & mask 1376 11: (byte >> 12) & mask 1377 ... 1378 1379 mask = 0x0003 1380 | | 1381 format = 2: 0000111122223333|4444555566667777|... 1382 | | 1383 byte 1 byte 2 1384 1385 0000: (byte >> 12) & mask 1386 1111: (byte >> 8) & mask 1387 ... 1388 1389 mask = 0x000F 1390 | | 1391 format = 3: 0000000011111111|2222222233333333|... 1392 | | 1393 byte 1 byte 2 1394 1395 00000000: (byte >> 8) & mask 1396 11111111: (byte >> 0) & mask 1397 .... 1398 1399 mask = 0x00FF */ 1400 1401 HB_INTERNAL HB_Error 1402 _HB_OPEN_Get_Device( HB_Device* d, 1403 HB_UShort size, 1404 HB_Short* value ) 1405 { 1406 HB_UShort byte, bits, mask, s; 1407 1408 if ( d && d->DeltaValue && size >= d->StartSize && size <= d->EndSize ) 1409 { 1410 HB_UShort f = d->DeltaFormat; 1411 s = size - d->StartSize; 1412 byte = d->DeltaValue[s >> ( 4 - f )]; 1413 bits = byte >> ( 16 - ( ( s % ( 1 << ( 4 - f ) ) + 1 ) << f ) ); 1414 mask = 0xFFFF >> ( 16 - ( 1 << f ) ); 1415 1416 *value = (HB_Short)( bits & mask ); 1417 1418 /* conversion to a signed value */ 1419 1420 if ( *value >= ( ( mask + 1 ) >> 1 ) ) 1421 *value -= mask + 1; 1422 1423 return HB_Err_Ok; 1424 } 1425 else 1426 { 1427 *value = 0; 1428 return HB_Err_Not_Covered; 1429 } 1430 } 1431 1432 1433 /* END */ 1434