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