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