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 /* Fix CVE-2025-27363 */ 1952 FT_Outline outline = { 0, 0, NULL, NULL, NULL, 0 }; 1953 FT_Vector* points = NULL; 1954 char* tags = NULL; 1955 short* contours = NULL; 1956 FT_Vector* unrounded = NULL; 1957 1958 1959 limit = (short)gloader->current.num_subglyphs; 1960 1961 /* Fix CVE-2025-27363 */ 1962 if ( limit < 0 ) 1963 { 1964 error = FT_THROW( Invalid_Argument ); 1965 goto Exit; 1966 } 1967 1968 /* construct an outline structure for */ 1969 /* communication with `TT_Vary_Apply_Glyph_Deltas' */ 1970 outline.n_points = (short)( gloader->current.num_subglyphs + 4 ); 1971 outline.n_contours = outline.n_points; 1972 1973 outline.points = NULL; 1974 outline.tags = NULL; 1975 outline.contours = NULL; 1976 1977 if ( FT_NEW_ARRAY( points, outline.n_points ) || 1978 FT_NEW_ARRAY( tags, outline.n_points ) || 1979 FT_NEW_ARRAY( contours, outline.n_points ) || 1980 FT_NEW_ARRAY( unrounded, outline.n_points ) ) 1981 goto Exit1; 1982 1983 subglyph = gloader->current.subglyphs; 1984 1985 for ( i = 0; i < limit; i++, subglyph++ ) 1986 { 1987 /* applying deltas for anchor points doesn't make sense, */ 1988 /* but we don't have to specially check this since */ 1989 /* unused delta values are zero anyways */ 1990 points[i].x = subglyph->arg1; 1991 points[i].y = subglyph->arg2; 1992 tags[i] = 1; 1993 contours[i] = i; 1994 } 1995 1996 points[i].x = loader->pp1.x; 1997 points[i].y = loader->pp1.y; 1998 tags[i] = 1; 1999 contours[i] = i; 2000 2001 i++; 2002 points[i].x = loader->pp2.x; 2003 points[i].y = loader->pp2.y; 2004 tags[i] = 1; 2005 contours[i] = i; 2006 2007 i++; 2008 points[i].x = loader->pp3.x; 2009 points[i].y = loader->pp3.y; 2010 tags[i] = 1; 2011 contours[i] = i; 2012 2013 i++; 2014 points[i].x = loader->pp4.x; 2015 points[i].y = loader->pp4.y; 2016 tags[i] = 1; 2017 contours[i] = i; 2018 2019 outline.points = points; 2020 outline.tags = tags; 2021 outline.contours = contours; 2022 2023 /* this call provides additional offsets */ 2024 /* for each component's translation */ 2025 if ( FT_SET_ERROR( TT_Vary_Apply_Glyph_Deltas( 2026 face, 2027 glyph_index, 2028 &outline, 2029 unrounded, 2030 (FT_UInt)outline.n_points ) ) ) 2031 goto Exit1; 2032 2033 subglyph = gloader->current.subglyphs; 2034 2035 for ( i = 0; i < limit; i++, subglyph++ ) 2036 { 2037 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 2038 { 2039 subglyph->arg1 = (FT_Int16)points[i].x; 2040 subglyph->arg2 = (FT_Int16)points[i].y; 2041 } 2042 } 2043 2044 loader->pp1.x = points[i + 0].x; 2045 loader->pp1.y = points[i + 0].y; 2046 loader->pp2.x = points[i + 1].x; 2047 loader->pp2.y = points[i + 1].y; 2048 2049 loader->pp3.x = points[i + 2].x; 2050 loader->pp3.y = points[i + 2].y; 2051 loader->pp4.x = points[i + 3].x; 2052 loader->pp4.y = points[i + 3].y; 2053 2054 /* recalculate linear horizontal and vertical advances */ 2055 /* if we don't have HVAR and VVAR, respectively */ 2056 if ( !( face->variation_support & TT_FACE_FLAG_VAR_HADVANCE ) ) 2057 loader->linear = 2058 FT_PIX_ROUND( unrounded[outline.n_points - 3].x - 2059 unrounded[outline.n_points - 4].x ) / 64; 2060 if ( !( face->variation_support & TT_FACE_FLAG_VAR_VADVANCE ) ) 2061 loader->vadvance = 2062 FT_PIX_ROUND( unrounded[outline.n_points - 1].x - 2063 unrounded[outline.n_points - 2].x ) / 64; 2064 2065 Exit1: 2066 FT_FREE( outline.points ); 2067 FT_FREE( outline.tags ); 2068 FT_FREE( outline.contours ); 2069 FT_FREE( unrounded ); 2070 2071 if ( error ) 2072 goto Exit; 2073 } 2074 2075 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 2076 2077 /* scale phantom points, if necessary; */ 2078 /* they get rounded in `TT_Hint_Glyph' */ 2079 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 2080 { 2081 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 2082 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 2083 /* pp1.y and pp2.y are always zero */ 2084 2085 loader->pp3.x = FT_MulFix( loader->pp3.x, x_scale ); 2086 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 2087 loader->pp4.x = FT_MulFix( loader->pp4.x, x_scale ); 2088 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 2089 } 2090 2091 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 2092 /* `as is' in the glyph slot (the client application will be */ 2093 /* responsible for interpreting these data)... */ 2094 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 2095 { 2096 FT_GlyphLoader_Add( gloader ); 2097 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 2098 2099 goto Exit; 2100 } 2101 2102 /*********************************************************************/ 2103 /*********************************************************************/ 2104 /*********************************************************************/ 2105 2106 { 2107 FT_UInt n, num_base_points; 2108 FT_SubGlyph subglyph = NULL; 2109 2110 FT_UInt num_points = start_point; 2111 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 2112 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 2113 2114 FT_Stream old_stream = loader->stream; 2115 FT_UInt old_byte_len = loader->byte_len; 2116 2117 2118 FT_GlyphLoader_Add( gloader ); 2119 2120 /* read each subglyph independently */ 2121 for ( n = 0; n < num_subglyphs; n++ ) 2122 { 2123 FT_Vector pp[4]; 2124 2125 FT_Int linear_hadvance; 2126 FT_Int linear_vadvance; 2127 2128 2129 /* Each time we call `load_truetype_glyph' in this loop, the */ 2130 /* value of `gloader.base.subglyphs' can change due to table */ 2131 /* reallocations. We thus need to recompute the subglyph */ 2132 /* pointer on each iteration. */ 2133 subglyph = gloader->base.subglyphs + num_base_subgs + n; 2134 2135 pp[0] = loader->pp1; 2136 pp[1] = loader->pp2; 2137 pp[2] = loader->pp3; 2138 pp[3] = loader->pp4; 2139 2140 linear_hadvance = loader->linear; 2141 linear_vadvance = loader->vadvance; 2142 2143 num_base_points = (FT_UInt)gloader->base.outline.n_points; 2144 2145 error = load_truetype_glyph( loader, 2146 (FT_UInt)subglyph->index, 2147 recurse_count + 1, 2148 FALSE ); 2149 if ( error ) 2150 goto Exit; 2151 2152 /* restore subglyph pointer */ 2153 subglyph = gloader->base.subglyphs + num_base_subgs + n; 2154 2155 /* restore phantom points if necessary */ 2156 if ( !( subglyph->flags & USE_MY_METRICS ) ) 2157 { 2158 loader->pp1 = pp[0]; 2159 loader->pp2 = pp[1]; 2160 loader->pp3 = pp[2]; 2161 loader->pp4 = pp[3]; 2162 2163 loader->linear = linear_hadvance; 2164 loader->vadvance = linear_vadvance; 2165 } 2166 2167 num_points = (FT_UInt)gloader->base.outline.n_points; 2168 2169 if ( num_points == num_base_points ) 2170 continue; 2171 2172 /* gloader->base.outline consists of three parts: */ 2173 /* */ 2174 /* 0 ----> start_point ----> num_base_points ----> n_points */ 2175 /* (1) (2) (3) */ 2176 /* */ 2177 /* (1) points that exist from the beginning */ 2178 /* (2) component points that have been loaded so far */ 2179 /* (3) points of the newly loaded component */ 2180 error = TT_Process_Composite_Component( loader, 2181 subglyph, 2182 start_point, 2183 num_base_points ); 2184 if ( error ) 2185 goto Exit; 2186 } 2187 2188 loader->stream = old_stream; 2189 loader->byte_len = old_byte_len; 2190 2191 /* process the glyph */ 2192 loader->ins_pos = ins_pos; 2193 if ( IS_HINTED( loader->load_flags ) && 2194 #ifdef TT_USE_BYTECODE_INTERPRETER 2195 subglyph && 2196 subglyph->flags & WE_HAVE_INSTR && 2197 #endif 2198 num_points > start_point ) 2199 { 2200 error = TT_Process_Composite_Glyph( loader, 2201 start_point, 2202 start_contour ); 2203 if ( error ) 2204 goto Exit; 2205 } 2206 } 2207 2208 /* retain the overlap flag */ 2209 if ( gloader->base.num_subglyphs && 2210 gloader->base.subglyphs[0].flags & OVERLAP_COMPOUND ) 2211 gloader->base.outline.flags |= FT_OUTLINE_OVERLAP; 2212 } 2213 2214 /***********************************************************************/ 2215 /***********************************************************************/ 2216 /***********************************************************************/ 2217 2218 Exit: 2219 2220 if ( opened_frame ) 2221 face->forget_glyph_frame( loader ); 2222 2223 #ifdef FT_CONFIG_OPTION_INCREMENTAL 2224 2225 if ( glyph_data_loaded ) 2226 face->root.internal->incremental_interface->funcs->free_glyph_data( 2227 face->root.internal->incremental_interface->object, 2228 &glyph_data ); 2229 2230 #endif 2231 2232 return error; 2233 } 2234 2235 2236 static FT_Error compute_glyph_metrics(TT_Loader loader,FT_UInt glyph_index)2237 compute_glyph_metrics( TT_Loader loader, 2238 FT_UInt glyph_index ) 2239 { 2240 TT_Face face = loader->face; 2241 #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ 2242 defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2243 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( face ); 2244 #endif 2245 2246 FT_BBox bbox; 2247 FT_Fixed y_scale; 2248 TT_GlyphSlot glyph = loader->glyph; 2249 TT_Size size = loader->size; 2250 2251 2252 y_scale = 0x10000L; 2253 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 2254 y_scale = size->metrics->y_scale; 2255 2256 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) 2257 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 2258 else 2259 bbox = loader->bbox; 2260 2261 /* get the device-independent horizontal advance; it is scaled later */ 2262 /* by the base layer. */ 2263 glyph->linearHoriAdvance = loader->linear; 2264 2265 glyph->metrics.horiBearingX = bbox.xMin; 2266 glyph->metrics.horiBearingY = bbox.yMax; 2267 glyph->metrics.horiAdvance = SUB_LONG(loader->pp2.x, loader->pp1.x); 2268 2269 /* Adjust advance width to the value contained in the hdmx table */ 2270 /* unless FT_LOAD_COMPUTE_METRICS is set or backward compatibility */ 2271 /* mode of the v40 interpreter is active. See `ttinterp.h' for */ 2272 /* details on backward compatibility mode. */ 2273 if ( 2274 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2275 !( driver->interpreter_version == TT_INTERPRETER_VERSION_40 && 2276 ( loader->exec && loader->exec->backward_compatibility ) ) && 2277 #endif 2278 !face->postscript.isFixedPitch && 2279 IS_HINTED( loader->load_flags ) && 2280 !( loader->load_flags & FT_LOAD_COMPUTE_METRICS ) ) 2281 { 2282 FT_Byte* widthp; 2283 2284 2285 widthp = tt_face_get_device_metrics( face, 2286 size->metrics->x_ppem, 2287 glyph_index ); 2288 2289 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 2290 2291 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 2292 { 2293 FT_Bool ignore_x_mode; 2294 2295 2296 ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != 2297 FT_RENDER_MODE_MONO ); 2298 2299 if ( widthp && 2300 ( ( ignore_x_mode && loader->exec->compatible_widths ) || 2301 !ignore_x_mode || 2302 SPH_OPTION_BITMAP_WIDTHS ) ) 2303 glyph->metrics.horiAdvance = *widthp * 64; 2304 } 2305 else 2306 2307 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ 2308 2309 { 2310 if ( widthp ) 2311 glyph->metrics.horiAdvance = *widthp * 64; 2312 } 2313 } 2314 2315 /* set glyph dimensions */ 2316 glyph->metrics.width = SUB_LONG( bbox.xMax, bbox.xMin ); 2317 glyph->metrics.height = SUB_LONG( bbox.yMax, bbox.yMin ); 2318 2319 /* Now take care of vertical metrics. In the case where there is */ 2320 /* no vertical information within the font (relatively common), */ 2321 /* create some metrics manually */ 2322 { 2323 FT_Pos top; /* scaled vertical top side bearing */ 2324 FT_Pos advance; /* scaled vertical advance height */ 2325 2326 2327 /* Get the unscaled top bearing and advance height. */ 2328 if ( face->vertical_info && 2329 face->vertical.number_Of_VMetrics > 0 ) 2330 { 2331 top = (FT_Short)FT_DivFix( SUB_LONG( loader->pp3.y, bbox.yMax ), 2332 y_scale ); 2333 2334 if ( loader->pp3.y <= loader->pp4.y ) 2335 advance = 0; 2336 else 2337 advance = (FT_UShort)FT_DivFix( SUB_LONG( loader->pp3.y, 2338 loader->pp4.y ), 2339 y_scale ); 2340 } 2341 else 2342 { 2343 FT_Pos height; 2344 2345 2346 /* XXX Compute top side bearing and advance height in */ 2347 /* Get_VMetrics instead of here. */ 2348 2349 /* NOTE: The OS/2 values are the only `portable' ones, */ 2350 /* which is why we use them, if there is an OS/2 */ 2351 /* table in the font. Otherwise, we use the */ 2352 /* values defined in the horizontal header. */ 2353 2354 height = (FT_Short)FT_DivFix( SUB_LONG( bbox.yMax, 2355 bbox.yMin ), 2356 y_scale ); 2357 if ( face->os2.version != 0xFFFFU ) 2358 advance = (FT_Pos)( face->os2.sTypoAscender - 2359 face->os2.sTypoDescender ); 2360 else 2361 advance = (FT_Pos)( face->horizontal.Ascender - 2362 face->horizontal.Descender ); 2363 2364 top = ( advance - height ) / 2; 2365 } 2366 2367 #ifdef FT_CONFIG_OPTION_INCREMENTAL 2368 { 2369 FT_Incremental_InterfaceRec* incr; 2370 FT_Incremental_MetricsRec incr_metrics; 2371 FT_Error error; 2372 2373 2374 incr = face->root.internal->incremental_interface; 2375 2376 /* If this is an incrementally loaded font see if there are */ 2377 /* overriding metrics for this glyph. */ 2378 if ( incr && incr->funcs->get_glyph_metrics ) 2379 { 2380 incr_metrics.bearing_x = 0; 2381 incr_metrics.bearing_y = top; 2382 incr_metrics.advance = advance; 2383 2384 error = incr->funcs->get_glyph_metrics( incr->object, 2385 glyph_index, 2386 TRUE, 2387 &incr_metrics ); 2388 if ( error ) 2389 return error; 2390 2391 top = incr_metrics.bearing_y; 2392 advance = incr_metrics.advance; 2393 } 2394 } 2395 2396 /* GWW: Do vertical metrics get loaded incrementally too? */ 2397 2398 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 2399 2400 glyph->linearVertAdvance = advance; 2401 2402 /* scale the metrics */ 2403 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 2404 { 2405 top = FT_MulFix( top, y_scale ); 2406 advance = FT_MulFix( advance, y_scale ); 2407 } 2408 2409 /* XXX: for now, we have no better algorithm for the lsb, but it */ 2410 /* should work fine. */ 2411 /* */ 2412 glyph->metrics.vertBearingX = SUB_LONG( glyph->metrics.horiBearingX, 2413 glyph->metrics.horiAdvance / 2 ); 2414 glyph->metrics.vertBearingY = top; 2415 glyph->metrics.vertAdvance = advance; 2416 } 2417 2418 return FT_Err_Ok; 2419 } 2420 2421 2422 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2423 2424 static FT_Error load_sbit_image(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2425 load_sbit_image( TT_Size size, 2426 TT_GlyphSlot glyph, 2427 FT_UInt glyph_index, 2428 FT_Int32 load_flags ) 2429 { 2430 TT_Face face; 2431 SFNT_Service sfnt; 2432 FT_Stream stream; 2433 FT_Error error; 2434 TT_SBit_MetricsRec sbit_metrics; 2435 2436 2437 face = (TT_Face)glyph->face; 2438 sfnt = (SFNT_Service)face->sfnt; 2439 stream = face->root.stream; 2440 2441 error = sfnt->load_sbit_image( face, 2442 size->strike_index, 2443 glyph_index, 2444 (FT_UInt)load_flags, 2445 stream, 2446 &glyph->bitmap, 2447 &sbit_metrics ); 2448 if ( !error ) 2449 { 2450 glyph->outline.n_points = 0; 2451 glyph->outline.n_contours = 0; 2452 2453 glyph->metrics.width = (FT_Pos)sbit_metrics.width * 64; 2454 glyph->metrics.height = (FT_Pos)sbit_metrics.height * 64; 2455 2456 glyph->metrics.horiBearingX = (FT_Pos)sbit_metrics.horiBearingX * 64; 2457 glyph->metrics.horiBearingY = (FT_Pos)sbit_metrics.horiBearingY * 64; 2458 glyph->metrics.horiAdvance = (FT_Pos)sbit_metrics.horiAdvance * 64; 2459 2460 glyph->metrics.vertBearingX = (FT_Pos)sbit_metrics.vertBearingX * 64; 2461 glyph->metrics.vertBearingY = (FT_Pos)sbit_metrics.vertBearingY * 64; 2462 glyph->metrics.vertAdvance = (FT_Pos)sbit_metrics.vertAdvance * 64; 2463 2464 glyph->format = FT_GLYPH_FORMAT_BITMAP; 2465 2466 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 2467 { 2468 glyph->bitmap_left = sbit_metrics.vertBearingX; 2469 glyph->bitmap_top = sbit_metrics.vertBearingY; 2470 } 2471 else 2472 { 2473 glyph->bitmap_left = sbit_metrics.horiBearingX; 2474 glyph->bitmap_top = sbit_metrics.horiBearingY; 2475 } 2476 } 2477 2478 return error; 2479 } 2480 2481 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2482 2483 2484 static FT_Error tt_loader_init(TT_Loader loader,TT_Size size,TT_GlyphSlot glyph,FT_Int32 load_flags,FT_Bool glyf_table_only)2485 tt_loader_init( TT_Loader loader, 2486 TT_Size size, 2487 TT_GlyphSlot glyph, 2488 FT_Int32 load_flags, 2489 FT_Bool glyf_table_only ) 2490 { 2491 TT_Face face; 2492 FT_Stream stream; 2493 2494 #ifdef TT_USE_BYTECODE_INTERPRETER 2495 FT_Error error; 2496 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2497 #if defined TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY || \ 2498 defined TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2499 TT_Driver driver = (TT_Driver)FT_FACE_DRIVER( (TT_Face)glyph->face ); 2500 #endif 2501 #endif 2502 2503 2504 face = (TT_Face)glyph->face; 2505 stream = face->root.stream; 2506 2507 FT_ZERO( loader ); 2508 2509 #ifdef TT_USE_BYTECODE_INTERPRETER 2510 2511 /* load execution context */ 2512 if ( IS_HINTED( load_flags ) && !glyf_table_only ) 2513 { 2514 TT_ExecContext exec; 2515 FT_Bool grayscale = TRUE; 2516 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2517 FT_Bool subpixel_hinting_lean; 2518 FT_Bool grayscale_cleartype; 2519 #endif 2520 2521 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 2522 FT_Bool subpixel_hinting = FALSE; 2523 2524 #if 0 2525 /* not used yet */ 2526 FT_Bool compatible_widths; 2527 FT_Bool symmetrical_smoothing; 2528 FT_Bool bgr; 2529 FT_Bool vertical_lcd; 2530 FT_Bool subpixel_positioned; 2531 FT_Bool gray_cleartype; 2532 #endif 2533 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ 2534 2535 FT_Bool reexecute = FALSE; 2536 2537 2538 if ( size->bytecode_ready < 0 || size->cvt_ready < 0 ) 2539 { 2540 error = tt_size_ready_bytecode( size, pedantic ); 2541 if ( error ) 2542 return error; 2543 } 2544 else if ( size->bytecode_ready ) 2545 return size->bytecode_ready; 2546 else if ( size->cvt_ready ) 2547 return size->cvt_ready; 2548 2549 /* query new execution context */ 2550 exec = size->context; 2551 if ( !exec ) 2552 return FT_THROW( Could_Not_Find_Context ); 2553 2554 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2555 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) 2556 { 2557 subpixel_hinting_lean = 2558 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2559 FT_RENDER_MODE_MONO ); 2560 grayscale_cleartype = 2561 FT_BOOL( subpixel_hinting_lean && 2562 !( ( load_flags & 2563 FT_LOAD_TARGET_LCD ) || 2564 ( load_flags & 2565 FT_LOAD_TARGET_LCD_V ) ) ); 2566 exec->vertical_lcd_lean = 2567 FT_BOOL( subpixel_hinting_lean && 2568 ( load_flags & 2569 FT_LOAD_TARGET_LCD_V ) ); 2570 } 2571 else 2572 { 2573 subpixel_hinting_lean = FALSE; 2574 grayscale_cleartype = FALSE; 2575 exec->vertical_lcd_lean = FALSE; 2576 } 2577 #endif 2578 2579 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 2580 2581 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 2582 { 2583 subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) != 2584 FT_RENDER_MODE_MONO ) && 2585 SPH_OPTION_SET_SUBPIXEL ); 2586 2587 if ( subpixel_hinting ) 2588 grayscale = FALSE; 2589 else if ( SPH_OPTION_SET_GRAYSCALE ) 2590 { 2591 grayscale = TRUE; 2592 subpixel_hinting = FALSE; 2593 } 2594 else 2595 grayscale = FALSE; 2596 2597 if ( FT_IS_TRICKY( glyph->face ) ) 2598 subpixel_hinting = FALSE; 2599 2600 exec->ignore_x_mode = subpixel_hinting || grayscale; 2601 exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; 2602 if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) 2603 exec->rasterizer_version = TT_INTERPRETER_VERSION_35; 2604 2605 #if 1 2606 exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; 2607 exec->symmetrical_smoothing = TRUE; 2608 exec->bgr = FALSE; 2609 exec->vertical_lcd = FALSE; 2610 exec->subpixel_positioned = TRUE; 2611 exec->gray_cleartype = FALSE; 2612 #else /* 0 */ 2613 exec->compatible_widths = 2614 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2615 TT_LOAD_COMPATIBLE_WIDTHS ); 2616 exec->symmetrical_smoothing = 2617 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2618 TT_LOAD_SYMMETRICAL_SMOOTHING ); 2619 exec->bgr = 2620 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2621 TT_LOAD_BGR ); 2622 exec->vertical_lcd = 2623 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2624 TT_LOAD_VERTICAL_LCD ); 2625 exec->subpixel_positioned = 2626 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2627 TT_LOAD_SUBPIXEL_POSITIONED ); 2628 exec->gray_cleartype = 2629 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2630 TT_LOAD_GRAY_CLEARTYPE ); 2631 #endif /* 0 */ 2632 2633 } 2634 else 2635 2636 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ 2637 2638 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2639 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) 2640 grayscale = FT_BOOL( !subpixel_hinting_lean && 2641 FT_LOAD_TARGET_MODE( load_flags ) != 2642 FT_RENDER_MODE_MONO ); 2643 else 2644 #endif 2645 grayscale = FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 2646 FT_RENDER_MODE_MONO ); 2647 2648 error = TT_Load_Context( exec, face, size ); 2649 if ( error ) 2650 return error; 2651 2652 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 2653 2654 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 ) 2655 { 2656 /* a change from mono to subpixel rendering (and vice versa) */ 2657 /* requires a re-execution of the CVT program */ 2658 if ( subpixel_hinting != exec->subpixel_hinting ) 2659 { 2660 FT_TRACE4(( "tt_loader_init: subpixel hinting change," 2661 " re-executing `prep' table\n" )); 2662 2663 exec->subpixel_hinting = subpixel_hinting; 2664 reexecute = TRUE; 2665 } 2666 2667 /* a change from mono to grayscale rendering (and vice versa) */ 2668 /* requires a re-execution of the CVT program */ 2669 if ( grayscale != exec->grayscale ) 2670 { 2671 FT_TRACE4(( "tt_loader_init: grayscale hinting change," 2672 " re-executing `prep' table\n" )); 2673 2674 exec->grayscale = grayscale; 2675 reexecute = TRUE; 2676 } 2677 } 2678 else 2679 2680 #endif /* TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY */ 2681 2682 { 2683 2684 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 2685 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_40 ) 2686 { 2687 /* a change from mono to subpixel rendering (and vice versa) */ 2688 /* requires a re-execution of the CVT program */ 2689 if ( subpixel_hinting_lean != exec->subpixel_hinting_lean ) 2690 { 2691 FT_TRACE4(( "tt_loader_init: subpixel hinting change," 2692 " re-executing `prep' table\n" )); 2693 2694 exec->subpixel_hinting_lean = subpixel_hinting_lean; 2695 reexecute = TRUE; 2696 } 2697 2698 /* a change from colored to grayscale subpixel rendering (and */ 2699 /* vice versa) requires a re-execution of the CVT program */ 2700 if ( grayscale_cleartype != exec->grayscale_cleartype ) 2701 { 2702 FT_TRACE4(( "tt_loader_init: grayscale subpixel hinting change," 2703 " re-executing `prep' table\n" )); 2704 2705 exec->grayscale_cleartype = grayscale_cleartype; 2706 reexecute = TRUE; 2707 } 2708 } 2709 #endif 2710 2711 /* a change from mono to grayscale rendering (and vice versa) */ 2712 /* requires a re-execution of the CVT program */ 2713 if ( grayscale != exec->grayscale ) 2714 { 2715 FT_TRACE4(( "tt_loader_init: grayscale hinting change," 2716 " re-executing `prep' table\n" )); 2717 2718 exec->grayscale = grayscale; 2719 reexecute = TRUE; 2720 } 2721 } 2722 2723 if ( reexecute ) 2724 { 2725 error = tt_size_run_prep( size, pedantic ); 2726 if ( error ) 2727 return error; 2728 error = TT_Load_Context( exec, face, size ); 2729 if ( error ) 2730 return error; 2731 } 2732 2733 /* check whether the cvt program has disabled hinting */ 2734 if ( exec->GS.instruct_control & 1 ) 2735 load_flags |= FT_LOAD_NO_HINTING; 2736 2737 /* load default graphics state -- if needed */ 2738 if ( exec->GS.instruct_control & 2 ) 2739 exec->GS = tt_default_graphics_state; 2740 2741 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 2742 /* check whether we have a font hinted for ClearType -- */ 2743 /* note that this flag can also be modified in a glyph's bytecode */ 2744 if ( driver->interpreter_version == TT_INTERPRETER_VERSION_38 && 2745 exec->GS.instruct_control & 4 ) 2746 exec->ignore_x_mode = 0; 2747 #endif 2748 2749 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2750 loader->exec = exec; 2751 loader->instructions = exec->glyphIns; 2752 } 2753 2754 #endif /* TT_USE_BYTECODE_INTERPRETER */ 2755 2756 /* get face's glyph loader */ 2757 if ( !glyf_table_only ) 2758 { 2759 FT_GlyphLoader gloader = glyph->internal->loader; 2760 2761 2762 FT_GlyphLoader_Rewind( gloader ); 2763 loader->gloader = gloader; 2764 } 2765 2766 loader->load_flags = (FT_ULong)load_flags; 2767 2768 loader->face = face; 2769 loader->size = size; 2770 loader->glyph = (FT_GlyphSlot)glyph; 2771 loader->stream = stream; 2772 2773 loader->composites.head = NULL; 2774 loader->composites.tail = NULL; 2775 2776 return FT_Err_Ok; 2777 } 2778 2779 2780 static void tt_loader_done(TT_Loader loader)2781 tt_loader_done( TT_Loader loader ) 2782 { 2783 FT_List_Finalize( &loader->composites, 2784 NULL, 2785 loader->face->root.memory, 2786 NULL ); 2787 } 2788 2789 2790 /************************************************************************** 2791 * 2792 * @Function: 2793 * TT_Load_Glyph 2794 * 2795 * @Description: 2796 * A function used to load a single glyph within a given glyph slot, 2797 * for a given size. 2798 * 2799 * @Input: 2800 * glyph :: 2801 * A handle to a target slot object where the glyph 2802 * will be loaded. 2803 * 2804 * size :: 2805 * A handle to the source face size at which the glyph 2806 * must be scaled/loaded. 2807 * 2808 * glyph_index :: 2809 * The index of the glyph in the font file. 2810 * 2811 * load_flags :: 2812 * A flag indicating what to load for this glyph. The 2813 * FT_LOAD_XXX constants can be used to control the 2814 * glyph loading process (e.g., whether the outline 2815 * should be scaled, whether to load bitmaps or not, 2816 * whether to hint the outline, etc). 2817 * 2818 * @Return: 2819 * FreeType error code. 0 means success. 2820 */ 2821 FT_LOCAL_DEF( FT_Error ) TT_Load_Glyph(TT_Size size,TT_GlyphSlot glyph,FT_UInt glyph_index,FT_Int32 load_flags)2822 TT_Load_Glyph( TT_Size size, 2823 TT_GlyphSlot glyph, 2824 FT_UInt glyph_index, 2825 FT_Int32 load_flags ) 2826 { 2827 FT_Error error; 2828 TT_LoaderRec loader; 2829 2830 2831 FT_TRACE1(( "TT_Load_Glyph: glyph index %d\n", glyph_index )); 2832 2833 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2834 2835 /* try to load embedded bitmap (if any) */ 2836 if ( size->strike_index != 0xFFFFFFFFUL && 2837 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && 2838 IS_DEFAULT_INSTANCE( glyph->face ) ) 2839 { 2840 FT_Fixed x_scale = size->root.metrics.x_scale; 2841 FT_Fixed y_scale = size->root.metrics.y_scale; 2842 2843 2844 error = load_sbit_image( size, glyph, glyph_index, load_flags ); 2845 if ( FT_ERR_EQ( error, Missing_Bitmap ) ) 2846 { 2847 /* the bitmap strike is incomplete and misses the requested glyph; */ 2848 /* if we have a bitmap-only font, return an empty glyph */ 2849 if ( !FT_IS_SCALABLE( glyph->face ) ) 2850 { 2851 TT_Face face = (TT_Face)glyph->face; 2852 2853 FT_Short left_bearing = 0; 2854 FT_Short top_bearing = 0; 2855 2856 FT_UShort advance_width = 0; 2857 FT_UShort advance_height = 0; 2858 2859 2860 /* to return an empty glyph, however, we need metrics data */ 2861 /* from the `hmtx' (or `vmtx') table; the assumption is that */ 2862 /* empty glyphs are missing intentionally, representing */ 2863 /* whitespace - not having at least horizontal metrics is */ 2864 /* thus considered an error */ 2865 if ( !face->horz_metrics_size ) 2866 return error; 2867 2868 /* we now construct an empty bitmap glyph */ 2869 TT_Get_HMetrics( face, glyph_index, 2870 &left_bearing, 2871 &advance_width ); 2872 TT_Get_VMetrics( face, glyph_index, 2873 0, 2874 &top_bearing, 2875 &advance_height ); 2876 2877 glyph->outline.n_points = 0; 2878 glyph->outline.n_contours = 0; 2879 2880 glyph->metrics.width = 0; 2881 glyph->metrics.height = 0; 2882 2883 glyph->metrics.horiBearingX = FT_MulFix( left_bearing, x_scale ); 2884 glyph->metrics.horiBearingY = 0; 2885 glyph->metrics.horiAdvance = FT_MulFix( advance_width, x_scale ); 2886 2887 glyph->metrics.vertBearingX = 0; 2888 glyph->metrics.vertBearingY = FT_MulFix( top_bearing, y_scale ); 2889 glyph->metrics.vertAdvance = FT_MulFix( advance_height, y_scale ); 2890 2891 glyph->format = FT_GLYPH_FORMAT_BITMAP; 2892 glyph->bitmap.pixel_mode = FT_PIXEL_MODE_MONO; 2893 2894 glyph->bitmap_left = 0; 2895 glyph->bitmap_top = 0; 2896 2897 return FT_Err_Ok; 2898 } 2899 } 2900 else if ( error ) 2901 { 2902 /* return error if font is not scalable */ 2903 if ( !FT_IS_SCALABLE( glyph->face ) ) 2904 return error; 2905 } 2906 else 2907 { 2908 if ( FT_IS_SCALABLE( glyph->face ) ) 2909 { 2910 /* for the bbox we need the header only */ 2911 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); 2912 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); 2913 tt_loader_done( &loader ); 2914 glyph->linearHoriAdvance = loader.linear; 2915 glyph->linearVertAdvance = loader.vadvance; 2916 2917 /* sanity checks: if `xxxAdvance' in the sbit metric */ 2918 /* structure isn't set, use `linearXXXAdvance' */ 2919 if ( !glyph->metrics.horiAdvance && glyph->linearHoriAdvance ) 2920 glyph->metrics.horiAdvance = FT_MulFix( glyph->linearHoriAdvance, 2921 x_scale ); 2922 if ( !glyph->metrics.vertAdvance && glyph->linearVertAdvance ) 2923 glyph->metrics.vertAdvance = FT_MulFix( glyph->linearVertAdvance, 2924 y_scale ); 2925 } 2926 2927 return FT_Err_Ok; 2928 } 2929 } 2930 2931 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2932 2933 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ 2934 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) 2935 { 2936 error = FT_THROW( Invalid_Size_Handle ); 2937 goto Exit; 2938 } 2939 2940 if ( load_flags & FT_LOAD_SBITS_ONLY ) 2941 { 2942 error = FT_THROW( Invalid_Argument ); 2943 goto Exit; 2944 } 2945 2946 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); 2947 if ( error ) 2948 goto Exit; 2949 2950 glyph->format = FT_GLYPH_FORMAT_OUTLINE; 2951 glyph->num_subglyphs = 0; 2952 glyph->outline.flags = 0; 2953 2954 /* main loading loop */ 2955 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); 2956 if ( !error ) 2957 { 2958 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) 2959 { 2960 glyph->num_subglyphs = loader.gloader->base.num_subglyphs; 2961 glyph->subglyphs = loader.gloader->base.subglyphs; 2962 } 2963 else 2964 { 2965 glyph->outline = loader.gloader->base.outline; 2966 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; 2967 2968 /* Translate array so that (0,0) is the glyph's origin. Note */ 2969 /* that this behaviour is independent on the value of bit 1 of */ 2970 /* the `flags' field in the `head' table -- at least major */ 2971 /* applications like Acroread indicate that. */ 2972 if ( loader.pp1.x ) 2973 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); 2974 } 2975 2976 #ifdef TT_USE_BYTECODE_INTERPRETER 2977 2978 if ( IS_HINTED( load_flags ) ) 2979 { 2980 if ( loader.exec->GS.scan_control ) 2981 { 2982 /* convert scan conversion mode to FT_OUTLINE_XXX flags */ 2983 switch ( loader.exec->GS.scan_type ) 2984 { 2985 case 0: /* simple drop-outs including stubs */ 2986 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; 2987 break; 2988 case 1: /* simple drop-outs excluding stubs */ 2989 /* nothing; it's the default rendering mode */ 2990 break; 2991 case 4: /* smart drop-outs including stubs */ 2992 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | 2993 FT_OUTLINE_INCLUDE_STUBS; 2994 break; 2995 case 5: /* smart drop-outs excluding stubs */ 2996 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; 2997 break; 2998 2999 default: /* no drop-out control */ 3000 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 3001 break; 3002 } 3003 } 3004 else 3005 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 3006 } 3007 3008 #endif /* TT_USE_BYTECODE_INTERPRETER */ 3009 3010 error = compute_glyph_metrics( &loader, glyph_index ); 3011 } 3012 3013 /* Set the `high precision' bit flag. */ 3014 /* This is _critical_ to get correct output for monochrome */ 3015 /* TrueType glyphs at all sizes using the bytecode interpreter. */ 3016 /* */ 3017 if ( !( load_flags & FT_LOAD_NO_SCALE ) && 3018 size->metrics->y_ppem < 24 ) 3019 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 3020 3021 FT_TRACE1(( " subglyphs = %u, contours = %hd, points = %hd," 3022 " flags = 0x%.3x\n", 3023 loader.gloader->base.num_subglyphs, 3024 glyph->outline.n_contours, 3025 glyph->outline.n_points, 3026 glyph->outline.flags )); 3027 3028 tt_loader_done( &loader ); 3029 3030 Exit: 3031 #ifdef FT_DEBUG_LEVEL_TRACE 3032 if ( error ) 3033 FT_TRACE1(( " failed (error code 0x%x)\n", 3034 error )); 3035 #endif 3036 3037 return error; 3038 } 3039 3040 3041 /* END */ 3042