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