1 /**************************************************************************** 2 * 3 * sfobjs.c 4 * 5 * SFNT object management (base). 6 * 7 * Copyright (C) 1996-2020 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 "sfobjs.h" 21 #include "ttload.h" 22 #include "ttcmap.h" 23 #include "ttkern.h" 24 #include "sfwoff.h" 25 #include "sfwoff2.h" 26 #include FT_INTERNAL_SFNT_H 27 #include FT_INTERNAL_DEBUG_H 28 #include FT_TRUETYPE_IDS_H 29 #include FT_TRUETYPE_TAGS_H 30 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 31 #include FT_SFNT_NAMES_H 32 33 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 34 #include FT_SERVICE_MULTIPLE_MASTERS_H 35 #include FT_SERVICE_METRICS_VARIATIONS_H 36 #endif 37 38 #include "sferrors.h" 39 40 #ifdef TT_CONFIG_OPTION_BDF 41 #include "ttbdf.h" 42 #endif 43 44 45 /************************************************************************** 46 * 47 * The macro FT_COMPONENT is used in trace mode. It is an implicit 48 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 49 * messages during execution. 50 */ 51 #undef FT_COMPONENT 52 #define FT_COMPONENT sfobjs 53 54 55 56 /* convert a UTF-16 name entry to ASCII */ 57 static FT_String* tt_name_ascii_from_utf16(TT_Name entry,FT_Memory memory)58 tt_name_ascii_from_utf16( TT_Name entry, 59 FT_Memory memory ) 60 { 61 FT_String* string = NULL; 62 FT_UInt len, code, n; 63 FT_Byte* read = (FT_Byte*)entry->string; 64 FT_Error error; 65 66 67 len = (FT_UInt)entry->stringLength / 2; 68 69 if ( FT_NEW_ARRAY( string, len + 1 ) ) 70 return NULL; 71 72 for ( n = 0; n < len; n++ ) 73 { 74 code = FT_NEXT_USHORT( read ); 75 76 if ( code == 0 ) 77 break; 78 79 if ( code < 32 || code > 127 ) 80 code = '?'; 81 82 string[n] = (char)code; 83 } 84 85 string[n] = 0; 86 87 return string; 88 } 89 90 91 /* convert an Apple Roman or symbol name entry to ASCII */ 92 static FT_String* tt_name_ascii_from_other(TT_Name entry,FT_Memory memory)93 tt_name_ascii_from_other( TT_Name entry, 94 FT_Memory memory ) 95 { 96 FT_String* string = NULL; 97 FT_UInt len, code, n; 98 FT_Byte* read = (FT_Byte*)entry->string; 99 FT_Error error; 100 101 102 len = (FT_UInt)entry->stringLength; 103 104 if ( FT_NEW_ARRAY( string, len + 1 ) ) 105 return NULL; 106 107 for ( n = 0; n < len; n++ ) 108 { 109 code = *read++; 110 111 if ( code == 0 ) 112 break; 113 114 if ( code < 32 || code > 127 ) 115 code = '?'; 116 117 string[n] = (char)code; 118 } 119 120 string[n] = 0; 121 122 return string; 123 } 124 125 126 typedef FT_String* (*TT_Name_ConvertFunc)( TT_Name entry, 127 FT_Memory memory ); 128 129 130 /* documentation is in sfnt.h */ 131 132 FT_LOCAL_DEF( FT_Error ) tt_face_get_name(TT_Face face,FT_UShort nameid,FT_String ** name)133 tt_face_get_name( TT_Face face, 134 FT_UShort nameid, 135 FT_String** name ) 136 { 137 FT_Memory memory = face->root.memory; 138 FT_Error error = FT_Err_Ok; 139 FT_String* result = NULL; 140 FT_UShort n; 141 TT_Name rec; 142 143 FT_Int found_apple = -1; 144 FT_Int found_apple_roman = -1; 145 FT_Int found_apple_english = -1; 146 FT_Int found_win = -1; 147 FT_Int found_unicode = -1; 148 149 FT_Bool is_english = 0; 150 151 TT_Name_ConvertFunc convert; 152 153 154 FT_ASSERT( name ); 155 156 rec = face->name_table.names; 157 for ( n = 0; n < face->num_names; n++, rec++ ) 158 { 159 /* According to the OpenType 1.3 specification, only Microsoft or */ 160 /* Apple platform IDs might be used in the `name' table. The */ 161 /* `Unicode' platform is reserved for the `cmap' table, and the */ 162 /* `ISO' one is deprecated. */ 163 /* */ 164 /* However, the Apple TrueType specification doesn't say the same */ 165 /* thing and goes to suggest that all Unicode `name' table entries */ 166 /* should be coded in UTF-16 (in big-endian format I suppose). */ 167 /* */ 168 if ( rec->nameID == nameid && rec->stringLength > 0 ) 169 { 170 switch ( rec->platformID ) 171 { 172 case TT_PLATFORM_APPLE_UNICODE: 173 case TT_PLATFORM_ISO: 174 /* there is `languageID' to check there. We should use this */ 175 /* field only as a last solution when nothing else is */ 176 /* available. */ 177 /* */ 178 found_unicode = n; 179 break; 180 181 case TT_PLATFORM_MACINTOSH: 182 /* This is a bit special because some fonts will use either */ 183 /* an English language id, or a Roman encoding id, to indicate */ 184 /* the English version of its font name. */ 185 /* */ 186 if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) 187 found_apple_english = n; 188 else if ( rec->encodingID == TT_MAC_ID_ROMAN ) 189 found_apple_roman = n; 190 break; 191 192 case TT_PLATFORM_MICROSOFT: 193 /* we only take a non-English name when there is nothing */ 194 /* else available in the font */ 195 /* */ 196 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) 197 { 198 switch ( rec->encodingID ) 199 { 200 case TT_MS_ID_SYMBOL_CS: 201 case TT_MS_ID_UNICODE_CS: 202 case TT_MS_ID_UCS_4: 203 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); 204 found_win = n; 205 break; 206 207 default: 208 ; 209 } 210 } 211 break; 212 213 default: 214 ; 215 } 216 } 217 } 218 219 found_apple = found_apple_roman; 220 if ( found_apple_english >= 0 ) 221 found_apple = found_apple_english; 222 223 /* some fonts contain invalid Unicode or Macintosh formatted entries; */ 224 /* we will thus favor names encoded in Windows formats if available */ 225 /* (provided it is an English name) */ 226 /* */ 227 convert = NULL; 228 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) 229 { 230 rec = face->name_table.names + found_win; 231 switch ( rec->encodingID ) 232 { 233 /* all Unicode strings are encoded using UTF-16BE */ 234 case TT_MS_ID_UNICODE_CS: 235 case TT_MS_ID_SYMBOL_CS: 236 convert = tt_name_ascii_from_utf16; 237 break; 238 239 case TT_MS_ID_UCS_4: 240 /* Apparently, if this value is found in a name table entry, it is */ 241 /* documented as `full Unicode repertoire'. Experience with the */ 242 /* MsGothic font shipped with Windows Vista shows that this really */ 243 /* means UTF-16 encoded names (UCS-4 values are only used within */ 244 /* charmaps). */ 245 convert = tt_name_ascii_from_utf16; 246 break; 247 248 default: 249 ; 250 } 251 } 252 else if ( found_apple >= 0 ) 253 { 254 rec = face->name_table.names + found_apple; 255 convert = tt_name_ascii_from_other; 256 } 257 else if ( found_unicode >= 0 ) 258 { 259 rec = face->name_table.names + found_unicode; 260 convert = tt_name_ascii_from_utf16; 261 } 262 263 if ( rec && convert ) 264 { 265 if ( !rec->string ) 266 { 267 FT_Stream stream = face->name_table.stream; 268 269 270 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || 271 FT_STREAM_SEEK( rec->stringOffset ) || 272 FT_STREAM_READ( rec->string, rec->stringLength ) ) 273 { 274 FT_FREE( rec->string ); 275 rec->stringLength = 0; 276 result = NULL; 277 goto Exit; 278 } 279 } 280 281 result = convert( rec, memory ); 282 } 283 284 Exit: 285 *name = result; 286 return error; 287 } 288 289 290 static FT_Encoding sfnt_find_encoding(int platform_id,int encoding_id)291 sfnt_find_encoding( int platform_id, 292 int encoding_id ) 293 { 294 typedef struct TEncoding_ 295 { 296 int platform_id; 297 int encoding_id; 298 FT_Encoding encoding; 299 300 } TEncoding; 301 302 static 303 const TEncoding tt_encodings[] = 304 { 305 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, 306 307 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, 308 309 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, 310 311 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, 312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, 313 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, 314 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, 315 { TT_PLATFORM_MICROSOFT, TT_MS_ID_PRC, FT_ENCODING_PRC }, 316 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, 317 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, 318 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } 319 }; 320 321 const TEncoding *cur, *limit; 322 323 324 cur = tt_encodings; 325 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); 326 327 for ( ; cur < limit; cur++ ) 328 { 329 if ( cur->platform_id == platform_id ) 330 { 331 if ( cur->encoding_id == encoding_id || 332 cur->encoding_id == -1 ) 333 return cur->encoding; 334 } 335 } 336 337 return FT_ENCODING_NONE; 338 } 339 340 341 /* Fill in face->ttc_header. If the font is not a TTC, it is */ 342 /* synthesized into a TTC with one offset table. */ 343 static FT_Error sfnt_open_font(FT_Stream stream,TT_Face face,FT_Int * face_instance_index,FT_Long * woff2_num_faces)344 sfnt_open_font( FT_Stream stream, 345 TT_Face face, 346 FT_Int* face_instance_index, 347 FT_Long* woff2_num_faces ) 348 { 349 FT_Memory memory = stream->memory; 350 FT_Error error; 351 FT_ULong tag, offset; 352 353 static const FT_Frame_Field ttc_header_fields[] = 354 { 355 #undef FT_STRUCTURE 356 #define FT_STRUCTURE TTC_HeaderRec 357 358 FT_FRAME_START( 8 ), 359 FT_FRAME_LONG( version ), 360 FT_FRAME_LONG( count ), /* this is ULong in the specs */ 361 FT_FRAME_END 362 }; 363 364 365 face->ttc_header.tag = 0; 366 face->ttc_header.version = 0; 367 face->ttc_header.count = 0; 368 369 retry: 370 offset = FT_STREAM_POS(); 371 372 if ( FT_READ_ULONG( tag ) ) 373 return error; 374 375 if ( tag == TTAG_wOFF ) 376 { 377 FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); 378 379 if ( FT_STREAM_SEEK( offset ) ) 380 return error; 381 382 error = woff_open_font( stream, face ); 383 if ( error ) 384 return error; 385 386 /* Swap out stream and retry! */ 387 stream = face->root.stream; 388 goto retry; 389 } 390 391 if ( tag == TTAG_wOF2 ) 392 { 393 FT_TRACE2(( "sfnt_open_font: file is a WOFF2; synthesizing SFNT\n" )); 394 395 if ( FT_STREAM_SEEK( offset ) ) 396 return error; 397 398 error = woff2_open_font( stream, 399 face, 400 face_instance_index, 401 woff2_num_faces ); 402 if ( error ) 403 return error; 404 405 /* Swap out stream and retry! */ 406 stream = face->root.stream; 407 goto retry; 408 } 409 410 if ( tag != 0x00010000UL && 411 tag != TTAG_ttcf && 412 tag != TTAG_OTTO && 413 tag != TTAG_true && 414 tag != TTAG_typ1 && 415 tag != TTAG_0xA5kbd && 416 tag != TTAG_0xA5lst && 417 tag != 0x00020000UL ) 418 { 419 FT_TRACE2(( " not a font using the SFNT container format\n" )); 420 return FT_THROW( Unknown_File_Format ); 421 } 422 423 face->ttc_header.tag = TTAG_ttcf; 424 425 if ( tag == TTAG_ttcf ) 426 { 427 FT_Int n; 428 429 430 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); 431 432 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) 433 return error; 434 435 FT_TRACE3(( " with %ld subfonts\n", 436 face->ttc_header.count )); 437 438 if ( face->ttc_header.count == 0 ) 439 return FT_THROW( Invalid_Table ); 440 441 /* a rough size estimate: let's conservatively assume that there */ 442 /* is just a single table info in each subfont header (12 + 16*1 = */ 443 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ 444 /* size of the TTC header plus `28*count' bytes for all subfont */ 445 /* headers */ 446 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) 447 return FT_THROW( Array_Too_Large ); 448 449 /* now read the offsets of each font in the file */ 450 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) 451 return error; 452 453 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) 454 return error; 455 456 for ( n = 0; n < face->ttc_header.count; n++ ) 457 face->ttc_header.offsets[n] = FT_GET_ULONG(); 458 459 FT_FRAME_EXIT(); 460 } 461 else 462 { 463 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); 464 465 face->ttc_header.version = 1 << 16; 466 face->ttc_header.count = 1; 467 468 if ( FT_NEW( face->ttc_header.offsets ) ) 469 return error; 470 471 face->ttc_header.offsets[0] = offset; 472 } 473 474 return error; 475 } 476 477 478 FT_LOCAL_DEF( FT_Error ) sfnt_init_face(FT_Stream stream,TT_Face face,FT_Int face_instance_index,FT_Int num_params,FT_Parameter * params)479 sfnt_init_face( FT_Stream stream, 480 TT_Face face, 481 FT_Int face_instance_index, 482 FT_Int num_params, 483 FT_Parameter* params ) 484 { 485 FT_Error error; 486 FT_Library library = face->root.driver->root.library; 487 SFNT_Service sfnt; 488 FT_Int face_index; 489 FT_Long woff2_num_faces = 0; 490 491 492 /* for now, parameters are unused */ 493 FT_UNUSED( num_params ); 494 FT_UNUSED( params ); 495 496 497 sfnt = (SFNT_Service)face->sfnt; 498 if ( !sfnt ) 499 { 500 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 501 if ( !sfnt ) 502 { 503 FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); 504 return FT_THROW( Missing_Module ); 505 } 506 507 face->sfnt = sfnt; 508 face->goto_table = sfnt->goto_table; 509 } 510 511 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); 512 513 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 514 if ( !face->mm ) 515 { 516 /* we want the MM interface from the `truetype' module only */ 517 FT_Module tt_module = FT_Get_Module( library, "truetype" ); 518 519 520 face->mm = ft_module_get_service( tt_module, 521 FT_SERVICE_ID_MULTI_MASTERS, 522 0 ); 523 } 524 525 if ( !face->var ) 526 { 527 /* we want the metrics variations interface */ 528 /* from the `truetype' module only */ 529 FT_Module tt_module = FT_Get_Module( library, "truetype" ); 530 531 532 face->var = ft_module_get_service( tt_module, 533 FT_SERVICE_ID_METRICS_VARIATIONS, 534 0 ); 535 } 536 #endif 537 538 FT_TRACE2(( "SFNT driver\n" )); 539 540 error = sfnt_open_font( stream, 541 face, 542 &face_instance_index, 543 &woff2_num_faces ); 544 if ( error ) 545 return error; 546 547 /* Stream may have changed in sfnt_open_font. */ 548 stream = face->root.stream; 549 550 FT_TRACE2(( "sfnt_init_face: %08p (index %d)\n", 551 face, 552 face_instance_index )); 553 554 face_index = FT_ABS( face_instance_index ) & 0xFFFF; 555 556 /* value -(N+1) requests information on index N */ 557 if ( face_instance_index < 0 ) 558 face_index--; 559 560 if ( face_index >= face->ttc_header.count ) 561 { 562 if ( face_instance_index >= 0 ) 563 return FT_THROW( Invalid_Argument ); 564 else 565 face_index = 0; 566 } 567 568 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) 569 return error; 570 571 /* check whether we have a valid TrueType file */ 572 error = sfnt->load_font_dir( face, stream ); 573 if ( error ) 574 return error; 575 576 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 577 { 578 FT_Memory memory = face->root.memory; 579 580 FT_ULong fvar_len; 581 582 FT_ULong version; 583 FT_ULong offset; 584 585 FT_UShort num_axes; 586 FT_UShort axis_size; 587 FT_UShort num_instances; 588 FT_UShort instance_size; 589 590 FT_Int instance_index; 591 592 FT_Byte* default_values = NULL; 593 FT_Byte* instance_values = NULL; 594 595 596 instance_index = FT_ABS( face_instance_index ) >> 16; 597 598 /* test whether current face is a GX font with named instances */ 599 if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || 600 fvar_len < 20 || 601 FT_READ_ULONG( version ) || 602 FT_READ_USHORT( offset ) || 603 FT_STREAM_SKIP( 2 ) /* reserved */ || 604 FT_READ_USHORT( num_axes ) || 605 FT_READ_USHORT( axis_size ) || 606 FT_READ_USHORT( num_instances ) || 607 FT_READ_USHORT( instance_size ) ) 608 { 609 version = 0; 610 offset = 0; 611 num_axes = 0; 612 axis_size = 0; 613 num_instances = 0; 614 instance_size = 0; 615 } 616 617 /* check that the data is bound by the table length */ 618 if ( version != 0x00010000UL || 619 axis_size != 20 || 620 num_axes == 0 || 621 /* `num_axes' limit implied by 16-bit `instance_size' */ 622 num_axes > 0x3FFE || 623 !( instance_size == 4 + 4 * num_axes || 624 instance_size == 6 + 4 * num_axes ) || 625 /* `num_instances' limit implied by limited range of name IDs */ 626 num_instances > 0x7EFF || 627 offset + 628 axis_size * num_axes + 629 instance_size * num_instances > fvar_len ) 630 num_instances = 0; 631 else 632 face->variation_support |= TT_FACE_FLAG_VAR_FVAR; 633 634 /* 635 * As documented in the OpenType specification, an entry for the 636 * default instance may be omitted in the named instance table. In 637 * particular this means that even if there is no named instance 638 * table in the font we actually do have a named instance, namely the 639 * default instance. 640 * 641 * For consistency, we always want the default instance in our list 642 * of named instances. If it is missing, we try to synthesize it 643 * later on. Here, we have to adjust `num_instances' accordingly. 644 */ 645 646 if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && 647 !( FT_ALLOC( default_values, num_axes * 4 ) || 648 FT_ALLOC( instance_values, num_axes * 4 ) ) ) 649 { 650 /* the current stream position is 16 bytes after the table start */ 651 FT_ULong array_start = FT_STREAM_POS() - 16 + offset; 652 FT_ULong default_value_offset, instance_offset; 653 654 FT_Byte* p; 655 FT_UInt i; 656 657 658 default_value_offset = array_start + 8; 659 p = default_values; 660 661 for ( i = 0; i < num_axes; i++ ) 662 { 663 (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); 664 665 default_value_offset += axis_size; 666 p += 4; 667 } 668 669 instance_offset = array_start + axis_size * num_axes + 4; 670 671 for ( i = 0; i < num_instances; i++ ) 672 { 673 (void)FT_STREAM_READ_AT( instance_offset, 674 instance_values, 675 num_axes * 4 ); 676 677 if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) 678 break; 679 680 instance_offset += instance_size; 681 } 682 683 if ( i == num_instances ) 684 { 685 /* no default instance in named instance table; */ 686 /* we thus have to synthesize it */ 687 num_instances++; 688 } 689 } 690 691 FT_FREE( default_values ); 692 FT_FREE( instance_values ); 693 694 /* we don't support Multiple Master CFFs yet; */ 695 /* note that `glyf' or `CFF2' have precedence */ 696 if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && 697 face->goto_table( face, TTAG_CFF2, stream, 0 ) && 698 !face->goto_table( face, TTAG_CFF, stream, 0 ) ) 699 num_instances = 0; 700 701 /* instance indices in `face_instance_index' start with index 1, */ 702 /* thus `>' and not `>=' */ 703 if ( instance_index > num_instances ) 704 { 705 if ( face_instance_index >= 0 ) 706 return FT_THROW( Invalid_Argument ); 707 else 708 num_instances = 0; 709 } 710 711 face->root.style_flags = (FT_Long)num_instances << 16; 712 } 713 #endif 714 715 face->root.num_faces = face->ttc_header.count; 716 face->root.face_index = face_instance_index; 717 718 /* `num_faces' for a WOFF2 needs to be handled separately. */ 719 if ( woff2_num_faces ) 720 face->root.num_faces = woff2_num_faces; 721 722 return error; 723 } 724 725 726 #define LOAD_( x ) \ 727 do \ 728 { \ 729 FT_TRACE2(( "`" #x "' " )); \ 730 FT_TRACE3(( "-->\n" )); \ 731 \ 732 error = sfnt->load_ ## x( face, stream ); \ 733 \ 734 FT_TRACE2(( "%s\n", ( !error ) \ 735 ? "loaded" \ 736 : FT_ERR_EQ( error, Table_Missing ) \ 737 ? "missing" \ 738 : "failed to load" )); \ 739 FT_TRACE3(( "\n" )); \ 740 } while ( 0 ) 741 742 #define LOADM_( x, vertical ) \ 743 do \ 744 { \ 745 FT_TRACE2(( "`%s" #x "' ", \ 746 vertical ? "vertical " : "" )); \ 747 FT_TRACE3(( "-->\n" )); \ 748 \ 749 error = sfnt->load_ ## x( face, stream, vertical ); \ 750 \ 751 FT_TRACE2(( "%s\n", ( !error ) \ 752 ? "loaded" \ 753 : FT_ERR_EQ( error, Table_Missing ) \ 754 ? "missing" \ 755 : "failed to load" )); \ 756 FT_TRACE3(( "\n" )); \ 757 } while ( 0 ) 758 759 #define GET_NAME( id, field ) \ 760 do \ 761 { \ 762 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ 763 if ( error ) \ 764 goto Exit; \ 765 } while ( 0 ) 766 767 768 FT_LOCAL_DEF( FT_Error ) sfnt_load_face(FT_Stream stream,TT_Face face,FT_Int face_instance_index,FT_Int num_params,FT_Parameter * params)769 sfnt_load_face( FT_Stream stream, 770 TT_Face face, 771 FT_Int face_instance_index, 772 FT_Int num_params, 773 FT_Parameter* params ) 774 { 775 FT_Error error; 776 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 777 FT_Error psnames_error; 778 #endif 779 FT_Bool has_outline; 780 FT_Bool is_apple_sbit; 781 FT_Bool is_apple_sbix; 782 FT_Bool has_CBLC; 783 FT_Bool has_CBDT; 784 FT_Bool ignore_typographic_family = FALSE; 785 FT_Bool ignore_typographic_subfamily = FALSE; 786 787 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 788 789 FT_UNUSED( face_instance_index ); 790 791 792 /* Check parameters */ 793 794 { 795 FT_Int i; 796 797 798 for ( i = 0; i < num_params; i++ ) 799 { 800 if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) 801 ignore_typographic_family = TRUE; 802 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) 803 ignore_typographic_subfamily = TRUE; 804 } 805 } 806 807 /* Load tables */ 808 809 /* We now support two SFNT-based bitmapped font formats. They */ 810 /* are recognized easily as they do not include a `glyf' */ 811 /* table. */ 812 /* */ 813 /* The first format comes from Apple, and uses a table named */ 814 /* `bhed' instead of `head' to store the font header (using */ 815 /* the same format). It also doesn't include horizontal and */ 816 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 817 /* missing). */ 818 /* */ 819 /* The other format comes from Microsoft, and is used with */ 820 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 821 /* it doesn't contain outlines. */ 822 /* */ 823 824 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); 825 826 /* do we have outlines in there? */ 827 #ifdef FT_CONFIG_OPTION_INCREMENTAL 828 has_outline = FT_BOOL( face->root.internal->incremental_interface || 829 tt_face_lookup_table( face, TTAG_glyf ) || 830 tt_face_lookup_table( face, TTAG_CFF ) || 831 tt_face_lookup_table( face, TTAG_CFF2 ) ); 832 #else 833 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) || 834 tt_face_lookup_table( face, TTAG_CFF ) || 835 tt_face_lookup_table( face, TTAG_CFF2 ) ); 836 #endif 837 838 is_apple_sbit = 0; 839 is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); 840 841 /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' 842 * outline rendered on top. We don't support that yet, so just ignore 843 * the 'glyf' outline and advertise it as a bitmap-only font. */ 844 if ( is_apple_sbix ) 845 has_outline = FALSE; 846 847 /* if this font doesn't contain outlines, we try to load */ 848 /* a `bhed' table */ 849 if ( !has_outline && sfnt->load_bhed ) 850 { 851 LOAD_( bhed ); 852 is_apple_sbit = FT_BOOL( !error ); 853 } 854 855 /* load the font header (`head' table) if this isn't an Apple */ 856 /* sbit font file */ 857 if ( !is_apple_sbit || is_apple_sbix ) 858 { 859 LOAD_( head ); 860 if ( error ) 861 goto Exit; 862 } 863 864 has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); 865 has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); 866 867 /* Ignore outlines for CBLC/CBDT fonts. */ 868 if ( has_CBLC || has_CBDT ) 869 has_outline = FALSE; 870 871 /* OpenType 1.8.2 introduced limits to this value; */ 872 /* however, they make sense for older SFNT fonts also */ 873 if ( face->header.Units_Per_EM < 16 || 874 face->header.Units_Per_EM > 16384 ) 875 { 876 error = FT_THROW( Invalid_Table ); 877 878 goto Exit; 879 } 880 881 /* the following tables are often not present in embedded TrueType */ 882 /* fonts within PDF documents, so don't check for them. */ 883 LOAD_( maxp ); 884 LOAD_( cmap ); 885 886 /* the following tables are optional in PCL fonts -- */ 887 /* don't check for errors */ 888 LOAD_( name ); 889 LOAD_( post ); 890 891 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 892 psnames_error = error; 893 #endif 894 895 /* do not load the metrics headers and tables if this is an Apple */ 896 /* sbit font file */ 897 if ( !is_apple_sbit ) 898 { 899 /* load the `hhea' and `hmtx' tables */ 900 LOADM_( hhea, 0 ); 901 if ( !error ) 902 { 903 LOADM_( hmtx, 0 ); 904 if ( FT_ERR_EQ( error, Table_Missing ) ) 905 { 906 error = FT_THROW( Hmtx_Table_Missing ); 907 908 #ifdef FT_CONFIG_OPTION_INCREMENTAL 909 /* If this is an incrementally loaded font and there are */ 910 /* overriding metrics, tolerate a missing `hmtx' table. */ 911 if ( face->root.internal->incremental_interface && 912 face->root.internal->incremental_interface->funcs-> 913 get_glyph_metrics ) 914 { 915 face->horizontal.number_Of_HMetrics = 0; 916 error = FT_Err_Ok; 917 } 918 #endif 919 } 920 } 921 else if ( FT_ERR_EQ( error, Table_Missing ) ) 922 { 923 /* No `hhea' table necessary for SFNT Mac fonts. */ 924 if ( face->format_tag == TTAG_true ) 925 { 926 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 927 928 has_outline = 0; 929 error = FT_Err_Ok; 930 } 931 else 932 { 933 error = FT_THROW( Horiz_Header_Missing ); 934 935 #ifdef FT_CONFIG_OPTION_INCREMENTAL 936 /* If this is an incrementally loaded font and there are */ 937 /* overriding metrics, tolerate a missing `hhea' table. */ 938 if ( face->root.internal->incremental_interface && 939 face->root.internal->incremental_interface->funcs-> 940 get_glyph_metrics ) 941 { 942 face->horizontal.number_Of_HMetrics = 0; 943 error = FT_Err_Ok; 944 } 945 #endif 946 947 } 948 } 949 950 if ( error ) 951 goto Exit; 952 953 /* try to load the `vhea' and `vmtx' tables */ 954 LOADM_( hhea, 1 ); 955 if ( !error ) 956 { 957 LOADM_( hmtx, 1 ); 958 if ( !error ) 959 face->vertical_info = 1; 960 } 961 962 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 963 goto Exit; 964 965 LOAD_( os2 ); 966 if ( error ) 967 { 968 /* we treat the table as missing if there are any errors */ 969 face->os2.version = 0xFFFFU; 970 } 971 } 972 973 /* the optional tables */ 974 975 /* embedded bitmap support */ 976 if ( sfnt->load_eblc ) 977 LOAD_( eblc ); 978 979 /* colored glyph support */ 980 if ( sfnt->load_cpal ) 981 { 982 LOAD_( cpal ); 983 LOAD_( colr ); 984 } 985 986 /* consider the pclt, kerning, and gasp tables as optional */ 987 LOAD_( pclt ); 988 LOAD_( gasp ); 989 LOAD_( kern ); 990 991 face->root.num_glyphs = face->max_profile.numGlyphs; 992 993 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 994 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 995 /* `slope', a term used by Microsoft's Windows Presentation */ 996 /* Foundation (WPF). This flag has been introduced in version */ 997 /* 1.5 of the OpenType specification (May 2008). */ 998 999 face->root.family_name = NULL; 1000 face->root.style_name = NULL; 1001 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 1002 { 1003 if ( !ignore_typographic_family ) 1004 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1005 if ( !face->root.family_name ) 1006 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1007 1008 if ( !ignore_typographic_subfamily ) 1009 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1010 if ( !face->root.style_name ) 1011 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1012 } 1013 else 1014 { 1015 GET_NAME( WWS_FAMILY, &face->root.family_name ); 1016 if ( !face->root.family_name && !ignore_typographic_family ) 1017 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1018 if ( !face->root.family_name ) 1019 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1020 1021 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 1022 if ( !face->root.style_name && !ignore_typographic_subfamily ) 1023 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1024 if ( !face->root.style_name ) 1025 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1026 } 1027 1028 /* now set up root fields */ 1029 { 1030 FT_Face root = &face->root; 1031 FT_Long flags = root->face_flags; 1032 1033 1034 /********************************************************************** 1035 * 1036 * Compute face flags. 1037 */ 1038 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || 1039 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || 1040 face->colr ) 1041 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ 1042 1043 if ( has_outline == TRUE ) 1044 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 1045 1046 /* The sfnt driver only supports bitmap fonts natively, thus we */ 1047 /* don't set FT_FACE_FLAG_HINTER. */ 1048 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 1049 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 1050 1051 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1052 if ( !psnames_error && 1053 face->postscript.FormatType != 0x00030000L ) 1054 flags |= FT_FACE_FLAG_GLYPH_NAMES; 1055 #endif 1056 1057 /* fixed width font? */ 1058 if ( face->postscript.isFixedPitch ) 1059 flags |= FT_FACE_FLAG_FIXED_WIDTH; 1060 1061 /* vertical information? */ 1062 if ( face->vertical_info ) 1063 flags |= FT_FACE_FLAG_VERTICAL; 1064 1065 /* kerning available ? */ 1066 if ( TT_FACE_HAS_KERNING( face ) ) 1067 flags |= FT_FACE_FLAG_KERNING; 1068 1069 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1070 /* Don't bother to load the tables unless somebody asks for them. */ 1071 /* No need to do work which will (probably) not be used. */ 1072 if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) 1073 { 1074 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && 1075 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) 1076 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1077 if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) 1078 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1079 } 1080 #endif 1081 1082 root->face_flags = flags; 1083 1084 /********************************************************************** 1085 * 1086 * Compute style flags. 1087 */ 1088 1089 flags = 0; 1090 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 1091 { 1092 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 1093 /* indicates an oblique font face. This flag has been */ 1094 /* introduced in version 1.5 of the OpenType specification. */ 1095 1096 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 1097 flags |= FT_STYLE_FLAG_ITALIC; 1098 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 1099 flags |= FT_STYLE_FLAG_ITALIC; 1100 1101 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 1102 flags |= FT_STYLE_FLAG_BOLD; 1103 } 1104 else 1105 { 1106 /* this is an old Mac font, use the header field */ 1107 1108 if ( face->header.Mac_Style & 1 ) 1109 flags |= FT_STYLE_FLAG_BOLD; 1110 1111 if ( face->header.Mac_Style & 2 ) 1112 flags |= FT_STYLE_FLAG_ITALIC; 1113 } 1114 1115 root->style_flags |= flags; 1116 1117 /********************************************************************** 1118 * 1119 * Polish the charmaps. 1120 * 1121 * Try to set the charmap encoding according to the platform & 1122 * encoding ID of each charmap. Emulate Unicode charmap if one 1123 * is missing. 1124 */ 1125 1126 tt_face_build_cmaps( face ); /* ignore errors */ 1127 1128 1129 /* set the encoding fields */ 1130 { 1131 FT_Int m; 1132 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1133 FT_Bool has_unicode = FALSE; 1134 #endif 1135 1136 1137 for ( m = 0; m < root->num_charmaps; m++ ) 1138 { 1139 FT_CharMap charmap = root->charmaps[m]; 1140 1141 1142 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 1143 charmap->encoding_id ); 1144 1145 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1146 1147 if ( charmap->encoding == FT_ENCODING_UNICODE || 1148 charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ 1149 has_unicode = TRUE; 1150 } 1151 1152 /* synthesize Unicode charmap if one is missing */ 1153 if ( !has_unicode ) 1154 { 1155 FT_CharMapRec cmaprec; 1156 1157 1158 cmaprec.face = root; 1159 cmaprec.platform_id = TT_PLATFORM_MICROSOFT; 1160 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; 1161 cmaprec.encoding = FT_ENCODING_UNICODE; 1162 1163 1164 error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, 1165 NULL, &cmaprec, NULL ); 1166 if ( error && 1167 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) && 1168 FT_ERR_NEQ( error, Unimplemented_Feature ) ) 1169 goto Exit; 1170 error = FT_Err_Ok; 1171 1172 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 1173 1174 } 1175 } 1176 1177 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1178 1179 /* 1180 * Now allocate the root array of FT_Bitmap_Size records and 1181 * populate them. Unfortunately, it isn't possible to indicate bit 1182 * depths in the FT_Bitmap_Size record. This is a design error. 1183 */ 1184 { 1185 FT_UInt count; 1186 1187 1188 count = face->sbit_num_strikes; 1189 1190 if ( count > 0 ) 1191 { 1192 FT_Memory memory = face->root.stream->memory; 1193 FT_UShort em_size = face->header.Units_Per_EM; 1194 FT_Short avgwidth = face->os2.xAvgCharWidth; 1195 FT_Size_Metrics metrics; 1196 1197 FT_UInt* sbit_strike_map = NULL; 1198 FT_UInt strike_idx, bsize_idx; 1199 1200 1201 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 1202 { 1203 avgwidth = 1; 1204 em_size = 1; 1205 } 1206 1207 /* to avoid invalid strike data in the `available_sizes' field */ 1208 /* of `FT_Face', we map `available_sizes' indices to strike */ 1209 /* indices */ 1210 if ( FT_NEW_ARRAY( root->available_sizes, count ) || 1211 FT_NEW_ARRAY( sbit_strike_map, count ) ) 1212 goto Exit; 1213 1214 bsize_idx = 0; 1215 for ( strike_idx = 0; strike_idx < count; strike_idx++ ) 1216 { 1217 FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx; 1218 1219 1220 error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); 1221 if ( error ) 1222 continue; 1223 1224 bsize->height = (FT_Short)( metrics.height >> 6 ); 1225 bsize->width = (FT_Short)( 1226 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 1227 1228 bsize->x_ppem = metrics.x_ppem << 6; 1229 bsize->y_ppem = metrics.y_ppem << 6; 1230 1231 /* assume 72dpi */ 1232 bsize->size = metrics.y_ppem << 6; 1233 1234 /* only use strikes with valid PPEM values */ 1235 if ( bsize->x_ppem && bsize->y_ppem ) 1236 sbit_strike_map[bsize_idx++] = strike_idx; 1237 } 1238 1239 /* reduce array size to the actually used elements */ 1240 (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx ); 1241 1242 /* from now on, all strike indices are mapped */ 1243 /* using `sbit_strike_map' */ 1244 if ( bsize_idx ) 1245 { 1246 face->sbit_strike_map = sbit_strike_map; 1247 1248 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 1249 root->num_fixed_sizes = (FT_Int)bsize_idx; 1250 } 1251 } 1252 } 1253 1254 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1255 1256 /* a font with no bitmaps and no outlines is scalable; */ 1257 /* it has only empty glyphs then */ 1258 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 1259 root->face_flags |= FT_FACE_FLAG_SCALABLE; 1260 1261 1262 /********************************************************************** 1263 * 1264 * Set up metrics. 1265 */ 1266 if ( FT_IS_SCALABLE( root ) ) 1267 { 1268 /* XXX What about if outline header is missing */ 1269 /* (e.g. sfnt wrapped bitmap)? */ 1270 root->bbox.xMin = face->header.xMin; 1271 root->bbox.yMin = face->header.yMin; 1272 root->bbox.xMax = face->header.xMax; 1273 root->bbox.yMax = face->header.yMax; 1274 root->units_per_EM = face->header.Units_Per_EM; 1275 1276 1277 /* 1278 * Computing the ascender/descender/height is tricky. 1279 * 1280 * The OpenType specification v1.8.3 says: 1281 * 1282 * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields 1283 * are intended to allow applications to lay out documents in a 1284 * typographically-correct and portable fashion. 1285 * 1286 * This is somewhat at odds with the decades of backwards 1287 * compatibility, operating systems and applications doing whatever 1288 * they want, not to mention broken fonts. 1289 * 1290 * Not all fonts have an OS/2 table; in this case, we take the values 1291 * in the horizontal header, although there is nothing stopping the 1292 * values from being unreliable. Even with a OS/2 table, certain fonts 1293 * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0 1294 * and instead correctly set usWinAscent and usWinDescent. 1295 * 1296 * As an example, Arial Narrow is shipped as four files ARIALN.TTF, 1297 * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have 1298 * the same values in their sTypo* fields, except ARIALNB.ttf which 1299 * sets them to 0. All of them have different usWinAscent/Descent 1300 * values. The OS/2 table therefore cannot be trusted for computing the 1301 * text height reliably. 1302 * 1303 * As a compromise, do the following: 1304 * 1305 * 1. If the OS/2 table exists and the fsSelection bit 7 is set 1306 * (USE_TYPO_METRICS), trust the font and use the sTypo* metrics. 1307 * 2. Otherwise, use the `hhea' table's metrics. 1308 * 3. If they are zero and the OS/2 table exists, 1309 * 1. use the OS/2 table's sTypo* metrics if they are non-zero. 1310 * 2. Otherwise, use the OS/2 table's usWin* metrics. 1311 */ 1312 1313 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 ) 1314 { 1315 root->ascender = face->os2.sTypoAscender; 1316 root->descender = face->os2.sTypoDescender; 1317 root->height = root->ascender - root->descender + 1318 face->os2.sTypoLineGap; 1319 } 1320 else 1321 { 1322 root->ascender = face->horizontal.Ascender; 1323 root->descender = face->horizontal.Descender; 1324 root->height = root->ascender - root->descender + 1325 face->horizontal.Line_Gap; 1326 1327 if ( !( root->ascender || root->descender ) ) 1328 { 1329 if ( face->os2.version != 0xFFFFU ) 1330 { 1331 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) 1332 { 1333 root->ascender = face->os2.sTypoAscender; 1334 root->descender = face->os2.sTypoDescender; 1335 root->height = root->ascender - root->descender + 1336 face->os2.sTypoLineGap; 1337 } 1338 else 1339 { 1340 root->ascender = (FT_Short)face->os2.usWinAscent; 1341 root->descender = -(FT_Short)face->os2.usWinDescent; 1342 root->height = root->ascender - root->descender; 1343 } 1344 } 1345 } 1346 } 1347 1348 root->max_advance_width = 1349 (FT_Short)face->horizontal.advance_Width_Max; 1350 root->max_advance_height = 1351 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max 1352 : root->height ); 1353 1354 /* See https://www.microsoft.com/typography/otspec/post.htm -- */ 1355 /* Adjust underline position from top edge to centre of */ 1356 /* stroke to convert TrueType meaning to FreeType meaning. */ 1357 root->underline_position = face->postscript.underlinePosition - 1358 face->postscript.underlineThickness / 2; 1359 root->underline_thickness = face->postscript.underlineThickness; 1360 } 1361 1362 } 1363 1364 Exit: 1365 FT_TRACE2(( "sfnt_load_face: done\n" )); 1366 1367 return error; 1368 } 1369 1370 1371 #undef LOAD_ 1372 #undef LOADM_ 1373 #undef GET_NAME 1374 1375 1376 FT_LOCAL_DEF( void ) sfnt_done_face(TT_Face face)1377 sfnt_done_face( TT_Face face ) 1378 { 1379 FT_Memory memory; 1380 SFNT_Service sfnt; 1381 1382 1383 if ( !face ) 1384 return; 1385 1386 memory = face->root.memory; 1387 sfnt = (SFNT_Service)face->sfnt; 1388 1389 if ( sfnt ) 1390 { 1391 /* destroy the postscript names table if it is loaded */ 1392 if ( sfnt->free_psnames ) 1393 sfnt->free_psnames( face ); 1394 1395 /* destroy the embedded bitmaps table if it is loaded */ 1396 if ( sfnt->free_eblc ) 1397 sfnt->free_eblc( face ); 1398 1399 /* destroy color table data if it is loaded */ 1400 if ( sfnt->free_cpal ) 1401 { 1402 sfnt->free_cpal( face ); 1403 sfnt->free_colr( face ); 1404 } 1405 } 1406 1407 #ifdef TT_CONFIG_OPTION_BDF 1408 /* freeing the embedded BDF properties */ 1409 tt_face_free_bdf_props( face ); 1410 #endif 1411 1412 /* freeing the kerning table */ 1413 tt_face_done_kern( face ); 1414 1415 /* freeing the collection table */ 1416 FT_FREE( face->ttc_header.offsets ); 1417 face->ttc_header.count = 0; 1418 1419 /* freeing table directory */ 1420 FT_FREE( face->dir_tables ); 1421 face->num_tables = 0; 1422 1423 { 1424 FT_Stream stream = FT_FACE_STREAM( face ); 1425 1426 1427 /* simply release the 'cmap' table frame */ 1428 FT_FRAME_RELEASE( face->cmap_table ); 1429 face->cmap_size = 0; 1430 } 1431 1432 face->horz_metrics_size = 0; 1433 face->vert_metrics_size = 0; 1434 1435 /* freeing vertical metrics, if any */ 1436 if ( face->vertical_info ) 1437 { 1438 FT_FREE( face->vertical.long_metrics ); 1439 FT_FREE( face->vertical.short_metrics ); 1440 face->vertical_info = 0; 1441 } 1442 1443 /* freeing the gasp table */ 1444 FT_FREE( face->gasp.gaspRanges ); 1445 face->gasp.numRanges = 0; 1446 1447 /* freeing the name table */ 1448 if ( sfnt ) 1449 sfnt->free_name( face ); 1450 1451 /* freeing family and style name */ 1452 FT_FREE( face->root.family_name ); 1453 FT_FREE( face->root.style_name ); 1454 1455 /* freeing sbit size table */ 1456 FT_FREE( face->root.available_sizes ); 1457 FT_FREE( face->sbit_strike_map ); 1458 face->root.num_fixed_sizes = 0; 1459 1460 FT_FREE( face->postscript_name ); 1461 1462 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1463 FT_FREE( face->var_postscript_prefix ); 1464 #endif 1465 1466 /* freeing glyph color palette data */ 1467 FT_FREE( face->palette_data.palette_name_ids ); 1468 FT_FREE( face->palette_data.palette_flags ); 1469 FT_FREE( face->palette_data.palette_entry_name_ids ); 1470 FT_FREE( face->palette ); 1471 1472 face->sfnt = NULL; 1473 } 1474 1475 1476 /* END */ 1477