ttgload.c revision 318f3befc67e026037da33fb7b5b9a22d567df9a
1/***************************************************************************/ 2/* */ 3/* ttgload.c */ 4/* */ 5/* TrueType Glyph Loader (body). */ 6/* */ 7/* Copyright 1996-2001, 2002 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#include "tterrors.h" 30 31 32 /*************************************************************************/ 33 /* */ 34 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 35 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 36 /* messages during execution. */ 37 /* */ 38#undef FT_COMPONENT 39#define FT_COMPONENT trace_ttgload 40 41 42 /*************************************************************************/ 43 /* */ 44 /* Composite font flags. */ 45 /* */ 46#define ARGS_ARE_WORDS 0x001 47#define ARGS_ARE_XY_VALUES 0x002 48#define ROUND_XY_TO_GRID 0x004 49#define WE_HAVE_A_SCALE 0x008 50/* reserved 0x010 */ 51#define MORE_COMPONENTS 0x020 52#define WE_HAVE_AN_XY_SCALE 0x040 53#define WE_HAVE_A_2X2 0x080 54#define WE_HAVE_INSTR 0x100 55#define USE_MY_METRICS 0x200 56 57 58 59 /*************************************************************************/ 60 /* */ 61 /* <Function> */ 62 /* TT_Get_Metrics */ 63 /* */ 64 /* <Description> */ 65 /* Returns the horizontal or vertical metrics in font units for a */ 66 /* given glyph. The metrics are the left side bearing (resp. top */ 67 /* side bearing) and advance width (resp. advance height). */ 68 /* */ 69 /* <Input> */ 70 /* header :: A pointer to either the horizontal or vertical metrics */ 71 /* structure. */ 72 /* */ 73 /* idx :: The glyph index. */ 74 /* */ 75 /* <Output> */ 76 /* bearing :: The bearing, either left side or top side. */ 77 /* */ 78 /* advance :: The advance width resp. advance height. */ 79 /* */ 80 /* <Note> */ 81 /* This function will much probably move to another component in the */ 82 /* near future, but I haven't decided which yet. */ 83 /* */ 84 FT_LOCAL_DEF( void ) 85 TT_Get_Metrics( TT_HoriHeader* header, 86 FT_UInt idx, 87 FT_Short* bearing, 88 FT_UShort* advance ) 89 { 90 TT_LongMetrics longs_m; 91 FT_UShort k = header->number_Of_HMetrics; 92 93 94 if ( idx < (FT_UInt)k ) 95 { 96 longs_m = (TT_LongMetrics )header->long_metrics + idx; 97 *bearing = longs_m->bearing; 98 *advance = longs_m->advance; 99 } 100 else 101 { 102 *bearing = ((TT_ShortMetrics*)header->short_metrics)[idx - k]; 103 *advance = ((TT_LongMetrics )header->long_metrics)[k - 1].advance; 104 } 105 } 106 107 108 /*************************************************************************/ 109 /* */ 110 /* Returns the horizontal metrics in font units for a given glyph. If */ 111 /* `check' is true, take care of monospaced fonts by returning the */ 112 /* advance width maximum. */ 113 /* */ 114 static void 115 Get_HMetrics( TT_Face face, 116 FT_UInt idx, 117 FT_Bool check, 118 FT_Short* lsb, 119 FT_UShort* aw ) 120 { 121 TT_Get_Metrics( &face->horizontal, idx, lsb, aw ); 122 123 if ( check && face->postscript.isFixedPitch ) 124 *aw = face->horizontal.advance_Width_Max; 125 } 126 127 128 /*************************************************************************/ 129 /* */ 130 /* Returns the advance width table for a given pixel size if it is found */ 131 /* in the font's `hdmx' table (if any). */ 132 /* */ 133 static FT_Byte* 134 Get_Advance_Widths( TT_Face face, 135 FT_UShort ppem ) 136 { 137 FT_UShort n; 138 139 140 for ( n = 0; n < face->hdmx.num_records; n++ ) 141 if ( face->hdmx.records[n].ppem == ppem ) 142 return face->hdmx.records[n].widths; 143 144 return NULL; 145 } 146 147 148#define cur_to_org( n, zone ) \ 149 FT_MEM_COPY( (zone)->org, (zone)->cur, (n) * sizeof ( FT_Vector ) ) 150 151#define org_to_cur( n, zone ) \ 152 FT_MEM_COPY( (zone)->cur, (zone)->org, (n) * sizeof ( FT_Vector ) ) 153 154 155 /*************************************************************************/ 156 /* */ 157 /* Translates an array of coordinates. */ 158 /* */ 159 static void 160 translate_array( FT_UInt n, 161 FT_Vector* coords, 162 FT_Pos delta_x, 163 FT_Pos delta_y ) 164 { 165 FT_UInt k; 166 167 168 if ( delta_x ) 169 for ( k = 0; k < n; k++ ) 170 coords[k].x += delta_x; 171 172 if ( delta_y ) 173 for ( k = 0; k < n; k++ ) 174 coords[k].y += delta_y; 175 } 176 177 178 static void 179 tt_prepare_zone( TT_GlyphZone zone, 180 FT_GlyphLoad load, 181 FT_UInt start_point, 182 FT_UInt start_contour ) 183 { 184 zone->n_points = (FT_UShort)( load->outline.n_points - start_point ); 185 zone->n_contours = (FT_Short) ( load->outline.n_contours - start_contour ); 186 zone->org = load->extra_points + start_point; 187 zone->cur = load->outline.points + start_point; 188 zone->tags = (FT_Byte*)load->outline.tags + start_point; 189 zone->contours = (FT_UShort*)load->outline.contours + start_contour; 190 } 191 192 193#undef IS_HINTED 194#define IS_HINTED( flags ) ( ( flags & FT_LOAD_NO_HINTING ) == 0 ) 195 196 197 /*************************************************************************/ 198 /* */ 199 /* The following functions are used by default with TrueType fonts. */ 200 /* However, they can be replaced by alternatives if we need to support */ 201 /* TrueType-compressed formats (like MicroType) in the future. */ 202 /* */ 203 /*************************************************************************/ 204 205 FT_CALLBACK_DEF( FT_Error ) 206 TT_Access_Glyph_Frame( TT_Loader loader, 207 FT_UInt glyph_index, 208 FT_ULong offset, 209 FT_UInt byte_count ) 210 { 211 FT_Error error; 212 FT_Stream stream = loader->stream; 213 214 /* for non-debug mode */ 215 FT_UNUSED( glyph_index ); 216 217 218 FT_TRACE5(( "Glyph %ld\n", glyph_index )); 219 220 /* the following line sets the `error' variable through macros! */ 221 if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( byte_count ) ) 222 return error; 223 224 return TT_Err_Ok; 225 } 226 227 228 FT_CALLBACK_DEF( void ) 229 TT_Forget_Glyph_Frame( TT_Loader loader ) 230 { 231 FT_Stream stream = loader->stream; 232 233 234 FT_FRAME_EXIT(); 235 } 236 237 238 FT_CALLBACK_DEF( FT_Error ) 239 TT_Load_Glyph_Header( TT_Loader loader ) 240 { 241 FT_Stream stream = loader->stream; 242 FT_Int byte_len = loader->byte_len - 10; 243 244 245 if ( byte_len < 0 ) 246 return TT_Err_Invalid_Outline; 247 248 loader->n_contours = FT_GET_SHORT(); 249 250 loader->bbox.xMin = FT_GET_SHORT(); 251 loader->bbox.yMin = FT_GET_SHORT(); 252 loader->bbox.xMax = FT_GET_SHORT(); 253 loader->bbox.yMax = FT_GET_SHORT(); 254 255 FT_TRACE5(( " # of contours: %d\n", loader->n_contours )); 256 FT_TRACE5(( " xMin: %4d xMax: %4d\n", loader->bbox.xMin, 257 loader->bbox.xMax )); 258 FT_TRACE5(( " yMin: %4d yMax: %4d\n", loader->bbox.yMin, 259 loader->bbox.yMax )); 260 loader->byte_len = byte_len; 261 262 return TT_Err_Ok; 263 } 264 265 266 FT_CALLBACK_DEF( FT_Error ) 267 TT_Load_Simple_Glyph( TT_Loader load ) 268 { 269 FT_Error error; 270 FT_Stream stream = load->stream; 271 FT_GlyphLoader gloader = load->gloader; 272 FT_Int n_contours = load->n_contours; 273 FT_Outline* outline; 274 TT_Face face = (TT_Face)load->face; 275 TT_GlyphSlot slot = (TT_GlyphSlot)load->glyph; 276 FT_UShort n_ins; 277 FT_Int n, n_points; 278 FT_Int byte_len = load->byte_len; 279 280 281 /* reading the contours endpoints & number of points */ 282 { 283 short* cur = gloader->current.outline.contours; 284 short* limit = cur + n_contours; 285 286 287 /* check space for contours array + instructions count */ 288 byte_len -= 2 * ( n_contours + 1 ); 289 if ( byte_len < 0 ) 290 goto Invalid_Outline; 291 292 for ( ; cur < limit; cur++ ) 293 cur[0] = FT_GET_USHORT(); 294 295 n_points = 0; 296 if ( n_contours > 0 ) 297 n_points = cur[-1] + 1; 298 299 error = FT_GlyphLoader_CheckPoints( gloader, n_points + 2, 0 ); 300 if ( error ) 301 goto Fail; 302 303 /* we'd better check the contours table right now */ 304 outline = &gloader->current.outline; 305 306 for ( cur = outline->contours + 1; cur < limit; cur++ ) 307 if ( cur[-1] >= cur[0] ) 308 goto Invalid_Outline; 309 } 310 311 /* reading the bytecode instructions */ 312 slot->control_len = 0; 313 slot->control_data = 0; 314 315 n_ins = FT_GET_USHORT(); 316 317 FT_TRACE5(( " Instructions size: %d\n", n_ins )); 318 319 if ( n_ins > face->max_profile.maxSizeOfInstructions ) 320 { 321 FT_TRACE0(( "TT_Load_Simple_Glyph: Too many instructions!\n" )); 322 error = TT_Err_Too_Many_Hints; 323 goto Fail; 324 } 325 326 byte_len -= n_ins; 327 if ( byte_len < 0 ) 328 { 329 FT_TRACE0(( "TT_Load_Simple_Glyph: Instruction count mismatch!\n" )); 330 error = TT_Err_Too_Many_Hints; 331 goto Fail; 332 } 333 334#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 335 336 if ( ( load->load_flags & 337 ( FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING ) ) == 0 && 338 load->instructions ) 339 { 340 slot->control_len = n_ins; 341 slot->control_data = load->instructions; 342 343 FT_MEM_COPY( load->instructions, stream->cursor, n_ins ); 344 } 345 346#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 347 348 stream->cursor += n_ins; 349 350 /* reading the point tags */ 351 { 352 FT_Byte* flag = (FT_Byte*)outline->tags; 353 FT_Byte* limit = flag + n_points; 354 FT_Byte c, count; 355 356 357 while ( flag < limit ) 358 { 359 if ( --byte_len < 0 ) 360 goto Invalid_Outline; 361 362 *flag++ = c = FT_GET_BYTE(); 363 if ( c & 8 ) 364 { 365 if ( --byte_len < 0 ) 366 goto Invalid_Outline; 367 368 count = FT_GET_BYTE(); 369 if ( flag + count > limit ) 370 goto Invalid_Outline; 371 372 for ( ; count > 0; count-- ) 373 *flag++ = c; 374 } 375 } 376 377 /* check that there is enough room to load the coordinates */ 378 for ( flag = (FT_Byte*)outline->tags; flag < limit; flag++ ) 379 { 380 if ( *flag & 2 ) 381 byte_len -= 1; 382 else if ( ( *flag & 16 ) == 0 ) 383 byte_len -= 2; 384 385 if ( *flag & 4 ) 386 byte_len -= 1; 387 else if ( ( *flag & 32 ) == 0 ) 388 byte_len -= 2; 389 } 390 391 if ( byte_len < 0 ) 392 goto Invalid_Outline; 393 } 394 395 /* reading the X coordinates */ 396 397 { 398 FT_Vector* vec = outline->points; 399 FT_Vector* limit = vec + n_points; 400 FT_Byte* flag = (FT_Byte*)outline->tags; 401 FT_Pos x = 0; 402 403 404 for ( ; vec < limit; vec++, flag++ ) 405 { 406 FT_Pos y = 0; 407 408 409 if ( *flag & 2 ) 410 { 411 y = FT_GET_BYTE(); 412 if ( ( *flag & 16 ) == 0 ) 413 y = -y; 414 } 415 else if ( ( *flag & 16 ) == 0 ) 416 y = FT_GET_SHORT(); 417 418 x += y; 419 vec->x = x; 420 } 421 } 422 423 /* reading the Y coordinates */ 424 425 { 426 FT_Vector* vec = gloader->current.outline.points; 427 FT_Vector* limit = vec + n_points; 428 FT_Byte* flag = (FT_Byte*)outline->tags; 429 FT_Pos x = 0; 430 431 432 for ( ; vec < limit; vec++, flag++ ) 433 { 434 FT_Pos y = 0; 435 436 437 if ( *flag & 4 ) 438 { 439 y = FT_GET_BYTE(); 440 if ( ( *flag & 32 ) == 0 ) 441 y = -y; 442 } 443 else if ( ( *flag & 32 ) == 0 ) 444 y = FT_GET_SHORT(); 445 446 x += y; 447 vec->y = x; 448 } 449 } 450 451 /* clear the touch tags */ 452 for ( n = 0; n < n_points; n++ ) 453 outline->tags[n] &= FT_Curve_Tag_On; 454 455 outline->n_points = (FT_UShort)n_points; 456 outline->n_contours = (FT_Short) n_contours; 457 458 load->byte_len = byte_len; 459 460 Fail: 461 return error; 462 463 Invalid_Outline: 464 error = TT_Err_Invalid_Outline; 465 goto Fail; 466 } 467 468 469 FT_CALLBACK_DEF( FT_Error ) 470 TT_Load_Composite_Glyph( TT_Loader loader ) 471 { 472 FT_Error error; 473 FT_Stream stream = loader->stream; 474 FT_GlyphLoader gloader = loader->gloader; 475 FT_SubGlyph subglyph; 476 FT_UInt num_subglyphs; 477 FT_Int byte_len = loader->byte_len; 478 479 480 num_subglyphs = 0; 481 482 do 483 { 484 FT_Fixed xx, xy, yy, yx; 485 486 487 /* check that we can load a new subglyph */ 488 error = FT_GlyphLoader_CheckSubGlyphs( gloader, num_subglyphs + 1 ); 489 if ( error ) 490 goto Fail; 491 492 /* check space */ 493 byte_len -= 4; 494 if ( byte_len < 0 ) 495 goto Invalid_Composite; 496 497 subglyph = gloader->current.subglyphs + num_subglyphs; 498 499 subglyph->arg1 = subglyph->arg2 = 0; 500 501 subglyph->flags = FT_GET_USHORT(); 502 subglyph->index = FT_GET_USHORT(); 503 504 /* check space */ 505 byte_len -= 2; 506 if ( subglyph->flags & ARGS_ARE_WORDS ) 507 byte_len -= 2; 508 if ( subglyph->flags & WE_HAVE_A_SCALE ) 509 byte_len -= 2; 510 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 511 byte_len -= 4; 512 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 513 byte_len -= 8; 514 515 if ( byte_len < 0 ) 516 goto Invalid_Composite; 517 518 /* read arguments */ 519 if ( subglyph->flags & ARGS_ARE_WORDS ) 520 { 521 subglyph->arg1 = FT_GET_SHORT(); 522 subglyph->arg2 = FT_GET_SHORT(); 523 } 524 else 525 { 526 subglyph->arg1 = FT_GET_CHAR(); 527 subglyph->arg2 = FT_GET_CHAR(); 528 } 529 530 /* read transform */ 531 xx = yy = 0x10000L; 532 xy = yx = 0; 533 534 if ( subglyph->flags & WE_HAVE_A_SCALE ) 535 { 536 xx = (FT_Fixed)FT_GET_SHORT() << 2; 537 yy = xx; 538 } 539 else if ( subglyph->flags & WE_HAVE_AN_XY_SCALE ) 540 { 541 xx = (FT_Fixed)FT_GET_SHORT() << 2; 542 yy = (FT_Fixed)FT_GET_SHORT() << 2; 543 } 544 else if ( subglyph->flags & WE_HAVE_A_2X2 ) 545 { 546 xx = (FT_Fixed)FT_GET_SHORT() << 2; 547 yx = (FT_Fixed)FT_GET_SHORT() << 2; 548 xy = (FT_Fixed)FT_GET_SHORT() << 2; 549 yy = (FT_Fixed)FT_GET_SHORT() << 2; 550 } 551 552 subglyph->transform.xx = xx; 553 subglyph->transform.xy = xy; 554 subglyph->transform.yx = yx; 555 subglyph->transform.yy = yy; 556 557 num_subglyphs++; 558 559 } while ( subglyph->flags & MORE_COMPONENTS ); 560 561 gloader->current.num_subglyphs = num_subglyphs; 562 563#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 564 { 565 /* we must undo the FT_FRAME_ENTER in order to point to the */ 566 /* composite instructions, if we find some. */ 567 /* we will process them later... */ 568 /* */ 569 loader->ins_pos = (FT_ULong)( FT_STREAM_POS() + 570 stream->cursor - stream->limit ); 571 } 572#endif 573 574 loader->byte_len = byte_len; 575 576 Fail: 577 return error; 578 579 Invalid_Composite: 580 error = TT_Err_Invalid_Composite; 581 goto Fail; 582 } 583 584 585 FT_LOCAL_DEF( void ) 586 TT_Init_Glyph_Loading( TT_Face face ) 587 { 588 face->access_glyph_frame = TT_Access_Glyph_Frame; 589 face->read_glyph_header = TT_Load_Glyph_Header; 590 face->read_simple_glyph = TT_Load_Simple_Glyph; 591 face->read_composite_glyph = TT_Load_Composite_Glyph; 592 face->forget_glyph_frame = TT_Forget_Glyph_Frame; 593 } 594 595 596 /*************************************************************************/ 597 /* */ 598 /* <Function> */ 599 /* TT_Process_Simple_Glyph */ 600 /* */ 601 /* <Description> */ 602 /* Once a simple glyph has been loaded, it needs to be processed. */ 603 /* Usually, this means scaling and hinting through bytecode */ 604 /* interpretation. */ 605 /* */ 606 static FT_Error 607 TT_Process_Simple_Glyph( TT_Loader load, 608 FT_Bool debug ) 609 { 610 FT_GlyphLoader gloader = load->gloader; 611 FT_Outline* outline = &gloader->current.outline; 612 FT_UInt n_points = outline->n_points; 613#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 614 FT_UInt n_ins; 615#endif 616 TT_GlyphZone zone = &load->zone; 617 FT_Error error = TT_Err_Ok; 618 619 FT_UNUSED( debug ); /* used by truetype interpreter only */ 620 621 622#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 623 n_ins = load->glyph->control_len; 624#endif 625 626 /* add shadow points */ 627 628 /* Now add the two shadow points at n and n + 1. */ 629 /* We need the left side bearing and advance width. */ 630 631 { 632 FT_Vector* pp1; 633 FT_Vector* pp2; 634 635 636 /* pp1 = xMin - lsb */ 637 pp1 = outline->points + n_points; 638 pp1->x = load->bbox.xMin - load->left_bearing; 639 pp1->y = 0; 640 641 /* pp2 = pp1 + aw */ 642 pp2 = pp1 + 1; 643 pp2->x = pp1->x + load->advance; 644 pp2->y = 0; 645 646 outline->tags[n_points ] = 0; 647 outline->tags[n_points + 1] = 0; 648 } 649 650 /* Note that we return two more points that are not */ 651 /* part of the glyph outline. */ 652 653 n_points += 2; 654 655 /* set up zone for hinting */ 656 tt_prepare_zone( zone, &gloader->current, 0, 0 ); 657 658 /* eventually scale the glyph */ 659 if ( !( load->load_flags & FT_LOAD_NO_SCALE ) ) 660 { 661 FT_Vector* vec = zone->cur; 662 FT_Vector* limit = vec + n_points; 663 FT_Fixed x_scale = load->size->metrics.x_scale; 664 FT_Fixed y_scale = load->size->metrics.y_scale; 665 666 667 /* first scale the glyph points */ 668 for ( ; vec < limit; vec++ ) 669 { 670 vec->x = FT_MulFix( vec->x, x_scale ); 671 vec->y = FT_MulFix( vec->y, y_scale ); 672 } 673 } 674 675 cur_to_org( n_points, zone ); 676 677 /* eventually hint the glyph */ 678 if ( IS_HINTED( load->load_flags ) ) 679 { 680 FT_Pos x = zone->org[n_points-2].x; 681 682 683 x = ( ( x + 32 ) & -64 ) - x; 684 translate_array( n_points, zone->org, x, 0 ); 685 686 org_to_cur( n_points, zone ); 687 688 zone->cur[n_points - 1].x = ( zone->cur[n_points - 1].x + 32 ) & -64; 689 690#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 691 692 /* now consider hinting */ 693 if ( n_ins > 0 ) 694 { 695 error = TT_Set_CodeRange( load->exec, tt_coderange_glyph, 696 load->exec->glyphIns, n_ins ); 697 if ( error ) 698 goto Exit; 699 700 load->exec->is_composite = FALSE; 701 load->exec->pedantic_hinting = (FT_Bool)( load->load_flags & 702 FT_LOAD_PEDANTIC ); 703 load->exec->pts = *zone; 704 load->exec->pts.n_points += 2; 705 706 error = TT_Run_Context( load->exec, debug ); 707 if ( error && load->exec->pedantic_hinting ) 708 goto Exit; 709 710 error = TT_Err_Ok; /* ignore bytecode errors in non-pedantic mode */ 711 } 712 713#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 714 715 } 716 717 /* save glyph phantom points */ 718 if ( !load->preserve_pps ) 719 { 720 load->pp1 = zone->cur[n_points - 2]; 721 load->pp2 = zone->cur[n_points - 1]; 722 } 723 724#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 725 Exit: 726#endif 727 return error; 728 } 729 730 731 /*************************************************************************/ 732 /* */ 733 /* <Function> */ 734 /* load_truetype_glyph */ 735 /* */ 736 /* <Description> */ 737 /* Loads a given truetype glyph. Handles composites and uses a */ 738 /* TT_Loader object. */ 739 /* */ 740 static FT_Error 741 load_truetype_glyph( TT_Loader loader, 742 FT_UInt glyph_index ) 743 { 744 745#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 746 FT_Stream stream = loader->stream; 747#endif 748 749 FT_Error error; 750 TT_Face face = (TT_Face)loader->face; 751 FT_ULong offset; 752 FT_Int contours_count; 753 FT_UInt idx, num_points, count; 754 FT_Fixed x_scale, y_scale; 755 FT_GlyphLoader gloader = loader->gloader; 756 FT_Bool opened_frame = 0; 757 758 759 /* check glyph index */ 760 idx = glyph_index; 761 if ( idx >= (FT_UInt)face->root.num_glyphs ) 762 { 763 error = TT_Err_Invalid_Glyph_Index; 764 goto Exit; 765 } 766 767 loader->glyph_index = glyph_index; 768 num_points = 0; 769 770 x_scale = 0x10000L; 771 y_scale = 0x10000L; 772 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 773 { 774 x_scale = loader->size->metrics.x_scale; 775 y_scale = loader->size->metrics.y_scale; 776 } 777 778 /* get horizontal metrics */ 779 { 780 FT_Short left_bearing; 781 FT_UShort advance_width; 782 783 784 Get_HMetrics( face, idx, 785 (FT_Bool)!( loader->load_flags & 786 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ), 787 &left_bearing, 788 &advance_width ); 789 790 loader->left_bearing = left_bearing; 791 loader->advance = advance_width; 792 793 if ( !loader->linear_def ) 794 { 795 loader->linear_def = 1; 796 loader->linear = advance_width; 797 } 798 } 799 800 offset = face->glyph_locations[idx]; 801 count = 0; 802 803 if ( idx < (FT_UInt)face->num_locations - 1 ) 804 count = face->glyph_locations[idx + 1] - offset; 805 806 if ( count == 0 ) 807 { 808 /* as described by Frederic Loyer, these are spaces, and */ 809 /* not the unknown glyph. */ 810 loader->bbox.xMin = 0; 811 loader->bbox.xMax = 0; 812 loader->bbox.yMin = 0; 813 loader->bbox.yMax = 0; 814 815 loader->pp1.x = 0; 816 loader->pp2.x = loader->advance; 817 818 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 819 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 820 821#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 822 823 if ( loader->exec ) 824 loader->exec->glyphSize = 0; 825 826#endif 827 828 error = TT_Err_Ok; 829 goto Exit; 830 } 831 832 loader->byte_len = (FT_Int)count; 833 834 offset = loader->glyf_offset + offset; 835 836 /* access glyph frame */ 837 error = face->access_glyph_frame( loader, glyph_index, offset, count ); 838 if ( error ) 839 goto Exit; 840 841 opened_frame = 1; 842 843 /* read first glyph header */ 844 error = face->read_glyph_header( loader ); 845 if ( error ) 846 goto Fail; 847 848 contours_count = loader->n_contours; 849 850 count -= 10; 851 852 loader->pp1.x = loader->bbox.xMin - loader->left_bearing; 853 loader->pp1.y = 0; 854 loader->pp2.x = loader->pp1.x + loader->advance; 855 loader->pp2.y = 0; 856 857 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 858 { 859 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 860 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 861 } 862 863 /***********************************************************************/ 864 /***********************************************************************/ 865 /***********************************************************************/ 866 867 /* if it is a simple glyph, load it */ 868 869 if ( contours_count >= 0 ) 870 { 871 /* check that we can add the contours to the glyph */ 872 error = FT_GlyphLoader_CheckPoints( gloader, 0, contours_count ); 873 if ( error ) 874 goto Fail; 875 876 error = face->read_simple_glyph( loader ); 877 if ( error ) 878 goto Fail; 879 880#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 881 882 { 883 TT_Size size = (TT_Size)loader->size; 884 885 886 error = TT_Process_Simple_Glyph( loader, 887 (FT_Bool)( size && size->debug ) ); 888 } 889 890#else 891 892 error = TT_Process_Simple_Glyph( loader, 0 ); 893 894#endif 895 896 if ( error ) 897 goto Fail; 898 899 FT_GlyphLoader_Add( gloader ); 900 901 /* Note: We could have put the simple loader source there */ 902 /* but the code is fat enough already :-) */ 903 } 904 905 /***********************************************************************/ 906 /***********************************************************************/ 907 /***********************************************************************/ 908 909 /* otherwise, load a composite! */ 910 else 911 { 912 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; 913 FT_UInt start_point; 914#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 915 FT_UInt start_contour; 916 FT_ULong ins_pos; /* position of composite instructions, if any */ 917#endif 918 919 920 /* for each subglyph, read composite header */ 921 start_point = gloader->base.outline.n_points; 922#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 923 start_contour = gloader->base.outline.n_contours; 924#endif 925 926 error = face->read_composite_glyph( loader ); 927 if ( error ) 928 goto Fail; 929 930#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 931 ins_pos = loader->ins_pos; 932#endif 933 face->forget_glyph_frame( loader ); 934 opened_frame = 0; 935 936 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 937 /* `as is' in the glyph slot (the client application will be */ 938 /* responsible for interpreting this data)... */ 939 /* */ 940 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 941 { 942 /* set up remaining glyph fields */ 943 FT_GlyphLoader_Add( gloader ); 944 945 glyph->num_subglyphs = gloader->base.num_subglyphs; 946 glyph->format = ft_glyph_format_composite; 947 glyph->subglyphs = gloader->base.subglyphs; 948 949 goto Exit; 950 } 951 952 /*********************************************************************/ 953 /*********************************************************************/ 954 /*********************************************************************/ 955 956 /* Now, read each subglyph independently. */ 957 { 958 FT_Int n, num_base_points, num_new_points; 959 FT_SubGlyph subglyph = 0; 960 961 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 962 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 963 964 965 FT_GlyphLoader_Add( gloader ); 966 967 for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) 968 { 969 FT_Vector pp1, pp2; 970 FT_Pos x, y; 971 972 973 /* Each time we call load_truetype_glyph in this loop, the */ 974 /* value of `gloader.base.subglyphs' can change due to table */ 975 /* reallocations. We thus need to recompute the subglyph */ 976 /* pointer on each iteration. */ 977 subglyph = gloader->base.subglyphs + num_base_subgs + n; 978 979 pp1 = loader->pp1; 980 pp2 = loader->pp2; 981 982 num_base_points = gloader->base.outline.n_points; 983 984 error = load_truetype_glyph( loader, subglyph->index ); 985 if ( error ) 986 goto Fail; 987 988 /* restore subglyph pointer */ 989 subglyph = gloader->base.subglyphs + num_base_subgs + n; 990 991 if ( subglyph->flags & USE_MY_METRICS ) 992 { 993 pp1 = loader->pp1; 994 pp2 = loader->pp2; 995 } 996 else 997 { 998 loader->pp1 = pp1; 999 loader->pp2 = pp2; 1000 } 1001 1002 num_points = gloader->base.outline.n_points; 1003 1004 num_new_points = num_points - num_base_points; 1005 1006 /* now perform the transform required for this subglyph */ 1007 1008 if ( subglyph->flags & ( WE_HAVE_A_SCALE | 1009 WE_HAVE_AN_XY_SCALE | 1010 WE_HAVE_A_2X2 ) ) 1011 { 1012 FT_Vector* cur = gloader->base.outline.points + 1013 num_base_points; 1014 FT_Vector* org = gloader->base.extra_points + 1015 num_base_points; 1016 FT_Vector* limit = cur + num_new_points; 1017 1018 1019 for ( ; cur < limit; cur++, org++ ) 1020 { 1021 FT_Vector_Transform( cur, &subglyph->transform ); 1022 FT_Vector_Transform( org, &subglyph->transform ); 1023 } 1024 } 1025 1026 /* apply offset */ 1027 1028 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) 1029 { 1030 FT_UInt k = subglyph->arg1; 1031 FT_UInt l = subglyph->arg2; 1032 FT_Vector* p1; 1033 FT_Vector* p2; 1034 1035 1036 if ( start_point + k >= (FT_UInt)num_base_points || 1037 l >= (FT_UInt)num_new_points ) 1038 { 1039 error = TT_Err_Invalid_Composite; 1040 goto Fail; 1041 } 1042 1043 l += num_base_points; 1044 1045 p1 = gloader->base.outline.points + start_point + k; 1046 p2 = gloader->base.outline.points + start_point + l; 1047 1048 x = p1->x - p2->x; 1049 y = p1->y - p2->y; 1050 } 1051 else 1052 { 1053 x = subglyph->arg1; 1054 y = subglyph->arg2; 1055 1056 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1057 { 1058 x = FT_MulFix( x, x_scale ); 1059 y = FT_MulFix( y, y_scale ); 1060 1061 if ( subglyph->flags & ROUND_XY_TO_GRID ) 1062 { 1063 x = ( x + 32 ) & -64; 1064 y = ( y + 32 ) & -64; 1065 } 1066 } 1067 } 1068 1069 if ( x || y ) 1070 { 1071 translate_array( num_new_points, 1072 gloader->base.outline.points + num_base_points, 1073 x, y ); 1074 1075 translate_array( num_new_points, 1076 gloader->base.extra_points + num_base_points, 1077 x, y ); 1078 } 1079 } 1080 1081 /*******************************************************************/ 1082 /*******************************************************************/ 1083 /*******************************************************************/ 1084 1085 /* we have finished loading all sub-glyphs; now, look for */ 1086 /* instructions for this composite! */ 1087 1088#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1089 1090 if ( num_subglyphs > 0 && 1091 loader->exec && 1092 ins_pos > 0 && 1093 subglyph->flags & WE_HAVE_INSTR ) 1094 { 1095 FT_UShort n_ins; 1096 TT_ExecContext exec = loader->exec; 1097 TT_GlyphZone pts; 1098 FT_Vector* pp1; 1099 1100 1101 /* read size of instructions */ 1102 if ( FT_STREAM_SEEK( ins_pos ) || 1103 FT_READ_USHORT( n_ins ) ) 1104 goto Fail; 1105 FT_TRACE5(( " Instructions size = %d\n", n_ins )); 1106 1107 /* in some fonts? */ 1108 if ( n_ins == 0xFFFFU ) 1109 n_ins = 0; 1110 1111 /* check it */ 1112 if ( n_ins > face->max_profile.maxSizeOfInstructions ) 1113 { 1114 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", 1115 n_ins, subglyph->index )); 1116 error = TT_Err_Too_Many_Hints; 1117 goto Fail; 1118 } 1119 1120 /* read the instructions */ 1121 if ( FT_STREAM_READ( exec->glyphIns, n_ins ) ) 1122 goto Fail; 1123 1124 glyph->control_data = exec->glyphIns; 1125 glyph->control_len = n_ins; 1126 1127 error = TT_Set_CodeRange( exec, 1128 tt_coderange_glyph, 1129 exec->glyphIns, 1130 n_ins ); 1131 if ( error ) 1132 goto Fail; 1133 1134 /* prepare the execution context */ 1135 tt_prepare_zone( &exec->pts, &gloader->base, 1136 start_point, start_contour ); 1137 pts = &exec->pts; 1138 1139 pts->n_points = (short)(num_points + 2); 1140 pts->n_contours = gloader->base.outline.n_contours; 1141 1142 /* add phantom points */ 1143 pp1 = pts->cur + num_points; 1144 pp1[0] = loader->pp1; 1145 pp1[1] = loader->pp2; 1146 1147 pts->tags[num_points ] = 0; 1148 pts->tags[num_points + 1] = 0; 1149 1150 /* if hinting, round the phantom points */ 1151 if ( IS_HINTED( loader->load_flags ) ) 1152 { 1153 pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 ); 1154 pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 ); 1155 } 1156 1157 { 1158 FT_UInt k; 1159 1160 1161 for ( k = 0; k < num_points; k++ ) 1162 pts->tags[k] &= FT_Curve_Tag_On; 1163 } 1164 1165 cur_to_org( num_points + 2, pts ); 1166 1167 /* now consider hinting */ 1168 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) 1169 { 1170 exec->is_composite = TRUE; 1171 exec->pedantic_hinting = 1172 (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC ); 1173 1174 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); 1175 if ( error && exec->pedantic_hinting ) 1176 goto Fail; 1177 } 1178 1179 /* save glyph origin and advance points */ 1180 loader->pp1 = pp1[0]; 1181 loader->pp2 = pp1[1]; 1182 } 1183 1184#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1185 1186 } 1187 /* end of composite loading */ 1188 } 1189 1190 /***********************************************************************/ 1191 /***********************************************************************/ 1192 /***********************************************************************/ 1193 1194 Fail: 1195 if ( opened_frame ) 1196 face->forget_glyph_frame( loader ); 1197 1198 Exit: 1199 return error; 1200 } 1201 1202 1203 static void 1204 compute_glyph_metrics( TT_Loader loader, 1205 FT_UInt glyph_index ) 1206 { 1207 FT_BBox bbox; 1208 TT_Face face = (TT_Face)loader->face; 1209 FT_Fixed y_scale; 1210 TT_GlyphSlot glyph = loader->glyph; 1211 TT_Size size = (TT_Size)loader->size; 1212 1213 1214 y_scale = 0x10000L; 1215 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1216 y_scale = size->root.metrics.y_scale; 1217 1218 if ( glyph->format != ft_glyph_format_composite ) 1219 { 1220 glyph->outline.flags &= ~ft_outline_single_pass; 1221 1222 /* copy outline to our glyph slot */ 1223 FT_GlyphLoader_CopyPoints( glyph->internal->loader, loader->gloader ); 1224 glyph->outline = glyph->internal->loader->base.outline; 1225 1226 /* translate array so that (0,0) is the glyph's origin */ 1227 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); 1228 1229 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 1230 1231 if ( IS_HINTED( loader->load_flags ) ) 1232 { 1233 /* grid-fit the bounding box */ 1234 bbox.xMin &= -64; 1235 bbox.yMin &= -64; 1236 bbox.xMax = ( bbox.xMax + 63 ) & -64; 1237 bbox.yMax = ( bbox.yMax + 63 ) & -64; 1238 } 1239 } 1240 else 1241 bbox = loader->bbox; 1242 1243 /* get the device-independent horizontal advance. It is scaled later */ 1244 /* by the base layer. */ 1245 { 1246 FT_Pos advance = loader->linear; 1247 1248 1249 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */ 1250 /* correctly support DynaLab fonts, which have an incorrect */ 1251 /* `advance_Width_Max' field! It is used, to my knowledge, */ 1252 /* exclusively in the X-TrueType font server. */ 1253 /* */ 1254 if ( face->postscript.isFixedPitch && 1255 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) 1256 advance = face->horizontal.advance_Width_Max; 1257 1258 /* we need to return the advance in font units in linearHoriAdvance, */ 1259 /* it will be scaled later by the base layer. */ 1260 glyph->linearHoriAdvance = advance; 1261 } 1262 1263 glyph->metrics.horiBearingX = bbox.xMin; 1264 glyph->metrics.horiBearingY = bbox.yMax; 1265 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 1266 1267 /* don't forget to hint the advance when we need to */ 1268 if ( IS_HINTED( loader->load_flags ) ) 1269 glyph->metrics.horiAdvance = ( glyph->metrics.horiAdvance + 32 ) & -64; 1270 1271 /* Now take care of vertical metrics. In the case where there is */ 1272 /* no vertical information within the font (relatively common), make */ 1273 /* up some metrics by `hand'... */ 1274 1275 { 1276 FT_Short top_bearing; /* vertical top side bearing (EM units) */ 1277 FT_UShort advance_height; /* vertical advance height (EM units) */ 1278 1279 FT_Pos left; /* scaled vertical left side bearing */ 1280 FT_Pos top; /* scaled vertical top side bearing */ 1281 FT_Pos advance; /* scaled vertical advance height */ 1282 1283 1284 /* Get the unscaled `tsb' and `ah' */ 1285 if ( face->vertical_info && 1286 face->vertical.number_Of_VMetrics > 0 ) 1287 { 1288 /* Don't assume that both the vertical header and vertical */ 1289 /* metrics are present in the same font :-) */ 1290 1291 TT_Get_Metrics( (TT_HoriHeader*)&face->vertical, 1292 glyph_index, 1293 &top_bearing, 1294 &advance_height ); 1295 } 1296 else 1297 { 1298 /* Make up the distances from the horizontal header. */ 1299 1300 /* NOTE: The OS/2 values are the only `portable' ones, */ 1301 /* which is why we use them, if there is an OS/2 */ 1302 /* table in the font. Otherwise, we use the */ 1303 /* values defined in the horizontal header. */ 1304 /* */ 1305 /* NOTE2: The sTypoDescender is negative, which is why */ 1306 /* we compute the baseline-to-baseline distance */ 1307 /* here with: */ 1308 /* ascender - descender + linegap */ 1309 /* */ 1310 if ( face->os2.version != 0xFFFFU ) 1311 { 1312 top_bearing = (FT_Short)( face->os2.sTypoLineGap / 2 ); 1313 advance_height = (FT_UShort)( face->os2.sTypoAscender - 1314 face->os2.sTypoDescender + 1315 face->os2.sTypoLineGap ); 1316 } 1317 else 1318 { 1319 top_bearing = (FT_Short)( face->horizontal.Line_Gap / 2 ); 1320 advance_height = (FT_UShort)( face->horizontal.Ascender + 1321 face->horizontal.Descender + 1322 face->horizontal.Line_Gap ); 1323 } 1324 } 1325 1326 /* We must adjust the top_bearing value from the bounding box given */ 1327 /* in the glyph header to te bounding box calculated with */ 1328 /* FT_Get_Outline_CBox(). */ 1329 1330 /* scale the metrics */ 1331 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1332 { 1333 top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) 1334 - bbox.yMax; 1335 advance = FT_MulFix( advance_height, y_scale ); 1336 } 1337 else 1338 { 1339 top = top_bearing + loader->bbox.yMax - bbox.yMax; 1340 advance = advance_height; 1341 } 1342 1343 /* set the advance height in design units. It is scaled later by */ 1344 /* the base layer. */ 1345 glyph->linearVertAdvance = advance_height; 1346 1347 /* XXX: for now, we have no better algorithm for the lsb, but it */ 1348 /* should work fine. */ 1349 /* */ 1350 left = ( bbox.xMin - bbox.xMax ) / 2; 1351 1352 /* grid-fit them if necessary */ 1353 if ( IS_HINTED( loader->load_flags ) ) 1354 { 1355 left &= -64; 1356 top = ( top + 63 ) & -64; 1357 advance = ( advance + 32 ) & -64; 1358 } 1359 1360 glyph->metrics.vertBearingX = left; 1361 glyph->metrics.vertBearingY = top; 1362 glyph->metrics.vertAdvance = advance; 1363 } 1364 1365 /* adjust advance width to the value contained in the hdmx table */ 1366 if ( !face->postscript.isFixedPitch && size && 1367 IS_HINTED( loader->load_flags ) ) 1368 { 1369 FT_Byte* widths = Get_Advance_Widths( face, 1370 size->root.metrics.x_ppem ); 1371 1372 1373 if ( widths ) 1374 glyph->metrics.horiAdvance = widths[glyph_index] << 6; 1375 } 1376 1377 /* set glyph dimensions */ 1378 glyph->metrics.width = bbox.xMax - bbox.xMin; 1379 glyph->metrics.height = bbox.yMax - bbox.yMin; 1380 } 1381 1382 1383 /*************************************************************************/ 1384 /* */ 1385 /* <Function> */ 1386 /* TT_Load_Glyph */ 1387 /* */ 1388 /* <Description> */ 1389 /* A function used to load a single glyph within a given glyph slot, */ 1390 /* for a given size. */ 1391 /* */ 1392 /* <Input> */ 1393 /* glyph :: A handle to a target slot object where the glyph */ 1394 /* will be loaded. */ 1395 /* */ 1396 /* size :: A handle to the source face size at which the glyph */ 1397 /* must be scaled/loaded. */ 1398 /* */ 1399 /* glyph_index :: The index of the glyph in the font file. */ 1400 /* */ 1401 /* load_flags :: A flag indicating what to load for this glyph. The */ 1402 /* FT_LOAD_XXX constants can be used to control the */ 1403 /* glyph loading process (e.g., whether the outline */ 1404 /* should be scaled, whether to load bitmaps or not, */ 1405 /* whether to hint the outline, etc). */ 1406 /* */ 1407 /* <Return> */ 1408 /* FreeType error code. 0 means success. */ 1409 /* */ 1410 FT_LOCAL_DEF( FT_Error ) 1411 TT_Load_Glyph( TT_Size size, 1412 TT_GlyphSlot glyph, 1413 FT_UShort glyph_index, 1414 FT_UInt load_flags ) 1415 { 1416 SFNT_Service sfnt; 1417 TT_Face face; 1418 FT_Stream stream; 1419 FT_Error error; 1420 TT_LoaderRec loader; 1421 1422 1423 face = (TT_Face)glyph->face; 1424 sfnt = (SFNT_Service)face->sfnt; 1425 stream = face->root.stream; 1426 error = 0; 1427 1428 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) || 1429 ( load_flags & FT_LOAD_NO_RECURSE ) ) 1430 { 1431 size = NULL; 1432 load_flags |= FT_LOAD_NO_SCALE | 1433 FT_LOAD_NO_HINTING | 1434 FT_LOAD_NO_BITMAP; 1435 } 1436 1437 glyph->num_subglyphs = 0; 1438 1439#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1440 1441 /* try to load embedded bitmap if any */ 1442 /* */ 1443 /* XXX: The convention should be emphasized in */ 1444 /* the documents because it can be confusing. */ 1445 if ( size && 1446 size->strike_index != 0xFFFFU && 1447 sfnt->load_sbits && 1448 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 ) 1449 1450 { 1451 TT_SBit_MetricsRec metrics; 1452 1453 1454 error = sfnt->load_sbit_image( face, 1455 size->strike_index, 1456 glyph_index, 1457 load_flags, 1458 stream, 1459 &glyph->bitmap, 1460 &metrics ); 1461 if ( !error ) 1462 { 1463 glyph->outline.n_points = 0; 1464 glyph->outline.n_contours = 0; 1465 1466 glyph->metrics.width = (FT_Pos)metrics.width << 6; 1467 glyph->metrics.height = (FT_Pos)metrics.height << 6; 1468 1469 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 1470 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 1471 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 1472 1473 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 1474 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 1475 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 1476 1477 glyph->format = ft_glyph_format_bitmap; 1478 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 1479 { 1480 glyph->bitmap_left = metrics.vertBearingX; 1481 glyph->bitmap_top = metrics.vertBearingY; 1482 } 1483 else 1484 { 1485 glyph->bitmap_left = metrics.horiBearingX; 1486 glyph->bitmap_top = metrics.horiBearingY; 1487 } 1488 return error; 1489 } 1490 } 1491 1492#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1493 1494 /* return immediately if we only want the embedded bitmaps */ 1495 if ( load_flags & FT_LOAD_SBITS_ONLY ) 1496 return FT_Err_Invalid_Argument; 1497 1498 /* seek to the beginning of the glyph table. For Type 42 fonts */ 1499 /* the table might be accessed from a Postscript stream or something */ 1500 /* else... */ 1501 1502 error = face->goto_table( face, TTAG_glyf, stream, 0 ); 1503 if ( error ) 1504 { 1505 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); 1506 goto Exit; 1507 } 1508 1509 FT_MEM_SET( &loader, 0, sizeof ( loader ) ); 1510 1511 /* update the glyph zone bounds */ 1512 { 1513 FT_GlyphLoader gloader = FT_FACE_DRIVER(face)->glyph_loader; 1514 1515 1516 loader.gloader = gloader; 1517 1518 FT_GlyphLoader_Rewind( gloader ); 1519 1520 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); 1521 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); 1522 } 1523 1524#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1525 1526 if ( size ) 1527 { 1528 /* query new execution context */ 1529 loader.exec = size->debug ? size->context : TT_New_Context( face ); 1530 if ( !loader.exec ) 1531 return TT_Err_Could_Not_Find_Context; 1532 1533 TT_Load_Context( loader.exec, face, size ); 1534 loader.instructions = loader.exec->glyphIns; 1535 1536 /* load default graphics state - if needed */ 1537 if ( size->GS.instruct_control & 2 ) 1538 loader.exec->GS = tt_default_graphics_state; 1539 } 1540 1541#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1542 1543 /* clear all outline flags, except the `owner' one */ 1544 glyph->outline.flags = 0; 1545 1546 /* let's initialize the rest of our loader now */ 1547 1548 loader.load_flags = load_flags; 1549 1550 loader.face = (FT_Face)face; 1551 loader.size = (FT_Size)size; 1552 loader.glyph = (FT_GlyphSlot)glyph; 1553 loader.stream = stream; 1554 1555 loader.glyf_offset = FT_STREAM_POS(); 1556 1557#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1558 1559 /* if the cvt program has disabled hinting, the argument */ 1560 /* is ignored. */ 1561 if ( size && ( size->GS.instruct_control & 1 ) ) 1562 loader.load_flags |= FT_LOAD_NO_HINTING; 1563 1564#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1565 1566 /* Main loading loop */ 1567 glyph->format = ft_glyph_format_outline; 1568 glyph->num_subglyphs = 0; 1569 1570 error = load_truetype_glyph( &loader, glyph_index ); 1571 if ( !error ) 1572 compute_glyph_metrics( &loader, glyph_index ); 1573 1574#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1575 1576 if ( !size || !size->debug ) 1577 TT_Done_Context( loader.exec ); 1578 1579#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1580 1581 /* Set the `high precision' bit flag. */ 1582 /* This is _critical_ to get correct output for monochrome */ 1583 /* TrueType glyphs at all sizes using the bytecode interpreter. */ 1584 /* */ 1585 if ( size && size->root.metrics.y_ppem < 24 ) 1586 glyph->outline.flags |= ft_outline_high_precision; 1587 1588 Exit: 1589 return error; 1590 } 1591 1592 1593/* END */ 1594