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