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