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