1 /***************************************************************************/ 2 /* */ 3 /* ttobjs.c */ 4 /* */ 5 /* Objects manager (body). */ 6 /* */ 7 /* Copyright 1996-2015 by */ 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 FT_UInt 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 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 260 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 261 { 0xA344A1EAUL, 0x000001E1UL } /* prep */ 262 }, 263 { /* MingLiU 1996- */ 264 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 265 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 266 { 0xA344A1EBUL, 0x000001E1UL } /* prep */ 267 }, 268 { /* DFKaiShu */ 269 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 270 { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ 271 { 0x13A42602UL, 0x0000007EUL } /* prep */ 272 }, 273 { /* HuaTianKaiTi */ 274 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 275 { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */ 276 { 0x70020112UL, 0x00000008UL } /* prep */ 277 }, 278 { /* HuaTianSongTi */ 279 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 280 { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */ 281 { 0x70020112UL, 0x00000008UL } /* prep */ 282 }, 283 { /* NEC fadpop7.ttf */ 284 { 0x00000000UL, 0x00000000UL }, /* cvt */ 285 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 286 { 0xA39B58E3UL, 0x0000117CUL } /* prep */ 287 }, 288 { /* NEC fadrei5.ttf */ 289 { 0x00000000UL, 0x00000000UL }, /* cvt */ 290 { 0x33C41652UL, 0x000000E5UL }, /* fpgm */ 291 { 0x26D6C52AUL, 0x00000F6AUL } /* prep */ 292 }, 293 { /* NEC fangot7.ttf */ 294 { 0x00000000UL, 0x00000000UL }, /* cvt */ 295 { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */ 296 { 0x6C6E4B03UL, 0x00002492UL } /* prep */ 297 }, 298 { /* NEC fangyo5.ttf */ 299 { 0x00000000UL, 0x00000000UL }, /* cvt */ 300 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 301 { 0xDE51FAD0UL, 0x0000117CUL } /* prep */ 302 }, 303 { /* NEC fankyo5.ttf */ 304 { 0x00000000UL, 0x00000000UL }, /* cvt */ 305 { 0x85E47664UL, 0x000000E5UL }, /* fpgm */ 306 { 0xA6C62831UL, 0x00001CAAUL } /* prep */ 307 }, 308 { /* NEC fanrgo5.ttf */ 309 { 0x00000000UL, 0x00000000UL }, /* cvt */ 310 { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */ 311 { 0xA0604633UL, 0x00001DE8UL } /* prep */ 312 }, 313 { /* NEC fangot5.ttc */ 314 { 0x00000000UL, 0x00000000UL }, /* cvt */ 315 { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */ 316 { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */ 317 }, 318 { /* NEC fanmin3.ttc */ 319 { 0x00000000UL, 0x00000000UL }, /* cvt */ 320 { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */ 321 { 0xD4127766UL, 0x00002280UL } /* prep */ 322 }, 323 { /* NEC FA-Gothic, 1996 */ 324 { 0x00000000UL, 0x00000000UL }, /* cvt */ 325 { 0x4A692698UL, 0x000001F0UL }, /* fpgm */ 326 { 0x340D4346UL, 0x00001FCAUL } /* prep */ 327 }, 328 { /* NEC FA-Minchou, 1996 */ 329 { 0x00000000UL, 0x00000000UL }, /* cvt */ 330 { 0xCD34C604UL, 0x00000166UL }, /* fpgm */ 331 { 0x6CF31046UL, 0x000022B0UL } /* prep */ 332 }, 333 { /* NEC FA-RoundGothicB, 1996 */ 334 { 0x00000000UL, 0x00000000UL }, /* cvt */ 335 { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */ 336 { 0x40745A5FUL, 0x000022E0UL } /* prep */ 337 }, 338 { /* NEC FA-RoundGothicM, 1996 */ 339 { 0x00000000UL, 0x00000000UL }, /* cvt */ 340 { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ 341 { 0x3900DED3UL, 0x00001E18UL } /* 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 TrueType font, if we are opening a */ 494 /* collection, in bits 0-15. The numbered instance */ 495 /* index~+~1 of a GX (sub)font, if applicable, in bits */ 496 /* 16-30. */ 497 /* */ 498 /* num_params :: Number of additional generic parameters. Ignored. */ 499 /* */ 500 /* params :: Additional generic parameters. Ignored. */ 501 /* */ 502 /* <InOut> */ 503 /* face :: The newly built face object. */ 504 /* */ 505 /* <Return> */ 506 /* FreeType error code. 0 means success. */ 507 /* */ 508 FT_LOCAL_DEF( FT_Error ) 509 tt_face_init( FT_Stream stream, 510 FT_Face ttface, /* TT_Face */ 511 FT_Int face_index, 512 FT_Int num_params, 513 FT_Parameter* params ) 514 { 515 FT_Error error; 516 FT_Library library; 517 SFNT_Service sfnt; 518 TT_Face face = (TT_Face)ttface; 519 520 521 FT_TRACE2(( "TTF driver\n" )); 522 523 library = ttface->driver->root.library; 524 525 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 526 if ( !sfnt ) 527 { 528 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); 529 error = FT_THROW( Missing_Module ); 530 goto Exit; 531 } 532 533 /* create input stream from resource */ 534 if ( FT_STREAM_SEEK( 0 ) ) 535 goto Exit; 536 537 /* check that we have a valid TrueType file */ 538 error = sfnt->init_face( stream, face, face_index, num_params, params ); 539 540 /* Stream may have changed. */ 541 stream = face->root.stream; 542 543 if ( error ) 544 goto Exit; 545 546 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ 547 /* The 0x00020000 tag is completely undocumented; some fonts from */ 548 /* Arphic made for Chinese Windows 3.1 have this. */ 549 if ( face->format_tag != 0x00010000L && /* MS fonts */ 550 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ 551 face->format_tag != TTAG_true ) /* Mac fonts */ 552 { 553 FT_TRACE2(( " not a TTF font\n" )); 554 goto Bad_Format; 555 } 556 557 #ifdef TT_USE_BYTECODE_INTERPRETER 558 ttface->face_flags |= FT_FACE_FLAG_HINTER; 559 #endif 560 561 /* If we are performing a simple font format check, exit immediately. */ 562 if ( face_index < 0 ) 563 return FT_Err_Ok; 564 565 /* Load font directory */ 566 error = sfnt->load_face( stream, face, face_index, num_params, params ); 567 if ( error ) 568 goto Exit; 569 570 if ( tt_check_trickyness( ttface ) ) 571 ttface->face_flags |= FT_FACE_FLAG_TRICKY; 572 573 error = tt_face_load_hdmx( face, stream ); 574 if ( error ) 575 goto Exit; 576 577 if ( FT_IS_SCALABLE( ttface ) ) 578 { 579 580 #ifdef FT_CONFIG_OPTION_INCREMENTAL 581 582 if ( !ttface->internal->incremental_interface ) 583 error = tt_face_load_loca( face, stream ); 584 if ( !error ) 585 error = tt_face_load_cvt( face, stream ); 586 if ( !error ) 587 error = tt_face_load_fpgm( face, stream ); 588 if ( !error ) 589 error = tt_face_load_prep( face, stream ); 590 591 /* Check the scalable flag based on `loca'. */ 592 if ( !ttface->internal->incremental_interface && 593 ttface->num_fixed_sizes && 594 face->glyph_locations && 595 tt_check_single_notdef( ttface ) ) 596 { 597 FT_TRACE5(( "tt_face_init:" 598 " Only the `.notdef' glyph has an outline.\n" 599 " " 600 " Resetting scalable flag to FALSE.\n" )); 601 602 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 603 } 604 605 #else /* !FT_CONFIG_OPTION_INCREMENTAL */ 606 607 if ( !error ) 608 error = tt_face_load_loca( face, stream ); 609 if ( !error ) 610 error = tt_face_load_cvt( face, stream ); 611 if ( !error ) 612 error = tt_face_load_fpgm( face, stream ); 613 if ( !error ) 614 error = tt_face_load_prep( face, stream ); 615 616 /* Check the scalable flag based on `loca'. */ 617 if ( ttface->num_fixed_sizes && 618 face->glyph_locations && 619 tt_check_single_notdef( ttface ) ) 620 { 621 FT_TRACE5(( "tt_face_init:" 622 " Only the `.notdef' glyph has an outline.\n" 623 " " 624 " Resetting scalable flag to FALSE.\n" )); 625 626 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 627 } 628 629 #endif /* !FT_CONFIG_OPTION_INCREMENTAL */ 630 631 } 632 633 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 634 635 { 636 FT_Int instance_index = face_index >> 16; 637 638 639 if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && 640 instance_index > 0 ) 641 { 642 error = TT_Get_MM_Var( face, NULL ); 643 if ( error ) 644 goto Exit; 645 646 if ( face->blend->mmvar->namedstyle ) 647 { 648 FT_Memory memory = ttface->memory; 649 650 FT_Var_Named_Style* named_style; 651 FT_String* style_name; 652 653 654 /* in `face_index', the instance index starts with value 1 */ 655 named_style = face->blend->mmvar->namedstyle + instance_index - 1; 656 error = sfnt->get_name( face, 657 (FT_UShort)named_style->strid, 658 &style_name ); 659 if ( error ) 660 goto Exit; 661 662 /* set style name; if already set, replace it */ 663 if ( face->root.style_name ) 664 FT_FREE( face->root.style_name ); 665 face->root.style_name = style_name; 666 667 /* finally, select the named instance */ 668 error = TT_Set_Var_Design( face, 669 face->blend->mmvar->num_axis, 670 named_style->coords ); 671 if ( error ) 672 goto Exit; 673 } 674 } 675 } 676 677 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 678 679 #if defined( TT_CONFIG_OPTION_UNPATENTED_HINTING ) && \ 680 !defined( TT_CONFIG_OPTION_BYTECODE_INTERPRETER ) 681 682 { 683 FT_Bool unpatented_hinting; 684 int i; 685 686 687 /* Determine whether unpatented hinting is to be used for this face. */ 688 unpatented_hinting = FT_BOOL 689 ( library->debug_hooks[FT_DEBUG_HOOK_UNPATENTED_HINTING] != NULL ); 690 691 for ( i = 0; i < num_params && !face->unpatented_hinting; i++ ) 692 if ( params[i].tag == FT_PARAM_TAG_UNPATENTED_HINTING ) 693 unpatented_hinting = TRUE; 694 695 if ( !unpatented_hinting ) 696 ttface->internal->ignore_unpatented_hinter = TRUE; 697 } 698 699 #endif /* TT_CONFIG_OPTION_UNPATENTED_HINTING && 700 !TT_CONFIG_OPTION_BYTECODE_INTERPRETER */ 701 702 /* initialize standard glyph loading routines */ 703 TT_Init_Glyph_Loading( face ); 704 705 Exit: 706 return error; 707 708 Bad_Format: 709 error = FT_THROW( Unknown_File_Format ); 710 goto Exit; 711 } 712 713 714 /*************************************************************************/ 715 /* */ 716 /* <Function> */ 717 /* tt_face_done */ 718 /* */ 719 /* <Description> */ 720 /* Finalize a given face object. */ 721 /* */ 722 /* <Input> */ 723 /* face :: A pointer to the face object to destroy. */ 724 /* */ 725 FT_LOCAL_DEF( void ) 726 tt_face_done( FT_Face ttface ) /* TT_Face */ 727 { 728 TT_Face face = (TT_Face)ttface; 729 FT_Memory memory; 730 FT_Stream stream; 731 SFNT_Service sfnt; 732 733 734 if ( !face ) 735 return; 736 737 memory = ttface->memory; 738 stream = ttface->stream; 739 sfnt = (SFNT_Service)face->sfnt; 740 741 /* for `extended TrueType formats' (i.e. compressed versions) */ 742 if ( face->extra.finalizer ) 743 face->extra.finalizer( face->extra.data ); 744 745 if ( sfnt ) 746 sfnt->done_face( face ); 747 748 /* freeing the locations table */ 749 tt_face_done_loca( face ); 750 751 tt_face_free_hdmx( face ); 752 753 /* freeing the CVT */ 754 FT_FREE( face->cvt ); 755 face->cvt_size = 0; 756 757 /* freeing the programs */ 758 FT_FRAME_RELEASE( face->font_program ); 759 FT_FRAME_RELEASE( face->cvt_program ); 760 face->font_program_size = 0; 761 face->cvt_program_size = 0; 762 763 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 764 tt_done_blend( memory, face->blend ); 765 face->blend = NULL; 766 #endif 767 } 768 769 770 /*************************************************************************/ 771 /* */ 772 /* SIZE FUNCTIONS */ 773 /* */ 774 /*************************************************************************/ 775 776 #ifdef TT_USE_BYTECODE_INTERPRETER 777 778 /*************************************************************************/ 779 /* */ 780 /* <Function> */ 781 /* tt_size_run_fpgm */ 782 /* */ 783 /* <Description> */ 784 /* Run the font program. */ 785 /* */ 786 /* <Input> */ 787 /* size :: A handle to the size object. */ 788 /* */ 789 /* pedantic :: Set if bytecode execution should be pedantic. */ 790 /* */ 791 /* <Return> */ 792 /* FreeType error code. 0 means success. */ 793 /* */ 794 FT_LOCAL_DEF( FT_Error ) 795 tt_size_run_fpgm( TT_Size size, 796 FT_Bool pedantic ) 797 { 798 TT_Face face = (TT_Face)size->root.face; 799 TT_ExecContext exec; 800 FT_Error error; 801 802 803 exec = size->context; 804 805 error = TT_Load_Context( exec, face, size ); 806 if ( error ) 807 return error; 808 809 exec->callTop = 0; 810 exec->top = 0; 811 812 exec->period = 64; 813 exec->phase = 0; 814 exec->threshold = 0; 815 816 exec->instruction_trap = FALSE; 817 exec->F_dot_P = 0x4000L; 818 819 exec->pedantic_hinting = pedantic; 820 821 { 822 FT_Size_Metrics* metrics = &exec->metrics; 823 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 824 825 826 metrics->x_ppem = 0; 827 metrics->y_ppem = 0; 828 metrics->x_scale = 0; 829 metrics->y_scale = 0; 830 831 tt_metrics->ppem = 0; 832 tt_metrics->scale = 0; 833 tt_metrics->ratio = 0x10000L; 834 } 835 836 /* allow font program execution */ 837 TT_Set_CodeRange( exec, 838 tt_coderange_font, 839 face->font_program, 840 (FT_Long)face->font_program_size ); 841 842 /* disable CVT and glyph programs coderange */ 843 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 844 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 845 846 if ( face->font_program_size > 0 ) 847 { 848 TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 849 850 FT_TRACE4(( "Executing `fpgm' table.\n" )); 851 error = face->interpreter( exec ); 852 } 853 else 854 error = FT_Err_Ok; 855 856 size->bytecode_ready = error; 857 858 if ( !error ) 859 TT_Save_Context( exec, size ); 860 861 return error; 862 } 863 864 865 /*************************************************************************/ 866 /* */ 867 /* <Function> */ 868 /* tt_size_run_prep */ 869 /* */ 870 /* <Description> */ 871 /* Run the control value program. */ 872 /* */ 873 /* <Input> */ 874 /* size :: A handle to the size object. */ 875 /* */ 876 /* pedantic :: Set if bytecode execution should be pedantic. */ 877 /* */ 878 /* <Return> */ 879 /* FreeType error code. 0 means success. */ 880 /* */ 881 FT_LOCAL_DEF( FT_Error ) 882 tt_size_run_prep( TT_Size size, 883 FT_Bool pedantic ) 884 { 885 TT_Face face = (TT_Face)size->root.face; 886 TT_ExecContext exec; 887 FT_Error error; 888 889 890 exec = size->context; 891 892 error = TT_Load_Context( exec, face, size ); 893 if ( error ) 894 return error; 895 896 exec->callTop = 0; 897 exec->top = 0; 898 899 exec->instruction_trap = FALSE; 900 901 exec->pedantic_hinting = pedantic; 902 903 TT_Set_CodeRange( exec, 904 tt_coderange_cvt, 905 face->cvt_program, 906 (FT_Long)face->cvt_program_size ); 907 908 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 909 910 if ( face->cvt_program_size > 0 ) 911 { 912 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 913 914 FT_TRACE4(( "Executing `prep' table.\n" )); 915 916 error = face->interpreter( exec ); 917 } 918 else 919 error = FT_Err_Ok; 920 921 size->cvt_ready = error; 922 923 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 924 /* graphics state variables to be modified by the CVT program. */ 925 926 exec->GS.dualVector.x = 0x4000; 927 exec->GS.dualVector.y = 0; 928 exec->GS.projVector.x = 0x4000; 929 exec->GS.projVector.y = 0x0; 930 exec->GS.freeVector.x = 0x4000; 931 exec->GS.freeVector.y = 0x0; 932 933 exec->GS.rp0 = 0; 934 exec->GS.rp1 = 0; 935 exec->GS.rp2 = 0; 936 937 exec->GS.gep0 = 1; 938 exec->GS.gep1 = 1; 939 exec->GS.gep2 = 1; 940 941 exec->GS.loop = 1; 942 943 /* save as default graphics state */ 944 size->GS = exec->GS; 945 946 TT_Save_Context( exec, size ); 947 948 return error; 949 } 950 951 952 static void 953 tt_size_done_bytecode( FT_Size ftsize ) 954 { 955 TT_Size size = (TT_Size)ftsize; 956 TT_Face face = (TT_Face)ftsize->face; 957 FT_Memory memory = face->root.memory; 958 959 if ( size->context ) 960 { 961 TT_Done_Context( size->context ); 962 size->context = NULL; 963 } 964 965 FT_FREE( size->cvt ); 966 size->cvt_size = 0; 967 968 /* free storage area */ 969 FT_FREE( size->storage ); 970 size->storage_size = 0; 971 972 /* twilight zone */ 973 tt_glyphzone_done( &size->twilight ); 974 975 FT_FREE( size->function_defs ); 976 FT_FREE( size->instruction_defs ); 977 978 size->num_function_defs = 0; 979 size->max_function_defs = 0; 980 size->num_instruction_defs = 0; 981 size->max_instruction_defs = 0; 982 983 size->max_func = 0; 984 size->max_ins = 0; 985 986 size->bytecode_ready = -1; 987 size->cvt_ready = -1; 988 } 989 990 991 /* Initialize bytecode-related fields in the size object. */ 992 /* We do this only if bytecode interpretation is really needed. */ 993 static FT_Error 994 tt_size_init_bytecode( FT_Size ftsize, 995 FT_Bool pedantic ) 996 { 997 FT_Error error; 998 TT_Size size = (TT_Size)ftsize; 999 TT_Face face = (TT_Face)ftsize->face; 1000 FT_Memory memory = face->root.memory; 1001 1002 FT_UShort n_twilight; 1003 TT_MaxProfile* maxp = &face->max_profile; 1004 1005 1006 /* clean up bytecode related data */ 1007 FT_FREE( size->function_defs ); 1008 FT_FREE( size->instruction_defs ); 1009 FT_FREE( size->cvt ); 1010 FT_FREE( size->storage ); 1011 1012 if ( size->context ) 1013 TT_Done_Context( size->context ); 1014 tt_glyphzone_done( &size->twilight ); 1015 1016 size->bytecode_ready = -1; 1017 size->cvt_ready = -1; 1018 1019 size->context = TT_New_Context( (TT_Driver)face->root.driver ); 1020 1021 size->max_function_defs = maxp->maxFunctionDefs; 1022 size->max_instruction_defs = maxp->maxInstructionDefs; 1023 1024 size->num_function_defs = 0; 1025 size->num_instruction_defs = 0; 1026 1027 size->max_func = 0; 1028 size->max_ins = 0; 1029 1030 size->cvt_size = face->cvt_size; 1031 size->storage_size = maxp->maxStorage; 1032 1033 /* Set default metrics */ 1034 { 1035 TT_Size_Metrics* metrics = &size->ttmetrics; 1036 1037 1038 metrics->rotated = FALSE; 1039 metrics->stretched = FALSE; 1040 1041 /* set default engine compensation */ 1042 metrics->compensations[0] = 0; /* gray */ 1043 metrics->compensations[1] = 0; /* black */ 1044 metrics->compensations[2] = 0; /* white */ 1045 metrics->compensations[3] = 0; /* reserved */ 1046 } 1047 1048 /* allocate function defs, instruction defs, cvt, and storage area */ 1049 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1050 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1051 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1052 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1053 goto Exit; 1054 1055 /* reserve twilight zone */ 1056 n_twilight = maxp->maxTwilightPoints; 1057 1058 /* there are 4 phantom points (do we need this?) */ 1059 n_twilight += 4; 1060 1061 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1062 if ( error ) 1063 goto Exit; 1064 1065 size->twilight.n_points = n_twilight; 1066 1067 size->GS = tt_default_graphics_state; 1068 1069 /* set `face->interpreter' according to the debug hook present */ 1070 { 1071 FT_Library library = face->root.driver->root.library; 1072 1073 1074 face->interpreter = (TT_Interpreter) 1075 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1076 if ( !face->interpreter ) 1077 face->interpreter = (TT_Interpreter)TT_RunIns; 1078 } 1079 1080 /* Fine, now run the font program! */ 1081 error = tt_size_run_fpgm( size, pedantic ); 1082 1083 Exit: 1084 if ( error ) 1085 tt_size_done_bytecode( ftsize ); 1086 1087 return error; 1088 } 1089 1090 1091 FT_LOCAL_DEF( FT_Error ) 1092 tt_size_ready_bytecode( TT_Size size, 1093 FT_Bool pedantic ) 1094 { 1095 FT_Error error = FT_Err_Ok; 1096 1097 1098 if ( size->bytecode_ready < 0 ) 1099 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1100 1101 if ( error || size->bytecode_ready ) 1102 goto Exit; 1103 1104 /* rescale CVT when needed */ 1105 if ( size->cvt_ready < 0 ) 1106 { 1107 FT_UInt i; 1108 TT_Face face = (TT_Face)size->root.face; 1109 1110 1111 /* Scale the cvt values to the new ppem. */ 1112 /* We use by default the y ppem to scale the CVT. */ 1113 for ( i = 0; i < size->cvt_size; i++ ) 1114 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 1115 1116 /* all twilight points are originally zero */ 1117 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) 1118 { 1119 size->twilight.org[i].x = 0; 1120 size->twilight.org[i].y = 0; 1121 size->twilight.cur[i].x = 0; 1122 size->twilight.cur[i].y = 0; 1123 } 1124 1125 /* clear storage area */ 1126 for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) 1127 size->storage[i] = 0; 1128 1129 size->GS = tt_default_graphics_state; 1130 1131 error = tt_size_run_prep( size, pedantic ); 1132 } 1133 1134 Exit: 1135 return error; 1136 } 1137 1138 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1139 1140 1141 /*************************************************************************/ 1142 /* */ 1143 /* <Function> */ 1144 /* tt_size_init */ 1145 /* */ 1146 /* <Description> */ 1147 /* Initialize a new TrueType size object. */ 1148 /* */ 1149 /* <InOut> */ 1150 /* size :: A handle to the size object. */ 1151 /* */ 1152 /* <Return> */ 1153 /* FreeType error code. 0 means success. */ 1154 /* */ 1155 FT_LOCAL_DEF( FT_Error ) 1156 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1157 { 1158 TT_Size size = (TT_Size)ttsize; 1159 FT_Error error = FT_Err_Ok; 1160 1161 1162 #ifdef TT_USE_BYTECODE_INTERPRETER 1163 size->bytecode_ready = -1; 1164 size->cvt_ready = -1; 1165 #endif 1166 1167 size->ttmetrics.valid = FALSE; 1168 size->strike_index = 0xFFFFFFFFUL; 1169 1170 return error; 1171 } 1172 1173 1174 /*************************************************************************/ 1175 /* */ 1176 /* <Function> */ 1177 /* tt_size_done */ 1178 /* */ 1179 /* <Description> */ 1180 /* The TrueType size object finalizer. */ 1181 /* */ 1182 /* <Input> */ 1183 /* size :: A handle to the target size object. */ 1184 /* */ 1185 FT_LOCAL_DEF( void ) 1186 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1187 { 1188 TT_Size size = (TT_Size)ttsize; 1189 1190 1191 #ifdef TT_USE_BYTECODE_INTERPRETER 1192 tt_size_done_bytecode( ttsize ); 1193 #endif 1194 1195 size->ttmetrics.valid = FALSE; 1196 } 1197 1198 1199 /*************************************************************************/ 1200 /* */ 1201 /* <Function> */ 1202 /* tt_size_reset */ 1203 /* */ 1204 /* <Description> */ 1205 /* Reset a TrueType size when resolutions and character dimensions */ 1206 /* have been changed. */ 1207 /* */ 1208 /* <Input> */ 1209 /* size :: A handle to the target size object. */ 1210 /* */ 1211 FT_LOCAL_DEF( FT_Error ) 1212 tt_size_reset( TT_Size size ) 1213 { 1214 TT_Face face; 1215 FT_Error error = FT_Err_Ok; 1216 FT_Size_Metrics* metrics; 1217 1218 1219 size->ttmetrics.valid = FALSE; 1220 1221 face = (TT_Face)size->root.face; 1222 1223 metrics = &size->metrics; 1224 1225 /* copy the result from base layer */ 1226 *metrics = size->root.metrics; 1227 1228 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) 1229 return FT_THROW( Invalid_PPem ); 1230 1231 /* This bit flag, if set, indicates that the ppems must be */ 1232 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1233 /* set, as hinting won't work really well otherwise. */ 1234 /* */ 1235 if ( face->header.Flags & 8 ) 1236 { 1237 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1238 face->root.units_per_EM ); 1239 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1240 face->root.units_per_EM ); 1241 1242 metrics->ascender = 1243 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); 1244 metrics->descender = 1245 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); 1246 metrics->height = 1247 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); 1248 metrics->max_advance = 1249 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, 1250 metrics->x_scale ) ); 1251 } 1252 1253 /* compute new transformation */ 1254 if ( metrics->x_ppem >= metrics->y_ppem ) 1255 { 1256 size->ttmetrics.scale = metrics->x_scale; 1257 size->ttmetrics.ppem = metrics->x_ppem; 1258 size->ttmetrics.x_ratio = 0x10000L; 1259 size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, 1260 metrics->x_ppem ); 1261 } 1262 else 1263 { 1264 size->ttmetrics.scale = metrics->y_scale; 1265 size->ttmetrics.ppem = metrics->y_ppem; 1266 size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, 1267 metrics->y_ppem ); 1268 size->ttmetrics.y_ratio = 0x10000L; 1269 } 1270 1271 #ifdef TT_USE_BYTECODE_INTERPRETER 1272 size->cvt_ready = -1; 1273 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1274 1275 if ( !error ) 1276 size->ttmetrics.valid = TRUE; 1277 1278 return error; 1279 } 1280 1281 1282 /*************************************************************************/ 1283 /* */ 1284 /* <Function> */ 1285 /* tt_driver_init */ 1286 /* */ 1287 /* <Description> */ 1288 /* Initialize a given TrueType driver object. */ 1289 /* */ 1290 /* <Input> */ 1291 /* driver :: A handle to the target driver object. */ 1292 /* */ 1293 /* <Return> */ 1294 /* FreeType error code. 0 means success. */ 1295 /* */ 1296 FT_LOCAL_DEF( FT_Error ) 1297 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1298 { 1299 1300 #ifdef TT_USE_BYTECODE_INTERPRETER 1301 1302 TT_Driver driver = (TT_Driver)ttdriver; 1303 1304 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1305 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1306 #else 1307 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1308 #endif 1309 1310 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1311 1312 FT_UNUSED( ttdriver ); 1313 1314 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1315 1316 return FT_Err_Ok; 1317 } 1318 1319 1320 /*************************************************************************/ 1321 /* */ 1322 /* <Function> */ 1323 /* tt_driver_done */ 1324 /* */ 1325 /* <Description> */ 1326 /* Finalize a given TrueType driver. */ 1327 /* */ 1328 /* <Input> */ 1329 /* driver :: A handle to the target TrueType driver. */ 1330 /* */ 1331 FT_LOCAL_DEF( void ) 1332 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1333 { 1334 FT_UNUSED( ttdriver ); 1335 } 1336 1337 1338 /*************************************************************************/ 1339 /* */ 1340 /* <Function> */ 1341 /* tt_slot_init */ 1342 /* */ 1343 /* <Description> */ 1344 /* Initialize a new slot object. */ 1345 /* */ 1346 /* <InOut> */ 1347 /* slot :: A handle to the slot object. */ 1348 /* */ 1349 /* <Return> */ 1350 /* FreeType error code. 0 means success. */ 1351 /* */ 1352 FT_LOCAL_DEF( FT_Error ) 1353 tt_slot_init( FT_GlyphSlot slot ) 1354 { 1355 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1356 } 1357 1358 1359 /* END */ 1360