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