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