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 ) tt_glyphzone_done(TT_GlyphZone zone)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 ) tt_glyphzone_new(FT_Memory memory,FT_UShort maxPoints,FT_Short maxContours,TT_GlyphZone zone)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 tt_check_trickyness_family(FT_String * name)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 tt_synth_sfnt_checksum(FT_Stream stream,FT_ULong length)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 tt_get_sfnt_checksum(TT_Face face,FT_UShort i)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 tt_check_trickyness_sfnt_ids(TT_Face face)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 tt_check_trickyness(FT_Face face)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 tt_check_single_notdef(FT_Face ttface)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 ) tt_face_init(FT_Stream stream,FT_Face ttface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)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 ) tt_face_done(FT_Face ttface)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 ) tt_size_run_fpgm(TT_Size size,FT_Bool pedantic)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 TT_Load_Context( exec, face, size ); 764 765 exec->callTop = 0; 766 exec->top = 0; 767 768 exec->period = 64; 769 exec->phase = 0; 770 exec->threshold = 0; 771 772 exec->instruction_trap = FALSE; 773 exec->F_dot_P = 0x4000L; 774 775 exec->pedantic_hinting = pedantic; 776 777 { 778 FT_Size_Metrics* metrics = &exec->metrics; 779 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 780 781 782 metrics->x_ppem = 0; 783 metrics->y_ppem = 0; 784 metrics->x_scale = 0; 785 metrics->y_scale = 0; 786 787 tt_metrics->ppem = 0; 788 tt_metrics->scale = 0; 789 tt_metrics->ratio = 0x10000L; 790 } 791 792 /* allow font program execution */ 793 TT_Set_CodeRange( exec, 794 tt_coderange_font, 795 face->font_program, 796 face->font_program_size ); 797 798 /* disable CVT and glyph programs coderange */ 799 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 800 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 801 802 if ( face->font_program_size > 0 ) 803 { 804 error = TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 805 806 if ( !error ) 807 { 808 FT_TRACE4(( "Executing `fpgm' table.\n" )); 809 810 error = face->interpreter( exec ); 811 } 812 } 813 else 814 error = FT_Err_Ok; 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 ) tt_size_run_prep(TT_Size size,FT_Bool pedantic)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 TT_Load_Context( exec, face, size ); 858 859 exec->callTop = 0; 860 exec->top = 0; 861 862 exec->instruction_trap = FALSE; 863 864 exec->pedantic_hinting = pedantic; 865 866 TT_Set_CodeRange( exec, 867 tt_coderange_cvt, 868 face->cvt_program, 869 face->cvt_program_size ); 870 871 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 872 873 if ( face->cvt_program_size > 0 ) 874 { 875 error = TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 876 877 if ( !error && !size->debug ) 878 { 879 FT_TRACE4(( "Executing `prep' table.\n" )); 880 881 error = face->interpreter( exec ); 882 } 883 } 884 else 885 error = FT_Err_Ok; 886 887 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 888 /* graphics state variables to be modified by the CVT program. */ 889 890 exec->GS.dualVector.x = 0x4000; 891 exec->GS.dualVector.y = 0; 892 exec->GS.projVector.x = 0x4000; 893 exec->GS.projVector.y = 0x0; 894 exec->GS.freeVector.x = 0x4000; 895 exec->GS.freeVector.y = 0x0; 896 897 exec->GS.rp0 = 0; 898 exec->GS.rp1 = 0; 899 exec->GS.rp2 = 0; 900 901 exec->GS.gep0 = 1; 902 exec->GS.gep1 = 1; 903 exec->GS.gep2 = 1; 904 905 exec->GS.loop = 1; 906 907 /* save as default graphics state */ 908 size->GS = exec->GS; 909 910 TT_Save_Context( exec, size ); 911 912 return error; 913 } 914 915 #endif /* TT_USE_BYTECODE_INTERPRETER */ 916 917 918 #ifdef TT_USE_BYTECODE_INTERPRETER 919 920 static void tt_size_done_bytecode(FT_Size ftsize)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 = 0; 957 size->cvt_ready = 0; 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 tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)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 FT_Int i; 972 973 FT_UShort n_twilight; 974 TT_MaxProfile* maxp = &face->max_profile; 975 976 977 size->bytecode_ready = 1; 978 size->cvt_ready = 0; 979 980 size->max_function_defs = maxp->maxFunctionDefs; 981 size->max_instruction_defs = maxp->maxInstructionDefs; 982 983 size->num_function_defs = 0; 984 size->num_instruction_defs = 0; 985 986 size->max_func = 0; 987 size->max_ins = 0; 988 989 size->cvt_size = face->cvt_size; 990 size->storage_size = maxp->maxStorage; 991 992 /* Set default metrics */ 993 { 994 TT_Size_Metrics* metrics = &size->ttmetrics; 995 996 997 metrics->rotated = FALSE; 998 metrics->stretched = FALSE; 999 1000 /* set default compensation (all 0) */ 1001 for ( i = 0; i < 4; i++ ) 1002 metrics->compensations[i] = 0; 1003 } 1004 1005 /* allocate function defs, instruction defs, cvt, and storage area */ 1006 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1007 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1008 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1009 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1010 goto Exit; 1011 1012 /* reserve twilight zone */ 1013 n_twilight = maxp->maxTwilightPoints; 1014 1015 /* there are 4 phantom points (do we need this?) */ 1016 n_twilight += 4; 1017 1018 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1019 if ( error ) 1020 goto Exit; 1021 1022 size->twilight.n_points = n_twilight; 1023 1024 size->GS = tt_default_graphics_state; 1025 1026 /* set `face->interpreter' according to the debug hook present */ 1027 { 1028 FT_Library library = face->root.driver->root.library; 1029 1030 1031 face->interpreter = (TT_Interpreter) 1032 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1033 if ( !face->interpreter ) 1034 face->interpreter = (TT_Interpreter)TT_RunIns; 1035 } 1036 1037 /* Fine, now run the font program! */ 1038 error = tt_size_run_fpgm( size, pedantic ); 1039 1040 Exit: 1041 if ( error ) 1042 tt_size_done_bytecode( ftsize ); 1043 1044 return error; 1045 } 1046 1047 1048 FT_LOCAL_DEF( FT_Error ) tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1049 tt_size_ready_bytecode( TT_Size size, 1050 FT_Bool pedantic ) 1051 { 1052 FT_Error error = FT_Err_Ok; 1053 1054 1055 if ( !size->bytecode_ready ) 1056 { 1057 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1058 if ( error ) 1059 goto Exit; 1060 } 1061 1062 /* rescale CVT when needed */ 1063 if ( !size->cvt_ready ) 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 if ( !error ) 1091 size->cvt_ready = 1; 1092 } 1093 1094 Exit: 1095 return error; 1096 } 1097 1098 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1099 1100 1101 /*************************************************************************/ 1102 /* */ 1103 /* <Function> */ 1104 /* tt_size_init */ 1105 /* */ 1106 /* <Description> */ 1107 /* Initialize a new TrueType size object. */ 1108 /* */ 1109 /* <InOut> */ 1110 /* size :: A handle to the size object. */ 1111 /* */ 1112 /* <Return> */ 1113 /* FreeType error code. 0 means success. */ 1114 /* */ 1115 FT_LOCAL_DEF( FT_Error ) tt_size_init(FT_Size ttsize)1116 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1117 { 1118 TT_Size size = (TT_Size)ttsize; 1119 FT_Error error = FT_Err_Ok; 1120 1121 #ifdef TT_USE_BYTECODE_INTERPRETER 1122 size->bytecode_ready = 0; 1123 size->cvt_ready = 0; 1124 #endif 1125 1126 size->ttmetrics.valid = FALSE; 1127 size->strike_index = 0xFFFFFFFFUL; 1128 1129 return error; 1130 } 1131 1132 1133 /*************************************************************************/ 1134 /* */ 1135 /* <Function> */ 1136 /* tt_size_done */ 1137 /* */ 1138 /* <Description> */ 1139 /* The TrueType size object finalizer. */ 1140 /* */ 1141 /* <Input> */ 1142 /* size :: A handle to the target size object. */ 1143 /* */ 1144 FT_LOCAL_DEF( void ) tt_size_done(FT_Size ttsize)1145 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1146 { 1147 TT_Size size = (TT_Size)ttsize; 1148 1149 1150 #ifdef TT_USE_BYTECODE_INTERPRETER 1151 if ( size->bytecode_ready ) 1152 tt_size_done_bytecode( ttsize ); 1153 #endif 1154 1155 size->ttmetrics.valid = FALSE; 1156 } 1157 1158 1159 /*************************************************************************/ 1160 /* */ 1161 /* <Function> */ 1162 /* tt_size_reset */ 1163 /* */ 1164 /* <Description> */ 1165 /* Reset a TrueType size when resolutions and character dimensions */ 1166 /* have been changed. */ 1167 /* */ 1168 /* <Input> */ 1169 /* size :: A handle to the target size object. */ 1170 /* */ 1171 FT_LOCAL_DEF( FT_Error ) tt_size_reset(TT_Size size)1172 tt_size_reset( TT_Size size ) 1173 { 1174 TT_Face face; 1175 FT_Error error = FT_Err_Ok; 1176 FT_Size_Metrics* metrics; 1177 1178 1179 size->ttmetrics.valid = FALSE; 1180 1181 face = (TT_Face)size->root.face; 1182 1183 metrics = &size->metrics; 1184 1185 /* copy the result from base layer */ 1186 *metrics = size->root.metrics; 1187 1188 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) 1189 return FT_THROW( Invalid_PPem ); 1190 1191 /* This bit flag, if set, indicates that the ppems must be */ 1192 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1193 /* set, as hinting won't work really well otherwise. */ 1194 /* */ 1195 if ( face->header.Flags & 8 ) 1196 { 1197 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1198 face->root.units_per_EM ); 1199 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1200 face->root.units_per_EM ); 1201 1202 metrics->ascender = 1203 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); 1204 metrics->descender = 1205 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); 1206 metrics->height = 1207 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); 1208 metrics->max_advance = 1209 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, 1210 metrics->x_scale ) ); 1211 } 1212 1213 /* compute new transformation */ 1214 if ( metrics->x_ppem >= metrics->y_ppem ) 1215 { 1216 size->ttmetrics.scale = metrics->x_scale; 1217 size->ttmetrics.ppem = metrics->x_ppem; 1218 size->ttmetrics.x_ratio = 0x10000L; 1219 size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, 1220 metrics->x_ppem ); 1221 } 1222 else 1223 { 1224 size->ttmetrics.scale = metrics->y_scale; 1225 size->ttmetrics.ppem = metrics->y_ppem; 1226 size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, 1227 metrics->y_ppem ); 1228 size->ttmetrics.y_ratio = 0x10000L; 1229 } 1230 1231 #ifdef TT_USE_BYTECODE_INTERPRETER 1232 size->cvt_ready = 0; 1233 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1234 1235 if ( !error ) 1236 size->ttmetrics.valid = TRUE; 1237 1238 return error; 1239 } 1240 1241 1242 /*************************************************************************/ 1243 /* */ 1244 /* <Function> */ 1245 /* tt_driver_init */ 1246 /* */ 1247 /* <Description> */ 1248 /* Initialize a given TrueType driver object. */ 1249 /* */ 1250 /* <Input> */ 1251 /* driver :: A handle to the target driver object. */ 1252 /* */ 1253 /* <Return> */ 1254 /* FreeType error code. 0 means success. */ 1255 /* */ 1256 FT_LOCAL_DEF( FT_Error ) tt_driver_init(FT_Module ttdriver)1257 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1258 { 1259 1260 #ifdef TT_USE_BYTECODE_INTERPRETER 1261 1262 TT_Driver driver = (TT_Driver)ttdriver; 1263 1264 1265 if ( !TT_New_Context( driver ) ) 1266 return FT_THROW( Could_Not_Find_Context ); 1267 1268 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1269 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1270 #else 1271 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1272 #endif 1273 1274 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1275 1276 FT_UNUSED( ttdriver ); 1277 1278 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1279 1280 return FT_Err_Ok; 1281 } 1282 1283 1284 /*************************************************************************/ 1285 /* */ 1286 /* <Function> */ 1287 /* tt_driver_done */ 1288 /* */ 1289 /* <Description> */ 1290 /* Finalize a given TrueType driver. */ 1291 /* */ 1292 /* <Input> */ 1293 /* driver :: A handle to the target TrueType driver. */ 1294 /* */ 1295 FT_LOCAL_DEF( void ) tt_driver_done(FT_Module ttdriver)1296 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1297 { 1298 #ifdef TT_USE_BYTECODE_INTERPRETER 1299 TT_Driver driver = (TT_Driver)ttdriver; 1300 1301 1302 /* destroy the execution context */ 1303 if ( driver->context ) 1304 { 1305 TT_Done_Context( driver->context ); 1306 driver->context = NULL; 1307 } 1308 #else 1309 FT_UNUSED( ttdriver ); 1310 #endif 1311 1312 } 1313 1314 1315 /*************************************************************************/ 1316 /* */ 1317 /* <Function> */ 1318 /* tt_slot_init */ 1319 /* */ 1320 /* <Description> */ 1321 /* Initialize a new slot object. */ 1322 /* */ 1323 /* <InOut> */ 1324 /* slot :: A handle to the slot object. */ 1325 /* */ 1326 /* <Return> */ 1327 /* FreeType error code. 0 means success. */ 1328 /* */ 1329 FT_LOCAL_DEF( FT_Error ) tt_slot_init(FT_GlyphSlot slot)1330 tt_slot_init( FT_GlyphSlot slot ) 1331 { 1332 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1333 } 1334 1335 1336 /* END */ 1337