1 /***************************************************************************/ 2 /* */ 3 /* sfobjs.c */ 4 /* */ 5 /* SFNT object management (base). */ 6 /* */ 7 /* Copyright 1996-2008, 2010-2013 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 <ft2build.h> 20 #include "sfobjs.h" 21 #include "ttload.h" 22 #include "ttcmap.h" 23 #include "ttkern.h" 24 #include FT_INTERNAL_SFNT_H 25 #include FT_INTERNAL_DEBUG_H 26 #include FT_TRUETYPE_IDS_H 27 #include FT_TRUETYPE_TAGS_H 28 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 29 #include FT_SFNT_NAMES_H 30 #include "sferrors.h" 31 32 #ifdef TT_CONFIG_OPTION_BDF 33 #include "ttbdf.h" 34 #endif 35 36 37 /*************************************************************************/ 38 /* */ 39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 41 /* messages during execution. */ 42 /* */ 43 #undef FT_COMPONENT 44 #define FT_COMPONENT trace_sfobjs 45 46 47 48 /* convert a UTF-16 name entry to ASCII */ 49 static FT_String* 50 tt_name_entry_ascii_from_utf16( TT_NameEntry entry, 51 FT_Memory memory ) 52 { 53 FT_String* string = NULL; 54 FT_UInt len, code, n; 55 FT_Byte* read = (FT_Byte*)entry->string; 56 FT_Error error; 57 58 59 len = (FT_UInt)entry->stringLength / 2; 60 61 if ( FT_NEW_ARRAY( string, len + 1 ) ) 62 return NULL; 63 64 for ( n = 0; n < len; n++ ) 65 { 66 code = FT_NEXT_USHORT( read ); 67 68 if ( code == 0 ) 69 break; 70 71 if ( code < 32 || code > 127 ) 72 code = '?'; 73 74 string[n] = (char)code; 75 } 76 77 string[n] = 0; 78 79 return string; 80 } 81 82 83 /* convert an Apple Roman or symbol name entry to ASCII */ 84 static FT_String* 85 tt_name_entry_ascii_from_other( TT_NameEntry entry, 86 FT_Memory memory ) 87 { 88 FT_String* string = NULL; 89 FT_UInt len, code, n; 90 FT_Byte* read = (FT_Byte*)entry->string; 91 FT_Error error; 92 93 94 len = (FT_UInt)entry->stringLength; 95 96 if ( FT_NEW_ARRAY( string, len + 1 ) ) 97 return NULL; 98 99 for ( n = 0; n < len; n++ ) 100 { 101 code = *read++; 102 103 if ( code == 0 ) 104 break; 105 106 if ( code < 32 || code > 127 ) 107 code = '?'; 108 109 string[n] = (char)code; 110 } 111 112 string[n] = 0; 113 114 return string; 115 } 116 117 118 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, 119 FT_Memory memory ); 120 121 122 /*************************************************************************/ 123 /* */ 124 /* <Function> */ 125 /* tt_face_get_name */ 126 /* */ 127 /* <Description> */ 128 /* Returns a given ENGLISH name record in ASCII. */ 129 /* */ 130 /* <Input> */ 131 /* face :: A handle to the source face object. */ 132 /* */ 133 /* nameid :: The name id of the name record to return. */ 134 /* */ 135 /* <InOut> */ 136 /* name :: The address of a string pointer. NULL if no name is */ 137 /* present. */ 138 /* */ 139 /* <Return> */ 140 /* FreeType error code. 0 means success. */ 141 /* */ 142 static FT_Error 143 tt_face_get_name( TT_Face face, 144 FT_UShort nameid, 145 FT_String** name ) 146 { 147 FT_Memory memory = face->root.memory; 148 FT_Error error = FT_Err_Ok; 149 FT_String* result = NULL; 150 FT_UShort n; 151 TT_NameEntryRec* rec; 152 FT_Int found_apple = -1; 153 FT_Int found_apple_roman = -1; 154 FT_Int found_apple_english = -1; 155 FT_Int found_win = -1; 156 FT_Int found_unicode = -1; 157 158 FT_Bool is_english = 0; 159 160 TT_NameEntry_ConvertFunc convert; 161 162 163 FT_ASSERT( name ); 164 165 rec = face->name_table.names; 166 for ( n = 0; n < face->num_names; n++, rec++ ) 167 { 168 /* According to the OpenType 1.3 specification, only Microsoft or */ 169 /* Apple platform IDs might be used in the `name' table. The */ 170 /* `Unicode' platform is reserved for the `cmap' table, and the */ 171 /* `ISO' one is deprecated. */ 172 /* */ 173 /* However, the Apple TrueType specification doesn't say the same */ 174 /* thing and goes to suggest that all Unicode `name' table entries */ 175 /* should be coded in UTF-16 (in big-endian format I suppose). */ 176 /* */ 177 if ( rec->nameID == nameid && rec->stringLength > 0 ) 178 { 179 switch ( rec->platformID ) 180 { 181 case TT_PLATFORM_APPLE_UNICODE: 182 case TT_PLATFORM_ISO: 183 /* there is `languageID' to check there. We should use this */ 184 /* field only as a last solution when nothing else is */ 185 /* available. */ 186 /* */ 187 found_unicode = n; 188 break; 189 190 case TT_PLATFORM_MACINTOSH: 191 /* This is a bit special because some fonts will use either */ 192 /* an English language id, or a Roman encoding id, to indicate */ 193 /* the English version of its font name. */ 194 /* */ 195 if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) 196 found_apple_english = n; 197 else if ( rec->encodingID == TT_MAC_ID_ROMAN ) 198 found_apple_roman = n; 199 break; 200 201 case TT_PLATFORM_MICROSOFT: 202 /* we only take a non-English name when there is nothing */ 203 /* else available in the font */ 204 /* */ 205 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) 206 { 207 switch ( rec->encodingID ) 208 { 209 case TT_MS_ID_SYMBOL_CS: 210 case TT_MS_ID_UNICODE_CS: 211 case TT_MS_ID_UCS_4: 212 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); 213 found_win = n; 214 break; 215 216 default: 217 ; 218 } 219 } 220 break; 221 222 default: 223 ; 224 } 225 } 226 } 227 228 found_apple = found_apple_roman; 229 if ( found_apple_english >= 0 ) 230 found_apple = found_apple_english; 231 232 /* some fonts contain invalid Unicode or Macintosh formatted entries; */ 233 /* we will thus favor names encoded in Windows formats if available */ 234 /* (provided it is an English name) */ 235 /* */ 236 convert = NULL; 237 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) 238 { 239 rec = face->name_table.names + found_win; 240 switch ( rec->encodingID ) 241 { 242 /* all Unicode strings are encoded using UTF-16BE */ 243 case TT_MS_ID_UNICODE_CS: 244 case TT_MS_ID_SYMBOL_CS: 245 convert = tt_name_entry_ascii_from_utf16; 246 break; 247 248 case TT_MS_ID_UCS_4: 249 /* Apparently, if this value is found in a name table entry, it is */ 250 /* documented as `full Unicode repertoire'. Experience with the */ 251 /* MsGothic font shipped with Windows Vista shows that this really */ 252 /* means UTF-16 encoded names (UCS-4 values are only used within */ 253 /* charmaps). */ 254 convert = tt_name_entry_ascii_from_utf16; 255 break; 256 257 default: 258 ; 259 } 260 } 261 else if ( found_apple >= 0 ) 262 { 263 rec = face->name_table.names + found_apple; 264 convert = tt_name_entry_ascii_from_other; 265 } 266 else if ( found_unicode >= 0 ) 267 { 268 rec = face->name_table.names + found_unicode; 269 convert = tt_name_entry_ascii_from_utf16; 270 } 271 272 if ( rec && convert ) 273 { 274 if ( rec->string == NULL ) 275 { 276 FT_Stream stream = face->name_table.stream; 277 278 279 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || 280 FT_STREAM_SEEK( rec->stringOffset ) || 281 FT_STREAM_READ( rec->string, rec->stringLength ) ) 282 { 283 FT_FREE( rec->string ); 284 rec->stringLength = 0; 285 result = NULL; 286 goto Exit; 287 } 288 } 289 290 result = convert( rec, memory ); 291 } 292 293 Exit: 294 *name = result; 295 return error; 296 } 297 298 299 static FT_Encoding 300 sfnt_find_encoding( int platform_id, 301 int encoding_id ) 302 { 303 typedef struct TEncoding_ 304 { 305 int platform_id; 306 int encoding_id; 307 FT_Encoding encoding; 308 309 } TEncoding; 310 311 static 312 const TEncoding tt_encodings[] = 313 { 314 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, 315 316 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, 317 318 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, 319 320 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, 321 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, 322 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, 323 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, 324 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, 325 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, 326 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, 327 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } 328 }; 329 330 const TEncoding *cur, *limit; 331 332 333 cur = tt_encodings; 334 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); 335 336 for ( ; cur < limit; cur++ ) 337 { 338 if ( cur->platform_id == platform_id ) 339 { 340 if ( cur->encoding_id == encoding_id || 341 cur->encoding_id == -1 ) 342 return cur->encoding; 343 } 344 } 345 346 return FT_ENCODING_NONE; 347 } 348 349 350 /* Fill in face->ttc_header. If the font is not a TTC, it is */ 351 /* synthesized into a TTC with one offset table. */ 352 static FT_Error 353 sfnt_open_font( FT_Stream stream, 354 TT_Face face ) 355 { 356 FT_Memory memory = stream->memory; 357 FT_Error error; 358 FT_ULong tag, offset; 359 360 static const FT_Frame_Field ttc_header_fields[] = 361 { 362 #undef FT_STRUCTURE 363 #define FT_STRUCTURE TTC_HeaderRec 364 365 FT_FRAME_START( 8 ), 366 FT_FRAME_LONG( version ), 367 FT_FRAME_LONG( count ), /* this is ULong in the specs */ 368 FT_FRAME_END 369 }; 370 371 372 face->ttc_header.tag = 0; 373 face->ttc_header.version = 0; 374 face->ttc_header.count = 0; 375 376 offset = FT_STREAM_POS(); 377 378 if ( FT_READ_ULONG( tag ) ) 379 return error; 380 381 if ( tag != 0x00010000UL && 382 tag != TTAG_ttcf && 383 tag != TTAG_OTTO && 384 tag != TTAG_true && 385 tag != TTAG_typ1 && 386 tag != 0x00020000UL ) 387 { 388 FT_TRACE2(( " not a font using the SFNT container format\n" )); 389 return FT_THROW( Unknown_File_Format ); 390 } 391 392 face->ttc_header.tag = TTAG_ttcf; 393 394 if ( tag == TTAG_ttcf ) 395 { 396 FT_Int n; 397 398 399 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); 400 401 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) 402 return error; 403 404 if ( face->ttc_header.count == 0 ) 405 return FT_THROW( Invalid_Table ); 406 407 /* a rough size estimate: let's conservatively assume that there */ 408 /* is just a single table info in each subfont header (12 + 16*1 = */ 409 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ 410 /* size of the TTC header plus `28*count' bytes for all subfont */ 411 /* headers */ 412 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) 413 return FT_THROW( Array_Too_Large ); 414 415 /* now read the offsets of each font in the file */ 416 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) 417 return error; 418 419 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) 420 return error; 421 422 for ( n = 0; n < face->ttc_header.count; n++ ) 423 face->ttc_header.offsets[n] = FT_GET_ULONG(); 424 425 FT_FRAME_EXIT(); 426 } 427 else 428 { 429 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); 430 431 face->ttc_header.version = 1 << 16; 432 face->ttc_header.count = 1; 433 434 if ( FT_NEW( face->ttc_header.offsets ) ) 435 return error; 436 437 face->ttc_header.offsets[0] = offset; 438 } 439 440 return error; 441 } 442 443 444 FT_LOCAL_DEF( FT_Error ) 445 sfnt_init_face( FT_Stream stream, 446 TT_Face face, 447 FT_Int face_index, 448 FT_Int num_params, 449 FT_Parameter* params ) 450 { 451 FT_Error error; 452 FT_Library library = face->root.driver->root.library; 453 SFNT_Service sfnt; 454 455 456 /* for now, parameters are unused */ 457 FT_UNUSED( num_params ); 458 FT_UNUSED( params ); 459 460 461 sfnt = (SFNT_Service)face->sfnt; 462 if ( !sfnt ) 463 { 464 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 465 if ( !sfnt ) 466 { 467 FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); 468 return FT_THROW( Missing_Module ); 469 } 470 471 face->sfnt = sfnt; 472 face->goto_table = sfnt->goto_table; 473 } 474 475 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); 476 477 FT_TRACE2(( "SFNT driver\n" )); 478 479 error = sfnt_open_font( stream, face ); 480 if ( error ) 481 return error; 482 483 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); 484 485 if ( face_index < 0 ) 486 face_index = 0; 487 488 if ( face_index >= face->ttc_header.count ) 489 return FT_THROW( Invalid_Argument ); 490 491 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) 492 return error; 493 494 /* check that we have a valid TrueType file */ 495 error = sfnt->load_font_dir( face, stream ); 496 if ( error ) 497 return error; 498 499 face->root.num_faces = face->ttc_header.count; 500 face->root.face_index = face_index; 501 502 return error; 503 } 504 505 506 #define LOAD_( x ) \ 507 do { \ 508 FT_TRACE2(( "`" #x "' " )); \ 509 FT_TRACE3(( "-->\n" )); \ 510 \ 511 error = sfnt->load_ ## x( face, stream ); \ 512 \ 513 FT_TRACE2(( "%s\n", ( !error ) \ 514 ? "loaded" \ 515 : FT_ERR_EQ( error, Table_Missing ) \ 516 ? "missing" \ 517 : "failed to load" )); \ 518 FT_TRACE3(( "\n" )); \ 519 } while ( 0 ) 520 521 #define LOADM_( x, vertical ) \ 522 do { \ 523 FT_TRACE2(( "`%s" #x "' ", \ 524 vertical ? "vertical " : "" )); \ 525 FT_TRACE3(( "-->\n" )); \ 526 \ 527 error = sfnt->load_ ## x( face, stream, vertical ); \ 528 \ 529 FT_TRACE2(( "%s\n", ( !error ) \ 530 ? "loaded" \ 531 : FT_ERR_EQ( error, Table_Missing ) \ 532 ? "missing" \ 533 : "failed to load" )); \ 534 FT_TRACE3(( "\n" )); \ 535 } while ( 0 ) 536 537 #define GET_NAME( id, field ) \ 538 do { \ 539 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ 540 if ( error ) \ 541 goto Exit; \ 542 } while ( 0 ) 543 544 545 FT_LOCAL_DEF( FT_Error ) 546 sfnt_load_face( FT_Stream stream, 547 TT_Face face, 548 FT_Int face_index, 549 FT_Int num_params, 550 FT_Parameter* params ) 551 { 552 FT_Error error; 553 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 554 FT_Error psnames_error; 555 #endif 556 FT_Bool has_outline; 557 FT_Bool is_apple_sbit; 558 FT_Bool ignore_preferred_family = FALSE; 559 FT_Bool ignore_preferred_subfamily = FALSE; 560 561 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 562 563 FT_UNUSED( face_index ); 564 565 566 /* Check parameters */ 567 568 { 569 FT_Int i; 570 571 572 for ( i = 0; i < num_params; i++ ) 573 { 574 if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) 575 ignore_preferred_family = TRUE; 576 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) 577 ignore_preferred_subfamily = TRUE; 578 } 579 } 580 581 /* Load tables */ 582 583 /* We now support two SFNT-based bitmapped font formats. They */ 584 /* are recognized easily as they do not include a `glyf' */ 585 /* table. */ 586 /* */ 587 /* The first format comes from Apple, and uses a table named */ 588 /* `bhed' instead of `head' to store the font header (using */ 589 /* the same format). It also doesn't include horizontal and */ 590 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 591 /* missing). */ 592 /* */ 593 /* The other format comes from Microsoft, and is used with */ 594 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 595 /* it doesn't contain outlines. */ 596 /* */ 597 598 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); 599 600 /* do we have outlines in there? */ 601 #ifdef FT_CONFIG_OPTION_INCREMENTAL 602 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || 603 tt_face_lookup_table( face, TTAG_glyf ) != 0 || 604 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); 605 #else 606 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || 607 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); 608 #endif 609 610 is_apple_sbit = 0; 611 612 /* if this font doesn't contain outlines, we try to load */ 613 /* a `bhed' table */ 614 if ( !has_outline && sfnt->load_bhed ) 615 { 616 LOAD_( bhed ); 617 is_apple_sbit = FT_BOOL( !error ); 618 } 619 620 /* load the font header (`head' table) if this isn't an Apple */ 621 /* sbit font file */ 622 if ( !is_apple_sbit ) 623 { 624 LOAD_( head ); 625 if ( error ) 626 goto Exit; 627 } 628 629 if ( face->header.Units_Per_EM == 0 ) 630 { 631 error = FT_THROW( Invalid_Table ); 632 633 goto Exit; 634 } 635 636 /* the following tables are often not present in embedded TrueType */ 637 /* fonts within PDF documents, so don't check for them. */ 638 LOAD_( maxp ); 639 LOAD_( cmap ); 640 641 /* the following tables are optional in PCL fonts -- */ 642 /* don't check for errors */ 643 LOAD_( name ); 644 LOAD_( post ); 645 646 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 647 psnames_error = error; 648 #endif 649 650 /* do not load the metrics headers and tables if this is an Apple */ 651 /* sbit font file */ 652 if ( !is_apple_sbit ) 653 { 654 /* load the `hhea' and `hmtx' tables */ 655 LOADM_( hhea, 0 ); 656 if ( !error ) 657 { 658 LOADM_( hmtx, 0 ); 659 if ( FT_ERR_EQ( error, Table_Missing ) ) 660 { 661 error = FT_THROW( Hmtx_Table_Missing ); 662 663 #ifdef FT_CONFIG_OPTION_INCREMENTAL 664 /* If this is an incrementally loaded font and there are */ 665 /* overriding metrics, tolerate a missing `hmtx' table. */ 666 if ( face->root.internal->incremental_interface && 667 face->root.internal->incremental_interface->funcs-> 668 get_glyph_metrics ) 669 { 670 face->horizontal.number_Of_HMetrics = 0; 671 error = FT_Err_Ok; 672 } 673 #endif 674 } 675 } 676 else if ( FT_ERR_EQ( error, Table_Missing ) ) 677 { 678 /* No `hhea' table necessary for SFNT Mac fonts. */ 679 if ( face->format_tag == TTAG_true ) 680 { 681 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 682 683 has_outline = 0; 684 error = FT_Err_Ok; 685 } 686 else 687 { 688 error = FT_THROW( Horiz_Header_Missing ); 689 690 #ifdef FT_CONFIG_OPTION_INCREMENTAL 691 /* If this is an incrementally loaded font and there are */ 692 /* overriding metrics, tolerate a missing `hhea' table. */ 693 if ( face->root.internal->incremental_interface && 694 face->root.internal->incremental_interface->funcs-> 695 get_glyph_metrics ) 696 { 697 face->horizontal.number_Of_HMetrics = 0; 698 error = FT_Err_Ok; 699 } 700 #endif 701 702 } 703 } 704 705 if ( error ) 706 goto Exit; 707 708 /* try to load the `vhea' and `vmtx' tables */ 709 LOADM_( hhea, 1 ); 710 if ( !error ) 711 { 712 LOADM_( hmtx, 1 ); 713 if ( !error ) 714 face->vertical_info = 1; 715 } 716 717 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 718 goto Exit; 719 720 LOAD_( os2 ); 721 if ( error ) 722 { 723 /* we treat the table as missing if there are any errors */ 724 face->os2.version = 0xFFFFU; 725 } 726 } 727 728 /* the optional tables */ 729 730 /* embedded bitmap support */ 731 if ( sfnt->load_eblc ) 732 { 733 LOAD_( eblc ); 734 if ( error ) 735 { 736 /* a font which contains neither bitmaps nor outlines is */ 737 /* still valid (although rather useless in most cases); */ 738 /* however, you can find such stripped fonts in PDFs */ 739 if ( FT_ERR_EQ( error, Table_Missing ) ) 740 error = FT_Err_Ok; 741 else 742 goto Exit; 743 } 744 } 745 746 LOAD_( pclt ); 747 if ( error ) 748 { 749 if ( FT_ERR_NEQ( error, Table_Missing ) ) 750 goto Exit; 751 752 face->pclt.Version = 0; 753 } 754 755 /* consider the kerning and gasp tables as optional */ 756 LOAD_( gasp ); 757 LOAD_( kern ); 758 759 face->root.num_glyphs = face->max_profile.numGlyphs; 760 761 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 762 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 763 /* `slope', a term used by Microsoft's Windows Presentation */ 764 /* Foundation (WPF). This flag has been introduced in version */ 765 /* 1.5 of the OpenType specification (May 2008). */ 766 767 face->root.family_name = NULL; 768 face->root.style_name = NULL; 769 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 770 { 771 if ( !ignore_preferred_family ) 772 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); 773 if ( !face->root.family_name ) 774 GET_NAME( FONT_FAMILY, &face->root.family_name ); 775 776 if ( !ignore_preferred_subfamily ) 777 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); 778 if ( !face->root.style_name ) 779 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 780 } 781 else 782 { 783 GET_NAME( WWS_FAMILY, &face->root.family_name ); 784 if ( !face->root.family_name && !ignore_preferred_family ) 785 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); 786 if ( !face->root.family_name ) 787 GET_NAME( FONT_FAMILY, &face->root.family_name ); 788 789 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 790 if ( !face->root.style_name && !ignore_preferred_subfamily ) 791 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); 792 if ( !face->root.style_name ) 793 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 794 } 795 796 /* now set up root fields */ 797 { 798 FT_Face root = &face->root; 799 FT_Long flags = root->face_flags; 800 801 802 /*********************************************************************/ 803 /* */ 804 /* Compute face flags. */ 805 /* */ 806 if ( has_outline == TRUE ) 807 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 808 809 /* The sfnt driver only supports bitmap fonts natively, thus we */ 810 /* don't set FT_FACE_FLAG_HINTER. */ 811 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 812 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 813 814 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 815 if ( !psnames_error && 816 face->postscript.FormatType != 0x00030000L ) 817 flags |= FT_FACE_FLAG_GLYPH_NAMES; 818 #endif 819 820 /* fixed width font? */ 821 if ( face->postscript.isFixedPitch ) 822 flags |= FT_FACE_FLAG_FIXED_WIDTH; 823 824 /* vertical information? */ 825 if ( face->vertical_info ) 826 flags |= FT_FACE_FLAG_VERTICAL; 827 828 /* kerning available ? */ 829 if ( TT_FACE_HAS_KERNING( face ) ) 830 flags |= FT_FACE_FLAG_KERNING; 831 832 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 833 /* Don't bother to load the tables unless somebody asks for them. */ 834 /* No need to do work which will (probably) not be used. */ 835 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && 836 tt_face_lookup_table( face, TTAG_fvar ) != 0 && 837 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) 838 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 839 #endif 840 841 root->face_flags = flags; 842 843 /*********************************************************************/ 844 /* */ 845 /* Compute style flags. */ 846 /* */ 847 848 flags = 0; 849 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 850 { 851 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 852 /* indicates an oblique font face. This flag has been */ 853 /* introduced in version 1.5 of the OpenType specification. */ 854 855 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 856 flags |= FT_STYLE_FLAG_ITALIC; 857 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 858 flags |= FT_STYLE_FLAG_ITALIC; 859 860 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 861 flags |= FT_STYLE_FLAG_BOLD; 862 } 863 else 864 { 865 /* this is an old Mac font, use the header field */ 866 867 if ( face->header.Mac_Style & 1 ) 868 flags |= FT_STYLE_FLAG_BOLD; 869 870 if ( face->header.Mac_Style & 2 ) 871 flags |= FT_STYLE_FLAG_ITALIC; 872 } 873 874 root->style_flags = flags; 875 876 /*********************************************************************/ 877 /* */ 878 /* Polish the charmaps. */ 879 /* */ 880 /* Try to set the charmap encoding according to the platform & */ 881 /* encoding ID of each charmap. */ 882 /* */ 883 884 tt_face_build_cmaps( face ); /* ignore errors */ 885 886 887 /* set the encoding fields */ 888 { 889 FT_Int m; 890 891 892 for ( m = 0; m < root->num_charmaps; m++ ) 893 { 894 FT_CharMap charmap = root->charmaps[m]; 895 896 897 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 898 charmap->encoding_id ); 899 900 #if 0 901 if ( root->charmap == NULL && 902 charmap->encoding == FT_ENCODING_UNICODE ) 903 { 904 /* set 'root->charmap' to the first Unicode encoding we find */ 905 root->charmap = charmap; 906 } 907 #endif 908 } 909 } 910 911 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 912 913 /* 914 * Now allocate the root array of FT_Bitmap_Size records and 915 * populate them. Unfortunately, it isn't possible to indicate bit 916 * depths in the FT_Bitmap_Size record. This is a design error. 917 */ 918 { 919 FT_UInt i, count; 920 921 922 count = face->sbit_num_strikes; 923 924 if ( count > 0 ) 925 { 926 FT_Memory memory = face->root.stream->memory; 927 FT_UShort em_size = face->header.Units_Per_EM; 928 FT_Short avgwidth = face->os2.xAvgCharWidth; 929 FT_Size_Metrics metrics; 930 931 932 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 933 { 934 avgwidth = 0; 935 em_size = 1; 936 } 937 938 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) 939 goto Exit; 940 941 for ( i = 0; i < count; i++ ) 942 { 943 FT_Bitmap_Size* bsize = root->available_sizes + i; 944 945 946 error = sfnt->load_strike_metrics( face, i, &metrics ); 947 if ( error ) 948 goto Exit; 949 950 bsize->height = (FT_Short)( metrics.height >> 6 ); 951 bsize->width = (FT_Short)( 952 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 953 954 bsize->x_ppem = metrics.x_ppem << 6; 955 bsize->y_ppem = metrics.y_ppem << 6; 956 957 /* assume 72dpi */ 958 bsize->size = metrics.y_ppem << 6; 959 } 960 961 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 962 root->num_fixed_sizes = (FT_Int)count; 963 } 964 } 965 966 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 967 968 /* a font with no bitmaps and no outlines is scalable; */ 969 /* it has only empty glyphs then */ 970 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 971 root->face_flags |= FT_FACE_FLAG_SCALABLE; 972 973 974 /*********************************************************************/ 975 /* */ 976 /* Set up metrics. */ 977 /* */ 978 if ( FT_IS_SCALABLE( root ) ) 979 { 980 /* XXX What about if outline header is missing */ 981 /* (e.g. sfnt wrapped bitmap)? */ 982 root->bbox.xMin = face->header.xMin; 983 root->bbox.yMin = face->header.yMin; 984 root->bbox.xMax = face->header.xMax; 985 root->bbox.yMax = face->header.yMax; 986 root->units_per_EM = face->header.Units_Per_EM; 987 988 989 /* XXX: Computing the ascender/descender/height is very different */ 990 /* from what the specification tells you. Apparently, we */ 991 /* must be careful because */ 992 /* */ 993 /* - not all fonts have an OS/2 table; in this case, we take */ 994 /* the values in the horizontal header. However, these */ 995 /* values very often are not reliable. */ 996 /* */ 997 /* - otherwise, the correct typographic values are in the */ 998 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ 999 /* */ 1000 /* However, certain fonts have these fields set to 0. */ 1001 /* Rather, they have usWinAscent & usWinDescent correctly */ 1002 /* set (but with different values). */ 1003 /* */ 1004 /* As an example, Arial Narrow is implemented through four */ 1005 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ 1006 /* */ 1007 /* Strangely, all fonts have the same values in their */ 1008 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ 1009 /* */ 1010 /* On the other hand, they all have different */ 1011 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ 1012 /* table cannot be used to compute the text height reliably! */ 1013 /* */ 1014 1015 /* The ascender and descender are taken from the `hhea' table. */ 1016 /* If zero, they are taken from the `OS/2' table. */ 1017 1018 root->ascender = face->horizontal.Ascender; 1019 root->descender = face->horizontal.Descender; 1020 1021 root->height = (FT_Short)( root->ascender - root->descender + 1022 face->horizontal.Line_Gap ); 1023 1024 if ( !( root->ascender || root->descender ) ) 1025 { 1026 if ( face->os2.version != 0xFFFFU ) 1027 { 1028 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) 1029 { 1030 root->ascender = face->os2.sTypoAscender; 1031 root->descender = face->os2.sTypoDescender; 1032 1033 root->height = (FT_Short)( root->ascender - root->descender + 1034 face->os2.sTypoLineGap ); 1035 } 1036 else 1037 { 1038 root->ascender = (FT_Short)face->os2.usWinAscent; 1039 root->descender = -(FT_Short)face->os2.usWinDescent; 1040 1041 root->height = (FT_UShort)( root->ascender - root->descender ); 1042 } 1043 } 1044 } 1045 1046 root->max_advance_width = face->horizontal.advance_Width_Max; 1047 root->max_advance_height = (FT_Short)( face->vertical_info 1048 ? face->vertical.advance_Height_Max 1049 : root->height ); 1050 1051 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ 1052 /* Adjust underline position from top edge to centre of */ 1053 /* stroke to convert TrueType meaning to FreeType meaning. */ 1054 root->underline_position = face->postscript.underlinePosition - 1055 face->postscript.underlineThickness / 2; 1056 root->underline_thickness = face->postscript.underlineThickness; 1057 } 1058 1059 } 1060 1061 Exit: 1062 FT_TRACE2(( "sfnt_load_face: done\n" )); 1063 1064 return error; 1065 } 1066 1067 1068 #undef LOAD_ 1069 #undef LOADM_ 1070 #undef GET_NAME 1071 1072 1073 FT_LOCAL_DEF( void ) 1074 sfnt_done_face( TT_Face face ) 1075 { 1076 FT_Memory memory; 1077 SFNT_Service sfnt; 1078 1079 1080 if ( !face ) 1081 return; 1082 1083 memory = face->root.memory; 1084 sfnt = (SFNT_Service)face->sfnt; 1085 1086 if ( sfnt ) 1087 { 1088 /* destroy the postscript names table if it is loaded */ 1089 if ( sfnt->free_psnames ) 1090 sfnt->free_psnames( face ); 1091 1092 /* destroy the embedded bitmaps table if it is loaded */ 1093 if ( sfnt->free_eblc ) 1094 sfnt->free_eblc( face ); 1095 } 1096 1097 #ifdef TT_CONFIG_OPTION_BDF 1098 /* freeing the embedded BDF properties */ 1099 tt_face_free_bdf_props( face ); 1100 #endif 1101 1102 /* freeing the kerning table */ 1103 tt_face_done_kern( face ); 1104 1105 /* freeing the collection table */ 1106 FT_FREE( face->ttc_header.offsets ); 1107 face->ttc_header.count = 0; 1108 1109 /* freeing table directory */ 1110 FT_FREE( face->dir_tables ); 1111 face->num_tables = 0; 1112 1113 { 1114 FT_Stream stream = FT_FACE_STREAM( face ); 1115 1116 1117 /* simply release the 'cmap' table frame */ 1118 FT_FRAME_RELEASE( face->cmap_table ); 1119 face->cmap_size = 0; 1120 } 1121 1122 /* freeing the horizontal metrics */ 1123 { 1124 FT_Stream stream = FT_FACE_STREAM( face ); 1125 1126 1127 FT_FRAME_RELEASE( face->horz_metrics ); 1128 FT_FRAME_RELEASE( face->vert_metrics ); 1129 face->horz_metrics_size = 0; 1130 face->vert_metrics_size = 0; 1131 } 1132 1133 /* freeing the vertical ones, if any */ 1134 if ( face->vertical_info ) 1135 { 1136 FT_FREE( face->vertical.long_metrics ); 1137 FT_FREE( face->vertical.short_metrics ); 1138 face->vertical_info = 0; 1139 } 1140 1141 /* freeing the gasp table */ 1142 FT_FREE( face->gasp.gaspRanges ); 1143 face->gasp.numRanges = 0; 1144 1145 /* freeing the name table */ 1146 if ( sfnt ) 1147 sfnt->free_name( face ); 1148 1149 /* freeing family and style name */ 1150 FT_FREE( face->root.family_name ); 1151 FT_FREE( face->root.style_name ); 1152 1153 /* freeing sbit size table */ 1154 FT_FREE( face->root.available_sizes ); 1155 face->root.num_fixed_sizes = 0; 1156 1157 FT_FREE( face->postscript_name ); 1158 1159 face->sfnt = 0; 1160 } 1161 1162 1163 /* END */ 1164