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