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