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