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