1 /***************************************************************************/ 2 /* */ 3 /* t1decode.c */ 4 /* */ 5 /* PostScript Type 1 decoding routines (body). */ 6 /* */ 7 /* Copyright 2000-2015 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 (FT_Int)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 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, (FT_UInt)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, (FT_UInt)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 ) t1_decoder_parse_charstrings(T1_Decoder decoder,FT_Byte * charstring_base,FT_UInt charstring_len)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_Offset)(char*)&seed ^ 385 (FT_Offset)(char*)&decoder ^ 386 (FT_Offset)(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, 800 (FT_UInt)builder->current->n_points ); 801 break; 802 803 case 12: 804 case 13: 805 /* counter control hints, clear stack */ 806 top = decoder->stack; 807 break; 808 809 case 14: 810 case 15: 811 case 16: 812 case 17: 813 case 18: /* multiple masters */ 814 { 815 PS_Blend blend = decoder->blend; 816 FT_UInt num_points, nn, mm; 817 FT_Long* delta; 818 FT_Long* values; 819 820 821 if ( !blend ) 822 { 823 FT_ERROR(( "t1_decoder_parse_charstrings:" 824 " unexpected multiple masters operator\n" )); 825 goto Syntax_Error; 826 } 827 828 num_points = (FT_UInt)subr_no - 13 + ( subr_no == 18 ); 829 if ( arg_cnt != (FT_Int)( num_points * blend->num_designs ) ) 830 { 831 FT_ERROR(( "t1_decoder_parse_charstrings:" 832 " incorrect number of multiple masters arguments\n" )); 833 goto Syntax_Error; 834 } 835 836 /* We want to compute */ 837 /* */ 838 /* a0*w0 + a1*w1 + ... + ak*wk */ 839 /* */ 840 /* but we only have a0, a1-a0, a2-a0, ..., ak-a0. */ 841 /* */ 842 /* However, given that w0 + w1 + ... + wk == 1, we can */ 843 /* rewrite it easily as */ 844 /* */ 845 /* a0 + (a1-a0)*w1 + (a2-a0)*w2 + ... + (ak-a0)*wk */ 846 /* */ 847 /* where k == num_designs-1. */ 848 /* */ 849 /* I guess that's why it's written in this `compact' */ 850 /* form. */ 851 /* */ 852 delta = top + num_points; 853 values = top; 854 for ( nn = 0; nn < num_points; nn++ ) 855 { 856 FT_Long tmp = values[0]; 857 858 859 for ( mm = 1; mm < blend->num_designs; mm++ ) 860 tmp += FT_MulFix( *delta++, blend->weight_vector[mm] ); 861 862 *values++ = tmp; 863 } 864 865 known_othersubr_result_cnt = (FT_Int)num_points; 866 break; 867 } 868 869 case 19: 870 /* <idx> 1 19 callothersubr */ 871 /* => replace elements starting from index cvi( <idx> ) */ 872 /* of BuildCharArray with WeightVector */ 873 { 874 FT_Int idx; 875 PS_Blend blend = decoder->blend; 876 877 878 if ( arg_cnt != 1 || blend == NULL ) 879 goto Unexpected_OtherSubr; 880 881 idx = Fix2Int( top[0] ); 882 883 if ( idx < 0 || 884 (FT_UInt)idx + blend->num_designs > decoder->len_buildchar ) 885 goto Unexpected_OtherSubr; 886 887 ft_memcpy( &decoder->buildchar[idx], 888 blend->weight_vector, 889 blend->num_designs * 890 sizeof ( blend->weight_vector[0] ) ); 891 } 892 break; 893 894 case 20: 895 /* <arg1> <arg2> 2 20 callothersubr pop */ 896 /* ==> push <arg1> + <arg2> onto T1 stack */ 897 if ( arg_cnt != 2 ) 898 goto Unexpected_OtherSubr; 899 900 top[0] += top[1]; /* XXX (over|under)flow */ 901 902 known_othersubr_result_cnt = 1; 903 break; 904 905 case 21: 906 /* <arg1> <arg2> 2 21 callothersubr pop */ 907 /* ==> push <arg1> - <arg2> onto T1 stack */ 908 if ( arg_cnt != 2 ) 909 goto Unexpected_OtherSubr; 910 911 top[0] -= top[1]; /* XXX (over|under)flow */ 912 913 known_othersubr_result_cnt = 1; 914 break; 915 916 case 22: 917 /* <arg1> <arg2> 2 22 callothersubr pop */ 918 /* ==> push <arg1> * <arg2> onto T1 stack */ 919 if ( arg_cnt != 2 ) 920 goto Unexpected_OtherSubr; 921 922 top[0] = FT_MulFix( top[0], top[1] ); 923 924 known_othersubr_result_cnt = 1; 925 break; 926 927 case 23: 928 /* <arg1> <arg2> 2 23 callothersubr pop */ 929 /* ==> push <arg1> / <arg2> onto T1 stack */ 930 if ( arg_cnt != 2 || top[1] == 0 ) 931 goto Unexpected_OtherSubr; 932 933 top[0] = FT_DivFix( top[0], top[1] ); 934 935 known_othersubr_result_cnt = 1; 936 break; 937 938 case 24: 939 /* <val> <idx> 2 24 callothersubr */ 940 /* ==> set BuildCharArray[cvi( <idx> )] = <val> */ 941 { 942 FT_Int idx; 943 PS_Blend blend = decoder->blend; 944 945 946 if ( arg_cnt != 2 || blend == NULL ) 947 goto Unexpected_OtherSubr; 948 949 idx = Fix2Int( top[1] ); 950 951 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) 952 goto Unexpected_OtherSubr; 953 954 decoder->buildchar[idx] = top[0]; 955 } 956 break; 957 958 case 25: 959 /* <idx> 1 25 callothersubr pop */ 960 /* ==> push BuildCharArray[cvi( idx )] */ 961 /* onto T1 stack */ 962 { 963 FT_Int idx; 964 PS_Blend blend = decoder->blend; 965 966 967 if ( arg_cnt != 1 || blend == NULL ) 968 goto Unexpected_OtherSubr; 969 970 idx = Fix2Int( top[0] ); 971 972 if ( idx < 0 || (FT_UInt) idx >= decoder->len_buildchar ) 973 goto Unexpected_OtherSubr; 974 975 top[0] = decoder->buildchar[idx]; 976 } 977 978 known_othersubr_result_cnt = 1; 979 break; 980 981 #if 0 982 case 26: 983 /* <val> mark <idx> ==> set BuildCharArray[cvi( <idx> )] = <val>, */ 984 /* leave mark on T1 stack */ 985 /* <val> <idx> ==> set BuildCharArray[cvi( <idx> )] = <val> */ 986 XXX which routine has left its mark on the (PostScript) stack?; 987 break; 988 #endif 989 990 case 27: 991 /* <res1> <res2> <val1> <val2> 4 27 callothersubr pop */ 992 /* ==> push <res1> onto T1 stack if <val1> <= <val2>, */ 993 /* otherwise push <res2> */ 994 if ( arg_cnt != 4 ) 995 goto Unexpected_OtherSubr; 996 997 if ( top[2] > top[3] ) 998 top[0] = top[1]; 999 1000 known_othersubr_result_cnt = 1; 1001 break; 1002 1003 case 28: 1004 /* 0 28 callothersubr pop */ 1005 /* => push random value from interval [0, 1) onto stack */ 1006 if ( arg_cnt != 0 ) 1007 goto Unexpected_OtherSubr; 1008 1009 { 1010 FT_Fixed Rand; 1011 1012 1013 Rand = seed; 1014 if ( Rand >= 0x8000L ) 1015 Rand++; 1016 1017 top[0] = Rand; 1018 1019 seed = FT_MulFix( seed, 0x10000L - seed ); 1020 if ( seed == 0 ) 1021 seed += 0x2873; 1022 } 1023 1024 known_othersubr_result_cnt = 1; 1025 break; 1026 1027 default: 1028 if ( arg_cnt >= 0 && subr_no >= 0 ) 1029 { 1030 FT_ERROR(( "t1_decoder_parse_charstrings:" 1031 " unknown othersubr [%d %d], wish me luck\n", 1032 arg_cnt, subr_no )); 1033 unknown_othersubr_result_cnt = arg_cnt; 1034 break; 1035 } 1036 /* fall through */ 1037 1038 Unexpected_OtherSubr: 1039 FT_ERROR(( "t1_decoder_parse_charstrings:" 1040 " invalid othersubr [%d %d]\n", arg_cnt, subr_no )); 1041 goto Syntax_Error; 1042 } 1043 1044 top += known_othersubr_result_cnt; 1045 1046 decoder->top = top; 1047 } 1048 else /* general operator */ 1049 { 1050 FT_Int num_args = t1_args_count[op]; 1051 1052 1053 FT_ASSERT( num_args >= 0 ); 1054 1055 if ( top - decoder->stack < num_args ) 1056 goto Stack_Underflow; 1057 1058 /* XXX Operators usually take their operands from the */ 1059 /* bottom of the stack, i.e., the operands are */ 1060 /* decoder->stack[0], ..., decoder->stack[num_args - 1]; */ 1061 /* only div, callsubr, and callothersubr are different. */ 1062 /* In practice it doesn't matter (?). */ 1063 1064 #ifdef FT_DEBUG_LEVEL_TRACE 1065 1066 switch ( op ) 1067 { 1068 case op_callsubr: 1069 case op_div: 1070 case op_callothersubr: 1071 case op_pop: 1072 case op_return: 1073 break; 1074 1075 default: 1076 if ( top - decoder->stack != num_args ) 1077 FT_TRACE0(( "t1_decoder_parse_charstrings:" 1078 " too much operands on the stack" 1079 " (seen %d, expected %d)\n", 1080 top - decoder->stack, num_args )); 1081 break; 1082 } 1083 1084 #endif /* FT_DEBUG_LEVEL_TRACE */ 1085 1086 top -= num_args; 1087 1088 switch ( op ) 1089 { 1090 case op_endchar: 1091 FT_TRACE4(( " endchar\n" )); 1092 1093 t1_builder_close_contour( builder ); 1094 1095 /* close hints recording session */ 1096 if ( hinter ) 1097 { 1098 if ( hinter->close( hinter->hints, 1099 (FT_UInt)builder->current->n_points ) ) 1100 goto Syntax_Error; 1101 1102 /* apply hints to the loaded glyph outline now */ 1103 error = hinter->apply( hinter->hints, 1104 builder->current, 1105 (PSH_Globals)builder->hints_globals, 1106 decoder->hint_mode ); 1107 if ( error ) 1108 goto Fail; 1109 } 1110 1111 /* add current outline to the glyph slot */ 1112 FT_GlyphLoader_Add( builder->loader ); 1113 1114 /* the compiler should optimize away this empty loop but ... */ 1115 1116 #ifdef FT_DEBUG_LEVEL_TRACE 1117 1118 if ( decoder->len_buildchar > 0 ) 1119 { 1120 FT_UInt i; 1121 1122 1123 FT_TRACE4(( "BuildCharArray = [ " )); 1124 1125 for ( i = 0; i < decoder->len_buildchar; ++i ) 1126 FT_TRACE4(( "%d ", decoder->buildchar[i] )); 1127 1128 FT_TRACE4(( "]\n" )); 1129 } 1130 1131 #endif /* FT_DEBUG_LEVEL_TRACE */ 1132 1133 FT_TRACE4(( "\n" )); 1134 1135 /* return now! */ 1136 return FT_Err_Ok; 1137 1138 case op_hsbw: 1139 FT_TRACE4(( " hsbw" )); 1140 1141 builder->parse_state = T1_Parse_Have_Width; 1142 1143 builder->left_bearing.x += top[0]; 1144 builder->advance.x = top[1]; 1145 builder->advance.y = 0; 1146 1147 orig_x = x = builder->pos_x + top[0]; 1148 orig_y = y = builder->pos_y; 1149 1150 FT_UNUSED( orig_y ); 1151 1152 /* the `metrics_only' indicates that we only want to compute */ 1153 /* the glyph's metrics (lsb + advance width), not load the */ 1154 /* rest of it; so exit immediately */ 1155 if ( builder->metrics_only ) 1156 return FT_Err_Ok; 1157 1158 break; 1159 1160 case op_seac: 1161 return t1operator_seac( decoder, 1162 top[0], 1163 top[1], 1164 top[2], 1165 Fix2Int( top[3] ), 1166 Fix2Int( top[4] ) ); 1167 1168 case op_sbw: 1169 FT_TRACE4(( " sbw" )); 1170 1171 builder->parse_state = T1_Parse_Have_Width; 1172 1173 builder->left_bearing.x += top[0]; 1174 builder->left_bearing.y += top[1]; 1175 builder->advance.x = top[2]; 1176 builder->advance.y = top[3]; 1177 1178 x = builder->pos_x + top[0]; 1179 y = builder->pos_y + top[1]; 1180 1181 /* the `metrics_only' indicates that we only want to compute */ 1182 /* the glyph's metrics (lsb + advance width), not load the */ 1183 /* rest of it; so exit immediately */ 1184 if ( builder->metrics_only ) 1185 return FT_Err_Ok; 1186 1187 break; 1188 1189 case op_closepath: 1190 FT_TRACE4(( " closepath" )); 1191 1192 /* if there is no path, `closepath' is a no-op */ 1193 if ( builder->parse_state == T1_Parse_Have_Path || 1194 builder->parse_state == T1_Parse_Have_Moveto ) 1195 t1_builder_close_contour( builder ); 1196 1197 builder->parse_state = T1_Parse_Have_Width; 1198 break; 1199 1200 case op_hlineto: 1201 FT_TRACE4(( " hlineto" )); 1202 1203 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1204 != FT_Err_Ok ) 1205 goto Fail; 1206 1207 x += top[0]; 1208 goto Add_Line; 1209 1210 case op_hmoveto: 1211 FT_TRACE4(( " hmoveto" )); 1212 1213 x += top[0]; 1214 if ( !decoder->flex_state ) 1215 { 1216 if ( builder->parse_state == T1_Parse_Start ) 1217 goto Syntax_Error; 1218 builder->parse_state = T1_Parse_Have_Moveto; 1219 } 1220 break; 1221 1222 case op_hvcurveto: 1223 FT_TRACE4(( " hvcurveto" )); 1224 1225 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1226 != FT_Err_Ok || 1227 ( error = t1_builder_check_points( builder, 3 ) ) 1228 != FT_Err_Ok ) 1229 goto Fail; 1230 1231 x += top[0]; 1232 t1_builder_add_point( builder, x, y, 0 ); 1233 x += top[1]; 1234 y += top[2]; 1235 t1_builder_add_point( builder, x, y, 0 ); 1236 y += top[3]; 1237 t1_builder_add_point( builder, x, y, 1 ); 1238 break; 1239 1240 case op_rlineto: 1241 FT_TRACE4(( " rlineto" )); 1242 1243 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1244 != FT_Err_Ok ) 1245 goto Fail; 1246 1247 x += top[0]; 1248 y += top[1]; 1249 1250 Add_Line: 1251 if ( ( error = t1_builder_add_point1( builder, x, y ) ) 1252 != FT_Err_Ok ) 1253 goto Fail; 1254 break; 1255 1256 case op_rmoveto: 1257 FT_TRACE4(( " rmoveto" )); 1258 1259 x += top[0]; 1260 y += top[1]; 1261 if ( !decoder->flex_state ) 1262 { 1263 if ( builder->parse_state == T1_Parse_Start ) 1264 goto Syntax_Error; 1265 builder->parse_state = T1_Parse_Have_Moveto; 1266 } 1267 break; 1268 1269 case op_rrcurveto: 1270 FT_TRACE4(( " rrcurveto" )); 1271 1272 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1273 != FT_Err_Ok || 1274 ( error = t1_builder_check_points( builder, 3 ) ) 1275 != FT_Err_Ok ) 1276 goto Fail; 1277 1278 x += top[0]; 1279 y += top[1]; 1280 t1_builder_add_point( builder, x, y, 0 ); 1281 1282 x += top[2]; 1283 y += top[3]; 1284 t1_builder_add_point( builder, x, y, 0 ); 1285 1286 x += top[4]; 1287 y += top[5]; 1288 t1_builder_add_point( builder, x, y, 1 ); 1289 break; 1290 1291 case op_vhcurveto: 1292 FT_TRACE4(( " vhcurveto" )); 1293 1294 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1295 != FT_Err_Ok || 1296 ( error = t1_builder_check_points( builder, 3 ) ) 1297 != FT_Err_Ok ) 1298 goto Fail; 1299 1300 y += top[0]; 1301 t1_builder_add_point( builder, x, y, 0 ); 1302 x += top[1]; 1303 y += top[2]; 1304 t1_builder_add_point( builder, x, y, 0 ); 1305 x += top[3]; 1306 t1_builder_add_point( builder, x, y, 1 ); 1307 break; 1308 1309 case op_vlineto: 1310 FT_TRACE4(( " vlineto" )); 1311 1312 if ( ( error = t1_builder_start_point( builder, x, y ) ) 1313 != FT_Err_Ok ) 1314 goto Fail; 1315 1316 y += top[0]; 1317 goto Add_Line; 1318 1319 case op_vmoveto: 1320 FT_TRACE4(( " vmoveto" )); 1321 1322 y += top[0]; 1323 if ( !decoder->flex_state ) 1324 { 1325 if ( builder->parse_state == T1_Parse_Start ) 1326 goto Syntax_Error; 1327 builder->parse_state = T1_Parse_Have_Moveto; 1328 } 1329 break; 1330 1331 case op_div: 1332 FT_TRACE4(( " div" )); 1333 1334 /* if `large_int' is set, we divide unscaled numbers; */ 1335 /* otherwise, we divide numbers in 16.16 format -- */ 1336 /* in both cases, it is the same operation */ 1337 *top = FT_DivFix( top[0], top[1] ); 1338 ++top; 1339 1340 large_int = FALSE; 1341 break; 1342 1343 case op_callsubr: 1344 { 1345 FT_Int idx; 1346 1347 1348 FT_TRACE4(( " callsubr" )); 1349 1350 idx = Fix2Int( top[0] ); 1351 if ( idx < 0 || idx >= decoder->num_subrs ) 1352 { 1353 FT_ERROR(( "t1_decoder_parse_charstrings:" 1354 " invalid subrs index\n" )); 1355 goto Syntax_Error; 1356 } 1357 1358 if ( zone - decoder->zones >= T1_MAX_SUBRS_CALLS ) 1359 { 1360 FT_ERROR(( "t1_decoder_parse_charstrings:" 1361 " too many nested subrs\n" )); 1362 goto Syntax_Error; 1363 } 1364 1365 zone->cursor = ip; /* save current instruction pointer */ 1366 1367 zone++; 1368 1369 /* The Type 1 driver stores subroutines without the seed bytes. */ 1370 /* The CID driver stores subroutines with seed bytes. This */ 1371 /* case is taken care of when decoder->subrs_len == 0. */ 1372 zone->base = decoder->subrs[idx]; 1373 1374 if ( decoder->subrs_len ) 1375 zone->limit = zone->base + decoder->subrs_len[idx]; 1376 else 1377 { 1378 /* We are using subroutines from a CID font. We must adjust */ 1379 /* for the seed bytes. */ 1380 zone->base += ( decoder->lenIV >= 0 ? decoder->lenIV : 0 ); 1381 zone->limit = decoder->subrs[idx + 1]; 1382 } 1383 1384 zone->cursor = zone->base; 1385 1386 if ( !zone->base ) 1387 { 1388 FT_ERROR(( "t1_decoder_parse_charstrings:" 1389 " invoking empty subrs\n" )); 1390 goto Syntax_Error; 1391 } 1392 1393 decoder->zone = zone; 1394 ip = zone->base; 1395 limit = zone->limit; 1396 break; 1397 } 1398 1399 case op_pop: 1400 FT_TRACE4(( " pop" )); 1401 1402 if ( known_othersubr_result_cnt > 0 ) 1403 { 1404 known_othersubr_result_cnt--; 1405 /* ignore, we pushed the operands ourselves */ 1406 break; 1407 } 1408 1409 if ( unknown_othersubr_result_cnt == 0 ) 1410 { 1411 FT_ERROR(( "t1_decoder_parse_charstrings:" 1412 " no more operands for othersubr\n" )); 1413 goto Syntax_Error; 1414 } 1415 1416 unknown_othersubr_result_cnt--; 1417 top++; /* `push' the operand to callothersubr onto the stack */ 1418 break; 1419 1420 case op_return: 1421 FT_TRACE4(( " return" )); 1422 1423 if ( zone <= decoder->zones ) 1424 { 1425 FT_ERROR(( "t1_decoder_parse_charstrings:" 1426 " unexpected return\n" )); 1427 goto Syntax_Error; 1428 } 1429 1430 zone--; 1431 ip = zone->cursor; 1432 limit = zone->limit; 1433 decoder->zone = zone; 1434 break; 1435 1436 case op_dotsection: 1437 FT_TRACE4(( " dotsection" )); 1438 1439 break; 1440 1441 case op_hstem: 1442 FT_TRACE4(( " hstem" )); 1443 1444 /* record horizontal hint */ 1445 if ( hinter ) 1446 { 1447 /* top[0] += builder->left_bearing.y; */ 1448 hinter->stem( hinter->hints, 1, top ); 1449 } 1450 break; 1451 1452 case op_hstem3: 1453 FT_TRACE4(( " hstem3" )); 1454 1455 /* record horizontal counter-controlled hints */ 1456 if ( hinter ) 1457 hinter->stem3( hinter->hints, 1, top ); 1458 break; 1459 1460 case op_vstem: 1461 FT_TRACE4(( " vstem" )); 1462 1463 /* record vertical hint */ 1464 if ( hinter ) 1465 { 1466 top[0] += orig_x; 1467 hinter->stem( hinter->hints, 0, top ); 1468 } 1469 break; 1470 1471 case op_vstem3: 1472 FT_TRACE4(( " vstem3" )); 1473 1474 /* record vertical counter-controlled hints */ 1475 if ( hinter ) 1476 { 1477 FT_Pos dx = orig_x; 1478 1479 1480 top[0] += dx; 1481 top[2] += dx; 1482 top[4] += dx; 1483 hinter->stem3( hinter->hints, 0, top ); 1484 } 1485 break; 1486 1487 case op_setcurrentpoint: 1488 FT_TRACE4(( " setcurrentpoint" )); 1489 1490 /* From the T1 specification, section 6.4: */ 1491 /* */ 1492 /* The setcurrentpoint command is used only in */ 1493 /* conjunction with results from OtherSubrs procedures. */ 1494 1495 /* known_othersubr_result_cnt != 0 is already handled */ 1496 /* above. */ 1497 1498 /* Note, however, that both Ghostscript and Adobe */ 1499 /* Distiller handle this situation by silently ignoring */ 1500 /* the inappropriate `setcurrentpoint' instruction. So */ 1501 /* we do the same. */ 1502 #if 0 1503 1504 if ( decoder->flex_state != 1 ) 1505 { 1506 FT_ERROR(( "t1_decoder_parse_charstrings:" 1507 " unexpected `setcurrentpoint'\n" )); 1508 goto Syntax_Error; 1509 } 1510 else 1511 ... 1512 #endif 1513 1514 x = top[0]; 1515 y = top[1]; 1516 decoder->flex_state = 0; 1517 break; 1518 1519 case op_unknown15: 1520 FT_TRACE4(( " opcode_15" )); 1521 /* nothing to do except to pop the two arguments */ 1522 break; 1523 1524 default: 1525 FT_ERROR(( "t1_decoder_parse_charstrings:" 1526 " unhandled opcode %d\n", op )); 1527 goto Syntax_Error; 1528 } 1529 1530 /* XXX Operators usually clear the operand stack; */ 1531 /* only div, callsubr, callothersubr, pop, and */ 1532 /* return are different. */ 1533 /* In practice it doesn't matter (?). */ 1534 1535 decoder->top = top; 1536 1537 #ifdef FT_DEBUG_LEVEL_TRACE 1538 FT_TRACE4(( "\n" )); 1539 bol = TRUE; 1540 #endif 1541 1542 } /* general operator processing */ 1543 1544 } /* while ip < limit */ 1545 1546 FT_TRACE4(( "..end..\n\n" )); 1547 1548 Fail: 1549 return error; 1550 1551 Syntax_Error: 1552 return FT_THROW( Syntax_Error ); 1553 1554 Stack_Underflow: 1555 return FT_THROW( Stack_Underflow ); 1556 } 1557 1558 1559 /* parse a single Type 1 glyph */ 1560 FT_LOCAL_DEF( FT_Error ) t1_decoder_parse_glyph(T1_Decoder decoder,FT_UInt glyph)1561 t1_decoder_parse_glyph( T1_Decoder decoder, 1562 FT_UInt glyph ) 1563 { 1564 return decoder->parse_callback( decoder, glyph ); 1565 } 1566 1567 1568 /* initialize T1 decoder */ 1569 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)1570 t1_decoder_init( T1_Decoder decoder, 1571 FT_Face face, 1572 FT_Size size, 1573 FT_GlyphSlot slot, 1574 FT_Byte** glyph_names, 1575 PS_Blend blend, 1576 FT_Bool hinting, 1577 FT_Render_Mode hint_mode, 1578 T1_Decoder_Callback parse_callback ) 1579 { 1580 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 1581 1582 /* retrieve PSNames interface from list of current modules */ 1583 { 1584 FT_Service_PsCMaps psnames; 1585 1586 1587 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 1588 if ( !psnames ) 1589 { 1590 FT_ERROR(( "t1_decoder_init:" 1591 " the `psnames' module is not available\n" )); 1592 return FT_THROW( Unimplemented_Feature ); 1593 } 1594 1595 decoder->psnames = psnames; 1596 } 1597 1598 t1_builder_init( &decoder->builder, face, size, slot, hinting ); 1599 1600 /* decoder->buildchar and decoder->len_buildchar have to be */ 1601 /* initialized by the caller since we cannot know the length */ 1602 /* of the BuildCharArray */ 1603 1604 decoder->num_glyphs = (FT_UInt)face->num_glyphs; 1605 decoder->glyph_names = glyph_names; 1606 decoder->hint_mode = hint_mode; 1607 decoder->blend = blend; 1608 decoder->parse_callback = parse_callback; 1609 1610 decoder->funcs = t1_decoder_funcs; 1611 1612 return FT_Err_Ok; 1613 } 1614 1615 1616 /* finalize T1 decoder */ 1617 FT_LOCAL_DEF( void ) t1_decoder_done(T1_Decoder decoder)1618 t1_decoder_done( T1_Decoder decoder ) 1619 { 1620 t1_builder_done( &decoder->builder ); 1621 } 1622 1623 1624 /* END */ 1625