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