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