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, %d\n", face, face_instance_index )); 922 923 face_index = FT_ABS( face_instance_index ) & 0xFFFF; 924 925 /* value -(N+1) requests information on index N */ 926 if ( face_instance_index < 0 ) 927 face_index--; 928 929 if ( face_index >= face->ttc_header.count ) 930 { 931 if ( face_instance_index >= 0 ) 932 return FT_THROW( Invalid_Argument ); 933 else 934 face_index = 0; 935 } 936 937 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) 938 return error; 939 940 /* check whether we have a valid TrueType file */ 941 error = sfnt->load_font_dir( face, stream ); 942 if ( error ) 943 return error; 944 945 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 946 { 947 FT_Memory memory = face->root.memory; 948 949 FT_ULong fvar_len; 950 951 FT_ULong version; 952 FT_ULong offset; 953 954 FT_UShort num_axes; 955 FT_UShort axis_size; 956 FT_UShort num_instances; 957 FT_UShort instance_size; 958 959 FT_Int instance_index; 960 961 FT_Byte* default_values = NULL; 962 FT_Byte* instance_values = NULL; 963 964 965 instance_index = FT_ABS( face_instance_index ) >> 16; 966 967 /* test whether current face is a GX font with named instances */ 968 if ( face->goto_table( face, TTAG_fvar, stream, &fvar_len ) || 969 fvar_len < 20 || 970 FT_READ_ULONG( version ) || 971 FT_READ_USHORT( offset ) || 972 FT_STREAM_SKIP( 2 ) /* reserved */ || 973 FT_READ_USHORT( num_axes ) || 974 FT_READ_USHORT( axis_size ) || 975 FT_READ_USHORT( num_instances ) || 976 FT_READ_USHORT( instance_size ) ) 977 { 978 version = 0; 979 offset = 0; 980 num_axes = 0; 981 axis_size = 0; 982 num_instances = 0; 983 instance_size = 0; 984 } 985 986 /* check that the data is bound by the table length */ 987 if ( version != 0x00010000UL || 988 axis_size != 20 || 989 num_axes == 0 || 990 /* `num_axes' limit implied by 16-bit `instance_size' */ 991 num_axes > 0x3FFE || 992 !( instance_size == 4 + 4 * num_axes || 993 instance_size == 6 + 4 * num_axes ) || 994 /* `num_instances' limit implied by limited range of name IDs */ 995 num_instances > 0x7EFF || 996 offset + 997 axis_size * num_axes + 998 instance_size * num_instances > fvar_len ) 999 num_instances = 0; 1000 else 1001 face->variation_support |= TT_FACE_FLAG_VAR_FVAR; 1002 1003 /* 1004 * As documented in the OpenType specification, an entry for the 1005 * default instance may be omitted in the named instance table. In 1006 * particular this means that even if there is no named instance 1007 * table in the font we actually do have a named instance, namely the 1008 * default instance. 1009 * 1010 * For consistency, we always want the default instance in our list 1011 * of named instances. If it is missing, we try to synthesize it 1012 * later on. Here, we have to adjust `num_instances' accordingly. 1013 */ 1014 1015 if ( ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) && 1016 !( FT_ALLOC( default_values, num_axes * 4 ) || 1017 FT_ALLOC( instance_values, num_axes * 4 ) ) ) 1018 { 1019 /* the current stream position is 16 bytes after the table start */ 1020 FT_ULong array_start = FT_STREAM_POS() - 16 + offset; 1021 FT_ULong default_value_offset, instance_offset; 1022 1023 FT_Byte* p; 1024 FT_UInt i; 1025 1026 1027 default_value_offset = array_start + 8; 1028 p = default_values; 1029 1030 for ( i = 0; i < num_axes; i++ ) 1031 { 1032 (void)FT_STREAM_READ_AT( default_value_offset, p, 4 ); 1033 1034 default_value_offset += axis_size; 1035 p += 4; 1036 } 1037 1038 instance_offset = array_start + axis_size * num_axes + 4; 1039 1040 for ( i = 0; i < num_instances; i++ ) 1041 { 1042 (void)FT_STREAM_READ_AT( instance_offset, 1043 instance_values, 1044 num_axes * 4 ); 1045 1046 if ( !ft_memcmp( default_values, instance_values, num_axes * 4 ) ) 1047 break; 1048 1049 instance_offset += instance_size; 1050 } 1051 1052 if ( i == num_instances ) 1053 { 1054 /* no default instance in named instance table; */ 1055 /* we thus have to synthesize it */ 1056 num_instances++; 1057 } 1058 } 1059 1060 FT_FREE( default_values ); 1061 FT_FREE( instance_values ); 1062 1063 /* we don't support Multiple Master CFFs yet; */ 1064 /* note that `glyf' or `CFF2' have precedence */ 1065 if ( face->goto_table( face, TTAG_glyf, stream, 0 ) && 1066 face->goto_table( face, TTAG_CFF2, stream, 0 ) && 1067 !face->goto_table( face, TTAG_CFF, stream, 0 ) ) 1068 num_instances = 0; 1069 1070 /* instance indices in `face_instance_index' start with index 1, */ 1071 /* thus `>' and not `>=' */ 1072 if ( instance_index > num_instances ) 1073 { 1074 if ( face_instance_index >= 0 ) 1075 return FT_THROW( Invalid_Argument ); 1076 else 1077 num_instances = 0; 1078 } 1079 1080 face->root.style_flags = (FT_Long)num_instances << 16; 1081 } 1082 #endif 1083 1084 face->root.num_faces = face->ttc_header.count; 1085 face->root.face_index = face_instance_index; 1086 1087 return error; 1088 } 1089 1090 1091 #define LOAD_( x ) \ 1092 do \ 1093 { \ 1094 FT_TRACE2(( "`" #x "' " )); \ 1095 FT_TRACE3(( "-->\n" )); \ 1096 \ 1097 error = sfnt->load_ ## x( face, stream ); \ 1098 \ 1099 FT_TRACE2(( "%s\n", ( !error ) \ 1100 ? "loaded" \ 1101 : FT_ERR_EQ( error, Table_Missing ) \ 1102 ? "missing" \ 1103 : "failed to load" )); \ 1104 FT_TRACE3(( "\n" )); \ 1105 } while ( 0 ) 1106 1107 #define LOADM_( x, vertical ) \ 1108 do \ 1109 { \ 1110 FT_TRACE2(( "`%s" #x "' ", \ 1111 vertical ? "vertical " : "" )); \ 1112 FT_TRACE3(( "-->\n" )); \ 1113 \ 1114 error = sfnt->load_ ## x( face, stream, vertical ); \ 1115 \ 1116 FT_TRACE2(( "%s\n", ( !error ) \ 1117 ? "loaded" \ 1118 : FT_ERR_EQ( error, Table_Missing ) \ 1119 ? "missing" \ 1120 : "failed to load" )); \ 1121 FT_TRACE3(( "\n" )); \ 1122 } while ( 0 ) 1123 1124 #define GET_NAME( id, field ) \ 1125 do \ 1126 { \ 1127 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ 1128 if ( error ) \ 1129 goto Exit; \ 1130 } while ( 0 ) 1131 1132 1133 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)1134 sfnt_load_face( FT_Stream stream, 1135 TT_Face face, 1136 FT_Int face_instance_index, 1137 FT_Int num_params, 1138 FT_Parameter* params ) 1139 { 1140 FT_Error error; 1141 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1142 FT_Error psnames_error; 1143 #endif 1144 FT_Bool has_outline; 1145 FT_Bool is_apple_sbit; 1146 FT_Bool is_apple_sbix; 1147 FT_Bool ignore_typographic_family = FALSE; 1148 FT_Bool ignore_typographic_subfamily = FALSE; 1149 1150 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 1151 1152 FT_UNUSED( face_instance_index ); 1153 1154 1155 /* Check parameters */ 1156 1157 { 1158 FT_Int i; 1159 1160 1161 for ( i = 0; i < num_params; i++ ) 1162 { 1163 if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_FAMILY ) 1164 ignore_typographic_family = TRUE; 1165 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_TYPOGRAPHIC_SUBFAMILY ) 1166 ignore_typographic_subfamily = TRUE; 1167 } 1168 } 1169 1170 /* Load tables */ 1171 1172 /* We now support two SFNT-based bitmapped font formats. They */ 1173 /* are recognized easily as they do not include a `glyf' */ 1174 /* table. */ 1175 /* */ 1176 /* The first format comes from Apple, and uses a table named */ 1177 /* `bhed' instead of `head' to store the font header (using */ 1178 /* the same format). It also doesn't include horizontal and */ 1179 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 1180 /* missing). */ 1181 /* */ 1182 /* The other format comes from Microsoft, and is used with */ 1183 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 1184 /* it doesn't contain outlines. */ 1185 /* */ 1186 1187 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); 1188 1189 /* do we have outlines in there? */ 1190 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1191 has_outline = FT_BOOL( face->root.internal->incremental_interface || 1192 tt_face_lookup_table( face, TTAG_glyf ) || 1193 tt_face_lookup_table( face, TTAG_CFF ) || 1194 tt_face_lookup_table( face, TTAG_CFF2 ) ); 1195 #else 1196 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) || 1197 tt_face_lookup_table( face, TTAG_CFF ) || 1198 tt_face_lookup_table( face, TTAG_CFF2 ) ); 1199 #endif 1200 1201 is_apple_sbit = 0; 1202 is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); 1203 1204 /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' 1205 * outline rendered on top. We don't support that yet, so just ignore 1206 * the 'glyf' outline and advertise it as a bitmap-only font. */ 1207 if ( is_apple_sbix ) 1208 has_outline = FALSE; 1209 1210 /* if this font doesn't contain outlines, we try to load */ 1211 /* a `bhed' table */ 1212 if ( !has_outline && sfnt->load_bhed ) 1213 { 1214 LOAD_( bhed ); 1215 is_apple_sbit = FT_BOOL( !error ); 1216 } 1217 1218 /* load the font header (`head' table) if this isn't an Apple */ 1219 /* sbit font file */ 1220 if ( !is_apple_sbit || is_apple_sbix ) 1221 { 1222 LOAD_( head ); 1223 if ( error ) 1224 goto Exit; 1225 } 1226 1227 /* OpenType 1.8.2 introduced limits to this value; */ 1228 /* however, they make sense for older SFNT fonts also */ 1229 if ( face->header.Units_Per_EM < 16 || 1230 face->header.Units_Per_EM > 16384 ) 1231 { 1232 error = FT_THROW( Invalid_Table ); 1233 1234 goto Exit; 1235 } 1236 1237 /* the following tables are often not present in embedded TrueType */ 1238 /* fonts within PDF documents, so don't check for them. */ 1239 LOAD_( maxp ); 1240 LOAD_( cmap ); 1241 1242 /* the following tables are optional in PCL fonts -- */ 1243 /* don't check for errors */ 1244 LOAD_( name ); 1245 LOAD_( post ); 1246 1247 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1248 psnames_error = error; 1249 #endif 1250 1251 /* do not load the metrics headers and tables if this is an Apple */ 1252 /* sbit font file */ 1253 if ( !is_apple_sbit ) 1254 { 1255 /* load the `hhea' and `hmtx' tables */ 1256 LOADM_( hhea, 0 ); 1257 if ( !error ) 1258 { 1259 LOADM_( hmtx, 0 ); 1260 if ( FT_ERR_EQ( error, Table_Missing ) ) 1261 { 1262 error = FT_THROW( Hmtx_Table_Missing ); 1263 1264 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1265 /* If this is an incrementally loaded font and there are */ 1266 /* overriding metrics, tolerate a missing `hmtx' table. */ 1267 if ( face->root.internal->incremental_interface && 1268 face->root.internal->incremental_interface->funcs-> 1269 get_glyph_metrics ) 1270 { 1271 face->horizontal.number_Of_HMetrics = 0; 1272 error = FT_Err_Ok; 1273 } 1274 #endif 1275 } 1276 } 1277 else if ( FT_ERR_EQ( error, Table_Missing ) ) 1278 { 1279 /* No `hhea' table necessary for SFNT Mac fonts. */ 1280 if ( face->format_tag == TTAG_true ) 1281 { 1282 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 1283 1284 has_outline = 0; 1285 error = FT_Err_Ok; 1286 } 1287 else 1288 { 1289 error = FT_THROW( Horiz_Header_Missing ); 1290 1291 #ifdef FT_CONFIG_OPTION_INCREMENTAL 1292 /* If this is an incrementally loaded font and there are */ 1293 /* overriding metrics, tolerate a missing `hhea' table. */ 1294 if ( face->root.internal->incremental_interface && 1295 face->root.internal->incremental_interface->funcs-> 1296 get_glyph_metrics ) 1297 { 1298 face->horizontal.number_Of_HMetrics = 0; 1299 error = FT_Err_Ok; 1300 } 1301 #endif 1302 1303 } 1304 } 1305 1306 if ( error ) 1307 goto Exit; 1308 1309 /* try to load the `vhea' and `vmtx' tables */ 1310 LOADM_( hhea, 1 ); 1311 if ( !error ) 1312 { 1313 LOADM_( hmtx, 1 ); 1314 if ( !error ) 1315 face->vertical_info = 1; 1316 } 1317 1318 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 1319 goto Exit; 1320 1321 LOAD_( os2 ); 1322 if ( error ) 1323 { 1324 /* we treat the table as missing if there are any errors */ 1325 face->os2.version = 0xFFFFU; 1326 } 1327 } 1328 1329 /* the optional tables */ 1330 1331 /* embedded bitmap support */ 1332 if ( sfnt->load_eblc ) 1333 LOAD_( eblc ); 1334 1335 /* consider the pclt, kerning, and gasp tables as optional */ 1336 LOAD_( pclt ); 1337 LOAD_( gasp ); 1338 LOAD_( kern ); 1339 1340 face->root.num_glyphs = face->max_profile.numGlyphs; 1341 1342 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 1343 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 1344 /* `slope', a term used by Microsoft's Windows Presentation */ 1345 /* Foundation (WPF). This flag has been introduced in version */ 1346 /* 1.5 of the OpenType specification (May 2008). */ 1347 1348 face->root.family_name = NULL; 1349 face->root.style_name = NULL; 1350 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 1351 { 1352 if ( !ignore_typographic_family ) 1353 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1354 if ( !face->root.family_name ) 1355 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1356 1357 if ( !ignore_typographic_subfamily ) 1358 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1359 if ( !face->root.style_name ) 1360 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1361 } 1362 else 1363 { 1364 GET_NAME( WWS_FAMILY, &face->root.family_name ); 1365 if ( !face->root.family_name && !ignore_typographic_family ) 1366 GET_NAME( TYPOGRAPHIC_FAMILY, &face->root.family_name ); 1367 if ( !face->root.family_name ) 1368 GET_NAME( FONT_FAMILY, &face->root.family_name ); 1369 1370 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 1371 if ( !face->root.style_name && !ignore_typographic_subfamily ) 1372 GET_NAME( TYPOGRAPHIC_SUBFAMILY, &face->root.style_name ); 1373 if ( !face->root.style_name ) 1374 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 1375 } 1376 1377 /* now set up root fields */ 1378 { 1379 FT_Face root = &face->root; 1380 FT_Long flags = root->face_flags; 1381 1382 1383 /*********************************************************************/ 1384 /* */ 1385 /* Compute face flags. */ 1386 /* */ 1387 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || 1388 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ) 1389 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ 1390 1391 if ( has_outline == TRUE ) 1392 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 1393 1394 /* The sfnt driver only supports bitmap fonts natively, thus we */ 1395 /* don't set FT_FACE_FLAG_HINTER. */ 1396 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 1397 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 1398 1399 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 1400 if ( !psnames_error && 1401 face->postscript.FormatType != 0x00030000L ) 1402 flags |= FT_FACE_FLAG_GLYPH_NAMES; 1403 #endif 1404 1405 /* fixed width font? */ 1406 if ( face->postscript.isFixedPitch ) 1407 flags |= FT_FACE_FLAG_FIXED_WIDTH; 1408 1409 /* vertical information? */ 1410 if ( face->vertical_info ) 1411 flags |= FT_FACE_FLAG_VERTICAL; 1412 1413 /* kerning available ? */ 1414 if ( TT_FACE_HAS_KERNING( face ) ) 1415 flags |= FT_FACE_FLAG_KERNING; 1416 1417 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1418 /* Don't bother to load the tables unless somebody asks for them. */ 1419 /* No need to do work which will (probably) not be used. */ 1420 if ( face->variation_support & TT_FACE_FLAG_VAR_FVAR ) 1421 { 1422 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && 1423 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) 1424 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1425 if ( tt_face_lookup_table( face, TTAG_CFF2 ) != 0 ) 1426 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 1427 } 1428 #endif 1429 1430 root->face_flags = flags; 1431 1432 /*********************************************************************/ 1433 /* */ 1434 /* Compute style flags. */ 1435 /* */ 1436 1437 flags = 0; 1438 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 1439 { 1440 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 1441 /* indicates an oblique font face. This flag has been */ 1442 /* introduced in version 1.5 of the OpenType specification. */ 1443 1444 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 1445 flags |= FT_STYLE_FLAG_ITALIC; 1446 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 1447 flags |= FT_STYLE_FLAG_ITALIC; 1448 1449 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 1450 flags |= FT_STYLE_FLAG_BOLD; 1451 } 1452 else 1453 { 1454 /* this is an old Mac font, use the header field */ 1455 1456 if ( face->header.Mac_Style & 1 ) 1457 flags |= FT_STYLE_FLAG_BOLD; 1458 1459 if ( face->header.Mac_Style & 2 ) 1460 flags |= FT_STYLE_FLAG_ITALIC; 1461 } 1462 1463 root->style_flags |= flags; 1464 1465 /*********************************************************************/ 1466 /* */ 1467 /* Polish the charmaps. */ 1468 /* */ 1469 /* Try to set the charmap encoding according to the platform & */ 1470 /* encoding ID of each charmap. Emulate Unicode charmap if one */ 1471 /* is missing. */ 1472 /* */ 1473 1474 tt_face_build_cmaps( face ); /* ignore errors */ 1475 1476 1477 /* set the encoding fields */ 1478 { 1479 FT_Int m; 1480 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1481 FT_Bool has_unicode = FALSE; 1482 #endif 1483 1484 1485 for ( m = 0; m < root->num_charmaps; m++ ) 1486 { 1487 FT_CharMap charmap = root->charmaps[m]; 1488 1489 1490 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 1491 charmap->encoding_id ); 1492 1493 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 1494 1495 if ( charmap->encoding == FT_ENCODING_UNICODE || 1496 charmap->encoding == FT_ENCODING_MS_SYMBOL ) /* PUA */ 1497 has_unicode = TRUE; 1498 } 1499 1500 /* synthesize Unicode charmap if one is missing */ 1501 if ( !has_unicode ) 1502 { 1503 FT_CharMapRec cmaprec; 1504 1505 1506 cmaprec.face = root; 1507 cmaprec.platform_id = TT_PLATFORM_MICROSOFT; 1508 cmaprec.encoding_id = TT_MS_ID_UNICODE_CS; 1509 cmaprec.encoding = FT_ENCODING_UNICODE; 1510 1511 1512 error = FT_CMap_New( (FT_CMap_Class)&tt_cmap_unicode_class_rec, 1513 NULL, &cmaprec, NULL ); 1514 if ( error && 1515 FT_ERR_NEQ( error, No_Unicode_Glyph_Name ) ) 1516 goto Exit; 1517 error = FT_Err_Ok; 1518 1519 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 1520 1521 } 1522 } 1523 1524 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 1525 1526 /* 1527 * Now allocate the root array of FT_Bitmap_Size records and 1528 * populate them. Unfortunately, it isn't possible to indicate bit 1529 * depths in the FT_Bitmap_Size record. This is a design error. 1530 */ 1531 { 1532 FT_UInt count; 1533 1534 1535 count = face->sbit_num_strikes; 1536 1537 if ( count > 0 ) 1538 { 1539 FT_Memory memory = face->root.stream->memory; 1540 FT_UShort em_size = face->header.Units_Per_EM; 1541 FT_Short avgwidth = face->os2.xAvgCharWidth; 1542 FT_Size_Metrics metrics; 1543 1544 FT_UInt* sbit_strike_map = NULL; 1545 FT_UInt strike_idx, bsize_idx; 1546 1547 1548 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 1549 { 1550 avgwidth = 1; 1551 em_size = 1; 1552 } 1553 1554 /* to avoid invalid strike data in the `available_sizes' field */ 1555 /* of `FT_Face', we map `available_sizes' indices to strike */ 1556 /* indices */ 1557 if ( FT_NEW_ARRAY( root->available_sizes, count ) || 1558 FT_NEW_ARRAY( sbit_strike_map, count ) ) 1559 goto Exit; 1560 1561 bsize_idx = 0; 1562 for ( strike_idx = 0; strike_idx < count; strike_idx++ ) 1563 { 1564 FT_Bitmap_Size* bsize = root->available_sizes + bsize_idx; 1565 1566 1567 error = sfnt->load_strike_metrics( face, strike_idx, &metrics ); 1568 if ( error ) 1569 continue; 1570 1571 bsize->height = (FT_Short)( metrics.height >> 6 ); 1572 bsize->width = (FT_Short)( 1573 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 1574 1575 bsize->x_ppem = metrics.x_ppem << 6; 1576 bsize->y_ppem = metrics.y_ppem << 6; 1577 1578 /* assume 72dpi */ 1579 bsize->size = metrics.y_ppem << 6; 1580 1581 /* only use strikes with valid PPEM values */ 1582 if ( bsize->x_ppem && bsize->y_ppem ) 1583 sbit_strike_map[bsize_idx++] = strike_idx; 1584 } 1585 1586 /* reduce array size to the actually used elements */ 1587 (void)FT_RENEW_ARRAY( sbit_strike_map, count, bsize_idx ); 1588 1589 /* from now on, all strike indices are mapped */ 1590 /* using `sbit_strike_map' */ 1591 if ( bsize_idx ) 1592 { 1593 face->sbit_strike_map = sbit_strike_map; 1594 1595 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 1596 root->num_fixed_sizes = (FT_Int)bsize_idx; 1597 } 1598 } 1599 } 1600 1601 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 1602 1603 /* a font with no bitmaps and no outlines is scalable; */ 1604 /* it has only empty glyphs then */ 1605 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 1606 root->face_flags |= FT_FACE_FLAG_SCALABLE; 1607 1608 1609 /*********************************************************************/ 1610 /* */ 1611 /* Set up metrics. */ 1612 /* */ 1613 if ( FT_IS_SCALABLE( root ) ) 1614 { 1615 /* XXX What about if outline header is missing */ 1616 /* (e.g. sfnt wrapped bitmap)? */ 1617 root->bbox.xMin = face->header.xMin; 1618 root->bbox.yMin = face->header.yMin; 1619 root->bbox.xMax = face->header.xMax; 1620 root->bbox.yMax = face->header.yMax; 1621 root->units_per_EM = face->header.Units_Per_EM; 1622 1623 1624 /* XXX: Computing the ascender/descender/height is very different */ 1625 /* from what the specification tells you. Apparently, we */ 1626 /* must be careful because */ 1627 /* */ 1628 /* - not all fonts have an OS/2 table; in this case, we take */ 1629 /* the values in the horizontal header. However, these */ 1630 /* values very often are not reliable. */ 1631 /* */ 1632 /* - otherwise, the correct typographic values are in the */ 1633 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ 1634 /* */ 1635 /* However, certain fonts have these fields set to 0. */ 1636 /* Rather, they have usWinAscent & usWinDescent correctly */ 1637 /* set (but with different values). */ 1638 /* */ 1639 /* As an example, Arial Narrow is implemented through four */ 1640 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ 1641 /* */ 1642 /* Strangely, all fonts have the same values in their */ 1643 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ 1644 /* */ 1645 /* On the other hand, they all have different */ 1646 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ 1647 /* table cannot be used to compute the text height reliably! */ 1648 /* */ 1649 1650 /* The ascender and descender are taken from the `hhea' table. */ 1651 /* If zero, they are taken from the `OS/2' table. */ 1652 1653 root->ascender = face->horizontal.Ascender; 1654 root->descender = face->horizontal.Descender; 1655 1656 root->height = root->ascender - root->descender + 1657 face->horizontal.Line_Gap; 1658 1659 if ( !( root->ascender || root->descender ) ) 1660 { 1661 if ( face->os2.version != 0xFFFFU ) 1662 { 1663 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) 1664 { 1665 root->ascender = face->os2.sTypoAscender; 1666 root->descender = face->os2.sTypoDescender; 1667 1668 root->height = root->ascender - root->descender + 1669 face->os2.sTypoLineGap; 1670 } 1671 else 1672 { 1673 root->ascender = (FT_Short)face->os2.usWinAscent; 1674 root->descender = -(FT_Short)face->os2.usWinDescent; 1675 1676 root->height = root->ascender - root->descender; 1677 } 1678 } 1679 } 1680 1681 root->max_advance_width = 1682 (FT_Short)face->horizontal.advance_Width_Max; 1683 root->max_advance_height = 1684 (FT_Short)( face->vertical_info ? face->vertical.advance_Height_Max 1685 : root->height ); 1686 1687 /* See https://www.microsoft.com/typography/otspec/post.htm -- */ 1688 /* Adjust underline position from top edge to centre of */ 1689 /* stroke to convert TrueType meaning to FreeType meaning. */ 1690 root->underline_position = face->postscript.underlinePosition - 1691 face->postscript.underlineThickness / 2; 1692 root->underline_thickness = face->postscript.underlineThickness; 1693 } 1694 1695 } 1696 1697 Exit: 1698 FT_TRACE2(( "sfnt_load_face: done\n" )); 1699 1700 return error; 1701 } 1702 1703 1704 #undef LOAD_ 1705 #undef LOADM_ 1706 #undef GET_NAME 1707 1708 1709 FT_LOCAL_DEF( void ) sfnt_done_face(TT_Face face)1710 sfnt_done_face( TT_Face face ) 1711 { 1712 FT_Memory memory; 1713 SFNT_Service sfnt; 1714 1715 1716 if ( !face ) 1717 return; 1718 1719 memory = face->root.memory; 1720 sfnt = (SFNT_Service)face->sfnt; 1721 1722 if ( sfnt ) 1723 { 1724 /* destroy the postscript names table if it is loaded */ 1725 if ( sfnt->free_psnames ) 1726 sfnt->free_psnames( face ); 1727 1728 /* destroy the embedded bitmaps table if it is loaded */ 1729 if ( sfnt->free_eblc ) 1730 sfnt->free_eblc( face ); 1731 } 1732 1733 #ifdef TT_CONFIG_OPTION_BDF 1734 /* freeing the embedded BDF properties */ 1735 tt_face_free_bdf_props( face ); 1736 #endif 1737 1738 /* freeing the kerning table */ 1739 tt_face_done_kern( face ); 1740 1741 /* freeing the collection table */ 1742 FT_FREE( face->ttc_header.offsets ); 1743 face->ttc_header.count = 0; 1744 1745 /* freeing table directory */ 1746 FT_FREE( face->dir_tables ); 1747 face->num_tables = 0; 1748 1749 { 1750 FT_Stream stream = FT_FACE_STREAM( face ); 1751 1752 1753 /* simply release the 'cmap' table frame */ 1754 FT_FRAME_RELEASE( face->cmap_table ); 1755 face->cmap_size = 0; 1756 } 1757 1758 face->horz_metrics_size = 0; 1759 face->vert_metrics_size = 0; 1760 1761 /* freeing vertical metrics, if any */ 1762 if ( face->vertical_info ) 1763 { 1764 FT_FREE( face->vertical.long_metrics ); 1765 FT_FREE( face->vertical.short_metrics ); 1766 face->vertical_info = 0; 1767 } 1768 1769 /* freeing the gasp table */ 1770 FT_FREE( face->gasp.gaspRanges ); 1771 face->gasp.numRanges = 0; 1772 1773 /* freeing the name table */ 1774 if ( sfnt ) 1775 sfnt->free_name( face ); 1776 1777 /* freeing family and style name */ 1778 FT_FREE( face->root.family_name ); 1779 FT_FREE( face->root.style_name ); 1780 1781 /* freeing sbit size table */ 1782 FT_FREE( face->root.available_sizes ); 1783 FT_FREE( face->sbit_strike_map ); 1784 face->root.num_fixed_sizes = 0; 1785 1786 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 1787 FT_FREE( face->postscript_name ); 1788 FT_FREE( face->var_postscript_prefix ); 1789 #endif 1790 1791 face->sfnt = NULL; 1792 } 1793 1794 1795 /* END */ 1796