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