1 /**************************************************************************** 2 * 3 * sfobjs.c 4 * 5 * SFNT object management (base). 6 * 7 * Copyright (C) 1996-2023 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 798 FT_Bool has_outline; 799 FT_Bool is_apple_sbit; 800 801 FT_Bool has_CBLC; 802 FT_Bool has_CBDT; 803 FT_Bool has_EBLC; 804 FT_Bool has_bloc; 805 FT_Bool has_sbix; 806 807 FT_Bool ignore_typographic_family = FALSE; 808 FT_Bool ignore_typographic_subfamily = FALSE; 809 FT_Bool ignore_sbix = FALSE; 810 811 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 812 813 FT_UNUSED( face_instance_index ); 814 815 816 /* Check parameters */ 817 818 { 819 FT_Int i; 820 821 822 for ( i = 0; i < num_params; i++ ) 823 { 824 if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) 825 ignore_typographic_family = TRUE; 826 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) 827 ignore_typographic_subfamily = TRUE; 828 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_SBIX ) 829 ignore_sbix = TRUE; 830 } 831 } 832 833 /* Load tables */ 834 835 /* We now support two SFNT-based bitmapped font formats. They */ 836 /* are recognized easily as they do not include a `glyf' */ 837 /* table. */ 838 /* */ 839 /* The first format comes from Apple, and uses a table named */ 840 /* `bhed' instead of `head' to store the font header (using */ 841 /* the same format). It also doesn't include horizontal and */ 842 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 843 /* missing). */ 844 /* */ 845 /* The other format comes from Microsoft, and is used with */ 846 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 847 /* it doesn't contain outlines. */ 848 /* */ 849 850 FT_TRACE2(( "sfnt_load_face: %p\n", (void *)face )); 851 FT_TRACE2(( "\n" )); 852 853 /* do we have outlines in there? */ 854 #ifdef FT_CONFIG_OPTION_INCREMENTAL 855 has_outline = FT_BOOL( face->root.internal->incremental_interface || 856 tt_face_lookup_table( face, TTAG_glyf ) || 857 tt_face_lookup_table( face, TTAG_CFF ) || 858 tt_face_lookup_table( face, TTAG_CFF2 ) ); 859 #else 860 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) || 861 tt_face_lookup_table( face, TTAG_CFF ) || 862 tt_face_lookup_table( face, TTAG_CFF2 ) ); 863 #endif 864 865 /* check which sbit formats are present */ 866 has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); 867 has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); 868 has_EBLC = !face->goto_table( face, TTAG_EBLC, stream, 0 ); 869 has_bloc = !face->goto_table( face, TTAG_bloc, stream, 0 ); 870 has_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); 871 872 is_apple_sbit = FALSE; 873 874 if ( ignore_sbix ) 875 has_sbix = FALSE; 876 877 /* if this font doesn't contain outlines, we try to load */ 878 /* a `bhed' table */ 879 if ( !has_outline && sfnt->load_bhed ) 880 { 881 LOAD_( bhed ); 882 is_apple_sbit = FT_BOOL( !error ); 883 } 884 885 /* load the font header (`head' table) if this isn't an Apple */ 886 /* sbit font file */ 887 if ( !is_apple_sbit || has_sbix ) 888 { 889 LOAD_( head ); 890 if ( error ) 891 goto Exit; 892 } 893 894 /* Ignore outlines for CBLC/CBDT fonts. */ 895 if ( has_CBLC || has_CBDT ) 896 has_outline = FALSE; 897 898 /* OpenType 1.8.2 introduced limits to this value; */ 899 /* however, they make sense for older SFNT fonts also */ 900 if ( face->header.Units_Per_EM < 16 || 901 face->header.Units_Per_EM > 16384 ) 902 { 903 error = FT_THROW( Invalid_Table ); 904 905 goto Exit; 906 } 907 908 /* the following tables are often not present in embedded TrueType */ 909 /* fonts within PDF documents, so don't check for them. */ 910 LOAD_( maxp ); 911 LOAD_( cmap ); 912 913 /* the following tables are optional in PCL fonts -- */ 914 /* don't check for errors */ 915 LOAD_( name ); 916 LOAD_( post ); 917 918 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 919 psnames_error = error; 920 #endif 921 922 /* do not load the metrics headers and tables if this is an Apple */ 923 /* sbit font file */ 924 if ( !is_apple_sbit ) 925 { 926 /* load the `hhea' and `hmtx' tables */ 927 LOADM_( hhea, 0 ); 928 if ( !error ) 929 { 930 LOADM_( hmtx, 0 ); 931 if ( FT_ERR_EQ( error, Table_Missing ) ) 932 { 933 error = FT_THROW( Hmtx_Table_Missing ); 934 935 #ifdef FT_CONFIG_OPTION_INCREMENTAL 936 /* If this is an incrementally loaded font and there are */ 937 /* overriding metrics, tolerate a missing `hmtx' table. */ 938 if ( face->root.internal->incremental_interface && 939 face->root.internal->incremental_interface->funcs-> 940 get_glyph_metrics ) 941 { 942 face->horizontal.number_Of_HMetrics = 0; 943 error = FT_Err_Ok; 944 } 945 #endif 946 } 947 } 948 else if ( FT_ERR_EQ( error, Table_Missing ) ) 949 { 950 /* No `hhea' table necessary for SFNT Mac fonts. */ 951 if ( face->format_tag == TTAG_true ) 952 { 953 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 954 955 has_outline = 0; 956 error = FT_Err_Ok; 957 } 958 else 959 { 960 error = FT_THROW( Horiz_Header_Missing ); 961 962 #ifdef FT_CONFIG_OPTION_INCREMENTAL 963 /* If this is an incrementally loaded font and there are */ 964 /* overriding metrics, tolerate a missing `hhea' table. */ 965 if ( face->root.internal->incremental_interface && 966 face->root.internal->incremental_interface->funcs-> 967 get_glyph_metrics ) 968 { 969 face->horizontal.number_Of_HMetrics = 0; 970 error = FT_Err_Ok; 971 } 972 #endif 973 974 } 975 } 976 977 if ( error ) 978 goto Exit; 979 980 /* try to load the `vhea' and `vmtx' tables */ 981 LOADM_( hhea, 1 ); 982 if ( !error ) 983 { 984 LOADM_( hmtx, 1 ); 985 if ( !error ) 986 face->vertical_info = 1; 987 } 988 989 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 990 goto Exit; 991 992 LOAD_( os2 ); 993 if ( error ) 994 { 995 /* we treat the table as missing if there are any errors */ 996 face->os2.version = 0xFFFFU; 997 } 998 } 999 1000 /* the optional tables */ 1001 1002 /* embedded bitmap support */ 1003 /* TODO: Replace this clumsy check for all possible sbit tables */ 1004 /* with something better (for example, by passing a parameter */ 1005 /* to suppress 'sbix' loading). */ 1006 if ( sfnt->load_eblc && 1007 ( has_CBLC || has_EBLC || has_bloc || has_sbix ) ) 1008 LOAD_( eblc ); 1009 1010 /* colored glyph support */ 1011 if ( sfnt->load_cpal ) 1012 { 1013 LOAD_( cpal ); 1014 LOAD_( colr ); 1015 } 1016 1017 /* OpenType-SVG glyph support */ 1018 if ( sfnt->load_svg ) 1019 LOAD_( svg ); 1020 1021 /* consider the pclt, kerning, and gasp tables as optional */ 1022 LOAD_( pclt ); 1023 LOAD_( gasp ); 1024 LOAD_( kern ); 1025 1026 face->root.num_glyphs = face->max_profile.numGlyphs; 1027 1028 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 1029 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 1030 /* `slope', a term used by Microsoft's Windows Presentation */ 1031 /* Foundation (WPF). This flag has been introduced in version */ 1032 /* 1.5 of the OpenType specification (May 2008). */ 1033 1034 face->root.family_name = NULL; 1035 face->root.style_name = NULL; 1036 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 1037 { 1038 if ( !ignore_typographic_family ) 1039 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1040 if ( !face->root.family_name ) 1041 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1042 1043 if ( !ignore_typographic_subfamily ) 1044 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1045 if ( !face->root.style_name ) 1046 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1047 } 1048 else 1049 { 1050 GET_NAME( WWS_FAMILY, &face->root.family_name ); 1051 if ( !face->root.family_name && !ignore_typographic_family ) 1052 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1053 if ( !face->root.family_name ) 1054 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1055 1056 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 1057 if ( !face->root.style_name && !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 1063 /* now set up root fields */ 1064 { 1065 FT_Face root = &face->root; 1066 FT_Long flags = root->face_flags; 1067 1068 1069 /********************************************************************** 1070 * 1071 * Compute face flags. 1072 */ 1073 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || 1074 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || 1075 face->colr || 1076 face->svg ) 1077 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ 1078 1079 if ( has_outline == TRUE ) 1080 { 1081 /* by default (and for backward compatibility) we handle */ 1082 /* fonts with an 'sbix' table as bitmap-only */ 1083 if ( has_sbix ) 1084 flags |= FT_FACE_FLAG_SBIX; /* with 'sbix' bitmaps */ 1085 else 1086 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 1087 } 1088 1089 /* The sfnt driver only supports bitmap fonts natively, thus we */ 1090 /* don't set FT_FACE_FLAG_HINTER. */ 1091 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 1092 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 1093 1094 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1095 if ( !psnames_error && 1096 face->postscript.FormatType != 0x00030000L ) 1097 flags |= FT_FACE_FLAG_GLYPH_NAMES; 1098 #endif 1099 1100 /* fixed width font? */ 1101 if ( face->postscript.isFixedPitch ) 1102 flags |= FT_FACE_FLAG_FIXED_WIDTH; 1103 1104 /* vertical information? */ 1105 if ( face->vertical_info ) 1106 flags |= FT_FACE_FLAG_VERTICAL; 1107 1108 /* kerning available ? */ 1109 if ( TT_FACE_HAS_KERNING( face ) ) 1110 flags |= FT_FACE_FLAG_KERNING; 1111 1112 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1113 /* Don't bother to load the tables unless somebody asks for them. */ 1114 /* No need to do work which will (probably) not be used. */ 1115 if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) 1116 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1117 #endif 1118 1119 root->face_flags = flags; 1120 1121 /********************************************************************** 1122 * 1123 * Compute style flags. 1124 */ 1125 1126 flags = 0; 1127 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 1128 { 1129 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 1130 /* indicates an oblique font face. This flag has been */ 1131 /* introduced in version 1.5 of the OpenType specification. */ 1132 1133 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 1134 flags |= FT_STYLE_FLAG_ITALIC; 1135 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 1136 flags |= FT_STYLE_FLAG_ITALIC; 1137 1138 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 1139 flags |= FT_STYLE_FLAG_BOLD; 1140 } 1141 else 1142 { 1143 /* this is an old Mac font, use the header field */ 1144 1145 if ( face->header.Mac_Style & 1 ) 1146 flags |= FT_STYLE_FLAG_BOLD; 1147 1148 if ( face->header.Mac_Style & 2 ) 1149 flags |= FT_STYLE_FLAG_ITALIC; 1150 } 1151 1152 root->style_flags |= flags; 1153 1154 /********************************************************************** 1155 * 1156 * Polish the charmaps. 1157 * 1158 * Try to set the charmap encoding according to the platform & 1159 * encoding ID of each charmap. Emulate Unicode charmap if one 1160 * is missing. 1161 */ 1162 1163 tt_face_build_cmaps( face ); /* ignore errors */ 1164 1165 1166 /* set the encoding fields */ 1167 { 1168 FT_Int m; 1169 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1170 FT_Bool has_unicode = FALSE; 1171 #endif 1172 1173 1174 for ( m = 0; m < root->num_charmaps; m++ ) 1175 { 1176 FT_CharMap charmap = root->charmaps[m]; 1177 1178 1179 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 1180 charmap->encoding_id ); 1181 1182 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1183 1184 if ( charmap->encoding == FT_ENCODING_UNICODE || 1185 charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ 1186 has_unicode = TRUE; 1187 } 1188 1189 /* synthesize Unicode charmap if one is missing */ 1190 if ( !has_unicode && 1191 root->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) 1192 { 1193 FT_CharMapRec cmaprec; 1194 1195 1196 cmaprec.face = root; 1197 cmaprec.platform_id = TT_PLATFORM_MICROSOFT; 1198 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; 1199 cmaprec.encoding = FT_ENCODING_UNICODE; 1200 1201 1202 error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, 1203 NULL, &cmaprec, NULL ); 1204 if ( error && 1205 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) && 1206 FT_ERR_NEQ( error, Unimplemented_Feature ) ) 1207 goto Exit; 1208 error = FT_Err_Ok; 1209 1210 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 1211 1212 } 1213 } 1214 1215 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1216 1217 /* 1218 * Now allocate the root array of FT_Bitmap_Size records and 1219 * populate them. Unfortunately, it isn't possible to indicate bit 1220 * depths in the FT_Bitmap_Size record. This is a design error. 1221 */ 1222 { 1223 FT_UInt count; 1224 1225 1226 count = face->sbit_num_strikes; 1227 1228 if ( count > 0 ) 1229 { 1230 FT_Memory memory = face->root.stream->memory; 1231 FT_UShort em_size = face->header.Units_Per_EM; 1232 FT_Short avgwidth = face->os2.xAvgCharWidth; 1233 FT_Size_Metrics metrics; 1234 1235 FT_UInt* sbit_strike_map = NULL; 1236 FT_UInt strike_idx, bsize_idx; 1237 1238 1239 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 1240 { 1241 avgwidth = 1; 1242 em_size = 1; 1243 } 1244 1245 /* to avoid invalid strike data in the `available_sizes' field */ 1246 /* of `FT_Face', we map `available_sizes' indices to strike */ 1247 /* indices */ 1248 if ( FT_NEW_ARRAY( root->available_sizes, count ) || 1249 FT_QNEW_ARRAY( sbit_strike_map, count ) ) 1250 goto Exit; 1251 1252 bsize_idx = 0; 1253 for ( strike_idx = 0; strike_idx < count; strike_idx++ ) 1254 { 1255 FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx; 1256 1257 1258 error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); 1259 if ( error ) 1260 continue; 1261 1262 bsize->height = (FT_Short)( metrics.height >> 6 ); 1263 bsize->width = (FT_Short)( 1264 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 1265 1266 bsize->x_ppem = metrics.x_ppem << 6; 1267 bsize->y_ppem = metrics.y_ppem << 6; 1268 1269 /* assume 72dpi */ 1270 bsize->size = metrics.y_ppem << 6; 1271 1272 /* only use strikes with valid PPEM values */ 1273 if ( bsize->x_ppem && bsize->y_ppem ) 1274 sbit_strike_map[bsize_idx++] = strike_idx; 1275 } 1276 1277 /* reduce array size to the actually used elements */ 1278 FT_MEM_QRENEW_ARRAY( sbit_strike_map, count, bsize_idx ); 1279 1280 /* from now on, all strike indices are mapped */ 1281 /* using `sbit_strike_map' */ 1282 if ( bsize_idx ) 1283 { 1284 face->sbit_strike_map = sbit_strike_map; 1285 1286 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 1287 root->num_fixed_sizes = (FT_Int)bsize_idx; 1288 } 1289 } 1290 } 1291 1292 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1293 1294 /* a font with no bitmaps and no outlines is scalable; */ 1295 /* it has only empty glyphs then */ 1296 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 1297 root->face_flags |= FT_FACE_FLAG_SCALABLE; 1298 1299 1300 /********************************************************************** 1301 * 1302 * Set up metrics. 1303 */ 1304 if ( FT_IS_SCALABLE( root ) || 1305 FT_HAS_SBIX( root ) ) 1306 { 1307 /* XXX What about if outline header is missing */ 1308 /* (e.g. sfnt wrapped bitmap)? */ 1309 root->bbox.xMin = face->header.xMin; 1310 root->bbox.yMin = face->header.yMin; 1311 root->bbox.xMax = face->header.xMax; 1312 root->bbox.yMax = face->header.yMax; 1313 root->units_per_EM = face->header.Units_Per_EM; 1314 1315 1316 /* 1317 * Computing the ascender/descender/height is tricky. 1318 * 1319 * The OpenType specification v1.8.3 says: 1320 * 1321 * [OS/2's] sTypoAscender, sTypoDescender and sTypoLineGap fields 1322 * are intended to allow applications to lay out documents in a 1323 * typographically-correct and portable fashion. 1324 * 1325 * This is somewhat at odds with the decades of backwards 1326 * compatibility, operating systems and applications doing whatever 1327 * they want, not to mention broken fonts. 1328 * 1329 * Not all fonts have an OS/2 table; in this case, we take the values 1330 * in the horizontal header, although there is nothing stopping the 1331 * values from being unreliable. Even with a OS/2 table, certain fonts 1332 * set the sTypoAscender, sTypoDescender and sTypoLineGap fields to 0 1333 * and instead correctly set usWinAscent and usWinDescent. 1334 * 1335 * As an example, Arial Narrow is shipped as four files ARIALN.TTF, 1336 * ARIALNI.TTF, ARIALNB.TTF and ARIALNBI.TTF. Strangely, all fonts have 1337 * the same values in their sTypo* fields, except ARIALNB.ttf which 1338 * sets them to 0. All of them have different usWinAscent/Descent 1339 * values. The OS/2 table therefore cannot be trusted for computing the 1340 * text height reliably. 1341 * 1342 * As a compromise, do the following: 1343 * 1344 * 1. If the OS/2 table exists and the fsSelection bit 7 is set 1345 * (USE_TYPO_METRICS), trust the font and use the sTypo* metrics. 1346 * 2. Otherwise, use the `hhea' table's metrics. 1347 * 3. If they are zero and the OS/2 table exists, 1348 * 1. use the OS/2 table's sTypo* metrics if they are non-zero. 1349 * 2. Otherwise, use the OS/2 table's usWin* metrics. 1350 */ 1351 1352 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 128 ) 1353 { 1354 root->ascender = face->os2.sTypoAscender; 1355 root->descender = face->os2.sTypoDescender; 1356 root->height = root->ascender - root->descender + 1357 face->os2.sTypoLineGap; 1358 } 1359 else 1360 { 1361 root->ascender = face->horizontal.Ascender; 1362 root->descender = face->horizontal.Descender; 1363 root->height = root->ascender - root->descender + 1364 face->horizontal.Line_Gap; 1365 1366 if ( !( root->ascender || root->descender ) ) 1367 { 1368 if ( face->os2.version != 0xFFFFU ) 1369 { 1370 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) 1371 { 1372 root->ascender = face->os2.sTypoAscender; 1373 root->descender = face->os2.sTypoDescender; 1374 root->height = root->ascender - root->descender + 1375 face->os2.sTypoLineGap; 1376 } 1377 else 1378 { 1379 root->ascender = (FT_Short)face->os2.usWinAscent; 1380 root->descender = -(FT_Short)face->os2.usWinDescent; 1381 root->height = root->ascender - root->descender; 1382 } 1383 } 1384 } 1385 } 1386 1387 root->max_advance_width = 1388 (FT_Short)face->horizontal.advance_Width_Max; 1389 root->max_advance_height = 1390 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max 1391 : root->height ); 1392 1393 /* See https://www.microsoft.com/typography/otspec/post.htm -- */ 1394 /* Adjust underline position from top edge to centre of */ 1395 /* stroke to convert TrueType meaning to FreeType meaning. */ 1396 root->underline_position = face->postscript.underlinePosition - 1397 face->postscript.underlineThickness / 2; 1398 root->underline_thickness = face->postscript.underlineThickness; 1399 } 1400 1401 } 1402 1403 Exit: 1404 FT_TRACE2(( "sfnt_load_face: done\n" )); 1405 1406 return error; 1407 } 1408 1409 1410 #undef LOAD_ 1411 #undef LOADM_ 1412 #undef GET_NAME 1413 1414 1415 FT_LOCAL_DEF( void ) sfnt_done_face(TT_Face face)1416 sfnt_done_face( TT_Face face ) 1417 { 1418 FT_Memory memory; 1419 SFNT_Service sfnt; 1420 1421 1422 if ( !face ) 1423 return; 1424 1425 memory = face->root.memory; 1426 sfnt = (SFNT_Service)face->sfnt; 1427 1428 if ( sfnt ) 1429 { 1430 /* destroy the postscript names table if it is loaded */ 1431 if ( sfnt->free_psnames ) 1432 sfnt->free_psnames( face ); 1433 1434 /* destroy the embedded bitmaps table if it is loaded */ 1435 if ( sfnt->free_eblc ) 1436 sfnt->free_eblc( face ); 1437 1438 /* destroy color table data if it is loaded */ 1439 if ( sfnt->free_cpal ) 1440 { 1441 sfnt->free_cpal( face ); 1442 sfnt->free_colr( face ); 1443 } 1444 1445 #ifdef FT_CONFIG_OPTION_SVG 1446 /* free SVG data */ 1447 if ( sfnt->free_svg ) 1448 sfnt->free_svg( face ); 1449 #endif 1450 } 1451 1452 #ifdef TT_CONFIG_OPTION_BDF 1453 /* freeing the embedded BDF properties */ 1454 tt_face_free_bdf_props( face ); 1455 #endif 1456 1457 /* freeing the kerning table */ 1458 tt_face_done_kern( face ); 1459 1460 /* freeing the collection table */ 1461 FT_FREE( face->ttc_header.offsets ); 1462 face->ttc_header.count = 0; 1463 1464 /* freeing table directory */ 1465 FT_FREE( face->dir_tables ); 1466 face->num_tables = 0; 1467 1468 { 1469 FT_Stream stream = FT_FACE_STREAM( face ); 1470 1471 1472 /* simply release the 'cmap' table frame */ 1473 FT_FRAME_RELEASE( face->cmap_table ); 1474 face->cmap_size = 0; 1475 } 1476 1477 face->horz_metrics_size = 0; 1478 face->vert_metrics_size = 0; 1479 1480 /* freeing vertical metrics, if any */ 1481 if ( face->vertical_info ) 1482 { 1483 FT_FREE( face->vertical.long_metrics ); 1484 FT_FREE( face->vertical.short_metrics ); 1485 face->vertical_info = 0; 1486 } 1487 1488 /* freeing the gasp table */ 1489 FT_FREE( face->gasp.gaspRanges ); 1490 face->gasp.numRanges = 0; 1491 1492 /* freeing the name table */ 1493 if ( sfnt ) 1494 sfnt->free_name( face ); 1495 1496 /* freeing family and style name */ 1497 FT_FREE( face->root.family_name ); 1498 FT_FREE( face->root.style_name ); 1499 1500 /* freeing sbit size table */ 1501 FT_FREE( face->root.available_sizes ); 1502 FT_FREE( face->sbit_strike_map ); 1503 face->root.num_fixed_sizes = 0; 1504 1505 FT_FREE( face->postscript_name ); 1506 1507 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1508 FT_FREE( face->var_postscript_prefix ); 1509 #endif 1510 1511 /* freeing glyph color palette data */ 1512 FT_FREE( face->palette_data.palette_name_ids ); 1513 FT_FREE( face->palette_data.palette_flags ); 1514 FT_FREE( face->palette_data.palette_entry_name_ids ); 1515 FT_FREE( face->palette ); 1516 1517 face->sfnt = NULL; 1518 } 1519 1520 1521 /* END */ 1522