1/***************************************************************************/ 2/* */ 3/* t1decode.c */ 4/* */ 5/* PostScript Type 1 decoding routines (body). */ 6/* */ 7/* Copyright 2000-2014 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 error = hinter->apply( hinter->hints, 1102 builder->current, 1103 (PSH_Globals)builder->hints_globals, 1104 decoder->hint_mode ); 1105 if ( error ) 1106 goto Fail; 1107 } 1108 1109 /* add current outline to the glyph slot */ 1110 FT_GlyphLoader_Add( builder->loader ); 1111 1112 /* the compiler should optimize away this empty loop but ... */ 1113 1114#ifdef FT_DEBUG_LEVEL_TRACE 1115 1116 if ( decoder->len_buildchar > 0 ) 1117 { 1118 FT_UInt i; 1119 1120 1121 FT_TRACE4(( "BuildCharArray = [ " )); 1122 1123 for ( i = 0; i < decoder->len_buildchar; ++i ) 1124 FT_TRACE4(( "%d ", decoder->buildchar[i] )); 1125 1126 FT_TRACE4(( "]\n" )); 1127 } 1128 1129#endif /* FT_DEBUG_LEVEL_TRACE */ 1130 1131 FT_TRACE4(( "\n" )); 1132 1133 /* return now! */ 1134 return FT_Err_Ok; 1135 1136 case op_hsbw: 1137 FT_TRACE4(( " hsbw" )); 1138 1139 builder->parse_state = T1_Parse_Have_Width; 1140 1141 builder->left_bearing.x += top[0]; 1142 builder->advance.x = top[1]; 1143 builder->advance.y = 0; 1144 1145 orig_x = x = builder->pos_x + top[0]; 1146 orig_y = y = builder->pos_y; 1147 1148 FT_UNUSED( orig_y ); 1149 1150 /* the `metrics_only' indicates that we only want to compute */ 1151 /* the glyph's metrics (lsb + advance width), not load the */ 1152 /* rest of it; so exit immediately */ 1153 if ( builder->metrics_only ) 1154 return FT_Err_Ok; 1155 1156 break; 1157 1158 case op_seac: 1159 return t1operator_seac( decoder, 1160 top[0], 1161 top[1], 1162 top[2], 1163 Fix2Int( top[3] ), 1164 Fix2Int( top[4] ) ); 1165 1166 case op_sbw: 1167 FT_TRACE4(( " sbw" )); 1168 1169 builder->parse_state = T1_Parse_Have_Width; 1170 1171 builder->left_bearing.x += top[0]; 1172 builder->left_bearing.y += top[1]; 1173 builder->advance.x = top[2]; 1174 builder->advance.y = top[3]; 1175 1176 x = builder->pos_x + top[0]; 1177 y = builder->pos_y + top[1]; 1178 1179 /* the `metrics_only' indicates that we only want to compute */ 1180 /* the glyph's metrics (lsb + advance width), not load the */ 1181 /* rest of it; so exit immediately */ 1182 if ( builder->metrics_only ) 1183 return FT_Err_Ok; 1184 1185 break; 1186 1187 case op_closepath: 1188 FT_TRACE4(( " closepath" )); 1189 1190 /* if there is no path, `closepath' is a no-op */ 1191 if ( builder->parse_state == T1_Parse_Have_Path || 1192 builder->parse_state == T1_Parse_Have_Moveto ) 1193 t1_builder_close_contour( builder ); 1194 1195 builder->parse_state = T1_Parse_Have_Width; 1196 break; 1197 1198 case op_hlineto: 1199 FT_TRACE4(( " hlineto" )); 1200 1201 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1202 != FT_Err_Ok ) 1203 goto Fail; 1204 1205 x += top[0]; 1206 goto Add_Line; 1207 1208 case op_hmoveto: 1209 FT_TRACE4(( " hmoveto" )); 1210 1211 x += top[0]; 1212 if ( !decoder->flex_state ) 1213 { 1214 if ( builder->parse_state == T1_Parse_Start ) 1215 goto Syntax_Error; 1216 builder->parse_state = T1_Parse_Have_Moveto; 1217 } 1218 break; 1219 1220 case op_hvcurveto: 1221 FT_TRACE4(( " hvcurveto" )); 1222 1223 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1224 != FT_Err_Ok || 1225 ( error = t1_builder_check_points( builder, 3 ) ) 1226 != FT_Err_Ok ) 1227 goto Fail; 1228 1229 x += top[0]; 1230 t1_builder_add_point( builder, x, y, 0 ); 1231 x += top[1]; 1232 y += top[2]; 1233 t1_builder_add_point( builder, x, y, 0 ); 1234 y += top[3]; 1235 t1_builder_add_point( builder, x, y, 1 ); 1236 break; 1237 1238 case op_rlineto: 1239 FT_TRACE4(( " rlineto" )); 1240 1241 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1242 != FT_Err_Ok ) 1243 goto Fail; 1244 1245 x += top[0]; 1246 y += top[1]; 1247 1248 Add_Line: 1249 if ( ( error = t1_builder_add_point1( builder, x, y ) ) 1250 != FT_Err_Ok ) 1251 goto Fail; 1252 break; 1253 1254 case op_rmoveto: 1255 FT_TRACE4(( " rmoveto" )); 1256 1257 x += top[0]; 1258 y += top[1]; 1259 if ( !decoder->flex_state ) 1260 { 1261 if ( builder->parse_state == T1_Parse_Start ) 1262 goto Syntax_Error; 1263 builder->parse_state = T1_Parse_Have_Moveto; 1264 } 1265 break; 1266 1267 case op_rrcurveto: 1268 FT_TRACE4(( " rrcurveto" )); 1269 1270 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1271 != FT_Err_Ok || 1272 ( error = t1_builder_check_points( builder, 3 ) ) 1273 != FT_Err_Ok ) 1274 goto Fail; 1275 1276 x += top[0]; 1277 y += top[1]; 1278 t1_builder_add_point( builder, x, y, 0 ); 1279 1280 x += top[2]; 1281 y += top[3]; 1282 t1_builder_add_point( builder, x, y, 0 ); 1283 1284 x += top[4]; 1285 y += top[5]; 1286 t1_builder_add_point( builder, x, y, 1 ); 1287 break; 1288 1289 case op_vhcurveto: 1290 FT_TRACE4(( " vhcurveto" )); 1291 1292 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1293 != FT_Err_Ok || 1294 ( error = t1_builder_check_points( builder, 3 ) ) 1295 != FT_Err_Ok ) 1296 goto Fail; 1297 1298 y += top[0]; 1299 t1_builder_add_point( builder, x, y, 0 ); 1300 x += top[1]; 1301 y += top[2]; 1302 t1_builder_add_point( builder, x, y, 0 ); 1303 x += top[3]; 1304 t1_builder_add_point( builder, x, y, 1 ); 1305 break; 1306 1307 case op_vlineto: 1308 FT_TRACE4(( " vlineto" )); 1309 1310 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1311 != FT_Err_Ok ) 1312 goto Fail; 1313 1314 y += top[0]; 1315 goto Add_Line; 1316 1317 case op_vmoveto: 1318 FT_TRACE4(( " vmoveto" )); 1319 1320 y += top[0]; 1321 if ( !decoder->flex_state ) 1322 { 1323 if ( builder->parse_state == T1_Parse_Start ) 1324 goto Syntax_Error; 1325 builder->parse_state = T1_Parse_Have_Moveto; 1326 } 1327 break; 1328 1329 case op_div: 1330 FT_TRACE4(( " div" )); 1331 1332 /* if `large_int' is set, we divide unscaled numbers; */ 1333 /* otherwise, we divide numbers in 16.16 format -- */ 1334 /* in both cases, it is the same operation */ 1335 *top = FT_DivFix( top[0], top[1] ); 1336 ++top; 1337 1338 large_int = FALSE; 1339 break; 1340 1341 case op_callsubr: 1342 { 1343 FT_Int idx; 1344 1345 1346 FT_TRACE4(( " callsubr" )); 1347 1348 idx = Fix2Int( top[0] ); 1349 if ( idx < 0 || idx >= (FT_Int)decoder->num_subrs ) 1350 { 1351 FT_ERROR(( "t1_decoder_parse_charstrings:" 1352 " invalid subrs index\n" )); 1353 goto Syntax_Error; 1354 } 1355 1356 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) 1357 { 1358 FT_ERROR(( "t1_decoder_parse_charstrings:" 1359 " too many nested subrs\n" )); 1360 goto Syntax_Error; 1361 } 1362 1363 zone->cursor = ip; /* save current instruction pointer */ 1364 1365 zone++; 1366 1367 /* The Type 1 driver stores subroutines without the seed bytes. */ 1368 /* The CID driver stores subroutines with seed bytes. This */ 1369 /* case is taken care of when decoder->subrs_len == 0. */ 1370 zone->base = decoder->subrs[idx]; 1371 1372 if ( decoder->subrs_len ) 1373 zone->limit = zone->base + decoder->subrs_len[idx]; 1374 else 1375 { 1376 /* We are using subroutines from a CID font. We must adjust */ 1377 /* for the seed bytes. */ 1378 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); 1379 zone->limit = decoder->subrs[idx + 1]; 1380 } 1381 1382 zone->cursor = zone->base; 1383 1384 if ( !zone->base ) 1385 { 1386 FT_ERROR(( "t1_decoder_parse_charstrings:" 1387 " invoking empty subrs\n" )); 1388 goto Syntax_Error; 1389 } 1390 1391 decoder->zone = zone; 1392 ip = zone->base; 1393 limit = zone->limit; 1394 break; 1395 } 1396 1397 case op_pop: 1398 FT_TRACE4(( " pop" )); 1399 1400 if ( known_othersubr_result_cnt > 0 ) 1401 { 1402 known_othersubr_result_cnt--; 1403 /* ignore, we pushed the operands ourselves */ 1404 break; 1405 } 1406 1407 if ( unknown_othersubr_result_cnt == 0 ) 1408 { 1409 FT_ERROR(( "t1_decoder_parse_charstrings:" 1410 " no more operands for othersubr\n" )); 1411 goto Syntax_Error; 1412 } 1413 1414 unknown_othersubr_result_cnt--; 1415 top++; /* `push' the operand to callothersubr onto the stack */ 1416 break; 1417 1418 case op_return: 1419 FT_TRACE4(( " return" )); 1420 1421 if ( zone <= decoder->zones ) 1422 { 1423 FT_ERROR(( "t1_decoder_parse_charstrings:" 1424 " unexpected return\n" )); 1425 goto Syntax_Error; 1426 } 1427 1428 zone--; 1429 ip = zone->cursor; 1430 limit = zone->limit; 1431 decoder->zone = zone; 1432 break; 1433 1434 case op_dotsection: 1435 FT_TRACE4(( " dotsection" )); 1436 1437 break; 1438 1439 case op_hstem: 1440 FT_TRACE4(( " hstem" )); 1441 1442 /* record horizontal hint */ 1443 if ( hinter ) 1444 { 1445 /* top[0] += builder->left_bearing.y; */ 1446 hinter->stem( hinter->hints, 1, top ); 1447 } 1448 break; 1449 1450 case op_hstem3: 1451 FT_TRACE4(( " hstem3" )); 1452 1453 /* record horizontal counter-controlled hints */ 1454 if ( hinter ) 1455 hinter->stem3( hinter->hints, 1, top ); 1456 break; 1457 1458 case op_vstem: 1459 FT_TRACE4(( " vstem" )); 1460 1461 /* record vertical hint */ 1462 if ( hinter ) 1463 { 1464 top[0] += orig_x; 1465 hinter->stem( hinter->hints, 0, top ); 1466 } 1467 break; 1468 1469 case op_vstem3: 1470 FT_TRACE4(( " vstem3" )); 1471 1472 /* record vertical counter-controlled hints */ 1473 if ( hinter ) 1474 { 1475 FT_Pos dx = orig_x; 1476 1477 1478 top[0] += dx; 1479 top[2] += dx; 1480 top[4] += dx; 1481 hinter->stem3( hinter->hints, 0, top ); 1482 } 1483 break; 1484 1485 case op_setcurrentpoint: 1486 FT_TRACE4(( " setcurrentpoint" )); 1487 1488 /* From the T1 specification, section 6.4: */ 1489 /* */ 1490 /* The setcurrentpoint command is used only in */ 1491 /* conjunction with results from OtherSubrs procedures. */ 1492 1493 /* known_othersubr_result_cnt != 0 is already handled */ 1494 /* above. */ 1495 1496 /* Note, however, that both Ghostscript and Adobe */ 1497 /* Distiller handle this situation by silently ignoring */ 1498 /* the inappropriate `setcurrentpoint' instruction. So */ 1499 /* we do the same. */ 1500#if 0 1501 1502 if ( decoder->flex_state != 1 ) 1503 { 1504 FT_ERROR(( "t1_decoder_parse_charstrings:" 1505 " unexpected `setcurrentpoint'\n" )); 1506 goto Syntax_Error; 1507 } 1508 else 1509 ... 1510#endif 1511 1512 x = top[0]; 1513 y = top[1]; 1514 decoder->flex_state = 0; 1515 break; 1516 1517 case op_unknown15: 1518 FT_TRACE4(( " opcode_15" )); 1519 /* nothing to do except to pop the two arguments */ 1520 break; 1521 1522 default: 1523 FT_ERROR(( "t1_decoder_parse_charstrings:" 1524 " unhandled opcode %d\n", op )); 1525 goto Syntax_Error; 1526 } 1527 1528 /* XXX Operators usually clear the operand stack; */ 1529 /* only div, callsubr, callothersubr, pop, and */ 1530 /* return are different. */ 1531 /* In practice it doesn't matter (?). */ 1532 1533 decoder->top = top; 1534 1535#ifdef FT_DEBUG_LEVEL_TRACE 1536 FT_TRACE4(( "\n" )); 1537 bol = TRUE; 1538#endif 1539 1540 } /* general operator processing */ 1541 1542 } /* while ip < limit */ 1543 1544 FT_TRACE4(( "..end..\n\n" )); 1545 1546 Fail: 1547 return error; 1548 1549 Syntax_Error: 1550 return FT_THROW( Syntax_Error ); 1551 1552 Stack_Underflow: 1553 return FT_THROW( Stack_Underflow ); 1554 } 1555 1556 1557 /* parse a single Type 1 glyph */ 1558 FT_LOCAL_DEF( FT_Error ) 1559 t1_decoder_parse_glyph( T1_Decoder decoder, 1560 FT_UInt glyph ) 1561 { 1562 return decoder->parse_callback( decoder, glyph ); 1563 } 1564 1565 1566 /* initialize T1 decoder */ 1567 FT_LOCAL_DEF( FT_Error ) 1568 t1_decoder_init( T1_Decoder decoder, 1569 FT_Face face, 1570 FT_Size size, 1571 FT_GlyphSlot slot, 1572 FT_Byte** glyph_names, 1573 PS_Blend blend, 1574 FT_Bool hinting, 1575 FT_Render_Mode hint_mode, 1576 T1_Decoder_Callback parse_callback ) 1577 { 1578 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 1579 1580 /* retrieve PSNames interface from list of current modules */ 1581 { 1582 FT_Service_PsCMaps psnames = 0; 1583 1584 1585 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 1586 if ( !psnames ) 1587 { 1588 FT_ERROR(( "t1_decoder_init:" 1589 " the `psnames' module is not available\n" )); 1590 return FT_THROW( Unimplemented_Feature ); 1591 } 1592 1593 decoder->psnames = psnames; 1594 } 1595 1596 t1_builder_init( &decoder->builder, face, size, slot, hinting ); 1597 1598 /* decoder->buildchar and decoder->len_buildchar have to be */ 1599 /* initialized by the caller since we cannot know the length */ 1600 /* of the BuildCharArray */ 1601 1602 decoder->num_glyphs = (FT_UInt)face->num_glyphs; 1603 decoder->glyph_names = glyph_names; 1604 decoder->hint_mode = hint_mode; 1605 decoder->blend = blend; 1606 decoder->parse_callback = parse_callback; 1607 1608 decoder->funcs = t1_decoder_funcs; 1609 1610 return FT_Err_Ok; 1611 } 1612 1613 1614 /* finalize T1 decoder */ 1615 FT_LOCAL_DEF( void ) 1616 t1_decoder_done( T1_Decoder decoder ) 1617 { 1618 t1_builder_done( &decoder->builder ); 1619 } 1620 1621 1622/* END */ 1623