cffgload.c revision 049d6fea481044fcc000e7782e5bc7046fc70844
1/***************************************************************************/ 2/* */ 3/* cffgload.c */ 4/* */ 5/* OpenType Glyph Loader (body). */ 6/* */ 7/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008 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_CALC_H 22#include FT_INTERNAL_STREAM_H 23#include FT_INTERNAL_SFNT_H 24#include FT_OUTLINE_H 25#include FT_TRUETYPE_TAGS_H 26#include FT_INTERNAL_POSTSCRIPT_HINTS_H 27 28#include "cffobjs.h" 29#include "cffload.h" 30#include "cffgload.h" 31 32#include "cfferrs.h" 33 34 35 /*************************************************************************/ 36 /* */ 37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 39 /* messages during execution. */ 40 /* */ 41#undef FT_COMPONENT 42#define FT_COMPONENT trace_cffgload 43 44 45 typedef enum CFF_Operator_ 46 { 47 cff_op_unknown = 0, 48 49 cff_op_rmoveto, 50 cff_op_hmoveto, 51 cff_op_vmoveto, 52 53 cff_op_rlineto, 54 cff_op_hlineto, 55 cff_op_vlineto, 56 57 cff_op_rrcurveto, 58 cff_op_hhcurveto, 59 cff_op_hvcurveto, 60 cff_op_rcurveline, 61 cff_op_rlinecurve, 62 cff_op_vhcurveto, 63 cff_op_vvcurveto, 64 65 cff_op_flex, 66 cff_op_hflex, 67 cff_op_hflex1, 68 cff_op_flex1, 69 70 cff_op_endchar, 71 72 cff_op_hstem, 73 cff_op_vstem, 74 cff_op_hstemhm, 75 cff_op_vstemhm, 76 77 cff_op_hintmask, 78 cff_op_cntrmask, 79 cff_op_dotsection, /* deprecated, acts as no-op */ 80 81 cff_op_abs, 82 cff_op_add, 83 cff_op_sub, 84 cff_op_div, 85 cff_op_neg, 86 cff_op_random, 87 cff_op_mul, 88 cff_op_sqrt, 89 90 cff_op_blend, 91 92 cff_op_drop, 93 cff_op_exch, 94 cff_op_index, 95 cff_op_roll, 96 cff_op_dup, 97 98 cff_op_put, 99 cff_op_get, 100 cff_op_store, 101 cff_op_load, 102 103 cff_op_and, 104 cff_op_or, 105 cff_op_not, 106 cff_op_eq, 107 cff_op_ifelse, 108 109 cff_op_callsubr, 110 cff_op_callgsubr, 111 cff_op_return, 112 113 cff_op_hsbw, /* Type 1 opcode: invalid but seen in real life */ 114 cff_op_closepath, /* ditto */ 115 116 /* do not remove */ 117 cff_op_max 118 119 } CFF_Operator; 120 121 122#define CFF_COUNT_CHECK_WIDTH 0x80 123#define CFF_COUNT_EXACT 0x40 124#define CFF_COUNT_CLEAR_STACK 0x20 125 126 127 static const FT_Byte cff_argument_counts[] = 128 { 129 0, /* unknown */ 130 131 2 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, /* rmoveto */ 132 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 133 1 | CFF_COUNT_CHECK_WIDTH | CFF_COUNT_EXACT, 134 135 0 | CFF_COUNT_CLEAR_STACK, /* rlineto */ 136 0 | CFF_COUNT_CLEAR_STACK, 137 0 | CFF_COUNT_CLEAR_STACK, 138 139 0 | CFF_COUNT_CLEAR_STACK, /* rrcurveto */ 140 0 | CFF_COUNT_CLEAR_STACK, 141 0 | CFF_COUNT_CLEAR_STACK, 142 0 | CFF_COUNT_CLEAR_STACK, 143 0 | CFF_COUNT_CLEAR_STACK, 144 0 | CFF_COUNT_CLEAR_STACK, 145 0 | CFF_COUNT_CLEAR_STACK, 146 147 13, /* flex */ 148 7, 149 9, 150 11, 151 152 0 | CFF_COUNT_CHECK_WIDTH, /* endchar */ 153 154 2 | CFF_COUNT_CHECK_WIDTH, /* hstem */ 155 2 | CFF_COUNT_CHECK_WIDTH, 156 2 | CFF_COUNT_CHECK_WIDTH, 157 2 | CFF_COUNT_CHECK_WIDTH, 158 159 0 | CFF_COUNT_CHECK_WIDTH, /* hintmask */ 160 0 | CFF_COUNT_CHECK_WIDTH, /* cntrmask */ 161 0, /* dotsection */ 162 163 1, /* abs */ 164 2, 165 2, 166 2, 167 1, 168 0, 169 2, 170 1, 171 172 1, /* blend */ 173 174 1, /* drop */ 175 2, 176 1, 177 2, 178 1, 179 180 2, /* put */ 181 1, 182 4, 183 3, 184 185 2, /* and */ 186 2, 187 1, 188 2, 189 4, 190 191 1, /* callsubr */ 192 1, 193 0, 194 195 2, /* hsbw */ 196 0 197 }; 198 199 200 /*************************************************************************/ 201 /*************************************************************************/ 202 /*************************************************************************/ 203 /********** *********/ 204 /********** *********/ 205 /********** GENERIC CHARSTRING PARSING *********/ 206 /********** *********/ 207 /********** *********/ 208 /*************************************************************************/ 209 /*************************************************************************/ 210 /*************************************************************************/ 211 212 213 /*************************************************************************/ 214 /* */ 215 /* <Function> */ 216 /* cff_builder_init */ 217 /* */ 218 /* <Description> */ 219 /* Initializes a given glyph builder. */ 220 /* */ 221 /* <InOut> */ 222 /* builder :: A pointer to the glyph builder to initialize. */ 223 /* */ 224 /* <Input> */ 225 /* face :: The current face object. */ 226 /* */ 227 /* size :: The current size object. */ 228 /* */ 229 /* glyph :: The current glyph object. */ 230 /* */ 231 /* hinting :: Whether hinting is active. */ 232 /* */ 233 static void 234 cff_builder_init( CFF_Builder* builder, 235 TT_Face face, 236 CFF_Size size, 237 CFF_GlyphSlot glyph, 238 FT_Bool hinting ) 239 { 240 builder->path_begun = 0; 241 builder->load_points = 1; 242 243 builder->face = face; 244 builder->glyph = glyph; 245 builder->memory = face->root.memory; 246 247 if ( glyph ) 248 { 249 FT_GlyphLoader loader = glyph->root.internal->loader; 250 251 252 builder->loader = loader; 253 builder->base = &loader->base.outline; 254 builder->current = &loader->current.outline; 255 FT_GlyphLoader_Rewind( loader ); 256 257 builder->hints_globals = 0; 258 builder->hints_funcs = 0; 259 260 if ( hinting && size ) 261 { 262 CFF_Internal internal = (CFF_Internal)size->root.internal; 263 264 265 builder->hints_globals = (void *)internal->topfont; 266 builder->hints_funcs = glyph->root.internal->glyph_hints; 267 } 268 } 269 270 builder->pos_x = 0; 271 builder->pos_y = 0; 272 273 builder->left_bearing.x = 0; 274 builder->left_bearing.y = 0; 275 builder->advance.x = 0; 276 builder->advance.y = 0; 277 } 278 279 280 /*************************************************************************/ 281 /* */ 282 /* <Function> */ 283 /* cff_builder_done */ 284 /* */ 285 /* <Description> */ 286 /* Finalizes a given glyph builder. Its contents can still be used */ 287 /* after the call, but the function saves important information */ 288 /* within the corresponding glyph slot. */ 289 /* */ 290 /* <Input> */ 291 /* builder :: A pointer to the glyph builder to finalize. */ 292 /* */ 293 static void 294 cff_builder_done( CFF_Builder* builder ) 295 { 296 CFF_GlyphSlot glyph = builder->glyph; 297 298 299 if ( glyph ) 300 glyph->root.outline = *builder->base; 301 } 302 303 304 /*************************************************************************/ 305 /* */ 306 /* <Function> */ 307 /* cff_compute_bias */ 308 /* */ 309 /* <Description> */ 310 /* Computes the bias value in dependence of the number of glyph */ 311 /* subroutines. */ 312 /* */ 313 /* <Input> */ 314 /* num_subrs :: The number of glyph subroutines. */ 315 /* */ 316 /* <Return> */ 317 /* The bias value. */ 318 static FT_Int 319 cff_compute_bias( FT_UInt num_subrs ) 320 { 321 FT_Int result; 322 323 324 if ( num_subrs < 1240 ) 325 result = 107; 326 else if ( num_subrs < 33900U ) 327 result = 1131; 328 else 329 result = 32768U; 330 331 return result; 332 } 333 334 335 /*************************************************************************/ 336 /* */ 337 /* <Function> */ 338 /* cff_decoder_init */ 339 /* */ 340 /* <Description> */ 341 /* Initializes a given glyph decoder. */ 342 /* */ 343 /* <InOut> */ 344 /* decoder :: A pointer to the glyph builder to initialize. */ 345 /* */ 346 /* <Input> */ 347 /* face :: The current face object. */ 348 /* */ 349 /* size :: The current size object. */ 350 /* */ 351 /* slot :: The current glyph object. */ 352 /* */ 353 /* hinting :: Whether hinting is active. */ 354 /* */ 355 /* hint_mode :: The hinting mode. */ 356 /* */ 357 FT_LOCAL_DEF( void ) 358 cff_decoder_init( CFF_Decoder* decoder, 359 TT_Face face, 360 CFF_Size size, 361 CFF_GlyphSlot slot, 362 FT_Bool hinting, 363 FT_Render_Mode hint_mode ) 364 { 365 CFF_Font cff = (CFF_Font)face->extra.data; 366 367 368 /* clear everything */ 369 FT_MEM_ZERO( decoder, sizeof ( *decoder ) ); 370 371 /* initialize builder */ 372 cff_builder_init( &decoder->builder, face, size, slot, hinting ); 373 374 /* initialize Type2 decoder */ 375 decoder->num_globals = cff->num_global_subrs; 376 decoder->globals = cff->global_subrs; 377 decoder->globals_bias = cff_compute_bias( decoder->num_globals ); 378 379 decoder->hint_mode = hint_mode; 380 } 381 382 FT_LOCAL_DEF( void ) 383 cff_decoder_set_width_only( CFF_Decoder* decoder ) 384 { 385 decoder->width_only = 1; 386 } 387 388 /* this function is used to select the subfont */ 389 /* and the locals subrs array */ 390 FT_LOCAL_DEF( FT_Error ) 391 cff_decoder_prepare( CFF_Decoder* decoder, 392 CFF_Size size, 393 FT_UInt glyph_index ) 394 { 395 CFF_Builder *builder = &decoder->builder; 396 CFF_Font cff = (CFF_Font)builder->face->extra.data; 397 CFF_SubFont sub = &cff->top_font; 398 FT_Error error = CFF_Err_Ok; 399 400 401 /* manage CID fonts */ 402 if ( cff->num_subfonts ) 403 { 404 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, glyph_index ); 405 406 407 if ( fd_index >= cff->num_subfonts ) 408 { 409 FT_TRACE4(( "cff_decoder_prepare: invalid CID subfont index\n" )); 410 error = CFF_Err_Invalid_File_Format; 411 goto Exit; 412 } 413 414 sub = cff->subfonts[fd_index]; 415 if ( builder->hints_funcs ) 416 { 417 CFF_Internal internal = (CFF_Internal)size->root.internal; 418 419 420 /* for CFFs without subfonts, this value has already been set */ 421 builder->hints_globals = (void *)internal->subfonts[fd_index]; 422 } 423 } 424 425 decoder->num_locals = sub->num_local_subrs; 426 decoder->locals = sub->local_subrs; 427 decoder->locals_bias = cff_compute_bias( decoder->num_locals ); 428 429 decoder->glyph_width = sub->private_dict.default_width; 430 decoder->nominal_width = sub->private_dict.nominal_width; 431 432 Exit: 433 return error; 434 } 435 436 437 /* check that there is enough space for `count' more points */ 438 static FT_Error 439 check_points( CFF_Builder* builder, 440 FT_Int count ) 441 { 442 return FT_GLYPHLOADER_CHECK_POINTS( builder->loader, count, 0 ); 443 } 444 445 446 /* add a new point, do not check space */ 447 static void 448 cff_builder_add_point( CFF_Builder* builder, 449 FT_Pos x, 450 FT_Pos y, 451 FT_Byte flag ) 452 { 453 FT_Outline* outline = builder->current; 454 455 456 if ( builder->load_points ) 457 { 458 FT_Vector* point = outline->points + outline->n_points; 459 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points; 460 461 462 point->x = x >> 16; 463 point->y = y >> 16; 464 *control = (FT_Byte)( flag ? FT_CURVE_TAG_ON : FT_CURVE_TAG_CUBIC ); 465 466 builder->last = *point; 467 } 468 469 outline->n_points++; 470 } 471 472 473 /* check space for a new on-curve point, then add it */ 474 static FT_Error 475 cff_builder_add_point1( CFF_Builder* builder, 476 FT_Pos x, 477 FT_Pos y ) 478 { 479 FT_Error error; 480 481 482 error = check_points( builder, 1 ); 483 if ( !error ) 484 cff_builder_add_point( builder, x, y, 1 ); 485 486 return error; 487 } 488 489 490 /* check space for a new contour, then add it */ 491 static FT_Error 492 cff_builder_add_contour( CFF_Builder* builder ) 493 { 494 FT_Outline* outline = builder->current; 495 FT_Error error; 496 497 498 if ( !builder->load_points ) 499 { 500 outline->n_contours++; 501 return CFF_Err_Ok; 502 } 503 504 error = FT_GLYPHLOADER_CHECK_POINTS( builder->loader, 0, 1 ); 505 if ( !error ) 506 { 507 if ( outline->n_contours > 0 ) 508 outline->contours[outline->n_contours - 1] = 509 (short)( outline->n_points - 1 ); 510 511 outline->n_contours++; 512 } 513 514 return error; 515 } 516 517 518 /* if a path was begun, add its first on-curve point */ 519 static FT_Error 520 cff_builder_start_point( CFF_Builder* builder, 521 FT_Pos x, 522 FT_Pos y ) 523 { 524 FT_Error error = CFF_Err_Ok; 525 526 527 /* test whether we are building a new contour */ 528 if ( !builder->path_begun ) 529 { 530 builder->path_begun = 1; 531 error = cff_builder_add_contour( builder ); 532 if ( !error ) 533 error = cff_builder_add_point1( builder, x, y ); 534 } 535 536 return error; 537 } 538 539 540 /* close the current contour */ 541 static void 542 cff_builder_close_contour( CFF_Builder* builder ) 543 { 544 FT_Outline* outline = builder->current; 545 546 547 if ( !outline ) 548 return; 549 550 /* XXXX: We must not include the last point in the path if it */ 551 /* is located on the first point. */ 552 if ( outline->n_points > 1 ) 553 { 554 FT_Int first = 0; 555 FT_Vector* p1 = outline->points + first; 556 FT_Vector* p2 = outline->points + outline->n_points - 1; 557 FT_Byte* control = (FT_Byte*)outline->tags + outline->n_points - 1; 558 559 560 if ( outline->n_contours > 1 ) 561 { 562 first = outline->contours[outline->n_contours - 2] + 1; 563 p1 = outline->points + first; 564 } 565 566 /* `delete' last point only if it coincides with the first */ 567 /* point and if it is not a control point (which can happen). */ 568 if ( p1->x == p2->x && p1->y == p2->y ) 569 if ( *control == FT_CURVE_TAG_ON ) 570 outline->n_points--; 571 } 572 573 if ( outline->n_contours > 0 ) 574 outline->contours[outline->n_contours - 1] = 575 (short)( outline->n_points - 1 ); 576 } 577 578 579 static FT_Int 580 cff_lookup_glyph_by_stdcharcode( CFF_Font cff, 581 FT_Int charcode ) 582 { 583 FT_UInt n; 584 FT_UShort glyph_sid; 585 586 587 /* CID-keyed fonts don't have glyph names */ 588 if ( !cff->charset.sids ) 589 return -1; 590 591 /* check range of standard char code */ 592 if ( charcode < 0 || charcode > 255 ) 593 return -1; 594 595 /* Get code to SID mapping from `cff_standard_encoding'. */ 596 glyph_sid = cff_get_standard_encoding( (FT_UInt)charcode ); 597 598 for ( n = 0; n < cff->num_glyphs; n++ ) 599 { 600 if ( cff->charset.sids[n] == glyph_sid ) 601 return n; 602 } 603 604 return -1; 605 } 606 607 608 static FT_Error 609 cff_get_glyph_data( TT_Face face, 610 FT_UInt glyph_index, 611 FT_Byte** pointer, 612 FT_ULong* length ) 613 { 614#ifdef FT_CONFIG_OPTION_INCREMENTAL 615 /* For incremental fonts get the character data using the */ 616 /* callback function. */ 617 if ( face->root.internal->incremental_interface ) 618 { 619 FT_Data data; 620 FT_Error error = 621 face->root.internal->incremental_interface->funcs->get_glyph_data( 622 face->root.internal->incremental_interface->object, 623 glyph_index, &data ); 624 625 626 *pointer = (FT_Byte*)data.pointer; 627 *length = data.length; 628 629 return error; 630 } 631 else 632#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 633 634 { 635 CFF_Font cff = (CFF_Font)(face->extra.data); 636 637 638 return cff_index_access_element( &cff->charstrings_index, glyph_index, 639 pointer, length ); 640 } 641 } 642 643 644 static void 645 cff_free_glyph_data( TT_Face face, 646 FT_Byte** pointer, 647 FT_ULong length ) 648 { 649#ifndef FT_CONFIG_OPTION_INCREMENTAL 650 FT_UNUSED( length ); 651#endif 652 653#ifdef FT_CONFIG_OPTION_INCREMENTAL 654 /* For incremental fonts get the character data using the */ 655 /* callback function. */ 656 if ( face->root.internal->incremental_interface ) 657 { 658 FT_Data data; 659 660 661 data.pointer = *pointer; 662 data.length = length; 663 664 face->root.internal->incremental_interface->funcs->free_glyph_data( 665 face->root.internal->incremental_interface->object,&data ); 666 } 667 else 668#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 669 670 { 671 CFF_Font cff = (CFF_Font)(face->extra.data); 672 673 674 cff_index_forget_element( &cff->charstrings_index, pointer ); 675 } 676 } 677 678 679 static FT_Error 680 cff_operator_seac( CFF_Decoder* decoder, 681 FT_Pos adx, 682 FT_Pos ady, 683 FT_Int bchar, 684 FT_Int achar ) 685 { 686 FT_Error error; 687 CFF_Builder* builder = &decoder->builder; 688 FT_Int bchar_index, achar_index; 689 TT_Face face = decoder->builder.face; 690 FT_Vector left_bearing, advance; 691 FT_Byte* charstring; 692 FT_ULong charstring_len; 693 694 695#ifdef FT_CONFIG_OPTION_INCREMENTAL 696 /* Incremental fonts don't necessarily have valid charsets. */ 697 /* They use the character code, not the glyph index, in this case. */ 698 if ( face->root.internal->incremental_interface ) 699 { 700 bchar_index = bchar; 701 achar_index = achar; 702 } 703 else 704#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 705 { 706 CFF_Font cff = (CFF_Font)(face->extra.data); 707 708 709 bchar_index = cff_lookup_glyph_by_stdcharcode( cff, bchar ); 710 achar_index = cff_lookup_glyph_by_stdcharcode( cff, achar ); 711 } 712 713 if ( bchar_index < 0 || achar_index < 0 ) 714 { 715 FT_ERROR(( "cff_operator_seac:" )); 716 FT_ERROR(( " invalid seac character code arguments\n" )); 717 return CFF_Err_Syntax_Error; 718 } 719 720 /* If we are trying to load a composite glyph, do not load the */ 721 /* accent character and return the array of subglyphs. */ 722 if ( builder->no_recurse ) 723 { 724 FT_GlyphSlot glyph = (FT_GlyphSlot)builder->glyph; 725 FT_GlyphLoader loader = glyph->internal->loader; 726 FT_SubGlyph subg; 727 728 729 /* reallocate subglyph array if necessary */ 730 error = FT_GlyphLoader_CheckSubGlyphs( loader, 2 ); 731 if ( error ) 732 goto Exit; 733 734 subg = loader->current.subglyphs; 735 736 /* subglyph 0 = base character */ 737 subg->index = bchar_index; 738 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES | 739 FT_SUBGLYPH_FLAG_USE_MY_METRICS; 740 subg->arg1 = 0; 741 subg->arg2 = 0; 742 subg++; 743 744 /* subglyph 1 = accent character */ 745 subg->index = achar_index; 746 subg->flags = FT_SUBGLYPH_FLAG_ARGS_ARE_XY_VALUES; 747 subg->arg1 = (FT_Int)( adx >> 16 ); 748 subg->arg2 = (FT_Int)( ady >> 16 ); 749 750 /* set up remaining glyph fields */ 751 glyph->num_subglyphs = 2; 752 glyph->subglyphs = loader->base.subglyphs; 753 glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 754 755 loader->current.num_subglyphs = 2; 756 } 757 758 FT_GlyphLoader_Prepare( builder->loader ); 759 760 /* First load `bchar' in builder */ 761 error = cff_get_glyph_data( face, bchar_index, 762 &charstring, &charstring_len ); 763 if ( !error ) 764 { 765 error = cff_decoder_parse_charstrings( decoder, charstring, 766 charstring_len ); 767 768 if ( error ) 769 goto Exit; 770 771 cff_free_glyph_data( face, &charstring, charstring_len ); 772 } 773 774 /* Save the left bearing and width of the base character */ 775 /* as they will be erased by the next load. */ 776 777 left_bearing = builder->left_bearing; 778 advance = builder->advance; 779 780 builder->left_bearing.x = 0; 781 builder->left_bearing.y = 0; 782 783 builder->pos_x = adx; 784 builder->pos_y = ady; 785 786 /* Now load `achar' on top of the base outline. */ 787 error = cff_get_glyph_data( face, achar_index, 788 &charstring, &charstring_len ); 789 if ( !error ) 790 { 791 error = cff_decoder_parse_charstrings( decoder, charstring, 792 charstring_len ); 793 794 if ( error ) 795 goto Exit; 796 797 cff_free_glyph_data( face, &charstring, charstring_len ); 798 } 799 800 /* Restore the left side bearing and advance width */ 801 /* of the base character. */ 802 builder->left_bearing = left_bearing; 803 builder->advance = advance; 804 805 builder->pos_x = 0; 806 builder->pos_y = 0; 807 808 Exit: 809 return error; 810 } 811 812 813 /*************************************************************************/ 814 /* */ 815 /* <Function> */ 816 /* cff_decoder_parse_charstrings */ 817 /* */ 818 /* <Description> */ 819 /* Parses a given Type 2 charstrings program. */ 820 /* */ 821 /* <InOut> */ 822 /* decoder :: The current Type 1 decoder. */ 823 /* */ 824 /* <Input> */ 825 /* charstring_base :: The base of the charstring stream. */ 826 /* */ 827 /* charstring_len :: The length in bytes of the charstring stream. */ 828 /* */ 829 /* <Return> */ 830 /* FreeType error code. 0 means success. */ 831 /* */ 832 FT_LOCAL_DEF( FT_Error ) 833 cff_decoder_parse_charstrings( CFF_Decoder* decoder, 834 FT_Byte* charstring_base, 835 FT_ULong charstring_len ) 836 { 837 FT_Error error; 838 CFF_Decoder_Zone* zone; 839 FT_Byte* ip; 840 FT_Byte* limit; 841 CFF_Builder* builder = &decoder->builder; 842 FT_Pos x, y; 843 FT_Fixed seed; 844 FT_Fixed* stack; 845 846 T2_Hints_Funcs hinter; 847 848 849 /* set default width */ 850 decoder->num_hints = 0; 851 decoder->read_width = 1; 852 853 /* compute random seed from stack address of parameter */ 854 seed = (FT_Fixed)(char*)&seed ^ 855 (FT_Fixed)(char*)&decoder ^ 856 (FT_Fixed)(char*)&charstring_base; 857 seed = ( seed ^ ( seed >> 10 ) ^ ( seed >> 20 ) ) & 0xFFFFL; 858 if ( seed == 0 ) 859 seed = 0x7384; 860 861 /* initialize the decoder */ 862 decoder->top = decoder->stack; 863 decoder->zone = decoder->zones; 864 zone = decoder->zones; 865 stack = decoder->top; 866 867 hinter = (T2_Hints_Funcs)builder->hints_funcs; 868 869 builder->path_begun = 0; 870 871 zone->base = charstring_base; 872 limit = zone->limit = charstring_base + charstring_len; 873 ip = zone->cursor = zone->base; 874 875 error = CFF_Err_Ok; 876 877 x = builder->pos_x; 878 y = builder->pos_y; 879 880 /* begin hints recording session, if any */ 881 if ( hinter ) 882 hinter->open( hinter->hints ); 883 884 /* now execute loop */ 885 while ( ip < limit ) 886 { 887 CFF_Operator op; 888 FT_Byte v; 889 890 891 /********************************************************************/ 892 /* */ 893 /* Decode operator or operand */ 894 /* */ 895 v = *ip++; 896 if ( v >= 32 || v == 28 ) 897 { 898 FT_Int shift = 16; 899 FT_Int32 val; 900 901 902 /* this is an operand, push it on the stack */ 903 if ( v == 28 ) 904 { 905 if ( ip + 1 >= limit ) 906 goto Syntax_Error; 907 val = (FT_Short)( ( (FT_Short)ip[0] << 8 ) | ip[1] ); 908 ip += 2; 909 } 910 else if ( v < 247 ) 911 val = (FT_Long)v - 139; 912 else if ( v < 251 ) 913 { 914 if ( ip >= limit ) 915 goto Syntax_Error; 916 val = ( (FT_Long)v - 247 ) * 256 + *ip++ + 108; 917 } 918 else if ( v < 255 ) 919 { 920 if ( ip >= limit ) 921 goto Syntax_Error; 922 val = -( (FT_Long)v - 251 ) * 256 - *ip++ - 108; 923 } 924 else 925 { 926 if ( ip + 3 >= limit ) 927 goto Syntax_Error; 928 val = ( (FT_Int32)ip[0] << 24 ) | 929 ( (FT_Int32)ip[1] << 16 ) | 930 ( (FT_Int32)ip[2] << 8 ) | 931 ip[3]; 932 ip += 4; 933 shift = 0; 934 } 935 if ( decoder->top - stack >= CFF_MAX_OPERANDS ) 936 goto Stack_Overflow; 937 938 val <<= shift; 939 *decoder->top++ = val; 940 941#ifdef FT_DEBUG_LEVEL_TRACE 942 if ( !( val & 0xFFFFL ) ) 943 FT_TRACE4(( " %ld", (FT_Int32)( val >> 16 ) )); 944 else 945 FT_TRACE4(( " %.2f", val / 65536.0 )); 946#endif 947 948 } 949 else 950 { 951 FT_Fixed* args = decoder->top; 952 FT_Int num_args = (FT_Int)( args - decoder->stack ); 953 FT_Int req_args; 954 955 956 /* find operator */ 957 op = cff_op_unknown; 958 959 switch ( v ) 960 { 961 case 1: 962 op = cff_op_hstem; 963 break; 964 case 3: 965 op = cff_op_vstem; 966 break; 967 case 4: 968 op = cff_op_vmoveto; 969 break; 970 case 5: 971 op = cff_op_rlineto; 972 break; 973 case 6: 974 op = cff_op_hlineto; 975 break; 976 case 7: 977 op = cff_op_vlineto; 978 break; 979 case 8: 980 op = cff_op_rrcurveto; 981 break; 982 case 9: 983 op = cff_op_closepath; 984 break; 985 case 10: 986 op = cff_op_callsubr; 987 break; 988 case 11: 989 op = cff_op_return; 990 break; 991 case 12: 992 { 993 if ( ip >= limit ) 994 goto Syntax_Error; 995 v = *ip++; 996 997 switch ( v ) 998 { 999 case 0: 1000 op = cff_op_dotsection; 1001 break; 1002 case 3: 1003 op = cff_op_and; 1004 break; 1005 case 4: 1006 op = cff_op_or; 1007 break; 1008 case 5: 1009 op = cff_op_not; 1010 break; 1011 case 8: 1012 op = cff_op_store; 1013 break; 1014 case 9: 1015 op = cff_op_abs; 1016 break; 1017 case 10: 1018 op = cff_op_add; 1019 break; 1020 case 11: 1021 op = cff_op_sub; 1022 break; 1023 case 12: 1024 op = cff_op_div; 1025 break; 1026 case 13: 1027 op = cff_op_load; 1028 break; 1029 case 14: 1030 op = cff_op_neg; 1031 break; 1032 case 15: 1033 op = cff_op_eq; 1034 break; 1035 case 18: 1036 op = cff_op_drop; 1037 break; 1038 case 20: 1039 op = cff_op_put; 1040 break; 1041 case 21: 1042 op = cff_op_get; 1043 break; 1044 case 22: 1045 op = cff_op_ifelse; 1046 break; 1047 case 23: 1048 op = cff_op_random; 1049 break; 1050 case 24: 1051 op = cff_op_mul; 1052 break; 1053 case 26: 1054 op = cff_op_sqrt; 1055 break; 1056 case 27: 1057 op = cff_op_dup; 1058 break; 1059 case 28: 1060 op = cff_op_exch; 1061 break; 1062 case 29: 1063 op = cff_op_index; 1064 break; 1065 case 30: 1066 op = cff_op_roll; 1067 break; 1068 case 34: 1069 op = cff_op_hflex; 1070 break; 1071 case 35: 1072 op = cff_op_flex; 1073 break; 1074 case 36: 1075 op = cff_op_hflex1; 1076 break; 1077 case 37: 1078 op = cff_op_flex1; 1079 break; 1080 default: 1081 /* decrement ip for syntax error message */ 1082 ip--; 1083 } 1084 } 1085 break; 1086 case 13: 1087 op = cff_op_hsbw; 1088 break; 1089 case 14: 1090 op = cff_op_endchar; 1091 break; 1092 case 16: 1093 op = cff_op_blend; 1094 break; 1095 case 18: 1096 op = cff_op_hstemhm; 1097 break; 1098 case 19: 1099 op = cff_op_hintmask; 1100 break; 1101 case 20: 1102 op = cff_op_cntrmask; 1103 break; 1104 case 21: 1105 op = cff_op_rmoveto; 1106 break; 1107 case 22: 1108 op = cff_op_hmoveto; 1109 break; 1110 case 23: 1111 op = cff_op_vstemhm; 1112 break; 1113 case 24: 1114 op = cff_op_rcurveline; 1115 break; 1116 case 25: 1117 op = cff_op_rlinecurve; 1118 break; 1119 case 26: 1120 op = cff_op_vvcurveto; 1121 break; 1122 case 27: 1123 op = cff_op_hhcurveto; 1124 break; 1125 case 29: 1126 op = cff_op_callgsubr; 1127 break; 1128 case 30: 1129 op = cff_op_vhcurveto; 1130 break; 1131 case 31: 1132 op = cff_op_hvcurveto; 1133 break; 1134 default: 1135 ; 1136 } 1137 if ( op == cff_op_unknown ) 1138 goto Syntax_Error; 1139 1140 /* check arguments */ 1141 req_args = cff_argument_counts[op]; 1142 if ( req_args & CFF_COUNT_CHECK_WIDTH ) 1143 { 1144 args = stack; 1145 1146 if ( num_args > 0 && decoder->read_width ) 1147 { 1148 /* If `nominal_width' is non-zero, the number is really a */ 1149 /* difference against `nominal_width'. Else, the number here */ 1150 /* is truly a width, not a difference against `nominal_width'. */ 1151 /* If the font does not set `nominal_width', then */ 1152 /* `nominal_width' defaults to zero, and so we can set */ 1153 /* `glyph_width' to `nominal_width' plus number on the stack */ 1154 /* -- for either case. */ 1155 1156 FT_Int set_width_ok; 1157 1158 1159 switch ( op ) 1160 { 1161 case cff_op_hmoveto: 1162 case cff_op_vmoveto: 1163 set_width_ok = num_args & 2; 1164 break; 1165 1166 case cff_op_hstem: 1167 case cff_op_vstem: 1168 case cff_op_hstemhm: 1169 case cff_op_vstemhm: 1170 case cff_op_rmoveto: 1171 case cff_op_hintmask: 1172 case cff_op_cntrmask: 1173 set_width_ok = num_args & 1; 1174 break; 1175 1176 case cff_op_endchar: 1177 /* If there is a width specified for endchar, we either have */ 1178 /* 1 argument or 5 arguments. We like to argue. */ 1179 set_width_ok = ( ( num_args == 5 ) || ( num_args == 1 ) ); 1180 break; 1181 1182 default: 1183 set_width_ok = 0; 1184 break; 1185 } 1186 1187 if ( set_width_ok ) 1188 { 1189 decoder->glyph_width = decoder->nominal_width + 1190 ( stack[0] >> 16 ); 1191 1192 if (decoder->width_only) 1193 { 1194 /* we only want the advance width, stop here */ 1195 break; 1196 } 1197 1198 /* Consumed an argument. */ 1199 num_args--; 1200 args++; 1201 } 1202 } 1203 1204 decoder->read_width = 0; 1205 req_args = 0; 1206 } 1207 1208 req_args &= 0x000F; 1209 if ( num_args < req_args ) 1210 goto Stack_Underflow; 1211 args -= req_args; 1212 num_args -= req_args; 1213 1214 switch ( op ) 1215 { 1216 case cff_op_hstem: 1217 case cff_op_vstem: 1218 case cff_op_hstemhm: 1219 case cff_op_vstemhm: 1220 /* the number of arguments is always even here */ 1221 FT_TRACE4(( op == cff_op_hstem ? " hstem" : 1222 ( op == cff_op_vstem ? " vstem" : 1223 ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" ) ) )); 1224 1225 if ( hinter ) 1226 hinter->stems( hinter->hints, 1227 ( op == cff_op_hstem || op == cff_op_hstemhm ), 1228 num_args / 2, 1229 args ); 1230 1231 decoder->num_hints += num_args / 2; 1232 args = stack; 1233 break; 1234 1235 case cff_op_hintmask: 1236 case cff_op_cntrmask: 1237 FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" )); 1238 1239 /* implement vstem when needed -- */ 1240 /* the specification doesn't say it, but this also works */ 1241 /* with the 'cntrmask' operator */ 1242 /* */ 1243 if ( num_args > 0 ) 1244 { 1245 if ( hinter ) 1246 hinter->stems( hinter->hints, 1247 0, 1248 num_args / 2, 1249 args ); 1250 1251 decoder->num_hints += num_args / 2; 1252 } 1253 1254 if ( hinter ) 1255 { 1256 if ( op == cff_op_hintmask ) 1257 hinter->hintmask( hinter->hints, 1258 builder->current->n_points, 1259 decoder->num_hints, 1260 ip ); 1261 else 1262 hinter->counter( hinter->hints, 1263 decoder->num_hints, 1264 ip ); 1265 } 1266 1267#ifdef FT_DEBUG_LEVEL_TRACE 1268 { 1269 FT_UInt maskbyte; 1270 1271 1272 FT_TRACE4(( " " )); 1273 1274 for ( maskbyte = 0; 1275 maskbyte < (FT_UInt)(( decoder->num_hints + 7 ) >> 3); 1276 maskbyte++, ip++ ) 1277 FT_TRACE4(( "0x%02X", *ip )); 1278 } 1279#else 1280 ip += ( decoder->num_hints + 7 ) >> 3; 1281#endif 1282 if ( ip >= limit ) 1283 goto Syntax_Error; 1284 args = stack; 1285 break; 1286 1287 case cff_op_rmoveto: 1288 FT_TRACE4(( " rmoveto" )); 1289 1290 cff_builder_close_contour( builder ); 1291 builder->path_begun = 0; 1292 x += args[0]; 1293 y += args[1]; 1294 args = stack; 1295 break; 1296 1297 case cff_op_vmoveto: 1298 FT_TRACE4(( " vmoveto" )); 1299 1300 cff_builder_close_contour( builder ); 1301 builder->path_begun = 0; 1302 y += args[0]; 1303 args = stack; 1304 break; 1305 1306 case cff_op_hmoveto: 1307 FT_TRACE4(( " hmoveto" )); 1308 1309 cff_builder_close_contour( builder ); 1310 builder->path_begun = 0; 1311 x += args[0]; 1312 args = stack; 1313 break; 1314 1315 case cff_op_rlineto: 1316 FT_TRACE4(( " rlineto" )); 1317 1318 if ( cff_builder_start_point ( builder, x, y ) || 1319 check_points( builder, num_args / 2 ) ) 1320 goto Fail; 1321 1322 if ( num_args < 2 || num_args & 1 ) 1323 goto Stack_Underflow; 1324 1325 args = stack; 1326 while ( args < decoder->top ) 1327 { 1328 x += args[0]; 1329 y += args[1]; 1330 cff_builder_add_point( builder, x, y, 1 ); 1331 args += 2; 1332 } 1333 args = stack; 1334 break; 1335 1336 case cff_op_hlineto: 1337 case cff_op_vlineto: 1338 { 1339 FT_Int phase = ( op == cff_op_hlineto ); 1340 1341 1342 FT_TRACE4(( op == cff_op_hlineto ? " hlineto" 1343 : " vlineto" )); 1344 1345 if ( cff_builder_start_point ( builder, x, y ) || 1346 check_points( builder, num_args ) ) 1347 goto Fail; 1348 1349 args = stack; 1350 while ( args < decoder->top ) 1351 { 1352 if ( phase ) 1353 x += args[0]; 1354 else 1355 y += args[0]; 1356 1357 if ( cff_builder_add_point1( builder, x, y ) ) 1358 goto Fail; 1359 1360 args++; 1361 phase ^= 1; 1362 } 1363 args = stack; 1364 } 1365 break; 1366 1367 case cff_op_rrcurveto: 1368 FT_TRACE4(( " rrcurveto" )); 1369 1370 /* check number of arguments; must be a multiple of 6 */ 1371 if ( num_args % 6 != 0 ) 1372 goto Stack_Underflow; 1373 1374 if ( cff_builder_start_point ( builder, x, y ) || 1375 check_points( builder, num_args / 2 ) ) 1376 goto Fail; 1377 1378 args = stack; 1379 while ( args < decoder->top ) 1380 { 1381 x += args[0]; 1382 y += args[1]; 1383 cff_builder_add_point( builder, x, y, 0 ); 1384 x += args[2]; 1385 y += args[3]; 1386 cff_builder_add_point( builder, x, y, 0 ); 1387 x += args[4]; 1388 y += args[5]; 1389 cff_builder_add_point( builder, x, y, 1 ); 1390 args += 6; 1391 } 1392 args = stack; 1393 break; 1394 1395 case cff_op_vvcurveto: 1396 FT_TRACE4(( " vvcurveto" )); 1397 1398 if ( cff_builder_start_point( builder, x, y ) ) 1399 goto Fail; 1400 1401 args = stack; 1402 if ( num_args & 1 ) 1403 { 1404 x += args[0]; 1405 args++; 1406 num_args--; 1407 } 1408 1409 if ( num_args % 4 != 0 ) 1410 goto Stack_Underflow; 1411 1412 if ( check_points( builder, 3 * ( num_args / 4 ) ) ) 1413 goto Fail; 1414 1415 while ( args < decoder->top ) 1416 { 1417 y += args[0]; 1418 cff_builder_add_point( builder, x, y, 0 ); 1419 x += args[1]; 1420 y += args[2]; 1421 cff_builder_add_point( builder, x, y, 0 ); 1422 y += args[3]; 1423 cff_builder_add_point( builder, x, y, 1 ); 1424 args += 4; 1425 } 1426 args = stack; 1427 break; 1428 1429 case cff_op_hhcurveto: 1430 FT_TRACE4(( " hhcurveto" )); 1431 1432 if ( cff_builder_start_point( builder, x, y ) ) 1433 goto Fail; 1434 1435 args = stack; 1436 if ( num_args & 1 ) 1437 { 1438 y += args[0]; 1439 args++; 1440 num_args--; 1441 } 1442 1443 if ( num_args % 4 != 0 ) 1444 goto Stack_Underflow; 1445 1446 if ( check_points( builder, 3 * ( num_args / 4 ) ) ) 1447 goto Fail; 1448 1449 while ( args < decoder->top ) 1450 { 1451 x += args[0]; 1452 cff_builder_add_point( builder, x, y, 0 ); 1453 x += args[1]; 1454 y += args[2]; 1455 cff_builder_add_point( builder, x, y, 0 ); 1456 x += args[3]; 1457 cff_builder_add_point( builder, x, y, 1 ); 1458 args += 4; 1459 } 1460 args = stack; 1461 break; 1462 1463 case cff_op_vhcurveto: 1464 case cff_op_hvcurveto: 1465 { 1466 FT_Int phase; 1467 1468 1469 FT_TRACE4(( op == cff_op_vhcurveto ? " vhcurveto" 1470 : " hvcurveto" )); 1471 1472 if ( cff_builder_start_point( builder, x, y ) ) 1473 goto Fail; 1474 1475 args = stack; 1476 if ( num_args < 4 || ( num_args % 4 ) > 1 ) 1477 goto Stack_Underflow; 1478 1479 if ( check_points( builder, ( num_args / 4 ) * 3 ) ) 1480 goto Stack_Underflow; 1481 1482 phase = ( op == cff_op_hvcurveto ); 1483 1484 while ( num_args >= 4 ) 1485 { 1486 num_args -= 4; 1487 if ( phase ) 1488 { 1489 x += args[0]; 1490 cff_builder_add_point( builder, x, y, 0 ); 1491 x += args[1]; 1492 y += args[2]; 1493 cff_builder_add_point( builder, x, y, 0 ); 1494 y += args[3]; 1495 if ( num_args == 1 ) 1496 x += args[4]; 1497 cff_builder_add_point( builder, x, y, 1 ); 1498 } 1499 else 1500 { 1501 y += args[0]; 1502 cff_builder_add_point( builder, x, y, 0 ); 1503 x += args[1]; 1504 y += args[2]; 1505 cff_builder_add_point( builder, x, y, 0 ); 1506 x += args[3]; 1507 if ( num_args == 1 ) 1508 y += args[4]; 1509 cff_builder_add_point( builder, x, y, 1 ); 1510 } 1511 args += 4; 1512 phase ^= 1; 1513 } 1514 args = stack; 1515 } 1516 break; 1517 1518 case cff_op_rlinecurve: 1519 { 1520 FT_Int num_lines = ( num_args - 6 ) / 2; 1521 1522 1523 FT_TRACE4(( " rlinecurve" )); 1524 1525 if ( num_args < 8 || ( num_args - 6 ) & 1 ) 1526 goto Stack_Underflow; 1527 1528 if ( cff_builder_start_point( builder, x, y ) || 1529 check_points( builder, num_lines + 3 ) ) 1530 goto Fail; 1531 1532 args = stack; 1533 1534 /* first, add the line segments */ 1535 while ( num_lines > 0 ) 1536 { 1537 x += args[0]; 1538 y += args[1]; 1539 cff_builder_add_point( builder, x, y, 1 ); 1540 args += 2; 1541 num_lines--; 1542 } 1543 1544 /* then the curve */ 1545 x += args[0]; 1546 y += args[1]; 1547 cff_builder_add_point( builder, x, y, 0 ); 1548 x += args[2]; 1549 y += args[3]; 1550 cff_builder_add_point( builder, x, y, 0 ); 1551 x += args[4]; 1552 y += args[5]; 1553 cff_builder_add_point( builder, x, y, 1 ); 1554 args = stack; 1555 } 1556 break; 1557 1558 case cff_op_rcurveline: 1559 { 1560 FT_Int num_curves = ( num_args - 2 ) / 6; 1561 1562 1563 FT_TRACE4(( " rcurveline" )); 1564 1565 if ( num_args < 8 || ( num_args - 2 ) % 6 ) 1566 goto Stack_Underflow; 1567 1568 if ( cff_builder_start_point ( builder, x, y ) || 1569 check_points( builder, num_curves*3 + 2 ) ) 1570 goto Fail; 1571 1572 args = stack; 1573 1574 /* first, add the curves */ 1575 while ( num_curves > 0 ) 1576 { 1577 x += args[0]; 1578 y += args[1]; 1579 cff_builder_add_point( builder, x, y, 0 ); 1580 x += args[2]; 1581 y += args[3]; 1582 cff_builder_add_point( builder, x, y, 0 ); 1583 x += args[4]; 1584 y += args[5]; 1585 cff_builder_add_point( builder, x, y, 1 ); 1586 args += 6; 1587 num_curves--; 1588 } 1589 1590 /* then the final line */ 1591 x += args[0]; 1592 y += args[1]; 1593 cff_builder_add_point( builder, x, y, 1 ); 1594 args = stack; 1595 } 1596 break; 1597 1598 case cff_op_hflex1: 1599 { 1600 FT_Pos start_y; 1601 1602 1603 FT_TRACE4(( " hflex1" )); 1604 1605 args = stack; 1606 1607 /* adding five more points; 4 control points, 1 on-curve point */ 1608 /* make sure we have enough space for the start point if it */ 1609 /* needs to be added */ 1610 if ( cff_builder_start_point( builder, x, y ) || 1611 check_points( builder, 6 ) ) 1612 goto Fail; 1613 1614 /* Record the starting point's y position for later use */ 1615 start_y = y; 1616 1617 /* first control point */ 1618 x += args[0]; 1619 y += args[1]; 1620 cff_builder_add_point( builder, x, y, 0 ); 1621 1622 /* second control point */ 1623 x += args[2]; 1624 y += args[3]; 1625 cff_builder_add_point( builder, x, y, 0 ); 1626 1627 /* join point; on curve, with y-value the same as the last */ 1628 /* control point's y-value */ 1629 x += args[4]; 1630 cff_builder_add_point( builder, x, y, 1 ); 1631 1632 /* third control point, with y-value the same as the join */ 1633 /* point's y-value */ 1634 x += args[5]; 1635 cff_builder_add_point( builder, x, y, 0 ); 1636 1637 /* fourth control point */ 1638 x += args[6]; 1639 y += args[7]; 1640 cff_builder_add_point( builder, x, y, 0 ); 1641 1642 /* ending point, with y-value the same as the start */ 1643 x += args[8]; 1644 y = start_y; 1645 cff_builder_add_point( builder, x, y, 1 ); 1646 1647 args = stack; 1648 break; 1649 } 1650 1651 case cff_op_hflex: 1652 { 1653 FT_Pos start_y; 1654 1655 1656 FT_TRACE4(( " hflex" )); 1657 1658 args = stack; 1659 1660 /* adding six more points; 4 control points, 2 on-curve points */ 1661 if ( cff_builder_start_point( builder, x, y ) || 1662 check_points( builder, 6 ) ) 1663 goto Fail; 1664 1665 /* record the starting point's y-position for later use */ 1666 start_y = y; 1667 1668 /* first control point */ 1669 x += args[0]; 1670 cff_builder_add_point( builder, x, y, 0 ); 1671 1672 /* second control point */ 1673 x += args[1]; 1674 y += args[2]; 1675 cff_builder_add_point( builder, x, y, 0 ); 1676 1677 /* join point; on curve, with y-value the same as the last */ 1678 /* control point's y-value */ 1679 x += args[3]; 1680 cff_builder_add_point( builder, x, y, 1 ); 1681 1682 /* third control point, with y-value the same as the join */ 1683 /* point's y-value */ 1684 x += args[4]; 1685 cff_builder_add_point( builder, x, y, 0 ); 1686 1687 /* fourth control point */ 1688 x += args[5]; 1689 y = start_y; 1690 cff_builder_add_point( builder, x, y, 0 ); 1691 1692 /* ending point, with y-value the same as the start point's */ 1693 /* y-value -- we don't add this point, though */ 1694 x += args[6]; 1695 cff_builder_add_point( builder, x, y, 1 ); 1696 1697 args = stack; 1698 break; 1699 } 1700 1701 case cff_op_flex1: 1702 { 1703 FT_Pos start_x, start_y; /* record start x, y values for */ 1704 /* alter use */ 1705 FT_Fixed dx = 0, dy = 0; /* used in horizontal/vertical */ 1706 /* algorithm below */ 1707 FT_Int horizontal, count; 1708 1709 1710 FT_TRACE4(( " flex1" )); 1711 1712 /* adding six more points; 4 control points, 2 on-curve points */ 1713 if ( cff_builder_start_point( builder, x, y ) || 1714 check_points( builder, 6 ) ) 1715 goto Fail; 1716 1717 /* record the starting point's x, y position for later use */ 1718 start_x = x; 1719 start_y = y; 1720 1721 /* XXX: figure out whether this is supposed to be a horizontal */ 1722 /* or vertical flex; the Type 2 specification is vague... */ 1723 1724 args = stack; 1725 1726 /* grab up to the last argument */ 1727 for ( count = 5; count > 0; count-- ) 1728 { 1729 dx += args[0]; 1730 dy += args[1]; 1731 args += 2; 1732 } 1733 1734 /* rewind */ 1735 args = stack; 1736 1737 if ( dx < 0 ) dx = -dx; 1738 if ( dy < 0 ) dy = -dy; 1739 1740 /* strange test, but here it is... */ 1741 horizontal = ( dx > dy ); 1742 1743 for ( count = 5; count > 0; count-- ) 1744 { 1745 x += args[0]; 1746 y += args[1]; 1747 cff_builder_add_point( builder, x, y, (FT_Bool)( count == 3 ) ); 1748 args += 2; 1749 } 1750 1751 /* is last operand an x- or y-delta? */ 1752 if ( horizontal ) 1753 { 1754 x += args[0]; 1755 y = start_y; 1756 } 1757 else 1758 { 1759 x = start_x; 1760 y += args[0]; 1761 } 1762 1763 cff_builder_add_point( builder, x, y, 1 ); 1764 1765 args = stack; 1766 break; 1767 } 1768 1769 case cff_op_flex: 1770 { 1771 FT_UInt count; 1772 1773 1774 FT_TRACE4(( " flex" )); 1775 1776 if ( cff_builder_start_point( builder, x, y ) || 1777 check_points( builder, 6 ) ) 1778 goto Fail; 1779 1780 args = stack; 1781 for ( count = 6; count > 0; count-- ) 1782 { 1783 x += args[0]; 1784 y += args[1]; 1785 cff_builder_add_point( builder, x, y, 1786 (FT_Bool)( count == 4 || count == 1 ) ); 1787 args += 2; 1788 } 1789 1790 args = stack; 1791 } 1792 break; 1793 1794 case cff_op_endchar: 1795 FT_TRACE4(( " endchar" )); 1796 1797 /* We are going to emulate the seac operator. */ 1798 if ( num_args == 4 ) 1799 { 1800 /* Save glyph width so that the subglyphs don't overwrite it. */ 1801 FT_Pos glyph_width = decoder->glyph_width; 1802 1803 1804 error = cff_operator_seac( decoder, 1805 args[0], 1806 args[1], 1807 (FT_Int)( args[2] >> 16 ), 1808 (FT_Int)( args[3] >> 16 ) ); 1809 args += 4; 1810 1811 decoder->glyph_width = glyph_width; 1812 } 1813 else 1814 { 1815 if ( !error ) 1816 error = CFF_Err_Ok; 1817 1818 cff_builder_close_contour( builder ); 1819 1820 /* close hints recording session */ 1821 if ( hinter ) 1822 { 1823 if ( hinter->close( hinter->hints, 1824 builder->current->n_points ) ) 1825 goto Syntax_Error; 1826 1827 /* apply hints to the loaded glyph outline now */ 1828 hinter->apply( hinter->hints, 1829 builder->current, 1830 (PSH_Globals)builder->hints_globals, 1831 decoder->hint_mode ); 1832 } 1833 1834 /* add current outline to the glyph slot */ 1835 FT_GlyphLoader_Add( builder->loader ); 1836 } 1837 1838 /* return now! */ 1839 FT_TRACE4(( "\n\n" )); 1840 return error; 1841 1842 case cff_op_abs: 1843 FT_TRACE4(( " abs" )); 1844 1845 if ( args[0] < 0 ) 1846 args[0] = -args[0]; 1847 args++; 1848 break; 1849 1850 case cff_op_add: 1851 FT_TRACE4(( " add" )); 1852 1853 args[0] += args[1]; 1854 args++; 1855 break; 1856 1857 case cff_op_sub: 1858 FT_TRACE4(( " sub" )); 1859 1860 args[0] -= args[1]; 1861 args++; 1862 break; 1863 1864 case cff_op_div: 1865 FT_TRACE4(( " div" )); 1866 1867 args[0] = FT_DivFix( args[0], args[1] ); 1868 args++; 1869 break; 1870 1871 case cff_op_neg: 1872 FT_TRACE4(( " neg" )); 1873 1874 args[0] = -args[0]; 1875 args++; 1876 break; 1877 1878 case cff_op_random: 1879 { 1880 FT_Fixed Rand; 1881 1882 1883 FT_TRACE4(( " rand" )); 1884 1885 Rand = seed; 1886 if ( Rand >= 0x8000L ) 1887 Rand++; 1888 1889 args[0] = Rand; 1890 seed = FT_MulFix( seed, 0x10000L - seed ); 1891 if ( seed == 0 ) 1892 seed += 0x2873; 1893 args++; 1894 } 1895 break; 1896 1897 case cff_op_mul: 1898 FT_TRACE4(( " mul" )); 1899 1900 args[0] = FT_MulFix( args[0], args[1] ); 1901 args++; 1902 break; 1903 1904 case cff_op_sqrt: 1905 FT_TRACE4(( " sqrt" )); 1906 1907 if ( args[0] > 0 ) 1908 { 1909 FT_Int count = 9; 1910 FT_Fixed root = args[0]; 1911 FT_Fixed new_root; 1912 1913 1914 for (;;) 1915 { 1916 new_root = ( root + FT_DivFix( args[0], root ) + 1 ) >> 1; 1917 if ( new_root == root || count <= 0 ) 1918 break; 1919 root = new_root; 1920 } 1921 args[0] = new_root; 1922 } 1923 else 1924 args[0] = 0; 1925 args++; 1926 break; 1927 1928 case cff_op_drop: 1929 /* nothing */ 1930 FT_TRACE4(( " drop" )); 1931 1932 break; 1933 1934 case cff_op_exch: 1935 { 1936 FT_Fixed tmp; 1937 1938 1939 FT_TRACE4(( " exch" )); 1940 1941 tmp = args[0]; 1942 args[0] = args[1]; 1943 args[1] = tmp; 1944 args += 2; 1945 } 1946 break; 1947 1948 case cff_op_index: 1949 { 1950 FT_Int idx = (FT_Int)( args[0] >> 16 ); 1951 1952 1953 FT_TRACE4(( " index" )); 1954 1955 if ( idx < 0 ) 1956 idx = 0; 1957 else if ( idx > num_args - 2 ) 1958 idx = num_args - 2; 1959 args[0] = args[-( idx + 1 )]; 1960 args++; 1961 } 1962 break; 1963 1964 case cff_op_roll: 1965 { 1966 FT_Int count = (FT_Int)( args[0] >> 16 ); 1967 FT_Int idx = (FT_Int)( args[1] >> 16 ); 1968 1969 1970 FT_TRACE4(( " roll" )); 1971 1972 if ( count <= 0 ) 1973 count = 1; 1974 1975 args -= count; 1976 if ( args < stack ) 1977 goto Stack_Underflow; 1978 1979 if ( idx >= 0 ) 1980 { 1981 while ( idx > 0 ) 1982 { 1983 FT_Fixed tmp = args[count - 1]; 1984 FT_Int i; 1985 1986 1987 for ( i = count - 2; i >= 0; i-- ) 1988 args[i + 1] = args[i]; 1989 args[0] = tmp; 1990 idx--; 1991 } 1992 } 1993 else 1994 { 1995 while ( idx < 0 ) 1996 { 1997 FT_Fixed tmp = args[0]; 1998 FT_Int i; 1999 2000 2001 for ( i = 0; i < count - 1; i++ ) 2002 args[i] = args[i + 1]; 2003 args[count - 1] = tmp; 2004 idx++; 2005 } 2006 } 2007 args += count; 2008 } 2009 break; 2010 2011 case cff_op_dup: 2012 FT_TRACE4(( " dup" )); 2013 2014 args[1] = args[0]; 2015 args++; 2016 break; 2017 2018 case cff_op_put: 2019 { 2020 FT_Fixed val = args[0]; 2021 FT_Int idx = (FT_Int)( args[1] >> 16 ); 2022 2023 2024 FT_TRACE4(( " put" )); 2025 2026 if ( idx >= 0 && idx < decoder->len_buildchar ) 2027 decoder->buildchar[idx] = val; 2028 } 2029 break; 2030 2031 case cff_op_get: 2032 { 2033 FT_Int idx = (FT_Int)( args[0] >> 16 ); 2034 FT_Fixed val = 0; 2035 2036 2037 FT_TRACE4(( " get" )); 2038 2039 if ( idx >= 0 && idx < decoder->len_buildchar ) 2040 val = decoder->buildchar[idx]; 2041 2042 args[0] = val; 2043 args++; 2044 } 2045 break; 2046 2047 case cff_op_store: 2048 FT_TRACE4(( " store ")); 2049 2050 goto Unimplemented; 2051 2052 case cff_op_load: 2053 FT_TRACE4(( " load" )); 2054 2055 goto Unimplemented; 2056 2057 case cff_op_dotsection: 2058 /* this operator is deprecated and ignored by the parser */ 2059 FT_TRACE4(( " dotsection" )); 2060 break; 2061 2062 case cff_op_closepath: 2063 /* this is an invalid Type 2 operator; however, there */ 2064 /* exist fonts which are incorrectly converted from probably */ 2065 /* Type 1 to CFF, and some parsers seem to accept it */ 2066 2067 FT_TRACE4(( " closepath (invalid op)" )); 2068 2069 args = stack; 2070 break; 2071 2072 case cff_op_hsbw: 2073 /* this is an invalid Type 2 operator; however, there */ 2074 /* exist fonts which are incorrectly converted from probably */ 2075 /* Type 1 to CFF, and some parsers seem to accept it */ 2076 2077 FT_TRACE4(( " hsbw (invalid op)" )); 2078 2079 decoder->glyph_width = decoder->nominal_width + 2080 (args[1] >> 16); 2081 x = args[0]; 2082 y = 0; 2083 args = stack; 2084 break; 2085 2086 case cff_op_and: 2087 { 2088 FT_Fixed cond = args[0] && args[1]; 2089 2090 2091 FT_TRACE4(( " and" )); 2092 2093 args[0] = cond ? 0x10000L : 0; 2094 args++; 2095 } 2096 break; 2097 2098 case cff_op_or: 2099 { 2100 FT_Fixed cond = args[0] || args[1]; 2101 2102 2103 FT_TRACE4(( " or" )); 2104 2105 args[0] = cond ? 0x10000L : 0; 2106 args++; 2107 } 2108 break; 2109 2110 case cff_op_eq: 2111 { 2112 FT_Fixed cond = !args[0]; 2113 2114 2115 FT_TRACE4(( " eq" )); 2116 2117 args[0] = cond ? 0x10000L : 0; 2118 args++; 2119 } 2120 break; 2121 2122 case cff_op_ifelse: 2123 { 2124 FT_Fixed cond = ( args[2] <= args[3] ); 2125 2126 2127 FT_TRACE4(( " ifelse" )); 2128 2129 if ( !cond ) 2130 args[0] = args[1]; 2131 args++; 2132 } 2133 break; 2134 2135 case cff_op_callsubr: 2136 { 2137 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2138 decoder->locals_bias ); 2139 2140 2141 FT_TRACE4(( " callsubr(%d)", idx )); 2142 2143 if ( idx >= decoder->num_locals ) 2144 { 2145 FT_ERROR(( "cff_decoder_parse_charstrings:" )); 2146 FT_ERROR(( " invalid local subr index\n" )); 2147 goto Syntax_Error; 2148 } 2149 2150 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2151 { 2152 FT_ERROR(( "cff_decoder_parse_charstrings:" 2153 " too many nested subrs\n" )); 2154 goto Syntax_Error; 2155 } 2156 2157 zone->cursor = ip; /* save current instruction pointer */ 2158 2159 zone++; 2160 zone->base = decoder->locals[idx]; 2161 zone->limit = decoder->locals[idx + 1]; 2162 zone->cursor = zone->base; 2163 2164 if ( !zone->base || zone->limit == zone->base ) 2165 { 2166 FT_ERROR(( "cff_decoder_parse_charstrings:" 2167 " invoking empty subrs!\n" )); 2168 goto Syntax_Error; 2169 } 2170 2171 decoder->zone = zone; 2172 ip = zone->base; 2173 limit = zone->limit; 2174 } 2175 break; 2176 2177 case cff_op_callgsubr: 2178 { 2179 FT_UInt idx = (FT_UInt)( ( args[0] >> 16 ) + 2180 decoder->globals_bias ); 2181 2182 2183 FT_TRACE4(( " callgsubr(%d)", idx )); 2184 2185 if ( idx >= decoder->num_globals ) 2186 { 2187 FT_ERROR(( "cff_decoder_parse_charstrings:" )); 2188 FT_ERROR(( " invalid global subr index\n" )); 2189 goto Syntax_Error; 2190 } 2191 2192 if ( zone - decoder->zones >= CFF_MAX_SUBRS_CALLS ) 2193 { 2194 FT_ERROR(( "cff_decoder_parse_charstrings:" 2195 " too many nested subrs\n" )); 2196 goto Syntax_Error; 2197 } 2198 2199 zone->cursor = ip; /* save current instruction pointer */ 2200 2201 zone++; 2202 zone->base = decoder->globals[idx]; 2203 zone->limit = decoder->globals[idx + 1]; 2204 zone->cursor = zone->base; 2205 2206 if ( !zone->base || zone->limit == zone->base ) 2207 { 2208 FT_ERROR(( "cff_decoder_parse_charstrings:" 2209 " invoking empty subrs!\n" )); 2210 goto Syntax_Error; 2211 } 2212 2213 decoder->zone = zone; 2214 ip = zone->base; 2215 limit = zone->limit; 2216 } 2217 break; 2218 2219 case cff_op_return: 2220 FT_TRACE4(( " return" )); 2221 2222 if ( decoder->zone <= decoder->zones ) 2223 { 2224 FT_ERROR(( "cff_decoder_parse_charstrings:" 2225 " unexpected return\n" )); 2226 goto Syntax_Error; 2227 } 2228 2229 decoder->zone--; 2230 zone = decoder->zone; 2231 ip = zone->cursor; 2232 limit = zone->limit; 2233 break; 2234 2235 default: 2236 Unimplemented: 2237 FT_ERROR(( "Unimplemented opcode: %d", ip[-1] )); 2238 2239 if ( ip[-1] == 12 ) 2240 FT_ERROR(( " %d", ip[0] )); 2241 FT_ERROR(( "\n" )); 2242 2243 return CFF_Err_Unimplemented_Feature; 2244 } 2245 2246 decoder->top = args; 2247 2248 } /* general operator processing */ 2249 2250 } /* while ip < limit */ 2251 2252 FT_TRACE4(( "..end..\n\n" )); 2253 2254 Fail: 2255 return error; 2256 2257 Syntax_Error: 2258 FT_TRACE4(( "cff_decoder_parse_charstrings: syntax error!" )); 2259 return CFF_Err_Invalid_File_Format; 2260 2261 Stack_Underflow: 2262 FT_TRACE4(( "cff_decoder_parse_charstrings: stack underflow!" )); 2263 return CFF_Err_Too_Few_Arguments; 2264 2265 Stack_Overflow: 2266 FT_TRACE4(( "cff_decoder_parse_charstrings: stack overflow!" )); 2267 return CFF_Err_Stack_Overflow; 2268 } 2269 2270 2271 /*************************************************************************/ 2272 /*************************************************************************/ 2273 /*************************************************************************/ 2274 /********** *********/ 2275 /********** *********/ 2276 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 2277 /********** *********/ 2278 /********** The following code is in charge of computing *********/ 2279 /********** the maximum advance width of the font. It *********/ 2280 /********** quickly processes each glyph charstring to *********/ 2281 /********** extract the value from either a `sbw' or `seac' *********/ 2282 /********** operator. *********/ 2283 /********** *********/ 2284 /*************************************************************************/ 2285 /*************************************************************************/ 2286 /*************************************************************************/ 2287 2288 2289#if 0 /* unused until we support pure CFF fonts */ 2290 2291 2292 FT_LOCAL_DEF( FT_Error ) 2293 cff_compute_max_advance( TT_Face face, 2294 FT_Int* max_advance ) 2295 { 2296 FT_Error error = CFF_Err_Ok; 2297 CFF_Decoder decoder; 2298 FT_Int glyph_index; 2299 CFF_Font cff = (CFF_Font)face->other; 2300 2301 2302 *max_advance = 0; 2303 2304 /* Initialize load decoder */ 2305 cff_decoder_init( &decoder, face, 0, 0, 0, 0 ); 2306 2307 decoder.builder.metrics_only = 1; 2308 decoder.builder.load_points = 0; 2309 2310 /* For each glyph, parse the glyph charstring and extract */ 2311 /* the advance width. */ 2312 for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 2313 glyph_index++ ) 2314 { 2315 FT_Byte* charstring; 2316 FT_ULong charstring_len; 2317 2318 2319 /* now get load the unscaled outline */ 2320 error = cff_get_glyph_data( face, glyph_index, 2321 &charstring, &charstring_len ); 2322 if ( !error ) 2323 { 2324 error = cff_decoder_prepare( &decoder, size, glyph_index ); 2325 if ( !error ) 2326 error = cff_decoder_parse_charstrings( &decoder, 2327 charstring, 2328 charstring_len ); 2329 2330 cff_free_glyph_data( face, &charstring, &charstring_len ); 2331 } 2332 2333 /* ignore the error if one has occurred -- skip to next glyph */ 2334 error = CFF_Err_Ok; 2335 } 2336 2337 *max_advance = decoder.builder.advance.x; 2338 2339 return CFF_Err_Ok; 2340 } 2341 2342 2343#endif /* 0 */ 2344 2345 2346 FT_LOCAL_DEF( FT_Error ) 2347 cff_slot_load( CFF_GlyphSlot glyph, 2348 CFF_Size size, 2349 FT_UInt glyph_index, 2350 FT_Int32 load_flags ) 2351 { 2352 FT_Error error; 2353 CFF_Decoder decoder; 2354 TT_Face face = (TT_Face)glyph->root.face; 2355 FT_Bool hinting, force_scaling; 2356 CFF_Font cff = (CFF_Font)face->extra.data; 2357 2358 FT_Matrix font_matrix; 2359 FT_Vector font_offset; 2360 2361 force_scaling = FALSE; 2362 2363 /* in a CID-keyed font, consider `glyph_index' as a CID and map */ 2364 /* it immediately to the real glyph_index -- if it isn't a */ 2365 /* subsetted font, glyph_indices and CIDs are identical, though */ 2366 if ( cff->top_font.font_dict.cid_registry != 0xFFFFU && 2367 cff->charset.cids ) 2368 { 2369 glyph_index = cff_charset_cid_to_gindex( &cff->charset, glyph_index ); 2370 if ( glyph_index == 0 ) 2371 return CFF_Err_Invalid_Argument; 2372 } 2373 else if ( glyph_index >= cff->num_glyphs ) 2374 return CFF_Err_Invalid_Argument; 2375 2376 if ( load_flags & FT_LOAD_NO_RECURSE ) 2377 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 2378 2379 glyph->x_scale = 0x10000L; 2380 glyph->y_scale = 0x10000L; 2381 if ( size ) 2382 { 2383 glyph->x_scale = size->root.metrics.x_scale; 2384 glyph->y_scale = size->root.metrics.y_scale; 2385 } 2386 2387#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2388 2389 /* try to load embedded bitmap if any */ 2390 /* */ 2391 /* XXX: The convention should be emphasized in */ 2392 /* the documents because it can be confusing. */ 2393 if ( size ) 2394 { 2395 CFF_Face cff_face = (CFF_Face)size->root.face; 2396 SFNT_Service sfnt = (SFNT_Service)cff_face->sfnt; 2397 FT_Stream stream = cff_face->root.stream; 2398 2399 2400 if ( size->strike_index != 0xFFFFFFFFUL && 2401 sfnt->load_eblc && 2402 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 2403 { 2404 TT_SBit_MetricsRec metrics; 2405 2406 2407 error = sfnt->load_sbit_image( face, 2408 size->strike_index, 2409 glyph_index, 2410 (FT_Int)load_flags, 2411 stream, 2412 &glyph->root.bitmap, 2413 &metrics ); 2414 2415 if ( !error ) 2416 { 2417 glyph->root.outline.n_points = 0; 2418 glyph->root.outline.n_contours = 0; 2419 2420 glyph->root.metrics.width = (FT_Pos)metrics.width << 6; 2421 glyph->root.metrics.height = (FT_Pos)metrics.height << 6; 2422 2423 glyph->root.metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 2424 glyph->root.metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 2425 glyph->root.metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 2426 2427 glyph->root.metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 2428 glyph->root.metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 2429 glyph->root.metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 2430 2431 glyph->root.format = FT_GLYPH_FORMAT_BITMAP; 2432 2433 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 2434 { 2435 glyph->root.bitmap_left = metrics.vertBearingX; 2436 glyph->root.bitmap_top = metrics.vertBearingY; 2437 } 2438 else 2439 { 2440 glyph->root.bitmap_left = metrics.horiBearingX; 2441 glyph->root.bitmap_top = metrics.horiBearingY; 2442 } 2443 return error; 2444 } 2445 } 2446 } 2447 2448#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2449 2450 /* return immediately if we only want the embedded bitmaps */ 2451 if ( load_flags & FT_LOAD_SBITS_ONLY ) 2452 return CFF_Err_Invalid_Argument; 2453 2454 /* if we have a CID subfont, use its matrix (which has already */ 2455 /* been multiplied with the root matrix) */ 2456 2457 /* this scaling is only relevant if the PS hinter isn't active */ 2458 if ( cff->num_subfonts ) 2459 { 2460 FT_Byte fd_index = cff_fd_select_get( &cff->fd_select, 2461 glyph_index ); 2462 2463 FT_Int top_upm = cff->top_font.font_dict.units_per_em; 2464 FT_Int sub_upm = cff->subfonts[fd_index]->font_dict.units_per_em; 2465 2466 2467 font_matrix = cff->subfonts[fd_index]->font_dict.font_matrix; 2468 font_offset = cff->subfonts[fd_index]->font_dict.font_offset; 2469 2470 if ( top_upm != sub_upm ) 2471 { 2472 glyph->x_scale = FT_MulDiv( glyph->x_scale, top_upm, sub_upm ); 2473 glyph->y_scale = FT_MulDiv( glyph->y_scale, top_upm, sub_upm ); 2474 2475 force_scaling = TRUE; 2476 } 2477 } 2478 else 2479 { 2480 font_matrix = cff->top_font.font_dict.font_matrix; 2481 font_offset = cff->top_font.font_dict.font_offset; 2482 } 2483 2484 glyph->root.outline.n_points = 0; 2485 glyph->root.outline.n_contours = 0; 2486 2487 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 2488 ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 2489 2490 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; /* by default */ 2491 2492 { 2493 FT_Byte* charstring; 2494 FT_ULong charstring_len; 2495 2496 2497 cff_decoder_init( &decoder, face, size, glyph, hinting, 2498 FT_LOAD_TARGET_MODE( load_flags ) ); 2499 2500 if ((load_flags & FT_LOAD_ADVANCE_ONLY) != 0) 2501 cff_decoder_set_width_only( &decoder ); 2502 2503 decoder.builder.no_recurse = 2504 (FT_Bool)( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ); 2505 2506 /* now load the unscaled outline */ 2507 error = cff_get_glyph_data( face, glyph_index, 2508 &charstring, &charstring_len ); 2509 if ( !error ) 2510 { 2511 error = cff_decoder_prepare( &decoder, size, glyph_index ); 2512 if ( !error ) 2513 { 2514 error = cff_decoder_parse_charstrings( &decoder, 2515 charstring, 2516 charstring_len ); 2517 2518 cff_free_glyph_data( face, &charstring, charstring_len ); 2519 2520 2521#ifdef FT_CONFIG_OPTION_INCREMENTAL 2522 /* Control data and length may not be available for incremental */ 2523 /* fonts. */ 2524 if ( face->root.internal->incremental_interface ) 2525 { 2526 glyph->root.control_data = 0; 2527 glyph->root.control_len = 0; 2528 } 2529 else 2530#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2531 2532 /* We set control_data and control_len if charstrings is loaded. */ 2533 /* See how charstring loads at cff_index_access_element() in */ 2534 /* cffload.c. */ 2535 { 2536 CFF_Index csindex = &cff->charstrings_index; 2537 2538 2539 if ( csindex->offsets ) 2540 { 2541 glyph->root.control_data = csindex->bytes + 2542 csindex->offsets[glyph_index] - 1; 2543 glyph->root.control_len = charstring_len; 2544 } 2545 } 2546 } 2547 } 2548 2549 /* save new glyph tables */ 2550 cff_builder_done( &decoder.builder ); 2551 } 2552 2553#ifdef FT_CONFIG_OPTION_INCREMENTAL 2554 2555 /* Incremental fonts can optionally override the metrics. */ 2556 if ( !error && 2557 face->root.internal->incremental_interface && 2558 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 2559 { 2560 FT_Incremental_MetricsRec metrics; 2561 2562 2563 metrics.bearing_x = decoder.builder.left_bearing.x; 2564 metrics.bearing_y = decoder.builder.left_bearing.y; 2565 metrics.advance = decoder.builder.advance.x; 2566 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 2567 face->root.internal->incremental_interface->object, 2568 glyph_index, FALSE, &metrics ); 2569 decoder.builder.left_bearing.x = metrics.bearing_x; 2570 decoder.builder.left_bearing.y = metrics.bearing_y; 2571 decoder.builder.advance.x = metrics.advance; 2572 decoder.builder.advance.y = 0; 2573 } 2574 2575#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2576 2577 if ( !error ) 2578 { 2579 /* Now, set the metrics -- this is rather simple, as */ 2580 /* the left side bearing is the xMin, and the top side */ 2581 /* bearing the yMax. */ 2582 2583 /* For composite glyphs, return only left side bearing and */ 2584 /* advance width. */ 2585 if ( load_flags & FT_LOAD_NO_RECURSE ) 2586 { 2587 FT_Slot_Internal internal = glyph->root.internal; 2588 2589 2590 glyph->root.metrics.horiBearingX = decoder.builder.left_bearing.x; 2591 glyph->root.metrics.horiAdvance = decoder.glyph_width; 2592 internal->glyph_matrix = font_matrix; 2593 internal->glyph_delta = font_offset; 2594 internal->glyph_transformed = 1; 2595 } 2596 else 2597 { 2598 FT_BBox cbox; 2599 FT_Glyph_Metrics* metrics = &glyph->root.metrics; 2600 FT_Vector advance; 2601 FT_Bool has_vertical_info; 2602 2603 2604 /* copy the _unscaled_ advance width */ 2605 metrics->horiAdvance = decoder.glyph_width; 2606 glyph->root.linearHoriAdvance = decoder.glyph_width; 2607 glyph->root.internal->glyph_transformed = 0; 2608 2609 has_vertical_info = FT_BOOL( face->vertical_info && 2610 face->vertical.number_Of_VMetrics > 0 && 2611 face->vertical.long_metrics != 0 ); 2612 2613 /* get the vertical metrics from the vtmx table if we have one */ 2614 if ( has_vertical_info ) 2615 { 2616 FT_Short vertBearingY = 0; 2617 FT_UShort vertAdvance = 0; 2618 2619 2620 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, 2621 glyph_index, 2622 &vertBearingY, 2623 &vertAdvance ); 2624 metrics->vertBearingY = vertBearingY; 2625 metrics->vertAdvance = vertAdvance; 2626 } 2627 else 2628 { 2629 /* make up vertical ones */ 2630 if ( face->os2.version != 0xFFFFU ) 2631 metrics->vertAdvance = (FT_Pos)( face->os2.sTypoAscender - 2632 face->os2.sTypoDescender ); 2633 else 2634 metrics->vertAdvance = (FT_Pos)( face->horizontal.Ascender - 2635 face->horizontal.Descender ); 2636 } 2637 2638 glyph->root.linearVertAdvance = metrics->vertAdvance; 2639 2640 glyph->root.format = FT_GLYPH_FORMAT_OUTLINE; 2641 2642 glyph->root.outline.flags = 0; 2643 if ( size && size->root.metrics.y_ppem < 24 ) 2644 glyph->root.outline.flags |= FT_OUTLINE_HIGH_PRECISION; 2645 2646 glyph->root.outline.flags |= FT_OUTLINE_REVERSE_FILL; 2647 2648 /* apply the font matrix -- `xx' has already been normalized */ 2649 if ( !( font_matrix.yy == 0x10000L && 2650 font_matrix.xy == 0 && 2651 font_matrix.yx == 0 ) ) 2652 FT_Outline_Transform( &glyph->root.outline, &font_matrix ); 2653 2654 if ( !( font_offset.x == 0 && 2655 font_offset.y == 0 ) ) 2656 FT_Outline_Translate( &glyph->root.outline, 2657 font_offset.x, font_offset.y ); 2658 2659 advance.x = metrics->horiAdvance; 2660 advance.y = 0; 2661 FT_Vector_Transform( &advance, &font_matrix ); 2662 metrics->horiAdvance = advance.x + font_offset.x; 2663 2664 advance.x = 0; 2665 advance.y = metrics->vertAdvance; 2666 FT_Vector_Transform( &advance, &font_matrix ); 2667 metrics->vertAdvance = advance.y + font_offset.y; 2668 2669 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) 2670 { 2671 /* scale the outline and the metrics */ 2672 FT_Int n; 2673 FT_Outline* cur = &glyph->root.outline; 2674 FT_Vector* vec = cur->points; 2675 FT_Fixed x_scale = glyph->x_scale; 2676 FT_Fixed y_scale = glyph->y_scale; 2677 2678 2679 /* First of all, scale the points */ 2680 if ( !hinting || !decoder.builder.hints_funcs ) 2681 for ( n = cur->n_points; n > 0; n--, vec++ ) 2682 { 2683 vec->x = FT_MulFix( vec->x, x_scale ); 2684 vec->y = FT_MulFix( vec->y, y_scale ); 2685 } 2686 2687 /* Then scale the metrics */ 2688 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 2689 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 2690 } 2691 2692 /* compute the other metrics */ 2693 FT_Outline_Get_CBox( &glyph->root.outline, &cbox ); 2694 2695 metrics->width = cbox.xMax - cbox.xMin; 2696 metrics->height = cbox.yMax - cbox.yMin; 2697 2698 metrics->horiBearingX = cbox.xMin; 2699 metrics->horiBearingY = cbox.yMax; 2700 2701 if ( has_vertical_info ) 2702 metrics->vertBearingX = -metrics->width / 2; 2703 else 2704 ft_synthesize_vertical_metrics( metrics, 2705 metrics->vertAdvance ); 2706 } 2707 } 2708 2709 return error; 2710 } 2711 2712 2713/* END */ 2714