cidparse.c revision e1d5dd78f4a75697a2584deac4af71dd21939f6a
1/******************************************************************* 2 * 3 * cidparse.c 2.0 4 * 5 * CID-keyed Type1 parser. 6 * 7 * Copyright 1996-1998 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 * The Type 1 parser is in charge of the following: 17 * 18 * - provide an implementation of a growing sequence of 19 * objects called a T1_Table (used to build various tables 20 * needed by the loader). 21 * 22 * - opening .pfb and .pfa files to extract their top-level 23 * and private dictionaries 24 * 25 * - read numbers, arrays & strings from any dictionary 26 * 27 * See "t1load.c" to see how data is loaded from the font file 28 * 29 ******************************************************************/ 30 31#include <freetype/internal/ftdebug.h> 32#include <freetype/internal/ftcalc.h> 33#include <freetype/internal/ftobjs.h> 34#include <freetype/internal/ftstream.h> 35#include <freetype/internal/t1errors.h> 36#include <cidparse.h> 37 38#undef FT_COMPONENT 39#define FT_COMPONENT trace_t1load 40 41#if 0 42/*************************************************************************/ 43/*************************************************************************/ 44/*************************************************************************/ 45/***** *****/ 46/***** IMPLEMENTATION OF T1_TABLE OBJECT *****/ 47/***** *****/ 48/***** *****/ 49/*************************************************************************/ 50/*************************************************************************/ 51/*************************************************************************/ 52 53 54/*************************************************************************/ 55/* */ 56/* <Function> T1_New_Table */ 57/* */ 58/* <Description> */ 59/* Initialise a T1_Table. */ 60/* */ 61/* <Input> */ 62/* table :: address of target table */ 63/* count :: table size = maximum number of elements */ 64/* memory :: memory object to use for all subsequent reallocations */ 65/* */ 66/* <Return> */ 67/* Error code. 0 means success */ 68/* */ 69 70 LOCAL_FUNC 71 FT_Error T1_New_Table( T1_Table* table, 72 FT_Int count, 73 FT_Memory memory ) 74 { 75 FT_Error error; 76 77 table->memory = memory; 78 if ( ALLOC_ARRAY( table->elements, count, FT_Byte* ) || 79 ALLOC_ARRAY( table->lengths, count, FT_Byte* ) ) 80 goto Exit; 81 82 table->max_elems = count; 83 table->init = 0xdeadbeef; 84 table->num_elems = 0; 85 table->block = 0; 86 table->capacity = 0; 87 table->cursor = 0; 88 89 Exit: 90 if (error) FREE(table->elements); 91 92 return error; 93 } 94 95 96 97/*************************************************************************/ 98/* */ 99/* <Function> T1_Add_Table */ 100/* */ 101/* <Description> */ 102/* Adds an object to a T1_Table, possibly growing its memory block */ 103/* */ 104/* <Input> */ 105/* table :: target table */ 106/* index :: index of object in table */ 107/* object :: address of object to copy in memory */ 108/* length :: length in bytes of source object */ 109/* */ 110/* <Return> */ 111/* Error code. 0 means success. An error is returned when a */ 112/* realloc failed.. */ 113/* */ 114 115 116 static void shift_elements( T1_Table* table, FT_Byte* old_base ) 117 { 118 FT_Long delta = table->block - old_base; 119 FT_Byte** offset = table->elements; 120 FT_Byte** limit = offset + table->max_elems; 121 122 if (delta) 123 for ( ; offset < limit; offset++ ) 124 { 125 if (offset[0]) 126 offset[0] += delta; 127 } 128 } 129 130 static 131 FT_Error reallocate_t1_table( T1_Table* table, 132 FT_Int new_size ) 133 { 134 FT_Memory memory = table->memory; 135 FT_Byte* old_base = table->block; 136 FT_Error error; 137 138 /* realloc the base block */ 139 if ( REALLOC( table->block, table->capacity, new_size ) ) 140 return error; 141 142 table->capacity = new_size; 143 144 /* shift all offsets when needed */ 145 if (old_base) 146 shift_elements( table, old_base ); 147 148 return T1_Err_Ok; 149 } 150 151 152 153 LOCAL_FUNC 154 FT_Error T1_Add_Table( T1_Table* table, 155 FT_Int index, 156 void* object, 157 FT_Int length ) 158 { 159 if (index < 0 || index > table->max_elems) 160 { 161 FT_ERROR(( "T1.Add_Table: invalid index\n" )); 162 return T1_Err_Syntax_Error; 163 } 164 165 /* grow the base block if needed */ 166 if ( table->cursor + length > table->capacity ) 167 { 168 FT_Error error; 169 FT_Int new_size = table->capacity; 170 171 while ( new_size < table->cursor+length ) 172 new_size += 1024; 173 174 error = reallocate_t1_table( table, new_size ); 175 if (error) return error; 176 } 177 178 /* add the object to the base block and adjust offset */ 179 table->elements[ index ] = table->block + table->cursor; 180 table->lengths [ index ] = length; 181 MEM_Copy( table->block + table->cursor, object, length ); 182 183 table->cursor += length; 184 return T1_Err_Ok; 185 } 186 187 188/*************************************************************************/ 189/* */ 190/* <Function> T1_Done_Table */ 191/* */ 192/* <Description> */ 193/* Finalise a T1_Table. (realloc it to its current cursor). */ 194/* */ 195/* <Input> */ 196/* table :: target table */ 197/* */ 198/* <Note> */ 199/* This function does NOT release the heap's memory block. It is up */ 200/* to the caller to clean it, or reference it in its own structures. */ 201/* */ 202#if 0 203 LOCAL_FUNC 204 void T1_Done_Table( T1_Table* table ) 205 { 206 FT_Memory memory = table->memory; 207 FT_Error error; 208 FT_Byte* old_base; 209 210 /* should never fail, as rec.cursor <= rec.size */ 211 old_base = table->block; 212 if (!old_base) 213 return; 214 215 (void)REALLOC( table->block, table->capacity, table->cursor ); 216 table->capacity = table->cursor; 217 218 if (old_base != table->block) 219 shift_elements( table, old_base ); 220 } 221#endif 222 223 LOCAL_FUNC 224 void T1_Release_Table( T1_Table* table ) 225 { 226 FT_Memory memory = table->memory; 227 228 if (table->init == (FT_Long)0xdeadbeef) 229 { 230 FREE( table->block ); 231 FREE( table->elements ); 232 FREE( table->lengths ); 233 table->init = 0; 234 } 235 } 236 237#endif 238 239/*************************************************************************/ 240/*************************************************************************/ 241/*************************************************************************/ 242/***** *****/ 243/***** INPUT STREAM PARSER *****/ 244/***** *****/ 245/***** *****/ 246/*************************************************************************/ 247/*************************************************************************/ 248/*************************************************************************/ 249 250 #define IS_T1_WHITESPACE(c) ( (c) == ' ' || (c) == '\t' ) 251 #define IS_T1_LINESPACE(c) ( (c) == '\r' || (c) == '\n' ) 252 253 #define IS_T1_SPACE(c) ( IS_T1_WHITESPACE(c) || IS_T1_LINESPACE(c) ) 254 255 LOCAL_FUNC 256 void CID_Skip_Spaces( CID_Parser* parser ) 257 { 258 FT_Byte* cur = parser->cursor; 259 FT_Byte* limit = parser->limit; 260 261 while (cur < limit) 262 { 263 FT_Byte c = *cur; 264 if (!IS_T1_SPACE(c)) 265 break; 266 cur++; 267 } 268 parser->cursor = cur; 269 } 270 271 LOCAL_FUNC 272 void CID_ToToken( CID_Parser* parser, 273 T1_Token_Rec* token ) 274 { 275 FT_Byte* cur; 276 FT_Byte* limit; 277 FT_Byte starter, ender; 278 FT_Int embed; 279 280 token->type = t1_token_none; 281 token->start = 0; 282 token->limit = 0; 283 284 /* first of all, skip space */ 285 CID_Skip_Spaces(parser); 286 287 cur = parser->cursor; 288 limit = parser->limit; 289 290 if ( cur < limit ) 291 { 292 switch (*cur) 293 { 294 /************* check for strings ***********************/ 295 case '(': 296 token->type = t1_token_string; 297 ender = ')'; 298 goto Lookup_Ender; 299 300 /************* check for programs/array ****************/ 301 case '{': 302 token->type = t1_token_array; 303 ender = '}'; 304 goto Lookup_Ender; 305 306 /************* check for table/array ******************/ 307 case '[': 308 token->type = t1_token_array; 309 ender = ']'; 310 311 Lookup_Ender: 312 embed = 1; 313 starter = *cur++; 314 token->start = cur; 315 while (cur < limit) 316 { 317 if (*cur == starter) 318 embed++; 319 else if (*cur == ender) 320 { 321 embed--; 322 if (embed <= 0) 323 { 324 token->limit = cur++; 325 break; 326 } 327 } 328 cur++; 329 } 330 break; 331 332 /* **************** otherwise, it's any token **********/ 333 default: 334 token->start = cur++; 335 token->type = t1_token_any; 336 while (cur < limit && !IS_T1_SPACE(*cur)) 337 cur++; 338 339 token->limit = cur; 340 } 341 342 if (!token->limit) 343 { 344 token->start = 0; 345 token->type = t1_token_none; 346 } 347 348 parser->cursor = cur; 349 } 350 } 351 352 353 LOCAL_FUNC 354 void CID_ToTokenArray( CID_Parser* parser, 355 T1_Token_Rec* tokens, 356 FT_UInt max_tokens, 357 FT_Int *pnum_tokens ) 358 { 359 T1_Token_Rec master; 360 361 *pnum_tokens = -1; 362 363 CID_ToToken( parser, &master ); 364 if (master.type == t1_token_array) 365 { 366 FT_Byte* old_cursor = parser->cursor; 367 FT_Byte* old_limit = parser->limit; 368 T1_Token_Rec* cur = tokens; 369 T1_Token_Rec* limit = cur + max_tokens; 370 371 parser->cursor = master.start; 372 parser->limit = master.limit; 373 374 while (parser->cursor < parser->limit) 375 { 376 T1_Token_Rec token; 377 378 CID_ToToken( parser, &token ); 379 if (!token.type) 380 break; 381 382 if (cur < limit) 383 *cur = token; 384 385 cur++; 386 } 387 388 *pnum_tokens = cur - tokens; 389 390 parser->cursor = old_cursor; 391 parser->limit = old_limit; 392 } 393 } 394 395 396 static 397 FT_Long t1_toint( FT_Byte* *cursor, 398 FT_Byte* limit ) 399 { 400 FT_Long result = 0; 401 FT_Byte* cur = *cursor; 402 FT_Byte c, d; 403 404 for (; cur < limit; cur++) 405 { 406 c = *cur; 407 d = (FT_Byte)(c - '0'); 408 if (d < 10) break; 409 410 if ( c=='-' ) 411 { 412 cur++; 413 break; 414 } 415 } 416 417 if (cur < limit) 418 { 419 do 420 { 421 d = (FT_Byte)(cur[0] - '0'); 422 if (d >= 10) 423 break; 424 425 result = result*10 + d; 426 cur++; 427 428 } while (cur < limit); 429 430 if (c == '-') 431 result = -result; 432 } 433 434 *cursor = cur; 435 return result; 436 } 437 438 439 static 440 FT_Long t1_tofixed( FT_Byte* *cursor, 441 FT_Byte* limit, 442 FT_Long power_ten ) 443 { 444 FT_Byte* cur = *cursor; 445 FT_Long num, divider, result; 446 FT_Int sign = 0; 447 FT_Byte d; 448 449 if (cur >= limit) return 0; 450 451 /* first of all, read the integer part */ 452 result = t1_toint( &cur, limit ) << 16; 453 num = 0; 454 divider = 1; 455 456 if (result < 0) 457 { 458 sign = 1; 459 result = -result; 460 } 461 if (cur >= limit) goto Exit; 462 463 /* read decimal part, if any */ 464 if (*cur == '.' && cur+1 < limit) 465 { 466 cur++; 467 468 for (;;) 469 { 470 d = (FT_Byte)(*cur - '0'); 471 if (d >= 10) break; 472 473 if (divider < 10000000L) 474 { 475 num = num*10 + d; 476 divider *= 10; 477 } 478 cur++; 479 if (cur >= limit) break; 480 } 481 } 482 483 /* read exponent, if any */ 484 if ( cur+1 < limit && (*cur == 'e' || *cur == 'E')) 485 { 486 cur++; 487 power_ten += t1_toint( &cur, limit ); 488 } 489 490 Exit: 491 /* raise to power of ten if needed */ 492 while (power_ten > 0) 493 { 494 result = result*10; 495 num = num*10; 496 power_ten--; 497 } 498 499 while (power_ten < 0) 500 { 501 result = result/10; 502 divider = divider*10; 503 power_ten++; 504 } 505 506 if (num) 507 result += FT_DivFix( num, divider ); 508 509 if (sign) 510 result = -result; 511 512 *cursor = cur; 513 return result; 514 } 515 516 517 static 518 int t1_tobool( FT_Byte* *cursor, FT_Byte* limit ) 519 { 520 FT_Byte* cur = *cursor; 521 T1_Bool result = 0; 522 523 /* return 1 if we find a "true", 0 otherwise */ 524 if ( cur+3 < limit && 525 cur[0] == 't' && 526 cur[1] == 'r' && 527 cur[2] == 'u' && 528 cur[3] == 'e' ) 529 { 530 result = 1; 531 cur += 5; 532 } 533 else if ( cur+4 < limit && 534 cur[0] == 'f' && 535 cur[1] == 'a' && 536 cur[2] == 'l' && 537 cur[3] == 's' && 538 cur[4] == 'e' ) 539 { 540 result = 0; 541 cur += 6; 542 } 543 *cursor = cur; 544 return result; 545 } 546 547 548 static 549 FT_Int t1_tocoordarray( FT_Byte* *cursor, 550 FT_Byte* limit, 551 FT_Int max_coords, 552 FT_Short* coords ) 553 { 554 FT_Byte* cur = *cursor; 555 FT_Int count = 0; 556 FT_Byte c, ender; 557 558 if (cur >= limit) goto Exit; 559 560 /* check for the beginning of an array. If not, only one number will be read */ 561 c = *cur; 562 ender = 0; 563 564 if (c == '[') 565 ender = ']'; 566 567 if (c == '{') 568 ender = '}'; 569 570 if (ender) 571 cur++; 572 573 /* now, read the coordinates */ 574 for ( ; cur < limit; ) 575 { 576 /* skip whitespace in front of data */ 577 for (;;) 578 { 579 c = *cur; 580 if ( c != ' ' && c != '\t' ) break; 581 582 cur++; 583 if (cur >= limit) goto Exit; 584 } 585 586 if (count >= max_coords || c == ender) 587 break; 588 589 coords[count] = (T1_Short)(t1_tofixed(&cur,limit,0) >> 16); 590 count++; 591 592 if (!ender) 593 break; 594 } 595 596 Exit: 597 *cursor = cur; 598 return count; 599 } 600 601 602 603 static 604 FT_Int t1_tofixedarray( FT_Byte* *cursor, 605 FT_Byte* limit, 606 FT_Int max_values, 607 FT_Fixed* values, 608 FT_Int power_ten ) 609 { 610 FT_Byte* cur = *cursor; 611 FT_Int count = 0; 612 FT_Byte c, ender; 613 614 if (cur >= limit) goto Exit; 615 616 /* check for the beginning of an array. If not, only one number will be read */ 617 c = *cur; 618 ender = 0; 619 620 if (c == '[') 621 ender = ']'; 622 623 if (c == '{') 624 ender = '}'; 625 626 if (ender) 627 cur++; 628 629 /* now, read the values */ 630 for ( ; cur < limit; ) 631 { 632 /* skip whitespace in front of data */ 633 for (;;) 634 { 635 c = *cur; 636 if ( c != ' ' && c != '\t' ) break; 637 638 cur++; 639 if (cur >= limit) goto Exit; 640 } 641 642 if (count >= max_values || c == ender) 643 break; 644 645 values[count] = t1_tofixed(&cur,limit,power_ten); 646 count++; 647 648 if (!ender) 649 break; 650 } 651 652 Exit: 653 *cursor = cur; 654 return count; 655 } 656 657 658 659 /* Loads a simple field (i.e. non-table) into the current list of objects */ 660 LOCAL_FUNC 661 FT_Error CID_Load_Field( CID_Parser* parser, 662 const T1_Field_Rec* field, 663 void* object ) 664 { 665 T1_Token_Rec token; 666 FT_Byte* cur; 667 FT_Byte* limit; 668 FT_UInt count; 669 FT_UInt index; 670 FT_Error error; 671 672 CID_ToToken( parser, &token ); 673 if (!token.type) 674 goto Fail; 675 676 count = 1; 677 index = 0; 678 cur = token.start; 679 limit = token.limit; 680 681 { 682 FT_Byte* q = (FT_Byte*)object + field->offset; 683 FT_Long val; 684 T1_String* string; 685 686 switch (field->type) 687 { 688 case t1_field_bool: 689 { 690 val = t1_tobool( &cur, limit ); 691 goto Store_Integer; 692 } 693 694 case t1_field_fixed: 695 { 696 val = t1_tofixed( &cur, limit, 0 ); 697 goto Store_Integer; 698 } 699 700 case t1_field_integer: 701 { 702 val = t1_toint( &cur, limit ); 703 Store_Integer: 704 switch (field->size) 705 { 706 case 1: *(FT_Byte*) q = (FT_Byte)val; break; 707 case 2: *(FT_UShort*)q = (FT_UShort)val; break; 708 default: *(FT_Long*) q = val; 709 } 710 } 711 break; 712 713 case t1_field_string: 714 { 715 FT_Memory memory = parser->memory; 716 FT_UInt len = limit-cur; 717 718 if ( ALLOC( string, len+1 ) ) 719 goto Exit; 720 721 MEM_Copy( string, cur, len ); 722 string[len] = 0; 723 724 *(T1_String**)q = string; 725 } 726 break; 727 728 default: 729 /* an error occured */ 730 goto Fail; 731 } 732 } 733 error = 0; 734 735 Exit: 736 return error; 737 Fail: 738 error = T1_Err_Invalid_File_Format; 739 goto Exit; 740 } 741 742 743#define CID_MAX_TABLE_ELEMENTS 32 744 745 LOCAL_FUNC 746 FT_Error CID_Load_Field_Table( CID_Parser* parser, 747 const T1_Field_Rec* field, 748 void* object ) 749 { 750 T1_Token_Rec elements[CID_MAX_TABLE_ELEMENTS]; 751 T1_Token_Rec* token; 752 FT_Int num_elements; 753 FT_Error error = 0; 754 FT_Byte* old_cursor; 755 FT_Byte* old_limit; 756 T1_Field_Rec fieldrec = *(T1_Field_Rec*)field; 757 758 fieldrec.type = t1_field_integer; 759 if (field->type == t1_field_fixed_array ) 760 fieldrec.type = t1_field_fixed; 761 762 CID_ToTokenArray( parser, elements, 32, &num_elements ); 763 if (num_elements < 0) 764 goto Fail; 765 766 if (num_elements > CID_MAX_TABLE_ELEMENTS) 767 num_elements = CID_MAX_TABLE_ELEMENTS; 768 769 old_cursor = parser->cursor; 770 old_limit = parser->limit; 771 772 /* we store the elements count */ 773 if (field->count_offset) 774 *(FT_Byte*)((FT_Byte*)object + field->count_offset) = num_elements; 775 776 /* we now load each element, adjusting the field.offset on each one */ 777 token = elements; 778 for ( ; num_elements > 0; num_elements--, token++ ) 779 { 780 parser->cursor = token->start; 781 parser->limit = token->limit; 782 CID_Load_Field( parser, &fieldrec, object ); 783 fieldrec.offset += fieldrec.size; 784 } 785 786 parser->cursor = old_cursor; 787 parser->limit = old_limit; 788 789 Exit: 790 return error; 791 Fail: 792 error = T1_Err_Invalid_File_Format; 793 goto Exit; 794 } 795 796 797 798 799 800 801 802 LOCAL_FUNC 803 FT_Long CID_ToInt ( CID_Parser* parser ) 804 { 805 return t1_toint( &parser->cursor, parser->limit ); 806 } 807 808 809 LOCAL_FUNC 810 FT_Int CID_ToCoordArray( CID_Parser* parser, 811 FT_Int max_coords, 812 FT_Short* coords ) 813 { 814 return t1_tocoordarray( &parser->cursor, parser->limit, max_coords, coords ); 815 } 816 817 818 LOCAL_FUNC 819 FT_Int CID_ToFixedArray( CID_Parser* parser, 820 FT_Int max_values, 821 FT_Fixed* values, 822 FT_Int power_ten ) 823 { 824 return t1_tofixedarray( &parser->cursor, parser->limit, max_values, values, power_ten ); 825 } 826 827 828#if 0 829 /* return the value of an hexadecimal digit */ 830 static 831 int hexa_value( char c ) 832 { 833 unsigned int d; 834 835 d = (unsigned int)(c-'0'); 836 if ( d <= 9 ) return (int)d; 837 838 d = (unsigned int)(c-'a'); 839 if ( d <= 5 ) return (int)(d+10); 840 841 d = (unsigned int)(c-'A'); 842 if ( d <= 5 ) return (int)(d+10); 843 844 return -1; 845 } 846#endif 847 848 849 LOCAL_FUNC 850 FT_Error CID_New_Parser( CID_Parser* parser, 851 FT_Stream stream, 852 FT_Memory memory ) 853 { 854 FT_Error error; 855 FT_ULong base_offset, offset, ps_len; 856 FT_Byte buffer[ 256 + 10 ]; 857 FT_Int buff_len; 858 859 MEM_Set( parser, 0, sizeof(*parser ) ); 860 parser->stream = stream; 861 parser->memory = memory; 862 863 base_offset = FILE_Pos(); 864 865 /* first of all, check the font format in the header */ 866 if ( ACCESS_Frame(31) ) 867 goto Exit; 868 869 if ( strncmp( stream->cursor, "%!PS-Adobe-3.0 Resource-CIDFont", 31 ) ) 870 { 871 FT_ERROR(( "[not a valid CID-keyed font]\n" )); 872 error = FT_Err_Unknown_File_Format; 873 } 874 875 FORGET_Frame(); 876 if (error) goto Exit; 877 878 /* now, read the rest of the file, until we find a "StartData" */ 879 buff_len = 256; 880 for (;;) 881 { 882 FT_Byte *p, *limit = buffer + 256; 883 884 /* fill input buffer */ 885 buff_len -= 256; 886 if (buff_len > 0) 887 MEM_Move( buffer, limit, buff_len ); 888 889 if ( FILE_Read( buffer, 256+10-buff_len ) ) 890 goto Exit; 891 892 buff_len = 256+10; 893 894 /* look for "StartData" */ 895 for ( p = buffer; p < limit; p++ ) 896 { 897 if ( p[0] == 'S' && strncmp( (char*)p, "StartData", 9 ) == 0 ) 898 { 899 /* save offset of binary data after "StartData" */ 900 offset = FILE_Pos() - ( limit-p ) + 10; 901 goto Found; 902 } 903 } 904 } 905 906 Found: 907 /* all right, we found the start of the binary data. We will now rewind */ 908 /* and extract the frame of corresponding to the Postscript section */ 909 ps_len = offset - base_offset; 910 if ( FILE_Seek( base_offset ) || 911 EXTRACT_Frame( ps_len, parser->postscript ) ) 912 goto Exit; 913 914 parser->data_offset = offset; 915 parser->postscript_len = ps_len; 916 parser->cursor = parser->postscript; 917 parser->limit = parser->cursor + ps_len; 918 parser->num_dict = -1; 919 920 Exit: 921 return error; 922 } 923 924 925 926 LOCAL_FUNC 927 void CID_Done_Parser( CID_Parser* parser ) 928 { 929 /* always free the private dictionary */ 930 if (parser->postscript) 931 { 932 FT_Stream stream = parser->stream; 933 RELEASE_Frame( parser->postscript ); 934 } 935 } 936 937