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