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 "../../include/ft2build.h" 20#include "../../include/freetype/internal/ftdebug.h" 21#include "../../include/freetype/internal/ftstream.h" 22#include "../../include/freetype/tttags.h" 23#include "../../include/freetype/internal/sfnt.h" 24#include "../../include/freetype/ftttdrv.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 "../../include/freetype/ttunpat.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 else 549 { 550 FT_ULong table_len; 551 if (face->goto_table( face, TTAG_CFF, stream, &table_len) != TT_Err_Table_Missing && 552 face->goto_table( face, TTAG_loca, stream, &table_len) == TT_Err_Table_Missing) 553 { 554 FT_TRACE2(( "[not a valid TTF font]\n" )); 555 goto Bad_Format; 556 } 557 } 558 559#ifdef TT_USE_BYTECODE_INTERPRETER 560 ttface->face_flags |= FT_FACE_FLAG_HINTER; 561#endif 562 563 /* If we are performing a simple font format check, exit immediately. */ 564 if ( face_index < 0 ) 565 return FT_Err_Ok; 566 567 /* Load font directory */ 568 error = sfnt->load_face( stream, face, face_index, num_params, params ); 569 if ( error ) 570 goto Exit; 571 572 if ( tt_check_trickyness( ttface ) ) 573 ttface->face_flags |= FT_FACE_FLAG_TRICKY; 574 575 error = tt_face_load_hdmx( face, stream ); 576 if ( error ) 577 goto Exit; 578 579 if ( FT_IS_SCALABLE( ttface ) ) 580 { 581 582#ifdef FT_CONFIG_OPTION_INCREMENTAL 583 584 if ( !ttface->internal->incremental_interface ) 585 error = tt_face_load_loca( face, stream ); 586 if ( !error ) 587 error = tt_face_load_cvt( face, stream ); 588 if ( !error ) 589 error = tt_face_load_fpgm( face, stream ); 590 if ( !error ) 591 error = tt_face_load_prep( face, stream ); 592 593 /* Check the scalable flag based on `loca'. */ 594 if ( !ttface->internal->incremental_interface && 595 ttface->num_fixed_sizes && 596 face->glyph_locations && 597 tt_check_single_notdef( ttface ) ) 598 { 599 FT_TRACE5(( "tt_face_init:" 600 " Only the `.notdef' glyph has an outline.\n" 601 " " 602 " Resetting scalable flag to FALSE.\n" )); 603 604 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 605 } 606 607#else 608 609 if ( !error ) 610 error = tt_face_load_loca( face, stream ); 611 if ( !error ) 612 error = tt_face_load_cvt( face, stream ); 613 if ( !error ) 614 error = tt_face_load_fpgm( face, stream ); 615 if ( !error ) 616 error = tt_face_load_prep( face, stream ); 617 618 /* Check the scalable flag based on `loca'. */ 619 if ( ttface->num_fixed_sizes && 620 face->glyph_locations && 621 tt_check_single_notdef( ttface ) ) 622 { 623 FT_TRACE5(( "tt_face_init:" 624 " Only the `.notdef' glyph has an outline.\n" 625 " " 626 " Resetting scalable flag to FALSE.\n" )); 627 628 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 629 } 630 631#endif 632 633 } 634 635#if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ 636 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) 637 638 { 639 FT_Bool unpatented_hinting; 640 int i; 641 642 643 /* Determine whether unpatented hinting is to be used for this face. */ 644 unpatented_hinting = FT_BOOL 645 ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL ); 646 647 for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) 648 if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) 649 unpatented_hinting = TRUE; 650 651 if ( !unpatented_hinting ) 652 ttface->internal->ignore_unpatented_hinter = TRUE; 653 } 654 655#endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING && 656 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 657 658 /* initialize standard glyph loading routines */ 659 TT_Init_Glyph_Loading( face ); 660 661 Exit: 662 return error; 663 664 Bad_Format: 665 error = FT_THROW( Unknown_File_Format ); 666 goto Exit; 667 } 668 669 670 /*************************************************************************/ 671 /* */ 672 /* <Function> */ 673 /* tt_face_done */ 674 /* */ 675 /* <Description> */ 676 /* Finalize a given face object. */ 677 /* */ 678 /* <Input> */ 679 /* face :: A pointer to the face object to destroy. */ 680 /* */ 681 FT_LOCAL_DEF( void ) 682 tt_face_done( FT_Face ttface ) /* TT_Face */ 683 { 684 TT_Face face = (TT_Face)ttface; 685 FT_Memory memory; 686 FT_Stream stream; 687 SFNT_Service sfnt; 688 689 690 if ( !face ) 691 return; 692 693 memory = ttface->memory; 694 stream = ttface->stream; 695 sfnt = (SFNT_Service)face->sfnt; 696 697 /* for `extended TrueType formats' (i.e. compressed versions) */ 698 if ( face->extra.finalizer ) 699 face->extra.finalizer( face->extra.data ); 700 701 if ( sfnt ) 702 sfnt->done_face( face ); 703 704 /* freeing the locations table */ 705 tt_face_done_loca( face ); 706 707 tt_face_free_hdmx( face ); 708 709 /* freeing the CVT */ 710 FT_FREE( face->cvt ); 711 face->cvt_size = 0; 712 713 /* freeing the programs */ 714 FT_FRAME_RELEASE( face->font_program ); 715 FT_FRAME_RELEASE( face->cvt_program ); 716 face->font_program_size = 0; 717 face->cvt_program_size = 0; 718 719#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 720 tt_done_blend( memory, face->blend ); 721 face->blend = NULL; 722#endif 723 } 724 725 726 /*************************************************************************/ 727 /* */ 728 /* SIZE FUNCTIONS */ 729 /* */ 730 /*************************************************************************/ 731 732#ifdef TT_USE_BYTECODE_INTERPRETER 733 734 /*************************************************************************/ 735 /* */ 736 /* <Function> */ 737 /* tt_size_run_fpgm */ 738 /* */ 739 /* <Description> */ 740 /* Run the font program. */ 741 /* */ 742 /* <Input> */ 743 /* size :: A handle to the size object. */ 744 /* */ 745 /* pedantic :: Set if bytecode execution should be pedantic. */ 746 /* */ 747 /* <Return> */ 748 /* FreeType error code. 0 means success. */ 749 /* */ 750 FT_LOCAL_DEF( FT_Error ) 751 tt_size_run_fpgm( TT_Size size, 752 FT_Bool pedantic ) 753 { 754 TT_Face face = (TT_Face)size->root.face; 755 TT_ExecContext exec; 756 FT_Error error; 757 758 759 /* debugging instances have their own context */ 760 if ( size->debug ) 761 exec = size->context; 762 else 763 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 764 765 if ( !exec ) 766 return FT_THROW( Could_Not_Find_Context ); 767 768 TT_Load_Context( exec, face, size ); 769 770 exec->callTop = 0; 771 exec->top = 0; 772 773 exec->period = 64; 774 exec->phase = 0; 775 exec->threshold = 0; 776 777 exec->instruction_trap = FALSE; 778 exec->F_dot_P = 0x4000L; 779 780 exec->pedantic_hinting = pedantic; 781 782 { 783 FT_Size_Metrics* metrics = &exec->metrics; 784 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 785 786 787 metrics->x_ppem = 0; 788 metrics->y_ppem = 0; 789 metrics->x_scale = 0; 790 metrics->y_scale = 0; 791 792 tt_metrics->ppem = 0; 793 tt_metrics->scale = 0; 794 tt_metrics->ratio = 0x10000L; 795 } 796 797 /* allow font program execution */ 798 TT_Set_CodeRange( exec, 799 tt_coderange_font, 800 face->font_program, 801 face->font_program_size ); 802 803 /* disable CVT and glyph programs coderange */ 804 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 805 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 806 807 if ( face->font_program_size > 0 ) 808 { 809 error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 810 811 if ( !error ) 812 { 813 FT_TRACE4(( "Executing `fpgm' table.\n" )); 814 815 error = face->interpreter( exec ); 816 } 817 } 818 else 819 error = FT_Err_Ok; 820 821 if ( !error ) 822 TT_Save_Context( exec, size ); 823 824 return error; 825 } 826 827 828 /*************************************************************************/ 829 /* */ 830 /* <Function> */ 831 /* tt_size_run_prep */ 832 /* */ 833 /* <Description> */ 834 /* Run the control value program. */ 835 /* */ 836 /* <Input> */ 837 /* size :: A handle to the size object. */ 838 /* */ 839 /* pedantic :: Set if bytecode execution should be pedantic. */ 840 /* */ 841 /* <Return> */ 842 /* FreeType error code. 0 means success. */ 843 /* */ 844 FT_LOCAL_DEF( FT_Error ) 845 tt_size_run_prep( TT_Size size, 846 FT_Bool pedantic ) 847 { 848 TT_Face face = (TT_Face)size->root.face; 849 TT_ExecContext exec; 850 FT_Error error; 851 852 853 /* debugging instances have their own context */ 854 if ( size->debug ) 855 exec = size->context; 856 else 857 exec = ( (TT_Driver)FT_FACE_DRIVER( face ) )->context; 858 859 if ( !exec ) 860 return FT_THROW( Could_Not_Find_Context ); 861 862 TT_Load_Context( exec, face, size ); 863 864 exec->callTop = 0; 865 exec->top = 0; 866 867 exec->instruction_trap = FALSE; 868 869 exec->pedantic_hinting = pedantic; 870 871 TT_Set_CodeRange( exec, 872 tt_coderange_cvt, 873 face->cvt_program, 874 face->cvt_program_size ); 875 876 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 877 878 if ( face->cvt_program_size > 0 ) 879 { 880 error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 881 882 if ( !error && !size->debug ) 883 { 884 FT_TRACE4(( "Executing `prep' table.\n" )); 885 886 error = face->interpreter( exec ); 887 } 888 } 889 else 890 error = FT_Err_Ok; 891 892 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 893 /* graphics state variables to be modified by the CVT program. */ 894 895 exec->GS.dualVector.x = 0x4000; 896 exec->GS.dualVector.y = 0; 897 exec->GS.projVector.x = 0x4000; 898 exec->GS.projVector.y = 0x0; 899 exec->GS.freeVector.x = 0x4000; 900 exec->GS.freeVector.y = 0x0; 901 902 exec->GS.rp0 = 0; 903 exec->GS.rp1 = 0; 904 exec->GS.rp2 = 0; 905 906 exec->GS.gep0 = 1; 907 exec->GS.gep1 = 1; 908 exec->GS.gep2 = 1; 909 910 exec->GS.loop = 1; 911 912 /* save as default graphics state */ 913 size->GS = exec->GS; 914 915 TT_Save_Context( exec, size ); 916 917 return error; 918 } 919 920#endif /* TT_USE_BYTECODE_INTERPRETER */ 921 922 923#ifdef TT_USE_BYTECODE_INTERPRETER 924 925 static void 926 tt_size_done_bytecode( FT_Size ftsize ) 927 { 928 TT_Size size = (TT_Size)ftsize; 929 TT_Face face = (TT_Face)ftsize->face; 930 FT_Memory memory = face->root.memory; 931 932 933 if ( size->debug ) 934 { 935 /* the debug context must be deleted by the debugger itself */ 936 size->context = NULL; 937 size->debug = FALSE; 938 } 939 940 FT_FREE( size->cvt ); 941 size->cvt_size = 0; 942 943 /* free storage area */ 944 FT_FREE( size->storage ); 945 size->storage_size = 0; 946 947 /* twilight zone */ 948 tt_glyphzone_done( &size->twilight ); 949 950 FT_FREE( size->function_defs ); 951 FT_FREE( size->instruction_defs ); 952 953 size->num_function_defs = 0; 954 size->max_function_defs = 0; 955 size->num_instruction_defs = 0; 956 size->max_instruction_defs = 0; 957 958 size->max_func = 0; 959 size->max_ins = 0; 960 961 size->bytecode_ready = 0; 962 size->cvt_ready = 0; 963 } 964 965 966 /* Initialize bytecode-related fields in the size object. */ 967 /* We do this only if bytecode interpretation is really needed. */ 968 static FT_Error 969 tt_size_init_bytecode( FT_Size ftsize, 970 FT_Bool pedantic ) 971 { 972 FT_Error error; 973 TT_Size size = (TT_Size)ftsize; 974 TT_Face face = (TT_Face)ftsize->face; 975 FT_Memory memory = face->root.memory; 976 FT_Int i; 977 978 FT_UShort n_twilight; 979 TT_MaxProfile* maxp = &face->max_profile; 980 981 982 size->bytecode_ready = 1; 983 size->cvt_ready = 0; 984 985 size->max_function_defs = maxp->maxFunctionDefs; 986 size->max_instruction_defs = maxp->maxInstructionDefs; 987 988 size->num_function_defs = 0; 989 size->num_instruction_defs = 0; 990 991 size->max_func = 0; 992 size->max_ins = 0; 993 994 size->cvt_size = face->cvt_size; 995 size->storage_size = maxp->maxStorage; 996 997 /* Set default metrics */ 998 { 999 TT_Size_Metrics* metrics = &size->ttmetrics; 1000 1001 1002 metrics->rotated = FALSE; 1003 metrics->stretched = FALSE; 1004 1005 /* set default compensation (all 0) */ 1006 for ( i = 0; i < 4; i++ ) 1007 metrics->compensations[i] = 0; 1008 } 1009 1010 /* allocate function defs, instruction defs, cvt, and storage area */ 1011 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1012 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1013 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1014 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1015 goto Exit; 1016 1017 /* reserve twilight zone */ 1018 n_twilight = maxp->maxTwilightPoints; 1019 1020 /* there are 4 phantom points (do we need this?) */ 1021 n_twilight += 4; 1022 1023 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1024 if ( error ) 1025 goto Exit; 1026 1027 size->twilight.n_points = n_twilight; 1028 1029 size->GS = tt_default_graphics_state; 1030 1031 /* set `face->interpreter' according to the debug hook present */ 1032 { 1033 FT_Library library = face->root.driver->root.library; 1034 1035 1036 face->interpreter = (TT_Interpreter) 1037 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1038 if ( !face->interpreter ) 1039 face->interpreter = (TT_Interpreter)TT_RunIns; 1040 } 1041 1042 /* Fine, now run the font program! */ 1043 error = tt_size_run_fpgm( size, pedantic ); 1044 /* It seems fpgm proc is causing some problem for some font, so we ignore the error. TESTDOC: Bug #12690 - Restaurantkarte_Oktober09+Wild.pdf*/ 1045 if ( error ) 1046 tt_size_done_bytecode( ftsize ); 1047 return TT_Err_Ok; 1048 1049 Exit: 1050 if ( error ) 1051 tt_size_done_bytecode( ftsize ); 1052 1053 return error; 1054 } 1055 1056 1057 FT_LOCAL_DEF( FT_Error ) 1058 tt_size_ready_bytecode( TT_Size size, 1059 FT_Bool pedantic ) 1060 { 1061 FT_Error error = FT_Err_Ok; 1062 1063 1064 if ( !size->bytecode_ready ) 1065 { 1066 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1067 if ( error ) 1068 goto Exit; 1069 } 1070 1071 /* rescale CVT when needed */ 1072 if ( !size->cvt_ready ) 1073 { 1074 FT_UInt i; 1075 TT_Face face = (TT_Face)size->root.face; 1076 1077 1078 /* Scale the cvt values to the new ppem. */ 1079 /* We use by default the y ppem to scale the CVT. */ 1080 for ( i = 0; i < size->cvt_size; i++ ) 1081 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 1082 1083 /* all twilight points are originally zero */ 1084 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) 1085 { 1086 size->twilight.org[i].x = 0; 1087 size->twilight.org[i].y = 0; 1088 size->twilight.cur[i].x = 0; 1089 size->twilight.cur[i].y = 0; 1090 } 1091 1092 /* clear storage area */ 1093 for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) 1094 size->storage[i] = 0; 1095 1096 size->GS = tt_default_graphics_state; 1097 1098 tt_size_run_prep( size, pedantic );/* It seems prep proc is causing some problem for some font, so we ignore the error. TESTDOC: Bug #5025 - naredba-rd-16-296.pdf */ 1099 /* However we can't disable the prep. TESTDOC: Bug #0063 - 050826_differ_table.pdf, page #4 */ 1100 if ( !error ) 1101 size->cvt_ready = 1; 1102 } 1103 1104 Exit: 1105 return error; 1106 } 1107 1108#endif /* TT_USE_BYTECODE_INTERPRETER */ 1109 1110 1111 /*************************************************************************/ 1112 /* */ 1113 /* <Function> */ 1114 /* tt_size_init */ 1115 /* */ 1116 /* <Description> */ 1117 /* Initialize a new TrueType size object. */ 1118 /* */ 1119 /* <InOut> */ 1120 /* size :: A handle to the size object. */ 1121 /* */ 1122 /* <Return> */ 1123 /* FreeType error code. 0 means success. */ 1124 /* */ 1125 FT_LOCAL_DEF( FT_Error ) 1126 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1127 { 1128 TT_Size size = (TT_Size)ttsize; 1129 FT_Error error = FT_Err_Ok; 1130 1131#ifdef TT_USE_BYTECODE_INTERPRETER 1132 size->bytecode_ready = 0; 1133 size->cvt_ready = 0; 1134#endif 1135 1136 size->ttmetrics.valid = FALSE; 1137 size->strike_index = 0xFFFFFFFFUL; 1138 1139 return error; 1140 } 1141 1142 1143 /*************************************************************************/ 1144 /* */ 1145 /* <Function> */ 1146 /* tt_size_done */ 1147 /* */ 1148 /* <Description> */ 1149 /* The TrueType size object finalizer. */ 1150 /* */ 1151 /* <Input> */ 1152 /* size :: A handle to the target size object. */ 1153 /* */ 1154 FT_LOCAL_DEF( void ) 1155 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1156 { 1157 TT_Size size = (TT_Size)ttsize; 1158 1159 1160#ifdef TT_USE_BYTECODE_INTERPRETER 1161 if ( size->bytecode_ready ) 1162 tt_size_done_bytecode( ttsize ); 1163#endif 1164 1165 size->ttmetrics.valid = FALSE; 1166 } 1167 1168 1169 /*************************************************************************/ 1170 /* */ 1171 /* <Function> */ 1172 /* tt_size_reset */ 1173 /* */ 1174 /* <Description> */ 1175 /* Reset a TrueType size when resolutions and character dimensions */ 1176 /* have been changed. */ 1177 /* */ 1178 /* <Input> */ 1179 /* size :: A handle to the target size object. */ 1180 /* */ 1181 FT_LOCAL_DEF( FT_Error ) 1182 tt_size_reset( TT_Size size ) 1183 { 1184 TT_Face face; 1185 FT_Error error = FT_Err_Ok; 1186 FT_Size_Metrics* metrics; 1187 1188 1189 size->ttmetrics.valid = FALSE; 1190 1191 face = (TT_Face)size->root.face; 1192 1193 metrics = &size->metrics; 1194 1195 /* copy the result from base layer */ 1196 *metrics = size->root.metrics; 1197 1198 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) 1199 return FT_THROW( Invalid_PPem ); 1200 1201 /* This bit flag, if set, indicates that the ppems must be */ 1202 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1203 /* set, as hinting won't work really well otherwise. */ 1204 /* */ 1205 if ( face->header.Flags & 8 ) 1206 { 1207 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1208 face->root.units_per_EM ); 1209 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1210 face->root.units_per_EM ); 1211 1212 metrics->ascender = 1213 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); 1214 metrics->descender = 1215 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); 1216 metrics->height = 1217 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); 1218 metrics->max_advance = 1219 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, 1220 metrics->x_scale ) ); 1221 } 1222 1223 /* compute new transformation */ 1224 if ( metrics->x_ppem >= metrics->y_ppem ) 1225 { 1226 size->ttmetrics.scale = metrics->x_scale; 1227 size->ttmetrics.ppem = metrics->x_ppem; 1228 size->ttmetrics.x_ratio = 0x10000L; 1229 size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, 1230 metrics->x_ppem ); 1231 } 1232 else 1233 { 1234 size->ttmetrics.scale = metrics->y_scale; 1235 size->ttmetrics.ppem = metrics->y_ppem; 1236 size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, 1237 metrics->y_ppem ); 1238 size->ttmetrics.y_ratio = 0x10000L; 1239 } 1240 1241#ifdef TT_USE_BYTECODE_INTERPRETER 1242 size->cvt_ready = 0; 1243#endif /* TT_USE_BYTECODE_INTERPRETER */ 1244 1245 if ( !error ) 1246 size->ttmetrics.valid = TRUE; 1247 1248 return error; 1249 } 1250 1251 1252 /*************************************************************************/ 1253 /* */ 1254 /* <Function> */ 1255 /* tt_driver_init */ 1256 /* */ 1257 /* <Description> */ 1258 /* Initialize a given TrueType driver object. */ 1259 /* */ 1260 /* <Input> */ 1261 /* driver :: A handle to the target driver object. */ 1262 /* */ 1263 /* <Return> */ 1264 /* FreeType error code. 0 means success. */ 1265 /* */ 1266 FT_LOCAL_DEF( FT_Error ) 1267 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1268 { 1269 1270#ifdef TT_USE_BYTECODE_INTERPRETER 1271 1272 TT_Driver driver = (TT_Driver)ttdriver; 1273 1274 1275 if ( !TT_New_Context( driver ) ) 1276 return FT_THROW( Could_Not_Find_Context ); 1277 1278#ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1279 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1280#else 1281 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1282#endif 1283 1284#else /* !TT_USE_BYTECODE_INTERPRETER */ 1285 1286 FT_UNUSED( ttdriver ); 1287 1288#endif /* !TT_USE_BYTECODE_INTERPRETER */ 1289 1290 return FT_Err_Ok; 1291 } 1292 1293 1294 /*************************************************************************/ 1295 /* */ 1296 /* <Function> */ 1297 /* tt_driver_done */ 1298 /* */ 1299 /* <Description> */ 1300 /* Finalize a given TrueType driver. */ 1301 /* */ 1302 /* <Input> */ 1303 /* driver :: A handle to the target TrueType driver. */ 1304 /* */ 1305 FT_LOCAL_DEF( void ) 1306 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1307 { 1308#ifdef TT_USE_BYTECODE_INTERPRETER 1309 TT_Driver driver = (TT_Driver)ttdriver; 1310 1311 1312 /* destroy the execution context */ 1313 if ( driver->context ) 1314 { 1315 TT_Done_Context( driver->context ); 1316 driver->context = NULL; 1317 } 1318#else 1319 FT_UNUSED( ttdriver ); 1320#endif 1321 1322 } 1323 1324 1325 /*************************************************************************/ 1326 /* */ 1327 /* <Function> */ 1328 /* tt_slot_init */ 1329 /* */ 1330 /* <Description> */ 1331 /* Initialize a new slot object. */ 1332 /* */ 1333 /* <InOut> */ 1334 /* slot :: A handle to the slot object. */ 1335 /* */ 1336 /* <Return> */ 1337 /* FreeType error code. 0 means success. */ 1338 /* */ 1339 FT_LOCAL_DEF( FT_Error ) 1340 tt_slot_init( FT_GlyphSlot slot ) 1341 { 1342 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1343 } 1344 1345 1346/* END */ 1347