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