1 /**************************************************************************** 2 * 3 * psobjs.c 4 * 5 * Auxiliary functions for PostScript fonts (body). 6 * 7 * Copyright (C) 1996-2020 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 <freetype/internal/psaux.h> 20 #include <freetype/internal/ftdebug.h> 21 #include <freetype/internal/ftcalc.h> 22 #include <freetype/ftdriver.h> 23 24 #include "psobjs.h" 25 #include "psconv.h" 26 27 #include "psauxerr.h" 28 #include "psauxmod.h" 29 30 31 /************************************************************************** 32 * 33 * The macro FT_COMPONENT is used in trace mode. It is an implicit 34 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 35 * messages during execution. 36 */ 37 #undef FT_COMPONENT 38 #define FT_COMPONENT psobjs 39 40 41 /*************************************************************************/ 42 /*************************************************************************/ 43 /***** *****/ 44 /***** PS_TABLE *****/ 45 /***** *****/ 46 /*************************************************************************/ 47 /*************************************************************************/ 48 49 /************************************************************************** 50 * 51 * @Function: 52 * ps_table_new 53 * 54 * @Description: 55 * Initializes a PS_Table. 56 * 57 * @InOut: 58 * table :: 59 * The address of the target table. 60 * 61 * @Input: 62 * count :: 63 * The table size = the maximum number of elements. 64 * 65 * memory :: 66 * The memory object to use for all subsequent 67 * reallocations. 68 * 69 * @Return: 70 * FreeType error code. 0 means success. 71 */ 72 FT_LOCAL_DEF( FT_Error ) ps_table_new(PS_Table table,FT_Int count,FT_Memory memory)73 ps_table_new( PS_Table table, 74 FT_Int count, 75 FT_Memory memory ) 76 { 77 FT_Error error; 78 79 80 table->memory = memory; 81 if ( FT_NEW_ARRAY( table->elements, count ) || 82 FT_NEW_ARRAY( table->lengths, count ) ) 83 goto Exit; 84 85 table->max_elems = count; 86 table->init = 0xDEADBEEFUL; 87 table->num_elems = 0; 88 table->block = NULL; 89 table->capacity = 0; 90 table->cursor = 0; 91 92 *(PS_Table_FuncsRec*)&table->funcs = ps_table_funcs; 93 94 Exit: 95 if ( error ) 96 FT_FREE( table->elements ); 97 98 return error; 99 } 100 101 102 static void shift_elements(PS_Table table,FT_Byte * old_base)103 shift_elements( PS_Table table, 104 FT_Byte* old_base ) 105 { 106 FT_PtrDist delta = table->block - old_base; 107 FT_Byte** offset = table->elements; 108 FT_Byte** limit = offset + table->max_elems; 109 110 111 for ( ; offset < limit; offset++ ) 112 { 113 if ( offset[0] ) 114 offset[0] += delta; 115 } 116 } 117 118 119 static FT_Error reallocate_t1_table(PS_Table table,FT_Offset new_size)120 reallocate_t1_table( PS_Table table, 121 FT_Offset new_size ) 122 { 123 FT_Memory memory = table->memory; 124 FT_Byte* old_base = table->block; 125 FT_Error error; 126 127 128 /* allocate new base block */ 129 if ( FT_ALLOC( table->block, new_size ) ) 130 { 131 table->block = old_base; 132 return error; 133 } 134 135 /* copy elements and shift offsets */ 136 if ( old_base ) 137 { 138 FT_MEM_COPY( table->block, old_base, table->capacity ); 139 shift_elements( table, old_base ); 140 FT_FREE( old_base ); 141 } 142 143 table->capacity = new_size; 144 145 return FT_Err_Ok; 146 } 147 148 149 /************************************************************************** 150 * 151 * @Function: 152 * ps_table_add 153 * 154 * @Description: 155 * Adds an object to a PS_Table, possibly growing its memory block. 156 * 157 * @InOut: 158 * table :: 159 * The target table. 160 * 161 * @Input: 162 * idx :: 163 * The index of the object in the table. 164 * 165 * object :: 166 * The address of the object to copy in memory. 167 * 168 * length :: 169 * The length in bytes of the source object. 170 * 171 * @Return: 172 * FreeType error code. 0 means success. An error is returned if a 173 * reallocation fails. 174 */ 175 FT_LOCAL_DEF( FT_Error ) ps_table_add(PS_Table table,FT_Int idx,const void * object,FT_UInt length)176 ps_table_add( PS_Table table, 177 FT_Int idx, 178 const void* object, 179 FT_UInt length ) 180 { 181 if ( idx < 0 || idx >= table->max_elems ) 182 { 183 FT_ERROR(( "ps_table_add: invalid index\n" )); 184 return FT_THROW( Invalid_Argument ); 185 } 186 187 /* grow the base block if needed */ 188 if ( table->cursor + length > table->capacity ) 189 { 190 FT_Error error; 191 FT_Offset new_size = table->capacity; 192 FT_PtrDist in_offset; 193 194 195 in_offset = (FT_Byte*)object - table->block; 196 if ( in_offset < 0 || (FT_Offset)in_offset >= table->capacity ) 197 in_offset = -1; 198 199 while ( new_size < table->cursor + length ) 200 { 201 /* increase size by 25% and round up to the nearest multiple 202 of 1024 */ 203 new_size += ( new_size >> 2 ) + 1; 204 new_size = FT_PAD_CEIL( new_size, 1024 ); 205 } 206 207 error = reallocate_t1_table( table, new_size ); 208 if ( error ) 209 return error; 210 211 if ( in_offset >= 0 ) 212 object = table->block + in_offset; 213 } 214 215 /* add the object to the base block and adjust offset */ 216 table->elements[idx] = FT_OFFSET( table->block, table->cursor ); 217 table->lengths [idx] = length; 218 FT_MEM_COPY( table->block + table->cursor, object, length ); 219 220 table->cursor += length; 221 return FT_Err_Ok; 222 } 223 224 225 /************************************************************************** 226 * 227 * @Function: 228 * ps_table_done 229 * 230 * @Description: 231 * Finalizes a PS_TableRec (i.e., reallocate it to its current 232 * cursor). 233 * 234 * @InOut: 235 * table :: 236 * The target table. 237 * 238 * @Note: 239 * This function does NOT release the heap's memory block. It is up 240 * to the caller to clean it, or reference it in its own structures. 241 */ 242 FT_LOCAL_DEF( void ) ps_table_done(PS_Table table)243 ps_table_done( PS_Table table ) 244 { 245 FT_Memory memory = table->memory; 246 FT_Error error; 247 FT_Byte* old_base = table->block; 248 249 250 /* should never fail, because rec.cursor <= rec.size */ 251 if ( !old_base ) 252 return; 253 254 if ( FT_ALLOC( table->block, table->cursor ) ) 255 return; 256 FT_MEM_COPY( table->block, old_base, table->cursor ); 257 shift_elements( table, old_base ); 258 259 table->capacity = table->cursor; 260 FT_FREE( old_base ); 261 262 FT_UNUSED( error ); 263 } 264 265 266 FT_LOCAL_DEF( void ) ps_table_release(PS_Table table)267 ps_table_release( PS_Table table ) 268 { 269 FT_Memory memory = table->memory; 270 271 272 if ( (FT_ULong)table->init == 0xDEADBEEFUL ) 273 { 274 FT_FREE( table->block ); 275 FT_FREE( table->elements ); 276 FT_FREE( table->lengths ); 277 table->init = 0; 278 } 279 } 280 281 282 /*************************************************************************/ 283 /*************************************************************************/ 284 /***** *****/ 285 /***** T1 PARSER *****/ 286 /***** *****/ 287 /*************************************************************************/ 288 /*************************************************************************/ 289 290 291 /* first character must be already part of the comment */ 292 293 static void skip_comment(FT_Byte ** acur,FT_Byte * limit)294 skip_comment( FT_Byte* *acur, 295 FT_Byte* limit ) 296 { 297 FT_Byte* cur = *acur; 298 299 300 while ( cur < limit ) 301 { 302 if ( IS_PS_NEWLINE( *cur ) ) 303 break; 304 cur++; 305 } 306 307 *acur = cur; 308 } 309 310 311 static void skip_spaces(FT_Byte ** acur,FT_Byte * limit)312 skip_spaces( FT_Byte* *acur, 313 FT_Byte* limit ) 314 { 315 FT_Byte* cur = *acur; 316 317 318 while ( cur < limit ) 319 { 320 if ( !IS_PS_SPACE( *cur ) ) 321 { 322 if ( *cur == '%' ) 323 /* According to the PLRM, a comment is equal to a space. */ 324 skip_comment( &cur, limit ); 325 else 326 break; 327 } 328 cur++; 329 } 330 331 *acur = cur; 332 } 333 334 335 #define IS_OCTAL_DIGIT( c ) ( '0' <= (c) && (c) <= '7' ) 336 337 338 /* first character must be `('; */ 339 /* *acur is positioned at the character after the closing `)' */ 340 341 static FT_Error skip_literal_string(FT_Byte ** acur,FT_Byte * limit)342 skip_literal_string( FT_Byte* *acur, 343 FT_Byte* limit ) 344 { 345 FT_Byte* cur = *acur; 346 FT_Int embed = 0; 347 FT_Error error = FT_ERR( Invalid_File_Format ); 348 unsigned int i; 349 350 351 while ( cur < limit ) 352 { 353 FT_Byte c = *cur; 354 355 356 cur++; 357 358 if ( c == '\\' ) 359 { 360 /* Red Book 3rd ed., section `Literal Text Strings', p. 29: */ 361 /* A backslash can introduce three different types */ 362 /* of escape sequences: */ 363 /* - a special escaped char like \r, \n, etc. */ 364 /* - a one-, two-, or three-digit octal number */ 365 /* - none of the above in which case the backslash is ignored */ 366 367 if ( cur == limit ) 368 /* error (or to be ignored?) */ 369 break; 370 371 switch ( *cur ) 372 { 373 /* skip `special' escape */ 374 case 'n': 375 case 'r': 376 case 't': 377 case 'b': 378 case 'f': 379 case '\\': 380 case '(': 381 case ')': 382 cur++; 383 break; 384 385 default: 386 /* skip octal escape or ignore backslash */ 387 for ( i = 0; i < 3 && cur < limit; i++ ) 388 { 389 if ( !IS_OCTAL_DIGIT( *cur ) ) 390 break; 391 392 cur++; 393 } 394 } 395 } 396 else if ( c == '(' ) 397 embed++; 398 else if ( c == ')' ) 399 { 400 embed--; 401 if ( embed == 0 ) 402 { 403 error = FT_Err_Ok; 404 break; 405 } 406 } 407 } 408 409 *acur = cur; 410 411 return error; 412 } 413 414 415 /* first character must be `<' */ 416 417 static FT_Error skip_string(FT_Byte ** acur,FT_Byte * limit)418 skip_string( FT_Byte* *acur, 419 FT_Byte* limit ) 420 { 421 FT_Byte* cur = *acur; 422 FT_Error err = FT_Err_Ok; 423 424 425 while ( ++cur < limit ) 426 { 427 /* All whitespace characters are ignored. */ 428 skip_spaces( &cur, limit ); 429 if ( cur >= limit ) 430 break; 431 432 if ( !IS_PS_XDIGIT( *cur ) ) 433 break; 434 } 435 436 if ( cur < limit && *cur != '>' ) 437 { 438 FT_ERROR(( "skip_string: missing closing delimiter `>'\n" )); 439 err = FT_THROW( Invalid_File_Format ); 440 } 441 else 442 cur++; 443 444 *acur = cur; 445 return err; 446 } 447 448 449 /* first character must be the opening brace that */ 450 /* starts the procedure */ 451 452 /* NB: [ and ] need not match: */ 453 /* `/foo {[} def' is a valid PostScript fragment, */ 454 /* even within a Type1 font */ 455 456 static FT_Error skip_procedure(FT_Byte ** acur,FT_Byte * limit)457 skip_procedure( FT_Byte* *acur, 458 FT_Byte* limit ) 459 { 460 FT_Byte* cur; 461 FT_Int embed = 0; 462 FT_Error error = FT_Err_Ok; 463 464 465 FT_ASSERT( **acur == '{' ); 466 467 for ( cur = *acur; cur < limit && error == FT_Err_Ok; cur++ ) 468 { 469 switch ( *cur ) 470 { 471 case '{': 472 embed++; 473 break; 474 475 case '}': 476 embed--; 477 if ( embed == 0 ) 478 { 479 cur++; 480 goto end; 481 } 482 break; 483 484 case '(': 485 error = skip_literal_string( &cur, limit ); 486 break; 487 488 case '<': 489 error = skip_string( &cur, limit ); 490 break; 491 492 case '%': 493 skip_comment( &cur, limit ); 494 break; 495 } 496 } 497 498 end: 499 if ( embed != 0 ) 500 error = FT_THROW( Invalid_File_Format ); 501 502 *acur = cur; 503 504 return error; 505 } 506 507 508 /************************************************************************ 509 * 510 * All exported parsing routines handle leading whitespace and stop at 511 * the first character which isn't part of the just handled token. 512 * 513 */ 514 515 516 FT_LOCAL_DEF( void ) ps_parser_skip_PS_token(PS_Parser parser)517 ps_parser_skip_PS_token( PS_Parser parser ) 518 { 519 /* Note: PostScript allows any non-delimiting, non-whitespace */ 520 /* character in a name (PS Ref Manual, 3rd ed, p31). */ 521 /* PostScript delimiters are (, ), <, >, [, ], {, }, /, and %. */ 522 523 FT_Byte* cur = parser->cursor; 524 FT_Byte* limit = parser->limit; 525 FT_Error error = FT_Err_Ok; 526 527 528 skip_spaces( &cur, limit ); /* this also skips comments */ 529 if ( cur >= limit ) 530 goto Exit; 531 532 /* self-delimiting, single-character tokens */ 533 if ( *cur == '[' || *cur == ']' ) 534 { 535 cur++; 536 goto Exit; 537 } 538 539 /* skip balanced expressions (procedures and strings) */ 540 541 if ( *cur == '{' ) /* {...} */ 542 { 543 error = skip_procedure( &cur, limit ); 544 goto Exit; 545 } 546 547 if ( *cur == '(' ) /* (...) */ 548 { 549 error = skip_literal_string( &cur, limit ); 550 goto Exit; 551 } 552 553 if ( *cur == '<' ) /* <...> */ 554 { 555 if ( cur + 1 < limit && *(cur + 1) == '<' ) /* << */ 556 { 557 cur++; 558 cur++; 559 } 560 else 561 error = skip_string( &cur, limit ); 562 563 goto Exit; 564 } 565 566 if ( *cur == '>' ) 567 { 568 cur++; 569 if ( cur >= limit || *cur != '>' ) /* >> */ 570 { 571 FT_ERROR(( "ps_parser_skip_PS_token:" 572 " unexpected closing delimiter `>'\n" )); 573 error = FT_THROW( Invalid_File_Format ); 574 goto Exit; 575 } 576 cur++; 577 goto Exit; 578 } 579 580 if ( *cur == '/' ) 581 cur++; 582 583 /* anything else */ 584 while ( cur < limit ) 585 { 586 /* *cur might be invalid (e.g., ')' or '}'), but this */ 587 /* is handled by the test `cur == parser->cursor' below */ 588 if ( IS_PS_DELIM( *cur ) ) 589 break; 590 591 cur++; 592 } 593 594 Exit: 595 if ( cur < limit && cur == parser->cursor ) 596 { 597 FT_ERROR(( "ps_parser_skip_PS_token:" 598 " current token is `%c' which is self-delimiting\n" 599 " " 600 " but invalid at this point\n", 601 *cur )); 602 603 error = FT_THROW( Invalid_File_Format ); 604 } 605 606 if ( cur > limit ) 607 cur = limit; 608 609 parser->error = error; 610 parser->cursor = cur; 611 } 612 613 614 FT_LOCAL_DEF( void ) ps_parser_skip_spaces(PS_Parser parser)615 ps_parser_skip_spaces( PS_Parser parser ) 616 { 617 skip_spaces( &parser->cursor, parser->limit ); 618 } 619 620 621 /* `token' here means either something between balanced delimiters */ 622 /* or the next token; the delimiters are not removed. */ 623 624 FT_LOCAL_DEF( void ) ps_parser_to_token(PS_Parser parser,T1_Token token)625 ps_parser_to_token( PS_Parser parser, 626 T1_Token token ) 627 { 628 FT_Byte* cur; 629 FT_Byte* limit; 630 FT_Int embed; 631 632 633 token->type = T1_TOKEN_TYPE_NONE; 634 token->start = NULL; 635 token->limit = NULL; 636 637 /* first of all, skip leading whitespace */ 638 ps_parser_skip_spaces( parser ); 639 640 cur = parser->cursor; 641 limit = parser->limit; 642 643 if ( cur >= limit ) 644 return; 645 646 switch ( *cur ) 647 { 648 /************* check for literal string *****************/ 649 case '(': 650 token->type = T1_TOKEN_TYPE_STRING; 651 token->start = cur; 652 653 if ( skip_literal_string( &cur, limit ) == FT_Err_Ok ) 654 token->limit = cur; 655 break; 656 657 /************* check for programs/array *****************/ 658 case '{': 659 token->type = T1_TOKEN_TYPE_ARRAY; 660 token->start = cur; 661 662 if ( skip_procedure( &cur, limit ) == FT_Err_Ok ) 663 token->limit = cur; 664 break; 665 666 /************* check for table/array ********************/ 667 /* XXX: in theory we should also look for "<<" */ 668 /* since this is semantically equivalent to "["; */ 669 /* in practice it doesn't matter (?) */ 670 case '[': 671 token->type = T1_TOKEN_TYPE_ARRAY; 672 embed = 1; 673 token->start = cur++; 674 675 /* we need this to catch `[ ]' */ 676 parser->cursor = cur; 677 ps_parser_skip_spaces( parser ); 678 cur = parser->cursor; 679 680 while ( cur < limit && !parser->error ) 681 { 682 /* XXX: this is wrong because it does not */ 683 /* skip comments, procedures, and strings */ 684 if ( *cur == '[' ) 685 embed++; 686 else if ( *cur == ']' ) 687 { 688 embed--; 689 if ( embed <= 0 ) 690 { 691 token->limit = ++cur; 692 break; 693 } 694 } 695 696 parser->cursor = cur; 697 ps_parser_skip_PS_token( parser ); 698 /* we need this to catch `[XXX ]' */ 699 ps_parser_skip_spaces ( parser ); 700 cur = parser->cursor; 701 } 702 break; 703 704 /* ************ otherwise, it is any token **************/ 705 default: 706 token->start = cur; 707 token->type = ( *cur == '/' ) ? T1_TOKEN_TYPE_KEY : T1_TOKEN_TYPE_ANY; 708 ps_parser_skip_PS_token( parser ); 709 cur = parser->cursor; 710 if ( !parser->error ) 711 token->limit = cur; 712 } 713 714 if ( !token->limit ) 715 { 716 token->start = NULL; 717 token->type = T1_TOKEN_TYPE_NONE; 718 } 719 720 parser->cursor = cur; 721 } 722 723 724 /* NB: `tokens' can be NULL if we only want to count */ 725 /* the number of array elements */ 726 727 FT_LOCAL_DEF( void ) ps_parser_to_token_array(PS_Parser parser,T1_Token tokens,FT_UInt max_tokens,FT_Int * pnum_tokens)728 ps_parser_to_token_array( PS_Parser parser, 729 T1_Token tokens, 730 FT_UInt max_tokens, 731 FT_Int* pnum_tokens ) 732 { 733 T1_TokenRec master; 734 735 736 *pnum_tokens = -1; 737 738 /* this also handles leading whitespace */ 739 ps_parser_to_token( parser, &master ); 740 741 if ( master.type == T1_TOKEN_TYPE_ARRAY ) 742 { 743 FT_Byte* old_cursor = parser->cursor; 744 FT_Byte* old_limit = parser->limit; 745 T1_Token cur = tokens; 746 T1_Token limit = cur + max_tokens; 747 748 749 /* don't include outermost delimiters */ 750 parser->cursor = master.start + 1; 751 parser->limit = master.limit - 1; 752 753 while ( parser->cursor < parser->limit ) 754 { 755 T1_TokenRec token; 756 757 758 ps_parser_to_token( parser, &token ); 759 if ( !token.type ) 760 break; 761 762 if ( tokens && cur < limit ) 763 *cur = token; 764 765 cur++; 766 } 767 768 *pnum_tokens = (FT_Int)( cur - tokens ); 769 770 parser->cursor = old_cursor; 771 parser->limit = old_limit; 772 } 773 } 774 775 776 /* first character must be a delimiter or a part of a number */ 777 /* NB: `coords' can be NULL if we just want to skip the */ 778 /* array; in this case we ignore `max_coords' */ 779 780 static FT_Int ps_tocoordarray(FT_Byte ** acur,FT_Byte * limit,FT_Int max_coords,FT_Short * coords)781 ps_tocoordarray( FT_Byte* *acur, 782 FT_Byte* limit, 783 FT_Int max_coords, 784 FT_Short* coords ) 785 { 786 FT_Byte* cur = *acur; 787 FT_Int count = 0; 788 FT_Byte c, ender; 789 790 791 if ( cur >= limit ) 792 goto Exit; 793 794 /* check for the beginning of an array; otherwise, only one number */ 795 /* will be read */ 796 c = *cur; 797 ender = 0; 798 799 if ( c == '[' ) 800 ender = ']'; 801 else if ( c == '{' ) 802 ender = '}'; 803 804 if ( ender ) 805 cur++; 806 807 /* now, read the coordinates */ 808 while ( cur < limit ) 809 { 810 FT_Short dummy; 811 FT_Byte* old_cur; 812 813 814 /* skip whitespace in front of data */ 815 skip_spaces( &cur, limit ); 816 if ( cur >= limit ) 817 goto Exit; 818 819 if ( *cur == ender ) 820 { 821 cur++; 822 break; 823 } 824 825 old_cur = cur; 826 827 if ( coords && count >= max_coords ) 828 break; 829 830 /* call PS_Conv_ToFixed() even if coords == NULL */ 831 /* to properly parse number at `cur' */ 832 *( coords ? &coords[count] : &dummy ) = 833 (FT_Short)( PS_Conv_ToFixed( &cur, limit, 0 ) >> 16 ); 834 835 if ( old_cur == cur ) 836 { 837 count = -1; 838 goto Exit; 839 } 840 else 841 count++; 842 843 if ( !ender ) 844 break; 845 } 846 847 Exit: 848 *acur = cur; 849 return count; 850 } 851 852 853 /* first character must be a delimiter or a part of a number */ 854 /* NB: `values' can be NULL if we just want to skip the */ 855 /* array; in this case we ignore `max_values' */ 856 /* */ 857 /* return number of successfully parsed values */ 858 859 static FT_Int ps_tofixedarray(FT_Byte ** acur,FT_Byte * limit,FT_Int max_values,FT_Fixed * values,FT_Int power_ten)860 ps_tofixedarray( FT_Byte* *acur, 861 FT_Byte* limit, 862 FT_Int max_values, 863 FT_Fixed* values, 864 FT_Int power_ten ) 865 { 866 FT_Byte* cur = *acur; 867 FT_Int count = 0; 868 FT_Byte c, ender; 869 870 871 if ( cur >= limit ) 872 goto Exit; 873 874 /* Check for the beginning of an array. Otherwise, only one number */ 875 /* will be read. */ 876 c = *cur; 877 ender = 0; 878 879 if ( c == '[' ) 880 ender = ']'; 881 else if ( c == '{' ) 882 ender = '}'; 883 884 if ( ender ) 885 cur++; 886 887 /* now, read the values */ 888 while ( cur < limit ) 889 { 890 FT_Fixed dummy; 891 FT_Byte* old_cur; 892 893 894 /* skip whitespace in front of data */ 895 skip_spaces( &cur, limit ); 896 if ( cur >= limit ) 897 goto Exit; 898 899 if ( *cur == ender ) 900 { 901 cur++; 902 break; 903 } 904 905 old_cur = cur; 906 907 if ( values && count >= max_values ) 908 break; 909 910 /* call PS_Conv_ToFixed() even if coords == NULL */ 911 /* to properly parse number at `cur' */ 912 *( values ? &values[count] : &dummy ) = 913 PS_Conv_ToFixed( &cur, limit, power_ten ); 914 915 if ( old_cur == cur ) 916 { 917 count = -1; 918 goto Exit; 919 } 920 else 921 count++; 922 923 if ( !ender ) 924 break; 925 } 926 927 Exit: 928 *acur = cur; 929 return count; 930 } 931 932 933 #if 0 934 935 static FT_String* 936 ps_tostring( FT_Byte** cursor, 937 FT_Byte* limit, 938 FT_Memory memory ) 939 { 940 FT_Byte* cur = *cursor; 941 FT_UInt len = 0; 942 FT_Int count; 943 FT_String* result; 944 FT_Error error; 945 946 947 /* XXX: some stupid fonts have a `Notice' or `Copyright' string */ 948 /* that simply doesn't begin with an opening parenthesis, even */ 949 /* though they have a closing one! E.g. "amuncial.pfb" */ 950 /* */ 951 /* We must deal with these ill-fated cases there. Note that */ 952 /* these fonts didn't work with the old Type 1 driver as the */ 953 /* notice/copyright was not recognized as a valid string token */ 954 /* and made the old token parser commit errors. */ 955 956 while ( cur < limit && ( *cur == ' ' || *cur == '\t' ) ) 957 cur++; 958 if ( cur + 1 >= limit ) 959 return 0; 960 961 if ( *cur == '(' ) 962 cur++; /* skip the opening parenthesis, if there is one */ 963 964 *cursor = cur; 965 count = 0; 966 967 /* then, count its length */ 968 for ( ; cur < limit; cur++ ) 969 { 970 if ( *cur == '(' ) 971 count++; 972 973 else if ( *cur == ')' ) 974 { 975 count--; 976 if ( count < 0 ) 977 break; 978 } 979 } 980 981 len = (FT_UInt)( cur - *cursor ); 982 if ( cur >= limit || FT_ALLOC( result, len + 1 ) ) 983 return 0; 984 985 /* now copy the string */ 986 FT_MEM_COPY( result, *cursor, len ); 987 result[len] = '\0'; 988 *cursor = cur; 989 return result; 990 } 991 992 #endif /* 0 */ 993 994 995 static int ps_tobool(FT_Byte ** acur,FT_Byte * limit)996 ps_tobool( FT_Byte* *acur, 997 FT_Byte* limit ) 998 { 999 FT_Byte* cur = *acur; 1000 FT_Bool result = 0; 1001 1002 1003 /* return 1 if we find `true', 0 otherwise */ 1004 if ( cur + 3 < limit && 1005 cur[0] == 't' && 1006 cur[1] == 'r' && 1007 cur[2] == 'u' && 1008 cur[3] == 'e' ) 1009 { 1010 result = 1; 1011 cur += 5; 1012 } 1013 else if ( cur + 4 < limit && 1014 cur[0] == 'f' && 1015 cur[1] == 'a' && 1016 cur[2] == 'l' && 1017 cur[3] == 's' && 1018 cur[4] == 'e' ) 1019 { 1020 result = 0; 1021 cur += 6; 1022 } 1023 1024 *acur = cur; 1025 return result; 1026 } 1027 1028 1029 /* load a simple field (i.e. non-table) into the current list of objects */ 1030 1031 FT_LOCAL_DEF( FT_Error ) ps_parser_load_field(PS_Parser parser,const T1_Field field,void ** objects,FT_UInt max_objects,FT_ULong * pflags)1032 ps_parser_load_field( PS_Parser parser, 1033 const T1_Field field, 1034 void** objects, 1035 FT_UInt max_objects, 1036 FT_ULong* pflags ) 1037 { 1038 T1_TokenRec token; 1039 FT_Byte* cur; 1040 FT_Byte* limit; 1041 FT_UInt count; 1042 FT_UInt idx; 1043 FT_Error error; 1044 T1_FieldType type; 1045 1046 1047 /* this also skips leading whitespace */ 1048 ps_parser_to_token( parser, &token ); 1049 if ( !token.type ) 1050 goto Fail; 1051 1052 count = 1; 1053 idx = 0; 1054 cur = token.start; 1055 limit = token.limit; 1056 1057 type = field->type; 1058 1059 /* we must detect arrays in /FontBBox */ 1060 if ( type == T1_FIELD_TYPE_BBOX ) 1061 { 1062 T1_TokenRec token2; 1063 FT_Byte* old_cur = parser->cursor; 1064 FT_Byte* old_limit = parser->limit; 1065 1066 1067 /* don't include delimiters */ 1068 parser->cursor = token.start + 1; 1069 parser->limit = token.limit - 1; 1070 1071 ps_parser_to_token( parser, &token2 ); 1072 parser->cursor = old_cur; 1073 parser->limit = old_limit; 1074 1075 if ( token2.type == T1_TOKEN_TYPE_ARRAY ) 1076 { 1077 type = T1_FIELD_TYPE_MM_BBOX; 1078 goto FieldArray; 1079 } 1080 } 1081 else if ( token.type == T1_TOKEN_TYPE_ARRAY ) 1082 { 1083 count = max_objects; 1084 1085 FieldArray: 1086 /* if this is an array and we have no blend, an error occurs */ 1087 if ( max_objects == 0 ) 1088 goto Fail; 1089 1090 idx = 1; 1091 1092 /* don't include delimiters */ 1093 cur++; 1094 limit--; 1095 } 1096 1097 for ( ; count > 0; count--, idx++ ) 1098 { 1099 FT_Byte* q = (FT_Byte*)objects[idx] + field->offset; 1100 FT_Long val; 1101 FT_String* string = NULL; 1102 1103 1104 skip_spaces( &cur, limit ); 1105 1106 switch ( type ) 1107 { 1108 case T1_FIELD_TYPE_BOOL: 1109 val = ps_tobool( &cur, limit ); 1110 FT_TRACE4(( " %s", val ? "true" : "false" )); 1111 goto Store_Integer; 1112 1113 case T1_FIELD_TYPE_FIXED: 1114 val = PS_Conv_ToFixed( &cur, limit, 0 ); 1115 FT_TRACE4(( " %f", (double)val / 65536 )); 1116 goto Store_Integer; 1117 1118 case T1_FIELD_TYPE_FIXED_1000: 1119 val = PS_Conv_ToFixed( &cur, limit, 3 ); 1120 FT_TRACE4(( " %f", (double)val / 65536 / 1000 )); 1121 goto Store_Integer; 1122 1123 case T1_FIELD_TYPE_INTEGER: 1124 val = PS_Conv_ToInt( &cur, limit ); 1125 FT_TRACE4(( " %ld", val )); 1126 /* fall through */ 1127 1128 Store_Integer: 1129 switch ( field->size ) 1130 { 1131 case (8 / FT_CHAR_BIT): 1132 *(FT_Byte*)q = (FT_Byte)val; 1133 break; 1134 1135 case (16 / FT_CHAR_BIT): 1136 *(FT_UShort*)q = (FT_UShort)val; 1137 break; 1138 1139 case (32 / FT_CHAR_BIT): 1140 *(FT_UInt32*)q = (FT_UInt32)val; 1141 break; 1142 1143 default: /* for 64-bit systems */ 1144 *(FT_Long*)q = val; 1145 } 1146 break; 1147 1148 case T1_FIELD_TYPE_STRING: 1149 case T1_FIELD_TYPE_KEY: 1150 { 1151 FT_Memory memory = parser->memory; 1152 FT_UInt len = (FT_UInt)( limit - cur ); 1153 1154 1155 if ( cur >= limit ) 1156 break; 1157 1158 /* we allow both a string or a name */ 1159 /* for cases like /FontName (foo) def */ 1160 if ( token.type == T1_TOKEN_TYPE_KEY ) 1161 { 1162 /* don't include leading `/' */ 1163 len--; 1164 cur++; 1165 } 1166 else if ( token.type == T1_TOKEN_TYPE_STRING ) 1167 { 1168 /* don't include delimiting parentheses */ 1169 /* XXX we don't handle <<...>> here */ 1170 /* XXX should we convert octal escapes? */ 1171 /* if so, what encoding should we use? */ 1172 cur++; 1173 len -= 2; 1174 } 1175 else 1176 { 1177 FT_ERROR(( "ps_parser_load_field:" 1178 " expected a name or string\n" 1179 " " 1180 " but found token of type %d instead\n", 1181 token.type )); 1182 error = FT_THROW( Invalid_File_Format ); 1183 goto Exit; 1184 } 1185 1186 /* for this to work (FT_String**)q must have been */ 1187 /* initialized to NULL */ 1188 if ( *(FT_String**)q ) 1189 { 1190 FT_TRACE0(( "ps_parser_load_field: overwriting field %s\n", 1191 field->ident )); 1192 FT_FREE( *(FT_String**)q ); 1193 *(FT_String**)q = NULL; 1194 } 1195 1196 if ( FT_ALLOC( string, len + 1 ) ) 1197 goto Exit; 1198 1199 FT_MEM_COPY( string, cur, len ); 1200 string[len] = 0; 1201 1202 #ifdef FT_DEBUG_LEVEL_TRACE 1203 if ( token.type == T1_TOKEN_TYPE_STRING ) 1204 FT_TRACE4(( " (%s)", string )); 1205 else 1206 FT_TRACE4(( " /%s", string )); 1207 #endif 1208 1209 *(FT_String**)q = string; 1210 } 1211 break; 1212 1213 case T1_FIELD_TYPE_BBOX: 1214 { 1215 FT_Fixed temp[4]; 1216 FT_BBox* bbox = (FT_BBox*)q; 1217 FT_Int result; 1218 1219 1220 result = ps_tofixedarray( &cur, limit, 4, temp, 0 ); 1221 1222 if ( result < 4 ) 1223 { 1224 FT_ERROR(( "ps_parser_load_field:" 1225 " expected four integers in bounding box\n" )); 1226 error = FT_THROW( Invalid_File_Format ); 1227 goto Exit; 1228 } 1229 1230 bbox->xMin = FT_RoundFix( temp[0] ); 1231 bbox->yMin = FT_RoundFix( temp[1] ); 1232 bbox->xMax = FT_RoundFix( temp[2] ); 1233 bbox->yMax = FT_RoundFix( temp[3] ); 1234 1235 FT_TRACE4(( " [%ld %ld %ld %ld]", 1236 bbox->xMin / 65536, 1237 bbox->yMin / 65536, 1238 bbox->xMax / 65536, 1239 bbox->yMax / 65536 )); 1240 } 1241 break; 1242 1243 case T1_FIELD_TYPE_MM_BBOX: 1244 { 1245 FT_Memory memory = parser->memory; 1246 FT_Fixed* temp = NULL; 1247 FT_Int result; 1248 FT_UInt i; 1249 1250 1251 if ( FT_NEW_ARRAY( temp, max_objects * 4 ) ) 1252 goto Exit; 1253 1254 for ( i = 0; i < 4; i++ ) 1255 { 1256 result = ps_tofixedarray( &cur, limit, (FT_Int)max_objects, 1257 temp + i * max_objects, 0 ); 1258 if ( result < 0 || (FT_UInt)result < max_objects ) 1259 { 1260 FT_ERROR(( "ps_parser_load_field:" 1261 " expected %d integer%s in the %s subarray\n" 1262 " " 1263 " of /FontBBox in the /Blend dictionary\n", 1264 max_objects, max_objects > 1 ? "s" : "", 1265 i == 0 ? "first" 1266 : ( i == 1 ? "second" 1267 : ( i == 2 ? "third" 1268 : "fourth" ) ) )); 1269 error = FT_THROW( Invalid_File_Format ); 1270 1271 FT_FREE( temp ); 1272 goto Exit; 1273 } 1274 1275 skip_spaces( &cur, limit ); 1276 } 1277 1278 FT_TRACE4(( " [" )); 1279 for ( i = 0; i < max_objects; i++ ) 1280 { 1281 FT_BBox* bbox = (FT_BBox*)objects[i]; 1282 1283 1284 bbox->xMin = FT_RoundFix( temp[i ] ); 1285 bbox->yMin = FT_RoundFix( temp[i + max_objects] ); 1286 bbox->xMax = FT_RoundFix( temp[i + 2 * max_objects] ); 1287 bbox->yMax = FT_RoundFix( temp[i + 3 * max_objects] ); 1288 1289 FT_TRACE4(( " [%ld %ld %ld %ld]", 1290 bbox->xMin / 65536, 1291 bbox->yMin / 65536, 1292 bbox->xMax / 65536, 1293 bbox->yMax / 65536 )); 1294 } 1295 FT_TRACE4(( "]" )); 1296 1297 FT_FREE( temp ); 1298 } 1299 break; 1300 1301 default: 1302 /* an error occurred */ 1303 goto Fail; 1304 } 1305 } 1306 1307 #if 0 /* obsolete -- keep for reference */ 1308 if ( pflags ) 1309 *pflags |= 1L << field->flag_bit; 1310 #else 1311 FT_UNUSED( pflags ); 1312 #endif 1313 1314 error = FT_Err_Ok; 1315 1316 Exit: 1317 return error; 1318 1319 Fail: 1320 error = FT_THROW( Invalid_File_Format ); 1321 goto Exit; 1322 } 1323 1324 1325 #define T1_MAX_TABLE_ELEMENTS 32 1326 1327 1328 FT_LOCAL_DEF( FT_Error ) ps_parser_load_field_table(PS_Parser parser,const T1_Field field,void ** objects,FT_UInt max_objects,FT_ULong * pflags)1329 ps_parser_load_field_table( PS_Parser parser, 1330 const T1_Field field, 1331 void** objects, 1332 FT_UInt max_objects, 1333 FT_ULong* pflags ) 1334 { 1335 T1_TokenRec elements[T1_MAX_TABLE_ELEMENTS]; 1336 T1_Token token; 1337 FT_Int num_elements; 1338 FT_Error error = FT_Err_Ok; 1339 FT_Byte* old_cursor; 1340 FT_Byte* old_limit; 1341 T1_FieldRec fieldrec = *(T1_Field)field; 1342 1343 1344 fieldrec.type = T1_FIELD_TYPE_INTEGER; 1345 if ( field->type == T1_FIELD_TYPE_FIXED_ARRAY || 1346 field->type == T1_FIELD_TYPE_BBOX ) 1347 fieldrec.type = T1_FIELD_TYPE_FIXED; 1348 1349 ps_parser_to_token_array( parser, elements, 1350 T1_MAX_TABLE_ELEMENTS, &num_elements ); 1351 if ( num_elements < 0 ) 1352 { 1353 error = FT_ERR( Ignore ); 1354 goto Exit; 1355 } 1356 if ( (FT_UInt)num_elements > field->array_max ) 1357 num_elements = (FT_Int)field->array_max; 1358 1359 old_cursor = parser->cursor; 1360 old_limit = parser->limit; 1361 1362 /* we store the elements count if necessary; */ 1363 /* we further assume that `count_offset' can't be zero */ 1364 if ( field->type != T1_FIELD_TYPE_BBOX && field->count_offset != 0 ) 1365 *(FT_Byte*)( (FT_Byte*)objects[0] + field->count_offset ) = 1366 (FT_Byte)num_elements; 1367 1368 FT_TRACE4(( " [" )); 1369 1370 /* we now load each element, adjusting the field.offset on each one */ 1371 token = elements; 1372 for ( ; num_elements > 0; num_elements--, token++ ) 1373 { 1374 parser->cursor = token->start; 1375 parser->limit = token->limit; 1376 1377 error = ps_parser_load_field( parser, 1378 &fieldrec, 1379 objects, 1380 max_objects, 1381 0 ); 1382 if ( error ) 1383 break; 1384 1385 fieldrec.offset += fieldrec.size; 1386 } 1387 1388 FT_TRACE4(( "]" )); 1389 1390 #if 0 /* obsolete -- keep for reference */ 1391 if ( pflags ) 1392 *pflags |= 1L << field->flag_bit; 1393 #else 1394 FT_UNUSED( pflags ); 1395 #endif 1396 1397 parser->cursor = old_cursor; 1398 parser->limit = old_limit; 1399 1400 Exit: 1401 return error; 1402 } 1403 1404 1405 FT_LOCAL_DEF( FT_Long ) ps_parser_to_int(PS_Parser parser)1406 ps_parser_to_int( PS_Parser parser ) 1407 { 1408 ps_parser_skip_spaces( parser ); 1409 return PS_Conv_ToInt( &parser->cursor, parser->limit ); 1410 } 1411 1412 1413 /* first character must be `<' if `delimiters' is non-zero */ 1414 1415 FT_LOCAL_DEF( FT_Error ) ps_parser_to_bytes(PS_Parser parser,FT_Byte * bytes,FT_Offset max_bytes,FT_ULong * pnum_bytes,FT_Bool delimiters)1416 ps_parser_to_bytes( PS_Parser parser, 1417 FT_Byte* bytes, 1418 FT_Offset max_bytes, 1419 FT_ULong* pnum_bytes, 1420 FT_Bool delimiters ) 1421 { 1422 FT_Error error = FT_Err_Ok; 1423 FT_Byte* cur; 1424 1425 1426 ps_parser_skip_spaces( parser ); 1427 cur = parser->cursor; 1428 1429 if ( cur >= parser->limit ) 1430 goto Exit; 1431 1432 if ( delimiters ) 1433 { 1434 if ( *cur != '<' ) 1435 { 1436 FT_ERROR(( "ps_parser_to_bytes: Missing starting delimiter `<'\n" )); 1437 error = FT_THROW( Invalid_File_Format ); 1438 goto Exit; 1439 } 1440 1441 cur++; 1442 } 1443 1444 *pnum_bytes = PS_Conv_ASCIIHexDecode( &cur, 1445 parser->limit, 1446 bytes, 1447 max_bytes ); 1448 1449 parser->cursor = cur; 1450 1451 if ( delimiters ) 1452 { 1453 if ( cur < parser->limit && *cur != '>' ) 1454 { 1455 FT_ERROR(( "ps_parser_to_bytes: Missing closing delimiter `>'\n" )); 1456 error = FT_THROW( Invalid_File_Format ); 1457 goto Exit; 1458 } 1459 1460 parser->cursor++; 1461 } 1462 1463 Exit: 1464 return error; 1465 } 1466 1467 1468 FT_LOCAL_DEF( FT_Fixed ) ps_parser_to_fixed(PS_Parser parser,FT_Int power_ten)1469 ps_parser_to_fixed( PS_Parser parser, 1470 FT_Int power_ten ) 1471 { 1472 ps_parser_skip_spaces( parser ); 1473 return PS_Conv_ToFixed( &parser->cursor, parser->limit, power_ten ); 1474 } 1475 1476 1477 FT_LOCAL_DEF( FT_Int ) ps_parser_to_coord_array(PS_Parser parser,FT_Int max_coords,FT_Short * coords)1478 ps_parser_to_coord_array( PS_Parser parser, 1479 FT_Int max_coords, 1480 FT_Short* coords ) 1481 { 1482 ps_parser_skip_spaces( parser ); 1483 return ps_tocoordarray( &parser->cursor, parser->limit, 1484 max_coords, coords ); 1485 } 1486 1487 1488 FT_LOCAL_DEF( FT_Int ) ps_parser_to_fixed_array(PS_Parser parser,FT_Int max_values,FT_Fixed * values,FT_Int power_ten)1489 ps_parser_to_fixed_array( PS_Parser parser, 1490 FT_Int max_values, 1491 FT_Fixed* values, 1492 FT_Int power_ten ) 1493 { 1494 ps_parser_skip_spaces( parser ); 1495 return ps_tofixedarray( &parser->cursor, parser->limit, 1496 max_values, values, power_ten ); 1497 } 1498 1499 1500 #if 0 1501 1502 FT_LOCAL_DEF( FT_String* ) 1503 T1_ToString( PS_Parser parser ) 1504 { 1505 return ps_tostring( &parser->cursor, parser->limit, parser->memory ); 1506 } 1507 1508 1509 FT_LOCAL_DEF( FT_Bool ) 1510 T1_ToBool( PS_Parser parser ) 1511 { 1512 return ps_tobool( &parser->cursor, parser->limit ); 1513 } 1514 1515 #endif /* 0 */ 1516 1517 1518 FT_LOCAL_DEF( void ) ps_parser_init(PS_Parser parser,FT_Byte * base,FT_Byte * limit,FT_Memory memory)1519 ps_parser_init( PS_Parser parser, 1520 FT_Byte* base, 1521 FT_Byte* limit, 1522 FT_Memory memory ) 1523 { 1524 parser->error = FT_Err_Ok; 1525 parser->base = base; 1526 parser->limit = limit; 1527 parser->cursor = base; 1528 parser->memory = memory; 1529 parser->funcs = ps_parser_funcs; 1530 } 1531 1532 1533 FT_LOCAL_DEF( void ) ps_parser_done(PS_Parser parser)1534 ps_parser_done( PS_Parser parser ) 1535 { 1536 FT_UNUSED( parser ); 1537 } 1538 1539 1540 /*************************************************************************/ 1541 /*************************************************************************/ 1542 /***** *****/ 1543 /***** T1 BUILDER *****/ 1544 /***** *****/ 1545 /*************************************************************************/ 1546 /*************************************************************************/ 1547 1548 /************************************************************************** 1549 * 1550 * @Function: 1551 * t1_builder_init 1552 * 1553 * @Description: 1554 * Initializes a given glyph builder. 1555 * 1556 * @InOut: 1557 * builder :: 1558 * A pointer to the glyph builder to initialize. 1559 * 1560 * @Input: 1561 * face :: 1562 * The current face object. 1563 * 1564 * size :: 1565 * The current size object. 1566 * 1567 * glyph :: 1568 * The current glyph object. 1569 * 1570 * hinting :: 1571 * Whether hinting should be applied. 1572 */ 1573 FT_LOCAL_DEF( void ) t1_builder_init(T1_Builder builder,FT_Face face,FT_Size size,FT_GlyphSlot glyph,FT_Bool hinting)1574 t1_builder_init( T1_Builder builder, 1575 FT_Face face, 1576 FT_Size size, 1577 FT_GlyphSlot glyph, 1578 FT_Bool hinting ) 1579 { 1580 builder->parse_state = T1_Parse_Start; 1581 builder->load_points = 1; 1582 1583 builder->face = face; 1584 builder->glyph = glyph; 1585 builder->memory = face->memory; 1586 1587 if ( glyph ) 1588 { 1589 FT_GlyphLoader loader = glyph->internal->loader; 1590 1591 1592 builder->loader = loader; 1593 builder->base = &loader->base.outline; 1594 builder->current = &loader->current.outline; 1595 FT_GlyphLoader_Rewind( loader ); 1596 1597 builder->hints_globals = size->internal->module_data; 1598 builder->hints_funcs = NULL; 1599 1600 if ( hinting ) 1601 builder->hints_funcs = glyph->internal->glyph_hints; 1602 } 1603 1604 builder->pos_x = 0; 1605 builder->pos_y = 0; 1606 1607 builder->left_bearing.x = 0; 1608 builder->left_bearing.y = 0; 1609 builder->advance.x = 0; 1610 builder->advance.y = 0; 1611 1612 builder->funcs = t1_builder_funcs; 1613 } 1614 1615 1616 /************************************************************************** 1617 * 1618 * @Function: 1619 * t1_builder_done 1620 * 1621 * @Description: 1622 * Finalizes a given glyph builder. Its contents can still be used 1623 * after the call, but the function saves important information 1624 * within the corresponding glyph slot. 1625 * 1626 * @Input: 1627 * builder :: 1628 * A pointer to the glyph builder to finalize. 1629 */ 1630 FT_LOCAL_DEF( void ) t1_builder_done(T1_Builder builder)1631 t1_builder_done( T1_Builder builder ) 1632 { 1633 FT_GlyphSlot glyph = builder->glyph; 1634 1635 1636 if ( glyph ) 1637 glyph->outline = *builder->base; 1638 } 1639 1640 1641 /* check that there is enough space for `count' more points */ 1642 FT_LOCAL_DEF( FT_Error ) t1_builder_check_points(T1_Builder builder,FT_Int count)1643 t1_builder_check_points( T1_Builder builder, 1644 FT_Int count ) 1645 { 1646 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 1647 } 1648 1649 1650 /* add a new point, do not check space */ 1651 FT_LOCAL_DEF( void ) t1_builder_add_point(T1_Builder builder,FT_Pos x,FT_Pos y,FT_Byte flag)1652 t1_builder_add_point( T1_Builder builder, 1653 FT_Pos x, 1654 FT_Pos y, 1655 FT_Byte flag ) 1656 { 1657 FT_Outline* outline = builder->current; 1658 1659 1660 if ( builder->load_points ) 1661 { 1662 FT_Vector* point = outline->points + outline->n_points; 1663 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 1664 1665 1666 point->x = FIXED_TO_INT( x ); 1667 point->y = FIXED_TO_INT( y ); 1668 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 1669 } 1670 outline->n_points++; 1671 } 1672 1673 1674 /* check space for a new on-curve point, then add it */ 1675 FT_LOCAL_DEF( FT_Error ) t1_builder_add_point1(T1_Builder builder,FT_Pos x,FT_Pos y)1676 t1_builder_add_point1( T1_Builder builder, 1677 FT_Pos x, 1678 FT_Pos y ) 1679 { 1680 FT_Error error; 1681 1682 1683 error = t1_builder_check_points( builder, 1 ); 1684 if ( !error ) 1685 t1_builder_add_point( builder, x, y, 1 ); 1686 1687 return error; 1688 } 1689 1690 1691 /* check space for a new contour, then add it */ 1692 FT_LOCAL_DEF( FT_Error ) t1_builder_add_contour(T1_Builder builder)1693 t1_builder_add_contour( T1_Builder builder ) 1694 { 1695 FT_Outline* outline = builder->current; 1696 FT_Error error; 1697 1698 1699 /* this might happen in invalid fonts */ 1700 if ( !outline ) 1701 { 1702 FT_ERROR(( "t1_builder_add_contour: no outline to add points to\n" )); 1703 return FT_THROW( Invalid_File_Format ); 1704 } 1705 1706 if ( !builder->load_points ) 1707 { 1708 outline->n_contours++; 1709 return FT_Err_Ok; 1710 } 1711 1712 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 1713 if ( !error ) 1714 { 1715 if ( outline->n_contours > 0 ) 1716 outline->contours[outline->n_contours - 1] = 1717 (short)( outline->n_points - 1 ); 1718 1719 outline->n_contours++; 1720 } 1721 1722 return error; 1723 } 1724 1725 1726 /* if a path was begun, add its first on-curve point */ 1727 FT_LOCAL_DEF( FT_Error ) t1_builder_start_point(T1_Builder builder,FT_Pos x,FT_Pos y)1728 t1_builder_start_point( T1_Builder builder, 1729 FT_Pos x, 1730 FT_Pos y ) 1731 { 1732 FT_Error error = FT_ERR( Invalid_File_Format ); 1733 1734 1735 /* test whether we are building a new contour */ 1736 1737 if ( builder->parse_state == T1_Parse_Have_Path ) 1738 error = FT_Err_Ok; 1739 else 1740 { 1741 builder->parse_state = T1_Parse_Have_Path; 1742 error = t1_builder_add_contour( builder ); 1743 if ( !error ) 1744 error = t1_builder_add_point1( builder, x, y ); 1745 } 1746 1747 return error; 1748 } 1749 1750 1751 /* close the current contour */ 1752 FT_LOCAL_DEF( void ) t1_builder_close_contour(T1_Builder builder)1753 t1_builder_close_contour( T1_Builder builder ) 1754 { 1755 FT_Outline* outline = builder->current; 1756 FT_Int first; 1757 1758 1759 if ( !outline ) 1760 return; 1761 1762 first = outline->n_contours <= 1 1763 ? 0 : outline->contours[outline->n_contours - 2] + 1; 1764 1765 /* in malformed fonts it can happen that a contour was started */ 1766 /* but no points were added */ 1767 if ( outline->n_contours && first == outline->n_points ) 1768 { 1769 outline->n_contours--; 1770 return; 1771 } 1772 1773 /* We must not include the last point in the path if it */ 1774 /* is located on the first point. */ 1775 if ( outline->n_points > 1 ) 1776 { 1777 FT_Vector* p1 = outline->points + first; 1778 FT_Vector* p2 = outline->points + outline->n_points - 1; 1779 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 1780 1781 1782 /* `delete' last point only if it coincides with the first */ 1783 /* point and it is not a control point (which can happen). */ 1784 if ( p1->x == p2->x && p1->y == p2->y ) 1785 if ( *control == FT_CURVE_TAG_ON ) 1786 outline->n_points--; 1787 } 1788 1789 if ( outline->n_contours > 0 ) 1790 { 1791 /* Don't add contours only consisting of one point, i.e., */ 1792 /* check whether the first and the last point is the same. */ 1793 if ( first == outline->n_points - 1 ) 1794 { 1795 outline->n_contours--; 1796 outline->n_points--; 1797 } 1798 else 1799 outline->contours[outline->n_contours - 1] = 1800 (short)( outline->n_points - 1 ); 1801 } 1802 } 1803 1804 1805 /*************************************************************************/ 1806 /*************************************************************************/ 1807 /***** *****/ 1808 /***** CFF BUILDER *****/ 1809 /***** *****/ 1810 /*************************************************************************/ 1811 /*************************************************************************/ 1812 1813 1814 /************************************************************************** 1815 * 1816 * @Function: 1817 * cff_builder_init 1818 * 1819 * @Description: 1820 * Initializes a given glyph builder. 1821 * 1822 * @InOut: 1823 * builder :: 1824 * A pointer to the glyph builder to initialize. 1825 * 1826 * @Input: 1827 * face :: 1828 * The current face object. 1829 * 1830 * size :: 1831 * The current size object. 1832 * 1833 * glyph :: 1834 * The current glyph object. 1835 * 1836 * hinting :: 1837 * Whether hinting is active. 1838 */ 1839 FT_LOCAL_DEF( void ) cff_builder_init(CFF_Builder * builder,TT_Face face,CFF_Size size,CFF_GlyphSlot glyph,FT_Bool hinting)1840 cff_builder_init( CFF_Builder* builder, 1841 TT_Face face, 1842 CFF_Size size, 1843 CFF_GlyphSlot glyph, 1844 FT_Bool hinting ) 1845 { 1846 builder->path_begun = 0; 1847 builder->load_points = 1; 1848 1849 builder->face = face; 1850 builder->glyph = glyph; 1851 builder->memory = face->root.memory; 1852 1853 if ( glyph ) 1854 { 1855 FT_GlyphLoader loader = glyph->root.internal->loader; 1856 1857 1858 builder->loader = loader; 1859 builder->base = &loader->base.outline; 1860 builder->current = &loader->current.outline; 1861 FT_GlyphLoader_Rewind( loader ); 1862 1863 builder->hints_globals = NULL; 1864 builder->hints_funcs = NULL; 1865 1866 if ( hinting && size ) 1867 { 1868 FT_Size ftsize = FT_SIZE( size ); 1869 CFF_Internal internal = (CFF_Internal)ftsize->internal->module_data; 1870 1871 if ( internal ) 1872 { 1873 builder->hints_globals = (void *)internal->topfont; 1874 builder->hints_funcs = glyph->root.internal->glyph_hints; 1875 } 1876 } 1877 } 1878 1879 builder->pos_x = 0; 1880 builder->pos_y = 0; 1881 1882 builder->left_bearing.x = 0; 1883 builder->left_bearing.y = 0; 1884 builder->advance.x = 0; 1885 builder->advance.y = 0; 1886 1887 builder->funcs = cff_builder_funcs; 1888 } 1889 1890 1891 /************************************************************************** 1892 * 1893 * @Function: 1894 * cff_builder_done 1895 * 1896 * @Description: 1897 * Finalizes a given glyph builder. Its contents can still be used 1898 * after the call, but the function saves important information 1899 * within the corresponding glyph slot. 1900 * 1901 * @Input: 1902 * builder :: 1903 * A pointer to the glyph builder to finalize. 1904 */ 1905 FT_LOCAL_DEF( void ) cff_builder_done(CFF_Builder * builder)1906 cff_builder_done( CFF_Builder* builder ) 1907 { 1908 CFF_GlyphSlot glyph = builder->glyph; 1909 1910 1911 if ( glyph ) 1912 glyph->root.outline = *builder->base; 1913 } 1914 1915 1916 /* check that there is enough space for `count' more points */ 1917 FT_LOCAL_DEF( FT_Error ) cff_check_points(CFF_Builder * builder,FT_Int count)1918 cff_check_points( CFF_Builder* builder, 1919 FT_Int count ) 1920 { 1921 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 1922 } 1923 1924 1925 /* add a new point, do not check space */ 1926 FT_LOCAL_DEF( void ) cff_builder_add_point(CFF_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)1927 cff_builder_add_point( CFF_Builder* builder, 1928 FT_Pos x, 1929 FT_Pos y, 1930 FT_Byte flag ) 1931 { 1932 FT_Outline* outline = builder->current; 1933 1934 1935 if ( builder->load_points ) 1936 { 1937 FT_Vector* point = outline->points + outline->n_points; 1938 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 1939 1940 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE 1941 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); 1942 1943 1944 if ( driver->hinting_engine == FT_HINTING_FREETYPE ) 1945 { 1946 point->x = x >> 16; 1947 point->y = y >> 16; 1948 } 1949 else 1950 #endif 1951 { 1952 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ 1953 point->x = x >> 10; 1954 point->y = y >> 10; 1955 } 1956 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 1957 } 1958 1959 outline->n_points++; 1960 } 1961 1962 1963 /* check space for a new on-curve point, then add it */ 1964 FT_LOCAL_DEF( FT_Error ) cff_builder_add_point1(CFF_Builder * builder,FT_Pos x,FT_Pos y)1965 cff_builder_add_point1( CFF_Builder* builder, 1966 FT_Pos x, 1967 FT_Pos y ) 1968 { 1969 FT_Error error; 1970 1971 1972 error = cff_check_points( builder, 1 ); 1973 if ( !error ) 1974 cff_builder_add_point( builder, x, y, 1 ); 1975 1976 return error; 1977 } 1978 1979 1980 /* check space for a new contour, then add it */ 1981 FT_LOCAL_DEF( FT_Error ) cff_builder_add_contour(CFF_Builder * builder)1982 cff_builder_add_contour( CFF_Builder* builder ) 1983 { 1984 FT_Outline* outline = builder->current; 1985 FT_Error error; 1986 1987 1988 if ( !builder->load_points ) 1989 { 1990 outline->n_contours++; 1991 return FT_Err_Ok; 1992 } 1993 1994 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 1995 if ( !error ) 1996 { 1997 if ( outline->n_contours > 0 ) 1998 outline->contours[outline->n_contours - 1] = 1999 (short)( outline->n_points - 1 ); 2000 2001 outline->n_contours++; 2002 } 2003 2004 return error; 2005 } 2006 2007 2008 /* if a path was begun, add its first on-curve point */ 2009 FT_LOCAL_DEF( FT_Error ) cff_builder_start_point(CFF_Builder * builder,FT_Pos x,FT_Pos y)2010 cff_builder_start_point( CFF_Builder* builder, 2011 FT_Pos x, 2012 FT_Pos y ) 2013 { 2014 FT_Error error = FT_Err_Ok; 2015 2016 2017 /* test whether we are building a new contour */ 2018 if ( !builder->path_begun ) 2019 { 2020 builder->path_begun = 1; 2021 error = cff_builder_add_contour( builder ); 2022 if ( !error ) 2023 error = cff_builder_add_point1( builder, x, y ); 2024 } 2025 2026 return error; 2027 } 2028 2029 2030 /* close the current contour */ 2031 FT_LOCAL_DEF( void ) cff_builder_close_contour(CFF_Builder * builder)2032 cff_builder_close_contour( CFF_Builder* builder ) 2033 { 2034 FT_Outline* outline = builder->current; 2035 FT_Int first; 2036 2037 2038 if ( !outline ) 2039 return; 2040 2041 first = outline->n_contours <= 1 2042 ? 0 : outline->contours[outline->n_contours - 2] + 1; 2043 2044 /* in malformed fonts it can happen that a contour was started */ 2045 /* but no points were added */ 2046 if ( outline->n_contours && first == outline->n_points ) 2047 { 2048 outline->n_contours--; 2049 return; 2050 } 2051 2052 /* We must not include the last point in the path if it */ 2053 /* is located on the first point. */ 2054 if ( outline->n_points > 1 ) 2055 { 2056 FT_Vector* p1 = outline->points + first; 2057 FT_Vector* p2 = outline->points + outline->n_points - 1; 2058 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 2059 2060 2061 /* `delete' last point only if it coincides with the first */ 2062 /* point and if it is not a control point (which can happen). */ 2063 if ( p1->x == p2->x && p1->y == p2->y ) 2064 if ( *control == FT_CURVE_TAG_ON ) 2065 outline->n_points--; 2066 } 2067 2068 if ( outline->n_contours > 0 ) 2069 { 2070 /* Don't add contours only consisting of one point, i.e., */ 2071 /* check whether begin point and last point are the same. */ 2072 if ( first == outline->n_points - 1 ) 2073 { 2074 outline->n_contours--; 2075 outline->n_points--; 2076 } 2077 else 2078 outline->contours[outline->n_contours - 1] = 2079 (short)( outline->n_points - 1 ); 2080 } 2081 } 2082 2083 2084 /*************************************************************************/ 2085 /*************************************************************************/ 2086 /***** *****/ 2087 /***** PS BUILDER *****/ 2088 /***** *****/ 2089 /*************************************************************************/ 2090 /*************************************************************************/ 2091 2092 /************************************************************************** 2093 * 2094 * @Function: 2095 * ps_builder_init 2096 * 2097 * @Description: 2098 * Initializes a given glyph builder. 2099 * 2100 * @InOut: 2101 * builder :: 2102 * A pointer to the glyph builder to initialize. 2103 * 2104 * @Input: 2105 * face :: 2106 * The current face object. 2107 * 2108 * size :: 2109 * The current size object. 2110 * 2111 * glyph :: 2112 * The current glyph object. 2113 * 2114 * hinting :: 2115 * Whether hinting should be applied. 2116 */ 2117 FT_LOCAL_DEF( void ) ps_builder_init(PS_Builder * ps_builder,void * builder,FT_Bool is_t1)2118 ps_builder_init( PS_Builder* ps_builder, 2119 void* builder, 2120 FT_Bool is_t1 ) 2121 { 2122 FT_ZERO( ps_builder ); 2123 2124 if ( is_t1 ) 2125 { 2126 T1_Builder t1builder = (T1_Builder)builder; 2127 2128 2129 ps_builder->memory = t1builder->memory; 2130 ps_builder->face = (FT_Face)t1builder->face; 2131 ps_builder->glyph = (CFF_GlyphSlot)t1builder->glyph; 2132 ps_builder->loader = t1builder->loader; 2133 ps_builder->base = t1builder->base; 2134 ps_builder->current = t1builder->current; 2135 2136 ps_builder->pos_x = &t1builder->pos_x; 2137 ps_builder->pos_y = &t1builder->pos_y; 2138 2139 ps_builder->left_bearing = &t1builder->left_bearing; 2140 ps_builder->advance = &t1builder->advance; 2141 2142 ps_builder->bbox = &t1builder->bbox; 2143 ps_builder->path_begun = 0; 2144 ps_builder->load_points = t1builder->load_points; 2145 ps_builder->no_recurse = t1builder->no_recurse; 2146 2147 ps_builder->metrics_only = t1builder->metrics_only; 2148 } 2149 else 2150 { 2151 CFF_Builder* cffbuilder = (CFF_Builder*)builder; 2152 2153 2154 ps_builder->memory = cffbuilder->memory; 2155 ps_builder->face = (FT_Face)cffbuilder->face; 2156 ps_builder->glyph = cffbuilder->glyph; 2157 ps_builder->loader = cffbuilder->loader; 2158 ps_builder->base = cffbuilder->base; 2159 ps_builder->current = cffbuilder->current; 2160 2161 ps_builder->pos_x = &cffbuilder->pos_x; 2162 ps_builder->pos_y = &cffbuilder->pos_y; 2163 2164 ps_builder->left_bearing = &cffbuilder->left_bearing; 2165 ps_builder->advance = &cffbuilder->advance; 2166 2167 ps_builder->bbox = &cffbuilder->bbox; 2168 ps_builder->path_begun = cffbuilder->path_begun; 2169 ps_builder->load_points = cffbuilder->load_points; 2170 ps_builder->no_recurse = cffbuilder->no_recurse; 2171 2172 ps_builder->metrics_only = cffbuilder->metrics_only; 2173 } 2174 2175 ps_builder->is_t1 = is_t1; 2176 ps_builder->funcs = ps_builder_funcs; 2177 } 2178 2179 2180 /************************************************************************** 2181 * 2182 * @Function: 2183 * ps_builder_done 2184 * 2185 * @Description: 2186 * Finalizes a given glyph builder. Its contents can still be used 2187 * after the call, but the function saves important information 2188 * within the corresponding glyph slot. 2189 * 2190 * @Input: 2191 * builder :: 2192 * A pointer to the glyph builder to finalize. 2193 */ 2194 FT_LOCAL_DEF( void ) ps_builder_done(PS_Builder * builder)2195 ps_builder_done( PS_Builder* builder ) 2196 { 2197 CFF_GlyphSlot glyph = builder->glyph; 2198 2199 2200 if ( glyph ) 2201 glyph->root.outline = *builder->base; 2202 } 2203 2204 2205 /* check that there is enough space for `count' more points */ 2206 FT_LOCAL_DEF( FT_Error ) ps_builder_check_points(PS_Builder * builder,FT_Int count)2207 ps_builder_check_points( PS_Builder* builder, 2208 FT_Int count ) 2209 { 2210 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 2211 } 2212 2213 2214 /* add a new point, do not check space */ 2215 FT_LOCAL_DEF( void ) ps_builder_add_point(PS_Builder * builder,FT_Pos x,FT_Pos y,FT_Byte flag)2216 ps_builder_add_point( PS_Builder* builder, 2217 FT_Pos x, 2218 FT_Pos y, 2219 FT_Byte flag ) 2220 { 2221 FT_Outline* outline = builder->current; 2222 2223 2224 if ( builder->load_points ) 2225 { 2226 FT_Vector* point = outline->points + outline->n_points; 2227 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 2228 2229 #ifdef CFF_CONFIG_OPTION_OLD_ENGINE 2230 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); 2231 2232 2233 if ( !builder->is_t1 && 2234 driver->hinting_engine == FT_HINTING_FREETYPE ) 2235 { 2236 point->x = x >> 16; 2237 point->y = y >> 16; 2238 } 2239 else 2240 #endif 2241 #ifdef T1_CONFIG_OPTION_OLD_ENGINE 2242 #ifndef CFF_CONFIG_OPTION_OLD_ENGINE 2243 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( builder->face ); 2244 #endif 2245 if ( builder->is_t1 && 2246 driver->hinting_engine == FT_HINTING_FREETYPE ) 2247 { 2248 point->x = FIXED_TO_INT( x ); 2249 point->y = FIXED_TO_INT( y ); 2250 } 2251 else 2252 #endif 2253 { 2254 /* cf2_decoder_parse_charstrings uses 16.16 coordinates */ 2255 point->x = x >> 10; 2256 point->y = y >> 10; 2257 } 2258 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 2259 } 2260 outline->n_points++; 2261 } 2262 2263 2264 /* check space for a new on-curve point, then add it */ 2265 FT_LOCAL_DEF( FT_Error ) ps_builder_add_point1(PS_Builder * builder,FT_Pos x,FT_Pos y)2266 ps_builder_add_point1( PS_Builder* builder, 2267 FT_Pos x, 2268 FT_Pos y ) 2269 { 2270 FT_Error error; 2271 2272 2273 error = ps_builder_check_points( builder, 1 ); 2274 if ( !error ) 2275 ps_builder_add_point( builder, x, y, 1 ); 2276 2277 return error; 2278 } 2279 2280 2281 /* check space for a new contour, then add it */ 2282 FT_LOCAL_DEF( FT_Error ) ps_builder_add_contour(PS_Builder * builder)2283 ps_builder_add_contour( PS_Builder* builder ) 2284 { 2285 FT_Outline* outline = builder->current; 2286 FT_Error error; 2287 2288 2289 /* this might happen in invalid fonts */ 2290 if ( !outline ) 2291 { 2292 FT_ERROR(( "ps_builder_add_contour: no outline to add points to\n" )); 2293 return FT_THROW( Invalid_File_Format ); 2294 } 2295 2296 if ( !builder->load_points ) 2297 { 2298 outline->n_contours++; 2299 return FT_Err_Ok; 2300 } 2301 2302 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 2303 if ( !error ) 2304 { 2305 if ( outline->n_contours > 0 ) 2306 outline->contours[outline->n_contours - 1] = 2307 (short)( outline->n_points - 1 ); 2308 2309 outline->n_contours++; 2310 } 2311 2312 return error; 2313 } 2314 2315 2316 /* if a path was begun, add its first on-curve point */ 2317 FT_LOCAL_DEF( FT_Error ) ps_builder_start_point(PS_Builder * builder,FT_Pos x,FT_Pos y)2318 ps_builder_start_point( PS_Builder* builder, 2319 FT_Pos x, 2320 FT_Pos y ) 2321 { 2322 FT_Error error = FT_Err_Ok; 2323 2324 2325 /* test whether we are building a new contour */ 2326 if ( !builder->path_begun ) 2327 { 2328 builder->path_begun = 1; 2329 error = ps_builder_add_contour( builder ); 2330 if ( !error ) 2331 error = ps_builder_add_point1( builder, x, y ); 2332 } 2333 2334 return error; 2335 } 2336 2337 2338 /* close the current contour */ 2339 FT_LOCAL_DEF( void ) ps_builder_close_contour(PS_Builder * builder)2340 ps_builder_close_contour( PS_Builder* builder ) 2341 { 2342 FT_Outline* outline = builder->current; 2343 FT_Int first; 2344 2345 2346 if ( !outline ) 2347 return; 2348 2349 first = outline->n_contours <= 1 2350 ? 0 : outline->contours[outline->n_contours - 2] + 1; 2351 2352 /* in malformed fonts it can happen that a contour was started */ 2353 /* but no points were added */ 2354 if ( outline->n_contours && first == outline->n_points ) 2355 { 2356 outline->n_contours--; 2357 return; 2358 } 2359 2360 /* We must not include the last point in the path if it */ 2361 /* is located on the first point. */ 2362 if ( outline->n_points > 1 ) 2363 { 2364 FT_Vector* p1 = outline->points + first; 2365 FT_Vector* p2 = outline->points + outline->n_points - 1; 2366 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 2367 2368 2369 /* `delete' last point only if it coincides with the first */ 2370 /* point and it is not a control point (which can happen). */ 2371 if ( p1->x == p2->x && p1->y == p2->y ) 2372 if ( *control == FT_CURVE_TAG_ON ) 2373 outline->n_points--; 2374 } 2375 2376 if ( outline->n_contours > 0 ) 2377 { 2378 /* Don't add contours only consisting of one point, i.e., */ 2379 /* check whether the first and the last point is the same. */ 2380 if ( first == outline->n_points - 1 ) 2381 { 2382 outline->n_contours--; 2383 outline->n_points--; 2384 } 2385 else 2386 outline->contours[outline->n_contours - 1] = 2387 (short)( outline->n_points - 1 ); 2388 } 2389 } 2390 2391 2392 /*************************************************************************/ 2393 /*************************************************************************/ 2394 /***** *****/ 2395 /***** OTHER *****/ 2396 /***** *****/ 2397 /*************************************************************************/ 2398 /*************************************************************************/ 2399 2400 2401 /************************************************************************** 2402 * 2403 * @Function: 2404 * ps_decoder_init 2405 * 2406 * @Description: 2407 * Creates a wrapper decoder for use in the combined 2408 * Type 1 / CFF interpreter. 2409 * 2410 * @InOut: 2411 * ps_decoder :: 2412 * A pointer to the decoder to initialize. 2413 * 2414 * @Input: 2415 * decoder :: 2416 * A pointer to the original decoder. 2417 * 2418 * is_t1 :: 2419 * Flag indicating Type 1 or CFF 2420 */ 2421 FT_LOCAL_DEF( void ) ps_decoder_init(PS_Decoder * ps_decoder,void * decoder,FT_Bool is_t1)2422 ps_decoder_init( PS_Decoder* ps_decoder, 2423 void* decoder, 2424 FT_Bool is_t1 ) 2425 { 2426 FT_ZERO( ps_decoder ); 2427 2428 if ( is_t1 ) 2429 { 2430 T1_Decoder t1_decoder = (T1_Decoder)decoder; 2431 2432 2433 ps_builder_init( &ps_decoder->builder, 2434 &t1_decoder->builder, 2435 is_t1 ); 2436 2437 ps_decoder->cf2_instance = &t1_decoder->cf2_instance; 2438 ps_decoder->psnames = t1_decoder->psnames; 2439 2440 ps_decoder->num_glyphs = t1_decoder->num_glyphs; 2441 ps_decoder->glyph_names = t1_decoder->glyph_names; 2442 ps_decoder->hint_mode = t1_decoder->hint_mode; 2443 ps_decoder->blend = t1_decoder->blend; 2444 2445 ps_decoder->num_locals = (FT_UInt)t1_decoder->num_subrs; 2446 ps_decoder->locals = t1_decoder->subrs; 2447 ps_decoder->locals_len = t1_decoder->subrs_len; 2448 ps_decoder->locals_hash = t1_decoder->subrs_hash; 2449 2450 ps_decoder->buildchar = t1_decoder->buildchar; 2451 ps_decoder->len_buildchar = t1_decoder->len_buildchar; 2452 2453 ps_decoder->lenIV = t1_decoder->lenIV; 2454 } 2455 else 2456 { 2457 CFF_Decoder* cff_decoder = (CFF_Decoder*)decoder; 2458 2459 2460 ps_builder_init( &ps_decoder->builder, 2461 &cff_decoder->builder, 2462 is_t1 ); 2463 2464 ps_decoder->cff = cff_decoder->cff; 2465 ps_decoder->cf2_instance = &cff_decoder->cff->cf2_instance; 2466 ps_decoder->current_subfont = cff_decoder->current_subfont; 2467 2468 ps_decoder->num_globals = cff_decoder->num_globals; 2469 ps_decoder->globals = cff_decoder->globals; 2470 ps_decoder->globals_bias = cff_decoder->globals_bias; 2471 ps_decoder->num_locals = cff_decoder->num_locals; 2472 ps_decoder->locals = cff_decoder->locals; 2473 ps_decoder->locals_bias = cff_decoder->locals_bias; 2474 2475 ps_decoder->glyph_width = &cff_decoder->glyph_width; 2476 ps_decoder->width_only = cff_decoder->width_only; 2477 2478 ps_decoder->hint_mode = cff_decoder->hint_mode; 2479 2480 ps_decoder->get_glyph_callback = cff_decoder->get_glyph_callback; 2481 ps_decoder->free_glyph_callback = cff_decoder->free_glyph_callback; 2482 } 2483 } 2484 2485 2486 /* Synthesize a SubFont object for Type 1 fonts, for use in the */ 2487 /* new interpreter to access Private dict data. */ 2488 FT_LOCAL_DEF( void ) t1_make_subfont(FT_Face face,PS_Private priv,CFF_SubFont subfont)2489 t1_make_subfont( FT_Face face, 2490 PS_Private priv, 2491 CFF_SubFont subfont ) 2492 { 2493 CFF_Private cpriv = &subfont->private_dict; 2494 FT_UInt n, count; 2495 2496 2497 FT_ZERO( subfont ); 2498 FT_ZERO( cpriv ); 2499 2500 count = cpriv->num_blue_values = priv->num_blue_values; 2501 for ( n = 0; n < count; n++ ) 2502 cpriv->blue_values[n] = (FT_Pos)priv->blue_values[n]; 2503 2504 count = cpriv->num_other_blues = priv->num_other_blues; 2505 for ( n = 0; n < count; n++ ) 2506 cpriv->other_blues[n] = (FT_Pos)priv->other_blues[n]; 2507 2508 count = cpriv->num_family_blues = priv->num_family_blues; 2509 for ( n = 0; n < count; n++ ) 2510 cpriv->family_blues[n] = (FT_Pos)priv->family_blues[n]; 2511 2512 count = cpriv->num_family_other_blues = priv->num_family_other_blues; 2513 for ( n = 0; n < count; n++ ) 2514 cpriv->family_other_blues[n] = (FT_Pos)priv->family_other_blues[n]; 2515 2516 cpriv->blue_scale = priv->blue_scale; 2517 cpriv->blue_shift = (FT_Pos)priv->blue_shift; 2518 cpriv->blue_fuzz = (FT_Pos)priv->blue_fuzz; 2519 2520 cpriv->standard_width = (FT_Pos)priv->standard_width[0]; 2521 cpriv->standard_height = (FT_Pos)priv->standard_height[0]; 2522 2523 count = cpriv->num_snap_widths = priv->num_snap_widths; 2524 for ( n = 0; n < count; n++ ) 2525 cpriv->snap_widths[n] = (FT_Pos)priv->snap_widths[n]; 2526 2527 count = cpriv->num_snap_heights = priv->num_snap_heights; 2528 for ( n = 0; n < count; n++ ) 2529 cpriv->snap_heights[n] = (FT_Pos)priv->snap_heights[n]; 2530 2531 cpriv->force_bold = priv->force_bold; 2532 cpriv->lenIV = priv->lenIV; 2533 cpriv->language_group = priv->language_group; 2534 cpriv->expansion_factor = priv->expansion_factor; 2535 2536 cpriv->subfont = subfont; 2537 2538 2539 /* Initialize the random number generator. */ 2540 if ( face->internal->random_seed != -1 ) 2541 { 2542 /* If we have a face-specific seed, use it. */ 2543 /* If non-zero, update it to a positive value. */ 2544 subfont->random = (FT_UInt32)face->internal->random_seed; 2545 if ( face->internal->random_seed ) 2546 { 2547 do 2548 { 2549 face->internal->random_seed = (FT_Int32)cff_random( 2550 (FT_UInt32)face->internal->random_seed ); 2551 2552 } while ( face->internal->random_seed < 0 ); 2553 } 2554 } 2555 if ( !subfont->random ) 2556 { 2557 FT_UInt32 seed; 2558 2559 2560 /* compute random seed from some memory addresses */ 2561 seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ 2562 (FT_Offset)(char*)&face ^ 2563 (FT_Offset)(char*)&subfont ); 2564 seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); 2565 if ( seed == 0 ) 2566 seed = 0x7384; 2567 2568 subfont->random = seed; 2569 } 2570 } 2571 2572 2573 FT_LOCAL_DEF( void ) t1_decrypt(FT_Byte * buffer,FT_Offset length,FT_UShort seed)2574 t1_decrypt( FT_Byte* buffer, 2575 FT_Offset length, 2576 FT_UShort seed ) 2577 { 2578 PS_Conv_EexecDecode( &buffer, 2579 FT_OFFSET( buffer, length ), 2580 buffer, 2581 length, 2582 &seed ); 2583 } 2584 2585 2586 FT_LOCAL_DEF( FT_UInt32 ) cff_random(FT_UInt32 r)2587 cff_random( FT_UInt32 r ) 2588 { 2589 /* a 32bit version of the `xorshift' algorithm */ 2590 r ^= r << 13; 2591 r ^= r >> 17; 2592 r ^= r << 5; 2593 2594 return r; 2595 } 2596 2597 2598 /* END */ 2599