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