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