1 /***************************************************************************/ 2 /* */ 3 /* ttobjs.c */ 4 /* */ 5 /* Objects manager (body). */ 6 /* */ 7 /* Copyright 1996-2011 */ 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 <ft2build.h> 20 #include FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 #include FT_TRUETYPE_TAGS_H 23 #include FT_INTERNAL_SFNT_H 24 25 #include "ttgload.h" 26 #include "ttpload.h" 27 28 #include "tterrors.h" 29 30 #ifdef TT_USE_BYTECODE_INTERPRETER 31 #include "ttinterp.h" 32 #endif 33 34 #ifdef TT_CONFIG_OPTION_UNPATENTED_HINTING 35 #include FT_TRUETYPE_UNPATENTED_H 36 #endif 37 38 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 39 #include "ttgxvar.h" 40 #endif 41 42 /*************************************************************************/ 43 /* */ 44 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 45 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 46 /* messages during execution. */ 47 /* */ 48 #undef FT_COMPONENT 49 #define FT_COMPONENT trace_ttobjs 50 51 52 #ifdef TT_USE_BYTECODE_INTERPRETER 53 54 /*************************************************************************/ 55 /* */ 56 /* GLYPH ZONE FUNCTIONS */ 57 /* */ 58 /*************************************************************************/ 59 60 61 /*************************************************************************/ 62 /* */ 63 /* <Function> */ 64 /* tt_glyphzone_done */ 65 /* */ 66 /* <Description> */ 67 /* Deallocate a glyph zone. */ 68 /* */ 69 /* <Input> */ 70 /* zone :: A pointer to the target glyph zone. */ 71 /* */ 72 FT_LOCAL_DEF( void ) 73 tt_glyphzone_done( TT_GlyphZone zone ) 74 { 75 FT_Memory memory = zone->memory; 76 77 78 if ( memory ) 79 { 80 FT_FREE( zone->contours ); 81 FT_FREE( zone->tags ); 82 FT_FREE( zone->cur ); 83 FT_FREE( zone->org ); 84 FT_FREE( zone->orus ); 85 86 zone->max_points = zone->n_points = 0; 87 zone->max_contours = zone->n_contours = 0; 88 zone->memory = NULL; 89 } 90 } 91 92 93 /*************************************************************************/ 94 /* */ 95 /* <Function> */ 96 /* tt_glyphzone_new */ 97 /* */ 98 /* <Description> */ 99 /* Allocate a new glyph zone. */ 100 /* */ 101 /* <Input> */ 102 /* memory :: A handle to the current memory object. */ 103 /* */ 104 /* maxPoints :: The capacity of glyph zone in points. */ 105 /* */ 106 /* maxContours :: The capacity of glyph zone in contours. */ 107 /* */ 108 /* <Output> */ 109 /* zone :: A pointer to the target glyph zone record. */ 110 /* */ 111 /* <Return> */ 112 /* FreeType error code. 0 means success. */ 113 /* */ 114 FT_LOCAL_DEF( FT_Error ) 115 tt_glyphzone_new( FT_Memory memory, 116 FT_UShort maxPoints, 117 FT_Short maxContours, 118 TT_GlyphZone zone ) 119 { 120 FT_Error error; 121 122 123 FT_MEM_ZERO( zone, sizeof ( *zone ) ); 124 zone->memory = memory; 125 126 if ( FT_NEW_ARRAY( zone->org, maxPoints ) || 127 FT_NEW_ARRAY( zone->cur, maxPoints ) || 128 FT_NEW_ARRAY( zone->orus, maxPoints ) || 129 FT_NEW_ARRAY( zone->tags, maxPoints ) || 130 FT_NEW_ARRAY( zone->contours, maxContours ) ) 131 { 132 tt_glyphzone_done( zone ); 133 } 134 else 135 { 136 zone->max_points = maxPoints; 137 zone->max_contours = maxContours; 138 } 139 140 return error; 141 } 142 #endif /* TT_USE_BYTECODE_INTERPRETER */ 143 144 145 /* Compare the face with a list of well-known `tricky' fonts. */ 146 /* This list shall be expanded as we find more of them. */ 147 148 static FT_Bool 149 tt_check_trickyness_family( FT_String* name ) 150 { 151 152 #define TRICK_NAMES_MAX_CHARACTERS 16 153 #define TRICK_NAMES_COUNT 8 154 155 static const char trick_names[TRICK_NAMES_COUNT] 156 [TRICK_NAMES_MAX_CHARACTERS + 1] = 157 { 158 "DFKaiSho-SB", /* dfkaisb.ttf */ 159 "DFKaiShu", 160 "DFKai-SB", /* kaiu.ttf */ 161 "HuaTianKaiTi?", /* htkt2.ttf */ 162 "HuaTianSongTi?", /* htst3.ttf */ 163 "MingLiU", /* mingliu.ttf & mingliu.ttc */ 164 "PMingLiU", /* mingliu.ttc */ 165 "MingLi43", /* mingli.ttf */ 166 }; 167 168 int nn; 169 170 171 for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) 172 if ( ft_strstr( name, trick_names[nn] ) ) 173 return TRUE; 174 175 return FALSE; 176 } 177 178 179 /* XXX: This function should be in the `sfnt' module. */ 180 181 /* Some PDF generators clear the checksums in the TrueType header table. */ 182 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */ 183 /* Printer clears the entries for subsetted subtables. We thus have to */ 184 /* recalculate the checksums where necessary. */ 185 186 static FT_UInt32 187 tt_synth_sfnt_checksum( FT_Stream stream, 188 FT_ULong length ) 189 { 190 FT_Error error; 191 FT_UInt32 checksum = 0; 192 int i; 193 194 195 if ( FT_FRAME_ENTER( length ) ) 196 return 0; 197 198 for ( ; length > 3; length -= 4 ) 199 checksum += (FT_UInt32)FT_GET_ULONG(); 200 201 for ( i = 3; length > 0; length --, i-- ) 202 checksum += (FT_UInt32)( FT_GET_BYTE() << ( i * 8 ) ); 203 204 FT_FRAME_EXIT(); 205 206 return checksum; 207 } 208 209 210 /* XXX: This function should be in the `sfnt' module. */ 211 212 static FT_ULong 213 tt_get_sfnt_checksum( TT_Face face, 214 FT_UShort i ) 215 { 216 #if 0 /* if we believe the written value, use following part. */ 217 if ( face->dir_tables[i].CheckSum ) 218 return face->dir_tables[i].CheckSum; 219 #endif 220 221 if ( !face->goto_table ) 222 return 0; 223 224 if ( face->goto_table( face, 225 face->dir_tables[i].Tag, 226 face->root.stream, 227 NULL ) ) 228 return 0; 229 230 return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream, 231 face->dir_tables[i].Length ); 232 } 233 234 235 typedef struct tt_sfnt_id_rec_ 236 { 237 FT_ULong CheckSum; 238 FT_ULong Length; 239 240 } tt_sfnt_id_rec; 241 242 243 static FT_Bool 244 tt_check_trickyness_sfnt_ids( TT_Face face ) 245 { 246 #define TRICK_SFNT_IDS_PER_FACE 3 247 #define TRICK_SFNT_IDS_NUM_FACES 13 248 249 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] 250 [TRICK_SFNT_IDS_PER_FACE] = { 251 252 #define TRICK_SFNT_ID_cvt 0 253 #define TRICK_SFNT_ID_fpgm 1 254 #define TRICK_SFNT_ID_prep 2 255 256 { /* MingLiU 1995 */ 257 { 0x05bcf058, 0x000002e4 }, /* cvt */ 258 { 0x28233bf1, 0x000087c4 }, /* fpgm */ 259 { 0xa344a1ea, 0x000001e1 } /* prep */ 260 }, 261 { /* MingLiU 1996- */ 262 { 0x05bcf058, 0x000002e4 }, /* cvt */ 263 { 0x28233bf1, 0x000087c4 }, /* fpgm */ 264 { 0xa344a1eb, 0x000001e1 } /* prep */ 265 }, 266 { /* DFKaiShu */ 267 { 0x11e5ead4, 0x00000350 }, /* cvt */ 268 { 0x5a30ca3b, 0x00009063 }, /* fpgm */ 269 { 0x13a42602, 0x0000007e } /* prep */ 270 }, 271 { /* HuaTianKaiTi */ 272 { 0xfffbfffc, 0x00000008 }, /* cvt */ 273 { 0x9c9e48b8, 0x0000bea2 }, /* fpgm */ 274 { 0x70020112, 0x00000008 } /* prep */ 275 }, 276 { /* HuaTianSongTi */ 277 { 0xfffbfffc, 0x00000008 }, /* cvt */ 278 { 0x0a5a0483, 0x00017c39 }, /* fpgm */ 279 { 0x70020112, 0x00000008 } /* prep */ 280 }, 281 { /* NEC fadpop7.ttf */ 282 { 0x00000000, 0x00000000 }, /* cvt */ 283 { 0x40c92555, 0x000000e5 }, /* fpgm */ 284 { 0xa39b58e3, 0x0000117c } /* prep */ 285 }, 286 { /* NEC fadrei5.ttf */ 287 { 0x00000000, 0x00000000 }, /* cvt */ 288 { 0x33c41652, 0x000000e5 }, /* fpgm */ 289 { 0x26d6c52a, 0x00000f6a } /* prep */ 290 }, 291 { /* NEC fangot7.ttf */ 292 { 0x00000000, 0x00000000 }, /* cvt */ 293 { 0x6db1651d, 0x0000019d }, /* fpgm */ 294 { 0x6c6e4b03, 0x00002492 } /* prep */ 295 }, 296 { /* NEC fangyo5.ttf */ 297 { 0x00000000, 0x00000000 }, /* cvt */ 298 { 0x40c92555, 0x000000e5 }, /* fpgm */ 299 { 0xde51fad0, 0x0000117c } /* prep */ 300 }, 301 { /* NEC fankyo5.ttf */ 302 { 0x00000000, 0x00000000 }, /* cvt */ 303 { 0x85e47664, 0x000000e5 }, /* fpgm */ 304 { 0xa6c62831, 0x00001caa } /* prep */ 305 }, 306 { /* NEC fanrgo5.ttf */ 307 { 0x00000000, 0x00000000 }, /* cvt */ 308 { 0x2d891cfd, 0x0000019d }, /* fpgm */ 309 { 0xa0604633, 0x00001de8 } /* prep */ 310 }, 311 { /* NEC fangot5.ttc */ 312 { 0x00000000, 0x00000000 }, /* cvt */ 313 { 0x40aa774c, 0x000001cb }, /* fpgm */ 314 { 0x9b5caa96, 0x00001f9a } /* prep */ 315 }, 316 { /* NEC fanmin3.ttc */ 317 { 0x00000000, 0x00000000 }, /* cvt */ 318 { 0x0d3de9cb, 0x00000141 }, /* fpgm */ 319 { 0xd4127766, 0x00002280 } /* prep */ 320 } 321 }; 322 323 FT_ULong checksum; 324 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; 325 FT_Bool has_cvt, has_fpgm, has_prep; 326 FT_UShort i; 327 int j, k; 328 329 330 FT_MEM_SET( num_matched_ids, 0, 331 sizeof( int ) * TRICK_SFNT_IDS_NUM_FACES ); 332 has_cvt = FALSE; 333 has_fpgm = FALSE; 334 has_prep = FALSE; 335 336 for ( i = 0; i < face->num_tables; i++ ) 337 { 338 checksum = 0; 339 340 switch( face->dir_tables[i].Tag ) 341 { 342 case TTAG_cvt: 343 k = TRICK_SFNT_ID_cvt; 344 has_cvt = TRUE; 345 break; 346 347 case TTAG_fpgm: 348 k = TRICK_SFNT_ID_fpgm; 349 has_fpgm = TRUE; 350 break; 351 352 case TTAG_prep: 353 k = TRICK_SFNT_ID_prep; 354 has_prep = TRUE; 355 break; 356 357 default: 358 continue; 359 } 360 361 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 362 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) 363 { 364 if ( !checksum ) 365 checksum = tt_get_sfnt_checksum( face, i ); 366 367 if ( sfnt_id[j][k].CheckSum == checksum ) 368 num_matched_ids[j]++; 369 370 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 371 return TRUE; 372 } 373 } 374 375 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 376 { 377 if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length ) 378 num_matched_ids[j] ++; 379 if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length ) 380 num_matched_ids[j] ++; 381 if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length ) 382 num_matched_ids[j] ++; 383 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 384 return TRUE; 385 } 386 387 return FALSE; 388 } 389 390 391 static FT_Bool 392 tt_check_trickyness( FT_Face face ) 393 { 394 if ( !face ) 395 return FALSE; 396 397 /* For first, check the face name for quick check. */ 398 if ( face->family_name && 399 tt_check_trickyness_family( face->family_name ) ) 400 return TRUE; 401 402 /* Type42 fonts may lack `name' tables, we thus try to identify */ 403 /* tricky fonts by checking the checksums of Type42-persistent */ 404 /* sfnt tables (`cvt', `fpgm', and `prep'). */ 405 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) 406 return TRUE; 407 408 return FALSE; 409 } 410 411 412 /* Check whether `.notdef' is the only glyph in the `loca' table. */ 413 static FT_Bool 414 tt_check_single_notdef( FT_Face ttface ) 415 { 416 FT_Bool result = FALSE; 417 418 TT_Face face = (TT_Face)ttface; 419 FT_UInt asize; 420 FT_ULong i; 421 FT_ULong glyph_index = 0; 422 FT_UInt count = 0; 423 424 425 for( i = 0; i < face->num_locations; i++ ) 426 { 427 tt_face_get_location( face, i, &asize ); 428 if ( asize > 0 ) 429 { 430 count += 1; 431 if ( count > 1 ) 432 break; 433 glyph_index = i; 434 } 435 } 436 437 /* Only have a single outline. */ 438 if ( count == 1 ) 439 { 440 if ( glyph_index == 0 ) 441 result = TRUE; 442 else 443 { 444 /* FIXME: Need to test glyphname == .notdef ? */ 445 FT_Error error; 446 char buf[8]; 447 448 449 error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 ); 450 if ( !error && 451 buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) ) 452 result = TRUE; 453 } 454 } 455 456 return result; 457 } 458 459 460 /*************************************************************************/ 461 /* */ 462 /* <Function> */ 463 /* tt_face_init */ 464 /* */ 465 /* <Description> */ 466 /* Initialize a given TrueType face object. */ 467 /* */ 468 /* <Input> */ 469 /* stream :: The source font stream. */ 470 /* */ 471 /* face_index :: The index of the font face in the resource. */ 472 /* */ 473 /* num_params :: Number of additional generic parameters. Ignored. */ 474 /* */ 475 /* params :: Additional generic parameters. Ignored. */ 476 /* */ 477 /* <InOut> */ 478 /* face :: The newly built face object. */ 479 /* */ 480 /* <Return> */ 481 /* FreeType error code. 0 means success. */ 482 /* */ 483 FT_LOCAL_DEF( FT_Error ) 484 tt_face_init( FT_Stream stream, 485 FT_Face ttface, /* TT_Face */ 486 FT_Int face_index, 487 FT_Int num_params, 488 FT_Parameter* params ) 489 { 490 FT_Error error; 491 FT_Library library; 492 SFNT_Service sfnt; 493 TT_Face face = (TT_Face)ttface; 494 495 496 library = ttface->driver->root.library; 497 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 498 if ( !sfnt ) 499 goto Bad_Format; 500 501 /* create input stream from resource */ 502 if ( FT_STREAM_SEEK( 0 ) ) 503 goto Exit; 504 505 /* check that we have a valid TrueType file */ 506 error = sfnt->init_face( stream, face, face_index, num_params, params ); 507 if ( error ) 508 goto Exit; 509 510 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ 511 /* The 0x00020000 tag is completely undocumented; some fonts from */ 512 /* Arphic made for Chinese Windows 3.1 have this. */ 513 if ( face->format_tag != 0x00010000L && /* MS fonts */ 514 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ 515 face->format_tag != TTAG_true ) /* Mac fonts */ 516 { 517 FT_TRACE2(( "[not a valid TTF font]\n" )); 518 goto Bad_Format; 519 } 520 521 #ifdef TT_USE_BYTECODE_INTERPRETER 522 ttface->face_flags |= FT_FACE_FLAG_HINTER; 523 #endif 524 525 /* If we are performing a simple font format check, exit immediately. */ 526 if ( face_index < 0 ) 527 return TT_Err_Ok; 528 529 /* Load font directory */ 530 error = sfnt->load_face( stream, face, face_index, num_params, params ); 531 if ( error ) 532 goto Exit; 533 534 if ( tt_check_trickyness( ttface ) ) 535 ttface->face_flags |= FT_FACE_FLAG_TRICKY; 536 537 error = tt_face_load_hdmx( face, stream ); 538 if ( error ) 539 goto Exit; 540 541 if ( FT_IS_SCALABLE( ttface ) ) 542 { 543 544 #ifdef FT_CONFIG_OPTION_INCREMENTAL 545 546 if ( !ttface->internal->incremental_interface ) 547 error = tt_face_load_loca( face, stream ); 548 if ( !error ) 549 error = tt_face_load_cvt( face, stream ); 550 if ( !error ) 551 error = tt_face_load_fpgm( face, stream ); 552 if ( !error ) 553 error = tt_face_load_prep( face, stream ); 554 555 /* Check the scalable flag based on `loca'. */ 556 if ( !ttface->internal->incremental_interface && 557 ttface->num_fixed_sizes && 558 face->glyph_locations && 559 tt_check_single_notdef( ttface ) ) 560 { 561 FT_TRACE5(( "tt_face_init:" 562 " Only the `.notdef' glyph has an outline.\n" 563 " " 564 " Resetting scalable flag to FALSE.\n" )); 565 566 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 567 } 568 569 #else 570 571 if ( !error ) 572 error = tt_face_load_loca( face, stream ); 573 if ( !error ) 574 error = tt_face_load_cvt( face, stream ); 575 if ( !error ) 576 error = tt_face_load_fpgm( face, stream ); 577 if ( !error ) 578 error = tt_face_load_prep( face, stream ); 579 580 /* Check the scalable flag based on `loca'. */ 581 if ( ttface->num_fixed_sizes && 582 face->glyph_locations && 583 tt_check_single_notdef( ttface ) ) 584 { 585 FT_TRACE5(( "tt_face_init:" 586 " Only the `.notdef' glyph has an outline.\n" 587 " " 588 " Resetting scalable flag to FALSE.\n" )); 589 590 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 591 } 592 593 #endif 594 595 } 596 597 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ 598 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) 599 600 { 601 FT_Bool unpatented_hinting; 602 int i; 603 604 605 /* Determine whether unpatented hinting is to be used for this face. */ 606 unpatented_hinting = FT_BOOL 607 ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL ); 608 609 for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) 610 if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) 611 unpatented_hinting = TRUE; 612 613 if ( !unpatented_hinting ) 614 ttface->internal->ignore_unpatented_hinter = TRUE; 615 } 616 617 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING && 618 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 619 620 /* initialize standard glyph loading routines */ 621 TT_Init_Glyph_Loading( face ); 622 623 Exit: 624 return error; 625 626 Bad_Format: 627 error = TT_Err_Unknown_File_Format; 628 goto Exit; 629 } 630 631 632 /*************************************************************************/ 633 /* */ 634 /* <Function> */ 635 /* tt_face_done */ 636 /* */ 637 /* <Description> */ 638 /* Finalize a given face object. */ 639 /* */ 640 /* <Input> */ 641 /* face :: A pointer to the face object to destroy. */ 642 /* */ 643 FT_LOCAL_DEF( void ) 644 tt_face_done( FT_Face ttface ) /* TT_Face */ 645 { 646 TT_Face face = (TT_Face)ttface; 647 FT_Memory memory; 648 FT_Stream stream; 649 SFNT_Service sfnt; 650 651 652 if ( !face ) 653 return; 654 655 memory = ttface->memory; 656 stream = ttface->stream; 657 sfnt = (SFNT_Service)face->sfnt; 658 659 /* for `extended TrueType formats' (i.e. compressed versions) */ 660 if ( face->extra.finalizer ) 661 face->extra.finalizer( face->extra.data ); 662 663 if ( sfnt ) 664 sfnt->done_face( face ); 665 666 /* freeing the locations table */ 667 tt_face_done_loca( face ); 668 669 tt_face_free_hdmx( face ); 670 671 /* freeing the CVT */ 672 FT_FREE( face->cvt ); 673 face->cvt_size = 0; 674 675 /* freeing the programs */ 676 FT_FRAME_RELEASE( face->font_program ); 677 FT_FRAME_RELEASE( face->cvt_program ); 678 face->font_program_size = 0; 679 face->cvt_program_size = 0; 680 681 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 682 tt_done_blend( memory, face->blend ); 683 face->blend = NULL; 684 #endif 685 } 686 687 688 /*************************************************************************/ 689 /* */ 690 /* SIZE FUNCTIONS */ 691 /* */ 692 /*************************************************************************/ 693 694 #ifdef TT_USE_BYTECODE_INTERPRETER 695 696 /*************************************************************************/ 697 /* */ 698 /* <Function> */ 699 /* tt_size_run_fpgm */ 700 /* */ 701 /* <Description> */ 702 /* Run the font program. */ 703 /* */ 704 /* <Input> */ 705 /* size :: A handle to the size object. */ 706 /* */ 707 /* pedantic :: Set if bytecode execution should be pedantic. */ 708 /* */ 709 /* <Return> */ 710 /* FreeType error code. 0 means success. */ 711 /* */ 712 FT_LOCAL_DEF( FT_Error ) 713 tt_size_run_fpgm( TT_Size size, 714 FT_Bool pedantic ) 715 { 716 TT_Face face = (TT_Face)size->root.face; 717 TT_ExecContext exec; 718 FT_Error error; 719 720 721 /* debugging instances have their own context */ 722 if ( size->debug ) 723 exec = size->context; 724 else 725 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 726 727 if ( !exec ) 728 return TT_Err_Could_Not_Find_Context; 729 730 TT_Load_Context( exec, face, size ); 731 732 exec->callTop = 0; 733 exec->top = 0; 734 735 exec->period = 64; 736 exec->phase = 0; 737 exec->threshold = 0; 738 739 exec->instruction_trap = FALSE; 740 exec->F_dot_P = 0x10000L; 741 742 exec->pedantic_hinting = pedantic; 743 744 { 745 FT_Size_Metrics* metrics = &exec->metrics; 746 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 747 748 749 metrics->x_ppem = 0; 750 metrics->y_ppem = 0; 751 metrics->x_scale = 0; 752 metrics->y_scale = 0; 753 754 tt_metrics->ppem = 0; 755 tt_metrics->scale = 0; 756 tt_metrics->ratio = 0x10000L; 757 } 758 759 /* allow font program execution */ 760 TT_Set_CodeRange( exec, 761 tt_coderange_font, 762 face->font_program, 763 face->font_program_size ); 764 765 /* disable CVT and glyph programs coderange */ 766 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 767 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 768 769 if ( face->font_program_size > 0 ) 770 { 771 error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 772 773 if ( !error ) 774 { 775 FT_TRACE4(( "Executing `fpgm' table.\n" )); 776 777 error = face->interpreter( exec ); 778 } 779 } 780 else 781 error = TT_Err_Ok; 782 783 if ( !error ) 784 TT_Save_Context( exec, size ); 785 786 return error; 787 } 788 789 790 /*************************************************************************/ 791 /* */ 792 /* <Function> */ 793 /* tt_size_run_prep */ 794 /* */ 795 /* <Description> */ 796 /* Run the control value program. */ 797 /* */ 798 /* <Input> */ 799 /* size :: A handle to the size object. */ 800 /* */ 801 /* pedantic :: Set if bytecode execution should be pedantic. */ 802 /* */ 803 /* <Return> */ 804 /* FreeType error code. 0 means success. */ 805 /* */ 806 FT_LOCAL_DEF( FT_Error ) 807 tt_size_run_prep( TT_Size size, 808 FT_Bool pedantic ) 809 { 810 TT_Face face = (TT_Face)size->root.face; 811 TT_ExecContext exec; 812 FT_Error error; 813 814 815 /* debugging instances have their own context */ 816 if ( size->debug ) 817 exec = size->context; 818 else 819 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 820 821 if ( !exec ) 822 return TT_Err_Could_Not_Find_Context; 823 824 TT_Load_Context( exec, face, size ); 825 826 exec->callTop = 0; 827 exec->top = 0; 828 829 exec->instruction_trap = FALSE; 830 831 exec->pedantic_hinting = pedantic; 832 833 TT_Set_CodeRange( exec, 834 tt_coderange_cvt, 835 face->cvt_program, 836 face->cvt_program_size ); 837 838 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 839 840 if ( face->cvt_program_size > 0 ) 841 { 842 error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 843 844 if ( !error && !size->debug ) 845 { 846 FT_TRACE4(( "Executing `prep' table.\n" )); 847 848 error = face->interpreter( exec ); 849 } 850 } 851 else 852 error = TT_Err_Ok; 853 854 /* save as default graphics state */ 855 size->GS = exec->GS; 856 857 TT_Save_Context( exec, size ); 858 859 return error; 860 } 861 862 #endif /* TT_USE_BYTECODE_INTERPRETER */ 863 864 865 #ifdef TT_USE_BYTECODE_INTERPRETER 866 867 static void 868 tt_size_done_bytecode( FT_Size ftsize ) 869 { 870 TT_Size size = (TT_Size)ftsize; 871 TT_Face face = (TT_Face)ftsize->face; 872 FT_Memory memory = face->root.memory; 873 874 875 if ( size->debug ) 876 { 877 /* the debug context must be deleted by the debugger itself */ 878 size->context = NULL; 879 size->debug = FALSE; 880 } 881 882 FT_FREE( size->cvt ); 883 size->cvt_size = 0; 884 885 /* free storage area */ 886 FT_FREE( size->storage ); 887 size->storage_size = 0; 888 889 /* twilight zone */ 890 tt_glyphzone_done( &size->twilight ); 891 892 FT_FREE( size->function_defs ); 893 FT_FREE( size->instruction_defs ); 894 895 size->num_function_defs = 0; 896 size->max_function_defs = 0; 897 size->num_instruction_defs = 0; 898 size->max_instruction_defs = 0; 899 900 size->max_func = 0; 901 size->max_ins = 0; 902 903 size->bytecode_ready = 0; 904 size->cvt_ready = 0; 905 } 906 907 908 /* Initialize bytecode-related fields in the size object. */ 909 /* We do this only if bytecode interpretation is really needed. */ 910 static FT_Error 911 tt_size_init_bytecode( FT_Size ftsize, 912 FT_Bool pedantic ) 913 { 914 FT_Error error; 915 TT_Size size = (TT_Size)ftsize; 916 TT_Face face = (TT_Face)ftsize->face; 917 FT_Memory memory = face->root.memory; 918 FT_Int i; 919 920 FT_UShort n_twilight; 921 TT_MaxProfile* maxp = &face->max_profile; 922 923 924 size->bytecode_ready = 1; 925 size->cvt_ready = 0; 926 927 size->max_function_defs = maxp->maxFunctionDefs; 928 size->max_instruction_defs = maxp->maxInstructionDefs; 929 930 size->num_function_defs = 0; 931 size->num_instruction_defs = 0; 932 933 size->max_func = 0; 934 size->max_ins = 0; 935 936 size->cvt_size = face->cvt_size; 937 size->storage_size = maxp->maxStorage; 938 939 /* Set default metrics */ 940 { 941 TT_Size_Metrics* metrics = &size->ttmetrics; 942 943 944 metrics->rotated = FALSE; 945 metrics->stretched = FALSE; 946 947 /* set default compensation (all 0) */ 948 for ( i = 0; i < 4; i++ ) 949 metrics->compensations[i] = 0; 950 } 951 952 /* allocate function defs, instruction defs, cvt, and storage area */ 953 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 954 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 955 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 956 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 957 goto Exit; 958 959 /* reserve twilight zone */ 960 n_twilight = maxp->maxTwilightPoints; 961 962 /* there are 4 phantom points (do we need this?) */ 963 n_twilight += 4; 964 965 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 966 if ( error ) 967 goto Exit; 968 969 size->twilight.n_points = n_twilight; 970 971 size->GS = tt_default_graphics_state; 972 973 /* set `face->interpreter' according to the debug hook present */ 974 { 975 FT_Library library = face->root.driver->root.library; 976 977 978 face->interpreter = (TT_Interpreter) 979 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 980 if ( !face->interpreter ) 981 face->interpreter = (TT_Interpreter)TT_RunIns; 982 } 983 984 /* Fine, now run the font program! */ 985 error = tt_size_run_fpgm( size, pedantic ); 986 987 Exit: 988 if ( error ) 989 tt_size_done_bytecode( ftsize ); 990 991 return error; 992 } 993 994 995 FT_LOCAL_DEF( FT_Error ) 996 tt_size_ready_bytecode( TT_Size size, 997 FT_Bool pedantic ) 998 { 999 FT_Error error = TT_Err_Ok; 1000 1001 1002 if ( !size->bytecode_ready ) 1003 { 1004 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1005 if ( error ) 1006 goto Exit; 1007 } 1008 1009 /* rescale CVT when needed */ 1010 if ( !size->cvt_ready ) 1011 { 1012 FT_UInt i; 1013 TT_Face face = (TT_Face)size->root.face; 1014 1015 1016 /* Scale the cvt values to the new ppem. */ 1017 /* We use by default the y ppem to scale the CVT. */ 1018 for ( i = 0; i < size->cvt_size; i++ ) 1019 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 1020 1021 /* all twilight points are originally zero */ 1022 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) 1023 { 1024 size->twilight.org[i].x = 0; 1025 size->twilight.org[i].y = 0; 1026 size->twilight.cur[i].x = 0; 1027 size->twilight.cur[i].y = 0; 1028 } 1029 1030 /* clear storage area */ 1031 for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) 1032 size->storage[i] = 0; 1033 1034 size->GS = tt_default_graphics_state; 1035 1036 error = tt_size_run_prep( size, pedantic ); 1037 if ( !error ) 1038 size->cvt_ready = 1; 1039 } 1040 1041 Exit: 1042 return error; 1043 } 1044 1045 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1046 1047 1048 /*************************************************************************/ 1049 /* */ 1050 /* <Function> */ 1051 /* tt_size_init */ 1052 /* */ 1053 /* <Description> */ 1054 /* Initialize a new TrueType size object. */ 1055 /* */ 1056 /* <InOut> */ 1057 /* size :: A handle to the size object. */ 1058 /* */ 1059 /* <Return> */ 1060 /* FreeType error code. 0 means success. */ 1061 /* */ 1062 FT_LOCAL_DEF( FT_Error ) 1063 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1064 { 1065 TT_Size size = (TT_Size)ttsize; 1066 FT_Error error = TT_Err_Ok; 1067 1068 #ifdef TT_USE_BYTECODE_INTERPRETER 1069 size->bytecode_ready = 0; 1070 size->cvt_ready = 0; 1071 #endif 1072 1073 size->ttmetrics.valid = FALSE; 1074 size->strike_index = 0xFFFFFFFFUL; 1075 1076 return error; 1077 } 1078 1079 1080 /*************************************************************************/ 1081 /* */ 1082 /* <Function> */ 1083 /* tt_size_done */ 1084 /* */ 1085 /* <Description> */ 1086 /* The TrueType size object finalizer. */ 1087 /* */ 1088 /* <Input> */ 1089 /* size :: A handle to the target size object. */ 1090 /* */ 1091 FT_LOCAL_DEF( void ) 1092 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1093 { 1094 TT_Size size = (TT_Size)ttsize; 1095 1096 1097 #ifdef TT_USE_BYTECODE_INTERPRETER 1098 if ( size->bytecode_ready ) 1099 tt_size_done_bytecode( ttsize ); 1100 #endif 1101 1102 size->ttmetrics.valid = FALSE; 1103 } 1104 1105 1106 /*************************************************************************/ 1107 /* */ 1108 /* <Function> */ 1109 /* tt_size_reset */ 1110 /* */ 1111 /* <Description> */ 1112 /* Reset a TrueType size when resolutions and character dimensions */ 1113 /* have been changed. */ 1114 /* */ 1115 /* <Input> */ 1116 /* size :: A handle to the target size object. */ 1117 /* */ 1118 FT_LOCAL_DEF( FT_Error ) 1119 tt_size_reset( TT_Size size ) 1120 { 1121 TT_Face face; 1122 FT_Error error = TT_Err_Ok; 1123 FT_Size_Metrics* metrics; 1124 1125 1126 size->ttmetrics.valid = FALSE; 1127 1128 face = (TT_Face)size->root.face; 1129 1130 metrics = &size->metrics; 1131 1132 /* copy the result from base layer */ 1133 *metrics = size->root.metrics; 1134 1135 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) 1136 return TT_Err_Invalid_PPem; 1137 1138 /* This bit flag, if set, indicates that the ppems must be */ 1139 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1140 /* set, as hinting won't work really well otherwise. */ 1141 /* */ 1142 if ( face->header.Flags & 8 ) 1143 { 1144 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1145 face->root.units_per_EM ); 1146 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1147 face->root.units_per_EM ); 1148 1149 metrics->ascender = 1150 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); 1151 metrics->descender = 1152 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); 1153 metrics->height = 1154 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); 1155 metrics->max_advance = 1156 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, 1157 metrics->x_scale ) ); 1158 } 1159 1160 /* compute new transformation */ 1161 if ( metrics->x_ppem >= metrics->y_ppem ) 1162 { 1163 size->ttmetrics.scale = metrics->x_scale; 1164 size->ttmetrics.ppem = metrics->x_ppem; 1165 size->ttmetrics.x_ratio = 0x10000L; 1166 size->ttmetrics.y_ratio = FT_MulDiv( metrics->y_ppem, 1167 0x10000L, 1168 metrics->x_ppem ); 1169 } 1170 else 1171 { 1172 size->ttmetrics.scale = metrics->y_scale; 1173 size->ttmetrics.ppem = metrics->y_ppem; 1174 size->ttmetrics.x_ratio = FT_MulDiv( metrics->x_ppem, 1175 0x10000L, 1176 metrics->y_ppem ); 1177 size->ttmetrics.y_ratio = 0x10000L; 1178 } 1179 1180 #ifdef TT_USE_BYTECODE_INTERPRETER 1181 size->cvt_ready = 0; 1182 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1183 1184 if ( !error ) 1185 size->ttmetrics.valid = TRUE; 1186 1187 return error; 1188 } 1189 1190 1191 /*************************************************************************/ 1192 /* */ 1193 /* <Function> */ 1194 /* tt_driver_init */ 1195 /* */ 1196 /* <Description> */ 1197 /* Initialize a given TrueType driver object. */ 1198 /* */ 1199 /* <Input> */ 1200 /* driver :: A handle to the target driver object. */ 1201 /* */ 1202 /* <Return> */ 1203 /* FreeType error code. 0 means success. */ 1204 /* */ 1205 FT_LOCAL_DEF( FT_Error ) 1206 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1207 { 1208 1209 #ifdef TT_USE_BYTECODE_INTERPRETER 1210 1211 TT_Driver driver = (TT_Driver)ttdriver; 1212 1213 1214 if ( !TT_New_Context( driver ) ) 1215 return TT_Err_Could_Not_Find_Context; 1216 1217 #else 1218 1219 FT_UNUSED( ttdriver ); 1220 1221 #endif 1222 1223 return TT_Err_Ok; 1224 } 1225 1226 1227 /*************************************************************************/ 1228 /* */ 1229 /* <Function> */ 1230 /* tt_driver_done */ 1231 /* */ 1232 /* <Description> */ 1233 /* Finalize a given TrueType driver. */ 1234 /* */ 1235 /* <Input> */ 1236 /* driver :: A handle to the target TrueType driver. */ 1237 /* */ 1238 FT_LOCAL_DEF( void ) 1239 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1240 { 1241 #ifdef TT_USE_BYTECODE_INTERPRETER 1242 TT_Driver driver = (TT_Driver)ttdriver; 1243 1244 1245 /* destroy the execution context */ 1246 if ( driver->context ) 1247 { 1248 TT_Done_Context( driver->context ); 1249 driver->context = NULL; 1250 } 1251 #else 1252 FT_UNUSED( ttdriver ); 1253 #endif 1254 1255 } 1256 1257 1258 /*************************************************************************/ 1259 /* */ 1260 /* <Function> */ 1261 /* tt_slot_init */ 1262 /* */ 1263 /* <Description> */ 1264 /* Initialize a new slot object. */ 1265 /* */ 1266 /* <InOut> */ 1267 /* slot :: A handle to the slot object. */ 1268 /* */ 1269 /* <Return> */ 1270 /* FreeType error code. 0 means success. */ 1271 /* */ 1272 FT_LOCAL_DEF( FT_Error ) 1273 tt_slot_init( FT_GlyphSlot slot ) 1274 { 1275 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1276 } 1277 1278 1279 /* END */ 1280