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