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