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