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