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