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