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