1 /**************************************************************************** 2 * 3 * sfobjs.c 4 * 5 * SFNT object management (base). 6 * 7 * Copyright 1996-2018 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 FT_GZIP_H 31 32 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 33 #include FT_SERVICE_MULTIPLE_MASTERS_H 34 #include FT_SERVICE_METRICS_VARIATIONS_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 trace_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_NEW_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_NEW_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 #define WRITE_USHORT( p, v ) \ 341 do \ 342 { \ 343 *(p)++ = (FT_Byte)( (v) >> 8 ); \ 344 *(p)++ = (FT_Byte)( (v) >> 0 ); \ 345 \ 346 } while ( 0 ) 347 348 #define WRITE_ULONG( p, v ) \ 349 do \ 350 { \ 351 *(p)++ = (FT_Byte)( (v) >> 24 ); \ 352 *(p)++ = (FT_Byte)( (v) >> 16 ); \ 353 *(p)++ = (FT_Byte)( (v) >> 8 ); \ 354 *(p)++ = (FT_Byte)( (v) >> 0 ); \ 355 \ 356 } while ( 0 ) 357 358 359 static void sfnt_stream_close(FT_Stream stream)360 sfnt_stream_close( FT_Stream stream ) 361 { 362 FT_Memory memory = stream->memory; 363 364 365 FT_FREE( stream->base ); 366 367 stream->size = 0; 368 stream->base = NULL; 369 stream->close = NULL; 370 } 371 372 373 FT_CALLBACK_DEF( int ) compare_offsets(const void * a,const void * b)374 compare_offsets( const void* a, 375 const void* b ) 376 { 377 WOFF_Table table1 = *(WOFF_Table*)a; 378 WOFF_Table table2 = *(WOFF_Table*)b; 379 380 FT_ULong offset1 = table1->Offset; 381 FT_ULong offset2 = table2->Offset; 382 383 384 if ( offset1 > offset2 ) 385 return 1; 386 else if ( offset1 < offset2 ) 387 return -1; 388 else 389 return 0; 390 } 391 392 393 /* Replace `face->root.stream' with a stream containing the extracted */ 394 /* SFNT of a WOFF font. */ 395 396 static FT_Error woff_open_font(FT_Stream stream,TT_Face face)397 woff_open_font( FT_Stream stream, 398 TT_Face face ) 399 { 400 FT_Memory memory = stream->memory; 401 FT_Error error = FT_Err_Ok; 402 403 WOFF_HeaderRec woff; 404 WOFF_Table tables = NULL; 405 WOFF_Table* indices = NULL; 406 407 FT_ULong woff_offset; 408 409 FT_Byte* sfnt = NULL; 410 FT_Stream sfnt_stream = NULL; 411 412 FT_Byte* sfnt_header; 413 FT_ULong sfnt_offset; 414 415 FT_Int nn; 416 FT_ULong old_tag = 0; 417 418 static const FT_Frame_Field woff_header_fields[] = 419 { 420 #undef FT_STRUCTURE 421 #define FT_STRUCTURE WOFF_HeaderRec 422 423 FT_FRAME_START( 44 ), 424 FT_FRAME_ULONG ( signature ), 425 FT_FRAME_ULONG ( flavor ), 426 FT_FRAME_ULONG ( length ), 427 FT_FRAME_USHORT( num_tables ), 428 FT_FRAME_USHORT( reserved ), 429 FT_FRAME_ULONG ( totalSfntSize ), 430 FT_FRAME_USHORT( majorVersion ), 431 FT_FRAME_USHORT( minorVersion ), 432 FT_FRAME_ULONG ( metaOffset ), 433 FT_FRAME_ULONG ( metaLength ), 434 FT_FRAME_ULONG ( metaOrigLength ), 435 FT_FRAME_ULONG ( privOffset ), 436 FT_FRAME_ULONG ( privLength ), 437 FT_FRAME_END 438 }; 439 440 441 FT_ASSERT( stream == face->root.stream ); 442 FT_ASSERT( FT_STREAM_POS() == 0 ); 443 444 if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) ) 445 return error; 446 447 /* Make sure we don't recurse back here or hit TTC code. */ 448 if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf ) 449 return FT_THROW( Invalid_Table ); 450 451 /* Miscellaneous checks. */ 452 if ( woff.length != stream->size || 453 woff.num_tables == 0 || 454 44 + woff.num_tables * 20UL >= woff.length || 455 12 + woff.num_tables * 16UL >= woff.totalSfntSize || 456 ( woff.totalSfntSize & 3 ) != 0 || 457 ( woff.metaOffset == 0 && ( woff.metaLength != 0 || 458 woff.metaOrigLength != 0 ) ) || 459 ( woff.metaLength != 0 && woff.metaOrigLength == 0 ) || 460 ( woff.privOffset == 0 && woff.privLength != 0 ) ) 461 { 462 FT_ERROR(( "woff_font_open: invalid WOFF header\n" )); 463 return FT_THROW( Invalid_Table ); 464 } 465 466 /* Don't trust `totalSfntSize' before thorough checks. */ 467 if ( FT_ALLOC( sfnt, 12 + woff.num_tables * 16UL ) || 468 FT_NEW( sfnt_stream ) ) 469 goto Exit; 470 471 sfnt_header = sfnt; 472 473 /* Write sfnt header. */ 474 { 475 FT_UInt searchRange, entrySelector, rangeShift, x; 476 477 478 x = woff.num_tables; 479 entrySelector = 0; 480 while ( x ) 481 { 482 x >>= 1; 483 entrySelector += 1; 484 } 485 entrySelector--; 486 487 searchRange = ( 1 << entrySelector ) * 16; 488 rangeShift = woff.num_tables * 16 - searchRange; 489 490 WRITE_ULONG ( sfnt_header, woff.flavor ); 491 WRITE_USHORT( sfnt_header, woff.num_tables ); 492 WRITE_USHORT( sfnt_header, searchRange ); 493 WRITE_USHORT( sfnt_header, entrySelector ); 494 WRITE_USHORT( sfnt_header, rangeShift ); 495 } 496 497 /* While the entries in the sfnt header must be sorted by the */ 498 /* tag value, the tables themselves are not. We thus have to */ 499 /* sort them by offset and check that they don't overlap. */ 500 501 if ( FT_NEW_ARRAY( tables, woff.num_tables ) || 502 FT_NEW_ARRAY( indices, woff.num_tables ) ) 503 goto Exit; 504 505 FT_TRACE2(( "\n" 506 " tag offset compLen origLen checksum\n" 507 " -------------------------------------------\n" )); 508 509 if ( FT_FRAME_ENTER( 20L * woff.num_tables ) ) 510 goto Exit; 511 512 for ( nn = 0; nn < woff.num_tables; nn++ ) 513 { 514 WOFF_Table table = tables + nn; 515 516 table->Tag = FT_GET_TAG4(); 517 table->Offset = FT_GET_ULONG(); 518 table->CompLength = FT_GET_ULONG(); 519 table->OrigLength = FT_GET_ULONG(); 520 table->CheckSum = FT_GET_ULONG(); 521 522 FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx %08lx\n", 523 (FT_Char)( table->Tag >> 24 ), 524 (FT_Char)( table->Tag >> 16 ), 525 (FT_Char)( table->Tag >> 8 ), 526 (FT_Char)( table->Tag ), 527 table->Offset, 528 table->CompLength, 529 table->OrigLength, 530 table->CheckSum )); 531 532 if ( table->Tag <= old_tag ) 533 { 534 FT_FRAME_EXIT(); 535 536 FT_ERROR(( "woff_font_open: table tags are not sorted\n" )); 537 error = FT_THROW( Invalid_Table ); 538 goto Exit; 539 } 540 541 old_tag = table->Tag; 542 indices[nn] = table; 543 } 544 545 FT_FRAME_EXIT(); 546 547 /* Sort by offset. */ 548 549 ft_qsort( indices, 550 woff.num_tables, 551 sizeof ( WOFF_Table ), 552 compare_offsets ); 553 554 /* Check offsets and lengths. */ 555 556 woff_offset = 44 + woff.num_tables * 20L; 557 sfnt_offset = 12 + woff.num_tables * 16L; 558 559 for ( nn = 0; nn < woff.num_tables; nn++ ) 560 { 561 WOFF_Table table = indices[nn]; 562 563 564 if ( table->Offset != woff_offset || 565 table->CompLength > woff.length || 566 table->Offset > woff.length - table->CompLength || 567 table->OrigLength > woff.totalSfntSize || 568 sfnt_offset > woff.totalSfntSize - table->OrigLength || 569 table->CompLength > table->OrigLength ) 570 { 571 FT_ERROR(( "woff_font_open: invalid table offsets\n" )); 572 error = FT_THROW( Invalid_Table ); 573 goto Exit; 574 } 575 576 table->OrigOffset = sfnt_offset; 577 578 /* The offsets must be multiples of 4. */ 579 woff_offset += ( table->CompLength + 3 ) & ~3U; 580 sfnt_offset += ( table->OrigLength + 3 ) & ~3U; 581 } 582 583 /* 584 * Final checks! 585 * 586 * We don't decode and check the metadata block. 587 * We don't check table checksums either. 588 * But other than those, I think we implement all 589 * `MUST' checks from the spec. 590 */ 591 592 if ( woff.metaOffset ) 593 { 594 if ( woff.metaOffset != woff_offset || 595 woff.metaOffset + woff.metaLength > woff.length ) 596 { 597 FT_ERROR(( "woff_font_open:" 598 " invalid `metadata' offset or length\n" )); 599 error = FT_THROW( Invalid_Table ); 600 goto Exit; 601 } 602 603 /* We have padding only ... */ 604 woff_offset += woff.metaLength; 605 } 606 607 if ( woff.privOffset ) 608 { 609 /* ... if it isn't the last block. */ 610 woff_offset = ( woff_offset + 3 ) & ~3U; 611 612 if ( woff.privOffset != woff_offset || 613 woff.privOffset + woff.privLength > woff.length ) 614 { 615 FT_ERROR(( "woff_font_open: invalid `private' offset or length\n" )); 616 error = FT_THROW( Invalid_Table ); 617 goto Exit; 618 } 619 620 /* No padding for the last block. */ 621 woff_offset += woff.privLength; 622 } 623 624 if ( sfnt_offset != woff.totalSfntSize || 625 woff_offset != woff.length ) 626 { 627 FT_ERROR(( "woff_font_open: invalid `sfnt' table structure\n" )); 628 error = FT_THROW( Invalid_Table ); 629 goto Exit; 630 } 631 632 /* Now use `totalSfntSize'. */ 633 if ( FT_REALLOC( sfnt, 634 12 + woff.num_tables * 16UL, 635 woff.totalSfntSize ) ) 636 goto Exit; 637 638 sfnt_header = sfnt + 12; 639 640 /* Write the tables. */ 641 642 for ( nn = 0; nn < woff.num_tables; nn++ ) 643 { 644 WOFF_Table table = tables + nn; 645 646 647 /* Write SFNT table entry. */ 648 WRITE_ULONG( sfnt_header, table->Tag ); 649 WRITE_ULONG( sfnt_header, table->CheckSum ); 650 WRITE_ULONG( sfnt_header, table->OrigOffset ); 651 WRITE_ULONG( sfnt_header, table->OrigLength ); 652 653 /* Write table data. */ 654 if ( FT_STREAM_SEEK( table->Offset ) || 655 FT_FRAME_ENTER( table->CompLength ) ) 656 goto Exit; 657 658 if ( table->CompLength == table->OrigLength ) 659 { 660 /* Uncompressed data; just copy. */ 661 ft_memcpy( sfnt + table->OrigOffset, 662 stream->cursor, 663 table->OrigLength ); 664 } 665 else 666 { 667 #ifdef FT_CONFIG_OPTION_USE_ZLIB 668 669 /* Uncompress with zlib. */ 670 FT_ULong output_len = table->OrigLength; 671 672 673 error = FT_Gzip_Uncompress( memory, 674 sfnt + table->OrigOffset, &output_len, 675 stream->cursor, table->CompLength ); 676 if ( error ) 677 goto Exit; 678 if ( output_len != table->OrigLength ) 679 { 680 FT_ERROR(( "woff_font_open: compressed table length mismatch\n" )); 681 error = FT_THROW( Invalid_Table ); 682 goto Exit; 683 } 684 685 #else /* !FT_CONFIG_OPTION_USE_ZLIB */ 686 687 error = FT_THROW( Unimplemented_Feature ); 688 goto Exit; 689 690 #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ 691 } 692 693 FT_FRAME_EXIT(); 694 695 /* We don't check whether the padding bytes in the WOFF file are */ 696 /* actually '\0'. For the output, however, we do set them properly. */ 697 sfnt_offset = table->OrigOffset + table->OrigLength; 698 while ( sfnt_offset & 3 ) 699 { 700 sfnt[sfnt_offset] = '\0'; 701 sfnt_offset++; 702 } 703 } 704 705 /* Ok! Finally ready. Swap out stream and return. */ 706 FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize ); 707 sfnt_stream->memory = stream->memory; 708 sfnt_stream->close = sfnt_stream_close; 709 710 FT_Stream_Free( 711 face->root.stream, 712 ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); 713 714 face->root.stream = sfnt_stream; 715 716 face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; 717 718 Exit: 719 FT_FREE( tables ); 720 FT_FREE( indices ); 721 722 if ( error ) 723 { 724 FT_FREE( sfnt ); 725 FT_Stream_Close( sfnt_stream ); 726 FT_FREE( sfnt_stream ); 727 } 728 729 return error; 730 } 731 732 733 #undef WRITE_USHORT 734 #undef WRITE_ULONG 735 736 737 /* Fill in face->ttc_header. If the font is not a TTC, it is */ 738 /* synthesized into a TTC with one offset table. */ 739 static FT_Error sfnt_open_font(FT_Stream stream,TT_Face face)740 sfnt_open_font( FT_Stream stream, 741 TT_Face face ) 742 { 743 FT_Memory memory = stream->memory; 744 FT_Error error; 745 FT_ULong tag, offset; 746 747 static const FT_Frame_Field ttc_header_fields[] = 748 { 749 #undef FT_STRUCTURE 750 #define FT_STRUCTURE TTC_HeaderRec 751 752 FT_FRAME_START( 8 ), 753 FT_FRAME_LONG( version ), 754 FT_FRAME_LONG( count ), /* this is ULong in the specs */ 755 FT_FRAME_END 756 }; 757 758 759 face->ttc_header.tag = 0; 760 face->ttc_header.version = 0; 761 face->ttc_header.count = 0; 762 763 retry: 764 offset = FT_STREAM_POS(); 765 766 if ( FT_READ_ULONG( tag ) ) 767 return error; 768 769 if ( tag == TTAG_wOFF ) 770 { 771 FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); 772 773 if ( FT_STREAM_SEEK( offset ) ) 774 return error; 775 776 error = woff_open_font( stream, face ); 777 if ( error ) 778 return error; 779 780 /* Swap out stream and retry! */ 781 stream = face->root.stream; 782 goto retry; 783 } 784 785 if ( tag != 0x00010000UL && 786 tag != TTAG_ttcf && 787 tag != TTAG_OTTO && 788 tag != TTAG_true && 789 tag != TTAG_typ1 && 790 tag != TTAG_0xA5kbd && 791 tag != TTAG_0xA5lst && 792 tag != 0x00020000UL ) 793 { 794 FT_TRACE2(( " not a font using the SFNT container format\n" )); 795 return FT_THROW( Unknown_File_Format ); 796 } 797 798 face->ttc_header.tag = TTAG_ttcf; 799 800 if ( tag == TTAG_ttcf ) 801 { 802 FT_Int n; 803 804 805 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); 806 807 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) 808 return error; 809 810 FT_TRACE3(( " with %ld subfonts\n", 811 face->ttc_header.count )); 812 813 if ( face->ttc_header.count == 0 ) 814 return FT_THROW( Invalid_Table ); 815 816 /* a rough size estimate: let's conservatively assume that there */ 817 /* is just a single table info in each subfont header (12 + 16*1 = */ 818 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ 819 /* size of the TTC header plus `28*count' bytes for all subfont */ 820 /* headers */ 821 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) 822 return FT_THROW( Array_Too_Large ); 823 824 /* now read the offsets of each font in the file */ 825 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) 826 return error; 827 828 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) 829 return error; 830 831 for ( n = 0; n < face->ttc_header.count; n++ ) 832 face->ttc_header.offsets[n] = FT_GET_ULONG(); 833 834 FT_FRAME_EXIT(); 835 } 836 else 837 { 838 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); 839 840 face->ttc_header.version = 1 << 16; 841 face->ttc_header.count = 1; 842 843 if ( FT_NEW( face->ttc_header.offsets ) ) 844 return error; 845 846 face->ttc_header.offsets[0] = offset; 847 } 848 849 return error; 850 } 851 852 853 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)854 sfnt_init_face( FT_Stream stream, 855 TT_Face face, 856 FT_Int face_instance_index, 857 FT_Int num_params, 858 FT_Parameter* params ) 859 { 860 FT_Error error; 861 FT_Library library = face->root.driver->root.library; 862 SFNT_Service sfnt; 863 FT_Int face_index; 864 865 866 /* for now, parameters are unused */ 867 FT_UNUSED( num_params ); 868 FT_UNUSED( params ); 869 870 871 sfnt = (SFNT_Service)face->sfnt; 872 if ( !sfnt ) 873 { 874 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 875 if ( !sfnt ) 876 { 877 FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); 878 return FT_THROW( Missing_Module ); 879 } 880 881 face->sfnt = sfnt; 882 face->goto_table = sfnt->goto_table; 883 } 884 885 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); 886 887 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 888 if ( !face->mm ) 889 { 890 /* we want the MM interface from the `truetype' module only */ 891 FT_Module tt_module = FT_Get_Module( library, "truetype" ); 892 893 894 face->mm = ft_module_get_service( tt_module, 895 FT_SERVICE_ID_MULTI_MASTERS, 896 0 ); 897 } 898 899 if ( !face->var ) 900 { 901 /* we want the metrics variations interface */ 902 /* from the `truetype' module only */ 903 FT_Module tt_module = FT_Get_Module( library, "truetype" ); 904 905 906 face->var = ft_module_get_service( tt_module, 907 FT_SERVICE_ID_METRICS_VARIATIONS, 908 0 ); 909 } 910 #endif 911 912 FT_TRACE2(( "SFNT driver\n" )); 913 914 error = sfnt_open_font( stream, face ); 915 if ( error ) 916 return error; 917 918 /* Stream may have changed in sfnt_open_font. */ 919 stream = face->root.stream; 920 921 FT_TRACE2(( "sfnt_init_face: %08p (index %d)\n", 922 face, 923 face_instance_index )); 924 925 face_index = FT_ABS( face_instance_index ) & 0xFFFF; 926 927 /* value -(N+1) requests information on index N */ 928 if ( face_instance_index < 0 ) 929 face_index--; 930 931 if ( face_index >= face->ttc_header.count ) 932 { 933 if ( face_instance_index >= 0 ) 934 return FT_THROW( Invalid_Argument ); 935 else 936 face_index = 0; 937 } 938 939 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) 940 return error; 941 942 /* check whether we have a valid TrueType file */ 943 error = sfnt->load_font_dir( face, stream ); 944 if ( error ) 945 return error; 946 947 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 948 { 949 FT_Memory memory = face->root.memory; 950 951 FT_ULong fvar_len; 952 953 FT_ULong version; 954 FT_ULong offset; 955 956 FT_UShort num_axes; 957 FT_UShort axis_size; 958 FT_UShort num_instances; 959 FT_UShort instance_size; 960 961 FT_Int instance_index; 962 963 FT_Byte* default_values = NULL; 964 FT_Byte* instance_values = NULL; 965 966 967 instance_index = FT_ABS( face_instance_index ) >> 16; 968 969 /* test whether current face is a GX font with named instances */ 970 if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || 971 fvar_len < 20 || 972 FT_READ_ULONG( version ) || 973 FT_READ_USHORT( offset ) || 974 FT_STREAM_SKIP( 2 ) /* reserved */ || 975 FT_READ_USHORT( num_axes ) || 976 FT_READ_USHORT( axis_size ) || 977 FT_READ_USHORT( num_instances ) || 978 FT_READ_USHORT( instance_size ) ) 979 { 980 version = 0; 981 offset = 0; 982 num_axes = 0; 983 axis_size = 0; 984 num_instances = 0; 985 instance_size = 0; 986 } 987 988 /* check that the data is bound by the table length */ 989 if ( version != 0x00010000UL || 990 axis_size != 20 || 991 num_axes == 0 || 992 /* `num_axes' limit implied by 16-bit `instance_size' */ 993 num_axes > 0x3FFE || 994 !( instance_size == 4 + 4 * num_axes || 995 instance_size == 6 + 4 * num_axes ) || 996 /* `num_instances' limit implied by limited range of name IDs */ 997 num_instances > 0x7EFF || 998 offset + 999 axis_size * num_axes + 1000 instance_size * num_instances > fvar_len ) 1001 num_instances = 0; 1002 else 1003 face->variation_support |= TT_FACE_FLAG_VAR_FVAR; 1004 1005 /* 1006 * As documented in the OpenType specification, an entry for the 1007 * default instance may be omitted in the named instance table. In 1008 * particular this means that even if there is no named instance 1009 * table in the font we actually do have a named instance, namely the 1010 * default instance. 1011 * 1012 * For consistency, we always want the default instance in our list 1013 * of named instances. If it is missing, we try to synthesize it 1014 * later on. Here, we have to adjust `num_instances' accordingly. 1015 */ 1016 1017 if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && 1018 !( FT_ALLOC( default_values, num_axes * 4 ) || 1019 FT_ALLOC( instance_values, num_axes * 4 ) ) ) 1020 { 1021 /* the current stream position is 16 bytes after the table start */ 1022 FT_ULong array_start = FT_STREAM_POS() - 16 + offset; 1023 FT_ULong default_value_offset, instance_offset; 1024 1025 FT_Byte* p; 1026 FT_UInt i; 1027 1028 1029 default_value_offset = array_start + 8; 1030 p = default_values; 1031 1032 for ( i = 0; i < num_axes; i++ ) 1033 { 1034 (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); 1035 1036 default_value_offset += axis_size; 1037 p += 4; 1038 } 1039 1040 instance_offset = array_start + axis_size * num_axes + 4; 1041 1042 for ( i = 0; i < num_instances; i++ ) 1043 { 1044 (void)FT_STREAM_READ_AT( instance_offset, 1045 instance_values, 1046 num_axes * 4 ); 1047 1048 if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) 1049 break; 1050 1051 instance_offset += instance_size; 1052 } 1053 1054 if ( i == num_instances ) 1055 { 1056 /* no default instance in named instance table; */ 1057 /* we thus have to synthesize it */ 1058 num_instances++; 1059 } 1060 } 1061 1062 FT_FREE( default_values ); 1063 FT_FREE( instance_values ); 1064 1065 /* we don't support Multiple Master CFFs yet; */ 1066 /* note that `glyf' or `CFF2' have precedence */ 1067 if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && 1068 face->goto_table( face, TTAG_CFF2, stream, 0 ) && 1069 !face->goto_table( face, TTAG_CFF, stream, 0 ) ) 1070 num_instances = 0; 1071 1072 /* instance indices in `face_instance_index' start with index 1, */ 1073 /* thus `>' and not `>=' */ 1074 if ( instance_index > num_instances ) 1075 { 1076 if ( face_instance_index >= 0 ) 1077 return FT_THROW( Invalid_Argument ); 1078 else 1079 num_instances = 0; 1080 } 1081 1082 face->root.style_flags = (FT_Long)num_instances << 16; 1083 } 1084 #endif 1085 1086 face->root.num_faces = face->ttc_header.count; 1087 face->root.face_index = face_instance_index; 1088 1089 return error; 1090 } 1091 1092 1093 #define LOAD_( x ) \ 1094 do \ 1095 { \ 1096 FT_TRACE2(( "`" #x "' " )); \ 1097 FT_TRACE3(( "-->\n" )); \ 1098 \ 1099 error = sfnt->load_ ## x( face, stream ); \ 1100 \ 1101 FT_TRACE2(( "%s\n", ( !error ) \ 1102 ? "loaded" \ 1103 : FT_ERR_EQ( error, Table_Missing ) \ 1104 ? "missing" \ 1105 : "failed to load" )); \ 1106 FT_TRACE3(( "\n" )); \ 1107 } while ( 0 ) 1108 1109 #define LOADM_( x, vertical ) \ 1110 do \ 1111 { \ 1112 FT_TRACE2(( "`%s" #x "' ", \ 1113 vertical ? "vertical " : "" )); \ 1114 FT_TRACE3(( "-->\n" )); \ 1115 \ 1116 error = sfnt->load_ ## x( face, stream, vertical ); \ 1117 \ 1118 FT_TRACE2(( "%s\n", ( !error ) \ 1119 ? "loaded" \ 1120 : FT_ERR_EQ( error, Table_Missing ) \ 1121 ? "missing" \ 1122 : "failed to load" )); \ 1123 FT_TRACE3(( "\n" )); \ 1124 } while ( 0 ) 1125 1126 #define GET_NAME( id, field ) \ 1127 do \ 1128 { \ 1129 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ 1130 if ( error ) \ 1131 goto Exit; \ 1132 } while ( 0 ) 1133 1134 1135 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)1136 sfnt_load_face( FT_Stream stream, 1137 TT_Face face, 1138 FT_Int face_instance_index, 1139 FT_Int num_params, 1140 FT_Parameter* params ) 1141 { 1142 FT_Error error; 1143 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1144 FT_Error psnames_error; 1145 #endif 1146 FT_Bool has_outline; 1147 FT_Bool is_apple_sbit; 1148 FT_Bool is_apple_sbix; 1149 FT_Bool has_CBLC; 1150 FT_Bool has_CBDT; 1151 FT_Bool ignore_typographic_family = FALSE; 1152 FT_Bool ignore_typographic_subfamily = FALSE; 1153 1154 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 1155 1156 FT_UNUSED( face_instance_index ); 1157 1158 1159 /* Check parameters */ 1160 1161 { 1162 FT_Int i; 1163 1164 1165 for ( i = 0; i < num_params; i++ ) 1166 { 1167 if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) 1168 ignore_typographic_family = TRUE; 1169 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) 1170 ignore_typographic_subfamily = TRUE; 1171 } 1172 } 1173 1174 /* Load tables */ 1175 1176 /* We now support two SFNT-based bitmapped font formats. They */ 1177 /* are recognized easily as they do not include a `glyf' */ 1178 /* table. */ 1179 /* */ 1180 /* The first format comes from Apple, and uses a table named */ 1181 /* `bhed' instead of `head' to store the font header (using */ 1182 /* the same format). It also doesn't include horizontal and */ 1183 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 1184 /* missing). */ 1185 /* */ 1186 /* The other format comes from Microsoft, and is used with */ 1187 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 1188 /* it doesn't contain outlines. */ 1189 /* */ 1190 1191 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); 1192 1193 /* do we have outlines in there? */ 1194 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1195 has_outline = FT_BOOL( face->root.internal->incremental_interface || 1196 tt_face_lookup_table( face, TTAG_glyf ) || 1197 tt_face_lookup_table( face, TTAG_CFF ) || 1198 tt_face_lookup_table( face, TTAG_CFF2 ) ); 1199 #else 1200 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) || 1201 tt_face_lookup_table( face, TTAG_CFF ) || 1202 tt_face_lookup_table( face, TTAG_CFF2 ) ); 1203 #endif 1204 1205 is_apple_sbit = 0; 1206 is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); 1207 1208 /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' 1209 * outline rendered on top. We don't support that yet, so just ignore 1210 * the 'glyf' outline and advertise it as a bitmap-only font. */ 1211 if ( is_apple_sbix ) 1212 has_outline = FALSE; 1213 1214 /* if this font doesn't contain outlines, we try to load */ 1215 /* a `bhed' table */ 1216 if ( !has_outline && sfnt->load_bhed ) 1217 { 1218 LOAD_( bhed ); 1219 is_apple_sbit = FT_BOOL( !error ); 1220 } 1221 1222 /* load the font header (`head' table) if this isn't an Apple */ 1223 /* sbit font file */ 1224 if ( !is_apple_sbit || is_apple_sbix ) 1225 { 1226 LOAD_( head ); 1227 if ( error ) 1228 goto Exit; 1229 } 1230 1231 has_CBLC = !face->goto_table( face, TTAG_CBLC, stream, 0 ); 1232 has_CBDT = !face->goto_table( face, TTAG_CBDT, stream, 0 ); 1233 1234 /* Ignore outlines for CBLC/CBDT fonts. */ 1235 if ( has_CBLC || has_CBDT ) 1236 has_outline = FALSE; 1237 1238 /* OpenType 1.8.2 introduced limits to this value; */ 1239 /* however, they make sense for older SFNT fonts also */ 1240 if ( face->header.Units_Per_EM < 16 || 1241 face->header.Units_Per_EM > 16384 ) 1242 { 1243 error = FT_THROW( Invalid_Table ); 1244 1245 goto Exit; 1246 } 1247 1248 /* the following tables are often not present in embedded TrueType */ 1249 /* fonts within PDF documents, so don't check for them. */ 1250 LOAD_( maxp ); 1251 LOAD_( cmap ); 1252 1253 /* the following tables are optional in PCL fonts -- */ 1254 /* don't check for errors */ 1255 LOAD_( name ); 1256 LOAD_( post ); 1257 1258 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1259 psnames_error = error; 1260 #endif 1261 1262 /* do not load the metrics headers and tables if this is an Apple */ 1263 /* sbit font file */ 1264 if ( !is_apple_sbit ) 1265 { 1266 /* load the `hhea' and `hmtx' tables */ 1267 LOADM_( hhea, 0 ); 1268 if ( !error ) 1269 { 1270 LOADM_( hmtx, 0 ); 1271 if ( FT_ERR_EQ( error, Table_Missing ) ) 1272 { 1273 error = FT_THROW( Hmtx_Table_Missing ); 1274 1275 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1276 /* If this is an incrementally loaded font and there are */ 1277 /* overriding metrics, tolerate a missing `hmtx' table. */ 1278 if ( face->root.internal->incremental_interface && 1279 face->root.internal->incremental_interface->funcs-> 1280 get_glyph_metrics ) 1281 { 1282 face->horizontal.number_Of_HMetrics = 0; 1283 error = FT_Err_Ok; 1284 } 1285 #endif 1286 } 1287 } 1288 else if ( FT_ERR_EQ( error, Table_Missing ) ) 1289 { 1290 /* No `hhea' table necessary for SFNT Mac fonts. */ 1291 if ( face->format_tag == TTAG_true ) 1292 { 1293 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 1294 1295 has_outline = 0; 1296 error = FT_Err_Ok; 1297 } 1298 else 1299 { 1300 error = FT_THROW( Horiz_Header_Missing ); 1301 1302 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1303 /* If this is an incrementally loaded font and there are */ 1304 /* overriding metrics, tolerate a missing `hhea' table. */ 1305 if ( face->root.internal->incremental_interface && 1306 face->root.internal->incremental_interface->funcs-> 1307 get_glyph_metrics ) 1308 { 1309 face->horizontal.number_Of_HMetrics = 0; 1310 error = FT_Err_Ok; 1311 } 1312 #endif 1313 1314 } 1315 } 1316 1317 if ( error ) 1318 goto Exit; 1319 1320 /* try to load the `vhea' and `vmtx' tables */ 1321 LOADM_( hhea, 1 ); 1322 if ( !error ) 1323 { 1324 LOADM_( hmtx, 1 ); 1325 if ( !error ) 1326 face->vertical_info = 1; 1327 } 1328 1329 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 1330 goto Exit; 1331 1332 LOAD_( os2 ); 1333 if ( error ) 1334 { 1335 /* we treat the table as missing if there are any errors */ 1336 face->os2.version = 0xFFFFU; 1337 } 1338 } 1339 1340 /* the optional tables */ 1341 1342 /* embedded bitmap support */ 1343 if ( sfnt->load_eblc ) 1344 LOAD_( eblc ); 1345 1346 /* colored glyph support */ 1347 if ( sfnt->load_cpal ) 1348 { 1349 LOAD_( cpal ); 1350 LOAD_( colr ); 1351 } 1352 1353 /* consider the pclt, kerning, and gasp tables as optional */ 1354 LOAD_( pclt ); 1355 LOAD_( gasp ); 1356 LOAD_( kern ); 1357 1358 face->root.num_glyphs = face->max_profile.numGlyphs; 1359 1360 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 1361 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 1362 /* `slope', a term used by Microsoft's Windows Presentation */ 1363 /* Foundation (WPF). This flag has been introduced in version */ 1364 /* 1.5 of the OpenType specification (May 2008). */ 1365 1366 face->root.family_name = NULL; 1367 face->root.style_name = NULL; 1368 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 1369 { 1370 if ( !ignore_typographic_family ) 1371 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1372 if ( !face->root.family_name ) 1373 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1374 1375 if ( !ignore_typographic_subfamily ) 1376 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1377 if ( !face->root.style_name ) 1378 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1379 } 1380 else 1381 { 1382 GET_NAME( WWS_FAMILY, &face->root.family_name ); 1383 if ( !face->root.family_name && !ignore_typographic_family ) 1384 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1385 if ( !face->root.family_name ) 1386 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1387 1388 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 1389 if ( !face->root.style_name && !ignore_typographic_subfamily ) 1390 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1391 if ( !face->root.style_name ) 1392 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1393 } 1394 1395 /* now set up root fields */ 1396 { 1397 FT_Face root = &face->root; 1398 FT_Long flags = root->face_flags; 1399 1400 1401 /********************************************************************** 1402 * 1403 * Compute face flags. 1404 */ 1405 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || 1406 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX || 1407 face->colr ) 1408 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ 1409 1410 if ( has_outline == TRUE ) 1411 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 1412 1413 /* The sfnt driver only supports bitmap fonts natively, thus we */ 1414 /* don't set FT_FACE_FLAG_HINTER. */ 1415 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 1416 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 1417 1418 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1419 if ( !psnames_error && 1420 face->postscript.FormatType != 0x00030000L ) 1421 flags |= FT_FACE_FLAG_GLYPH_NAMES; 1422 #endif 1423 1424 /* fixed width font? */ 1425 if ( face->postscript.isFixedPitch ) 1426 flags |= FT_FACE_FLAG_FIXED_WIDTH; 1427 1428 /* vertical information? */ 1429 if ( face->vertical_info ) 1430 flags |= FT_FACE_FLAG_VERTICAL; 1431 1432 /* kerning available ? */ 1433 if ( TT_FACE_HAS_KERNING( face ) ) 1434 flags |= FT_FACE_FLAG_KERNING; 1435 1436 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1437 /* Don't bother to load the tables unless somebody asks for them. */ 1438 /* No need to do work which will (probably) not be used. */ 1439 if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) 1440 { 1441 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && 1442 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) 1443 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1444 if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) 1445 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1446 } 1447 #endif 1448 1449 root->face_flags = flags; 1450 1451 /********************************************************************** 1452 * 1453 * Compute style flags. 1454 */ 1455 1456 flags = 0; 1457 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 1458 { 1459 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 1460 /* indicates an oblique font face. This flag has been */ 1461 /* introduced in version 1.5 of the OpenType specification. */ 1462 1463 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 1464 flags |= FT_STYLE_FLAG_ITALIC; 1465 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 1466 flags |= FT_STYLE_FLAG_ITALIC; 1467 1468 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 1469 flags |= FT_STYLE_FLAG_BOLD; 1470 } 1471 else 1472 { 1473 /* this is an old Mac font, use the header field */ 1474 1475 if ( face->header.Mac_Style & 1 ) 1476 flags |= FT_STYLE_FLAG_BOLD; 1477 1478 if ( face->header.Mac_Style & 2 ) 1479 flags |= FT_STYLE_FLAG_ITALIC; 1480 } 1481 1482 root->style_flags |= flags; 1483 1484 /********************************************************************** 1485 * 1486 * Polish the charmaps. 1487 * 1488 * Try to set the charmap encoding according to the platform & 1489 * encoding ID of each charmap. Emulate Unicode charmap if one 1490 * is missing. 1491 */ 1492 1493 tt_face_build_cmaps( face ); /* ignore errors */ 1494 1495 1496 /* set the encoding fields */ 1497 { 1498 FT_Int m; 1499 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1500 FT_Bool has_unicode = FALSE; 1501 #endif 1502 1503 1504 for ( m = 0; m < root->num_charmaps; m++ ) 1505 { 1506 FT_CharMap charmap = root->charmaps[m]; 1507 1508 1509 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 1510 charmap->encoding_id ); 1511 1512 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1513 1514 if ( charmap->encoding == FT_ENCODING_UNICODE || 1515 charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ 1516 has_unicode = TRUE; 1517 } 1518 1519 /* synthesize Unicode charmap if one is missing */ 1520 if ( !has_unicode ) 1521 { 1522 FT_CharMapRec cmaprec; 1523 1524 1525 cmaprec.face = root; 1526 cmaprec.platform_id = TT_PLATFORM_MICROSOFT; 1527 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; 1528 cmaprec.encoding = FT_ENCODING_UNICODE; 1529 1530 1531 error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, 1532 NULL, &cmaprec, NULL ); 1533 if ( error && 1534 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 1535 goto Exit; 1536 error = FT_Err_Ok; 1537 1538 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 1539 1540 } 1541 } 1542 1543 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1544 1545 /* 1546 * Now allocate the root array of FT_Bitmap_Size records and 1547 * populate them. Unfortunately, it isn't possible to indicate bit 1548 * depths in the FT_Bitmap_Size record. This is a design error. 1549 */ 1550 { 1551 FT_UInt count; 1552 1553 1554 count = face->sbit_num_strikes; 1555 1556 if ( count > 0 ) 1557 { 1558 FT_Memory memory = face->root.stream->memory; 1559 FT_UShort em_size = face->header.Units_Per_EM; 1560 FT_Short avgwidth = face->os2.xAvgCharWidth; 1561 FT_Size_Metrics metrics; 1562 1563 FT_UInt* sbit_strike_map = NULL; 1564 FT_UInt strike_idx, bsize_idx; 1565 1566 1567 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 1568 { 1569 avgwidth = 1; 1570 em_size = 1; 1571 } 1572 1573 /* to avoid invalid strike data in the `available_sizes' field */ 1574 /* of `FT_Face', we map `available_sizes' indices to strike */ 1575 /* indices */ 1576 if ( FT_NEW_ARRAY( root->available_sizes, count ) || 1577 FT_NEW_ARRAY( sbit_strike_map, count ) ) 1578 goto Exit; 1579 1580 bsize_idx = 0; 1581 for ( strike_idx = 0; strike_idx < count; strike_idx++ ) 1582 { 1583 FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx; 1584 1585 1586 error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); 1587 if ( error ) 1588 continue; 1589 1590 bsize->height = (FT_Short)( metrics.height >> 6 ); 1591 bsize->width = (FT_Short)( 1592 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 1593 1594 bsize->x_ppem = metrics.x_ppem << 6; 1595 bsize->y_ppem = metrics.y_ppem << 6; 1596 1597 /* assume 72dpi */ 1598 bsize->size = metrics.y_ppem << 6; 1599 1600 /* only use strikes with valid PPEM values */ 1601 if ( bsize->x_ppem && bsize->y_ppem ) 1602 sbit_strike_map[bsize_idx++] = strike_idx; 1603 } 1604 1605 /* reduce array size to the actually used elements */ 1606 (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx ); 1607 1608 /* from now on, all strike indices are mapped */ 1609 /* using `sbit_strike_map' */ 1610 if ( bsize_idx ) 1611 { 1612 face->sbit_strike_map = sbit_strike_map; 1613 1614 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 1615 root->num_fixed_sizes = (FT_Int)bsize_idx; 1616 } 1617 } 1618 } 1619 1620 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1621 1622 /* a font with no bitmaps and no outlines is scalable; */ 1623 /* it has only empty glyphs then */ 1624 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 1625 root->face_flags |= FT_FACE_FLAG_SCALABLE; 1626 1627 1628 /********************************************************************** 1629 * 1630 * Set up metrics. 1631 */ 1632 if ( FT_IS_SCALABLE( root ) ) 1633 { 1634 /* XXX What about if outline header is missing */ 1635 /* (e.g. sfnt wrapped bitmap)? */ 1636 root->bbox.xMin = face->header.xMin; 1637 root->bbox.yMin = face->header.yMin; 1638 root->bbox.xMax = face->header.xMax; 1639 root->bbox.yMax = face->header.yMax; 1640 root->units_per_EM = face->header.Units_Per_EM; 1641 1642 1643 /* XXX: Computing the ascender/descender/height is very different */ 1644 /* from what the specification tells you. Apparently, we */ 1645 /* must be careful because */ 1646 /* */ 1647 /* - not all fonts have an OS/2 table; in this case, we take */ 1648 /* the values in the horizontal header. However, these */ 1649 /* values very often are not reliable. */ 1650 /* */ 1651 /* - otherwise, the correct typographic values are in the */ 1652 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ 1653 /* */ 1654 /* However, certain fonts have these fields set to 0. */ 1655 /* Rather, they have usWinAscent & usWinDescent correctly */ 1656 /* set (but with different values). */ 1657 /* */ 1658 /* As an example, Arial Narrow is implemented through four */ 1659 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ 1660 /* */ 1661 /* Strangely, all fonts have the same values in their */ 1662 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ 1663 /* */ 1664 /* On the other hand, they all have different */ 1665 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ 1666 /* table cannot be used to compute the text height reliably! */ 1667 /* */ 1668 1669 /* The ascender and descender are taken from the `hhea' table. */ 1670 /* If zero, they are taken from the `OS/2' table. */ 1671 1672 root->ascender = face->horizontal.Ascender; 1673 root->descender = face->horizontal.Descender; 1674 1675 root->height = root->ascender - root->descender + 1676 face->horizontal.Line_Gap; 1677 1678 if ( !( root->ascender || root->descender ) ) 1679 { 1680 if ( face->os2.version != 0xFFFFU ) 1681 { 1682 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) 1683 { 1684 root->ascender = face->os2.sTypoAscender; 1685 root->descender = face->os2.sTypoDescender; 1686 1687 root->height = root->ascender - root->descender + 1688 face->os2.sTypoLineGap; 1689 } 1690 else 1691 { 1692 root->ascender = (FT_Short)face->os2.usWinAscent; 1693 root->descender = -(FT_Short)face->os2.usWinDescent; 1694 1695 root->height = root->ascender - root->descender; 1696 } 1697 } 1698 } 1699 1700 root->max_advance_width = 1701 (FT_Short)face->horizontal.advance_Width_Max; 1702 root->max_advance_height = 1703 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max 1704 : root->height ); 1705 1706 /* See https://www.microsoft.com/typography/otspec/post.htm -- */ 1707 /* Adjust underline position from top edge to centre of */ 1708 /* stroke to convert TrueType meaning to FreeType meaning. */ 1709 root->underline_position = face->postscript.underlinePosition - 1710 face->postscript.underlineThickness / 2; 1711 root->underline_thickness = face->postscript.underlineThickness; 1712 } 1713 1714 } 1715 1716 Exit: 1717 FT_TRACE2(( "sfnt_load_face: done\n" )); 1718 1719 return error; 1720 } 1721 1722 1723 #undef LOAD_ 1724 #undef LOADM_ 1725 #undef GET_NAME 1726 1727 1728 FT_LOCAL_DEF( void ) sfnt_done_face(TT_Face face)1729 sfnt_done_face( TT_Face face ) 1730 { 1731 FT_Memory memory; 1732 SFNT_Service sfnt; 1733 1734 1735 if ( !face ) 1736 return; 1737 1738 memory = face->root.memory; 1739 sfnt = (SFNT_Service)face->sfnt; 1740 1741 if ( sfnt ) 1742 { 1743 /* destroy the postscript names table if it is loaded */ 1744 if ( sfnt->free_psnames ) 1745 sfnt->free_psnames( face ); 1746 1747 /* destroy the embedded bitmaps table if it is loaded */ 1748 if ( sfnt->free_eblc ) 1749 sfnt->free_eblc( face ); 1750 1751 /* destroy color table data if it is loaded */ 1752 if ( sfnt->free_cpal ) 1753 { 1754 sfnt->free_cpal( face ); 1755 sfnt->free_colr( face ); 1756 } 1757 } 1758 1759 #ifdef TT_CONFIG_OPTION_BDF 1760 /* freeing the embedded BDF properties */ 1761 tt_face_free_bdf_props( face ); 1762 #endif 1763 1764 /* freeing the kerning table */ 1765 tt_face_done_kern( face ); 1766 1767 /* freeing the collection table */ 1768 FT_FREE( face->ttc_header.offsets ); 1769 face->ttc_header.count = 0; 1770 1771 /* freeing table directory */ 1772 FT_FREE( face->dir_tables ); 1773 face->num_tables = 0; 1774 1775 { 1776 FT_Stream stream = FT_FACE_STREAM( face ); 1777 1778 1779 /* simply release the 'cmap' table frame */ 1780 FT_FRAME_RELEASE( face->cmap_table ); 1781 face->cmap_size = 0; 1782 } 1783 1784 face->horz_metrics_size = 0; 1785 face->vert_metrics_size = 0; 1786 1787 /* freeing vertical metrics, if any */ 1788 if ( face->vertical_info ) 1789 { 1790 FT_FREE( face->vertical.long_metrics ); 1791 FT_FREE( face->vertical.short_metrics ); 1792 face->vertical_info = 0; 1793 } 1794 1795 /* freeing the gasp table */ 1796 FT_FREE( face->gasp.gaspRanges ); 1797 face->gasp.numRanges = 0; 1798 1799 /* freeing the name table */ 1800 if ( sfnt ) 1801 sfnt->free_name( face ); 1802 1803 /* freeing family and style name */ 1804 FT_FREE( face->root.family_name ); 1805 FT_FREE( face->root.style_name ); 1806 1807 /* freeing sbit size table */ 1808 FT_FREE( face->root.available_sizes ); 1809 FT_FREE( face->sbit_strike_map ); 1810 face->root.num_fixed_sizes = 0; 1811 1812 FT_FREE( face->postscript_name ); 1813 1814 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1815 FT_FREE( face->var_postscript_prefix ); 1816 #endif 1817 1818 /* freeing glyph color palette data */ 1819 FT_FREE( face->palette_data.palette_name_ids ); 1820 FT_FREE( face->palette_data.palette_flags ); 1821 FT_FREE( face->palette_data.palette_entry_name_ids ); 1822 FT_FREE( face->palette ); 1823 1824 face->sfnt = NULL; 1825 } 1826 1827 1828 /* END */ 1829