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