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