1 /***************************************************************************/ 2 /* */ 3 /* t1decode.c */ 4 /* */ 5 /* PostScript Type 1 decoding routines (body). */ 6 /* */ 7 /* Copyright 2000-2011 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_CALC_H 21 #include FT_INTERNAL_DEBUG_H 22 #include FT_INTERNAL_POSTSCRIPT_HINTS_H 23 #include FT_OUTLINE_H 24 25 #include "t1decode.h" 26 #include "psobjs.h" 27 28 #include "psauxerr.h" 29 30 /* ensure proper sign extension */ 31 #define Fix2Int( f ) ( (FT_Int)(FT_Short)( (f) >> 16 ) ) 32 33 /*************************************************************************/ 34 /* */ 35 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 36 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 37 /* messages during execution. */ 38 /* */ 39 #undef FT_COMPONENT 40 #define FT_COMPONENT trace_t1decode 41 42 43 typedef enum T1_Operator_ 44 { 45 op_none = 0, 46 op_endchar, 47 op_hsbw, 48 op_seac, 49 op_sbw, 50 op_closepath, 51 op_hlineto, 52 op_hmoveto, 53 op_hvcurveto, 54 op_rlineto, 55 op_rmoveto, 56 op_rrcurveto, 57 op_vhcurveto, 58 op_vlineto, 59 op_vmoveto, 60 op_dotsection, 61 op_hstem, 62 op_hstem3, 63 op_vstem, 64 op_vstem3, 65 op_div, 66 op_callothersubr, 67 op_callsubr, 68 op_pop, 69 op_return, 70 op_setcurrentpoint, 71 op_unknown15, 72 73 op_max /* never remove this one */ 74 75 } T1_Operator; 76 77 78 static 79 const FT_Int t1_args_count[op_max] = 80 { 81 0, /* none */ 82 0, /* endchar */ 83 2, /* hsbw */ 84 5, /* seac */ 85 4, /* sbw */ 86 0, /* closepath */ 87 1, /* hlineto */ 88 1, /* hmoveto */ 89 4, /* hvcurveto */ 90 2, /* rlineto */ 91 2, /* rmoveto */ 92 6, /* rrcurveto */ 93 4, /* vhcurveto */ 94 1, /* vlineto */ 95 1, /* vmoveto */ 96 0, /* dotsection */ 97 2, /* hstem */ 98 6, /* hstem3 */ 99 2, /* vstem */ 100 6, /* vstem3 */ 101 2, /* div */ 102 -1, /* callothersubr */ 103 1, /* callsubr */ 104 0, /* pop */ 105 0, /* return */ 106 2, /* setcurrentpoint */ 107 2 /* opcode 15 (undocumented and obsolete) */ 108 }; 109 110 111 /*************************************************************************/ 112 /* */ 113 /* <Function> */ 114 /* t1_lookup_glyph_by_stdcharcode */ 115 /* */ 116 /* <Description> */ 117 /* Looks up a given glyph by its StandardEncoding charcode. Used to */ 118 /* implement the SEAC Type 1 operator. */ 119 /* */ 120 /* <Input> */ 121 /* face :: The current face object. */ 122 /* */ 123 /* charcode :: The character code to look for. */ 124 /* */ 125 /* <Return> */ 126 /* A glyph index in the font face. Returns -1 if the corresponding */ 127 /* glyph wasn't found. */ 128 /* */ 129 static FT_Int t1_lookup_glyph_by_stdcharcode(T1_Decoder decoder,FT_Int charcode)130 t1_lookup_glyph_by_stdcharcode( T1_Decoder decoder, 131 FT_Int charcode ) 132 { 133 FT_UInt n; 134 const FT_String* glyph_name; 135 FT_Service_PsCMaps psnames = decoder->psnames; 136 137 138 /* check range of standard char code */ 139 if ( charcode < 0 || charcode > 255 ) 140 return -1; 141 142 glyph_name = psnames->adobe_std_strings( 143 psnames->adobe_std_encoding[charcode]); 144 145 for ( n = 0; n < decoder->num_glyphs; n++ ) 146 { 147 FT_String* name = (FT_String*)decoder->glyph_names[n]; 148 149 150 if ( name && 151 name[0] == glyph_name[0] && 152 ft_strcmp( name, glyph_name ) == 0 ) 153 return n; 154 } 155 156 return -1; 157 } 158 159 160 /*************************************************************************/ 161 /* */ 162 /* <Function> */ 163 /* t1operator_seac */ 164 /* */ 165 /* <Description> */ 166 /* Implements the `seac' Type 1 operator for a Type 1 decoder. */ 167 /* */ 168 /* <Input> */ 169 /* decoder :: The current CID decoder. */ 170 /* */ 171 /* asb :: The accent's side bearing. */ 172 /* */ 173 /* adx :: The horizontal offset of the accent. */ 174 /* */ 175 /* ady :: The vertical offset of the accent. */ 176 /* */ 177 /* bchar :: The base character's StandardEncoding charcode. */ 178 /* */ 179 /* achar :: The accent character's StandardEncoding charcode. */ 180 /* */ 181 /* <Return> */ 182 /* FreeType error code. 0 means success. */ 183 /* */ 184 static FT_Error t1operator_seac(T1_Decoder decoder,FT_Pos asb,FT_Pos adx,FT_Pos ady,FT_Int bchar,FT_Int achar)185 t1operator_seac( T1_Decoder decoder, 186 FT_Pos asb, 187 FT_Pos adx, 188 FT_Pos ady, 189 FT_Int bchar, 190 FT_Int achar ) 191 { 192 FT_Error error; 193 FT_Int bchar_index, achar_index; 194 #if 0 195 FT_Int n_base_points; 196 FT_Outline* base = decoder->builder.base; 197 #endif 198 FT_Vector left_bearing, advance; 199 200 #ifdef FT_CONFIG_OPTION_INCREMENTAL 201 T1_Face face = (T1_Face)decoder->builder.face; 202 #endif 203 204 205 if ( decoder->seac ) 206 { 207 FT_ERROR(( "t1operator_seac: invalid nested seac\n" )); 208 return PSaux_Err_Syntax_Error; 209 } 210 211 /* seac weirdness */ 212 adx += decoder->builder.left_bearing.x; 213 214 /* `glyph_names' is set to 0 for CID fonts which do not */ 215 /* include an encoding. How can we deal with these? */ 216 #ifdef FT_CONFIG_OPTION_INCREMENTAL 217 if ( decoder->glyph_names == 0 && 218 !face->root.internal->incremental_interface ) 219 #else 220 if ( decoder->glyph_names == 0 ) 221 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 222 { 223 FT_ERROR(( "t1operator_seac:" 224 " glyph names table not available in this font\n" )); 225 return PSaux_Err_Syntax_Error; 226 } 227 228 #ifdef FT_CONFIG_OPTION_INCREMENTAL 229 if ( face->root.internal->incremental_interface ) 230 { 231 /* the caller must handle the font encoding also */ 232 bchar_index = bchar; 233 achar_index = achar; 234 } 235 else 236 #endif 237 { 238 bchar_index = t1_lookup_glyph_by_stdcharcode( decoder, bchar ); 239 achar_index = t1_lookup_glyph_by_stdcharcode( decoder, achar ); 240 } 241 242 if ( bchar_index < 0 || achar_index < 0 ) 243 { 244 FT_ERROR(( "t1operator_seac:" 245 " invalid seac character code arguments\n" )); 246 return PSaux_Err_Syntax_Error; 247 } 248 249 /* if we are trying to load a composite glyph, do not load the */ 250 /* accent character and return the array of subglyphs. */ 251 if ( decoder->builder.no_recurse ) 252 { 253 FT_GlyphSlot glyph = (FT_GlyphSlot)decoder->builder.glyph; 254 FT_GlyphLoader loader = glyph->internal->loader; 255 FT_SubGlyph subg; 256 257 258 /* reallocate subglyph array if necessary */ 259 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 260 if ( error ) 261 goto Exit; 262 263 subg = loader->current.subglyphs; 264 265 /* subglyph 0 = base character */ 266 subg->index = bchar_index; 267 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 268 FT_SUBGLYPH_FLAG_USE_MY_METRICS; 269 subg->arg1 = 0; 270 subg->arg2 = 0; 271 subg++; 272 273 /* subglyph 1 = accent character */ 274 subg->index = achar_index; 275 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 276 subg->arg1 = (FT_Int)FIXED_TO_INT( adx - asb ); 277 subg->arg2 = (FT_Int)FIXED_TO_INT( ady ); 278 279 /* set up remaining glyph fields */ 280 glyph->num_subglyphs = 2; 281 glyph->subglyphs = loader->base.subglyphs; 282 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 283 284 loader->current.num_subglyphs = 2; 285 goto Exit; 286 } 287 288 /* First load `bchar' in builder */ 289 /* now load the unscaled outline */ 290 291 FT_GlyphLoader_Prepare( decoder->builder.loader ); /* prepare loader */ 292 293 /* the seac operator must not be nested */ 294 decoder->seac = TRUE; 295 error = t1_decoder_parse_glyph( decoder, bchar_index ); 296 decoder->seac = FALSE; 297 if ( error ) 298 goto Exit; 299 300 /* save the left bearing and width of the base character */ 301 /* as they will be erased by the next load. */ 302 303 left_bearing = decoder->builder.left_bearing; 304 advance = decoder->builder.advance; 305 306 decoder->builder.left_bearing.x = 0; 307 decoder->builder.left_bearing.y = 0; 308 309 decoder->builder.pos_x = adx - asb; 310 decoder->builder.pos_y = ady; 311 312 /* Now load `achar' on top of */ 313 /* the base outline */ 314 315 /* the seac operator must not be nested */ 316 decoder->seac = TRUE; 317 error = t1_decoder_parse_glyph( decoder, achar_index ); 318 decoder->seac = FALSE; 319 if ( error ) 320 goto Exit; 321 322 /* restore the left side bearing and */ 323 /* advance width of the base character */ 324 325 decoder->builder.left_bearing = left_bearing; 326 decoder->builder.advance = advance; 327 328 decoder->builder.pos_x = 0; 329 decoder->builder.pos_y = 0; 330 331 Exit: 332 return error; 333 } 334 335 336 /*************************************************************************/ 337 /* */ 338 /* <Function> */ 339 /* t1_decoder_parse_charstrings */ 340 /* */ 341 /* <Description> */ 342 /* Parses a given Type 1 charstrings program. */ 343 /* */ 344 /* <Input> */ 345 /* decoder :: The current Type 1 decoder. */ 346 /* */ 347 /* charstring_base :: The base address of the charstring stream. */ 348 /* */ 349 /* charstring_len :: The length in bytes of the charstring stream. */ 350 /* */ 351 /* <Return> */ 352 /* FreeType error code. 0 means success. */ 353 /* */ 354 FT_LOCAL_DEF( FT_Error ) t1_decoder_parse_charstrings(T1_Decoder decoder,FT_Byte * charstring_base,FT_UInt charstring_len)355 t1_decoder_parse_charstrings( T1_Decoder decoder, 356 FT_Byte* charstring_base, 357 FT_UInt charstring_len ) 358 { 359 FT_Error error; 360 T1_Decoder_Zone zone; 361 FT_Byte* ip; 362 FT_Byte* limit; 363 T1_Builder builder = &decoder->builder; 364 FT_Pos x, y, orig_x, orig_y; 365 FT_Int known_othersubr_result_cnt = 0; 366 FT_Int unknown_othersubr_result_cnt = 0; 367 FT_Bool large_int; 368 FT_Fixed seed; 369 370 T1_Hints_Funcs hinter; 371 372 #ifdef FT_DEBUG_LEVEL_TRACE 373 FT_Bool bol = TRUE; 374 #endif 375 376 377 /* compute random seed from stack address of parameter */ 378 seed = (FT_Fixed)( ( (FT_PtrDist)(char*)&seed ^ 379 (FT_PtrDist)(char*)&decoder ^ 380 (FT_PtrDist)(char*)&charstring_base ) & 381 FT_ULONG_MAX ) ; 382 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; 383 if ( seed == 0 ) 384 seed = 0x7384; 385 386 /* First of all, initialize the decoder */ 387 decoder->top = decoder->stack; 388 decoder->zone = decoder->zones; 389 zone = decoder->zones; 390 391 builder->parse_state = T1_Parse_Start; 392 393 hinter = (T1_Hints_Funcs)builder->hints_funcs; 394 395 /* a font that reads BuildCharArray without setting */ 396 /* its values first is buggy, but ... */ 397 FT_ASSERT( ( decoder->len_buildchar == 0 ) == 398 ( decoder->buildchar == NULL ) ); 399 400 if ( decoder->buildchar && decoder->len_buildchar > 0 ) 401 ft_memset( &decoder->buildchar[0], 402 0, 403 sizeof( decoder->buildchar[0] ) * decoder->len_buildchar ); 404 405 FT_TRACE4(( "\n" 406 "Start charstring\n" )); 407 408 zone->base = charstring_base; 409 limit = zone->limit = charstring_base + charstring_len; 410 ip = zone->cursor = zone->base; 411 412 error = PSaux_Err_Ok; 413 414 x = orig_x = builder->pos_x; 415 y = orig_y = builder->pos_y; 416 417 /* begin hints recording session, if any */ 418 if ( hinter ) 419 hinter->open( hinter->hints ); 420 421 large_int = FALSE; 422 423 /* now, execute loop */ 424 while ( ip < limit ) 425 { 426 FT_Long* top = decoder->top; 427 T1_Operator op = op_none; 428 FT_Int32 value = 0; 429 430 431 FT_ASSERT( known_othersubr_result_cnt == 0 || 432 unknown_othersubr_result_cnt == 0 ); 433 434 #ifdef FT_DEBUG_LEVEL_TRACE 435 if ( bol ) 436 { 437 FT_TRACE5(( " (%d)", decoder->top - decoder->stack )); 438 bol = FALSE; 439 } 440 #endif 441 442 /*********************************************************************/ 443 /* */ 444 /* Decode operator or operand */ 445 /* */ 446 /* */ 447 448 /* first of all, decompress operator or value */ 449 switch ( *ip++ ) 450 { 451 case 1: 452 op = op_hstem; 453 break; 454 455 case 3: 456 op = op_vstem; 457 break; 458 case 4: 459 op = op_vmoveto; 460 break; 461 case 5: 462 op = op_rlineto; 463 break; 464 case 6: 465 op = op_hlineto; 466 break; 467 case 7: 468 op = op_vlineto; 469 break; 470 case 8: 471 op = op_rrcurveto; 472 break; 473 case 9: 474 op = op_closepath; 475 break; 476 case 10: 477 op = op_callsubr; 478 break; 479 case 11: 480 op = op_return; 481 break; 482 483 case 13: 484 op = op_hsbw; 485 break; 486 case 14: 487 op = op_endchar; 488 break; 489 490 case 15: /* undocumented, obsolete operator */ 491 op = op_unknown15; 492 break; 493 494 case 21: 495 op = op_rmoveto; 496 break; 497 case 22: 498 op = op_hmoveto; 499 break; 500 501 case 30: 502 op = op_vhcurveto; 503 break; 504 case 31: 505 op = op_hvcurveto; 506 break; 507 508 case 12: 509 if ( ip > limit ) 510 { 511 FT_ERROR(( "t1_decoder_parse_charstrings:" 512 " invalid escape (12+EOF)\n" )); 513 goto Syntax_Error; 514 } 515 516 switch ( *ip++ ) 517 { 518 case 0: 519 op = op_dotsection; 520 break; 521 case 1: 522 op = op_vstem3; 523 break; 524 case 2: 525 op = op_hstem3; 526 break; 527 case 6: 528 op = op_seac; 529 break; 530 case 7: 531 op = op_sbw; 532 break; 533 case 12: 534 op = op_div; 535 break; 536 case 16: 537 op = op_callothersubr; 538 break; 539 case 17: 540 op = op_pop; 541 break; 542 case 33: 543 op = op_setcurrentpoint; 544 break; 545 546 default: 547 FT_ERROR(( "t1_decoder_parse_charstrings:" 548 " invalid escape (12+%d)\n", 549 ip[-1] )); 550 goto Syntax_Error; 551 } 552 break; 553 554 case 255: /* four bytes integer */ 555 if ( ip + 4 > limit ) 556 { 557 FT_ERROR(( "t1_decoder_parse_charstrings:" 558 " unexpected EOF in integer\n" )); 559 goto Syntax_Error; 560 } 561 562 value = (FT_Int32)( ( (FT_Long)ip[0] << 24 ) | 563 ( (FT_Long)ip[1] << 16 ) | 564 ( (FT_Long)ip[2] << 8 ) | 565 ip[3] ); 566 ip += 4; 567 568 /* According to the specification, values > 32000 or < -32000 must */ 569 /* be followed by a `div' operator to make the result be in the */ 570 /* range [-32000;32000]. We expect that the second argument of */ 571 /* `div' is not a large number. Additionally, we don't handle */ 572 /* stuff like `<large1> <large2> <num> div <num> div' or */ 573 /* <large1> <large2> <num> div div'. This is probably not allowed */ 574 /* anyway. */ 575 if ( value > 32000 || value < -32000 ) 576 { 577 if ( large_int ) 578 { 579 FT_ERROR(( "t1_decoder_parse_charstrings:" 580 " no `div' after large integer\n" )); 581 } 582 else 583 large_int = TRUE; 584 } 585 else 586 { 587 if ( !large_int ) 588 value <<= 16; 589 } 590 591 break; 592 593 default: 594 if ( ip[-1] >= 32 ) 595 { 596 if ( ip[-1] < 247 ) 597 value = (FT_Int32)ip[-1] - 139; 598 else 599 { 600 if ( ++ip > limit ) 601 { 602 FT_ERROR(( "t1_decoder_parse_charstrings:" 603 " unexpected EOF in integer\n" )); 604 goto Syntax_Error; 605 } 606 607 if ( ip[-2] < 251 ) 608 value = ( ( (FT_Int32)ip[-2] - 247 ) << 8 ) + ip[-1] + 108; 609 else 610 value = -( ( ( (FT_Int32)ip[-2] - 251 ) << 8 ) + ip[-1] + 108 ); 611 } 612 613 if ( !large_int ) 614 value <<= 16; 615 } 616 else 617 { 618 FT_ERROR(( "t1_decoder_parse_charstrings:" 619 " invalid byte (%d)\n", ip[-1] )); 620 goto Syntax_Error; 621 } 622 } 623 624 if ( unknown_othersubr_result_cnt > 0 ) 625 { 626 switch ( op ) 627 { 628 case op_callsubr: 629 case op_return: 630 case op_none: 631 case op_pop: 632 break; 633 634 default: 635 /* all operands have been transferred by previous pops */ 636 unknown_othersubr_result_cnt = 0; 637 break; 638 } 639 } 640 641 if ( large_int && !( op == op_none || op == op_div ) ) 642 { 643 FT_ERROR(( "t1_decoder_parse_charstrings:" 644 " no `div' after large integer\n" )); 645 646 large_int = FALSE; 647 } 648 649 /*********************************************************************/ 650 /* */ 651 /* Push value on stack, or process operator */ 652 /* */ 653 /* */ 654 if ( op == op_none ) 655 { 656 if ( top - decoder->stack >= T1_MAX_CHARSTRINGS_OPERANDS ) 657 { 658 FT_ERROR(( "t1_decoder_parse_charstrings: stack overflow\n" )); 659 goto Syntax_Error; 660 } 661 662 #ifdef FT_DEBUG_LEVEL_TRACE 663 if ( large_int ) 664 FT_TRACE4(( " %ld", value )); 665 else 666 FT_TRACE4(( " %ld", Fix2Int( value ) )); 667 #endif 668 669 *top++ = value; 670 decoder->top = top; 671 } 672 else if ( op == op_callothersubr ) /* callothersubr */ 673 { 674 FT_Int subr_no; 675 FT_Int arg_cnt; 676 677 678 #ifdef FT_DEBUG_LEVEL_TRACE 679 FT_TRACE4(( " callothersubr\n" )); 680 bol = TRUE; 681 #endif 682 683 if ( top - decoder->stack < 2 ) 684 goto Stack_Underflow; 685 686 top -= 2; 687 688 subr_no = Fix2Int( top[1] ); 689 arg_cnt = Fix2Int( top[0] ); 690 691 /***********************************************************/ 692 /* */ 693 /* remove all operands to callothersubr from the stack */ 694 /* */ 695 /* for handled othersubrs, where we know the number of */ 696 /* arguments, we increase the stack by the value of */ 697 /* known_othersubr_result_cnt */ 698 /* */ 699 /* for unhandled othersubrs the following pops adjust the */ 700 /* stack pointer as necessary */ 701 702 if ( arg_cnt > top - decoder->stack ) 703 goto Stack_Underflow; 704 705 top -= arg_cnt; 706 707 known_othersubr_result_cnt = 0; 708 unknown_othersubr_result_cnt = 0; 709 710 /* XXX TODO: The checks to `arg_count == <whatever>' */ 711 /* might not be correct; an othersubr expects a certain */ 712 /* number of operands on the PostScript stack (as opposed */ 713 /* to the T1 stack) but it doesn't have to put them there */ 714 /* by itself; previous othersubrs might have left the */ 715 /* operands there if they were not followed by an */ 716 /* appropriate number of pops */ 717 /* */ 718 /* On the other hand, Adobe Reader 7.0.8 for Linux doesn't */ 719 /* accept a font that contains charstrings like */ 720 /* */ 721 /* 100 200 2 20 callothersubr */ 722 /* 300 1 20 callothersubr pop */ 723 /* */ 724 /* Perhaps this is the reason why BuildCharArray exists. */ 725 726 switch ( subr_no ) 727 { 728 case 0: /* end flex feature */ 729 if ( arg_cnt != 3 ) 730 goto Unexpected_OtherSubr; 731 732 if ( decoder->flex_state == 0 || 733 decoder->num_flex_vectors != 7 ) 734 { 735 FT_ERROR(( "t1_decoder_parse_charstrings:" 736 " unexpected flex end\n" )); 737 goto Syntax_Error; 738 } 739 740 /* the two `results' are popped by the following setcurrentpoint */ 741 top[0] = x; 742 top[1] = y; 743 known_othersubr_result_cnt = 2; 744 break; 745 746 case 1: /* start flex feature */ 747 if ( arg_cnt != 0 ) 748 goto Unexpected_OtherSubr; 749 750 decoder->flex_state = 1; 751 decoder->num_flex_vectors = 0; 752 if ( ( error = t1_builder_start_point( builder, x, y ) ) 753 != PSaux_Err_Ok || 754 ( error = t1_builder_check_points( builder, 6 ) ) 755 != PSaux_Err_Ok ) 756 goto Fail; 757 break; 758 759 case 2: /* add flex vectors */ 760 { 761 FT_Int idx; 762 763 764 if ( arg_cnt != 0 ) 765 goto Unexpected_OtherSubr; 766 767 /* note that we should not add a point for index 0; */ 768 /* this will move our current position to the flex */ 769 /* point without adding any point to the outline */ 770 idx = decoder->num_flex_vectors++; 771 if ( idx > 0 && idx < 7 ) 772 t1_builder_add_point( builder, 773 x, 774 y, 775 (FT_Byte)( idx == 3 || idx == 6 ) ); 776 } 777 break; 778 779 case 3: /* change hints */ 780 if ( arg_cnt != 1 ) 781 goto Unexpected_OtherSubr; 782 783 known_othersubr_result_cnt = 1; 784 785 if ( hinter ) 786 hinter->reset( hinter->hints, builder->current->n_points ); 787 break; 788 789 case 12: 790 case 13: 791 /* counter control hints, clear stack */ 792 top = decoder->stack; 793 break; 794 795 case 14: 796 case 15: 797 case 16: 798 case 17: 799 case 18: /* multiple masters */ 800 { 801 PS_Blend blend = decoder->blend; 802 FT_UInt num_points, nn, mm; 803 FT_Long* delta; 804 FT_Long* values; 805 806 807 if ( !blend ) 808 { 809 FT_ERROR(( "t1_decoder_parse_charstrings:" 810 " unexpected multiple masters operator\n" )); 811 goto Syntax_Error; 812 } 813 814 num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); 815 if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) 816 { 817 FT_ERROR(( "t1_decoder_parse_charstrings:" 818 " incorrect number of multiple masters arguments\n" )); 819 goto Syntax_Error; 820 } 821 822 /* We want to compute */ 823 /* */ 824 /* a0*w0 + a1*w1 + ... + ak*wk */ 825 /* */ 826 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ 827 /* */ 828 /* However, given that w0 + w1 + ... + wk == 1, we can */ 829 /* rewrite it easily as */ 830 /* */ 831 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ 832 /* */ 833 /* where k == num_designs-1. */ 834 /* */ 835 /* I guess that's why it's written in this `compact' */ 836 /* form. */ 837 /* */ 838 delta = top + num_points; 839 values = top; 840 for ( nn = 0; nn < num_points; nn++ ) 841 { 842 FT_Long tmp = values[0]; 843 844 845 for ( mm = 1; mm < blend->num_designs; mm++ ) 846 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); 847 848 *values++ = tmp; 849 } 850 851 known_othersubr_result_cnt = num_points; 852 break; 853 } 854 855 case 19: 856 /* <idx> 1 19 callothersubr */ 857 /* => replace elements starting from index cvi( <idx> ) */ 858 /* of BuildCharArray with WeightVector */ 859 { 860 FT_Int idx; 861 PS_Blend blend = decoder->blend; 862 863 864 if ( arg_cnt != 1 || blend == NULL ) 865 goto Unexpected_OtherSubr; 866 867 idx = Fix2Int( top[0] ); 868 869 if ( idx < 0 || 870 idx + blend->num_designs > decoder->len_buildchar ) 871 goto Unexpected_OtherSubr; 872 873 ft_memcpy( &decoder->buildchar[idx], 874 blend->weight_vector, 875 blend->num_designs * 876 sizeof( blend->weight_vector[0] ) ); 877 } 878 break; 879 880 case 20: 881 /* <arg1> <arg2> 2 20 callothersubr pop */ 882 /* ==> push <arg1> + <arg2> onto T1 stack */ 883 if ( arg_cnt != 2 ) 884 goto Unexpected_OtherSubr; 885 886 top[0] += top[1]; /* XXX (over|under)flow */ 887 888 known_othersubr_result_cnt = 1; 889 break; 890 891 case 21: 892 /* <arg1> <arg2> 2 21 callothersubr pop */ 893 /* ==> push <arg1> - <arg2> onto T1 stack */ 894 if ( arg_cnt != 2 ) 895 goto Unexpected_OtherSubr; 896 897 top[0] -= top[1]; /* XXX (over|under)flow */ 898 899 known_othersubr_result_cnt = 1; 900 break; 901 902 case 22: 903 /* <arg1> <arg2> 2 22 callothersubr pop */ 904 /* ==> push <arg1> * <arg2> onto T1 stack */ 905 if ( arg_cnt != 2 ) 906 goto Unexpected_OtherSubr; 907 908 top[0] = FT_MulFix( top[0], top[1] ); 909 910 known_othersubr_result_cnt = 1; 911 break; 912 913 case 23: 914 /* <arg1> <arg2> 2 23 callothersubr pop */ 915 /* ==> push <arg1> / <arg2> onto T1 stack */ 916 if ( arg_cnt != 2 || top[1] == 0 ) 917 goto Unexpected_OtherSubr; 918 919 top[0] = FT_DivFix( top[0], top[1] ); 920 921 known_othersubr_result_cnt = 1; 922 break; 923 924 case 24: 925 /* <val> <idx> 2 24 callothersubr */ 926 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 927 { 928 FT_Int idx; 929 PS_Blend blend = decoder->blend; 930 931 932 if ( arg_cnt != 2 || blend == NULL ) 933 goto Unexpected_OtherSubr; 934 935 idx = Fix2Int( top[1] ); 936 937 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) 938 goto Unexpected_OtherSubr; 939 940 decoder->buildchar[idx] = top[0]; 941 } 942 break; 943 944 case 25: 945 /* <idx> 1 25 callothersubr pop */ 946 /* ==> push BuildCharArray[cvi( idx )] */ 947 /* onto T1 stack */ 948 { 949 FT_Int idx; 950 PS_Blend blend = decoder->blend; 951 952 953 if ( arg_cnt != 1 || blend == NULL ) 954 goto Unexpected_OtherSubr; 955 956 idx = Fix2Int( top[0] ); 957 958 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) 959 goto Unexpected_OtherSubr; 960 961 top[0] = decoder->buildchar[idx]; 962 } 963 964 known_othersubr_result_cnt = 1; 965 break; 966 967 #if 0 968 case 26: 969 /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ 970 /* leave mark on T1 stack */ 971 /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ 972 XXX which routine has left its mark on the (PostScript) stack?; 973 break; 974 #endif 975 976 case 27: 977 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ 978 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ 979 /* otherwise push <res2> */ 980 if ( arg_cnt != 4 ) 981 goto Unexpected_OtherSubr; 982 983 if ( top[2] > top[3] ) 984 top[0] = top[1]; 985 986 known_othersubr_result_cnt = 1; 987 break; 988 989 case 28: 990 /* 0 28 callothersubr pop */ 991 /* => push random value from interval [0, 1) onto stack */ 992 if ( arg_cnt != 0 ) 993 goto Unexpected_OtherSubr; 994 995 { 996 FT_Fixed Rand; 997 998 999 Rand = seed; 1000 if ( Rand >= 0x8000L ) 1001 Rand++; 1002 1003 top[0] = Rand; 1004 1005 seed = FT_MulFix( seed, 0x10000L - seed ); 1006 if ( seed == 0 ) 1007 seed += 0x2873; 1008 } 1009 1010 known_othersubr_result_cnt = 1; 1011 break; 1012 1013 default: 1014 if ( arg_cnt >= 0 && subr_no >= 0 ) 1015 { 1016 FT_ERROR(( "t1_decoder_parse_charstrings:" 1017 " unknown othersubr [%d %d], wish me luck\n", 1018 arg_cnt, subr_no )); 1019 unknown_othersubr_result_cnt = arg_cnt; 1020 break; 1021 } 1022 /* fall through */ 1023 1024 Unexpected_OtherSubr: 1025 FT_ERROR(( "t1_decoder_parse_charstrings:" 1026 " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); 1027 goto Syntax_Error; 1028 } 1029 1030 top += known_othersubr_result_cnt; 1031 1032 decoder->top = top; 1033 } 1034 else /* general operator */ 1035 { 1036 FT_Int num_args = t1_args_count[op]; 1037 1038 1039 FT_ASSERT( num_args >= 0 ); 1040 1041 if ( top - decoder->stack < num_args ) 1042 goto Stack_Underflow; 1043 1044 /* XXX Operators usually take their operands from the */ 1045 /* bottom of the stack, i.e., the operands are */ 1046 /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ 1047 /* only div, callsubr, and callothersubr are different. */ 1048 /* In practice it doesn't matter (?). */ 1049 1050 #ifdef FT_DEBUG_LEVEL_TRACE 1051 1052 switch ( op ) 1053 { 1054 case op_callsubr: 1055 case op_div: 1056 case op_callothersubr: 1057 case op_pop: 1058 case op_return: 1059 break; 1060 1061 default: 1062 if ( top - decoder->stack != num_args ) 1063 FT_TRACE0(( "t1_decoder_parse_charstrings:" 1064 " too much operands on the stack" 1065 " (seen %d, expected %d)\n", 1066 top - decoder->stack, num_args )); 1067 break; 1068 } 1069 1070 #endif /* FT_DEBUG_LEVEL_TRACE */ 1071 1072 top -= num_args; 1073 1074 switch ( op ) 1075 { 1076 case op_endchar: 1077 FT_TRACE4(( " endchar\n" )); 1078 1079 t1_builder_close_contour( builder ); 1080 1081 /* close hints recording session */ 1082 if ( hinter ) 1083 { 1084 if ( hinter->close( hinter->hints, builder->current->n_points ) ) 1085 goto Syntax_Error; 1086 1087 /* apply hints to the loaded glyph outline now */ 1088 hinter->apply( hinter->hints, 1089 builder->current, 1090 (PSH_Globals)builder->hints_globals, 1091 decoder->hint_mode ); 1092 } 1093 1094 /* add current outline to the glyph slot */ 1095 FT_GlyphLoader_Add( builder->loader ); 1096 1097 /* the compiler should optimize away this empty loop but ... */ 1098 1099 #ifdef FT_DEBUG_LEVEL_TRACE 1100 1101 if ( decoder->len_buildchar > 0 ) 1102 { 1103 FT_UInt i; 1104 1105 1106 FT_TRACE4(( "BuildCharArray = [ " )); 1107 1108 for ( i = 0; i < decoder->len_buildchar; ++i ) 1109 FT_TRACE4(( "%d ", decoder->buildchar[ i ] )); 1110 1111 FT_TRACE4(( "]\n" )); 1112 } 1113 1114 #endif /* FT_DEBUG_LEVEL_TRACE */ 1115 1116 FT_TRACE4(( "\n" )); 1117 1118 /* return now! */ 1119 return PSaux_Err_Ok; 1120 1121 case op_hsbw: 1122 FT_TRACE4(( " hsbw" )); 1123 1124 builder->parse_state = T1_Parse_Have_Width; 1125 1126 builder->left_bearing.x += top[0]; 1127 builder->advance.x = top[1]; 1128 builder->advance.y = 0; 1129 1130 orig_x = x = builder->pos_x + top[0]; 1131 orig_y = y = builder->pos_y; 1132 1133 FT_UNUSED( orig_y ); 1134 1135 /* the `metrics_only' indicates that we only want to compute */ 1136 /* the glyph's metrics (lsb + advance width), not load the */ 1137 /* rest of it; so exit immediately */ 1138 if ( builder->metrics_only ) 1139 return PSaux_Err_Ok; 1140 1141 break; 1142 1143 case op_seac: 1144 return t1operator_seac( decoder, 1145 top[0], 1146 top[1], 1147 top[2], 1148 Fix2Int( top[3] ), 1149 Fix2Int( top[4] ) ); 1150 1151 case op_sbw: 1152 FT_TRACE4(( " sbw" )); 1153 1154 builder->parse_state = T1_Parse_Have_Width; 1155 1156 builder->left_bearing.x += top[0]; 1157 builder->left_bearing.y += top[1]; 1158 builder->advance.x = top[2]; 1159 builder->advance.y = top[3]; 1160 1161 x = builder->pos_x + top[0]; 1162 y = builder->pos_y + top[1]; 1163 1164 /* the `metrics_only' indicates that we only want to compute */ 1165 /* the glyph's metrics (lsb + advance width), not load the */ 1166 /* rest of it; so exit immediately */ 1167 if ( builder->metrics_only ) 1168 return PSaux_Err_Ok; 1169 1170 break; 1171 1172 case op_closepath: 1173 FT_TRACE4(( " closepath" )); 1174 1175 /* if there is no path, `closepath' is a no-op */ 1176 if ( builder->parse_state == T1_Parse_Have_Path || 1177 builder->parse_state == T1_Parse_Have_Moveto ) 1178 t1_builder_close_contour( builder ); 1179 1180 builder->parse_state = T1_Parse_Have_Width; 1181 break; 1182 1183 case op_hlineto: 1184 FT_TRACE4(( " hlineto" )); 1185 1186 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1187 != PSaux_Err_Ok ) 1188 goto Fail; 1189 1190 x += top[0]; 1191 goto Add_Line; 1192 1193 case op_hmoveto: 1194 FT_TRACE4(( " hmoveto" )); 1195 1196 x += top[0]; 1197 if ( !decoder->flex_state ) 1198 { 1199 if ( builder->parse_state == T1_Parse_Start ) 1200 goto Syntax_Error; 1201 builder->parse_state = T1_Parse_Have_Moveto; 1202 } 1203 break; 1204 1205 case op_hvcurveto: 1206 FT_TRACE4(( " hvcurveto" )); 1207 1208 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1209 != PSaux_Err_Ok || 1210 ( error = t1_builder_check_points( builder, 3 ) ) 1211 != PSaux_Err_Ok ) 1212 goto Fail; 1213 1214 x += top[0]; 1215 t1_builder_add_point( builder, x, y, 0 ); 1216 x += top[1]; 1217 y += top[2]; 1218 t1_builder_add_point( builder, x, y, 0 ); 1219 y += top[3]; 1220 t1_builder_add_point( builder, x, y, 1 ); 1221 break; 1222 1223 case op_rlineto: 1224 FT_TRACE4(( " rlineto" )); 1225 1226 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1227 != PSaux_Err_Ok ) 1228 goto Fail; 1229 1230 x += top[0]; 1231 y += top[1]; 1232 1233 Add_Line: 1234 if ( ( error = t1_builder_add_point1( builder, x, y ) ) 1235 != PSaux_Err_Ok ) 1236 goto Fail; 1237 break; 1238 1239 case op_rmoveto: 1240 FT_TRACE4(( " rmoveto" )); 1241 1242 x += top[0]; 1243 y += top[1]; 1244 if ( !decoder->flex_state ) 1245 { 1246 if ( builder->parse_state == T1_Parse_Start ) 1247 goto Syntax_Error; 1248 builder->parse_state = T1_Parse_Have_Moveto; 1249 } 1250 break; 1251 1252 case op_rrcurveto: 1253 FT_TRACE4(( " rrcurveto" )); 1254 1255 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1256 != PSaux_Err_Ok || 1257 ( error = t1_builder_check_points( builder, 3 ) ) 1258 != PSaux_Err_Ok ) 1259 goto Fail; 1260 1261 x += top[0]; 1262 y += top[1]; 1263 t1_builder_add_point( builder, x, y, 0 ); 1264 1265 x += top[2]; 1266 y += top[3]; 1267 t1_builder_add_point( builder, x, y, 0 ); 1268 1269 x += top[4]; 1270 y += top[5]; 1271 t1_builder_add_point( builder, x, y, 1 ); 1272 break; 1273 1274 case op_vhcurveto: 1275 FT_TRACE4(( " vhcurveto" )); 1276 1277 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1278 != PSaux_Err_Ok || 1279 ( error = t1_builder_check_points( builder, 3 ) ) 1280 != PSaux_Err_Ok ) 1281 goto Fail; 1282 1283 y += top[0]; 1284 t1_builder_add_point( builder, x, y, 0 ); 1285 x += top[1]; 1286 y += top[2]; 1287 t1_builder_add_point( builder, x, y, 0 ); 1288 x += top[3]; 1289 t1_builder_add_point( builder, x, y, 1 ); 1290 break; 1291 1292 case op_vlineto: 1293 FT_TRACE4(( " vlineto" )); 1294 1295 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1296 != PSaux_Err_Ok ) 1297 goto Fail; 1298 1299 y += top[0]; 1300 goto Add_Line; 1301 1302 case op_vmoveto: 1303 FT_TRACE4(( " vmoveto" )); 1304 1305 y += top[0]; 1306 if ( !decoder->flex_state ) 1307 { 1308 if ( builder->parse_state == T1_Parse_Start ) 1309 goto Syntax_Error; 1310 builder->parse_state = T1_Parse_Have_Moveto; 1311 } 1312 break; 1313 1314 case op_div: 1315 FT_TRACE4(( " div" )); 1316 1317 /* if `large_int' is set, we divide unscaled numbers; */ 1318 /* otherwise, we divide numbers in 16.16 format -- */ 1319 /* in both cases, it is the same operation */ 1320 *top = FT_DivFix( top[0], top[1] ); 1321 ++top; 1322 1323 large_int = FALSE; 1324 break; 1325 1326 case op_callsubr: 1327 { 1328 FT_Int idx; 1329 1330 1331 FT_TRACE4(( " callsubr" )); 1332 1333 idx = Fix2Int( top[0] ); 1334 if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) 1335 { 1336 FT_ERROR(( "t1_decoder_parse_charstrings:" 1337 " invalid subrs index\n" )); 1338 goto Syntax_Error; 1339 } 1340 1341 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) 1342 { 1343 FT_ERROR(( "t1_decoder_parse_charstrings:" 1344 " too many nested subrs\n" )); 1345 goto Syntax_Error; 1346 } 1347 1348 zone->cursor = ip; /* save current instruction pointer */ 1349 1350 zone++; 1351 1352 /* The Type 1 driver stores subroutines without the seed bytes. */ 1353 /* The CID driver stores subroutines with seed bytes. This */ 1354 /* case is taken care of when decoder->subrs_len == 0. */ 1355 zone->base = decoder->subrs[idx]; 1356 1357 if ( decoder->subrs_len ) 1358 zone->limit = zone->base + decoder->subrs_len[idx]; 1359 else 1360 { 1361 /* We are using subroutines from a CID font. We must adjust */ 1362 /* for the seed bytes. */ 1363 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); 1364 zone->limit = decoder->subrs[idx + 1]; 1365 } 1366 1367 zone->cursor = zone->base; 1368 1369 if ( !zone->base ) 1370 { 1371 FT_ERROR(( "t1_decoder_parse_charstrings:" 1372 " invoking empty subrs\n" )); 1373 goto Syntax_Error; 1374 } 1375 1376 decoder->zone = zone; 1377 ip = zone->base; 1378 limit = zone->limit; 1379 break; 1380 } 1381 1382 case op_pop: 1383 FT_TRACE4(( " pop" )); 1384 1385 if ( known_othersubr_result_cnt > 0 ) 1386 { 1387 known_othersubr_result_cnt--; 1388 /* ignore, we pushed the operands ourselves */ 1389 break; 1390 } 1391 1392 if ( unknown_othersubr_result_cnt == 0 ) 1393 { 1394 FT_ERROR(( "t1_decoder_parse_charstrings:" 1395 " no more operands for othersubr\n" )); 1396 goto Syntax_Error; 1397 } 1398 1399 unknown_othersubr_result_cnt--; 1400 top++; /* `push' the operand to callothersubr onto the stack */ 1401 break; 1402 1403 case op_return: 1404 FT_TRACE4(( " return" )); 1405 1406 if ( zone <= decoder->zones ) 1407 { 1408 FT_ERROR(( "t1_decoder_parse_charstrings:" 1409 " unexpected return\n" )); 1410 goto Syntax_Error; 1411 } 1412 1413 zone--; 1414 ip = zone->cursor; 1415 limit = zone->limit; 1416 decoder->zone = zone; 1417 break; 1418 1419 case op_dotsection: 1420 FT_TRACE4(( " dotsection" )); 1421 1422 break; 1423 1424 case op_hstem: 1425 FT_TRACE4(( " hstem" )); 1426 1427 /* record horizontal hint */ 1428 if ( hinter ) 1429 { 1430 /* top[0] += builder->left_bearing.y; */ 1431 hinter->stem( hinter->hints, 1, top ); 1432 } 1433 break; 1434 1435 case op_hstem3: 1436 FT_TRACE4(( " hstem3" )); 1437 1438 /* record horizontal counter-controlled hints */ 1439 if ( hinter ) 1440 hinter->stem3( hinter->hints, 1, top ); 1441 break; 1442 1443 case op_vstem: 1444 FT_TRACE4(( " vstem" )); 1445 1446 /* record vertical hint */ 1447 if ( hinter ) 1448 { 1449 top[0] += orig_x; 1450 hinter->stem( hinter->hints, 0, top ); 1451 } 1452 break; 1453 1454 case op_vstem3: 1455 FT_TRACE4(( " vstem3" )); 1456 1457 /* record vertical counter-controlled hints */ 1458 if ( hinter ) 1459 { 1460 FT_Pos dx = orig_x; 1461 1462 1463 top[0] += dx; 1464 top[2] += dx; 1465 top[4] += dx; 1466 hinter->stem3( hinter->hints, 0, top ); 1467 } 1468 break; 1469 1470 case op_setcurrentpoint: 1471 FT_TRACE4(( " setcurrentpoint" )); 1472 1473 /* From the T1 specification, section 6.4: */ 1474 /* */ 1475 /* The setcurrentpoint command is used only in */ 1476 /* conjunction with results from OtherSubrs procedures. */ 1477 1478 /* known_othersubr_result_cnt != 0 is already handled */ 1479 /* above. */ 1480 1481 /* Note, however, that both Ghostscript and Adobe */ 1482 /* Distiller handle this situation by silently ignoring */ 1483 /* the inappropriate `setcurrentpoint' instruction. So */ 1484 /* we do the same. */ 1485 #if 0 1486 1487 if ( decoder->flex_state != 1 ) 1488 { 1489 FT_ERROR(( "t1_decoder_parse_charstrings:" 1490 " unexpected `setcurrentpoint'\n" )); 1491 goto Syntax_Error; 1492 } 1493 else 1494 ... 1495 #endif 1496 1497 x = top[0]; 1498 y = top[1]; 1499 decoder->flex_state = 0; 1500 break; 1501 1502 case op_unknown15: 1503 FT_TRACE4(( " opcode_15" )); 1504 /* nothing to do except to pop the two arguments */ 1505 break; 1506 1507 default: 1508 FT_ERROR(( "t1_decoder_parse_charstrings:" 1509 " unhandled opcode %d\n", op )); 1510 goto Syntax_Error; 1511 } 1512 1513 /* XXX Operators usually clear the operand stack; */ 1514 /* only div, callsubr, callothersubr, pop, and */ 1515 /* return are different. */ 1516 /* In practice it doesn't matter (?). */ 1517 1518 decoder->top = top; 1519 1520 #ifdef FT_DEBUG_LEVEL_TRACE 1521 FT_TRACE4(( "\n" )); 1522 bol = TRUE; 1523 #endif 1524 1525 } /* general operator processing */ 1526 1527 } /* while ip < limit */ 1528 1529 FT_TRACE4(( "..end..\n\n" )); 1530 1531 Fail: 1532 return error; 1533 1534 Syntax_Error: 1535 return PSaux_Err_Syntax_Error; 1536 1537 Stack_Underflow: 1538 return PSaux_Err_Stack_Underflow; 1539 } 1540 1541 1542 /* parse a single Type 1 glyph */ 1543 FT_LOCAL_DEF( FT_Error ) t1_decoder_parse_glyph(T1_Decoder decoder,FT_UInt glyph)1544 t1_decoder_parse_glyph( T1_Decoder decoder, 1545 FT_UInt glyph ) 1546 { 1547 return decoder->parse_callback( decoder, glyph ); 1548 } 1549 1550 1551 /* initialize T1 decoder */ 1552 FT_LOCAL_DEF( FT_Error ) t1_decoder_init(T1_Decoder decoder,FT_Face face,FT_Size size,FT_GlyphSlot slot,FT_Byte ** glyph_names,PS_Blend blend,FT_Bool hinting,FT_Render_Mode hint_mode,T1_Decoder_Callback parse_callback)1553 t1_decoder_init( T1_Decoder decoder, 1554 FT_Face face, 1555 FT_Size size, 1556 FT_GlyphSlot slot, 1557 FT_Byte** glyph_names, 1558 PS_Blend blend, 1559 FT_Bool hinting, 1560 FT_Render_Mode hint_mode, 1561 T1_Decoder_Callback parse_callback ) 1562 { 1563 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 1564 1565 /* retrieve PSNames interface from list of current modules */ 1566 { 1567 FT_Service_PsCMaps psnames = 0; 1568 1569 1570 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 1571 if ( !psnames ) 1572 { 1573 FT_ERROR(( "t1_decoder_init:" 1574 " the `psnames' module is not available\n" )); 1575 return PSaux_Err_Unimplemented_Feature; 1576 } 1577 1578 decoder->psnames = psnames; 1579 } 1580 1581 t1_builder_init( &decoder->builder, face, size, slot, hinting ); 1582 1583 /* decoder->buildchar and decoder->len_buildchar have to be */ 1584 /* initialized by the caller since we cannot know the length */ 1585 /* of the BuildCharArray */ 1586 1587 decoder->num_glyphs = (FT_UInt)face->num_glyphs; 1588 decoder->glyph_names = glyph_names; 1589 decoder->hint_mode = hint_mode; 1590 decoder->blend = blend; 1591 decoder->parse_callback = parse_callback; 1592 1593 decoder->funcs = t1_decoder_funcs; 1594 1595 return PSaux_Err_Ok; 1596 } 1597 1598 1599 /* finalize T1 decoder */ 1600 FT_LOCAL_DEF( void ) t1_decoder_done(T1_Decoder decoder)1601 t1_decoder_done( T1_Decoder decoder ) 1602 { 1603 t1_builder_done( &decoder->builder ); 1604 } 1605 1606 1607 /* END */ 1608