ttgload.c revision b6de8e661251ebd14b363b8286e68ce16de20174
1/***************************************************************************/ 2/* */ 3/* ttgload.c */ 4/* */ 5/* TrueType Glyph Loader (body). */ 6/* */ 7/* Copyright 1996-2013 */ 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_INTERNAL_CALC_H 22#include FT_INTERNAL_STREAM_H 23#include FT_INTERNAL_SFNT_H 24#include FT_TRUETYPE_TAGS_H 25#include FT_TRIGONOMETRY_H 26#include FT_OUTLINE_H 27 28#include "ttgload.h" 29#include "ttpload.h" 30 31#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 32#include "ttgxvar.h" 33#endif 34 35#include "tterrors.h" 36#include "ttsubpix.h" 37 38 39 /*************************************************************************/ 40 /* */ 41 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 42 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 43 /* messages during execution. */ 44 /* */ 45#undef FT_COMPONENT 46#define FT_COMPONENT trace_ttgload 47 48 49 /*************************************************************************/ 50 /* */ 51 /* Composite glyph flags. */ 52 /* */ 53#define ARGS_ARE_WORDS 0x0001 54#define ARGS_ARE_XY_VALUES 0x0002 55#define ROUND_XY_TO_GRID 0x0004 56#define WE_HAVE_A_SCALE 0x0008 57/* reserved 0x0010 */ 58#define MORE_COMPONENTS 0x0020 59#define WE_HAVE_AN_XY_SCALE 0x0040 60#define WE_HAVE_A_2X2 0x0080 61#define WE_HAVE_INSTR 0x0100 62#define USE_MY_METRICS 0x0200 63#define OVERLAP_COMPOUND 0x0400 64#define SCALED_COMPONENT_OFFSET 0x0800 65#define UNSCALED_COMPONENT_OFFSET 0x1000 66 67 68 /*************************************************************************/ 69 /* */ 70 /* Return the horizontal metrics in font units for a given glyph. */ 71 /* */ 72 FT_LOCAL_DEF( void ) 73 TT_Get_HMetrics( TT_Face face, 74 FT_UInt idx, 75 FT_Short* lsb, 76 FT_UShort* aw ) 77 { 78 ( (SFNT_Service)face->sfnt )->get_metrics( face, 0, idx, lsb, aw ); 79 80 FT_TRACE5(( " advance width (font units): %d\n", *aw )); 81 FT_TRACE5(( " left side bearing (font units): %d\n", *lsb )); 82 } 83 84 85 /*************************************************************************/ 86 /* */ 87 /* Return the vertical metrics in font units for a given glyph. */ 88 /* Greg Hitchcock from Microsoft told us that if there were no `vmtx' */ 89 /* table, typoAscender/Descender from the `OS/2' table would be used */ 90 /* instead, and if there were no `OS/2' table, use ascender/descender */ 91 /* from the `hhea' table. But that is not what Microsoft's rasterizer */ 92 /* apparently does: It uses the ppem value as the advance height, and */ 93 /* sets the top side bearing to be zero. */ 94 /* */ 95 FT_LOCAL_DEF( void ) 96 TT_Get_VMetrics( TT_Face face, 97 FT_UInt idx, 98 FT_Short* tsb, 99 FT_UShort* ah ) 100 { 101 if ( face->vertical_info ) 102 ( (SFNT_Service)face->sfnt )->get_metrics( face, 1, idx, tsb, ah ); 103 104#if 1 /* Empirically determined, at variance with what MS said */ 105 106 else 107 { 108 *tsb = 0; 109 *ah = face->root.units_per_EM; 110 } 111 112#else /* This is what MS said to do. It isn't what they do, however. */ 113 114 else if ( face->os2.version != 0xFFFFU ) 115 { 116 *tsb = face->os2.sTypoAscender; 117 *ah = face->os2.sTypoAscender - face->os2.sTypoDescender; 118 } 119 else 120 { 121 *tsb = face->horizontal.Ascender; 122 *ah = face->horizontal.Ascender - face->horizontal.Descender; 123 } 124 125#endif 126 127 FT_TRACE5(( " advance height (font units): %d\n", *ah )); 128 FT_TRACE5(( " top side bearing (font units): %d\n", *tsb )); 129 } 130 131 132 static void 133 tt_get_metrics( TT_Loader loader, 134 FT_UInt glyph_index ) 135 { 136 TT_Face face = (TT_Face)loader->face; 137 138 FT_Short left_bearing = 0, top_bearing = 0; 139 FT_UShort advance_width = 0, advance_height = 0; 140 141 142 TT_Get_HMetrics( face, glyph_index, 143 &left_bearing, 144 &advance_width ); 145 TT_Get_VMetrics( face, glyph_index, 146 &top_bearing, 147 &advance_height ); 148 149 loader->left_bearing = left_bearing; 150 loader->advance = advance_width; 151 loader->top_bearing = top_bearing; 152 loader->vadvance = advance_height; 153 154#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 155 if ( loader->exec ) 156 loader->exec->sph_tweak_flags = 0; 157 158 /* this may not be the right place for this, but it works */ 159 if ( loader->exec && loader->exec->ignore_x_mode ) 160 sph_set_tweaks( loader, glyph_index ); 161#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 162 163 if ( !loader->linear_def ) 164 { 165 loader->linear_def = 1; 166 loader->linear = advance_width; 167 } 168 } 169 170 171#ifdef FT_CONFIG_OPTION_INCREMENTAL 172 173 static void 174 tt_get_metrics_incr_overrides( TT_Loader loader, 175 FT_UInt glyph_index ) 176 { 177 TT_Face face = (TT_Face)loader->face; 178 179 FT_Short left_bearing = 0, top_bearing = 0; 180 FT_UShort advance_width = 0, advance_height = 0; 181 182 183 /* If this is an incrementally loaded font check whether there are */ 184 /* overriding metrics for this glyph. */ 185 if ( face->root.internal->incremental_interface && 186 face->root.internal->incremental_interface->funcs->get_glyph_metrics ) 187 { 188 FT_Incremental_MetricsRec metrics; 189 FT_Error error; 190 191 192 metrics.bearing_x = loader->left_bearing; 193 metrics.bearing_y = 0; 194 metrics.advance = loader->advance; 195 metrics.advance_v = 0; 196 197 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 198 face->root.internal->incremental_interface->object, 199 glyph_index, FALSE, &metrics ); 200 if ( error ) 201 goto Exit; 202 203 left_bearing = (FT_Short)metrics.bearing_x; 204 advance_width = (FT_UShort)metrics.advance; 205 206#if 0 207 208 /* GWW: Do I do the same for vertical metrics? */ 209 metrics.bearing_x = 0; 210 metrics.bearing_y = loader->top_bearing; 211 metrics.advance = loader->vadvance; 212 213 error = face->root.internal->incremental_interface->funcs->get_glyph_metrics( 214 face->root.internal->incremental_interface->object, 215 glyph_index, TRUE, &metrics ); 216 if ( error ) 217 goto Exit; 218 219 top_bearing = (FT_Short)metrics.bearing_y; 220 advance_height = (FT_UShort)metrics.advance; 221 222#endif /* 0 */ 223 224 loader->left_bearing = left_bearing; 225 loader->advance = advance_width; 226 loader->top_bearing = top_bearing; 227 loader->vadvance = advance_height; 228 229 if ( !loader->linear_def ) 230 { 231 loader->linear_def = 1; 232 loader->linear = advance_width; 233 } 234 } 235 236 Exit: 237 return; 238 } 239 240#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 241 242 243 /*************************************************************************/ 244 /* */ 245 /* Translates an array of coordinates. */ 246 /* */ 247 static void 248 translate_array( FT_UInt n, 249 FT_Vector* coords, 250 FT_Pos delta_x, 251 FT_Pos delta_y ) 252 { 253 FT_UInt k; 254 255 256 if ( delta_x ) 257 for ( k = 0; k < n; k++ ) 258 coords[k].x += delta_x; 259 260 if ( delta_y ) 261 for ( k = 0; k < n; k++ ) 262 coords[k].y += delta_y; 263 } 264 265 266 /*************************************************************************/ 267 /* */ 268 /* The following functions are used by default with TrueType fonts. */ 269 /* However, they can be replaced by alternatives if we need to support */ 270 /* TrueType-compressed formats (like MicroType) in the future. */ 271 /* */ 272 /*************************************************************************/ 273 274 FT_CALLBACK_DEF( FT_Error ) 275 TT_Access_Glyph_Frame( TT_Loader loader, 276 FT_UInt glyph_index, 277 FT_ULong offset, 278 FT_UInt byte_count ) 279 { 280 FT_Error error; 281 FT_Stream stream = loader->stream; 282 283 /* for non-debug mode */ 284 FT_UNUSED( glyph_index ); 285 286 287 FT_TRACE4(( "Glyph %ld\n", glyph_index )); 288 289 /* the following line sets the `error' variable through macros! */ 290 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) 291 return error; 292 293 loader->cursor = stream->cursor; 294 loader->limit = stream->limit; 295 296 return TT_Err_Ok; 297 } 298 299 300 FT_CALLBACK_DEF( void ) 301 TT_Forget_Glyph_Frame( TT_Loader loader ) 302 { 303 FT_Stream stream = loader->stream; 304 305 306 FT_FRAME_EXIT(); 307 } 308 309 310 FT_CALLBACK_DEF( FT_Error ) 311 TT_Load_Glyph_Header( TT_Loader loader ) 312 { 313 FT_Byte* p = loader->cursor; 314 FT_Byte* limit = loader->limit; 315 316 317 if ( p + 10 > limit ) 318 return TT_Err_Invalid_Outline; 319 320 loader->n_contours = FT_NEXT_SHORT( p ); 321 322 loader->bbox.xMin = FT_NEXT_SHORT( p ); 323 loader->bbox.yMin = FT_NEXT_SHORT( p ); 324 loader->bbox.xMax = FT_NEXT_SHORT( p ); 325 loader->bbox.yMax = FT_NEXT_SHORT( p ); 326 327 FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); 328 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, 329 loader->bbox.xMax )); 330 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, 331 loader->bbox.yMax )); 332 loader->cursor = p; 333 334 return TT_Err_Ok; 335 } 336 337 338 FT_CALLBACK_DEF( FT_Error ) 339 TT_Load_Simple_Glyph( TT_Loader load ) 340 { 341 FT_Error error; 342 FT_Byte* p = load->cursor; 343 FT_Byte* limit = load->limit; 344 FT_GlyphLoader gloader = load->gloader; 345 FT_Int n_contours = load->n_contours; 346 FT_Outline* outline; 347 TT_Face face = (TT_Face)load->face; 348 FT_UShort n_ins; 349 FT_Int n_points; 350 351 FT_Byte *flag, *flag_limit; 352 FT_Byte c, count; 353 FT_Vector *vec, *vec_limit; 354 FT_Pos x; 355 FT_Short *cont, *cont_limit, prev_cont; 356 FT_Int xy_size = 0; 357 358 359 /* check that we can add the contours to the glyph */ 360 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, 0, n_contours ); 361 if ( error ) 362 goto Fail; 363 364 /* reading the contours' endpoints & number of points */ 365 cont = gloader->current.outline.contours; 366 cont_limit = cont + n_contours; 367 368 /* check space for contours array + instructions count */ 369 if ( n_contours >= 0xFFF || p + ( n_contours + 1 ) * 2 > limit ) 370 goto Invalid_Outline; 371 372 prev_cont = FT_NEXT_SHORT( p ); 373 374 if ( n_contours > 0 ) 375 cont[0] = prev_cont; 376 377 if ( prev_cont < 0 ) 378 goto Invalid_Outline; 379 380 for ( cont++; cont < cont_limit; cont++ ) 381 { 382 cont[0] = FT_NEXT_SHORT( p ); 383 if ( cont[0] <= prev_cont ) 384 { 385 /* unordered contours: this is invalid */ 386 goto Invalid_Outline; 387 } 388 prev_cont = cont[0]; 389 } 390 391 n_points = 0; 392 if ( n_contours > 0 ) 393 { 394 n_points = cont[-1] + 1; 395 if ( n_points < 0 ) 396 goto Invalid_Outline; 397 } 398 399 /* note that we will add four phantom points later */ 400 error = FT_GLYPHLOADER_CHECK_POINTS( gloader, n_points + 4, 0 ); 401 if ( error ) 402 goto Fail; 403 404 /* reading the bytecode instructions */ 405 load->glyph->control_len = 0; 406 load->glyph->control_data = 0; 407 408 if ( p + 2 > limit ) 409 goto Invalid_Outline; 410 411 n_ins = FT_NEXT_USHORT( p ); 412 413 FT_TRACE5(( " Instructions size: %u\n", n_ins )); 414 415 if ( n_ins > face->max_profile.maxSizeOfInstructions ) 416 { 417 FT_TRACE0(( "TT_Load_Simple_Glyph: too many instructions (%d)\n", 418 n_ins )); 419 error = TT_Err_Too_Many_Hints; 420 goto Fail; 421 } 422 423 if ( ( limit - p ) < n_ins ) 424 { 425 FT_TRACE0(( "TT_Load_Simple_Glyph: instruction count mismatch\n" )); 426 error = TT_Err_Too_Many_Hints; 427 goto Fail; 428 } 429 430#ifdef TT_USE_BYTECODE_INTERPRETER 431 432 if ( IS_HINTED( load->load_flags ) ) 433 { 434 load->glyph->control_len = n_ins; 435 load->glyph->control_data = load->exec->glyphIns; 436 437 FT_MEM_COPY( load->exec->glyphIns, p, (FT_Long)n_ins ); 438 } 439 440#endif /* TT_USE_BYTECODE_INTERPRETER */ 441 442 p += n_ins; 443 444 outline = &gloader->current.outline; 445 446 /* reading the point tags */ 447 flag = (FT_Byte*)outline->tags; 448 flag_limit = flag + n_points; 449 450 FT_ASSERT( flag != NULL ); 451 452 while ( flag < flag_limit ) 453 { 454 if ( p + 1 > limit ) 455 goto Invalid_Outline; 456 457 *flag++ = c = FT_NEXT_BYTE( p ); 458 if ( c & 8 ) 459 { 460 if ( p + 1 > limit ) 461 goto Invalid_Outline; 462 463 count = FT_NEXT_BYTE( p ); 464 if ( flag + (FT_Int)count > flag_limit ) 465 goto Invalid_Outline; 466 467 for ( ; count > 0; count-- ) 468 *flag++ = c; 469 } 470 } 471 472 /* reading the X coordinates */ 473 474 vec = outline->points; 475 vec_limit = vec + n_points; 476 flag = (FT_Byte*)outline->tags; 477 x = 0; 478 479 if ( p + xy_size > limit ) 480 goto Invalid_Outline; 481 482 for ( ; vec < vec_limit; vec++, flag++ ) 483 { 484 FT_Pos y = 0; 485 FT_Byte f = *flag; 486 487 488 if ( f & 2 ) 489 { 490 if ( p + 1 > limit ) 491 goto Invalid_Outline; 492 493 y = (FT_Pos)FT_NEXT_BYTE( p ); 494 if ( ( f & 16 ) == 0 ) 495 y = -y; 496 } 497 else if ( ( f & 16 ) == 0 ) 498 { 499 if ( p + 2 > limit ) 500 goto Invalid_Outline; 501 502 y = (FT_Pos)FT_NEXT_SHORT( p ); 503 } 504 505 x += y; 506 vec->x = x; 507 /* the cast is for stupid compilers */ 508 *flag = (FT_Byte)( f & ~( 2 | 16 ) ); 509 } 510 511 /* reading the Y coordinates */ 512 513 vec = gloader->current.outline.points; 514 vec_limit = vec + n_points; 515 flag = (FT_Byte*)outline->tags; 516 x = 0; 517 518 for ( ; vec < vec_limit; vec++, flag++ ) 519 { 520 FT_Pos y = 0; 521 FT_Byte f = *flag; 522 523 524 if ( f & 4 ) 525 { 526 if ( p + 1 > limit ) 527 goto Invalid_Outline; 528 529 y = (FT_Pos)FT_NEXT_BYTE( p ); 530 if ( ( f & 32 ) == 0 ) 531 y = -y; 532 } 533 else if ( ( f & 32 ) == 0 ) 534 { 535 if ( p + 2 > limit ) 536 goto Invalid_Outline; 537 538 y = (FT_Pos)FT_NEXT_SHORT( p ); 539 } 540 541 x += y; 542 vec->y = x; 543 /* the cast is for stupid compilers */ 544 *flag = (FT_Byte)( f & FT_CURVE_TAG_ON ); 545 } 546 547 outline->n_points = (FT_UShort)n_points; 548 outline->n_contours = (FT_Short) n_contours; 549 550 load->cursor = p; 551 552 Fail: 553 return error; 554 555 Invalid_Outline: 556 error = TT_Err_Invalid_Outline; 557 goto Fail; 558 } 559 560 561 FT_CALLBACK_DEF( FT_Error ) 562 TT_Load_Composite_Glyph( TT_Loader loader ) 563 { 564 FT_Error error; 565 FT_Byte* p = loader->cursor; 566 FT_Byte* limit = loader->limit; 567 FT_GlyphLoader gloader = loader->gloader; 568 FT_SubGlyph subglyph; 569 FT_UInt num_subglyphs; 570 571 572 num_subglyphs = 0; 573 574 do 575 { 576 FT_Fixed xx, xy, yy, yx; 577 FT_UInt count; 578 579 580 /* check that we can load a new subglyph */ 581 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); 582 if ( error ) 583 goto Fail; 584 585 /* check space */ 586 if ( p + 4 > limit ) 587 goto Invalid_Composite; 588 589 subglyph = gloader->current.subglyphs + num_subglyphs; 590 591 subglyph->arg1 = subglyph->arg2 = 0; 592 593 subglyph->flags = FT_NEXT_USHORT( p ); 594 subglyph->index = FT_NEXT_USHORT( p ); 595 596 /* check space */ 597 count = 2; 598 if ( subglyph->flags & ARGS_ARE_WORDS ) 599 count += 2; 600 if ( subglyph->flags & WE_HAVE_A_SCALE ) 601 count += 2; 602 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 603 count += 4; 604 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 605 count += 8; 606 607 if ( p + count > limit ) 608 goto Invalid_Composite; 609 610 /* read arguments */ 611 if ( subglyph->flags & ARGS_ARE_WORDS ) 612 { 613 subglyph->arg1 = FT_NEXT_SHORT( p ); 614 subglyph->arg2 = FT_NEXT_SHORT( p ); 615 } 616 else 617 { 618 subglyph->arg1 = FT_NEXT_CHAR( p ); 619 subglyph->arg2 = FT_NEXT_CHAR( p ); 620 } 621 622 /* read transform */ 623 xx = yy = 0x10000L; 624 xy = yx = 0; 625 626 if ( subglyph->flags & WE_HAVE_A_SCALE ) 627 { 628 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 629 yy = xx; 630 } 631 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 632 { 633 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 634 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 635 } 636 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 637 { 638 xx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 639 yx = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 640 xy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 641 yy = (FT_Fixed)FT_NEXT_SHORT( p ) << 2; 642 } 643 644 subglyph->transform.xx = xx; 645 subglyph->transform.xy = xy; 646 subglyph->transform.yx = yx; 647 subglyph->transform.yy = yy; 648 649 num_subglyphs++; 650 651 } while ( subglyph->flags & MORE_COMPONENTS ); 652 653 gloader->current.num_subglyphs = num_subglyphs; 654 655#ifdef TT_USE_BYTECODE_INTERPRETER 656 657 { 658 FT_Stream stream = loader->stream; 659 660 661 /* we must undo the FT_FRAME_ENTER in order to point */ 662 /* to the composite instructions, if we find some. */ 663 /* We will process them later. */ 664 /* */ 665 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + 666 p - limit ); 667 } 668 669#endif 670 671 loader->cursor = p; 672 673 Fail: 674 return error; 675 676 Invalid_Composite: 677 error = TT_Err_Invalid_Composite; 678 goto Fail; 679 } 680 681 682 FT_LOCAL_DEF( void ) 683 TT_Init_Glyph_Loading( TT_Face face ) 684 { 685 face->access_glyph_frame = TT_Access_Glyph_Frame; 686 face->read_glyph_header = TT_Load_Glyph_Header; 687 face->read_simple_glyph = TT_Load_Simple_Glyph; 688 face->read_composite_glyph = TT_Load_Composite_Glyph; 689 face->forget_glyph_frame = TT_Forget_Glyph_Frame; 690 } 691 692 693 static void 694 tt_prepare_zone( TT_GlyphZone zone, 695 FT_GlyphLoad load, 696 FT_UInt start_point, 697 FT_UInt start_contour ) 698 { 699 zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); 700 zone->n_contours = (FT_Short) ( load->outline.n_contours - 701 start_contour ); 702 zone->org = load->extra_points + start_point; 703 zone->cur = load->outline.points + start_point; 704 zone->orus = load->extra_points2 + start_point; 705 zone->tags = (FT_Byte*)load->outline.tags + start_point; 706 zone->contours = (FT_UShort*)load->outline.contours + start_contour; 707 zone->first_point = (FT_UShort)start_point; 708 } 709 710 711 /*************************************************************************/ 712 /* */ 713 /* <Function> */ 714 /* TT_Hint_Glyph */ 715 /* */ 716 /* <Description> */ 717 /* Hint the glyph using the zone prepared by the caller. Note that */ 718 /* the zone is supposed to include four phantom points. */ 719 /* */ 720 static FT_Error 721 TT_Hint_Glyph( TT_Loader loader, 722 FT_Bool is_composite ) 723 { 724 TT_GlyphZone zone = &loader->zone; 725 FT_Pos origin; 726 727#ifdef TT_USE_BYTECODE_INTERPRETER 728 FT_UInt n_ins; 729#else 730 FT_UNUSED( is_composite ); 731#endif 732 733 734#ifdef TT_USE_BYTECODE_INTERPRETER 735 if ( loader->glyph->control_len > 0xFFFFL ) 736 { 737 FT_TRACE1(( "TT_Hint_Glyph: too long instructions " )); 738 FT_TRACE1(( "(0x%lx byte) is truncated\n", 739 loader->glyph->control_len )); 740 } 741 n_ins = (FT_UInt)( loader->glyph->control_len ); 742#endif 743 744 origin = zone->cur[zone->n_points - 4].x; 745 origin = FT_PIX_ROUND( origin ) - origin; 746 if ( origin ) 747 translate_array( zone->n_points, zone->cur, origin, 0 ); 748 749#ifdef TT_USE_BYTECODE_INTERPRETER 750 /* save original point position in org */ 751 if ( n_ins > 0 ) 752 FT_ARRAY_COPY( zone->org, zone->cur, zone->n_points ); 753 754 /* Reset graphics state. */ 755 loader->exec->GS = ((TT_Size)loader->size)->GS; 756 757 /* XXX: UNDOCUMENTED! Hinting instructions of a composite glyph */ 758 /* completely refer to the (already) hinted subglyphs. */ 759 if ( is_composite ) 760 { 761 loader->exec->metrics.x_scale = 1 << 16; 762 loader->exec->metrics.y_scale = 1 << 16; 763 764 FT_ARRAY_COPY( zone->orus, zone->cur, zone->n_points ); 765 } 766 else 767 { 768 loader->exec->metrics.x_scale = 769 ((TT_Size)loader->size)->metrics.x_scale; 770 loader->exec->metrics.y_scale = 771 ((TT_Size)loader->size)->metrics.y_scale; 772 } 773#endif 774 775 /* round pp2 and pp4 */ 776 zone->cur[zone->n_points - 3].x = 777 FT_PIX_ROUND( zone->cur[zone->n_points - 3].x ); 778 zone->cur[zone->n_points - 1].y = 779 FT_PIX_ROUND( zone->cur[zone->n_points - 1].y ); 780 781#ifdef TT_USE_BYTECODE_INTERPRETER 782 783 if ( n_ins > 0 ) 784 { 785 FT_Bool debug; 786 FT_Error error; 787 788 FT_GlyphLoader gloader = loader->gloader; 789 FT_Outline current_outline = gloader->current.outline; 790 791 792 error = TT_Set_CodeRange( loader->exec, tt_coderange_glyph, 793 loader->exec->glyphIns, n_ins ); 794 if ( error ) 795 return error; 796 797 loader->exec->is_composite = is_composite; 798 loader->exec->pts = *zone; 799 800 debug = FT_BOOL( !( loader->load_flags & FT_LOAD_NO_SCALE ) && 801 ((TT_Size)loader->size)->debug ); 802 803 error = TT_Run_Context( loader->exec, debug ); 804 if ( error && loader->exec->pedantic_hinting ) 805 return error; 806 807 /* store drop-out mode in bits 5-7; set bit 2 also as a marker */ 808 current_outline.tags[0] |= 809 ( loader->exec->GS.scan_type << 5 ) | FT_CURVE_TAG_HAS_SCANMODE; 810 } 811 812#endif 813 814 /* save glyph phantom points */ 815 if ( !loader->preserve_pps ) 816 { 817 loader->pp1 = zone->cur[zone->n_points - 4]; 818 loader->pp2 = zone->cur[zone->n_points - 3]; 819 loader->pp3 = zone->cur[zone->n_points - 2]; 820 loader->pp4 = zone->cur[zone->n_points - 1]; 821 } 822 823#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 824 if ( loader->exec->sph_tweak_flags & SPH_TWEAK_DEEMBOLDEN ) 825 FT_Outline_EmboldenXY( &loader->gloader->current.outline, -24, 0 ); 826 827 else if ( loader->exec->sph_tweak_flags & SPH_TWEAK_EMBOLDEN ) 828 FT_Outline_EmboldenXY( &loader->gloader->current.outline, 24, 0 ); 829#endif 830 return TT_Err_Ok; 831 } 832 833 834 /*************************************************************************/ 835 /* */ 836 /* <Function> */ 837 /* TT_Process_Simple_Glyph */ 838 /* */ 839 /* <Description> */ 840 /* Once a simple glyph has been loaded, it needs to be processed. */ 841 /* Usually, this means scaling and hinting through bytecode */ 842 /* interpretation. */ 843 /* */ 844 static FT_Error 845 TT_Process_Simple_Glyph( TT_Loader loader ) 846 { 847 FT_GlyphLoader gloader = loader->gloader; 848 FT_Error error = TT_Err_Ok; 849 FT_Outline* outline; 850 FT_Int n_points; 851 852#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 853 TT_Face face = (TT_Face)loader->face; 854 FT_String* family = face->root.family_name; 855 FT_Int ppem = loader->size->metrics.x_ppem; 856 FT_String* style = face->root.style_name; 857 FT_Int x_scale_factor = 1000; 858#endif 859 860 861 outline = &gloader->current.outline; 862 n_points = outline->n_points; 863 864 /* set phantom points */ 865 866 outline->points[n_points ] = loader->pp1; 867 outline->points[n_points + 1] = loader->pp2; 868 outline->points[n_points + 2] = loader->pp3; 869 outline->points[n_points + 3] = loader->pp4; 870 871 outline->tags[n_points ] = 0; 872 outline->tags[n_points + 1] = 0; 873 outline->tags[n_points + 2] = 0; 874 outline->tags[n_points + 3] = 0; 875 876 n_points += 4; 877 878#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 879 880 if ( ((TT_Face)loader->face)->doblend ) 881 { 882 /* Deltas apply to the unscaled data. */ 883 FT_Vector* deltas; 884 FT_Memory memory = loader->face->memory; 885 FT_Int i; 886 887 888 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), 889 loader->glyph_index, 890 &deltas, 891 n_points ); 892 if ( error ) 893 return error; 894 895 for ( i = 0; i < n_points; ++i ) 896 { 897 outline->points[i].x += deltas[i].x; 898 outline->points[i].y += deltas[i].y; 899 } 900 901 FT_FREE( deltas ); 902 } 903 904#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 905 906 if ( IS_HINTED( loader->load_flags ) ) 907 { 908 tt_prepare_zone( &loader->zone, &gloader->current, 0, 0 ); 909 910 FT_ARRAY_COPY( loader->zone.orus, loader->zone.cur, 911 loader->zone.n_points + 4 ); 912 } 913 914#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 915 /* scale, but only if enabled and only if TT hinting is being used */ 916 if ( IS_HINTED( loader->load_flags ) ) 917 x_scale_factor = scale_test_tweak( face, family, ppem, style, 918 loader->glyph_index, 919 sph_X_SCALING_Rules, 920 SPH_X_SCALING_RULES_SIZE ); 921 /* scale the glyph */ 922 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 || 923 x_scale_factor != 1000 ) 924 { 925 FT_Vector* vec = outline->points; 926 FT_Vector* limit = outline->points + n_points; 927 FT_Fixed x_scale = FT_MulDiv( 928 ((TT_Size)loader->size)->metrics.x_scale, 929 x_scale_factor, 1000 ); 930 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; 931 932 933 /* compensate for any scaling by de/emboldening; */ 934 /* the amount was determined via experimentation */ 935 if ( x_scale_factor != 1000 && ppem > 11 ) 936 FT_Outline_EmboldenXY( outline, 937 FT_MulFix( 1280 * ppem, 938 1000 - x_scale_factor ), 939 0 ); 940#else 941 /* scale the glyph */ 942 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 943 { 944 FT_Vector* vec = outline->points; 945 FT_Vector* limit = outline->points + n_points; 946 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; 947 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; 948#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 949 950 951 for ( ; vec < limit; vec++ ) 952 { 953 vec->x = FT_MulFix( vec->x, x_scale ); 954 vec->y = FT_MulFix( vec->y, y_scale ); 955 } 956 957 loader->pp1 = outline->points[n_points - 4]; 958 loader->pp2 = outline->points[n_points - 3]; 959 loader->pp3 = outline->points[n_points - 2]; 960 loader->pp4 = outline->points[n_points - 1]; 961 } 962 963 if ( IS_HINTED( loader->load_flags ) ) 964 { 965 loader->zone.n_points += 4; 966 967 error = TT_Hint_Glyph( loader, 0 ); 968 } 969 970 return error; 971 } 972 973 974 /*************************************************************************/ 975 /* */ 976 /* <Function> */ 977 /* TT_Process_Composite_Component */ 978 /* */ 979 /* <Description> */ 980 /* Once a composite component has been loaded, it needs to be */ 981 /* processed. Usually, this means transforming and translating. */ 982 /* */ 983 static FT_Error 984 TT_Process_Composite_Component( TT_Loader loader, 985 FT_SubGlyph subglyph, 986 FT_UInt start_point, 987 FT_UInt num_base_points ) 988 { 989 FT_GlyphLoader gloader = loader->gloader; 990 FT_Vector* base_vec = gloader->base.outline.points; 991 FT_UInt num_points = gloader->base.outline.n_points; 992 FT_Bool have_scale; 993 FT_Pos x, y; 994 995 996 have_scale = FT_BOOL( subglyph->flags & ( WE_HAVE_A_SCALE | 997 WE_HAVE_AN_XY_SCALE | 998 WE_HAVE_A_2X2 ) ); 999 1000 /* perform the transform required for this subglyph */ 1001 if ( have_scale ) 1002 { 1003 FT_UInt i; 1004 1005 1006 for ( i = num_base_points; i < num_points; i++ ) 1007 FT_Vector_Transform( base_vec + i, &subglyph->transform ); 1008 } 1009 1010 /* get offset */ 1011 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) 1012 { 1013 FT_UInt k = subglyph->arg1; 1014 FT_UInt l = subglyph->arg2; 1015 FT_Vector* p1; 1016 FT_Vector* p2; 1017 1018 1019 /* match l-th point of the newly loaded component to the k-th point */ 1020 /* of the previously loaded components. */ 1021 1022 /* change to the point numbers used by our outline */ 1023 k += start_point; 1024 l += num_base_points; 1025 if ( k >= num_base_points || 1026 l >= num_points ) 1027 return TT_Err_Invalid_Composite; 1028 1029 p1 = gloader->base.outline.points + k; 1030 p2 = gloader->base.outline.points + l; 1031 1032 x = p1->x - p2->x; 1033 y = p1->y - p2->y; 1034 } 1035 else 1036 { 1037 x = subglyph->arg1; 1038 y = subglyph->arg2; 1039 1040 if ( !x && !y ) 1041 return TT_Err_Ok; 1042 1043 /* Use a default value dependent on */ 1044 /* TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED. This is useful for old TT */ 1045 /* fonts which don't set the xxx_COMPONENT_OFFSET bit. */ 1046 1047 if ( have_scale && 1048#ifdef TT_CONFIG_OPTION_COMPONENT_OFFSET_SCALED 1049 !( subglyph->flags & UNSCALED_COMPONENT_OFFSET ) ) 1050#else 1051 ( subglyph->flags & SCALED_COMPONENT_OFFSET ) ) 1052#endif 1053 { 1054 1055#if 0 1056 1057 /*************************************************************************/ 1058 /* */ 1059 /* This algorithm is what Apple documents. But it doesn't work. */ 1060 /* */ 1061 int a = subglyph->transform.xx > 0 ? subglyph->transform.xx 1062 : -subglyph->transform.xx; 1063 int b = subglyph->transform.yx > 0 ? subglyph->transform.yx 1064 : -subglyph->transform.yx; 1065 int c = subglyph->transform.xy > 0 ? subglyph->transform.xy 1066 : -subglyph->transform.xy; 1067 int d = subglyph->transform.yy > 0 ? subglyph->transform.yy 1068 : -subglyph->transform.yy; 1069 int m = a > b ? a : b; 1070 int n = c > d ? c : d; 1071 1072 1073 if ( a - b <= 33 && a - b >= -33 ) 1074 m *= 2; 1075 if ( c - d <= 33 && c - d >= -33 ) 1076 n *= 2; 1077 x = FT_MulFix( x, m ); 1078 y = FT_MulFix( y, n ); 1079 1080#else /* 0 */ 1081 1082 /*************************************************************************/ 1083 /* */ 1084 /* This algorithm is a guess and works much better than the above. */ 1085 /* */ 1086 FT_Fixed mac_xscale = FT_Hypot( subglyph->transform.xx, 1087 subglyph->transform.xy ); 1088 FT_Fixed mac_yscale = FT_Hypot( subglyph->transform.yy, 1089 subglyph->transform.yx ); 1090 1091 1092 x = FT_MulFix( x, mac_xscale ); 1093 y = FT_MulFix( y, mac_yscale ); 1094 1095#endif /* 0 */ 1096 1097 } 1098 1099 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1100 { 1101 FT_Fixed x_scale = ((TT_Size)loader->size)->metrics.x_scale; 1102 FT_Fixed y_scale = ((TT_Size)loader->size)->metrics.y_scale; 1103 1104 1105 x = FT_MulFix( x, x_scale ); 1106 y = FT_MulFix( y, y_scale ); 1107 1108 if ( subglyph->flags & ROUND_XY_TO_GRID ) 1109 { 1110 x = FT_PIX_ROUND( x ); 1111 y = FT_PIX_ROUND( y ); 1112 } 1113 } 1114 } 1115 1116 if ( x || y ) 1117 translate_array( num_points - num_base_points, 1118 base_vec + num_base_points, 1119 x, y ); 1120 1121 return TT_Err_Ok; 1122 } 1123 1124 1125 /*************************************************************************/ 1126 /* */ 1127 /* <Function> */ 1128 /* TT_Process_Composite_Glyph */ 1129 /* */ 1130 /* <Description> */ 1131 /* This is slightly different from TT_Process_Simple_Glyph, in that */ 1132 /* its sole purpose is to hint the glyph. Thus this function is */ 1133 /* only available when bytecode interpreter is enabled. */ 1134 /* */ 1135 static FT_Error 1136 TT_Process_Composite_Glyph( TT_Loader loader, 1137 FT_UInt start_point, 1138 FT_UInt start_contour ) 1139 { 1140 FT_Error error; 1141 FT_Outline* outline; 1142 FT_UInt i; 1143 1144 1145 outline = &loader->gloader->base.outline; 1146 1147 /* make room for phantom points */ 1148 error = FT_GLYPHLOADER_CHECK_POINTS( loader->gloader, 1149 outline->n_points + 4, 1150 0 ); 1151 if ( error ) 1152 return error; 1153 1154 outline->points[outline->n_points ] = loader->pp1; 1155 outline->points[outline->n_points + 1] = loader->pp2; 1156 outline->points[outline->n_points + 2] = loader->pp3; 1157 outline->points[outline->n_points + 3] = loader->pp4; 1158 1159 outline->tags[outline->n_points ] = 0; 1160 outline->tags[outline->n_points + 1] = 0; 1161 outline->tags[outline->n_points + 2] = 0; 1162 outline->tags[outline->n_points + 3] = 0; 1163 1164#ifdef TT_USE_BYTECODE_INTERPRETER 1165 1166 { 1167 FT_Stream stream = loader->stream; 1168 FT_UShort n_ins, max_ins; 1169 FT_ULong tmp; 1170 1171 1172 /* TT_Load_Composite_Glyph only gives us the offset of instructions */ 1173 /* so we read them here */ 1174 if ( FT_STREAM_SEEK( loader->ins_pos ) || 1175 FT_READ_USHORT( n_ins ) ) 1176 return error; 1177 1178 FT_TRACE5(( " Instructions size = %d\n", n_ins )); 1179 1180 /* check it */ 1181 max_ins = ((TT_Face)loader->face)->max_profile.maxSizeOfInstructions; 1182 if ( n_ins > max_ins ) 1183 { 1184 /* acroread ignores this field, so we only do a rough safety check */ 1185 if ( (FT_Int)n_ins > loader->byte_len ) 1186 { 1187 FT_TRACE1(( "TT_Process_Composite_Glyph: " 1188 "too many instructions (%d) for glyph with length %d\n", 1189 n_ins, loader->byte_len )); 1190 return TT_Err_Too_Many_Hints; 1191 } 1192 1193 tmp = loader->exec->glyphSize; 1194 error = Update_Max( loader->exec->memory, 1195 &tmp, 1196 sizeof ( FT_Byte ), 1197 (void*)&loader->exec->glyphIns, 1198 n_ins ); 1199 loader->exec->glyphSize = (FT_UShort)tmp; 1200 if ( error ) 1201 return error; 1202 } 1203 else if ( n_ins == 0 ) 1204 return TT_Err_Ok; 1205 1206 if ( FT_STREAM_READ( loader->exec->glyphIns, n_ins ) ) 1207 return error; 1208 1209 loader->glyph->control_data = loader->exec->glyphIns; 1210 loader->glyph->control_len = n_ins; 1211 } 1212 1213#endif 1214 1215 tt_prepare_zone( &loader->zone, &loader->gloader->base, 1216 start_point, start_contour ); 1217 1218 /* Some points are likely touched during execution of */ 1219 /* instructions on components. So let's untouch them. */ 1220 for ( i = start_point; i < loader->zone.n_points; i++ ) 1221 loader->zone.tags[i] &= ~FT_CURVE_TAG_TOUCH_BOTH; 1222 1223 loader->zone.n_points += 4; 1224 1225 return TT_Hint_Glyph( loader, 1 ); 1226 } 1227 1228 1229 /* Calculate the four phantom points. */ 1230 /* The first two stand for horizontal origin and advance. */ 1231 /* The last two stand for vertical origin and advance. */ 1232#define TT_LOADER_SET_PP( loader ) \ 1233 do { \ 1234 (loader)->pp1.x = (loader)->bbox.xMin - (loader)->left_bearing; \ 1235 (loader)->pp1.y = 0; \ 1236 (loader)->pp2.x = (loader)->pp1.x + (loader)->advance; \ 1237 (loader)->pp2.y = 0; \ 1238 (loader)->pp3.x = 0; \ 1239 (loader)->pp3.y = (loader)->top_bearing + (loader)->bbox.yMax; \ 1240 (loader)->pp4.x = 0; \ 1241 (loader)->pp4.y = (loader)->pp3.y - (loader)->vadvance; \ 1242 } while ( 0 ) 1243 1244 1245 /*************************************************************************/ 1246 /* */ 1247 /* <Function> */ 1248 /* load_truetype_glyph */ 1249 /* */ 1250 /* <Description> */ 1251 /* Loads a given truetype glyph. Handles composites and uses a */ 1252 /* TT_Loader object. */ 1253 /* */ 1254 static FT_Error 1255 load_truetype_glyph( TT_Loader loader, 1256 FT_UInt glyph_index, 1257 FT_UInt recurse_count, 1258 FT_Bool header_only ) 1259 { 1260 FT_Error error = TT_Err_Ok; 1261 FT_Fixed x_scale, y_scale; 1262 FT_ULong offset; 1263 TT_Face face = (TT_Face)loader->face; 1264 FT_GlyphLoader gloader = loader->gloader; 1265 FT_Bool opened_frame = 0; 1266 1267#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1268 FT_Vector* deltas = NULL; 1269#endif 1270 1271#ifdef FT_CONFIG_OPTION_INCREMENTAL 1272 FT_StreamRec inc_stream; 1273 FT_Data glyph_data; 1274 FT_Bool glyph_data_loaded = 0; 1275#endif 1276 1277 1278 /* some fonts have an incorrect value of `maxComponentDepth', */ 1279 /* thus we allow depth 1 to catch the majority of them */ 1280 if ( recurse_count > 1 && 1281 recurse_count > face->max_profile.maxComponentDepth ) 1282 { 1283 error = TT_Err_Invalid_Composite; 1284 goto Exit; 1285 } 1286 1287 /* check glyph index */ 1288 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 1289 { 1290 error = TT_Err_Invalid_Glyph_Index; 1291 goto Exit; 1292 } 1293 1294 loader->glyph_index = glyph_index; 1295 1296 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1297 { 1298 x_scale = ((TT_Size)loader->size)->metrics.x_scale; 1299 y_scale = ((TT_Size)loader->size)->metrics.y_scale; 1300 } 1301 else 1302 { 1303 x_scale = 0x10000L; 1304 y_scale = 0x10000L; 1305 } 1306 1307 tt_get_metrics( loader, glyph_index ); 1308 1309 /* Set `offset' to the start of the glyph relative to the start of */ 1310 /* the `glyf' table, and `byte_len' to the length of the glyph in */ 1311 /* bytes. */ 1312 1313#ifdef FT_CONFIG_OPTION_INCREMENTAL 1314 1315 /* If we are loading glyph data via the incremental interface, set */ 1316 /* the loader stream to a memory stream reading the data returned */ 1317 /* by the interface. */ 1318 if ( face->root.internal->incremental_interface ) 1319 { 1320 error = face->root.internal->incremental_interface->funcs->get_glyph_data( 1321 face->root.internal->incremental_interface->object, 1322 glyph_index, &glyph_data ); 1323 if ( error ) 1324 goto Exit; 1325 1326 glyph_data_loaded = 1; 1327 offset = 0; 1328 loader->byte_len = glyph_data.length; 1329 1330 FT_MEM_ZERO( &inc_stream, sizeof ( inc_stream ) ); 1331 FT_Stream_OpenMemory( &inc_stream, 1332 glyph_data.pointer, glyph_data.length ); 1333 1334 loader->stream = &inc_stream; 1335 } 1336 else 1337 1338#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1339 1340 offset = tt_face_get_location( face, glyph_index, 1341 (FT_UInt*)&loader->byte_len ); 1342 1343 if ( loader->byte_len > 0 ) 1344 { 1345#ifdef FT_CONFIG_OPTION_INCREMENTAL 1346 /* for the incremental interface, `glyf_offset' is always zero */ 1347 if ( !loader->glyf_offset && 1348 !face->root.internal->incremental_interface ) 1349#else 1350 if ( !loader->glyf_offset ) 1351#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1352 { 1353 FT_TRACE2(( "no `glyf' table but non-zero `loca' entry\n" )); 1354 error = TT_Err_Invalid_Table; 1355 goto Exit; 1356 } 1357 1358 error = face->access_glyph_frame( loader, glyph_index, 1359 loader->glyf_offset + offset, 1360 loader->byte_len ); 1361 if ( error ) 1362 goto Exit; 1363 1364 opened_frame = 1; 1365 1366 /* read glyph header first */ 1367 error = face->read_glyph_header( loader ); 1368 if ( error || header_only ) 1369 goto Exit; 1370 } 1371 1372 if ( loader->byte_len == 0 || loader->n_contours == 0 ) 1373 { 1374 loader->bbox.xMin = 0; 1375 loader->bbox.xMax = 0; 1376 loader->bbox.yMin = 0; 1377 loader->bbox.yMax = 0; 1378 1379 if ( header_only ) 1380 goto Exit; 1381 1382 /* must initialize points before (possibly) overriding */ 1383 /* glyph metrics from the incremental interface */ 1384 TT_LOADER_SET_PP( loader ); 1385 1386#ifdef FT_CONFIG_OPTION_INCREMENTAL 1387 tt_get_metrics_incr_overrides( loader, glyph_index ); 1388#endif 1389 1390#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1391 1392 if ( ((TT_Face)(loader->face))->doblend ) 1393 { 1394 /* this must be done before scaling */ 1395 FT_Memory memory = loader->face->memory; 1396 1397 1398 error = TT_Vary_Get_Glyph_Deltas( (TT_Face)(loader->face), 1399 glyph_index, &deltas, 4 ); 1400 if ( error ) 1401 goto Exit; 1402 1403 loader->pp1.x += deltas[0].x; loader->pp1.y += deltas[0].y; 1404 loader->pp2.x += deltas[1].x; loader->pp2.y += deltas[1].y; 1405 loader->pp3.x += deltas[2].x; loader->pp3.y += deltas[2].y; 1406 loader->pp4.x += deltas[3].x; loader->pp4.y += deltas[3].y; 1407 1408 FT_FREE( deltas ); 1409 } 1410 1411#endif 1412 1413 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1414 { 1415 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1416 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1417 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1418 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1419 } 1420 1421 error = TT_Err_Ok; 1422 goto Exit; 1423 } 1424 1425 /* must initialize points before (possibly) overriding */ 1426 /* glyph metrics from the incremental interface */ 1427 TT_LOADER_SET_PP( loader ); 1428 1429#ifdef FT_CONFIG_OPTION_INCREMENTAL 1430 tt_get_metrics_incr_overrides( loader, glyph_index ); 1431#endif 1432 1433 /***********************************************************************/ 1434 /***********************************************************************/ 1435 /***********************************************************************/ 1436 1437 /* if it is a simple glyph, load it */ 1438 1439 if ( loader->n_contours > 0 ) 1440 { 1441 error = face->read_simple_glyph( loader ); 1442 if ( error ) 1443 goto Exit; 1444 1445 /* all data have been read */ 1446 face->forget_glyph_frame( loader ); 1447 opened_frame = 0; 1448 1449 error = TT_Process_Simple_Glyph( loader ); 1450 if ( error ) 1451 goto Exit; 1452 1453 FT_GlyphLoader_Add( gloader ); 1454 } 1455 1456 /***********************************************************************/ 1457 /***********************************************************************/ 1458 /***********************************************************************/ 1459 1460 /* otherwise, load a composite! */ 1461 else if ( loader->n_contours == -1 ) 1462 { 1463 FT_UInt start_point; 1464 FT_UInt start_contour; 1465 FT_ULong ins_pos; /* position of composite instructions, if any */ 1466 1467 1468 start_point = gloader->base.outline.n_points; 1469 start_contour = gloader->base.outline.n_contours; 1470 1471 /* for each subglyph, read composite header */ 1472 error = face->read_composite_glyph( loader ); 1473 if ( error ) 1474 goto Exit; 1475 1476 /* store the offset of instructions */ 1477 ins_pos = loader->ins_pos; 1478 1479 /* all data we need are read */ 1480 face->forget_glyph_frame( loader ); 1481 opened_frame = 0; 1482 1483#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1484 1485 if ( face->doblend ) 1486 { 1487 FT_Int i, limit; 1488 FT_SubGlyph subglyph; 1489 FT_Memory memory = face->root.memory; 1490 1491 1492 /* this provides additional offsets */ 1493 /* for each component's translation */ 1494 1495 if ( ( error = TT_Vary_Get_Glyph_Deltas( 1496 face, 1497 glyph_index, 1498 &deltas, 1499 gloader->current.num_subglyphs + 4 )) != 0 ) 1500 goto Exit; 1501 1502 subglyph = gloader->current.subglyphs + gloader->base.num_subglyphs; 1503 limit = gloader->current.num_subglyphs; 1504 1505 for ( i = 0; i < limit; ++i, ++subglyph ) 1506 { 1507 if ( subglyph->flags & ARGS_ARE_XY_VALUES ) 1508 { 1509 /* XXX: overflow check for subglyph->{arg1,arg2}. */ 1510 /* deltas[i].{x,y} must be within signed 16-bit, */ 1511 /* but the restriction of summed delta is not clear */ 1512 subglyph->arg1 += (FT_Int16)deltas[i].x; 1513 subglyph->arg2 += (FT_Int16)deltas[i].y; 1514 } 1515 } 1516 1517 loader->pp1.x += deltas[i + 0].x; loader->pp1.y += deltas[i + 0].y; 1518 loader->pp2.x += deltas[i + 1].x; loader->pp2.y += deltas[i + 1].y; 1519 loader->pp3.x += deltas[i + 2].x; loader->pp3.y += deltas[i + 2].y; 1520 loader->pp4.x += deltas[i + 3].x; loader->pp4.y += deltas[i + 3].y; 1521 1522 FT_FREE( deltas ); 1523 } 1524 1525#endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 1526 1527 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1528 { 1529 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 1530 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 1531 loader->pp3.y = FT_MulFix( loader->pp3.y, y_scale ); 1532 loader->pp4.y = FT_MulFix( loader->pp4.y, y_scale ); 1533 } 1534 1535 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 1536 /* `as is' in the glyph slot (the client application will be */ 1537 /* responsible for interpreting these data)... */ 1538 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 1539 { 1540 FT_GlyphLoader_Add( gloader ); 1541 loader->glyph->format = FT_GLYPH_FORMAT_COMPOSITE; 1542 1543 goto Exit; 1544 } 1545 1546 /*********************************************************************/ 1547 /*********************************************************************/ 1548 /*********************************************************************/ 1549 1550 { 1551 FT_UInt n, num_base_points; 1552 FT_SubGlyph subglyph = 0; 1553 1554 FT_UInt num_points = start_point; 1555 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 1556 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 1557 1558 FT_Stream old_stream = loader->stream; 1559 FT_Int old_byte_len = loader->byte_len; 1560 1561 1562 FT_GlyphLoader_Add( gloader ); 1563 1564 /* read each subglyph independently */ 1565 for ( n = 0; n < num_subglyphs; n++ ) 1566 { 1567 FT_Vector pp[4]; 1568 1569 1570 /* Each time we call load_truetype_glyph in this loop, the */ 1571 /* value of `gloader.base.subglyphs' can change due to table */ 1572 /* reallocations. We thus need to recompute the subglyph */ 1573 /* pointer on each iteration. */ 1574 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1575 1576 pp[0] = loader->pp1; 1577 pp[1] = loader->pp2; 1578 pp[2] = loader->pp3; 1579 pp[3] = loader->pp4; 1580 1581 num_base_points = gloader->base.outline.n_points; 1582 1583 error = load_truetype_glyph( loader, subglyph->index, 1584 recurse_count + 1, FALSE ); 1585 if ( error ) 1586 goto Exit; 1587 1588 /* restore subglyph pointer */ 1589 subglyph = gloader->base.subglyphs + num_base_subgs + n; 1590 1591 if ( !( subglyph->flags & USE_MY_METRICS ) ) 1592 { 1593 loader->pp1 = pp[0]; 1594 loader->pp2 = pp[1]; 1595 loader->pp3 = pp[2]; 1596 loader->pp4 = pp[3]; 1597 } 1598 1599 num_points = gloader->base.outline.n_points; 1600 1601 if ( num_points == num_base_points ) 1602 continue; 1603 1604 /* gloader->base.outline consists of three parts: */ 1605 /* 0 -(1)-> start_point -(2)-> num_base_points -(3)-> n_points. */ 1606 /* */ 1607 /* (1): exists from the beginning */ 1608 /* (2): components that have been loaded so far */ 1609 /* (3): the newly loaded component */ 1610 TT_Process_Composite_Component( loader, subglyph, start_point, 1611 num_base_points ); 1612 } 1613 1614 loader->stream = old_stream; 1615 loader->byte_len = old_byte_len; 1616 1617 /* process the glyph */ 1618 loader->ins_pos = ins_pos; 1619 if ( IS_HINTED( loader->load_flags ) && 1620 1621#ifdef TT_USE_BYTECODE_INTERPRETER 1622 1623 subglyph->flags & WE_HAVE_INSTR && 1624 1625#endif 1626 1627 num_points > start_point ) 1628 TT_Process_Composite_Glyph( loader, start_point, start_contour ); 1629 1630 } 1631 } 1632 else 1633 { 1634 /* invalid composite count (negative but not -1) */ 1635 error = TT_Err_Invalid_Outline; 1636 goto Exit; 1637 } 1638 1639 /***********************************************************************/ 1640 /***********************************************************************/ 1641 /***********************************************************************/ 1642 1643 Exit: 1644 1645 if ( opened_frame ) 1646 face->forget_glyph_frame( loader ); 1647 1648#ifdef FT_CONFIG_OPTION_INCREMENTAL 1649 1650 if ( glyph_data_loaded ) 1651 face->root.internal->incremental_interface->funcs->free_glyph_data( 1652 face->root.internal->incremental_interface->object, 1653 &glyph_data ); 1654 1655#endif 1656 1657 return error; 1658 } 1659 1660 1661 static FT_Error 1662 compute_glyph_metrics( TT_Loader loader, 1663 FT_UInt glyph_index ) 1664 { 1665 FT_BBox bbox; 1666 TT_Face face = (TT_Face)loader->face; 1667 FT_Fixed y_scale; 1668 TT_GlyphSlot glyph = loader->glyph; 1669 TT_Size size = (TT_Size)loader->size; 1670 1671 1672 y_scale = 0x10000L; 1673 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1674 y_scale = size->root.metrics.y_scale; 1675 1676 if ( glyph->format != FT_GLYPH_FORMAT_COMPOSITE ) 1677 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 1678 else 1679 bbox = loader->bbox; 1680 1681 /* get the device-independent horizontal advance; it is scaled later */ 1682 /* by the base layer. */ 1683 glyph->linearHoriAdvance = loader->linear; 1684 1685 glyph->metrics.horiBearingX = bbox.xMin; 1686 glyph->metrics.horiBearingY = bbox.yMax; 1687 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 1688 1689 /* adjust advance width to the value contained in the hdmx table */ 1690 if ( !face->postscript.isFixedPitch && 1691 IS_HINTED( loader->load_flags ) ) 1692 { 1693 FT_Byte* widthp; 1694 1695#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1696 FT_Bool ignore_x_mode; 1697 1698 1699 ignore_x_mode = FT_BOOL( FT_LOAD_TARGET_MODE( loader->load_flags ) != 1700 FT_RENDER_MODE_MONO ); 1701#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1702 1703 widthp = tt_face_get_device_metrics( face, 1704 size->root.metrics.x_ppem, 1705 glyph_index ); 1706 1707#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1708 if ( widthp && 1709 ( ( ignore_x_mode && loader->exec->compatible_widths ) || 1710 !ignore_x_mode || 1711 SPH_OPTION_BITMAP_WIDTHS ) ) 1712#else 1713 if ( widthp ) 1714#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1715 glyph->metrics.horiAdvance = *widthp << 6; 1716 } 1717 1718 /* set glyph dimensions */ 1719 glyph->metrics.width = bbox.xMax - bbox.xMin; 1720 glyph->metrics.height = bbox.yMax - bbox.yMin; 1721 1722 /* Now take care of vertical metrics. In the case where there is */ 1723 /* no vertical information within the font (relatively common), */ 1724 /* create some metrics manually */ 1725 { 1726 FT_Pos top; /* scaled vertical top side bearing */ 1727 FT_Pos advance; /* scaled vertical advance height */ 1728 1729 1730 /* Get the unscaled top bearing and advance height. */ 1731 if ( face->vertical_info && 1732 face->vertical.number_Of_VMetrics > 0 ) 1733 { 1734 top = (FT_Short)FT_DivFix( loader->pp3.y - bbox.yMax, 1735 y_scale ); 1736 1737 if ( loader->pp3.y <= loader->pp4.y ) 1738 advance = 0; 1739 else 1740 advance = (FT_UShort)FT_DivFix( loader->pp3.y - loader->pp4.y, 1741 y_scale ); 1742 } 1743 else 1744 { 1745 FT_Pos height; 1746 1747 1748 /* XXX Compute top side bearing and advance height in */ 1749 /* Get_VMetrics instead of here. */ 1750 1751 /* NOTE: The OS/2 values are the only `portable' ones, */ 1752 /* which is why we use them, if there is an OS/2 */ 1753 /* table in the font. Otherwise, we use the */ 1754 /* values defined in the horizontal header. */ 1755 1756 height = (FT_Short)FT_DivFix( bbox.yMax - bbox.yMin, 1757 y_scale ); 1758 if ( face->os2.version != 0xFFFFU ) 1759 advance = (FT_Pos)( face->os2.sTypoAscender - 1760 face->os2.sTypoDescender ); 1761 else 1762 advance = (FT_Pos)( face->horizontal.Ascender - 1763 face->horizontal.Descender ); 1764 1765 top = ( advance - height ) / 2; 1766 } 1767 1768#ifdef FT_CONFIG_OPTION_INCREMENTAL 1769 { 1770 FT_Incremental_InterfaceRec* incr; 1771 FT_Incremental_MetricsRec metrics; 1772 FT_Error error; 1773 1774 1775 incr = face->root.internal->incremental_interface; 1776 1777 /* If this is an incrementally loaded font see if there are */ 1778 /* overriding metrics for this glyph. */ 1779 if ( incr && incr->funcs->get_glyph_metrics ) 1780 { 1781 metrics.bearing_x = 0; 1782 metrics.bearing_y = top; 1783 metrics.advance = advance; 1784 1785 error = incr->funcs->get_glyph_metrics( incr->object, 1786 glyph_index, 1787 TRUE, 1788 &metrics ); 1789 if ( error ) 1790 return error; 1791 1792 top = metrics.bearing_y; 1793 advance = metrics.advance; 1794 } 1795 } 1796 1797 /* GWW: Do vertical metrics get loaded incrementally too? */ 1798 1799#endif /* FT_CONFIG_OPTION_INCREMENTAL */ 1800 1801 glyph->linearVertAdvance = advance; 1802 1803 /* scale the metrics */ 1804 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1805 { 1806 top = FT_MulFix( top, y_scale ); 1807 advance = FT_MulFix( advance, y_scale ); 1808 } 1809 1810 /* XXX: for now, we have no better algorithm for the lsb, but it */ 1811 /* should work fine. */ 1812 /* */ 1813 glyph->metrics.vertBearingX = glyph->metrics.horiBearingX - 1814 glyph->metrics.horiAdvance / 2; 1815 glyph->metrics.vertBearingY = top; 1816 glyph->metrics.vertAdvance = advance; 1817 } 1818 1819 return 0; 1820 } 1821 1822 1823#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1824 1825 static FT_Error 1826 load_sbit_image( TT_Size size, 1827 TT_GlyphSlot glyph, 1828 FT_UInt glyph_index, 1829 FT_Int32 load_flags ) 1830 { 1831 TT_Face face; 1832 SFNT_Service sfnt; 1833 FT_Stream stream; 1834 FT_Error error; 1835 TT_SBit_MetricsRec metrics; 1836 1837 1838 face = (TT_Face)glyph->face; 1839 sfnt = (SFNT_Service)face->sfnt; 1840 stream = face->root.stream; 1841 1842 error = sfnt->load_sbit_image( face, 1843 size->strike_index, 1844 glyph_index, 1845 (FT_Int)load_flags, 1846 stream, 1847 &glyph->bitmap, 1848 &metrics ); 1849 if ( !error ) 1850 { 1851 glyph->outline.n_points = 0; 1852 glyph->outline.n_contours = 0; 1853 1854 glyph->metrics.width = (FT_Pos)metrics.width << 6; 1855 glyph->metrics.height = (FT_Pos)metrics.height << 6; 1856 1857 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 1858 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 1859 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 1860 1861 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 1862 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 1863 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 1864 1865 glyph->format = FT_GLYPH_FORMAT_BITMAP; 1866 1867 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 1868 { 1869 glyph->bitmap_left = metrics.vertBearingX; 1870 glyph->bitmap_top = metrics.vertBearingY; 1871 } 1872 else 1873 { 1874 glyph->bitmap_left = metrics.horiBearingX; 1875 glyph->bitmap_top = metrics.horiBearingY; 1876 } 1877 } 1878 1879 return error; 1880 } 1881 1882#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1883 1884 1885 static FT_Error 1886 tt_loader_init( TT_Loader loader, 1887 TT_Size size, 1888 TT_GlyphSlot glyph, 1889 FT_Int32 load_flags, 1890 FT_Bool glyf_table_only ) 1891 { 1892 TT_Face face; 1893 FT_Stream stream; 1894#ifdef TT_USE_BYTECODE_INTERPRETER 1895 FT_Bool pedantic = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 1896#endif 1897 1898 1899 face = (TT_Face)glyph->face; 1900 stream = face->root.stream; 1901 1902 FT_MEM_ZERO( loader, sizeof ( TT_LoaderRec ) ); 1903 1904#ifdef TT_USE_BYTECODE_INTERPRETER 1905 1906 /* load execution context */ 1907 if ( IS_HINTED( load_flags ) && !glyf_table_only ) 1908 { 1909 TT_ExecContext exec; 1910 FT_Bool grayscale; 1911#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1912 FT_Bool subpixel_hinting; 1913 FT_Bool grayscale_hinting; 1914#if 0 1915 FT_Bool compatible_widths; 1916 FT_Bool symmetrical_smoothing; 1917 FT_Bool bgr; 1918 FT_Bool subpixel_positioned; 1919#endif 1920#endif /* TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1921 1922 1923 if ( !size->cvt_ready ) 1924 { 1925 FT_Error error = tt_size_ready_bytecode( size, pedantic ); 1926 1927 1928 if ( error ) 1929 return error; 1930 } 1931 1932 /* query new execution context */ 1933 exec = size->debug ? size->context 1934 : ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 1935 if ( !exec ) 1936 return TT_Err_Could_Not_Find_Context; 1937 1938#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1939 1940 subpixel_hinting = FT_BOOL( ( FT_LOAD_TARGET_MODE( load_flags ) 1941 != FT_RENDER_MODE_MONO ) && 1942 SPH_OPTION_SET_SUBPIXEL ); 1943 1944 if ( subpixel_hinting ) 1945 grayscale = grayscale_hinting = FALSE; 1946 1947 else if ( SPH_OPTION_SET_GRAYSCALE ) 1948 { 1949 grayscale = grayscale_hinting = TRUE; 1950 subpixel_hinting = FALSE; 1951 } 1952 1953 if ( FT_IS_TRICKY( glyph->face ) ) 1954 subpixel_hinting = grayscale_hinting = FALSE; 1955 1956 exec->ignore_x_mode = subpixel_hinting || grayscale_hinting; 1957 exec->rasterizer_version = SPH_OPTION_SET_RASTERIZER_VERSION; 1958 if ( exec->sph_tweak_flags & SPH_TWEAK_RASTERIZER_35 ) 1959 exec->rasterizer_version = 35; 1960 1961#if 1 1962 exec->compatible_widths = SPH_OPTION_SET_COMPATIBLE_WIDTHS; 1963 exec->symmetrical_smoothing = FALSE; 1964 exec->bgr = FALSE; 1965 exec->subpixel_positioned = TRUE; 1966#else /* 0 */ 1967 exec->compatible_widths = 1968 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 1969 TT_LOAD_COMPATIBLE_WIDTHS ); 1970 exec->symmetrical_smoothing = 1971 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 1972 TT_LOAD_SYMMETRICAL_SMOOTHING ); 1973 exec->bgr = 1974 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 1975 TT_LOAD_BGR ); 1976 exec->subpixel_positioned = 1977 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != 1978 TT_LOAD_SUBPIXEL_POSITIONED ); 1979#endif /* 0 */ 1980 1981#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1982 1983 grayscale = 1984 FT_BOOL( FT_LOAD_TARGET_MODE( load_flags ) != FT_RENDER_MODE_MONO ); 1985 1986#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 1987 1988 TT_Load_Context( exec, face, size ); 1989 1990#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1991 1992 /* a change from mono to subpixel rendering (and vice versa) */ 1993 /* requires a re-execution of the CVT program */ 1994 if ( subpixel_hinting != exec->subpixel_hinting ) 1995 { 1996 FT_UInt i; 1997 1998 1999 FT_TRACE4(( "tt_loader_init: subpixel hinting change," 2000 " re-executing `prep' table\n" )); 2001 2002 exec->subpixel_hinting = subpixel_hinting; 2003 2004 for ( i = 0; i < size->cvt_size; i++ ) 2005 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 2006 tt_size_run_prep( size, pedantic ); 2007 } 2008 2009 /* a change from mono to grayscale rendering (and vice versa) */ 2010 /* requires a re-execution of the CVT program */ 2011 if ( grayscale != exec->grayscale_hinting ) 2012 { 2013 FT_UInt i; 2014 2015 2016 FT_TRACE4(( "tt_loader_init: grayscale hinting change," 2017 " re-executing `prep' table\n" )); 2018 2019 exec->grayscale_hinting = grayscale_hinting; 2020 2021 for ( i = 0; i < size->cvt_size; i++ ) 2022 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 2023 tt_size_run_prep( size, pedantic ); 2024 } 2025 2026#else /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 2027 2028 /* a change from mono to grayscale rendering (and vice versa) */ 2029 /* requires a re-execution of the CVT program */ 2030 if ( grayscale != exec->grayscale ) 2031 { 2032 FT_UInt i; 2033 2034 2035 FT_TRACE4(( "tt_loader_init: grayscale change," 2036 " re-executing `prep' table\n" )); 2037 2038 exec->grayscale = grayscale; 2039 2040 for ( i = 0; i < size->cvt_size; i++ ) 2041 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 2042 tt_size_run_prep( size, pedantic ); 2043 } 2044 2045#endif /* !TT_CONFIG_OPTION_SUBPIXEL_HINTING */ 2046 2047 /* see whether the cvt program has disabled hinting */ 2048 if ( exec->GS.instruct_control & 1 ) 2049 load_flags |= FT_LOAD_NO_HINTING; 2050 2051 /* load default graphics state -- if needed */ 2052 if ( exec->GS.instruct_control & 2 ) 2053 exec->GS = tt_default_graphics_state; 2054 2055 exec->pedantic_hinting = FT_BOOL( load_flags & FT_LOAD_PEDANTIC ); 2056 loader->exec = exec; 2057 loader->instructions = exec->glyphIns; 2058 } 2059 2060#endif /* TT_USE_BYTECODE_INTERPRETER */ 2061 2062 /* seek to the beginning of the glyph table -- for Type 42 fonts */ 2063 /* the table might be accessed from a Postscript stream or something */ 2064 /* else... */ 2065 2066#ifdef FT_CONFIG_OPTION_INCREMENTAL 2067 2068 if ( face->root.internal->incremental_interface ) 2069 loader->glyf_offset = 0; 2070 else 2071 2072#endif 2073 2074 { 2075 FT_Error error = face->goto_table( face, TTAG_glyf, stream, 0 ); 2076 2077 2078 if ( error == TT_Err_Table_Missing ) 2079 loader->glyf_offset = 0; 2080 else if ( error ) 2081 { 2082 FT_ERROR(( "tt_loader_init: could not access glyph table\n" )); 2083 return error; 2084 } 2085 else 2086 loader->glyf_offset = FT_STREAM_POS(); 2087 } 2088 2089 /* get face's glyph loader */ 2090 if ( !glyf_table_only ) 2091 { 2092 FT_GlyphLoader gloader = glyph->internal->loader; 2093 2094 2095 FT_GlyphLoader_Rewind( gloader ); 2096 loader->gloader = gloader; 2097 } 2098 2099 loader->load_flags = load_flags; 2100 2101 loader->face = (FT_Face)face; 2102 loader->size = (FT_Size)size; 2103 loader->glyph = (FT_GlyphSlot)glyph; 2104 loader->stream = stream; 2105 2106 return TT_Err_Ok; 2107 } 2108 2109 2110 /*************************************************************************/ 2111 /* */ 2112 /* <Function> */ 2113 /* TT_Load_Glyph */ 2114 /* */ 2115 /* <Description> */ 2116 /* A function used to load a single glyph within a given glyph slot, */ 2117 /* for a given size. */ 2118 /* */ 2119 /* <Input> */ 2120 /* glyph :: A handle to a target slot object where the glyph */ 2121 /* will be loaded. */ 2122 /* */ 2123 /* size :: A handle to the source face size at which the glyph */ 2124 /* must be scaled/loaded. */ 2125 /* */ 2126 /* glyph_index :: The index of the glyph in the font file. */ 2127 /* */ 2128 /* load_flags :: A flag indicating what to load for this glyph. The */ 2129 /* FT_LOAD_XXX constants can be used to control the */ 2130 /* glyph loading process (e.g., whether the outline */ 2131 /* should be scaled, whether to load bitmaps or not, */ 2132 /* whether to hint the outline, etc). */ 2133 /* */ 2134 /* <Return> */ 2135 /* FreeType error code. 0 means success. */ 2136 /* */ 2137 FT_LOCAL_DEF( FT_Error ) 2138 TT_Load_Glyph( TT_Size size, 2139 TT_GlyphSlot glyph, 2140 FT_UInt glyph_index, 2141 FT_Int32 load_flags ) 2142 { 2143 FT_Error error; 2144 TT_LoaderRec loader; 2145 2146 2147 error = TT_Err_Ok; 2148 2149#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 2150 2151 /* try to load embedded bitmap if any */ 2152 /* */ 2153 /* XXX: The convention should be emphasized in */ 2154 /* the documents because it can be confusing. */ 2155 if ( size->strike_index != 0xFFFFFFFFUL && 2156 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 2157 { 2158 error = load_sbit_image( size, glyph, glyph_index, load_flags ); 2159 if ( !error ) 2160 { 2161 if ( FT_IS_SCALABLE( glyph->face ) ) 2162 { 2163 /* for the bbox we need the header only */ 2164 (void)tt_loader_init( &loader, size, glyph, load_flags, TRUE ); 2165 (void)load_truetype_glyph( &loader, glyph_index, 0, TRUE ); 2166 glyph->linearHoriAdvance = loader.linear; 2167 glyph->linearVertAdvance = loader.top_bearing + loader.bbox.yMax - 2168 loader.vadvance; 2169 } 2170 2171 return TT_Err_Ok; 2172 } 2173 } 2174 2175#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 2176 2177 /* if FT_LOAD_NO_SCALE is not set, `ttmetrics' must be valid */ 2178 if ( !( load_flags & FT_LOAD_NO_SCALE ) && !size->ttmetrics.valid ) 2179 return TT_Err_Invalid_Size_Handle; 2180 2181 if ( load_flags & FT_LOAD_SBITS_ONLY ) 2182 return TT_Err_Invalid_Argument; 2183 2184 error = tt_loader_init( &loader, size, glyph, load_flags, FALSE ); 2185 if ( error ) 2186 return error; 2187 2188 glyph->format = FT_GLYPH_FORMAT_OUTLINE; 2189 glyph->num_subglyphs = 0; 2190 glyph->outline.flags = 0; 2191 2192 /* main loading loop */ 2193 error = load_truetype_glyph( &loader, glyph_index, 0, FALSE ); 2194 if ( !error ) 2195 { 2196 if ( glyph->format == FT_GLYPH_FORMAT_COMPOSITE ) 2197 { 2198 glyph->num_subglyphs = loader.gloader->base.num_subglyphs; 2199 glyph->subglyphs = loader.gloader->base.subglyphs; 2200 } 2201 else 2202 { 2203 glyph->outline = loader.gloader->base.outline; 2204 glyph->outline.flags &= ~FT_OUTLINE_SINGLE_PASS; 2205 2206 /* Translate array so that (0,0) is the glyph's origin. Note */ 2207 /* that this behaviour is independent on the value of bit 1 of */ 2208 /* the `flags' field in the `head' table -- at least major */ 2209 /* applications like Acroread indicate that. */ 2210 if ( loader.pp1.x ) 2211 FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 ); 2212 } 2213 2214#ifdef TT_USE_BYTECODE_INTERPRETER 2215 2216 if ( IS_HINTED( load_flags ) ) 2217 { 2218 if ( loader.exec->GS.scan_control ) 2219 { 2220 /* convert scan conversion mode to FT_OUTLINE_XXX flags */ 2221 switch ( loader.exec->GS.scan_type ) 2222 { 2223 case 0: /* simple drop-outs including stubs */ 2224 glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS; 2225 break; 2226 case 1: /* simple drop-outs excluding stubs */ 2227 /* nothing; it's the default rendering mode */ 2228 break; 2229 case 4: /* smart drop-outs including stubs */ 2230 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS | 2231 FT_OUTLINE_INCLUDE_STUBS; 2232 break; 2233 case 5: /* smart drop-outs excluding stubs */ 2234 glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS; 2235 break; 2236 2237 default: /* no drop-out control */ 2238 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2239 break; 2240 } 2241 } 2242 else 2243 glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS; 2244 } 2245 2246#endif /* TT_USE_BYTECODE_INTERPRETER */ 2247 2248 compute_glyph_metrics( &loader, glyph_index ); 2249 } 2250 2251 /* Set the `high precision' bit flag. */ 2252 /* This is _critical_ to get correct output for monochrome */ 2253 /* TrueType glyphs at all sizes using the bytecode interpreter. */ 2254 /* */ 2255 if ( !( load_flags & FT_LOAD_NO_SCALE ) && 2256 size->root.metrics.y_ppem < 24 ) 2257 glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 2258 2259 return error; 2260 } 2261 2262 2263/* END */ 2264