ttgload.c revision 321cd27d0f89f8646c95218b16dca4a3c02d7f17
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 663#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 664 FT_Stream stream = loader->stream; 665#endif 666 667 FT_Error error; 668 TT_Face face = (TT_Face)loader->face; 669 FT_ULong offset; 670 FT_Int contours_count; 671 FT_UInt index, num_points, num_contours, count; 672 FT_Fixed x_scale, y_scale; 673 FT_ULong ins_offset; 674 FT_GlyphLoader* gloader = loader->gloader; 675 FT_Bool opened_frame = 0; 676 677 678 /* check glyph index */ 679 index = glyph_index; 680 if ( index >= (FT_UInt)face->root.num_glyphs ) 681 { 682 error = TT_Err_Invalid_Glyph_Index; 683 goto Exit; 684 } 685 686 loader->glyph_index = glyph_index; 687 num_contours = 0; 688 num_points = 0; 689 ins_offset = 0; 690 691 x_scale = 0x10000L; 692 y_scale = 0x10000L; 693 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 694 { 695 x_scale = loader->size->metrics.x_scale; 696 y_scale = loader->size->metrics.y_scale; 697 } 698 699 /* get horizontal metrics */ 700 { 701 FT_Short left_bearing; 702 FT_UShort advance_width; 703 704 705 Get_HMetrics( face, index, 706 (FT_Bool)!(loader->load_flags & 707 FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH), 708 &left_bearing, 709 &advance_width ); 710 711 loader->left_bearing = left_bearing; 712 loader->advance = advance_width; 713 } 714 715 offset = face->glyph_locations[index]; 716 count = 0; 717 718 if ( index < (FT_UInt)face->num_locations - 1 ) 719 count = face->glyph_locations[index + 1] - offset; 720 721 if ( count == 0 ) 722 { 723 /* as described by Frederic Loyer, these are spaces, and */ 724 /* not the unknown glyph. */ 725 loader->bbox.xMin = 0; 726 loader->bbox.xMax = 0; 727 loader->bbox.yMin = 0; 728 loader->bbox.yMax = 0; 729 730 loader->pp1.x = 0; 731 loader->pp2.x = loader->advance; 732 733 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 734 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 735 736#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 737 738 if ( loader->exec ) 739 loader->exec->glyphSize = 0; 740 741#endif 742 743 error = FT_Err_Ok; 744 goto Exit; 745 } 746 747 offset = loader->glyf_offset + offset; 748 749 /* access glyph frame */ 750 error = face->access_glyph_frame( loader, glyph_index, offset, count ); 751 if ( error ) 752 goto Exit; 753 754 opened_frame = 1; 755 756 /* read first glyph header */ 757 error = face->read_glyph_header( loader ); 758 if ( error ) 759 goto Fail; 760 761 contours_count = loader->n_contours; 762 763 count -= 10; 764 765 loader->pp1.x = loader->bbox.xMin - loader->left_bearing; 766 loader->pp1.y = 0; 767 loader->pp2.x = loader->pp1.x + loader->advance; 768 loader->pp2.y = 0; 769 770 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 771 { 772 loader->pp1.x = FT_MulFix( loader->pp1.x, x_scale ); 773 loader->pp2.x = FT_MulFix( loader->pp2.x, x_scale ); 774 } 775 776 /***********************************************************************/ 777 /***********************************************************************/ 778 /***********************************************************************/ 779 780 /* if it is a simple glyph, load it */ 781 782 if ( contours_count >= 0 ) 783 { 784 /* check that we can add the contours to the glyph */ 785 error = FT_GlyphLoader_Check_Points( gloader, 0, contours_count ); 786 if ( error ) 787 goto Fail; 788 789 error = face->read_simple_glyph( loader ); 790 if ( error ) 791 goto Fail; 792 793#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 794 795 { 796 TT_Size size = (TT_Size)loader->size; 797 798 799 error = TT_Process_Simple_Glyph( loader, 800 (FT_Bool)( size && size->debug ) ); 801 } 802 803#else 804 805 error = TT_Process_Simple_Glyph( loader, 0 ); 806 807#endif 808 809 if ( error ) 810 goto Fail; 811 812 FT_GlyphLoader_Add( gloader ); 813 814 /* Note: We could have put the simple loader source there */ 815 /* but the code is fat enough already :-) */ 816 } 817 818 /***********************************************************************/ 819 /***********************************************************************/ 820 /***********************************************************************/ 821 822 /* otherwise, load a composite! */ 823 else 824 { 825 TT_GlyphSlot glyph = (TT_GlyphSlot)loader->glyph; 826 FT_UInt start_point, start_contour; 827 FT_ULong ins_pos; /* position of composite instructions, if any */ 828 829 830 /* for each subglyph, read composite header */ 831 start_point = gloader->base.outline.n_points; 832 start_contour = gloader->base.outline.n_contours; 833 834 error = face->read_composite_glyph( loader ); 835 if ( error ) 836 goto Fail; 837 838 ins_pos = loader->ins_pos; 839 face->forget_glyph_frame( loader ); 840 opened_frame = 0; 841 842 /* if the flag FT_LOAD_NO_RECURSE is set, we return the subglyph */ 843 /* `as is' in the glyph slot (the client application will be */ 844 /* responsible for interpreting this data)... */ 845 /* */ 846 if ( loader->load_flags & FT_LOAD_NO_RECURSE ) 847 { 848 /* set up remaining glyph fields */ 849 FT_GlyphLoader_Add( gloader ); 850 851 glyph->num_subglyphs = gloader->base.num_subglyphs; 852 glyph->format = ft_glyph_format_composite; 853 glyph->subglyphs = gloader->base.subglyphs; 854 855 goto Exit; 856 } 857 858 /*********************************************************************/ 859 /*********************************************************************/ 860 /*********************************************************************/ 861 862 /* Now, read each subglyph independently. */ 863 { 864 FT_Int n, num_base_points, num_new_points; 865 FT_SubGlyph* subglyph = 0; 866 867 FT_UInt num_subglyphs = gloader->current.num_subglyphs; 868 FT_UInt num_base_subgs = gloader->base.num_subglyphs; 869 870 871 FT_GlyphLoader_Add( gloader ); 872 873 for ( n = 0; n < (FT_Int)num_subglyphs; n++ ) 874 { 875 FT_Vector pp1, pp2; 876 FT_Pos x, y; 877 878 879 /* Each time we call load_truetype_glyph in this loop, the */ 880 /* value of `gloader.base.subglyphs' can change due to table */ 881 /* reallocations. We thus need to recompute the subglyph */ 882 /* pointer on each iteration. */ 883 subglyph = gloader->base.subglyphs + num_base_subgs + n; 884 885 pp1 = loader->pp1; 886 pp2 = loader->pp2; 887 888 num_base_points = gloader->base.outline.n_points; 889 890 error = load_truetype_glyph( loader, subglyph->index ); 891 if ( error ) 892 goto Fail; 893 894 subglyph = gloader->base.subglyphs + num_base_subgs + n; 895 896 if ( subglyph->flags & USE_MY_METRICS ) 897 { 898 pp1 = loader->pp1; 899 pp2 = loader->pp2; 900 } 901 else 902 { 903 loader->pp1 = pp1; 904 loader->pp2 = pp2; 905 } 906 907 num_points = gloader->base.outline.n_points; 908 909 num_new_points = num_points - num_base_points; 910 911 /* now perform the transform required for this subglyph */ 912 913 if ( subglyph->flags & ( WE_HAVE_A_SCALE | 914 WE_HAVE_AN_XY_SCALE | 915 WE_HAVE_A_2X2 ) ) 916 { 917 FT_Vector* cur = gloader->base.outline.points + 918 num_base_points; 919 FT_Vector* org = gloader->base.extra_points + 920 num_base_points; 921 FT_Vector* limit = cur + num_new_points; 922 923 924 for ( ; cur < limit; cur++, org++ ) 925 { 926 FT_Vector_Transform( cur, &subglyph->transform ); 927 FT_Vector_Transform( org, &subglyph->transform ); 928 } 929 } 930 931 /* apply offset */ 932 933 if ( !( subglyph->flags & ARGS_ARE_XY_VALUES ) ) 934 { 935 FT_UInt k = subglyph->arg1; 936 FT_UInt l = subglyph->arg2; 937 FT_Vector* p1; 938 FT_Vector* p2; 939 940 941 if ( start_point + k >= (FT_UInt)num_base_points || 942 l >= (FT_UInt)num_new_points ) 943 { 944 error = TT_Err_Invalid_Composite; 945 goto Fail; 946 } 947 948 l += num_base_points; 949 950 p1 = gloader->base.outline.points + start_point + k; 951 p2 = gloader->base.outline.points + start_point + l; 952 953 x = p1->x - p2->x; 954 y = p1->y - p2->y; 955 } 956 else 957 { 958 x = subglyph->arg1; 959 y = subglyph->arg2; 960 961 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 962 { 963 x = FT_MulFix( x, x_scale ); 964 y = FT_MulFix( y, y_scale ); 965 966 if ( subglyph->flags & ROUND_XY_TO_GRID ) 967 { 968 x = ( x + 32 ) & -64; 969 y = ( y + 32 ) & -64; 970 } 971 } 972 } 973 974 translate_array( num_new_points, loader->zone.cur, x, y ); 975 cur_to_org( num_new_points, &loader->zone ); 976 } 977 978 /*******************************************************************/ 979 /*******************************************************************/ 980 /*******************************************************************/ 981 982 /* we have finished loading all sub-glyphs; now, look for */ 983 /* instructions for this composite! */ 984 985#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 986 987 if ( num_subglyphs > 0 && 988 loader->exec && 989 ins_pos > 0 && 990 subglyph->flags & WE_HAVE_INSTR ) 991 { 992 FT_UShort n_ins; 993 TT_ExecContext exec = loader->exec; 994 TT_GlyphZone* pts; 995 FT_Vector* pp1; 996 997 998 /* read size of instructions */ 999 if ( FILE_Seek( ins_pos ) || 1000 READ_UShort( n_ins ) ) 1001 goto Fail; 1002 FT_TRACE5(( " Instructions size = %d\n", n_ins )); 1003 1004 /* in some fonts? */ 1005 if ( n_ins == 0xFFFF ) 1006 n_ins = 0; 1007 1008 /* check it */ 1009 if ( n_ins > face->max_profile.maxSizeOfInstructions ) 1010 { 1011 FT_TRACE0(( "Too many instructions (%d) in composite glyph %ld\n", 1012 n_ins, subglyph->index )); 1013 return TT_Err_Too_Many_Ins; 1014 } 1015 1016 /* read the instructions */ 1017 if ( FILE_Read( exec->glyphIns, n_ins ) ) 1018 goto Fail; 1019 1020 glyph->control_data = exec->glyphIns; 1021 glyph->control_len = n_ins; 1022 1023 error = TT_Set_CodeRange( exec, 1024 tt_coderange_glyph, 1025 exec->glyphIns, 1026 n_ins ); 1027 if ( error ) 1028 goto Fail; 1029 1030 /* prepare the execution context */ 1031 tt_prepare_zone( &exec->pts, &gloader->base, 1032 start_point, start_contour ); 1033 pts = &exec->pts; 1034 1035 pts->n_points = num_points + 2; 1036 pts->n_contours = gloader->base.outline.n_contours; 1037 1038 /* add phantom points */ 1039 pp1 = pts->cur + num_points; 1040 pp1[0] = loader->pp1; 1041 pp1[1] = loader->pp2; 1042 1043 pts->tags[num_points ] = 0; 1044 pts->tags[num_points + 1] = 0; 1045 1046 /* if hinting, round the phantom points */ 1047 if ( IS_HINTED( loader->load_flags ) ) 1048 { 1049 pp1[0].x = ( ( loader->pp1.x + 32 ) & -64 ); 1050 pp1[1].x = ( ( loader->pp2.x + 32 ) & -64 ); 1051 } 1052 1053 { 1054 FT_UInt k; 1055 1056 1057 for ( k = 0; k < num_points; k++ ) 1058 pts->tags[k] &= FT_Curve_Tag_On; 1059 } 1060 1061 cur_to_org( num_points + 2, pts ); 1062 1063 /* now consider hinting */ 1064 if ( IS_HINTED( loader->load_flags ) && n_ins > 0 ) 1065 { 1066 exec->is_composite = TRUE; 1067 exec->pedantic_hinting = 1068 (FT_Bool)( loader->load_flags & FT_LOAD_PEDANTIC ); 1069 1070 error = TT_Run_Context( exec, ((TT_Size)loader->size)->debug ); 1071 if ( error && exec->pedantic_hinting ) 1072 goto Fail; 1073 } 1074 1075 /* save glyph origin and advance points */ 1076 loader->pp1 = pp1[0]; 1077 loader->pp2 = pp1[1]; 1078 } 1079 1080#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1081 1082 } 1083 /* end of composite loading */ 1084 } 1085 1086 /***********************************************************************/ 1087 /***********************************************************************/ 1088 /***********************************************************************/ 1089 1090 Fail: 1091 if ( opened_frame ) 1092 face->forget_glyph_frame( loader ); 1093 1094 Exit: 1095 return error; 1096 } 1097 1098 1099 static 1100 void compute_glyph_metrics( TT_Loader* loader, 1101 FT_UInt glyph_index ) 1102 { 1103 FT_BBox bbox; 1104 TT_Face face = (TT_Face)loader->face; 1105 FT_Fixed x_scale, y_scale; 1106 TT_GlyphSlot glyph = loader->glyph; 1107 TT_Size size = (TT_Size)loader->size; 1108 1109 1110 x_scale = 0x10000L; 1111 y_scale = 0x10000L; 1112 if ( ( loader->load_flags & FT_LOAD_NO_SCALE ) == 0 ) 1113 { 1114 x_scale = size->root.metrics.x_scale; 1115 y_scale = size->root.metrics.y_scale; 1116 } 1117 1118 if ( glyph->format != ft_glyph_format_composite ) 1119 { 1120 glyph->outline.flags &= ~ft_outline_single_pass; 1121 1122 /* copy outline to our glyph slot */ 1123 FT_GlyphLoader_Copy_Points( glyph->loader, loader->gloader ); 1124 glyph->outline = glyph->loader->base.outline; 1125 1126 /* translate array so that (0,0) is the glyph's origin */ 1127 FT_Outline_Translate( &glyph->outline, -loader->pp1.x, 0 ); 1128 1129 FT_Outline_Get_CBox( &glyph->outline, &bbox ); 1130 1131 if ( IS_HINTED( loader->load_flags ) ) 1132 { 1133 /* grid-fit the bounding box */ 1134 bbox.xMin &= -64; 1135 bbox.yMin &= -64; 1136 bbox.xMax = ( bbox.xMax + 63 ) & -64; 1137 bbox.yMax = ( bbox.yMax + 63 ) & -64; 1138 } 1139 } 1140 else 1141 bbox = loader->bbox; 1142 1143 /* get the device-independent horizontal advance. It is scaled later */ 1144 /* by the base layer. */ 1145 { 1146 FT_Pos advance = loader->advance; 1147 1148 1149 /* the flag FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH was introduced to */ 1150 /* correctly support DynaLab fonts, which have an incorrect */ 1151 /* `advance_Width_Max' field! It is used, to my knowledge, */ 1152 /* exclusively in the X-TrueType font server. */ 1153 /* */ 1154 if ( face->postscript.isFixedPitch && 1155 ( loader->load_flags & FT_LOAD_IGNORE_GLOBAL_ADVANCE_WIDTH ) == 0 ) 1156 advance = face->horizontal.advance_Width_Max; 1157 1158 /* we need to return the advance in font units in linearHoriAdvance, */ 1159 /* it will be scaled later by the base layer. */ 1160 glyph->linearHoriAdvance = advance; 1161 } 1162 1163 glyph->metrics.horiBearingX = bbox.xMin; 1164 glyph->metrics.horiBearingY = bbox.yMax; 1165 glyph->metrics.horiAdvance = loader->pp2.x - loader->pp1.x; 1166 1167 /* Now take care of vertical metrics. In the case where there is */ 1168 /* no vertical information within the font (relatively common), make */ 1169 /* up some metrics by `hand'... */ 1170 1171 { 1172 FT_Short top_bearing; /* vertical top side bearing (EM units) */ 1173 FT_UShort advance_height; /* vertical advance height (EM units) */ 1174 1175 FT_Pos left; /* scaled vertical left side bearing */ 1176 FT_Pos Top; /* scaled original vertical top side bearing */ 1177 FT_Pos top; /* scaled vertical top side bearing */ 1178 FT_Pos advance; /* scaled vertical advance height */ 1179 1180 1181 /* Get the unscaled `tsb' and `ah' */ 1182 if ( face->vertical_info && 1183 face->vertical.number_Of_VMetrics > 0 ) 1184 { 1185 /* Don't assume that both the vertical header and vertical */ 1186 /* metrics are present in the same font :-) */ 1187 1188 TT_Get_Metrics( (TT_HoriHeader*)&face->vertical, 1189 glyph_index, 1190 &top_bearing, 1191 &advance_height ); 1192 } 1193 else 1194 { 1195 /* Make up the distances from the horizontal header. */ 1196 1197 /* NOTE: The OS/2 values are the only `portable' ones, */ 1198 /* which is why we use them, if there is an OS/2 */ 1199 /* table in the font. Otherwise, we use the */ 1200 /* values defined in the horizontal header. */ 1201 /* */ 1202 /* NOTE2: The sTypoDescender is negative, which is why */ 1203 /* we compute the baseline-to-baseline distance */ 1204 /* here with: */ 1205 /* ascender - descender + linegap */ 1206 /* */ 1207 if ( face->os2.version != 0xFFFF ) 1208 { 1209 top_bearing = face->os2.sTypoLineGap / 2; 1210 advance_height = (FT_UShort)( face->os2.sTypoAscender - 1211 face->os2.sTypoDescender + 1212 face->os2.sTypoLineGap ); 1213 } 1214 else 1215 { 1216 top_bearing = face->horizontal.Line_Gap / 2; 1217 advance_height = (FT_UShort)( face->horizontal.Ascender + 1218 face->horizontal.Descender + 1219 face->horizontal.Line_Gap ); 1220 } 1221 } 1222 1223 /* We must adjust the top_bearing value from the bounding box given */ 1224 /* in the glyph header to te bounding box calculated with */ 1225 /* FT_Get_Outline_CBox(). */ 1226 1227 /* scale the metrics */ 1228 if ( !( loader->load_flags & FT_LOAD_NO_SCALE ) ) 1229 { 1230 Top = FT_MulFix( top_bearing, y_scale ); 1231 top = FT_MulFix( top_bearing + loader->bbox.yMax, y_scale ) 1232 - bbox.yMax; 1233 advance = FT_MulFix( advance_height, y_scale ); 1234 } 1235 else 1236 { 1237 Top = top_bearing; 1238 top = top_bearing + loader->bbox.yMax - bbox.yMax; 1239 advance = advance_height; 1240 } 1241 1242 /* set the advance height in design units. It is scaled later by */ 1243 /* the base layer. */ 1244 glyph->linearVertAdvance = advance_height; 1245 1246 /* XXX: for now, we have no better algorithm for the lsb, but it */ 1247 /* should work fine. */ 1248 /* */ 1249 left = ( bbox.xMin - bbox.xMax ) / 2; 1250 1251 /* grid-fit them if necessary */ 1252 if ( IS_HINTED( loader->load_flags ) ) 1253 { 1254 left &= -64; 1255 top = ( top + 63 ) & -64; 1256 advance = ( advance + 32 ) & -64; 1257 } 1258 1259 glyph->metrics.vertBearingX = left; 1260 glyph->metrics.vertBearingY = top; 1261 glyph->metrics.vertAdvance = advance; 1262 } 1263 1264 /* adjust advance width to the value contained in the hdmx table */ 1265 if ( !face->postscript.isFixedPitch && size && 1266 IS_HINTED( loader->load_flags ) ) 1267 { 1268 FT_Byte* widths = Get_Advance_Widths( face, 1269 size->root.metrics.x_ppem ); 1270 1271 1272 if ( widths ) 1273 glyph->metrics.horiAdvance = widths[glyph_index] << 6; 1274 } 1275 1276 /* set glyph dimensions */ 1277 glyph->metrics.width = bbox.xMax - bbox.xMin; 1278 glyph->metrics.height = bbox.yMax - bbox.yMin; 1279 } 1280 1281 1282 /*************************************************************************/ 1283 /* */ 1284 /* <Function> */ 1285 /* TT_Load_Glyph */ 1286 /* */ 1287 /* <Description> */ 1288 /* A function used to load a single glyph within a given glyph slot, */ 1289 /* for a given size. */ 1290 /* */ 1291 /* <Input> */ 1292 /* glyph :: A handle to a target slot object where the glyph */ 1293 /* will be loaded. */ 1294 /* */ 1295 /* size :: A handle to the source face size at which the glyph */ 1296 /* must be scaled/loaded. */ 1297 /* */ 1298 /* glyph_index :: The index of the glyph in the font file. */ 1299 /* */ 1300 /* load_flags :: A flag indicating what to load for this glyph. The */ 1301 /* FT_LOAD_XXX constants can be used to control the */ 1302 /* glyph loading process (e.g., whether the outline */ 1303 /* should be scaled, whether to load bitmaps or not, */ 1304 /* whether to hint the outline, etc). */ 1305 /* */ 1306 /* <Return> */ 1307 /* FreeType error code. 0 means success. */ 1308 /* */ 1309 LOCAL_FUNC 1310 FT_Error TT_Load_Glyph( TT_Size size, 1311 TT_GlyphSlot glyph, 1312 FT_UShort glyph_index, 1313 FT_UInt load_flags ) 1314 { 1315 SFNT_Interface* sfnt; 1316 TT_Face face; 1317 FT_Stream stream; 1318 FT_Memory memory; 1319 FT_Error error; 1320 TT_Loader loader; 1321 1322 1323 face = (TT_Face)glyph->face; 1324 sfnt = (SFNT_Interface*)face->sfnt; 1325 stream = face->root.stream; 1326 memory = face->root.memory; 1327 error = 0; 1328 1329 if ( !size || ( load_flags & FT_LOAD_NO_SCALE ) || 1330 ( load_flags & FT_LOAD_NO_RECURSE ) ) 1331 { 1332 size = NULL; 1333 load_flags |= FT_LOAD_NO_SCALE | 1334 FT_LOAD_NO_HINTING | 1335 FT_LOAD_NO_BITMAP; 1336 } 1337 1338 glyph->num_subglyphs = 0; 1339 1340#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1341 1342 /* try to load embedded bitmap if any */ 1343 if ( size && 1344 ( load_flags & FT_LOAD_NO_BITMAP ) == 0 && 1345 sfnt->load_sbits ) 1346 { 1347 TT_SBit_Metrics metrics; 1348 1349 1350 error = sfnt->load_sbit_image( face, 1351 size->root.metrics.x_ppem, 1352 size->root.metrics.y_ppem, 1353 glyph_index, 1354 load_flags, 1355 stream, 1356 &glyph->bitmap, 1357 &metrics ); 1358 if ( !error ) 1359 { 1360 glyph->outline.n_points = 0; 1361 glyph->outline.n_contours = 0; 1362 1363 glyph->metrics.width = (FT_Pos)metrics.width << 6; 1364 glyph->metrics.height = (FT_Pos)metrics.height << 6; 1365 1366 glyph->metrics.horiBearingX = (FT_Pos)metrics.horiBearingX << 6; 1367 glyph->metrics.horiBearingY = (FT_Pos)metrics.horiBearingY << 6; 1368 glyph->metrics.horiAdvance = (FT_Pos)metrics.horiAdvance << 6; 1369 1370 glyph->metrics.vertBearingX = (FT_Pos)metrics.vertBearingX << 6; 1371 glyph->metrics.vertBearingY = (FT_Pos)metrics.vertBearingY << 6; 1372 glyph->metrics.vertAdvance = (FT_Pos)metrics.vertAdvance << 6; 1373 1374 glyph->format = ft_glyph_format_bitmap; 1375 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 1376 { 1377 glyph->bitmap_left = metrics.vertBearingX; 1378 glyph->bitmap_top = metrics.vertBearingY; 1379 } 1380 else 1381 { 1382 glyph->bitmap_left = metrics.horiBearingX; 1383 glyph->bitmap_top = metrics.horiBearingY; 1384 } 1385 return error; 1386 } 1387 } 1388 1389#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1390 1391 /* seek to the beginning of the glyph table. For Type 42 fonts */ 1392 /* the table might be accessed from a Postscript stream or something */ 1393 /* else... */ 1394 1395 error = face->goto_table( face, TTAG_glyf, stream, 0 ); 1396 if ( error ) 1397 { 1398 FT_ERROR(( "TT_Load_Glyph: could not access glyph table\n" )); 1399 goto Exit; 1400 } 1401 1402 MEM_Set( &loader, 0, sizeof ( loader ) ); 1403 1404 /* update the glyph zone bounds */ 1405 { 1406 FT_GlyphLoader* gloader = FT_FACE_DRIVER(face)->glyph_loader; 1407 1408 1409 loader.gloader = gloader; 1410 1411 FT_GlyphLoader_Rewind( gloader ); 1412 1413 tt_prepare_zone( &loader.zone, &gloader->base, 0, 0 ); 1414 tt_prepare_zone( &loader.base, &gloader->base, 0, 0 ); 1415 } 1416 1417#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1418 1419 if ( size ) 1420 { 1421 /* query new execution context */ 1422 loader.exec = size->debug ? size->context : TT_New_Context( face ); 1423 if ( !loader.exec ) 1424 return TT_Err_Could_Not_Find_Context; 1425 1426 TT_Load_Context( loader.exec, face, size ); 1427 loader.instructions = loader.exec->glyphIns; 1428 1429 /* load default graphics state - if needed */ 1430 if ( size->GS.instruct_control & 2 ) 1431 loader.exec->GS = tt_default_graphics_state; 1432 } 1433 1434#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1435 1436 /* clear all outline flags, except the `owner' one */ 1437 glyph->outline.flags = 0; 1438 1439 if ( size && size->root.metrics.y_ppem < 24 ) 1440 glyph->outline.flags |= ft_outline_high_precision; 1441 1442 /* let's initialize the rest of our loader now */ 1443 1444 loader.load_flags = load_flags; 1445 1446 loader.face = (FT_Face)face; 1447 loader.size = (FT_Size)size; 1448 loader.glyph = (FT_GlyphSlot)glyph; 1449 loader.stream = stream; 1450 1451 loader.glyf_offset = FILE_Pos(); 1452 1453#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1454 1455 /* if the cvt program has disabled hinting, the argument */ 1456 /* is ignored. */ 1457 if ( size && ( size->GS.instruct_control & 1 ) ) 1458 loader.load_flags |= FT_LOAD_NO_HINTING; 1459 1460#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1461 1462 /* Main loading loop */ 1463 glyph->format = ft_glyph_format_outline; 1464 glyph->num_subglyphs = 0; 1465 error = load_truetype_glyph( &loader, glyph_index ); 1466 if ( !error ) 1467 compute_glyph_metrics( &loader, glyph_index ); 1468 1469#ifdef TT_CONFIG_OPTION_BYTECODE_INTERPRETER 1470 1471 if ( !size || !size->debug ) 1472 TT_Done_Context( loader.exec ); 1473 1474#endif /* TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 1475 1476 Exit: 1477 return error; 1478 } 1479 1480 1481/* END */ 1482