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