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 ) 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 { 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 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 exec = size->context; 755 756 error = TT_Load_Context( exec, face, size ); 757 if ( error ) 758 return error; 759 760 exec->callTop = 0; 761 exec->top = 0; 762 763 exec->period = 64; 764 exec->phase = 0; 765 exec->threshold = 0; 766 767 exec->instruction_trap = FALSE; 768 exec->F_dot_P = 0x4000L; 769 770 exec->pedantic_hinting = pedantic; 771 772 { 773 FT_Size_Metrics* metrics = &exec->metrics; 774 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 775 776 777 metrics->x_ppem = 0; 778 metrics->y_ppem = 0; 779 metrics->x_scale = 0; 780 metrics->y_scale = 0; 781 782 tt_metrics->ppem = 0; 783 tt_metrics->scale = 0; 784 tt_metrics->ratio = 0x10000L; 785 } 786 787 /* allow font program execution */ 788 TT_Set_CodeRange( exec, 789 tt_coderange_font, 790 face->font_program, 791 (FT_Long)face->font_program_size ); 792 793 /* disable CVT and glyph programs coderange */ 794 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 795 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 796 797 if ( face->font_program_size > 0 ) 798 { 799 TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 800 801 FT_TRACE4(( "Executing `fpgm' table.\n" )); 802 error = face->interpreter( exec ); 803 } 804 else 805 error = FT_Err_Ok; 806 807 size->bytecode_ready = error; 808 809 if ( !error ) 810 TT_Save_Context( exec, size ); 811 812 return error; 813 } 814 815 816 /*************************************************************************/ 817 /* */ 818 /* <Function> */ 819 /* tt_size_run_prep */ 820 /* */ 821 /* <Description> */ 822 /* Run the control value program. */ 823 /* */ 824 /* <Input> */ 825 /* size :: A handle to the size object. */ 826 /* */ 827 /* pedantic :: Set if bytecode execution should be pedantic. */ 828 /* */ 829 /* <Return> */ 830 /* FreeType error code. 0 means success. */ 831 /* */ 832 FT_LOCAL_DEF( FT_Error ) tt_size_run_prep(TT_Size size,FT_Bool pedantic)833 tt_size_run_prep( TT_Size size, 834 FT_Bool pedantic ) 835 { 836 TT_Face face = (TT_Face)size->root.face; 837 TT_ExecContext exec; 838 FT_Error error; 839 840 841 exec = size->context; 842 843 error = TT_Load_Context( exec, face, size ); 844 if ( error ) 845 return error; 846 847 exec->callTop = 0; 848 exec->top = 0; 849 850 exec->instruction_trap = FALSE; 851 852 exec->pedantic_hinting = pedantic; 853 854 TT_Set_CodeRange( exec, 855 tt_coderange_cvt, 856 face->cvt_program, 857 (FT_Long)face->cvt_program_size ); 858 859 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 860 861 if ( face->cvt_program_size > 0 ) 862 { 863 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 864 865 FT_TRACE4(( "Executing `prep' table.\n" )); 866 867 error = face->interpreter( exec ); 868 } 869 else 870 error = FT_Err_Ok; 871 872 size->cvt_ready = error; 873 874 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 875 /* graphics state variables to be modified by the CVT program. */ 876 877 exec->GS.dualVector.x = 0x4000; 878 exec->GS.dualVector.y = 0; 879 exec->GS.projVector.x = 0x4000; 880 exec->GS.projVector.y = 0x0; 881 exec->GS.freeVector.x = 0x4000; 882 exec->GS.freeVector.y = 0x0; 883 884 exec->GS.rp0 = 0; 885 exec->GS.rp1 = 0; 886 exec->GS.rp2 = 0; 887 888 exec->GS.gep0 = 1; 889 exec->GS.gep1 = 1; 890 exec->GS.gep2 = 1; 891 892 exec->GS.loop = 1; 893 894 /* save as default graphics state */ 895 size->GS = exec->GS; 896 897 TT_Save_Context( exec, size ); 898 899 return error; 900 } 901 902 903 static void tt_size_done_bytecode(FT_Size ftsize)904 tt_size_done_bytecode( FT_Size ftsize ) 905 { 906 TT_Size size = (TT_Size)ftsize; 907 TT_Face face = (TT_Face)ftsize->face; 908 FT_Memory memory = face->root.memory; 909 910 if ( size->context ) 911 { 912 TT_Done_Context( size->context ); 913 size->context = NULL; 914 } 915 916 FT_FREE( size->cvt ); 917 size->cvt_size = 0; 918 919 /* free storage area */ 920 FT_FREE( size->storage ); 921 size->storage_size = 0; 922 923 /* twilight zone */ 924 tt_glyphzone_done( &size->twilight ); 925 926 FT_FREE( size->function_defs ); 927 FT_FREE( size->instruction_defs ); 928 929 size->num_function_defs = 0; 930 size->max_function_defs = 0; 931 size->num_instruction_defs = 0; 932 size->max_instruction_defs = 0; 933 934 size->max_func = 0; 935 size->max_ins = 0; 936 937 size->bytecode_ready = -1; 938 size->cvt_ready = -1; 939 } 940 941 942 /* Initialize bytecode-related fields in the size object. */ 943 /* We do this only if bytecode interpretation is really needed. */ 944 static FT_Error tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)945 tt_size_init_bytecode( FT_Size ftsize, 946 FT_Bool pedantic ) 947 { 948 FT_Error error; 949 TT_Size size = (TT_Size)ftsize; 950 TT_Face face = (TT_Face)ftsize->face; 951 FT_Memory memory = face->root.memory; 952 953 FT_UShort n_twilight; 954 TT_MaxProfile* maxp = &face->max_profile; 955 956 957 /* clean up bytecode related data */ 958 FT_FREE( size->function_defs ); 959 FT_FREE( size->instruction_defs ); 960 FT_FREE( size->cvt ); 961 FT_FREE( size->storage ); 962 963 if ( size->context ) 964 TT_Done_Context( size->context ); 965 tt_glyphzone_done( &size->twilight ); 966 967 size->bytecode_ready = -1; 968 size->cvt_ready = -1; 969 970 size->context = TT_New_Context( (TT_Driver)face->root.driver ); 971 972 size->max_function_defs = maxp->maxFunctionDefs; 973 size->max_instruction_defs = maxp->maxInstructionDefs; 974 975 size->num_function_defs = 0; 976 size->num_instruction_defs = 0; 977 978 size->max_func = 0; 979 size->max_ins = 0; 980 981 size->cvt_size = face->cvt_size; 982 size->storage_size = maxp->maxStorage; 983 984 /* Set default metrics */ 985 { 986 TT_Size_Metrics* metrics = &size->ttmetrics; 987 988 989 metrics->rotated = FALSE; 990 metrics->stretched = FALSE; 991 992 /* set default engine compensation */ 993 metrics->compensations[0] = 0; /* gray */ 994 metrics->compensations[1] = 0; /* black */ 995 metrics->compensations[2] = 0; /* white */ 996 metrics->compensations[3] = 0; /* reserved */ 997 } 998 999 /* allocate function defs, instruction defs, cvt, and storage area */ 1000 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1001 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1002 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1003 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1004 goto Exit; 1005 1006 /* reserve twilight zone */ 1007 n_twilight = maxp->maxTwilightPoints; 1008 1009 /* there are 4 phantom points (do we need this?) */ 1010 n_twilight += 4; 1011 1012 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1013 if ( error ) 1014 goto Exit; 1015 1016 size->twilight.n_points = n_twilight; 1017 1018 size->GS = tt_default_graphics_state; 1019 1020 /* set `face->interpreter' according to the debug hook present */ 1021 { 1022 FT_Library library = face->root.driver->root.library; 1023 1024 1025 face->interpreter = (TT_Interpreter) 1026 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1027 if ( !face->interpreter ) 1028 face->interpreter = (TT_Interpreter)TT_RunIns; 1029 } 1030 1031 /* Fine, now run the font program! */ 1032 error = tt_size_run_fpgm( size, pedantic ); 1033 1034 Exit: 1035 if ( error ) 1036 tt_size_done_bytecode( ftsize ); 1037 1038 return error; 1039 } 1040 1041 1042 FT_LOCAL_DEF( FT_Error ) tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1043 tt_size_ready_bytecode( TT_Size size, 1044 FT_Bool pedantic ) 1045 { 1046 FT_Error error = FT_Err_Ok; 1047 1048 1049 if ( size->bytecode_ready < 0 ) 1050 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1051 1052 if ( error || size->bytecode_ready ) 1053 goto Exit; 1054 1055 /* rescale CVT when needed */ 1056 if ( size->cvt_ready < 0 ) 1057 { 1058 FT_UInt i; 1059 TT_Face face = (TT_Face)size->root.face; 1060 1061 1062 /* Scale the cvt values to the new ppem. */ 1063 /* We use by default the y ppem to scale the CVT. */ 1064 for ( i = 0; i < size->cvt_size; i++ ) 1065 size->cvt[i] = FT_MulFix( face->cvt[i], size->ttmetrics.scale ); 1066 1067 /* all twilight points are originally zero */ 1068 for ( i = 0; i < (FT_UInt)size->twilight.n_points; i++ ) 1069 { 1070 size->twilight.org[i].x = 0; 1071 size->twilight.org[i].y = 0; 1072 size->twilight.cur[i].x = 0; 1073 size->twilight.cur[i].y = 0; 1074 } 1075 1076 /* clear storage area */ 1077 for ( i = 0; i < (FT_UInt)size->storage_size; i++ ) 1078 size->storage[i] = 0; 1079 1080 size->GS = tt_default_graphics_state; 1081 1082 error = tt_size_run_prep( size, pedantic ); 1083 } 1084 1085 Exit: 1086 return error; 1087 } 1088 1089 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1090 1091 1092 /*************************************************************************/ 1093 /* */ 1094 /* <Function> */ 1095 /* tt_size_init */ 1096 /* */ 1097 /* <Description> */ 1098 /* Initialize a new TrueType size object. */ 1099 /* */ 1100 /* <InOut> */ 1101 /* size :: A handle to the size object. */ 1102 /* */ 1103 /* <Return> */ 1104 /* FreeType error code. 0 means success. */ 1105 /* */ 1106 FT_LOCAL_DEF( FT_Error ) tt_size_init(FT_Size ttsize)1107 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1108 { 1109 TT_Size size = (TT_Size)ttsize; 1110 FT_Error error = FT_Err_Ok; 1111 1112 1113 #ifdef TT_USE_BYTECODE_INTERPRETER 1114 size->bytecode_ready = -1; 1115 size->cvt_ready = -1; 1116 #endif 1117 1118 size->ttmetrics.valid = FALSE; 1119 size->strike_index = 0xFFFFFFFFUL; 1120 1121 return error; 1122 } 1123 1124 1125 /*************************************************************************/ 1126 /* */ 1127 /* <Function> */ 1128 /* tt_size_done */ 1129 /* */ 1130 /* <Description> */ 1131 /* The TrueType size object finalizer. */ 1132 /* */ 1133 /* <Input> */ 1134 /* size :: A handle to the target size object. */ 1135 /* */ 1136 FT_LOCAL_DEF( void ) tt_size_done(FT_Size ttsize)1137 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1138 { 1139 TT_Size size = (TT_Size)ttsize; 1140 1141 1142 #ifdef TT_USE_BYTECODE_INTERPRETER 1143 tt_size_done_bytecode( ttsize ); 1144 #endif 1145 1146 size->ttmetrics.valid = FALSE; 1147 } 1148 1149 1150 /*************************************************************************/ 1151 /* */ 1152 /* <Function> */ 1153 /* tt_size_reset */ 1154 /* */ 1155 /* <Description> */ 1156 /* Reset a TrueType size when resolutions and character dimensions */ 1157 /* have been changed. */ 1158 /* */ 1159 /* <Input> */ 1160 /* size :: A handle to the target size object. */ 1161 /* */ 1162 FT_LOCAL_DEF( FT_Error ) tt_size_reset(TT_Size size)1163 tt_size_reset( TT_Size size ) 1164 { 1165 TT_Face face; 1166 FT_Error error = FT_Err_Ok; 1167 FT_Size_Metrics* metrics; 1168 1169 1170 size->ttmetrics.valid = FALSE; 1171 1172 face = (TT_Face)size->root.face; 1173 1174 metrics = &size->metrics; 1175 1176 /* copy the result from base layer */ 1177 *metrics = size->root.metrics; 1178 1179 if ( metrics->x_ppem < 1 || metrics->y_ppem < 1 ) 1180 return FT_THROW( Invalid_PPem ); 1181 1182 /* This bit flag, if set, indicates that the ppems must be */ 1183 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1184 /* set, as hinting won't work really well otherwise. */ 1185 /* */ 1186 if ( face->header.Flags & 8 ) 1187 { 1188 metrics->x_scale = FT_DivFix( metrics->x_ppem << 6, 1189 face->root.units_per_EM ); 1190 metrics->y_scale = FT_DivFix( metrics->y_ppem << 6, 1191 face->root.units_per_EM ); 1192 1193 metrics->ascender = 1194 FT_PIX_ROUND( FT_MulFix( face->root.ascender, metrics->y_scale ) ); 1195 metrics->descender = 1196 FT_PIX_ROUND( FT_MulFix( face->root.descender, metrics->y_scale ) ); 1197 metrics->height = 1198 FT_PIX_ROUND( FT_MulFix( face->root.height, metrics->y_scale ) ); 1199 metrics->max_advance = 1200 FT_PIX_ROUND( FT_MulFix( face->root.max_advance_width, 1201 metrics->x_scale ) ); 1202 } 1203 1204 /* compute new transformation */ 1205 if ( metrics->x_ppem >= metrics->y_ppem ) 1206 { 1207 size->ttmetrics.scale = metrics->x_scale; 1208 size->ttmetrics.ppem = metrics->x_ppem; 1209 size->ttmetrics.x_ratio = 0x10000L; 1210 size->ttmetrics.y_ratio = FT_DivFix( metrics->y_ppem, 1211 metrics->x_ppem ); 1212 } 1213 else 1214 { 1215 size->ttmetrics.scale = metrics->y_scale; 1216 size->ttmetrics.ppem = metrics->y_ppem; 1217 size->ttmetrics.x_ratio = FT_DivFix( metrics->x_ppem, 1218 metrics->y_ppem ); 1219 size->ttmetrics.y_ratio = 0x10000L; 1220 } 1221 1222 #ifdef TT_USE_BYTECODE_INTERPRETER 1223 size->cvt_ready = -1; 1224 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1225 1226 if ( !error ) 1227 size->ttmetrics.valid = TRUE; 1228 1229 return error; 1230 } 1231 1232 1233 /*************************************************************************/ 1234 /* */ 1235 /* <Function> */ 1236 /* tt_driver_init */ 1237 /* */ 1238 /* <Description> */ 1239 /* Initialize a given TrueType driver object. */ 1240 /* */ 1241 /* <Input> */ 1242 /* driver :: A handle to the target driver object. */ 1243 /* */ 1244 /* <Return> */ 1245 /* FreeType error code. 0 means success. */ 1246 /* */ 1247 FT_LOCAL_DEF( FT_Error ) tt_driver_init(FT_Module ttdriver)1248 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1249 { 1250 1251 #ifdef TT_USE_BYTECODE_INTERPRETER 1252 1253 TT_Driver driver = (TT_Driver)ttdriver; 1254 1255 #ifdef TT_CONFIG_OPTION_SUBPIXEL_HINTING 1256 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1257 #else 1258 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1259 #endif 1260 1261 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1262 1263 FT_UNUSED( ttdriver ); 1264 1265 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1266 1267 return FT_Err_Ok; 1268 } 1269 1270 1271 /*************************************************************************/ 1272 /* */ 1273 /* <Function> */ 1274 /* tt_driver_done */ 1275 /* */ 1276 /* <Description> */ 1277 /* Finalize a given TrueType driver. */ 1278 /* */ 1279 /* <Input> */ 1280 /* driver :: A handle to the target TrueType driver. */ 1281 /* */ 1282 FT_LOCAL_DEF( void ) tt_driver_done(FT_Module ttdriver)1283 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1284 { 1285 FT_UNUSED( ttdriver ); 1286 } 1287 1288 1289 /*************************************************************************/ 1290 /* */ 1291 /* <Function> */ 1292 /* tt_slot_init */ 1293 /* */ 1294 /* <Description> */ 1295 /* Initialize a new slot object. */ 1296 /* */ 1297 /* <InOut> */ 1298 /* slot :: A handle to the slot object. */ 1299 /* */ 1300 /* <Return> */ 1301 /* FreeType error code. 0 means success. */ 1302 /* */ 1303 FT_LOCAL_DEF( FT_Error ) tt_slot_init(FT_GlyphSlot slot)1304 tt_slot_init( FT_GlyphSlot slot ) 1305 { 1306 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1307 } 1308 1309 1310 /* END */ 1311