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