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