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