1 /**************************************************************************** 2 * 3 * ttgload.c 4 * 5 * TrueType Glyph Loader (body). 6 * 7 * Copyright (C) 1996-2023 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 <freetype/internal/ftdebug.h> 21 #include FT_CONFIG_CONFIG_H 22 #include <freetype/internal/ftcalc.h> 23 #include <freetype/internal/ftstream.h> 24 #include <freetype/internal/sfnt.h> 25 #include <freetype/tttags.h> 26 #include <freetype/ftoutln.h> 27 #include <freetype/ftdriver.h> 28 #include <freetype/ftlist.h> 29 30 #include "ttgload.h" 31 #include "ttpload.h" 32 33 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 34 #include "ttgxvar.h" 35 #endif 36 37 #include "tterrors.h" 38 39 40 /************************************************************************** 41 * 42 * The macro FT_COMPONENT is used in trace mode. It is an implicit 43 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 44 * messages during execution. 45 */ 46 #undef FT_COMPONENT 47 #define FT_COMPONENT ttgload 48 49 50 /************************************************************************** 51 * 52 * Simple glyph flags. 53 */ 54 #define ON_CURVE_POINT 0x01 /* same value as FT_CURVE_TAG_ON */ 55 #define X_SHORT_VECTOR 0x02 56 #define Y_SHORT_VECTOR 0x04 57 #define REPEAT_FLAG 0x08 58 #define X_POSITIVE 0x10 /* two meanings depending on X_SHORT_VECTOR */ 59 #define SAME_X 0x10 60 #define Y_POSITIVE 0x20 /* two meanings depending on Y_SHORT_VECTOR */ 61 #define SAME_Y 0x20 62 #define OVERLAP_SIMPLE 0x40 /* retained as FT_OUTLINE_OVERLAP */ 63 64 65 /************************************************************************** 66 * 67 * Composite glyph flags. 68 */ 69 #define ARGS_ARE_WORDS 0x0001 70 #define ARGS_ARE_XY_VALUES 0x0002 71 #define ROUND_XY_TO_GRID 0x0004 72 #define WE_HAVE_A_SCALE 0x0008 73 /* reserved 0x0010 */ 74 #define MORE_COMPONENTS 0x0020 75 #define WE_HAVE_AN_XY_SCALE 0x0040 76 #define WE_HAVE_A_2X2 0x0080 77 #define WE_HAVE_INSTR 0x0100 78 #define USE_MY_METRICS 0x0200 79 #define OVERLAP_COMPOUND 0x0400 /* retained as FT_OUTLINE_OVERLAP */ 80 #define SCALED_COMPONENT_OFFSET 0x0800 81 #define UNSCALED_COMPONENT_OFFSET 0x1000 82 83 84 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 85 #define IS_DEFAULT_INSTANCE( _face ) \ 86 ( !( FT_IS_NAMED_INSTANCE( _face ) || \ 87 FT_IS_VARIATION( _face ) ) ) 88 #else 89 #define IS_DEFAULT_INSTANCE( _face ) 1 90 #endif 91 92 93 /************************************************************************** 94 * 95 * Return the horizontal metrics in font units for a given glyph. 96 */ 97 FT_LOCAL_DEF( void ) TT_Get_HMetrics(TT_Face face,FT_UInt idx,FT_Short * lsb,FT_UShort * aw)98 TT_Get_HMetrics( TT_Face face, 99 FT_UInt idx, 100 FT_Short* lsb, 101 FT_UShort* aw ) 102 { 103 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); 104 105 FT_TRACE5(( " advance width (font units): %d\n", *aw )); 106 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb )); 107 } 108 109 110 /************************************************************************** 111 * 112 * Return the vertical metrics in font units for a given glyph. 113 * See function `tt_loader_set_pp' below for explanations. 114 */ 115 FT_LOCAL_DEF( void ) TT_Get_VMetrics(TT_Face face,FT_UInt idx,FT_Pos yMax,FT_Short * tsb,FT_UShort * ah)116 TT_Get_VMetrics( TT_Face face, 117 FT_UInt idx, 118 FT_Pos yMax, 119 FT_Short* tsb, 120 FT_UShort* ah ) 121 { 122 if ( face->vertical_info ) 123 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); 124 125 else if ( face->os2.version != 0xFFFFU ) 126 { 127 *tsb = (FT_Short)( face->os2.sTypoAscender - yMax ); 128 *ah = (FT_UShort)FT_ABS( face->os2.sTypoAscender - 129 face->os2.sTypoDescender ); 130 } 131 132 else 133 { 134 *tsb = (FT_Short)( face->horizontal.Ascender - yMax ); 135 *ah = (FT_UShort)FT_ABS( face->horizontal.Ascender - 136 face->horizontal.Descender ); 137 } 138 139 #ifdef FT_DEBUG_LEVEL_TRACE 140 if ( !face->vertical_info ) 141 FT_TRACE5(( " [vertical metrics missing, computing values]\n" )); 142 #endif 143 144 FT_TRACE5(( " advance height (font units): %d\n", *ah )); 145 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb )); 146 } 147 148 149 static FT_Error tt_get_metrics(TT_Loader loader,FT_UInt glyph_index)150 tt_get_metrics( TT_Loader loader, 151 FT_UInt glyph_index ) 152 { 153 TT_Face face = loader->face; 154 155 FT_Error error; 156 FT_Stream stream = loader->stream; 157 158 FT_Short left_bearing = 0, top_bearing = 0; 159 FT_UShort advance_width = 0, advance_height = 0; 160 161 /* we must preserve the stream position */ 162 /* (which gets altered by the metrics functions) */ 163 FT_ULong pos = FT_STREAM_POS(); 164 165 166 TT_Get_HMetrics( face, glyph_index, 167 &left_bearing, 168 &advance_width ); 169 TT_Get_VMetrics( face, glyph_index, 170 loader->bbox.yMax, 171 &top_bearing, 172 &advance_height ); 173 174 if ( FT_STREAM_SEEK( pos ) ) 175 return error; 176 177 loader->left_bearing = left_bearing; 178 loader->advance = advance_width; 179 loader->top_bearing = top_bearing; 180 loader->vadvance = advance_height; 181 182 #ifdef FT_CONFIG_OPTION_INCREMENTAL 183 /* With the incremental interface, these values are set by */ 184 /* a call to `tt_get_metrics_incremental'. */ 185 if ( face->root.internal->incremental_interface == NULL ) 186 #endif 187 { 188 if ( !loader->linear_def ) 189 { 190 loader->linear_def = 1; 191 loader->linear = advance_width; 192 } 193 } 194 195 return FT_Err_Ok; 196 } 197 198 199 #ifdef FT_CONFIG_OPTION_INCREMENTAL 200 201 static void tt_get_metrics_incremental(TT_Loader loader,FT_UInt glyph_index)202 tt_get_metrics_incremental( TT_Loader loader, 203 FT_UInt glyph_index ) 204 { 205 TT_Face face = loader->face; 206 207 FT_Short left_bearing = 0, top_bearing = 0; 208 FT_UShort advance_width = 0, advance_height = 0; 209 210 211 /* If this is an incrementally loaded font check whether there are */ 212 /* overriding metrics for this glyph. */ 213 if ( face->root.internal->incremental_interface && 214 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 215 { 216 FT_Incremental_MetricsRec incr_metrics; 217 FT_Error error; 218 219 220 incr_metrics.bearing_x = loader->left_bearing; 221 incr_metrics.bearing_y = 0; 222 incr_metrics.advance = loader->advance; 223 incr_metrics.advance_v = 0; 224 225 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 226 face->root.internal->incremental_interface->object, 227 glyph_index, FALSE, &incr_metrics ); 228 if ( error ) 229 goto Exit; 230 231 left_bearing = (FT_Short)incr_metrics.bearing_x; 232 advance_width = (FT_UShort)incr_metrics.advance; 233 234 #if 0 235 236 /* GWW: Do I do the same for vertical metrics? */ 237 incr_metrics.bearing_x = 0; 238 incr_metrics.bearing_y = loader->top_bearing; 239 incr_metrics.advance = loader->vadvance; 240 241 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 242 face->root.internal->incremental_interface->object, 243 glyph_index, TRUE, &incr_metrics ); 244 if ( error ) 245 goto Exit; 246 247 top_bearing = (FT_Short)incr_metrics.bearing_y; 248 advance_height = (FT_UShort)incr_metrics.advance; 249 250 #endif /* 0 */ 251 252 loader->left_bearing = left_bearing; 253 loader->advance = advance_width; 254 loader->top_bearing = top_bearing; 255 loader->vadvance = advance_height; 256 257 if ( !loader->linear_def ) 258 { 259 loader->linear_def = 1; 260 loader->linear = advance_width; 261 } 262 } 263 264 Exit: 265 return; 266 } 267 268 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 269 270 271 /************************************************************************** 272 * 273 * The following functions are used by default with TrueType fonts. 274 * However, they can be replaced by alternatives if we need to support 275 * TrueType-compressed formats (like MicroType) in the future. 276 * 277 */ 278 279 FT_CALLBACK_DEF( FT_Error ) TT_Access_Glyph_Frame(TT_Loader loader,FT_UInt glyph_index,FT_ULong offset,FT_UInt byte_count)280 TT_Access_Glyph_Frame( TT_Loader loader, 281 FT_UInt glyph_index, 282 FT_ULong offset, 283 FT_UInt byte_count ) 284 { 285 FT_Error error; 286 FT_Stream stream = loader->stream; 287 288 FT_UNUSED( glyph_index ); 289 290 291 /* the following line sets the `error' variable through macros! */ 292 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) 293 return error; 294 295 loader->cursor = stream->cursor; 296 loader->limit = stream->limit; 297 298 return FT_Err_Ok; 299 } 300 301 302 FT_CALLBACK_DEF( void ) TT_Forget_Glyph_Frame(TT_Loader loader)303 TT_Forget_Glyph_Frame( TT_Loader loader ) 304 { 305 FT_Stream stream = loader->stream; 306 307 308 FT_FRAME_EXIT(); 309 } 310 311 312 FT_CALLBACK_DEF( FT_Error ) TT_Load_Glyph_Header(TT_Loader loader)313 TT_Load_Glyph_Header( TT_Loader loader ) 314 { 315 FT_Byte* p = loader->cursor; 316 FT_Byte* limit = loader->limit; 317 318 319 if ( p + 10 > limit ) 320 return FT_THROW( Invalid_Outline ); 321 322 loader->n_contours = FT_NEXT_SHORT( p ); 323 324 loader->bbox.xMin = FT_NEXT_SHORT( p ); 325 loader->bbox.yMin = FT_NEXT_SHORT( p ); 326 loader->bbox.xMax = FT_NEXT_SHORT( p ); 327 loader->bbox.yMax = FT_NEXT_SHORT( p ); 328 329 FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); 330 FT_TRACE5(( " xMin: %4ld xMax: %4ld\n", loader->bbox.xMin, 331 loader->bbox.xMax )); 332 FT_TRACE5(( " yMin: %4ld yMax: %4ld\n", loader->bbox.yMin, 333 loader->bbox.yMax )); 334 loader->cursor = p; 335 336 return FT_Err_Ok; 337 } 338 339 340 FT_CALLBACK_DEF( FT_Error ) TT_Load_Simple_Glyph(TT_Loader load)341 TT_Load_Simple_Glyph( TT_Loader load ) 342 { 343 FT_Error error; 344 FT_Byte* p = load->cursor; 345 FT_Byte* limit = load->limit; 346 FT_GlyphLoader gloader = load->gloader; 347 FT_Outline* outline = &gloader->current.outline; 348 FT_Int n_contours = load->n_contours; 349 FT_Int n_points; 350 FT_UShort n_ins; 351 352 FT_Byte *flag, *flag_limit; 353 FT_Byte c, count; 354 FT_Vector *vec, *vec_limit; 355 FT_Pos x, y; 356 FT_Short *cont, *cont_limit, last; 357 358 359 /* check that we can add the contours to the glyph */ 360 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); 361 if ( error ) 362 goto Fail; 363 364 /* check space for contours array + instructions count */ 365 if ( n_contours >= 0xFFF || p + 2 * n_contours + 2 > limit ) 366 goto Invalid_Outline; 367 368 /* reading the contours' endpoints & number of points */ 369 cont = outline->contours; 370 cont_limit = cont + n_contours; 371 372 last = -1; 373 for ( ; cont < cont_limit; cont++ ) 374 { 375 *cont = FT_NEXT_SHORT( p ); 376 377 if ( *cont <= last ) 378 goto Invalid_Outline; 379 380 last = *cont; 381 } 382 383 n_points = last + 1; 384 385 FT_TRACE5(( " # of points: %d\n", n_points )); 386 387 /* note that we will add four phantom points later */ 388 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); 389 if ( error ) 390 goto Fail; 391 392 /* space checked above */ 393 n_ins = FT_NEXT_USHORT( p ); 394 395 FT_TRACE5(( " Instructions size: %u\n", n_ins )); 396 397 /* check instructions size */ 398 if ( p + n_ins > limit ) 399 { 400 FT_TRACE1(( "TT_Load_Simple_Glyph: excessive instruction count\n" )); 401 error = FT_THROW( Too_Many_Hints ); 402 goto Fail; 403 } 404 405 #ifdef TT_USE_BYTECODE_INTERPRETER 406 407 if ( IS_HINTED( load->load_flags ) ) 408 { 409 TT_ExecContext exec = load->exec; 410 FT_Memory memory = exec->memory; 411 412 413 if ( exec->glyphSize ) 414 FT_FREE( exec->glyphIns ); 415 exec->glyphSize = 0; 416 417 /* we don't trust `maxSizeOfInstructions' in the `maxp' table */ 418 /* and thus allocate the bytecode array size by ourselves */ 419 if ( n_ins ) 420 { 421 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) ) 422 return error; 423 424 FT_MEM_COPY( exec->glyphIns, p, (FT_Long)n_ins ); 425 426 exec->glyphSize = n_ins; 427 } 428 } 429 430 #endif /* TT_USE_BYTECODE_INTERPRETER */ 431 432 p += n_ins; 433 434 /* reading the point tags */ 435 flag = (FT_Byte*)outline->tags; 436 flag_limit = flag + n_points; 437 438 FT_ASSERT( flag ); 439 440 while ( flag < flag_limit ) 441 { 442 if ( p + 1 > limit ) 443 goto Invalid_Outline; 444 445 *flag++ = c = FT_NEXT_BYTE( p ); 446 if ( c & REPEAT_FLAG ) 447 { 448 if ( p + 1 > limit ) 449 goto Invalid_Outline; 450 451 count = FT_NEXT_BYTE( p ); 452 if ( flag + (FT_Int)count > flag_limit ) 453 goto Invalid_Outline; 454 455 for ( ; count > 0; count-- ) 456 *flag++ = c; 457 } 458 } 459 460 /* retain the overlap flag */ 461 if ( n_points && outline->tags[0] & OVERLAP_SIMPLE ) 462 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP; 463 464 /* reading the X coordinates */ 465 466 vec = outline->points; 467 vec_limit = vec + n_points; 468 flag = (FT_Byte*)outline->tags; 469 x = 0; 470 471 for ( ; vec < vec_limit; vec++, flag++ ) 472 { 473 FT_Pos delta = 0; 474 FT_Byte f = *flag; 475 476 477 if ( f & X_SHORT_VECTOR ) 478 { 479 if ( p + 1 > limit ) 480 goto Invalid_Outline; 481 482 delta = (FT_Pos)FT_NEXT_BYTE( p ); 483 if ( !( f & X_POSITIVE ) ) 484 delta = -delta; 485 } 486 else if ( !( f & SAME_X ) ) 487 { 488 if ( p + 2 > limit ) 489 goto Invalid_Outline; 490 491 delta = (FT_Pos)FT_NEXT_SHORT( p ); 492 } 493 494 x += delta; 495 vec->x = x; 496 } 497 498 /* reading the Y coordinates */ 499 500 vec = outline->points; 501 vec_limit = vec + n_points; 502 flag = (FT_Byte*)outline->tags; 503 y = 0; 504 505 for ( ; vec < vec_limit; vec++, flag++ ) 506 { 507 FT_Pos delta = 0; 508 FT_Byte f = *flag; 509 510 511 if ( f & Y_SHORT_VECTOR ) 512 { 513 if ( p + 1 > limit ) 514 goto Invalid_Outline; 515 516 delta = (FT_Pos)FT_NEXT_BYTE( p ); 517 if ( !( f & Y_POSITIVE ) ) 518 delta = -delta; 519 } 520 else if ( !( f & SAME_Y ) ) 521 { 522 if ( p + 2 > limit ) 523 goto Invalid_Outline; 524 525 delta = (FT_Pos)FT_NEXT_SHORT( p ); 526 } 527 528 y += delta; 529 vec->y = y; 530 531 /* the cast is for stupid compilers */ 532 *flag = (FT_Byte)( f & ON_CURVE_POINT ); 533 } 534 535 outline->n_points = (FT_Short)n_points; 536 outline->n_contours = (FT_Short)n_contours; 537 538 load->cursor = p; 539 540 Fail: 541 return error; 542 543 Invalid_Outline: 544 error = FT_THROW( Invalid_Outline ); 545 goto Fail; 546 } 547 548 549 FT_CALLBACK_DEF( FT_Error ) TT_Load_Composite_Glyph(TT_Loader loader)550 TT_Load_Composite_Glyph( TT_Loader loader ) 551 { 552 FT_Error error; 553 FT_Byte* p = loader->cursor; 554 FT_Byte* limit = loader->limit; 555 FT_GlyphLoader gloader = loader->gloader; 556 FT_Long num_glyphs = loader->face->root.num_glyphs; 557 FT_SubGlyph subglyph; 558 FT_UInt num_subglyphs; 559 560 561 num_subglyphs = 0; 562 563 do 564 { 565 FT_Fixed xx, xy, yy, yx; 566 FT_UInt count; 567 568 569 /* check that we can load a new subglyph */ 570 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); 571 if ( error ) 572 goto Fail; 573 574 /* check space */ 575 if ( p + 4 > limit ) 576 goto Invalid_Composite; 577 578 subglyph = gloader->current.subglyphs + num_subglyphs; 579 580 subglyph->arg1 = subglyph->arg2 = 0; 581 582 subglyph->flags = FT_NEXT_USHORT( p ); 583 subglyph->index = FT_NEXT_USHORT( p ); 584 585 /* we reject composites that have components */ 586 /* with invalid glyph indices */ 587 if ( subglyph->index >= num_glyphs ) 588 goto Invalid_Composite; 589 590 /* check space */ 591 count = 2; 592 if ( subglyph->flags & ARGS_ARE_WORDS ) 593 count += 2; 594 if ( subglyph->flags & WE_HAVE_A_SCALE ) 595 count += 2; 596 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 597 count += 4; 598 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 599 count += 8; 600 601 if ( p + count > limit ) 602 goto Invalid_Composite; 603 604 /* read arguments */ 605 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 606 { 607 if ( subglyph->flags & ARGS_ARE_WORDS ) 608 { 609 subglyph->arg1 = FT_NEXT_SHORT( p ); 610 subglyph->arg2 = FT_NEXT_SHORT( p ); 611 } 612 else 613 { 614 subglyph->arg1 = FT_NEXT_CHAR( p ); 615 subglyph->arg2 = FT_NEXT_CHAR( p ); 616 } 617 } 618 else 619 { 620 if ( subglyph->flags & ARGS_ARE_WORDS ) 621 { 622 subglyph->arg1 = (FT_Int)FT_NEXT_USHORT( p ); 623 subglyph->arg2 = (FT_Int)FT_NEXT_USHORT( p ); 624 } 625 else 626 { 627 subglyph->arg1 = (FT_Int)FT_NEXT_BYTE( p ); 628 subglyph->arg2 = (FT_Int)FT_NEXT_BYTE( p ); 629 } 630 } 631 632 /* read transform */ 633 xx = yy = 0x10000L; 634 xy = yx = 0; 635 636 if ( subglyph->flags & WE_HAVE_A_SCALE ) 637 { 638 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 639 yy = xx; 640 } 641 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 642 { 643 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 644 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 645 } 646 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 647 { 648 xx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 649 yx = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 650 xy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 651 yy = (FT_Fixed)FT_NEXT_SHORT( p ) * 4; 652 } 653 654 subglyph->transform.xx = xx; 655 subglyph->transform.xy = xy; 656 subglyph->transform.yx = yx; 657 subglyph->transform.yy = yy; 658 659 num_subglyphs++; 660 661 } while ( subglyph->flags & MORE_COMPONENTS ); 662 663 gloader->current.num_subglyphs = num_subglyphs; 664 FT_TRACE5(( " %d component%s\n", 665 num_subglyphs, 666 num_subglyphs > 1 ? "s" : "" )); 667 668 #ifdef FT_DEBUG_LEVEL_TRACE 669 { 670 FT_UInt i; 671 672 673 subglyph = gloader->current.subglyphs; 674 675 for ( i = 0; i < num_subglyphs; i++ ) 676 { 677 if ( num_subglyphs > 1 ) 678 FT_TRACE7(( " subglyph %d:\n", i )); 679 680 FT_TRACE7(( " glyph index: %d\n", subglyph->index )); 681 682 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 683 FT_TRACE7(( " offset: x=%d, y=%d\n", 684 subglyph->arg1, 685 subglyph->arg2 )); 686 else 687 FT_TRACE7(( " matching points: base=%d, component=%d\n", 688 subglyph->arg1, 689 subglyph->arg2 )); 690 691 if ( subglyph->flags & WE_HAVE_A_SCALE ) 692 FT_TRACE7(( " scaling: %f\n", 693 (double)subglyph->transform.xx / 65536 )); 694 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 695 FT_TRACE7(( " scaling: x=%f, y=%f\n", 696 (double)subglyph->transform.xx / 65536, 697 (double)subglyph->transform.yy / 65536 )); 698 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 699 { 700 FT_TRACE7(( " scaling: xx=%f, yx=%f\n", 701 (double)subglyph->transform.xx / 65536, 702 (double)subglyph->transform.yx / 65536 )); 703 FT_TRACE7(( " xy=%f, yy=%f\n", 704 (double)subglyph->transform.xy / 65536, 705 (double)subglyph->transform.yy / 65536 )); 706 } 707 708 subglyph++; 709 } 710 } 711 #endif /* FT_DEBUG_LEVEL_TRACE */ 712 713 #ifdef TT_USE_BYTECODE_INTERPRETER 714 715 { 716 FT_Stream stream = loader->stream; 717 718 719 /* we must undo the FT_FRAME_ENTER in order to point */ 720 /* to the composite instructions, if we find some. */ 721 /* We will process them later. */ 722 /* */ 723 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + 724 p - limit ); 725 } 726 727 #endif 728 729 loader->cursor = p; 730 731 Fail: 732 return error; 733 734 Invalid_Composite: 735 error = FT_THROW( Invalid_Composite ); 736 goto Fail; 737 } 738 739 740 FT_LOCAL_DEF( void ) TT_Init_Glyph_Loading(TT_Face face)741 TT_Init_Glyph_Loading( TT_Face face ) 742 { 743 face->access_glyph_frame = TT_Access_Glyph_Frame; 744 face->read_glyph_header = TT_Load_Glyph_Header; 745 face->read_simple_glyph = TT_Load_Simple_Glyph; 746 face->read_composite_glyph = TT_Load_Composite_Glyph; 747 face->forget_glyph_frame = TT_Forget_Glyph_Frame; 748 } 749 750 751 static void tt_prepare_zone(TT_GlyphZone zone,FT_GlyphLoad load,FT_UInt start_point,FT_UInt start_contour)752 tt_prepare_zone( TT_GlyphZone zone, 753 FT_GlyphLoad load, 754 FT_UInt start_point, 755 FT_UInt start_contour ) 756 { 757 zone->n_points = (FT_UShort)load->outline.n_points + 4 - 758 (FT_UShort)start_point; 759 zone->n_contours = load->outline.n_contours - 760 (FT_Short)start_contour; 761 zone->org = load->extra_points + start_point; 762 zone->cur = load->outline.points + start_point; 763 zone->orus = load->extra_points2 + start_point; 764 zone->tags = (FT_Byte*)load->outline.tags + start_point; 765 zone->contours = (FT_UShort*)load->outline.contours + start_contour; 766 zone->first_point = (FT_UShort)start_point; 767 } 768 769 770 /************************************************************************** 771 * 772 * @Function: 773 * TT_Hint_Glyph 774 * 775 * @Description: 776 * Hint the glyph using the zone prepared by the caller. Note that 777 * the zone is supposed to include four phantom points. 778 */ 779 static FT_Error TT_Hint_Glyph(TT_Loader loader,FT_Bool is_composite)780 TT_Hint_Glyph( TT_Loader loader, 781 FT_Bool is_composite ) 782 { 783 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 784 TT_Face face = loader->face; 785 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 786 #endif 787 788 TT_GlyphZone zone = &loader->zone; 789 790 #ifdef TT_USE_BYTECODE_INTERPRETER 791 TT_ExecContext exec = loader->exec; 792 FT_Long n_ins = exec->glyphSize; 793 #else 794 FT_UNUSED( is_composite ); 795 #endif 796 797 798 #ifdef TT_USE_BYTECODE_INTERPRETER 799 /* save original point positions in `org' array */ 800 if ( n_ins > 0 ) 801 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); 802 803 /* Reset graphics state. */ 804 exec->GS = loader->size->GS; 805 806 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ 807 /* completely refer to the (already) hinted subglyphs. */ 808 if ( is_composite ) 809 { 810 exec->metrics.x_scale = 1 << 16; 811 exec->metrics.y_scale = 1 << 16; 812 813 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); 814 } 815 else 816 { 817 exec->metrics.x_scale = loader->size->metrics->x_scale; 818 exec->metrics.y_scale = loader->size->metrics->y_scale; 819 } 820 #endif 821 822 /* round phantom points */ 823 zone->cur[zone->n_points - 4].x = 824 FT_PIX_ROUND( zone->cur[zone->n_points - 4].x ); 825 zone->cur[zone->n_points - 3].x = 826 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); 827 zone->cur[zone->n_points - 2].y = 828 FT_PIX_ROUND( zone->cur[zone->n_points - 2].y ); 829 zone->cur[zone->n_points - 1].y = 830 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); 831 832 #ifdef TT_USE_BYTECODE_INTERPRETER 833 834 if ( n_ins > 0 ) 835 { 836 FT_Error error; 837 838 839 TT_Set_CodeRange( exec, tt_coderange_glyph, exec->glyphIns, n_ins ); 840 841 exec->is_composite = is_composite; 842 exec->pts = *zone; 843 844 error = TT_Run_Context( exec ); 845 if ( error && exec->pedantic_hinting ) 846 return error; 847 848 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ 849 loader->gloader->current.outline.tags[0] |= 850 ( exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; 851 } 852 853 #endif 854 855 /* Save possibly modified glyph phantom points unless in v40 backward */ 856 /* compatibility mode, where no movement on the x axis means no reason */ 857 /* to change bearings or advance widths. */ 858 859 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 860 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && 861 exec->backward_compatibility ) 862 return FT_Err_Ok; 863 #endif 864 865 loader->pp1 = zone->cur[zone->n_points - 4]; 866 loader->pp2 = zone->cur[zone->n_points - 3]; 867 loader->pp3 = zone->cur[zone->n_points - 2]; 868 loader->pp4 = zone->cur[zone->n_points - 1]; 869 870 return FT_Err_Ok; 871 } 872 873 874 /************************************************************************** 875 * 876 * @Function: 877 * TT_Process_Simple_Glyph 878 * 879 * @Description: 880 * Once a simple glyph has been loaded, it needs to be processed. 881 * Usually, this means scaling and hinting through bytecode 882 * interpretation. 883 */ 884 static FT_Error TT_Process_Simple_Glyph(TT_Loader loader)885 TT_Process_Simple_Glyph( TT_Loader loader ) 886 { 887 FT_Error error = FT_Err_Ok; 888 FT_GlyphLoader gloader = loader->gloader; 889 FT_Outline* outline = &gloader->current.outline; 890 FT_Int n_points = outline->n_points; 891 892 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 893 FT_Memory memory = loader->face->root.memory; 894 FT_Vector* unrounded = NULL; 895 #endif 896 897 898 /* set phantom points */ 899 outline->points[n_points ] = loader->pp1; 900 outline->points[n_points + 1] = loader->pp2; 901 outline->points[n_points + 2] = loader->pp3; 902 outline->points[n_points + 3] = loader->pp4; 903 904 n_points += 4; 905 906 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 907 908 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) 909 { 910 if ( FT_QNEW_ARRAY( unrounded, n_points ) ) 911 goto Exit; 912 913 /* Deltas apply to the unscaled data. */ 914 error = TT_Vary_Apply_Glyph_Deltas( loader, 915 outline, 916 unrounded ); 917 if ( error ) 918 goto Exit; 919 } 920 921 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 922 923 if ( IS_HINTED( loader->load_flags ) ) 924 { 925 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); 926 927 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, 928 loader->zone.n_points ); 929 } 930 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 { 942 /* scale the glyph */ 943 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 944 { 945 x_scale = loader->size->metrics->x_scale; 946 y_scale = loader->size->metrics->y_scale; 947 948 do_scale = TRUE; 949 } 950 } 951 952 if ( do_scale ) 953 { 954 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 955 if ( !IS_DEFAULT_INSTANCE( FT_FACE( loader->face ) ) ) 956 { 957 FT_Vector* u = unrounded; 958 959 960 for ( ; vec < limit; vec++, u++ ) 961 { 962 vec->x = ADD_LONG( FT_MulFix( u->x, x_scale ), 32 ) >> 6; 963 vec->y = ADD_LONG( FT_MulFix( u->y, y_scale ), 32 ) >> 6; 964 } 965 } 966 else 967 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 968 { 969 for ( ; vec < limit; vec++ ) 970 { 971 vec->x = FT_MulFix( vec->x, x_scale ); 972 vec->y = FT_MulFix( vec->y, y_scale ); 973 } 974 } 975 } 976 977 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 978 /* if we have a HVAR table, `pp1' and/or `pp2' */ 979 /* are already adjusted but unscaled */ 980 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) && 981 IS_HINTED( loader->load_flags ) ) 982 { 983 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 984 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 985 /* pp1.y and pp2.y are always zero */ 986 } 987 else 988 #endif 989 { 990 loader->pp1 = outline->points[n_points - 4]; 991 loader->pp2 = outline->points[n_points - 3]; 992 } 993 994 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 995 /* if we have a VVAR table, `pp3' and/or `pp4' */ 996 /* are already adjusted but unscaled */ 997 if ( ( loader->face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) && 998 IS_HINTED( loader->load_flags ) ) 999 { 1000 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); 1001 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1002 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); 1003 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1004 } 1005 else 1006 #endif 1007 { 1008 loader->pp3 = outline->points[n_points - 2]; 1009 loader->pp4 = outline->points[n_points - 1]; 1010 } 1011 } 1012 1013 if ( IS_HINTED( loader->load_flags ) ) 1014 error = TT_Hint_Glyph( loader, 0 ); 1015 1016 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1017 Exit: 1018 FT_FREE( unrounded ); 1019 #endif 1020 1021 return error; 1022 } 1023 1024 1025 /************************************************************************** 1026 * 1027 * @Function: 1028 * TT_Process_Composite_Component 1029 * 1030 * @Description: 1031 * Once a composite component has been loaded, it needs to be 1032 * processed. Usually, this means transforming and translating. 1033 */ 1034 static FT_Error TT_Process_Composite_Component(TT_Loader loader,FT_SubGlyph subglyph,FT_UInt start_point,FT_UInt num_base_points)1035 TT_Process_Composite_Component( TT_Loader loader, 1036 FT_SubGlyph subglyph, 1037 FT_UInt start_point, 1038 FT_UInt num_base_points ) 1039 { 1040 FT_GlyphLoader gloader = loader->gloader; 1041 FT_Outline current; 1042 FT_Bool have_scale; 1043 FT_Pos x, y; 1044 1045 1046 current.points = gloader->base.outline.points + 1047 num_base_points; 1048 current.n_points = gloader->base.outline.n_points - 1049 (short)num_base_points; 1050 1051 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | 1052 WE_HAVE_AN_XY_SCALE | 1053 WE_HAVE_A_2X2 ) ); 1054 1055 /* perform the transform required for this subglyph */ 1056 if ( have_scale ) 1057 FT_Outline_Transform( ¤t, &subglyph->transform ); 1058 1059 /* get offset */ 1060 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) 1061 { 1062 FT_UInt num_points = (FT_UInt)gloader->base.outline.n_points; 1063 FT_UInt k = (FT_UInt)subglyph->arg1; 1064 FT_UInt l = (FT_UInt)subglyph->arg2; 1065 FT_Vector* p1; 1066 FT_Vector* p2; 1067 1068 1069 /* match l-th point of the newly loaded component to the k-th point */ 1070 /* of the previously loaded components. */ 1071 1072 /* change to the point numbers used by our outline */ 1073 k += start_point; 1074 l += num_base_points; 1075 if ( k >= num_base_points || 1076 l >= num_points ) 1077 return FT_THROW( Invalid_Composite ); 1078 1079 p1 = gloader->base.outline.points + k; 1080 p2 = gloader->base.outline.points + l; 1081 1082 x = SUB_LONG( p1->x, p2->x ); 1083 y = SUB_LONG( p1->y, p2->y ); 1084 } 1085 else 1086 { 1087 x = subglyph->arg1; 1088 y = subglyph->arg2; 1089 1090 if ( !x && !y ) 1091 return FT_Err_Ok; 1092 1093 /* Use a default value dependent on */ 1094 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old */ 1095 /* TT fonts which don't set the xxx_COMPONENT_OFFSET bit. */ 1096 1097 if ( have_scale && 1098 #ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED 1099 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) 1100 #else 1101 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) 1102 #endif 1103 { 1104 1105 #if 0 1106 1107 /******************************************************************** 1108 * 1109 * This algorithm is what Apple documents. But it doesn't work. 1110 */ 1111 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx 1112 : -subglyph->transform.xx; 1113 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx 1114 : -subglyph->transform.yx; 1115 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy 1116 : -subglyph->transform.xy; 1117 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy 1118 : -subglyph->transform.yy; 1119 int m = a > b ? a : b; 1120 int n = c > d ? c : d; 1121 1122 1123 if ( a - b <= 33 && a - b >= -33 ) 1124 m *= 2; 1125 if ( c - d <= 33 && c - d >= -33 ) 1126 n *= 2; 1127 x = FT_MulFix( x, m ); 1128 y = FT_MulFix( y, n ); 1129 1130 #else /* 1 */ 1131 1132 /******************************************************************** 1133 * 1134 * This algorithm is a guess and works much better than the above. 1135 */ 1136 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx, 1137 subglyph->transform.xy ); 1138 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy, 1139 subglyph->transform.yx ); 1140 1141 1142 x = FT_MulFix( x, mac_xscale ); 1143 y = FT_MulFix( y, mac_yscale ); 1144 1145 #endif /* 1 */ 1146 1147 } 1148 1149 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1150 { 1151 FT_Fixed x_scale = loader->size->metrics->x_scale; 1152 FT_Fixed y_scale = loader->size->metrics->y_scale; 1153 1154 1155 x = FT_MulFix( x, x_scale ); 1156 y = FT_MulFix( y, y_scale ); 1157 1158 if ( subglyph->flags & ROUND_XY_TO_GRID ) 1159 { 1160 TT_Face face = loader->face; 1161 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 1162 1163 1164 if ( IS_HINTED( loader->load_flags ) ) 1165 { 1166 /* 1167 * We round the horizontal offset only if there is hinting along 1168 * the x axis; this corresponds to integer advance width values. 1169 * 1170 * Theoretically, a glyph's bytecode can toggle ClearType's 1171 * `backward compatibility' mode, which would allow modification 1172 * of the advance width. In reality, however, applications 1173 * neither allow nor expect modified advance widths if subpixel 1174 * rendering is active. 1175 * 1176 */ 1177 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_35 ) 1178 x = FT_PIX_ROUND( x ); 1179 1180 y = FT_PIX_ROUND( y ); 1181 } 1182 } 1183 } 1184 } 1185 1186 if ( x || y ) 1187 FT_Outline_Translate( ¤t, x, y ); 1188 1189 return FT_Err_Ok; 1190 } 1191 1192 1193 /************************************************************************** 1194 * 1195 * @Function: 1196 * TT_Process_Composite_Glyph 1197 * 1198 * @Description: 1199 * This is slightly different from TT_Process_Simple_Glyph, in that 1200 * its sole purpose is to hint the glyph. Thus this function is 1201 * only available when bytecode interpreter is enabled. 1202 */ 1203 static FT_Error TT_Process_Composite_Glyph(TT_Loader loader,FT_UInt start_point,FT_UInt start_contour)1204 TT_Process_Composite_Glyph( TT_Loader loader, 1205 FT_UInt start_point, 1206 FT_UInt start_contour ) 1207 { 1208 FT_Error error; 1209 FT_Outline* outline = &loader->gloader->base.outline; 1210 FT_Stream stream = loader->stream; 1211 FT_UShort n_ins; 1212 FT_UInt i; 1213 1214 1215 /* make room for phantom points */ 1216 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, 1217 outline->n_points + 4, 1218 0 ); 1219 if ( error ) 1220 return error; 1221 1222 outline->points[outline->n_points ] = loader->pp1; 1223 outline->points[outline->n_points + 1] = loader->pp2; 1224 outline->points[outline->n_points + 2] = loader->pp3; 1225 outline->points[outline->n_points + 3] = loader->pp4; 1226 1227 #ifdef TT_USE_BYTECODE_INTERPRETER 1228 1229 { 1230 TT_ExecContext exec = loader->exec; 1231 FT_Memory memory = exec->memory; 1232 1233 1234 if ( exec->glyphSize ) 1235 FT_FREE( exec->glyphIns ); 1236 exec->glyphSize = 0; 1237 1238 /* TT_Load_Composite_Glyph only gives us the offset of instructions */ 1239 /* so we read them here */ 1240 if ( FT_STREAM_SEEK( loader->ins_pos ) || 1241 FT_READ_USHORT( n_ins ) ) 1242 return error; 1243 1244 FT_TRACE5(( " Instructions size = %hu\n", n_ins )); 1245 1246 if ( !n_ins ) 1247 return FT_Err_Ok; 1248 1249 /* don't trust `maxSizeOfInstructions'; */ 1250 /* only do a rough safety check */ 1251 if ( n_ins > loader->byte_len ) 1252 { 1253 FT_TRACE1(( "TT_Process_Composite_Glyph:" 1254 " too many instructions (%hu) for glyph with length %u\n", 1255 n_ins, loader->byte_len )); 1256 return FT_THROW( Too_Many_Hints ); 1257 } 1258 1259 if ( FT_QNEW_ARRAY( exec->glyphIns, n_ins ) || 1260 FT_STREAM_READ( exec->glyphIns, n_ins ) ) 1261 return error; 1262 1263 exec->glyphSize = n_ins; 1264 } 1265 1266 #endif 1267 1268 tt_prepare_zone( &loader->zone, &loader->gloader->base, 1269 start_point, start_contour ); 1270 1271 /* Some points are likely touched during execution of */ 1272 /* instructions on components. So let's untouch them. */ 1273 for ( i = 0; i < loader->zone.n_points - 4U; i++ ) 1274 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; 1275 1276 return TT_Hint_Glyph( loader, 1 ); 1277 } 1278 1279 1280 /* 1281 * Calculate the phantom points 1282 * 1283 * Defining the right side bearing (rsb) as 1284 * 1285 * rsb = aw - (lsb + xmax - xmin) 1286 * 1287 * (with `aw' the advance width, `lsb' the left side bearing, and `xmin' 1288 * and `xmax' the glyph's minimum and maximum x value), the OpenType 1289 * specification defines the initial position of horizontal phantom points 1290 * as 1291 * 1292 * pp1 = (round(xmin - lsb), 0) , 1293 * pp2 = (round(pp1 + aw), 0) . 1294 * 1295 * Note that the rounding to the grid (in the device space) is not 1296 * documented currently in the specification. 1297 * 1298 * However, the specification lacks the precise definition of vertical 1299 * phantom points. Greg Hitchcock provided the following explanation. 1300 * 1301 * - a `vmtx' table is present 1302 * 1303 * For any glyph, the minimum and maximum y values (`ymin' and `ymax') 1304 * are given in the `glyf' table, the top side bearing (tsb) and advance 1305 * height (ah) are given in the `vmtx' table. The bottom side bearing 1306 * (bsb) is then calculated as 1307 * 1308 * bsb = ah - (tsb + ymax - ymin) , 1309 * 1310 * and the initial position of vertical phantom points is 1311 * 1312 * pp3 = (x, round(ymax + tsb)) , 1313 * pp4 = (x, round(pp3 - ah)) . 1314 * 1315 * See below for value `x'. 1316 * 1317 * - no `vmtx' table in the font 1318 * 1319 * If there is an `OS/2' table, we set 1320 * 1321 * DefaultAscender = sTypoAscender , 1322 * DefaultDescender = sTypoDescender , 1323 * 1324 * otherwise we use data from the `hhea' table: 1325 * 1326 * DefaultAscender = Ascender , 1327 * DefaultDescender = Descender . 1328 * 1329 * With these two variables we can now set 1330 * 1331 * ah = DefaultAscender - sDefaultDescender , 1332 * tsb = DefaultAscender - yMax , 1333 * 1334 * and proceed as if a `vmtx' table was present. 1335 * 1336 * Usually we have 1337 * 1338 * x = aw / 2 , (1) 1339 * 1340 * but there is one compatibility case where it can be set to 1341 * 1342 * x = -DefaultDescender - 1343 * ((DefaultAscender - DefaultDescender - aw) / 2) . (2) 1344 * 1345 * and another one with 1346 * 1347 * x = 0 . (3) 1348 * 1349 * In Windows, the history of those values is quite complicated, 1350 * depending on the hinting engine (that is, the graphics framework). 1351 * 1352 * framework from to formula 1353 * ---------------------------------------------------------- 1354 * GDI Windows 98 current (1) 1355 * (Windows 2000 for NT) 1356 * GDI+ Windows XP Windows 7 (2) 1357 * GDI+ Windows 8 current (3) 1358 * DWrite Windows 7 current (3) 1359 * 1360 * For simplicity, FreeType uses (1) for grayscale subpixel hinting and 1361 * (3) for everything else. 1362 * 1363 */ 1364 static void tt_loader_set_pp(TT_Loader loader)1365 tt_loader_set_pp( TT_Loader loader ) 1366 { 1367 loader->pp1.x = loader->bbox.xMin - loader->left_bearing; 1368 loader->pp1.y = 0; 1369 loader->pp2.x = loader->pp1.x + loader->advance; 1370 loader->pp2.y = 0; 1371 1372 loader->pp3.x = 0; 1373 loader->pp3.y = loader->bbox.yMax + loader->top_bearing; 1374 loader->pp4.x = 0; 1375 loader->pp4.y = loader->pp3.y - loader->vadvance; 1376 1377 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 1378 { 1379 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( loader->face ); 1380 1381 1382 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && 1383 loader->exec && 1384 loader->exec->subpixel_hinting_lean && 1385 loader->exec->grayscale_cleartype ) 1386 { 1387 loader->pp3.x = loader->advance / 2; 1388 loader->pp4.x = loader->advance / 2; 1389 } 1390 } 1391 #endif 1392 } 1393 1394 1395 /* a utility function to retrieve i-th node from given FT_List */ 1396 static FT_ListNode ft_list_get_node_at(FT_List list,FT_UInt idx)1397 ft_list_get_node_at( FT_List list, 1398 FT_UInt idx ) 1399 { 1400 FT_ListNode cur; 1401 1402 1403 if ( !list ) 1404 return NULL; 1405 1406 for ( cur = list->head; cur; cur = cur->next ) 1407 { 1408 if ( !idx ) 1409 return cur; 1410 1411 idx--; 1412 } 1413 1414 return NULL; 1415 } 1416 1417 1418 /************************************************************************** 1419 * 1420 * @Function: 1421 * load_truetype_glyph 1422 * 1423 * @Description: 1424 * Loads a given truetype glyph. Handles composites and uses a 1425 * TT_Loader object. 1426 */ 1427 static FT_Error load_truetype_glyph(TT_Loader loader,FT_UInt glyph_index,FT_UInt recurse_count,FT_Bool header_only)1428 load_truetype_glyph( TT_Loader loader, 1429 FT_UInt glyph_index, 1430 FT_UInt recurse_count, 1431 FT_Bool header_only ) 1432 { 1433 FT_Error error = FT_Err_Ok; 1434 FT_Fixed x_scale, y_scale; 1435 FT_ULong offset; 1436 TT_Face face = loader->face; 1437 FT_GlyphLoader gloader = loader->gloader; 1438 1439 FT_Bool opened_frame = 0; 1440 1441 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1442 FT_StreamRec inc_stream; 1443 FT_Data glyph_data; 1444 FT_Bool glyph_data_loaded = 0; 1445 #endif 1446 1447 1448 #ifdef FT_DEBUG_LEVEL_TRACE 1449 if ( recurse_count ) 1450 FT_TRACE5(( " nesting level: %d\n", recurse_count )); 1451 #endif 1452 1453 /* some fonts have an incorrect value of `maxComponentDepth' */ 1454 if ( recurse_count > face->max_profile.maxComponentDepth ) 1455 { 1456 FT_TRACE1(( "load_truetype_glyph: maxComponentDepth set to %d\n", 1457 recurse_count )); 1458 face->max_profile.maxComponentDepth = (FT_UShort)recurse_count; 1459 } 1460 1461 #ifndef FT_CONFIG_OPTION_INCREMENTAL 1462 /* check glyph index */ 1463 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 1464 { 1465 error = FT_THROW( Invalid_Glyph_Index ); 1466 goto Exit; 1467 } 1468 #endif 1469 1470 loader->glyph_index = glyph_index; 1471 1472 if ( loader->load_flags & FT_LOAD_NO_SCALE ) 1473 { 1474 x_scale = 0x10000L; 1475 y_scale = 0x10000L; 1476 } 1477 else 1478 { 1479 x_scale = loader->size->metrics->x_scale; 1480 y_scale = loader->size->metrics->y_scale; 1481 } 1482 1483 /* Set `offset' to the start of the glyph relative to the start of */ 1484 /* the `glyf' table, and `byte_len' to the length of the glyph in */ 1485 /* bytes. */ 1486 1487 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1488 1489 /* If we are loading glyph data via the incremental interface, set */ 1490 /* the loader stream to a memory stream reading the data returned */ 1491 /* by the interface. */ 1492 if ( face->root.internal->incremental_interface ) 1493 { 1494 error = face->root.internal->incremental_interface->funcs->get_glyph_data( 1495 face->root.internal->incremental_interface->object, 1496 glyph_index, &glyph_data ); 1497 if ( error ) 1498 goto Exit; 1499 1500 glyph_data_loaded = 1; 1501 offset = 0; 1502 loader->byte_len = glyph_data.length; 1503 1504 FT_ZERO( &inc_stream ); 1505 FT_Stream_OpenMemory( &inc_stream, 1506 glyph_data.pointer, 1507 glyph_data.length ); 1508 1509 loader->stream = &inc_stream; 1510 } 1511 else 1512 1513 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1514 { 1515 FT_ULong len; 1516 1517 1518 offset = tt_face_get_location( FT_FACE( face ), glyph_index, &len ); 1519 1520 loader->byte_len = (FT_UInt)len; 1521 } 1522 1523 if ( loader->byte_len > 0 ) 1524 { 1525 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1526 /* for the incremental interface, `glyf_offset' is always zero */ 1527 if ( !face->glyf_offset && 1528 !face->root.internal->incremental_interface ) 1529 #else 1530 if ( !face->glyf_offset ) 1531 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1532 { 1533 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); 1534 error = FT_THROW( Invalid_Table ); 1535 goto Exit; 1536 } 1537 1538 error = face->access_glyph_frame( loader, glyph_index, 1539 face->glyf_offset + offset, 1540 loader->byte_len ); 1541 if ( error ) 1542 goto Exit; 1543 1544 /* read glyph header first */ 1545 error = face->read_glyph_header( loader ); 1546 1547 face->forget_glyph_frame( loader ); 1548 1549 if ( error ) 1550 goto Exit; 1551 } 1552 1553 /* a space glyph */ 1554 if ( loader->byte_len == 0 || loader->n_contours == 0 ) 1555 { 1556 loader->bbox.xMin = 0; 1557 loader->bbox.xMax = 0; 1558 loader->bbox.yMin = 0; 1559 loader->bbox.yMax = 0; 1560 } 1561 1562 /* the metrics must be computed after loading the glyph header */ 1563 /* since we need the glyph's `yMax' value in case the vertical */ 1564 /* metrics must be emulated */ 1565 error = tt_get_metrics( loader, glyph_index ); 1566 if ( error ) 1567 goto Exit; 1568 1569 if ( header_only ) 1570 goto Exit; 1571 1572 if ( loader->byte_len == 0 || loader->n_contours == 0 ) 1573 { 1574 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1575 tt_get_metrics_incremental( loader, glyph_index ); 1576 #endif 1577 tt_loader_set_pp( loader ); 1578 1579 1580 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1581 1582 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || 1583 FT_IS_VARIATION( FT_FACE( face ) ) ) 1584 { 1585 /* a small outline structure with four elements for */ 1586 /* communication with `TT_Vary_Apply_Glyph_Deltas' */ 1587 FT_Vector points[4]; 1588 FT_Outline outline; 1589 1590 /* unrounded values */ 1591 FT_Vector unrounded[4] = { {0, 0}, {0, 0}, {0, 0}, {0, 0} }; 1592 1593 1594 points[0] = loader->pp1; 1595 points[1] = loader->pp2; 1596 points[2] = loader->pp3; 1597 points[3] = loader->pp4; 1598 1599 outline.n_points = 0; 1600 outline.n_contours = 0; 1601 outline.points = points; 1602 outline.tags = NULL; 1603 outline.contours = NULL; 1604 1605 /* this must be done before scaling */ 1606 error = TT_Vary_Apply_Glyph_Deltas( loader, 1607 &outline, 1608 unrounded ); 1609 if ( error ) 1610 goto Exit; 1611 } 1612 1613 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1614 1615 /* scale phantom points, if necessary; */ 1616 /* they get rounded in `TT_Hint_Glyph' */ 1617 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1618 { 1619 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1620 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1621 /* pp1.y and pp2.y are always zero */ 1622 1623 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); 1624 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1625 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); 1626 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1627 } 1628 1629 error = FT_Err_Ok; 1630 goto Exit; 1631 } 1632 1633 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1634 tt_get_metrics_incremental( loader, glyph_index ); 1635 #endif 1636 tt_loader_set_pp( loader ); 1637 1638 1639 /***********************************************************************/ 1640 /***********************************************************************/ 1641 /***********************************************************************/ 1642 1643 /* we now open a frame again, right after the glyph header */ 1644 /* (which consists of 10 bytes) */ 1645 error = face->access_glyph_frame( loader, glyph_index, 1646 face->glyf_offset + offset + 10, 1647 loader->byte_len - 10 ); 1648 if ( error ) 1649 goto Exit; 1650 1651 opened_frame = 1; 1652 1653 /* if it is a simple glyph, load it */ 1654 1655 if ( loader->n_contours > 0 ) 1656 { 1657 error = face->read_simple_glyph( loader ); 1658 if ( error ) 1659 goto Exit; 1660 1661 /* all data have been read */ 1662 face->forget_glyph_frame( loader ); 1663 opened_frame = 0; 1664 1665 error = TT_Process_Simple_Glyph( loader ); 1666 if ( error ) 1667 goto Exit; 1668 1669 FT_GlyphLoader_Add( gloader ); 1670 } 1671 1672 /***********************************************************************/ 1673 /***********************************************************************/ 1674 /***********************************************************************/ 1675 1676 /* otherwise, load a composite! */ 1677 else if ( loader->n_contours < 0 ) 1678 { 1679 FT_Memory memory = face->root.memory; 1680 1681 FT_UInt start_point; 1682 FT_UInt start_contour; 1683 FT_ULong ins_pos; /* position of composite instructions, if any */ 1684 1685 FT_ListNode node, node2; 1686 1687 1688 /* normalize the `n_contours' value */ 1689 loader->n_contours = -1; 1690 1691 /* 1692 * We store the glyph index directly in the `node->data' pointer, 1693 * following the glib solution (cf. macro `GUINT_TO_POINTER') with a 1694 * double cast to make this portable. Note, however, that this needs 1695 * pointers with a width of at least 32 bits. 1696 */ 1697 1698 /* clear the nodes filled by sibling chains */ 1699 node = ft_list_get_node_at( &loader->composites, recurse_count ); 1700 for ( node2 = node; node2; node2 = node2->next ) 1701 node2->data = (void*)-1; 1702 1703 /* check whether we already have a composite glyph with this index */ 1704 if ( FT_List_Find( &loader->composites, 1705 FT_UINT_TO_POINTER( glyph_index ) ) ) 1706 { 1707 FT_TRACE1(( "TT_Load_Composite_Glyph:" 1708 " infinite recursion detected\n" )); 1709 error = FT_THROW( Invalid_Composite ); 1710 goto Exit; 1711 } 1712 1713 else if ( node ) 1714 node->data = FT_UINT_TO_POINTER( glyph_index ); 1715 1716 else 1717 { 1718 if ( FT_QNEW( node ) ) 1719 goto Exit; 1720 node->data = FT_UINT_TO_POINTER( glyph_index ); 1721 FT_List_Add( &loader->composites, node ); 1722 } 1723 1724 start_point = (FT_UInt)gloader->base.outline.n_points; 1725 start_contour = (FT_UInt)gloader->base.outline.n_contours; 1726 1727 /* for each subglyph, read composite header */ 1728 error = face->read_composite_glyph( loader ); 1729 if ( error ) 1730 goto Exit; 1731 1732 /* store the offset of instructions */ 1733 ins_pos = loader->ins_pos; 1734 1735 /* all data we need are read */ 1736 face->forget_glyph_frame( loader ); 1737 opened_frame = 0; 1738 1739 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1740 1741 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) || 1742 FT_IS_VARIATION( FT_FACE( face ) ) ) 1743 { 1744 short i, limit; 1745 FT_SubGlyph subglyph; 1746 1747 FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; 1748 FT_Vector* unrounded = NULL; 1749 1750 1751 limit = (short)gloader->current.num_subglyphs; 1752 1753 /* construct an outline structure for */ 1754 /* communication with `TT_Vary_Apply_Glyph_Deltas' */ 1755 if ( FT_QNEW_ARRAY( outline.points, limit + 4 ) || 1756 FT_QNEW_ARRAY( outline.tags, limit ) || 1757 FT_QNEW_ARRAY( outline.contours, limit ) || 1758 FT_QNEW_ARRAY( unrounded, limit + 4 ) ) 1759 goto Exit1; 1760 1761 outline.n_contours = outline.n_points = limit; 1762 1763 subglyph = gloader->current.subglyphs; 1764 1765 for ( i = 0; i < limit; i++, subglyph++ ) 1766 { 1767 /* applying deltas for anchor points doesn't make sense, */ 1768 /* but we don't have to specially check this since */ 1769 /* unused delta values are zero anyways */ 1770 outline.points[i].x = subglyph->arg1; 1771 outline.points[i].y = subglyph->arg2; 1772 outline.tags[i] = ON_CURVE_POINT; 1773 outline.contours[i] = i; 1774 } 1775 1776 outline.points[i++] = loader->pp1; 1777 outline.points[i++] = loader->pp2; 1778 outline.points[i++] = loader->pp3; 1779 outline.points[i ] = loader->pp4; 1780 1781 /* this call provides additional offsets */ 1782 /* for each component's translation */ 1783 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( loader, 1784 &outline, 1785 unrounded ) ) ) 1786 goto Exit1; 1787 1788 subglyph = gloader->current.subglyphs; 1789 1790 for ( i = 0; i < limit; i++, subglyph++ ) 1791 { 1792 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 1793 { 1794 subglyph->arg1 = (FT_Int16)outline.points[i].x; 1795 subglyph->arg2 = (FT_Int16)outline.points[i].y; 1796 } 1797 } 1798 1799 Exit1: 1800 FT_FREE( outline.points ); 1801 FT_FREE( outline.tags ); 1802 FT_FREE( outline.contours ); 1803 FT_FREE( unrounded ); 1804 1805 if ( error ) 1806 goto Exit; 1807 } 1808 1809 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1810 1811 /* scale phantom points, if necessary; */ 1812 /* they get rounded in `TT_Hint_Glyph' */ 1813 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1814 { 1815 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1816 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1817 /* pp1.y and pp2.y are always zero */ 1818 1819 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); 1820 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1821 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); 1822 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1823 } 1824 1825 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 1826 /* `as is' in the glyph slot (the client application will be */ 1827 /* responsible for interpreting these data)... */ 1828 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 1829 { 1830 FT_GlyphLoader_Add( gloader ); 1831 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 1832 1833 goto Exit; 1834 } 1835 1836 /*********************************************************************/ 1837 /*********************************************************************/ 1838 /*********************************************************************/ 1839 1840 { 1841 FT_UInt n, num_base_points; 1842 FT_SubGlyph subglyph = NULL; 1843 1844 FT_UInt num_points = start_point; 1845 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 1846 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 1847 1848 FT_Stream old_stream = loader->stream; 1849 FT_UInt old_byte_len = loader->byte_len; 1850 1851 1852 FT_GlyphLoader_Add( gloader ); 1853 1854 /* read each subglyph independently */ 1855 for ( n = 0; n < num_subglyphs; n++ ) 1856 { 1857 FT_Vector pp[4]; 1858 1859 FT_Int linear_hadvance; 1860 FT_Int linear_vadvance; 1861 1862 1863 /* Each time we call `load_truetype_glyph' in this loop, the */ 1864 /* value of `gloader.base.subglyphs' can change due to table */ 1865 /* reallocations. We thus need to recompute the subglyph */ 1866 /* pointer on each iteration. */ 1867 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1868 1869 pp[0] = loader->pp1; 1870 pp[1] = loader->pp2; 1871 pp[2] = loader->pp3; 1872 pp[3] = loader->pp4; 1873 1874 linear_hadvance = loader->linear; 1875 linear_vadvance = loader->vadvance; 1876 1877 num_base_points = (FT_UInt)gloader->base.outline.n_points; 1878 1879 error = load_truetype_glyph( loader, 1880 (FT_UInt)subglyph->index, 1881 recurse_count + 1, 1882 FALSE ); 1883 if ( error ) 1884 goto Exit; 1885 1886 /* restore subglyph pointer */ 1887 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1888 1889 /* restore phantom points if necessary */ 1890 if ( !( subglyph->flags & USE_MY_METRICS ) ) 1891 { 1892 loader->pp1 = pp[0]; 1893 loader->pp2 = pp[1]; 1894 loader->pp3 = pp[2]; 1895 loader->pp4 = pp[3]; 1896 1897 loader->linear = linear_hadvance; 1898 loader->vadvance = linear_vadvance; 1899 } 1900 1901 num_points = (FT_UInt)gloader->base.outline.n_points; 1902 1903 if ( num_points == num_base_points ) 1904 continue; 1905 1906 /* gloader->base.outline consists of three parts: */ 1907 /* */ 1908 /* 0 ----> start_point ----> num_base_points ----> n_points */ 1909 /* (1) (2) (3) */ 1910 /* */ 1911 /* (1) points that exist from the beginning */ 1912 /* (2) component points that have been loaded so far */ 1913 /* (3) points of the newly loaded component */ 1914 error = TT_Process_Composite_Component( loader, 1915 subglyph, 1916 start_point, 1917 num_base_points ); 1918 if ( error ) 1919 goto Exit; 1920 } 1921 1922 loader->stream = old_stream; 1923 loader->byte_len = old_byte_len; 1924 1925 /* process the glyph */ 1926 loader->ins_pos = ins_pos; 1927 if ( IS_HINTED( loader->load_flags ) && 1928 #ifdef TT_USE_BYTECODE_INTERPRETER 1929 subglyph && 1930 subglyph->flags & WE_HAVE_INSTR && 1931 #endif 1932 num_points > start_point ) 1933 { 1934 error = TT_Process_Composite_Glyph( loader, 1935 start_point, 1936 start_contour ); 1937 if ( error ) 1938 goto Exit; 1939 } 1940 } 1941 1942 /* retain the overlap flag */ 1943 if ( gloader->base.num_subglyphs && 1944 gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND ) 1945 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP; 1946 } 1947 1948 /***********************************************************************/ 1949 /***********************************************************************/ 1950 /***********************************************************************/ 1951 1952 Exit: 1953 1954 if ( opened_frame ) 1955 face->forget_glyph_frame( loader ); 1956 1957 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1958 1959 if ( glyph_data_loaded ) 1960 face->root.internal->incremental_interface->funcs->free_glyph_data( 1961 face->root.internal->incremental_interface->object, 1962 &glyph_data ); 1963 1964 #endif 1965 1966 return error; 1967 } 1968 1969 1970 static FT_Error compute_glyph_metrics(TT_Loader loader,FT_UInt glyph_index)1971 compute_glyph_metrics( TT_Loader loader, 1972 FT_UInt glyph_index ) 1973 { 1974 TT_Face face = loader->face; 1975 TT_Size size = loader->size; 1976 TT_GlyphSlot glyph = loader->glyph; 1977 FT_BBox bbox; 1978 FT_Fixed y_scale; 1979 1980 1981 y_scale = 0x10000L; 1982 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1983 y_scale = size->metrics->y_scale; 1984 1985 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) 1986 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 1987 else 1988 bbox = loader->bbox; 1989 1990 /* get the device-independent horizontal advance; it is scaled later */ 1991 /* by the base layer. */ 1992 glyph->linearHoriAdvance = loader->linear; 1993 1994 glyph->metrics.horiBearingX = bbox.xMin; 1995 glyph->metrics.horiBearingY = bbox.yMax; 1996 if ( loader->widthp ) 1997 glyph->metrics.horiAdvance = loader->widthp[glyph_index] * 64; 1998 else 1999 glyph->metrics.horiAdvance = SUB_LONG( loader->pp2.x, loader->pp1.x ); 2000 2001 /* set glyph dimensions */ 2002 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); 2003 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin ); 2004 2005 /* Now take care of vertical metrics. In the case where there is */ 2006 /* no vertical information within the font (relatively common), */ 2007 /* create some metrics manually */ 2008 { 2009 FT_Pos top; /* scaled vertical top side bearing */ 2010 FT_Pos advance; /* scaled vertical advance height */ 2011 2012 2013 /* Get the unscaled top bearing and advance height. */ 2014 if ( face->vertical_info && 2015 face->vertical.number_Of_VMetrics > 0 ) 2016 { 2017 top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ), 2018 y_scale ); 2019 2020 if ( loader->pp3.y <= loader->pp4.y ) 2021 advance = 0; 2022 else 2023 advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y, 2024 loader->pp4.y ), 2025 y_scale ); 2026 } 2027 else 2028 { 2029 FT_Pos height; 2030 2031 2032 /* XXX Compute top side bearing and advance height in */ 2033 /* Get_VMetrics instead of here. */ 2034 2035 /* NOTE: The OS/2 values are the only `portable' ones, */ 2036 /* which is why we use them, if there is an OS/2 */ 2037 /* table in the font. Otherwise, we use the */ 2038 /* values defined in the horizontal header. */ 2039 2040 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax, 2041 bbox.yMin ), 2042 y_scale ); 2043 if ( face->os2.version != 0xFFFFU ) 2044 advance = (FT_Pos)( face->os2.sTypoAscender - 2045 face->os2.sTypoDescender ); 2046 else 2047 advance = (FT_Pos)( face->horizontal.Ascender - 2048 face->horizontal.Descender ); 2049 2050 top = ( advance - height ) / 2; 2051 } 2052 2053 #ifdef FT_CONFIG_OPTION_INCREMENTAL 2054 { 2055 FT_Incremental_InterfaceRec* incr; 2056 FT_Incremental_MetricsRec incr_metrics; 2057 FT_Error error; 2058 2059 2060 incr = face->root.internal->incremental_interface; 2061 2062 /* If this is an incrementally loaded font see if there are */ 2063 /* overriding metrics for this glyph. */ 2064 if ( incr && incr->funcs->get_glyph_metrics ) 2065 { 2066 incr_metrics.bearing_x = 0; 2067 incr_metrics.bearing_y = top; 2068 incr_metrics.advance = advance; 2069 2070 error = incr->funcs->get_glyph_metrics( incr->object, 2071 glyph_index, 2072 TRUE, 2073 &incr_metrics ); 2074 if ( error ) 2075 return error; 2076 2077 top = incr_metrics.bearing_y; 2078 advance = incr_metrics.advance; 2079 } 2080 } 2081 2082 /* GWW: Do vertical metrics get loaded incrementally too? */ 2083 2084 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2085 2086 glyph->linearVertAdvance = advance; 2087 2088 /* scale the metrics */ 2089 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 2090 { 2091 top = FT_MulFix( top, y_scale ); 2092 advance = FT_MulFix( advance, y_scale ); 2093 } 2094 2095 /* XXX: for now, we have no better algorithm for the lsb, but it */ 2096 /* should work fine. */ 2097 /* */ 2098 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX, 2099 glyph->metrics.horiAdvance / 2 ); 2100 glyph->metrics.vertBearingY = top; 2101 glyph->metrics.vertAdvance = advance; 2102 } 2103 2104 return FT_Err_Ok; 2105 } 2106 2107 2108 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2109 2110 static FT_Error load_sbit_image(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2111 load_sbit_image( TT_Size size, 2112 TT_GlyphSlot glyph, 2113 FT_UInt glyph_index, 2114 FT_Int32 load_flags ) 2115 { 2116 TT_Face face = (TT_Face)glyph->face; 2117 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 2118 FT_Stream stream = face->root.stream; 2119 FT_Error error; 2120 TT_SBit_MetricsRec sbit_metrics; 2121 2122 2123 error = sfnt->load_sbit_image( face, 2124 size->strike_index, 2125 glyph_index, 2126 (FT_UInt)load_flags, 2127 stream, 2128 &glyph->bitmap, 2129 &sbit_metrics ); 2130 if ( !error ) 2131 { 2132 glyph->outline.n_points = 0; 2133 glyph->outline.n_contours = 0; 2134 2135 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64; 2136 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64; 2137 2138 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64; 2139 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64; 2140 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64; 2141 2142 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64; 2143 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64; 2144 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64; 2145 2146 glyph->format = FT_GLYPH_FORMAT_BITMAP; 2147 2148 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 2149 { 2150 glyph->bitmap_left = sbit_metrics.vertBearingX; 2151 glyph->bitmap_top = sbit_metrics.vertBearingY; 2152 } 2153 else 2154 { 2155 glyph->bitmap_left = sbit_metrics.horiBearingX; 2156 glyph->bitmap_top = sbit_metrics.horiBearingY; 2157 } 2158 } 2159 2160 return error; 2161 } 2162 2163 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2164 2165 2166 static FT_Error tt_loader_init(TT_Loader loader,TT_Size size,TT_GlyphSlot glyph,FT_Int32 load_flags,FT_Bool glyf_table_only)2167 tt_loader_init( TT_Loader loader, 2168 TT_Size size, 2169 TT_GlyphSlot glyph, 2170 FT_Int32 load_flags, 2171 FT_Bool glyf_table_only ) 2172 { 2173 TT_Face face = (TT_Face)glyph->face; 2174 FT_Stream stream = face->root.stream; 2175 2176 #ifdef TT_USE_BYTECODE_INTERPRETER 2177 FT_Error error; 2178 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2179 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2180 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( glyph->face ); 2181 #endif 2182 #endif 2183 2184 2185 FT_ZERO( loader ); 2186 2187 #ifdef TT_USE_BYTECODE_INTERPRETER 2188 2189 /* load execution context */ 2190 if ( IS_HINTED( load_flags ) && !glyf_table_only ) 2191 { 2192 TT_ExecContext exec; 2193 FT_Bool grayscale = TRUE; 2194 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2195 FT_Bool subpixel_hinting_lean; 2196 FT_Bool grayscale_cleartype; 2197 #endif 2198 2199 FT_Bool reexecute = FALSE; 2200 2201 2202 if ( size->bytecode_ready < 0 || size->cvt_ready < 0 ) 2203 { 2204 error = tt_size_ready_bytecode( size, pedantic ); 2205 if ( error ) 2206 return error; 2207 } 2208 else if ( size->bytecode_ready ) 2209 return size->bytecode_ready; 2210 else if ( size->cvt_ready ) 2211 return size->cvt_ready; 2212 2213 /* query new execution context */ 2214 exec = size->context; 2215 if ( !exec ) 2216 return FT_THROW( Could_Not_Find_Context ); 2217 2218 grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2219 FT_RENDER_MODE_MONO ); 2220 2221 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2222 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) 2223 { 2224 subpixel_hinting_lean = 2225 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2226 FT_RENDER_MODE_MONO ); 2227 grayscale_cleartype = 2228 FT_BOOL( subpixel_hinting_lean && 2229 !( ( load_flags & 2230 FT_LOAD_TARGET_LCD ) || 2231 ( load_flags & 2232 FT_LOAD_TARGET_LCD_V ) ) ); 2233 exec->vertical_lcd_lean = 2234 FT_BOOL( subpixel_hinting_lean && 2235 ( load_flags & 2236 FT_LOAD_TARGET_LCD_V ) ); 2237 grayscale = FT_BOOL( grayscale && !subpixel_hinting_lean ); 2238 } 2239 else 2240 { 2241 subpixel_hinting_lean = FALSE; 2242 grayscale_cleartype = FALSE; 2243 exec->vertical_lcd_lean = FALSE; 2244 } 2245 #endif 2246 2247 error = TT_Load_Context( exec, face, size ); 2248 if ( error ) 2249 return error; 2250 2251 { 2252 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2253 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) 2254 { 2255 /* a change from mono to subpixel rendering (and vice versa) */ 2256 /* requires a re-execution of the CVT program */ 2257 if ( subpixel_hinting_lean != exec->subpixel_hinting_lean ) 2258 { 2259 FT_TRACE4(( "tt_loader_init: subpixel hinting change," 2260 " re-executing `prep' table\n" )); 2261 2262 exec->subpixel_hinting_lean = subpixel_hinting_lean; 2263 reexecute = TRUE; 2264 } 2265 2266 /* a change from colored to grayscale subpixel rendering (and */ 2267 /* vice versa) requires a re-execution of the CVT program */ 2268 if ( grayscale_cleartype != exec->grayscale_cleartype ) 2269 { 2270 FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change," 2271 " re-executing `prep' table\n" )); 2272 2273 exec->grayscale_cleartype = grayscale_cleartype; 2274 reexecute = TRUE; 2275 } 2276 } 2277 #endif 2278 2279 /* a change from mono to grayscale rendering (and vice versa) */ 2280 /* requires a re-execution of the CVT program */ 2281 if ( grayscale != exec->grayscale ) 2282 { 2283 FT_TRACE4(( "tt_loader_init: grayscale hinting change," 2284 " re-executing `prep' table\n" )); 2285 2286 exec->grayscale = grayscale; 2287 reexecute = TRUE; 2288 } 2289 } 2290 2291 if ( reexecute ) 2292 { 2293 error = tt_size_run_prep( size, pedantic ); 2294 if ( error ) 2295 return error; 2296 error = TT_Load_Context( exec, face, size ); 2297 if ( error ) 2298 return error; 2299 } 2300 2301 /* check whether the cvt program has disabled hinting */ 2302 if ( exec->GS.instruct_control & 1 ) 2303 load_flags |= FT_LOAD_NO_HINTING; 2304 2305 /* load default graphics state -- if needed */ 2306 if ( exec->GS.instruct_control & 2 ) 2307 exec->GS = tt_default_graphics_state; 2308 2309 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2310 /* 2311 * Toggle backward compatibility according to what font wants, except 2312 * when 2313 * 2314 * 1) we have a `tricky' font that heavily relies on the interpreter to 2315 * render glyphs correctly, for example DFKai-SB, or 2316 * 2) FT_RENDER_MODE_MONO (i.e, monochome rendering) is requested. 2317 * 2318 * In those cases, backward compatibility needs to be turned off to get 2319 * correct rendering. The rendering is then completely up to the 2320 * font's programming. 2321 * 2322 */ 2323 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && 2324 subpixel_hinting_lean && 2325 !FT_IS_TRICKY( glyph->face ) ) 2326 exec->backward_compatibility = !( exec->GS.instruct_control & 4 ); 2327 else 2328 exec->backward_compatibility = FALSE; 2329 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL */ 2330 2331 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2332 loader->exec = exec; 2333 loader->instructions = exec->glyphIns; 2334 2335 /* Use the hdmx table if any unless FT_LOAD_COMPUTE_METRICS */ 2336 /* is set or backward compatibility mode of the v38 or v40 */ 2337 /* interpreters is active. See `ttinterp.h' for details on */ 2338 /* backward compatibility mode. */ 2339 if ( IS_HINTED( loader->load_flags ) && 2340 !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) && 2341 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2342 !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && 2343 exec->backward_compatibility ) && 2344 #endif 2345 !face->postscript.isFixedPitch ) 2346 { 2347 loader->widthp = size->widthp; 2348 } 2349 else 2350 loader->widthp = NULL; 2351 } 2352 2353 #endif /* TT_USE_BYTECODE_INTERPRETER */ 2354 2355 /* get face's glyph loader */ 2356 if ( !glyf_table_only ) 2357 { 2358 FT_GlyphLoader gloader = glyph->internal->loader; 2359 2360 2361 FT_GlyphLoader_Rewind( gloader ); 2362 loader->gloader = gloader; 2363 } 2364 2365 loader->load_flags = (FT_ULong)load_flags; 2366 2367 loader->face = face; 2368 loader->size = size; 2369 loader->glyph = (FT_GlyphSlot)glyph; 2370 loader->stream = stream; 2371 2372 loader->composites.head = NULL; 2373 loader->composites.tail = NULL; 2374 2375 return FT_Err_Ok; 2376 } 2377 2378 2379 static void tt_loader_done(TT_Loader loader)2380 tt_loader_done( TT_Loader loader ) 2381 { 2382 FT_List_Finalize( &loader->composites, 2383 NULL, 2384 loader->face->root.memory, 2385 NULL ); 2386 } 2387 2388 2389 /************************************************************************** 2390 * 2391 * @Function: 2392 * TT_Load_Glyph 2393 * 2394 * @Description: 2395 * A function used to load a single glyph within a given glyph slot, 2396 * for a given size. 2397 * 2398 * @InOut: 2399 * glyph :: 2400 * A handle to a target slot object where the glyph 2401 * will be loaded. 2402 * 2403 * @Input: 2404 * size :: 2405 * A handle to the source face size at which the glyph 2406 * must be scaled/loaded. 2407 * 2408 * glyph_index :: 2409 * The index of the glyph in the font file. 2410 * 2411 * load_flags :: 2412 * A flag indicating what to load for this glyph. The 2413 * FT_LOAD_XXX constants can be used to control the 2414 * glyph loading process (e.g., whether the outline 2415 * should be scaled, whether to load bitmaps or not, 2416 * whether to hint the outline, etc). 2417 * 2418 * @Return: 2419 * FreeType error code. 0 means success. 2420 */ 2421 FT_LOCAL_DEF( FT_Error ) TT_Load_Glyph(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2422 TT_Load_Glyph( TT_Size size, 2423 TT_GlyphSlot glyph, 2424 FT_UInt glyph_index, 2425 FT_Int32 load_flags ) 2426 { 2427 TT_Face face = (TT_Face)glyph->face; 2428 FT_Error error; 2429 TT_LoaderRec loader; 2430 2431 2432 FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index )); 2433 2434 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2435 2436 /* try to load embedded bitmap (if any) */ 2437 if ( size->strike_index != 0xFFFFFFFFUL && 2438 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && 2439 IS_DEFAULT_INSTANCE( glyph->face ) ) 2440 { 2441 FT_Fixed x_scale = size->root.metrics.x_scale; 2442 FT_Fixed y_scale = size->root.metrics.y_scale; 2443 2444 2445 error = load_sbit_image( size, glyph, glyph_index, load_flags ); 2446 if ( FT_ERR_EQ( error, Missing_Bitmap ) ) 2447 { 2448 /* the bitmap strike is incomplete and misses the requested glyph; */ 2449 /* if we have a bitmap-only font, return an empty glyph */ 2450 if ( !FT_IS_SCALABLE( glyph->face ) ) 2451 { 2452 FT_Short left_bearing = 0; 2453 FT_Short top_bearing = 0; 2454 2455 FT_UShort advance_width = 0; 2456 FT_UShort advance_height = 0; 2457 2458 2459 /* to return an empty glyph, however, we need metrics data */ 2460 /* from the `hmtx' (or `vmtx') table; the assumption is that */ 2461 /* empty glyphs are missing intentionally, representing */ 2462 /* whitespace - not having at least horizontal metrics is */ 2463 /* thus considered an error */ 2464 if ( !face->horz_metrics_size ) 2465 return error; 2466 2467 /* we now construct an empty bitmap glyph */ 2468 TT_Get_HMetrics( face, glyph_index, 2469 &left_bearing, 2470 &advance_width ); 2471 TT_Get_VMetrics( face, glyph_index, 2472 0, 2473 &top_bearing, 2474 &advance_height ); 2475 2476 glyph->outline.n_points = 0; 2477 glyph->outline.n_contours = 0; 2478 2479 glyph->metrics.width = 0; 2480 glyph->metrics.height = 0; 2481 2482 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale ); 2483 glyph->metrics.horiBearingY = 0; 2484 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale ); 2485 2486 glyph->metrics.vertBearingX = 0; 2487 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale ); 2488 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale ); 2489 2490 glyph->format = FT_GLYPH_FORMAT_BITMAP; 2491 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 2492 2493 glyph->bitmap_left = 0; 2494 glyph->bitmap_top = 0; 2495 2496 return FT_Err_Ok; 2497 } 2498 } 2499 else if ( error ) 2500 { 2501 /* return error if font is not scalable */ 2502 if ( !FT_IS_SCALABLE( glyph->face ) ) 2503 return error; 2504 } 2505 else 2506 { 2507 if ( FT_IS_SCALABLE( glyph->face ) || 2508 FT_HAS_SBIX( glyph->face ) ) 2509 { 2510 /* for the bbox we need the header only */ 2511 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); 2512 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); 2513 tt_loader_done( &loader ); 2514 glyph->linearHoriAdvance = loader.linear; 2515 glyph->linearVertAdvance = loader.vadvance; 2516 2517 /* Bitmaps from the 'sbix' table need special treatment: */ 2518 /* if there is a glyph contour, the bitmap origin must be */ 2519 /* shifted to be relative to the lower left corner of the */ 2520 /* glyph bounding box, also taking the left-side bearing */ 2521 /* (or top bearing) into account. */ 2522 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX && 2523 loader.n_contours > 0 ) 2524 { 2525 FT_Int bitmap_left; 2526 FT_Int bitmap_top; 2527 2528 2529 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 2530 { 2531 /* This is a guess, since Apple's CoreText engine doesn't */ 2532 /* really do vertical typesetting. */ 2533 bitmap_left = loader.bbox.xMin; 2534 bitmap_top = loader.top_bearing; 2535 } 2536 else 2537 { 2538 bitmap_left = loader.left_bearing; 2539 bitmap_top = loader.bbox.yMin; 2540 } 2541 2542 glyph->bitmap_left += FT_MulFix( bitmap_left, x_scale ) >> 6; 2543 glyph->bitmap_top += FT_MulFix( bitmap_top, y_scale ) >> 6; 2544 } 2545 2546 /* sanity checks: if `xxxAdvance' in the sbit metric */ 2547 /* structure isn't set, use `linearXXXAdvance' */ 2548 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) 2549 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance, 2550 x_scale ); 2551 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance ) 2552 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance, 2553 y_scale ); 2554 } 2555 2556 return FT_Err_Ok; 2557 } 2558 } 2559 2560 if ( load_flags & FT_LOAD_SBITS_ONLY ) 2561 { 2562 error = FT_THROW( Invalid_Argument ); 2563 goto Exit; 2564 } 2565 2566 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2567 2568 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ 2569 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) 2570 { 2571 error = FT_THROW( Invalid_Size_Handle ); 2572 goto Exit; 2573 } 2574 2575 #ifdef FT_CONFIG_OPTION_SVG 2576 2577 /* check for OT-SVG */ 2578 if ( ( load_flags & FT_LOAD_NO_SVG ) == 0 && 2579 ( load_flags & FT_LOAD_COLOR ) && 2580 face->svg ) 2581 { 2582 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 2583 2584 2585 FT_TRACE3(( "Trying to load SVG glyph\n" )); 2586 2587 error = sfnt->load_svg_doc( glyph, glyph_index ); 2588 if ( !error ) 2589 { 2590 FT_Fixed x_scale = size->root.metrics.x_scale; 2591 FT_Fixed y_scale = size->root.metrics.y_scale; 2592 2593 FT_Short leftBearing; 2594 FT_Short topBearing; 2595 FT_UShort advanceX; 2596 FT_UShort advanceY; 2597 2598 2599 FT_TRACE3(( "Successfully loaded SVG glyph\n" )); 2600 2601 glyph->format = FT_GLYPH_FORMAT_SVG; 2602 2603 sfnt->get_metrics( face, 2604 FALSE, 2605 glyph_index, 2606 &leftBearing, 2607 &advanceX ); 2608 sfnt->get_metrics( face, 2609 TRUE, 2610 glyph_index, 2611 &topBearing, 2612 &advanceY ); 2613 2614 glyph->linearHoriAdvance = advanceX; 2615 glyph->linearVertAdvance = advanceY; 2616 2617 glyph->metrics.horiAdvance = FT_MulFix( advanceX, x_scale ); 2618 glyph->metrics.vertAdvance = FT_MulFix( advanceY, y_scale ); 2619 2620 return error; 2621 } 2622 2623 FT_TRACE3(( "Failed to load SVG glyph\n" )); 2624 } 2625 2626 /* return immediately if we only want SVG glyphs */ 2627 if ( load_flags & FT_LOAD_SVG_ONLY ) 2628 { 2629 error = FT_THROW( Invalid_Argument ); 2630 goto Exit; 2631 } 2632 2633 #endif /* FT_CONFIG_OPTION_SVG */ 2634 2635 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); 2636 if ( error ) 2637 goto Exit; 2638 2639 /* done if we are only interested in the `hdmx` advance */ 2640 if ( load_flags & FT_LOAD_ADVANCE_ONLY && 2641 !( load_flags & FT_LOAD_VERTICAL_LAYOUT ) && 2642 loader.widthp ) 2643 { 2644 glyph->metrics.horiAdvance = loader.widthp[glyph_index] * 64; 2645 goto Done; 2646 } 2647 2648 glyph->format = FT_GLYPH_FORMAT_OUTLINE; 2649 glyph->num_subglyphs = 0; 2650 glyph->outline.flags = 0; 2651 2652 /* main loading loop */ 2653 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); 2654 if ( !error ) 2655 { 2656 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) 2657 { 2658 glyph->num_subglyphs = loader.gloader->base.num_subglyphs; 2659 glyph->subglyphs = loader.gloader->base.subglyphs; 2660 } 2661 else 2662 { 2663 glyph->outline = loader.gloader->base.outline; 2664 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; 2665 2666 /* Translate array so that (0,0) is the glyph's origin. Note */ 2667 /* that this behaviour is independent on the value of bit 1 of */ 2668 /* the `flags' field in the `head' table -- at least major */ 2669 /* applications like Acroread indicate that. */ 2670 if ( loader.pp1.x ) 2671 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); 2672 } 2673 2674 #ifdef TT_USE_BYTECODE_INTERPRETER 2675 2676 if ( IS_HINTED( load_flags ) ) 2677 { 2678 glyph->control_data = loader.exec->glyphIns; 2679 glyph->control_len = loader.exec->glyphSize; 2680 2681 if ( loader.exec->GS.scan_control ) 2682 { 2683 /* convert scan conversion mode to FT_OUTLINE_XXX flags */ 2684 switch ( loader.exec->GS.scan_type ) 2685 { 2686 case 0: /* simple drop-outs including stubs */ 2687 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; 2688 break; 2689 case 1: /* simple drop-outs excluding stubs */ 2690 /* nothing; it's the default rendering mode */ 2691 break; 2692 case 4: /* smart drop-outs including stubs */ 2693 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | 2694 FT_OUTLINE_INCLUDE_STUBS; 2695 break; 2696 case 5: /* smart drop-outs excluding stubs */ 2697 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; 2698 break; 2699 2700 default: /* no drop-out control */ 2701 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2702 break; 2703 } 2704 } 2705 else 2706 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2707 } 2708 2709 #endif /* TT_USE_BYTECODE_INTERPRETER */ 2710 2711 error = compute_glyph_metrics( &loader, glyph_index ); 2712 } 2713 2714 /* Set the `high precision' bit flag. */ 2715 /* This is _critical_ to get correct output for monochrome */ 2716 /* TrueType glyphs at all sizes using the bytecode interpreter. */ 2717 /* */ 2718 if ( !( load_flags & FT_LOAD_NO_SCALE ) && 2719 size->metrics->y_ppem < 24 ) 2720 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 2721 2722 FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd," 2723 " flags = 0x%.3x\n", 2724 loader.gloader->base.num_subglyphs, 2725 glyph->outline.n_contours, 2726 glyph->outline.n_points, 2727 glyph->outline.flags )); 2728 2729 Done: 2730 tt_loader_done( &loader ); 2731 2732 Exit: 2733 #ifdef FT_DEBUG_LEVEL_TRACE 2734 if ( error ) 2735 FT_TRACE1(( " failed (error code 0x%x)\n", 2736 error )); 2737 #endif 2738 2739 return error; 2740 } 2741 2742 2743 /* END */ 2744