ttgload.c (75997B)
1 /***************************************************************************/ 2 /* */ 3 /* ttgload.c */ 4 /* */ 5 /* TrueType Glyph Loader (body). */ 6 /* */ 7 /* Copyright 1996-2013 */ 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_TRUETYPE_TAGS_H 25 #include FT_OUTLINE_H 26 #include FT_TRUETYPE_DRIVER_H 27 28 #include "ttgload.h" 29 #include "ttpload.h" 30 31 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 32 #include "ttgxvar.h" 33 #endif 34 35 #include "tterrors.h" 36 #include "ttsubpix.h" 37 38 39 /*************************************************************************/ 40 /* */ 41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 43 /* messages during execution. */ 44 /* */ 45 #undef FT_COMPONENT 46 #define FT_COMPONENT trace_ttgload 47 48 49 /*************************************************************************/ 50 /* */ 51 /* Composite glyph flags. */ 52 /* */ 53 #define ARGS_ARE_WORDS 0x0001 54 #define ARGS_ARE_XY_VALUES 0x0002 55 #define ROUND_XY_TO_GRID 0x0004 56 #define WE_HAVE_A_SCALE 0x0008 57 /* reserved 0x0010 */ 58 #define MORE_COMPONENTS 0x0020 59 #define WE_HAVE_AN_XY_SCALE 0x0040 60 #define WE_HAVE_A_2X2 0x0080 61 #define WE_HAVE_INSTR 0x0100 62 #define USE_MY_METRICS 0x0200 63 #define OVERLAP_COMPOUND 0x0400 64 #define SCALED_COMPONENT_OFFSET 0x0800 65 #define UNSCALED_COMPONENT_OFFSET 0x1000 66 67 68 /*************************************************************************/ 69 /* */ 70 /* Return the horizontal metrics in font units for a given glyph. */ 71 /* */ 72 FT_LOCAL_DEF( void ) 73 TT_Get_HMetrics( TT_Face face, 74 FT_UInt idx, 75 FT_Short* lsb, 76 FT_UShort* aw ) 77 { 78 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); 79 80 FT_TRACE5(( " advance width (font units): %d\n", *aw )); 81 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb )); 82 } 83 84 85 /*************************************************************************/ 86 /* */ 87 /* Return the vertical metrics in font units for a given glyph. */ 88 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */ 89 /* table, typoAscender/Descender from the `OS/2' table would be used */ 90 /* instead, and if there were no `OS/2' table, use ascender/descender */ 91 /* from the `hhea' table. But that is not what Microsoft's rasterizer */ 92 /* apparently does: It uses the ppem value as the advance height, and */ 93 /* sets the top side bearing to be zero. */ 94 /* */ 95 FT_LOCAL_DEF( void ) 96 TT_Get_VMetrics( TT_Face face, 97 FT_UInt idx, 98 FT_Short* tsb, 99 FT_UShort* ah ) 100 { 101 if ( face->vertical_info ) 102 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); 103 104 #if 1 /* Empirically determined, at variance with what MS said */ 105 106 else 107 { 108 *tsb = 0; 109 *ah = face->root.units_per_EM; 110 } 111 112 #else /* This is what MS said to do. It isn't what they do, however. */ 113 114 else if ( face->os2.version != 0xFFFFU ) 115 { 116 *tsb = face->os2.sTypoAscender; 117 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; 118 } 119 else 120 { 121 *tsb = face->horizontal.Ascender; 122 *ah = face->horizontal.Ascender - face->horizontal.Descender; 123 } 124 125 #endif 126 127 FT_TRACE5(( " advance height (font units): %d\n", *ah )); 128 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb )); 129 } 130 131 132 static void 133 tt_get_metrics( TT_Loader loader, 134 FT_UInt glyph_index ) 135 { 136 TT_Face face = (TT_Face)loader->face; 137 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 138 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 139 #endif 140 141 FT_Short left_bearing = 0, top_bearing = 0; 142 FT_UShort advance_width = 0, advance_height = 0; 143 144 145 TT_Get_HMetrics( face, glyph_index, 146 &left_bearing, 147 &advance_width ); 148 TT_Get_VMetrics( face, glyph_index, 149 &top_bearing, 150 &advance_height ); 151 152 loader->left_bearing = left_bearing; 153 loader->advance = advance_width; 154 loader->top_bearing = top_bearing; 155 loader->vadvance = advance_height; 156 157 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 158 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 159 { 160 if ( loader->exec ) 161 loader->exec->sph_tweak_flags = 0; 162 163 /* this may not be the right place for this, but it works */ 164 if ( loader->exec && loader->exec->ignore_x_mode ) 165 sph_set_tweaks( loader, glyph_index ); 166 } 167 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 168 169 if ( !loader->linear_def ) 170 { 171 loader->linear_def = 1; 172 loader->linear = advance_width; 173 } 174 } 175 176 177 #ifdef FT_CONFIG_OPTION_INCREMENTAL 178 179 static void 180 tt_get_metrics_incr_overrides( TT_Loader loader, 181 FT_UInt glyph_index ) 182 { 183 TT_Face face = (TT_Face)loader->face; 184 185 FT_Short left_bearing = 0, top_bearing = 0; 186 FT_UShort advance_width = 0, advance_height = 0; 187 188 189 /* If this is an incrementally loaded font check whether there are */ 190 /* overriding metrics for this glyph. */ 191 if ( face->root.internal->incremental_interface && 192 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 193 { 194 FT_Incremental_MetricsRec metrics; 195 FT_Error error; 196 197 198 metrics.bearing_x = loader->left_bearing; 199 metrics.bearing_y = 0; 200 metrics.advance = loader->advance; 201 metrics.advance_v = 0; 202 203 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 204 face->root.internal->incremental_interface->object, 205 glyph_index, FALSE, &metrics ); 206 if ( error ) 207 goto Exit; 208 209 left_bearing = (FT_Short)metrics.bearing_x; 210 advance_width = (FT_UShort)metrics.advance; 211 212 #if 0 213 214 /* GWW: Do I do the same for vertical metrics? */ 215 metrics.bearing_x = 0; 216 metrics.bearing_y = loader->top_bearing; 217 metrics.advance = loader->vadvance; 218 219 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 220 face->root.internal->incremental_interface->object, 221 glyph_index, TRUE, &metrics ); 222 if ( error ) 223 goto Exit; 224 225 top_bearing = (FT_Short)metrics.bearing_y; 226 advance_height = (FT_UShort)metrics.advance; 227 228 #endif /* 0 */ 229 230 loader->left_bearing = left_bearing; 231 loader->advance = advance_width; 232 loader->top_bearing = top_bearing; 233 loader->vadvance = advance_height; 234 235 if ( !loader->linear_def ) 236 { 237 loader->linear_def = 1; 238 loader->linear = advance_width; 239 } 240 } 241 242 Exit: 243 return; 244 } 245 246 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 247 248 249 /*************************************************************************/ 250 /* */ 251 /* Translates an array of coordinates. */ 252 /* */ 253 static void 254 translate_array( FT_UInt n, 255 FT_Vector* coords, 256 FT_Pos delta_x, 257 FT_Pos delta_y ) 258 { 259 FT_UInt k; 260 261 262 if ( delta_x ) 263 for ( k = 0; k < n; k++ ) 264 coords[k].x += delta_x; 265 266 if ( delta_y ) 267 for ( k = 0; k < n; k++ ) 268 coords[k].y += delta_y; 269 } 270 271 272 /*************************************************************************/ 273 /* */ 274 /* The following functions are used by default with TrueType fonts. */ 275 /* However, they can be replaced by alternatives if we need to support */ 276 /* TrueType-compressed formats (like MicroType) in the future. */ 277 /* */ 278 /*************************************************************************/ 279 280 FT_CALLBACK_DEF( FT_Error ) 281 TT_Access_Glyph_Frame( TT_Loader loader, 282 FT_UInt glyph_index, 283 FT_ULong offset, 284 FT_UInt byte_count ) 285 { 286 FT_Error error; 287 FT_Stream stream = loader->stream; 288 289 /* for non-debug mode */ 290 FT_UNUSED( glyph_index ); 291 292 293 FT_TRACE4(( "Glyph %ld\n", glyph_index )); 294 295 /* the following line sets the `error' variable through macros! */ 296 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) 297 return error; 298 299 loader->cursor = stream->cursor; 300 loader->limit = stream->limit; 301 302 return FT_Err_Ok; 303 } 304 305 306 FT_CALLBACK_DEF( void ) 307 TT_Forget_Glyph_Frame( TT_Loader loader ) 308 { 309 FT_Stream stream = loader->stream; 310 311 312 FT_FRAME_EXIT(); 313 } 314 315 316 FT_CALLBACK_DEF( FT_Error ) 317 TT_Load_Glyph_Header( TT_Loader loader ) 318 { 319 FT_Byte* p = loader->cursor; 320 FT_Byte* limit = loader->limit; 321 322 323 if ( p + 10 > limit ) 324 return FT_THROW( Invalid_Outline ); 325 326 loader->n_contours = FT_NEXT_SHORT( p ); 327 328 loader->bbox.xMin = FT_NEXT_SHORT( p ); 329 loader->bbox.yMin = FT_NEXT_SHORT( p ); 330 loader->bbox.xMax = FT_NEXT_SHORT( p ); 331 loader->bbox.yMax = FT_NEXT_SHORT( p ); 332 333 FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); 334 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, 335 loader->bbox.xMax )); 336 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, 337 loader->bbox.yMax )); 338 loader->cursor = p; 339 340 return FT_Err_Ok; 341 } 342 343 344 FT_CALLBACK_DEF( FT_Error ) 345 TT_Load_Simple_Glyph( TT_Loader load ) 346 { 347 FT_Error error; 348 FT_Byte* p = load->cursor; 349 FT_Byte* limit = load->limit; 350 FT_GlyphLoader gloader = load->gloader; 351 FT_Int n_contours = load->n_contours; 352 FT_Outline* outline; 353 TT_Face face = (TT_Face)load->face; 354 FT_UShort n_ins; 355 FT_Int n_points; 356 357 FT_Byte *flag, *flag_limit; 358 FT_Byte c, count; 359 FT_Vector *vec, *vec_limit; 360 FT_Pos x; 361 FT_Short *cont, *cont_limit, prev_cont; 362 FT_Int xy_size = 0; 363 364 365 /* check that we can add the contours to the glyph */ 366 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); 367 if ( error ) 368 goto Fail; 369 370 /* reading the contours' endpoints & number of points */ 371 cont = gloader->current.outline.contours; 372 cont_limit = cont + n_contours; 373 374 /* check space for contours array + instructions count */ 375 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) 376 goto Invalid_Outline; 377 378 prev_cont = FT_NEXT_SHORT( p ); 379 380 if ( n_contours > 0 ) 381 cont[0] = prev_cont; 382 383 if ( prev_cont < 0 ) 384 goto Invalid_Outline; 385 386 for ( cont++; cont < cont_limit; cont++ ) 387 { 388 cont[0] = FT_NEXT_SHORT( p ); 389 if ( cont[0] <= prev_cont ) 390 { 391 /* unordered contours: this is invalid */ 392 goto Invalid_Outline; 393 } 394 prev_cont = cont[0]; 395 } 396 397 n_points = 0; 398 if ( n_contours > 0 ) 399 { 400 n_points = cont[-1] + 1; 401 if ( n_points < 0 ) 402 goto Invalid_Outline; 403 } 404 405 /* note that we will add four phantom points later */ 406 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); 407 if ( error ) 408 goto Fail; 409 410 /* reading the bytecode instructions */ 411 load->glyph->control_len = 0; 412 load->glyph->control_data = 0; 413 414 if ( p + 2 > limit ) 415 goto Invalid_Outline; 416 417 n_ins = FT_NEXT_USHORT( p ); 418 419 FT_TRACE5(( " Instructions size: %u\n", n_ins )); 420 421 if ( n_ins > face->max_profile.maxSizeOfInstructions ) 422 { 423 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n", 424 n_ins )); 425 error = FT_THROW( Too_Many_Hints ); 426 goto Fail; 427 } 428 429 if ( ( limit - p ) < n_ins ) 430 { 431 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); 432 error = FT_THROW( Too_Many_Hints ); 433 goto Fail; 434 } 435 436 #ifdef TT_USE_BYTECODE_INTERPRETER 437 438 if ( IS_HINTED( load->load_flags ) ) 439 { 440 load->glyph->control_len = n_ins; 441 load->glyph->control_data = load->exec->glyphIns; 442 443 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); 444 } 445 446 #endif /* TT_USE_BYTECODE_INTERPRETER */ 447 448 p += n_ins; 449 450 outline = &gloader->current.outline; 451 452 /* reading the point tags */ 453 flag = (FT_Byte*)outline->tags; 454 flag_limit = flag + n_points; 455 456 FT_ASSERT( flag != NULL ); 457 458 while ( flag < flag_limit ) 459 { 460 if ( p + 1 > limit ) 461 goto Invalid_Outline; 462 463 *flag++ = c = FT_NEXT_BYTE( p ); 464 if ( c & 8 ) 465 { 466 if ( p + 1 > limit ) 467 goto Invalid_Outline; 468 469 count = FT_NEXT_BYTE( p ); 470 if ( flag + (FT_Int)count > flag_limit ) 471 goto Invalid_Outline; 472 473 for ( ; count > 0; count-- ) 474 *flag++ = c; 475 } 476 } 477 478 /* reading the X coordinates */ 479 480 vec = outline->points; 481 vec_limit = vec + n_points; 482 flag = (FT_Byte*)outline->tags; 483 x = 0; 484 485 if ( p + xy_size > limit ) 486 goto Invalid_Outline; 487 488 for ( ; vec < vec_limit; vec++, flag++ ) 489 { 490 FT_Pos y = 0; 491 FT_Byte f = *flag; 492 493 494 if ( f & 2 ) 495 { 496 if ( p + 1 > limit ) 497 goto Invalid_Outline; 498 499 y = (FT_Pos)FT_NEXT_BYTE( p ); 500 if ( ( f & 16 ) == 0 ) 501 y = -y; 502 } 503 else if ( ( f & 16 ) == 0 ) 504 { 505 if ( p + 2 > limit ) 506 goto Invalid_Outline; 507 508 y = (FT_Pos)FT_NEXT_SHORT( p ); 509 } 510 511 x += y; 512 vec->x = x; 513 /* the cast is for stupid compilers */ 514 *flag = (FT_Byte)( f & ~( 2 | 16 ) ); 515 } 516 517 /* reading the Y coordinates */ 518 519 vec = gloader->current.outline.points; 520 vec_limit = vec + n_points; 521 flag = (FT_Byte*)outline->tags; 522 x = 0; 523 524 for ( ; vec < vec_limit; vec++, flag++ ) 525 { 526 FT_Pos y = 0; 527 FT_Byte f = *flag; 528 529 530 if ( f & 4 ) 531 { 532 if ( p + 1 > limit ) 533 goto Invalid_Outline; 534 535 y = (FT_Pos)FT_NEXT_BYTE( p ); 536 if ( ( f & 32 ) == 0 ) 537 y = -y; 538 } 539 else if ( ( f & 32 ) == 0 ) 540 { 541 if ( p + 2 > limit ) 542 goto Invalid_Outline; 543 544 y = (FT_Pos)FT_NEXT_SHORT( p ); 545 } 546 547 x += y; 548 vec->y = x; 549 /* the cast is for stupid compilers */ 550 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON ); 551 } 552 553 outline->n_points = (FT_UShort)n_points; 554 outline->n_contours = (FT_Short) n_contours; 555 556 load->cursor = p; 557 558 Fail: 559 return error; 560 561 Invalid_Outline: 562 error = FT_THROW( Invalid_Outline ); 563 goto Fail; 564 } 565 566 567 FT_CALLBACK_DEF( FT_Error ) 568 TT_Load_Composite_Glyph( TT_Loader loader ) 569 { 570 FT_Error error; 571 FT_Byte* p = loader->cursor; 572 FT_Byte* limit = loader->limit; 573 FT_GlyphLoader gloader = loader->gloader; 574 FT_SubGlyph subglyph; 575 FT_UInt num_subglyphs; 576 577 578 num_subglyphs = 0; 579 580 do 581 { 582 FT_Fixed xx, xy, yy, yx; 583 FT_UInt count; 584 585 586 /* check that we can load a new subglyph */ 587 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); 588 if ( error ) 589 goto Fail; 590 591 /* check space */ 592 if ( p + 4 > limit ) 593 goto Invalid_Composite; 594 595 subglyph = gloader->current.subglyphs + num_subglyphs; 596 597 subglyph->arg1 = subglyph->arg2 = 0; 598 599 subglyph->flags = FT_NEXT_USHORT( p ); 600 subglyph->index = FT_NEXT_USHORT( p ); 601 602 /* check space */ 603 count = 2; 604 if ( subglyph->flags & ARGS_ARE_WORDS ) 605 count += 2; 606 if ( subglyph->flags & WE_HAVE_A_SCALE ) 607 count += 2; 608 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 609 count += 4; 610 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 611 count += 8; 612 613 if ( p + count > limit ) 614 goto Invalid_Composite; 615 616 /* read arguments */ 617 if ( subglyph->flags & ARGS_ARE_WORDS ) 618 { 619 subglyph->arg1 = FT_NEXT_SHORT( p ); 620 subglyph->arg2 = FT_NEXT_SHORT( p ); 621 } 622 else 623 { 624 subglyph->arg1 = FT_NEXT_CHAR( p ); 625 subglyph->arg2 = FT_NEXT_CHAR( p ); 626 } 627 628 /* read transform */ 629 xx = yy = 0x10000L; 630 xy = yx = 0; 631 632 if ( subglyph->flags & WE_HAVE_A_SCALE ) 633 { 634 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 635 yy = xx; 636 } 637 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 638 { 639 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 640 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 641 } 642 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 643 { 644 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 645 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 646 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 647 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 648 } 649 650 subglyph->transform.xx = xx; 651 subglyph->transform.xy = xy; 652 subglyph->transform.yx = yx; 653 subglyph->transform.yy = yy; 654 655 num_subglyphs++; 656 657 } while ( subglyph->flags & MORE_COMPONENTS ); 658 659 gloader->current.num_subglyphs = num_subglyphs; 660 661 #ifdef TT_USE_BYTECODE_INTERPRETER 662 663 { 664 FT_Stream stream = loader->stream; 665 666 667 /* we must undo the FT_FRAME_ENTER in order to point */ 668 /* to the composite instructions, if we find some. */ 669 /* We will process them later. */ 670 /* */ 671 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + 672 p - limit ); 673 } 674 675 #endif 676 677 loader->cursor = p; 678 679 Fail: 680 return error; 681 682 Invalid_Composite: 683 error = FT_THROW( Invalid_Composite ); 684 goto Fail; 685 } 686 687 688 FT_LOCAL_DEF( void ) 689 TT_Init_Glyph_Loading( TT_Face face ) 690 { 691 face->access_glyph_frame = TT_Access_Glyph_Frame; 692 face->read_glyph_header = TT_Load_Glyph_Header; 693 face->read_simple_glyph = TT_Load_Simple_Glyph; 694 face->read_composite_glyph = TT_Load_Composite_Glyph; 695 face->forget_glyph_frame = TT_Forget_Glyph_Frame; 696 } 697 698 699 static void 700 tt_prepare_zone( TT_GlyphZone zone, 701 FT_GlyphLoad load, 702 FT_UInt start_point, 703 FT_UInt start_contour ) 704 { 705 zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); 706 zone->n_contours = (FT_Short) ( load->outline.n_contours - 707 start_contour ); 708 zone->org = load->extra_points + start_point; 709 zone->cur = load->outline.points + start_point; 710 zone->orus = load->extra_points2 + start_point; 711 zone->tags = (FT_Byte*)load->outline.tags + start_point; 712 zone->contours = (FT_UShort*)load->outline.contours + start_contour; 713 zone->first_point = (FT_UShort)start_point; 714 } 715 716 717 /*************************************************************************/ 718 /* */ 719 /* <Function> */ 720 /* TT_Hint_Glyph */ 721 /* */ 722 /* <Description> */ 723 /* Hint the glyph using the zone prepared by the caller. Note that */ 724 /* the zone is supposed to include four phantom points. */ 725 /* */ 726 static FT_Error 727 TT_Hint_Glyph( TT_Loader loader, 728 FT_Bool is_composite ) 729 { 730 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 731 TT_Face face = (TT_Face)loader->face; 732 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 733 #endif 734 735 TT_GlyphZone zone = &loader->zone; 736 FT_Pos origin; 737 738 #ifdef TT_USE_BYTECODE_INTERPRETER 739 FT_UInt n_ins; 740 #else 741 FT_UNUSED( is_composite ); 742 #endif 743 744 745 #ifdef TT_USE_BYTECODE_INTERPRETER 746 if ( loader->glyph->control_len > 0xFFFFL ) 747 { 748 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " )); 749 FT_TRACE1(( "(0x%lx byte) is truncated\n", 750 loader->glyph->control_len )); 751 } 752 n_ins = (FT_UInt)( loader->glyph->control_len ); 753 #endif 754 755 origin = zone->cur[zone->n_points - 4].x; 756 origin = FT_PIX_ROUND( origin ) - origin; 757 if ( origin ) 758 translate_array( zone->n_points, zone->cur, origin, 0 ); 759 760 #ifdef TT_USE_BYTECODE_INTERPRETER 761 /* save original point position in org */ 762 if ( n_ins > 0 ) 763 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); 764 765 /* Reset graphics state. */ 766 loader->exec->GS = ((TT_Size)loader->size)->GS; 767 768 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ 769 /* completely refer to the (already) hinted subglyphs. */ 770 if ( is_composite ) 771 { 772 loader->exec->metrics.x_scale = 1 << 16; 773 loader->exec->metrics.y_scale = 1 << 16; 774 775 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); 776 } 777 else 778 { 779 loader->exec->metrics.x_scale = 780 ((TT_Size)loader->size)->metrics.x_scale; 781 loader->exec->metrics.y_scale = 782 ((TT_Size)loader->size)->metrics.y_scale; 783 } 784 #endif 785 786 /* round pp2 and pp4 */ 787 zone->cur[zone->n_points - 3].x = 788 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); 789 zone->cur[zone->n_points - 1].y = 790 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); 791 792 #ifdef TT_USE_BYTECODE_INTERPRETER 793 794 if ( n_ins > 0 ) 795 { 796 FT_Bool debug; 797 FT_Error error; 798 799 FT_GlyphLoader gloader = loader->gloader; 800 FT_Outline current_outline = gloader->current.outline; 801 802 803 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph, 804 loader->exec->glyphIns, n_ins ); 805 if ( error ) 806 return error; 807 808 loader->exec->is_composite = is_composite; 809 loader->exec->pts = *zone; 810 811 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) && 812 ((TT_Size)loader->size)->debug ); 813 814 error = TT_Run_Context( loader->exec, debug ); 815 if ( error && loader->exec->pedantic_hinting ) 816 return error; 817 818 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ 819 current_outline.tags[0] |= 820 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; 821 } 822 823 #endif 824 825 /* save glyph phantom points */ 826 if ( !loader->preserve_pps ) 827 { 828 loader->pp1 = zone->cur[zone->n_points - 4]; 829 loader->pp2 = zone->cur[zone->n_points - 3]; 830 loader->pp3 = zone->cur[zone->n_points - 2]; 831 loader->pp4 = zone->cur[zone->n_points - 1]; 832 } 833 834 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 835 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 836 { 837 if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) 838 FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); 839 840 else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) 841 FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); 842 } 843 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 844 845 return FT_Err_Ok; 846 } 847 848 849 /*************************************************************************/ 850 /* */ 851 /* <Function> */ 852 /* TT_Process_Simple_Glyph */ 853 /* */ 854 /* <Description> */ 855 /* Once a simple glyph has been loaded, it needs to be processed. */ 856 /* Usually, this means scaling and hinting through bytecode */ 857 /* interpretation. */ 858 /* */ 859 static FT_Error 860 TT_Process_Simple_Glyph( TT_Loader loader ) 861 { 862 FT_GlyphLoader gloader = loader->gloader; 863 FT_Error error = FT_Err_Ok; 864 FT_Outline* outline; 865 FT_Int n_points; 866 867 868 outline = &gloader->current.outline; 869 n_points = outline->n_points; 870 871 /* set phantom points */ 872 873 outline->points[n_points ] = loader->pp1; 874 outline->points[n_points + 1] = loader->pp2; 875 outline->points[n_points + 2] = loader->pp3; 876 outline->points[n_points + 3] = loader->pp4; 877 878 outline->tags[n_points ] = 0; 879 outline->tags[n_points + 1] = 0; 880 outline->tags[n_points + 2] = 0; 881 outline->tags[n_points + 3] = 0; 882 883 n_points += 4; 884 885 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 886 887 if ( ((TT_Face)loader->face)->doblend ) 888 { 889 /* Deltas apply to the unscaled data. */ 890 FT_Vector* deltas; 891 FT_Memory memory = loader->face->memory; 892 FT_Int i; 893 894 895 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), 896 loader->glyph_index, 897 &deltas, 898 n_points ); 899 if ( error ) 900 return error; 901 902 for ( i = 0; i < n_points; ++i ) 903 { 904 outline->points[i].x += deltas[i].x; 905 outline->points[i].y += deltas[i].y; 906 } 907 908 FT_FREE( deltas ); 909 } 910 911 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 912 913 if ( IS_HINTED( loader->load_flags ) ) 914 { 915 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); 916 917 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, 918 loader->zone.n_points + 4 ); 919 } 920 921 { 922 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 923 TT_Face face = (TT_Face)loader->face; 924 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 925 926 FT_String* family = face->root.family_name; 927 FT_Int ppem = loader->size->metrics.x_ppem; 928 FT_String* style = face->root.style_name; 929 FT_Int x_scale_factor = 1000; 930 #endif 931 932 FT_Vector* vec = outline->points; 933 FT_Vector* limit = outline->points + n_points; 934 935 FT_Fixed x_scale = 0; /* pacify compiler */ 936 FT_Fixed y_scale = 0; 937 938 FT_Bool do_scale = FALSE; 939 940 941 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 942 943 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 944 { 945 /* scale, but only if enabled and only if TT hinting is being used */ 946 if ( IS_HINTED( loader->load_flags ) ) 947 x_scale_factor = sph_test_tweak_x_scaling( face, 948 family, 949 ppem, 950 style, 951 loader->glyph_index ); 952 /* scale the glyph */ 953 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || 954 x_scale_factor != 1000 ) 955 { 956 x_scale = FT_MulDiv( ((TT_Size)loader->size)->metrics.x_scale, 957 x_scale_factor, 1000 ); 958 y_scale = ((TT_Size)loader->size)->metrics.y_scale; 959 960 /* compensate for any scaling by de/emboldening; */ 961 /* the amount was determined via experimentation */ 962 if ( x_scale_factor != 1000 && ppem > 11 ) 963 FT_Outline_EmboldenXY( outline, 964 FT_MulFix( 1280 * ppem, 965 1000 - x_scale_factor ), 966 0 ); 967 do_scale = TRUE; 968 } 969 } 970 else 971 972 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 973 974 { 975 /* scale the glyph */ 976 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 977 { 978 x_scale = ((TT_Size)loader->size)->metrics.x_scale; 979 y_scale = ((TT_Size)loader->size)->metrics.y_scale; 980 981 do_scale = TRUE; 982 } 983 } 984 985 if ( do_scale ) 986 { 987 for ( ; vec < limit; vec++ ) 988 { 989 vec->x = FT_MulFix( vec->x, x_scale ); 990 vec->y = FT_MulFix( vec->y, y_scale ); 991 } 992 993 loader->pp1 = outline->points[n_points - 4]; 994 loader->pp2 = outline->points[n_points - 3]; 995 loader->pp3 = outline->points[n_points - 2]; 996 loader->pp4 = outline->points[n_points - 1]; 997 } 998 } 999 1000 if ( IS_HINTED( loader->load_flags ) ) 1001 { 1002 loader->zone.n_points += 4; 1003 1004 error = TT_Hint_Glyph( loader, 0 ); 1005 } 1006 1007 return error; 1008 } 1009 1010 1011 /*************************************************************************/ 1012 /* */ 1013 /* <Function> */ 1014 /* TT_Process_Composite_Component */ 1015 /* */ 1016 /* <Description> */ 1017 /* Once a composite component has been loaded, it needs to be */ 1018 /* processed. Usually, this means transforming and translating. */ 1019 /* */ 1020 static FT_Error 1021 TT_Process_Composite_Component( TT_Loader loader, 1022 FT_SubGlyph subglyph, 1023 FT_UInt start_point, 1024 FT_UInt num_base_points ) 1025 { 1026 FT_GlyphLoader gloader = loader->gloader; 1027 FT_Vector* base_vec = gloader->base.outline.points; 1028 FT_UInt num_points = gloader->base.outline.n_points; 1029 FT_Bool have_scale; 1030 FT_Pos x, y; 1031 1032 1033 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | 1034 WE_HAVE_AN_XY_SCALE | 1035 WE_HAVE_A_2X2 ) ); 1036 1037 /* perform the transform required for this subglyph */ 1038 if ( have_scale ) 1039 { 1040 FT_UInt i; 1041 1042 1043 for ( i = num_base_points; i < num_points; i++ ) 1044 FT_Vector_Transform( base_vec + i, &subglyph->transform ); 1045 } 1046 1047 /* get offset */ 1048 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) 1049 { 1050 FT_UInt k = subglyph->arg1; 1051 FT_UInt l = subglyph->arg2; 1052 FT_Vector* p1; 1053 FT_Vector* p2; 1054 1055 1056 /* match l-th point of the newly loaded component to the k-th point */ 1057 /* of the previously loaded components. */ 1058 1059 /* change to the point numbers used by our outline */ 1060 k += start_point; 1061 l += num_base_points; 1062 if ( k >= num_base_points || 1063 l >= num_points ) 1064 return FT_THROW( Invalid_Composite ); 1065 1066 p1 = gloader->base.outline.points + k; 1067 p2 = gloader->base.outline.points + l; 1068 1069 x = p1->x - p2->x; 1070 y = p1->y - p2->y; 1071 } 1072 else 1073 { 1074 x = subglyph->arg1; 1075 y = subglyph->arg2; 1076 1077 if ( !x && !y ) 1078 return FT_Err_Ok; 1079 1080 /* Use a default value dependent on */ 1081 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ 1082 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ 1083 1084 if ( have_scale && 1085 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED 1086 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) 1087 #else 1088 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) 1089 #endif 1090 { 1091 1092 #if 0 1093 1094 /*************************************************************************/ 1095 /* */ 1096 /* This algorithm is what Apple documents. But it doesn't work. */ 1097 /* */ 1098 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx 1099 : -subglyph->transform.xx; 1100 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx 1101 : -subglyph->transform.yx; 1102 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy 1103 : -subglyph->transform.xy; 1104 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy 1105 : -subglyph->transform.yy; 1106 int m = a > b ? a : b; 1107 int n = c > d ? c : d; 1108 1109 1110 if ( a - b <= 33 && a - b >= -33 ) 1111 m *= 2; 1112 if ( c - d <= 33 && c - d >= -33 ) 1113 n *= 2; 1114 x = FT_MulFix( x, m ); 1115 y = FT_MulFix( y, n ); 1116 1117 #else /* 0 */ 1118 1119 /*************************************************************************/ 1120 /* */ 1121 /* This algorithm is a guess and works much better than the above. */ 1122 /* */ 1123 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx, 1124 subglyph->transform.xy ); 1125 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy, 1126 subglyph->transform.yx ); 1127 1128 1129 x = FT_MulFix( x, mac_xscale ); 1130 y = FT_MulFix( y, mac_yscale ); 1131 1132 #endif /* 0 */ 1133 1134 } 1135 1136 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1137 { 1138 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; 1139 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; 1140 1141 1142 x = FT_MulFix( x, x_scale ); 1143 y = FT_MulFix( y, y_scale ); 1144 1145 if ( subglyph->flags & ROUND_XY_TO_GRID ) 1146 { 1147 x = FT_PIX_ROUND( x ); 1148 y = FT_PIX_ROUND( y ); 1149 } 1150 } 1151 } 1152 1153 if ( x || y ) 1154 translate_array( num_points - num_base_points, 1155 base_vec + num_base_points, 1156 x, y ); 1157 1158 return FT_Err_Ok; 1159 } 1160 1161 1162 /*************************************************************************/ 1163 /* */ 1164 /* <Function> */ 1165 /* TT_Process_Composite_Glyph */ 1166 /* */ 1167 /* <Description> */ 1168 /* This is slightly different from TT_Process_Simple_Glyph, in that */ 1169 /* its sole purpose is to hint the glyph. Thus this function is */ 1170 /* only available when bytecode interpreter is enabled. */ 1171 /* */ 1172 static FT_Error 1173 TT_Process_Composite_Glyph( TT_Loader loader, 1174 FT_UInt start_point, 1175 FT_UInt start_contour ) 1176 { 1177 FT_Error error; 1178 FT_Outline* outline; 1179 FT_UInt i; 1180 1181 1182 outline = &loader->gloader->base.outline; 1183 1184 /* make room for phantom points */ 1185 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, 1186 outline->n_points + 4, 1187 0 ); 1188 if ( error ) 1189 return error; 1190 1191 outline->points[outline->n_points ] = loader->pp1; 1192 outline->points[outline->n_points + 1] = loader->pp2; 1193 outline->points[outline->n_points + 2] = loader->pp3; 1194 outline->points[outline->n_points + 3] = loader->pp4; 1195 1196 outline->tags[outline->n_points ] = 0; 1197 outline->tags[outline->n_points + 1] = 0; 1198 outline->tags[outline->n_points + 2] = 0; 1199 outline->tags[outline->n_points + 3] = 0; 1200 1201 #ifdef TT_USE_BYTECODE_INTERPRETER 1202 1203 { 1204 FT_Stream stream = loader->stream; 1205 FT_UShort n_ins, max_ins; 1206 FT_ULong tmp; 1207 1208 1209 /* TT_Load_Composite_Glyph only gives us the offset of instructions */ 1210 /* so we read them here */ 1211 if ( FT_STREAM_SEEK( loader->ins_pos ) || 1212 FT_READ_USHORT( n_ins ) ) 1213 return error; 1214 1215 FT_TRACE5(( " Instructions size = %d\n", n_ins )); 1216 1217 /* check it */ 1218 max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions; 1219 if ( n_ins > max_ins ) 1220 { 1221 /* acroread ignores this field, so we only do a rough safety check */ 1222 if ( (FT_Int)n_ins > loader->byte_len ) 1223 { 1224 FT_TRACE1(( "TT_Process_Composite_Glyph: " 1225 "too many instructions (%d) for glyph with length %d\n", 1226 n_ins, loader->byte_len )); 1227 return FT_THROW( Too_Many_Hints ); 1228 } 1229 1230 tmp = loader->exec->glyphSize; 1231 error = Update_Max( loader->exec->memory, 1232 &tmp, 1233 sizeof ( FT_Byte ), 1234 (void*)&loader->exec->glyphIns, 1235 n_ins ); 1236 loader->exec->glyphSize = (FT_UShort)tmp; 1237 if ( error ) 1238 return error; 1239 } 1240 else if ( n_ins == 0 ) 1241 return FT_Err_Ok; 1242 1243 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) 1244 return error; 1245 1246 loader->glyph->control_data = loader->exec->glyphIns; 1247 loader->glyph->control_len = n_ins; 1248 } 1249 1250 #endif 1251 1252 tt_prepare_zone( &loader->zone, &loader->gloader->base, 1253 start_point, start_contour ); 1254 1255 /* Some points are likely touched during execution of */ 1256 /* instructions on components. So let's untouch them. */ 1257 for ( i = start_point; i < loader->zone.n_points; i++ ) 1258 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; 1259 1260 loader->zone.n_points += 4; 1261 1262 return TT_Hint_Glyph( loader, 1 ); 1263 } 1264 1265 1266 /* Calculate the four phantom points. */ 1267 /* The first two stand for horizontal origin and advance. */ 1268 /* The last two stand for vertical origin and advance. */ 1269 #define TT_LOADER_SET_PP( loader ) \ 1270 do { \ 1271 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \ 1272 (loader)->pp1.y = 0; \ 1273 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \ 1274 (loader)->pp2.y = 0; \ 1275 (loader)->pp3.x = 0; \ 1276 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \ 1277 (loader)->pp4.x = 0; \ 1278 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ 1279 } while ( 0 ) 1280 1281 1282 /*************************************************************************/ 1283 /* */ 1284 /* <Function> */ 1285 /* load_truetype_glyph */ 1286 /* */ 1287 /* <Description> */ 1288 /* Loads a given truetype glyph. Handles composites and uses a */ 1289 /* TT_Loader object. */ 1290 /* */ 1291 static FT_Error 1292 load_truetype_glyph( TT_Loader loader, 1293 FT_UInt glyph_index, 1294 FT_UInt recurse_count, 1295 FT_Bool header_only ) 1296 { 1297 FT_Error error = FT_Err_Ok; 1298 FT_Fixed x_scale, y_scale; 1299 FT_ULong offset; 1300 TT_Face face = (TT_Face)loader->face; 1301 FT_GlyphLoader gloader = loader->gloader; 1302 FT_Bool opened_frame = 0; 1303 1304 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1305 FT_Vector* deltas = NULL; 1306 #endif 1307 1308 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1309 FT_StreamRec inc_stream; 1310 FT_Data glyph_data; 1311 FT_Bool glyph_data_loaded = 0; 1312 #endif 1313 1314 1315 /* some fonts have an incorrect value of `maxComponentDepth', */ 1316 /* thus we allow depth 1 to catch the majority of them */ 1317 if ( recurse_count > 1 && 1318 recurse_count > face->max_profile.maxComponentDepth ) 1319 { 1320 error = FT_THROW( Invalid_Composite ); 1321 goto Exit; 1322 } 1323 1324 /* check glyph index */ 1325 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 1326 { 1327 error = FT_THROW( Invalid_Glyph_Index ); 1328 goto Exit; 1329 } 1330 1331 loader->glyph_index = glyph_index; 1332 1333 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1334 { 1335 x_scale = ((TT_Size)loader->size)->metrics.x_scale; 1336 y_scale = ((TT_Size)loader->size)->metrics.y_scale; 1337 } 1338 else 1339 { 1340 x_scale = 0x10000L; 1341 y_scale = 0x10000L; 1342 } 1343 1344 tt_get_metrics( loader, glyph_index ); 1345 1346 /* Set `offset' to the start of the glyph relative to the start of */ 1347 /* the `glyf' table, and `byte_len' to the length of the glyph in */ 1348 /* bytes. */ 1349 1350 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1351 1352 /* If we are loading glyph data via the incremental interface, set */ 1353 /* the loader stream to a memory stream reading the data returned */ 1354 /* by the interface. */ 1355 if ( face->root.internal->incremental_interface ) 1356 { 1357 error = face->root.internal->incremental_interface->funcs->get_glyph_data( 1358 face->root.internal->incremental_interface->object, 1359 glyph_index, &glyph_data ); 1360 if ( error ) 1361 goto Exit; 1362 1363 glyph_data_loaded = 1; 1364 offset = 0; 1365 loader->byte_len = glyph_data.length; 1366 1367 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); 1368 FT_Stream_OpenMemory( &inc_stream, 1369 glyph_data.pointer, glyph_data.length ); 1370 1371 loader->stream = &inc_stream; 1372 } 1373 else 1374 1375 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1376 1377 offset = tt_face_get_location( face, glyph_index, 1378 (FT_UInt*)&loader->byte_len ); 1379 1380 if ( loader->byte_len > 0 ) 1381 { 1382 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1383 /* for the incremental interface, `glyf_offset' is always zero */ 1384 if ( !loader->glyf_offset && 1385 !face->root.internal->incremental_interface ) 1386 #else 1387 if ( !loader->glyf_offset ) 1388 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1389 { 1390 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); 1391 error = FT_THROW( Invalid_Table ); 1392 goto Exit; 1393 } 1394 1395 error = face->access_glyph_frame( loader, glyph_index, 1396 loader->glyf_offset + offset, 1397 loader->byte_len ); 1398 if ( error ) 1399 goto Exit; 1400 1401 opened_frame = 1; 1402 1403 /* read glyph header first */ 1404 error = face->read_glyph_header( loader ); 1405 if ( error || header_only ) 1406 goto Exit; 1407 } 1408 1409 if ( loader->byte_len == 0 || loader->n_contours == 0 ) 1410 { 1411 loader->bbox.xMin = 0; 1412 loader->bbox.xMax = 0; 1413 loader->bbox.yMin = 0; 1414 loader->bbox.yMax = 0; 1415 1416 if ( header_only ) 1417 goto Exit; 1418 1419 /* must initialize points before (possibly) overriding */ 1420 /* glyph metrics from the incremental interface */ 1421 TT_LOADER_SET_PP( loader ); 1422 1423 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1424 tt_get_metrics_incr_overrides( loader, glyph_index ); 1425 #endif 1426 1427 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1428 1429 if ( ((TT_Face)(loader->face))->doblend ) 1430 { 1431 /* this must be done before scaling */ 1432 FT_Memory memory = loader->face->memory; 1433 1434 1435 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), 1436 glyph_index, &deltas, 4 ); 1437 if ( error ) 1438 goto Exit; 1439 1440 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y; 1441 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y; 1442 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y; 1443 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y; 1444 1445 FT_FREE( deltas ); 1446 } 1447 1448 #endif 1449 1450 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1451 { 1452 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1453 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1454 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1455 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1456 } 1457 1458 error = FT_Err_Ok; 1459 goto Exit; 1460 } 1461 1462 /* must initialize points before (possibly) overriding */ 1463 /* glyph metrics from the incremental interface */ 1464 TT_LOADER_SET_PP( loader ); 1465 1466 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1467 tt_get_metrics_incr_overrides( loader, glyph_index ); 1468 #endif 1469 1470 /***********************************************************************/ 1471 /***********************************************************************/ 1472 /***********************************************************************/ 1473 1474 /* if it is a simple glyph, load it */ 1475 1476 if ( loader->n_contours > 0 ) 1477 { 1478 error = face->read_simple_glyph( loader ); 1479 if ( error ) 1480 goto Exit; 1481 1482 /* all data have been read */ 1483 face->forget_glyph_frame( loader ); 1484 opened_frame = 0; 1485 1486 error = TT_Process_Simple_Glyph( loader ); 1487 if ( error ) 1488 goto Exit; 1489 1490 FT_GlyphLoader_Add( gloader ); 1491 } 1492 1493 /***********************************************************************/ 1494 /***********************************************************************/ 1495 /***********************************************************************/ 1496 1497 /* otherwise, load a composite! */ 1498 else if ( loader->n_contours == -1 ) 1499 { 1500 FT_UInt start_point; 1501 FT_UInt start_contour; 1502 FT_ULong ins_pos; /* position of composite instructions, if any */ 1503 1504 1505 start_point = gloader->base.outline.n_points; 1506 start_contour = gloader->base.outline.n_contours; 1507 1508 /* for each subglyph, read composite header */ 1509 error = face->read_composite_glyph( loader ); 1510 if ( error ) 1511 goto Exit; 1512 1513 /* store the offset of instructions */ 1514 ins_pos = loader->ins_pos; 1515 1516 /* all data we need are read */ 1517 face->forget_glyph_frame( loader ); 1518 opened_frame = 0; 1519 1520 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1521 1522 if ( face->doblend ) 1523 { 1524 FT_Int i, limit; 1525 FT_SubGlyph subglyph; 1526 FT_Memory memory = face->root.memory; 1527 1528 1529 /* this provides additional offsets */ 1530 /* for each component's translation */ 1531 1532 if ( ( error = TT_Vary_Get_Glyph_Deltas( 1533 face, 1534 glyph_index, 1535 &deltas, 1536 gloader->current.num_subglyphs + 4 )) != 0 ) 1537 goto Exit; 1538 1539 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; 1540 limit = gloader->current.num_subglyphs; 1541 1542 for ( i = 0; i < limit; ++i, ++subglyph ) 1543 { 1544 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 1545 { 1546 /* XXX: overflow check for subglyph->{arg1,arg2}. */ 1547 /* deltas[i].{x,y} must be within signed 16-bit, */ 1548 /* but the restriction of summed delta is not clear */ 1549 subglyph->arg1 += (FT_Int16)deltas[i].x; 1550 subglyph->arg2 += (FT_Int16)deltas[i].y; 1551 } 1552 } 1553 1554 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y; 1555 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y; 1556 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y; 1557 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y; 1558 1559 FT_FREE( deltas ); 1560 } 1561 1562 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1563 1564 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1565 { 1566 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1567 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1568 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1569 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1570 } 1571 1572 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 1573 /* `as is' in the glyph slot (the client application will be */ 1574 /* responsible for interpreting these data)... */ 1575 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 1576 { 1577 FT_GlyphLoader_Add( gloader ); 1578 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 1579 1580 goto Exit; 1581 } 1582 1583 /*********************************************************************/ 1584 /*********************************************************************/ 1585 /*********************************************************************/ 1586 1587 { 1588 FT_UInt n, num_base_points; 1589 FT_SubGlyph subglyph = 0; 1590 1591 FT_UInt num_points = start_point; 1592 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 1593 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 1594 1595 FT_Stream old_stream = loader->stream; 1596 FT_Int old_byte_len = loader->byte_len; 1597 1598 1599 FT_GlyphLoader_Add( gloader ); 1600 1601 /* read each subglyph independently */ 1602 for ( n = 0; n < num_subglyphs; n++ ) 1603 { 1604 FT_Vector pp[4]; 1605 1606 1607 /* Each time we call load_truetype_glyph in this loop, the */ 1608 /* value of `gloader.base.subglyphs' can change due to table */ 1609 /* reallocations. We thus need to recompute the subglyph */ 1610 /* pointer on each iteration. */ 1611 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1612 1613 pp[0] = loader->pp1; 1614 pp[1] = loader->pp2; 1615 pp[2] = loader->pp3; 1616 pp[3] = loader->pp4; 1617 1618 num_base_points = gloader->base.outline.n_points; 1619 1620 error = load_truetype_glyph( loader, subglyph->index, 1621 recurse_count + 1, FALSE ); 1622 if ( error ) 1623 goto Exit; 1624 1625 /* restore subglyph pointer */ 1626 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1627 1628 if ( !( subglyph->flags & USE_MY_METRICS ) ) 1629 { 1630 loader->pp1 = pp[0]; 1631 loader->pp2 = pp[1]; 1632 loader->pp3 = pp[2]; 1633 loader->pp4 = pp[3]; 1634 } 1635 1636 num_points = gloader->base.outline.n_points; 1637 1638 if ( num_points == num_base_points ) 1639 continue; 1640 1641 /* gloader->base.outline consists of three parts: */ 1642 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ 1643 /* */ 1644 /* (1): exists from the beginning */ 1645 /* (2): components that have been loaded so far */ 1646 /* (3): the newly loaded component */ 1647 TT_Process_Composite_Component( loader, subglyph, start_point, 1648 num_base_points ); 1649 } 1650 1651 loader->stream = old_stream; 1652 loader->byte_len = old_byte_len; 1653 1654 /* process the glyph */ 1655 loader->ins_pos = ins_pos; 1656 if ( IS_HINTED( loader->load_flags ) && 1657 1658 #ifdef TT_USE_BYTECODE_INTERPRETER 1659 1660 subglyph->flags & WE_HAVE_INSTR && 1661 1662 #endif 1663 1664 num_points > start_point ) 1665 TT_Process_Composite_Glyph( loader, start_point, start_contour ); 1666 1667 } 1668 } 1669 else 1670 { 1671 /* invalid composite count (negative but not -1) */ 1672 error = FT_THROW( Invalid_Outline ); 1673 goto Exit; 1674 } 1675 1676 /***********************************************************************/ 1677 /***********************************************************************/ 1678 /***********************************************************************/ 1679 1680 Exit: 1681 1682 if ( opened_frame ) 1683 face->forget_glyph_frame( loader ); 1684 1685 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1686 1687 if ( glyph_data_loaded ) 1688 face->root.internal->incremental_interface->funcs->free_glyph_data( 1689 face->root.internal->incremental_interface->object, 1690 &glyph_data ); 1691 1692 #endif 1693 1694 return error; 1695 } 1696 1697 1698 static FT_Error 1699 compute_glyph_metrics( TT_Loader loader, 1700 FT_UInt glyph_index ) 1701 { 1702 TT_Face face = (TT_Face)loader->face; 1703 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1704 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 1705 #endif 1706 1707 FT_BBox bbox; 1708 FT_Fixed y_scale; 1709 TT_GlyphSlot glyph = loader->glyph; 1710 TT_Size size = (TT_Size)loader->size; 1711 1712 1713 y_scale = 0x10000L; 1714 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1715 y_scale = size->root.metrics.y_scale; 1716 1717 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) 1718 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 1719 else 1720 bbox = loader->bbox; 1721 1722 /* get the device-independent horizontal advance; it is scaled later */ 1723 /* by the base layer. */ 1724 glyph->linearHoriAdvance = loader->linear; 1725 1726 glyph->metrics.horiBearingX = bbox.xMin; 1727 glyph->metrics.horiBearingY = bbox.yMax; 1728 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 1729 1730 /* adjust advance width to the value contained in the hdmx table */ 1731 if ( !face->postscript.isFixedPitch && 1732 IS_HINTED( loader->load_flags ) ) 1733 { 1734 FT_Byte* widthp; 1735 1736 1737 widthp = tt_face_get_device_metrics( face, 1738 size->root.metrics.x_ppem, 1739 glyph_index ); 1740 1741 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1742 1743 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 1744 { 1745 FT_Bool ignore_x_mode; 1746 1747 1748 ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != 1749 FT_RENDER_MODE_MONO ); 1750 1751 if ( widthp && 1752 ( ( ignore_x_mode && loader->exec->compatible_widths ) || 1753 !ignore_x_mode || 1754 SPH_OPTION_BITMAP_WIDTHS ) ) 1755 glyph->metrics.horiAdvance = *widthp << 6; 1756 } 1757 else 1758 1759 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1760 1761 { 1762 if ( widthp ) 1763 glyph->metrics.horiAdvance = *widthp << 6; 1764 } 1765 } 1766 1767 /* set glyph dimensions */ 1768 glyph->metrics.width = bbox.xMax - bbox.xMin; 1769 glyph->metrics.height = bbox.yMax - bbox.yMin; 1770 1771 /* Now take care of vertical metrics. In the case where there is */ 1772 /* no vertical information within the font (relatively common), */ 1773 /* create some metrics manually */ 1774 { 1775 FT_Pos top; /* scaled vertical top side bearing */ 1776 FT_Pos advance; /* scaled vertical advance height */ 1777 1778 1779 /* Get the unscaled top bearing and advance height. */ 1780 if ( face->vertical_info && 1781 face->vertical.number_Of_VMetrics > 0 ) 1782 { 1783 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax, 1784 y_scale ); 1785 1786 if ( loader->pp3.y <= loader->pp4.y ) 1787 advance = 0; 1788 else 1789 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y, 1790 y_scale ); 1791 } 1792 else 1793 { 1794 FT_Pos height; 1795 1796 1797 /* XXX Compute top side bearing and advance height in */ 1798 /* Get_VMetrics instead of here. */ 1799 1800 /* NOTE: The OS/2 values are the only `portable' ones, */ 1801 /* which is why we use them, if there is an OS/2 */ 1802 /* table in the font. Otherwise, we use the */ 1803 /* values defined in the horizontal header. */ 1804 1805 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, 1806 y_scale ); 1807 if ( face->os2.version != 0xFFFFU ) 1808 advance = (FT_Pos)( face->os2.sTypoAscender - 1809 face->os2.sTypoDescender ); 1810 else 1811 advance = (FT_Pos)( face->horizontal.Ascender - 1812 face->horizontal.Descender ); 1813 1814 top = ( advance - height ) / 2; 1815 } 1816 1817 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1818 { 1819 FT_Incremental_InterfaceRec* incr; 1820 FT_Incremental_MetricsRec metrics; 1821 FT_Error error; 1822 1823 1824 incr = face->root.internal->incremental_interface; 1825 1826 /* If this is an incrementally loaded font see if there are */ 1827 /* overriding metrics for this glyph. */ 1828 if ( incr && incr->funcs->get_glyph_metrics ) 1829 { 1830 metrics.bearing_x = 0; 1831 metrics.bearing_y = top; 1832 metrics.advance = advance; 1833 1834 error = incr->funcs->get_glyph_metrics( incr->object, 1835 glyph_index, 1836 TRUE, 1837 &metrics ); 1838 if ( error ) 1839 return error; 1840 1841 top = metrics.bearing_y; 1842 advance = metrics.advance; 1843 } 1844 } 1845 1846 /* GWW: Do vertical metrics get loaded incrementally too? */ 1847 1848 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1849 1850 glyph->linearVertAdvance = advance; 1851 1852 /* scale the metrics */ 1853 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1854 { 1855 top = FT_MulFix( top, y_scale ); 1856 advance = FT_MulFix( advance, y_scale ); 1857 } 1858 1859 /* XXX: for now, we have no better algorithm for the lsb, but it */ 1860 /* should work fine. */ 1861 /* */ 1862 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX - 1863 glyph->metrics.horiAdvance / 2; 1864 glyph->metrics.vertBearingY = top; 1865 glyph->metrics.vertAdvance = advance; 1866 } 1867 1868 return 0; 1869 } 1870 1871 1872 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1873 1874 static FT_Error 1875 load_sbit_image( TT_Size size, 1876 TT_GlyphSlot glyph, 1877 FT_UInt glyph_index, 1878 FT_Int32 load_flags ) 1879 { 1880 TT_Face face; 1881 SFNT_Service sfnt; 1882 FT_Stream stream; 1883 FT_Error error; 1884 TT_SBit_MetricsRec metrics; 1885 1886 1887 face = (TT_Face)glyph->face; 1888 sfnt = (SFNT_Service)face->sfnt; 1889 stream = face->root.stream; 1890 1891 error = sfnt->load_sbit_image( face, 1892 size->strike_index, 1893 glyph_index, 1894 (FT_Int)load_flags, 1895 stream, 1896 &glyph->bitmap, 1897 &metrics ); 1898 if ( !error ) 1899 { 1900 glyph->outline.n_points = 0; 1901 glyph->outline.n_contours = 0; 1902 1903 glyph->metrics.width = (FT_Pos)metrics.width << 6; 1904 glyph->metrics.height = (FT_Pos)metrics.height << 6; 1905 1906 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 1907 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 1908 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 1909 1910 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 1911 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 1912 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 1913 1914 glyph->format = FT_GLYPH_FORMAT_BITMAP; 1915 1916 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 1917 { 1918 glyph->bitmap_left = metrics.vertBearingX; 1919 glyph->bitmap_top = metrics.vertBearingY; 1920 } 1921 else 1922 { 1923 glyph->bitmap_left = metrics.horiBearingX; 1924 glyph->bitmap_top = metrics.horiBearingY; 1925 } 1926 } 1927 1928 return error; 1929 } 1930 1931 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1932 1933 1934 static FT_Error 1935 tt_loader_init( TT_Loader loader, 1936 TT_Size size, 1937 TT_GlyphSlot glyph, 1938 FT_Int32 load_flags, 1939 FT_Bool glyf_table_only ) 1940 { 1941 TT_Face face; 1942 FT_Stream stream; 1943 #ifdef TT_USE_BYTECODE_INTERPRETER 1944 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 1945 #endif 1946 1947 1948 face = (TT_Face)glyph->face; 1949 stream = face->root.stream; 1950 1951 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) ); 1952 1953 #ifdef TT_USE_BYTECODE_INTERPRETER 1954 1955 /* load execution context */ 1956 if ( IS_HINTED( load_flags ) && !glyf_table_only ) 1957 { 1958 TT_ExecContext exec; 1959 FT_Bool grayscale; 1960 1961 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1962 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 1963 1964 FT_Bool subpixel_hinting = FALSE; 1965 FT_Bool grayscale_hinting = TRUE; 1966 1967 #if 0 1968 /* not used yet */ 1969 FT_Bool compatible_widths; 1970 FT_Bool symmetrical_smoothing; 1971 FT_Bool bgr; 1972 FT_Bool subpixel_positioned; 1973 #endif 1974 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1975 1976 FT_Bool reexecute = FALSE; 1977 1978 1979 if ( !size->cvt_ready ) 1980 { 1981 FT_Error error = tt_size_ready_bytecode( size, pedantic ); 1982 1983 1984 if ( error ) 1985 return error; 1986 } 1987 1988 /* query new execution context */ 1989 exec = size->debug ? size->context 1990 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 1991 if ( !exec ) 1992 return FT_THROW( Could_Not_Find_Context ); 1993 1994 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1995 1996 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 1997 { 1998 subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) 1999 != FT_RENDER_MODE_MONO ) && 2000 SPH_OPTION_SET_SUBPIXEL ); 2001 2002 if ( subpixel_hinting ) 2003 grayscale = grayscale_hinting = FALSE; 2004 else if ( SPH_OPTION_SET_GRAYSCALE ) 2005 { 2006 grayscale = grayscale_hinting = TRUE; 2007 subpixel_hinting = FALSE; 2008 } 2009 else 2010 grayscale = grayscale_hinting = FALSE; 2011 2012 if ( FT_IS_TRICKY( glyph->face ) ) 2013 subpixel_hinting = grayscale_hinting = FALSE; 2014 2015 exec->ignore_x_mode = subpixel_hinting || grayscale_hinting; 2016 exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; 2017 if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) 2018 exec->rasterizer_version = TT_INTERPRETER_VERSION_35; 2019 2020 #if 1 2021 exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; 2022 exec->symmetrical_smoothing = FALSE; 2023 exec->bgr = FALSE; 2024 exec->subpixel_positioned = TRUE; 2025 #else /* 0 */ 2026 exec->compatible_widths = 2027 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2028 TT_LOAD_COMPATIBLE_WIDTHS ); 2029 exec->symmetrical_smoothing = 2030 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2031 TT_LOAD_SYMMETRICAL_SMOOTHING ); 2032 exec->bgr = 2033 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2034 TT_LOAD_BGR ); 2035 exec->subpixel_positioned = 2036 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2037 TT_LOAD_SUBPIXEL_POSITIONED ); 2038 #endif /* 0 */ 2039 2040 } 2041 else 2042 2043 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 2044 2045 { 2046 grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2047 FT_RENDER_MODE_MONO ); 2048 } 2049 2050 TT_Load_Context( exec, face, size ); 2051 2052 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 2053 2054 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 2055 { 2056 /* a change from mono to subpixel rendering (and vice versa) */ 2057 /* requires a re-execution of the CVT program */ 2058 if ( subpixel_hinting != exec->subpixel_hinting ) 2059 { 2060 FT_TRACE4(( "tt_loader_init: subpixel hinting change," 2061 " re-executing `prep' table\n" )); 2062 2063 exec->subpixel_hinting = subpixel_hinting; 2064 reexecute = TRUE; 2065 } 2066 2067 /* a change from mono to grayscale rendering (and vice versa) */ 2068 /* requires a re-execution of the CVT program */ 2069 if ( grayscale != exec->grayscale_hinting ) 2070 { 2071 FT_TRACE4(( "tt_loader_init: grayscale hinting change," 2072 " re-executing `prep' table\n" )); 2073 2074 exec->grayscale_hinting = grayscale_hinting; 2075 reexecute = TRUE; 2076 } 2077 } 2078 else 2079 2080 #endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 2081 2082 { 2083 /* a change from mono to grayscale rendering (and vice versa) */ 2084 /* requires a re-execution of the CVT program */ 2085 if ( grayscale != exec->grayscale ) 2086 { 2087 FT_TRACE4(( "tt_loader_init: grayscale change," 2088 " re-executing `prep' table\n" )); 2089 2090 exec->grayscale = grayscale; 2091 reexecute = TRUE; 2092 } 2093 } 2094 2095 if ( reexecute ) 2096 { 2097 FT_UInt i; 2098 2099 2100 for ( i = 0; i < size->cvt_size; i++ ) 2101 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 2102 tt_size_run_prep( size, pedantic ); 2103 } 2104 2105 /* see whether the cvt program has disabled hinting */ 2106 if ( exec->GS.instruct_control & 1 ) 2107 load_flags |= FT_LOAD_NO_HINTING; 2108 2109 /* load default graphics state -- if needed */ 2110 if ( exec->GS.instruct_control & 2 ) 2111 exec->GS = tt_default_graphics_state; 2112 2113 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2114 loader->exec = exec; 2115 loader->instructions = exec->glyphIns; 2116 } 2117 2118 #endif /* TT_USE_BYTECODE_INTERPRETER */ 2119 2120 /* seek to the beginning of the glyph table -- for Type 42 fonts */ 2121 /* the table might be accessed from a Postscript stream or something */ 2122 /* else... */ 2123 2124 #ifdef FT_CONFIG_OPTION_INCREMENTAL 2125 2126 if ( face->root.internal->incremental_interface ) 2127 loader->glyf_offset = 0; 2128 else 2129 2130 #endif 2131 2132 { 2133 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 ); 2134 2135 2136 if ( FT_ERR_EQ( error, Table_Missing ) ) 2137 loader->glyf_offset = 0; 2138 else if ( error ) 2139 { 2140 FT_ERROR(( "tt_loader_init: could not access glyph table\n" )); 2141 return error; 2142 } 2143 else 2144 loader->glyf_offset = FT_STREAM_POS(); 2145 } 2146 2147 /* get face's glyph loader */ 2148 if ( !glyf_table_only ) 2149 { 2150 FT_GlyphLoader gloader = glyph->internal->loader; 2151 2152 2153 FT_GlyphLoader_Rewind( gloader ); 2154 loader->gloader = gloader; 2155 } 2156 2157 loader->load_flags = load_flags; 2158 2159 loader->face = (FT_Face)face; 2160 loader->size = (FT_Size)size; 2161 loader->glyph = (FT_GlyphSlot)glyph; 2162 loader->stream = stream; 2163 2164 return FT_Err_Ok; 2165 } 2166 2167 2168 /*************************************************************************/ 2169 /* */ 2170 /* <Function> */ 2171 /* TT_Load_Glyph */ 2172 /* */ 2173 /* <Description> */ 2174 /* A function used to load a single glyph within a given glyph slot, */ 2175 /* for a given size. */ 2176 /* */ 2177 /* <Input> */ 2178 /* glyph :: A handle to a target slot object where the glyph */ 2179 /* will be loaded. */ 2180 /* */ 2181 /* size :: A handle to the source face size at which the glyph */ 2182 /* must be scaled/loaded. */ 2183 /* */ 2184 /* glyph_index :: The index of the glyph in the font file. */ 2185 /* */ 2186 /* load_flags :: A flag indicating what to load for this glyph. The */ 2187 /* FT_LOAD_XXX constants can be used to control the */ 2188 /* glyph loading process (e.g., whether the outline */ 2189 /* should be scaled, whether to load bitmaps or not, */ 2190 /* whether to hint the outline, etc). */ 2191 /* */ 2192 /* <Return> */ 2193 /* FreeType error code. 0 means success. */ 2194 /* */ 2195 FT_LOCAL_DEF( FT_Error ) 2196 TT_Load_Glyph( TT_Size size, 2197 TT_GlyphSlot glyph, 2198 FT_UInt glyph_index, 2199 FT_Int32 load_flags ) 2200 { 2201 FT_Error error; 2202 TT_LoaderRec loader; 2203 2204 2205 error = FT_Err_Ok; 2206 2207 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2208 2209 /* try to load embedded bitmap if any */ 2210 /* */ 2211 /* XXX: The convention should be emphasized in */ 2212 /* the documents because it can be confusing. */ 2213 if ( size->strike_index != 0xFFFFFFFFUL && 2214 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 2215 { 2216 error = load_sbit_image( size, glyph, glyph_index, load_flags ); 2217 if ( !error ) 2218 { 2219 if ( FT_IS_SCALABLE( glyph->face ) ) 2220 { 2221 /* for the bbox we need the header only */ 2222 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); 2223 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); 2224 glyph->linearHoriAdvance = loader.linear; 2225 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax - 2226 loader.vadvance; 2227 2228 /* sanity check: if `horiAdvance' in the sbit metric */ 2229 /* structure isn't set, use `linearHoriAdvance' */ 2230 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) 2231 glyph->metrics.horiAdvance = 2232 FT_MulFix( glyph->linearHoriAdvance, 2233 size->root.metrics.x_scale ); 2234 } 2235 2236 return FT_Err_Ok; 2237 } 2238 } 2239 2240 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2241 2242 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ 2243 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) 2244 return FT_THROW( Invalid_Size_Handle ); 2245 2246 if ( load_flags & FT_LOAD_SBITS_ONLY ) 2247 return FT_THROW( Invalid_Argument ); 2248 2249 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); 2250 if ( error ) 2251 return error; 2252 2253 glyph->format = FT_GLYPH_FORMAT_OUTLINE; 2254 glyph->num_subglyphs = 0; 2255 glyph->outline.flags = 0; 2256 2257 /* main loading loop */ 2258 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); 2259 if ( !error ) 2260 { 2261 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) 2262 { 2263 glyph->num_subglyphs = loader.gloader->base.num_subglyphs; 2264 glyph->subglyphs = loader.gloader->base.subglyphs; 2265 } 2266 else 2267 { 2268 glyph->outline = loader.gloader->base.outline; 2269 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; 2270 2271 /* Translate array so that (0,0) is the glyph's origin. Note */ 2272 /* that this behaviour is independent on the value of bit 1 of */ 2273 /* the `flags' field in the `head' table -- at least major */ 2274 /* applications like Acroread indicate that. */ 2275 if ( loader.pp1.x ) 2276 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); 2277 } 2278 2279 #ifdef TT_USE_BYTECODE_INTERPRETER 2280 2281 if ( IS_HINTED( load_flags ) ) 2282 { 2283 if ( loader.exec->GS.scan_control ) 2284 { 2285 /* convert scan conversion mode to FT_OUTLINE_XXX flags */ 2286 switch ( loader.exec->GS.scan_type ) 2287 { 2288 case 0: /* simple drop-outs including stubs */ 2289 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; 2290 break; 2291 case 1: /* simple drop-outs excluding stubs */ 2292 /* nothing; it's the default rendering mode */ 2293 break; 2294 case 4: /* smart drop-outs including stubs */ 2295 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | 2296 FT_OUTLINE_INCLUDE_STUBS; 2297 break; 2298 case 5: /* smart drop-outs excluding stubs */ 2299 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; 2300 break; 2301 2302 default: /* no drop-out control */ 2303 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2304 break; 2305 } 2306 } 2307 else 2308 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2309 } 2310 2311 #endif /* TT_USE_BYTECODE_INTERPRETER */ 2312 2313 compute_glyph_metrics( &loader, glyph_index ); 2314 } 2315 2316 /* Set the `high precision' bit flag. */ 2317 /* This is _critical_ to get correct output for monochrome */ 2318 /* TrueType glyphs at all sizes using the bytecode interpreter. */ 2319 /* */ 2320 if ( !( load_flags & FT_LOAD_NO_SCALE ) && 2321 size->root.metrics.y_ppem < 24 ) 2322 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 2323 2324 return error; 2325 } 2326 2327 2328 /* END */