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