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