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