OLD | NEW |
1 /***************************************************************************/ | 1 /***************************************************************************/ |
2 /* */ | 2 /* */ |
3 /* sfobjs.c */ | 3 /* sfobjs.c */ |
4 /* */ | 4 /* */ |
5 /* SFNT object management (base). */ | 5 /* SFNT object management (base). */ |
6 /* */ | 6 /* */ |
7 /* Copyright 1996-2008, 2010-2013 by */ | 7 /* Copyright 1996-2008, 2010-2014 by */ |
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ |
9 /* */ | 9 /* */ |
10 /* This file is part of the FreeType project, and may only be used, */ | 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 */ | 11 /* modified, and distributed under the terms of the FreeType project */ |
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ |
13 /* this file you indicate that you have read the license and */ | 13 /* this file you indicate that you have read the license and */ |
14 /* understand and accept it fully. */ | 14 /* understand and accept it fully. */ |
15 /* */ | 15 /* */ |
16 /***************************************************************************/ | 16 /***************************************************************************/ |
17 | 17 |
18 | 18 |
19 #include "../../include/ft2build.h" | 19 #include <ft2build.h> |
20 #include "sfobjs.h" | 20 #include "sfobjs.h" |
21 #include "ttload.h" | 21 #include "ttload.h" |
22 #include "ttcmap.h" | 22 #include "ttcmap.h" |
23 #include "ttkern.h" | 23 #include "ttkern.h" |
24 #include "../../include/freetype/internal/sfnt.h" | 24 #include FT_INTERNAL_SFNT_H |
25 #include "../../include/freetype/internal/ftdebug.h" | 25 #include FT_INTERNAL_DEBUG_H |
26 #include "../../include/freetype/ttnameid.h" | 26 #include FT_TRUETYPE_IDS_H |
27 #include "../../include/freetype/tttags.h" | 27 #include FT_TRUETYPE_TAGS_H |
28 #include "../../include/freetype/internal/services/svpscmap.h" | 28 #include FT_SERVICE_POSTSCRIPT_CMAPS_H |
29 #include "../../include/freetype/ftsnames.h" | 29 #include FT_SFNT_NAMES_H |
| 30 #include FT_GZIP_H |
30 #include "sferrors.h" | 31 #include "sferrors.h" |
31 | 32 |
32 #ifdef TT_CONFIG_OPTION_BDF | 33 #ifdef TT_CONFIG_OPTION_BDF |
33 #include "ttbdf.h" | 34 #include "ttbdf.h" |
34 #endif | 35 #endif |
35 | 36 |
36 | 37 |
37 /*************************************************************************/ | 38 /*************************************************************************/ |
38 /* */ | 39 /* */ |
39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | 40 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ |
(...skipping 21 matching lines...) Expand all Loading... |
61 if ( FT_NEW_ARRAY( string, len + 1 ) ) | 62 if ( FT_NEW_ARRAY( string, len + 1 ) ) |
62 return NULL; | 63 return NULL; |
63 | 64 |
64 for ( n = 0; n < len; n++ ) | 65 for ( n = 0; n < len; n++ ) |
65 { | 66 { |
66 code = FT_NEXT_USHORT( read ); | 67 code = FT_NEXT_USHORT( read ); |
67 | 68 |
68 if ( code == 0 ) | 69 if ( code == 0 ) |
69 break; | 70 break; |
70 | 71 |
71 if (code > 255) /*Johnson 2010-10-09, #TESTDOC:0000042_QUT20005_5.pdf.*/ | 72 if ( code < 32 || code > 127 ) |
72 » » code = code>>8&0x00ff; | |
73 » if ( code < 32 || code > 127 ) | |
74 code = '?'; | 73 code = '?'; |
75 | 74 |
76 string[n] = (char)code; | 75 string[n] = (char)code; |
77 } | 76 } |
78 | 77 |
79 string[n] = 0; | 78 string[n] = 0; |
80 | 79 |
81 return string; | 80 return string; |
82 } | 81 } |
83 | 82 |
(...skipping 258 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
342 if ( cur->encoding_id == encoding_id || | 341 if ( cur->encoding_id == encoding_id || |
343 cur->encoding_id == -1 ) | 342 cur->encoding_id == -1 ) |
344 return cur->encoding; | 343 return cur->encoding; |
345 } | 344 } |
346 } | 345 } |
347 | 346 |
348 return FT_ENCODING_NONE; | 347 return FT_ENCODING_NONE; |
349 } | 348 } |
350 | 349 |
351 | 350 |
| 351 #define WRITE_USHORT( p, v ) \ |
| 352 do \ |
| 353 { \ |
| 354 *(p)++ = (FT_Byte)( (v) >> 8 ); \ |
| 355 *(p)++ = (FT_Byte)( (v) >> 0 ); \ |
| 356 \ |
| 357 } while ( 0 ) |
| 358 |
| 359 #define WRITE_ULONG( p, v ) \ |
| 360 do \ |
| 361 { \ |
| 362 *(p)++ = (FT_Byte)( (v) >> 24 ); \ |
| 363 *(p)++ = (FT_Byte)( (v) >> 16 ); \ |
| 364 *(p)++ = (FT_Byte)( (v) >> 8 ); \ |
| 365 *(p)++ = (FT_Byte)( (v) >> 0 ); \ |
| 366 \ |
| 367 } while ( 0 ) |
| 368 |
| 369 |
| 370 static void |
| 371 sfnt_stream_close( FT_Stream stream ) |
| 372 { |
| 373 FT_Memory memory = stream->memory; |
| 374 |
| 375 |
| 376 FT_FREE( stream->base ); |
| 377 |
| 378 stream->size = 0; |
| 379 stream->base = 0; |
| 380 stream->close = 0; |
| 381 } |
| 382 |
| 383 |
| 384 FT_CALLBACK_DEF( int ) |
| 385 compare_offsets( const void* a, |
| 386 const void* b ) |
| 387 { |
| 388 WOFF_Table table1 = *(WOFF_Table*)a; |
| 389 WOFF_Table table2 = *(WOFF_Table*)b; |
| 390 |
| 391 FT_ULong offset1 = table1->Offset; |
| 392 FT_ULong offset2 = table2->Offset; |
| 393 |
| 394 |
| 395 if ( offset1 > offset2 ) |
| 396 return 1; |
| 397 else if ( offset1 < offset2 ) |
| 398 return -1; |
| 399 else |
| 400 return 0; |
| 401 } |
| 402 |
| 403 |
| 404 /* Replace `face->root.stream' with a stream containing the extracted */ |
| 405 /* SFNT of a WOFF font. */ |
| 406 |
| 407 static FT_Error |
| 408 woff_open_font( FT_Stream stream, |
| 409 TT_Face face ) |
| 410 { |
| 411 FT_Memory memory = stream->memory; |
| 412 FT_Error error = FT_Err_Ok; |
| 413 |
| 414 WOFF_HeaderRec woff; |
| 415 WOFF_Table tables = NULL; |
| 416 WOFF_Table* indices = NULL; |
| 417 |
| 418 FT_ULong woff_offset; |
| 419 |
| 420 FT_Byte* sfnt = NULL; |
| 421 FT_Stream sfnt_stream = NULL; |
| 422 |
| 423 FT_Byte* sfnt_header; |
| 424 FT_ULong sfnt_offset; |
| 425 |
| 426 FT_Int nn; |
| 427 FT_ULong old_tag = 0; |
| 428 |
| 429 static const FT_Frame_Field woff_header_fields[] = |
| 430 { |
| 431 #undef FT_STRUCTURE |
| 432 #define FT_STRUCTURE WOFF_HeaderRec |
| 433 |
| 434 FT_FRAME_START( 44 ), |
| 435 FT_FRAME_ULONG ( signature ), |
| 436 FT_FRAME_ULONG ( flavor ), |
| 437 FT_FRAME_ULONG ( length ), |
| 438 FT_FRAME_USHORT( num_tables ), |
| 439 FT_FRAME_USHORT( reserved ), |
| 440 FT_FRAME_ULONG ( totalSfntSize ), |
| 441 FT_FRAME_USHORT( majorVersion ), |
| 442 FT_FRAME_USHORT( minorVersion ), |
| 443 FT_FRAME_ULONG ( metaOffset ), |
| 444 FT_FRAME_ULONG ( metaLength ), |
| 445 FT_FRAME_ULONG ( metaOrigLength ), |
| 446 FT_FRAME_ULONG ( privOffset ), |
| 447 FT_FRAME_ULONG ( privLength ), |
| 448 FT_FRAME_END |
| 449 }; |
| 450 |
| 451 |
| 452 FT_ASSERT( stream == face->root.stream ); |
| 453 FT_ASSERT( FT_STREAM_POS() == 0 ); |
| 454 |
| 455 if ( FT_STREAM_READ_FIELDS( woff_header_fields, &woff ) ) |
| 456 return error; |
| 457 |
| 458 /* Make sure we don't recurse back here or hit TTC code. */ |
| 459 if ( woff.flavor == TTAG_wOFF || woff.flavor == TTAG_ttcf ) |
| 460 return FT_THROW( Invalid_Table ); |
| 461 |
| 462 /* Miscellaneous checks. */ |
| 463 if ( woff.length != stream->size || |
| 464 woff.num_tables == 0 || |
| 465 44 + woff.num_tables * 20UL >= woff.length || |
| 466 12 + woff.num_tables * 16UL >= woff.totalSfntSize || |
| 467 ( woff.totalSfntSize & 3 ) != 0 || |
| 468 ( woff.metaOffset == 0 && ( woff.metaLength != 0 || |
| 469 woff.metaOrigLength != 0 ) ) || |
| 470 ( woff.metaLength != 0 && woff.metaOrigLength == 0 ) || |
| 471 ( woff.privOffset == 0 && woff.privLength != 0 ) ) |
| 472 return FT_THROW( Invalid_Table ); |
| 473 |
| 474 if ( FT_ALLOC( sfnt, woff.totalSfntSize ) || |
| 475 FT_NEW( sfnt_stream ) ) |
| 476 goto Exit; |
| 477 |
| 478 sfnt_header = sfnt; |
| 479 |
| 480 /* Write sfnt header. */ |
| 481 { |
| 482 FT_UInt searchRange, entrySelector, rangeShift, x; |
| 483 |
| 484 |
| 485 x = woff.num_tables; |
| 486 entrySelector = 0; |
| 487 while ( x ) |
| 488 { |
| 489 x >>= 1; |
| 490 entrySelector += 1; |
| 491 } |
| 492 entrySelector--; |
| 493 |
| 494 searchRange = ( 1 << entrySelector ) * 16; |
| 495 rangeShift = woff.num_tables * 16 - searchRange; |
| 496 |
| 497 WRITE_ULONG ( sfnt_header, woff.flavor ); |
| 498 WRITE_USHORT( sfnt_header, woff.num_tables ); |
| 499 WRITE_USHORT( sfnt_header, searchRange ); |
| 500 WRITE_USHORT( sfnt_header, entrySelector ); |
| 501 WRITE_USHORT( sfnt_header, rangeShift ); |
| 502 } |
| 503 |
| 504 /* While the entries in the sfnt header must be sorted by the */ |
| 505 /* tag value, the tables themselves are not. We thus have to */ |
| 506 /* sort them by offset and check that they don't overlap. */ |
| 507 |
| 508 if ( FT_NEW_ARRAY( tables, woff.num_tables ) || |
| 509 FT_NEW_ARRAY( indices, woff.num_tables ) ) |
| 510 goto Exit; |
| 511 |
| 512 FT_TRACE2(( "\n" |
| 513 " tag offset compLen origLen checksum\n" |
| 514 " -------------------------------------------\n" )); |
| 515 |
| 516 if ( FT_FRAME_ENTER( 20L * woff.num_tables ) ) |
| 517 goto Exit; |
| 518 |
| 519 for ( nn = 0; nn < woff.num_tables; nn++ ) |
| 520 { |
| 521 WOFF_Table table = tables + nn; |
| 522 |
| 523 table->Tag = FT_GET_TAG4(); |
| 524 table->Offset = FT_GET_ULONG(); |
| 525 table->CompLength = FT_GET_ULONG(); |
| 526 table->OrigLength = FT_GET_ULONG(); |
| 527 table->CheckSum = FT_GET_ULONG(); |
| 528 |
| 529 FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx %08lx\n", |
| 530 (FT_Char)( table->Tag >> 24 ), |
| 531 (FT_Char)( table->Tag >> 16 ), |
| 532 (FT_Char)( table->Tag >> 8 ), |
| 533 (FT_Char)( table->Tag ), |
| 534 table->Offset, |
| 535 table->CompLength, |
| 536 table->OrigLength, |
| 537 table->CheckSum )); |
| 538 |
| 539 if ( table->Tag <= old_tag ) |
| 540 { |
| 541 FT_FRAME_EXIT(); |
| 542 error = FT_THROW( Invalid_Table ); |
| 543 goto Exit; |
| 544 } |
| 545 |
| 546 old_tag = table->Tag; |
| 547 indices[nn] = table; |
| 548 } |
| 549 |
| 550 FT_FRAME_EXIT(); |
| 551 |
| 552 /* Sort by offset. */ |
| 553 |
| 554 ft_qsort( indices, |
| 555 woff.num_tables, |
| 556 sizeof ( WOFF_Table ), |
| 557 compare_offsets ); |
| 558 |
| 559 /* Check offsets and lengths. */ |
| 560 |
| 561 woff_offset = 44 + woff.num_tables * 20L; |
| 562 sfnt_offset = 12 + woff.num_tables * 16L; |
| 563 |
| 564 for ( nn = 0; nn < woff.num_tables; nn++ ) |
| 565 { |
| 566 WOFF_Table table = indices[nn]; |
| 567 |
| 568 |
| 569 if ( table->Offset != woff_offset || |
| 570 table->CompLength > woff.length || |
| 571 table->Offset > woff.length - table->CompLength || |
| 572 table->OrigLength > woff.totalSfntSize || |
| 573 sfnt_offset > woff.totalSfntSize - table->OrigLength || |
| 574 table->CompLength > table->OrigLength ) |
| 575 { |
| 576 error = FT_THROW( Invalid_Table ); |
| 577 goto Exit; |
| 578 } |
| 579 |
| 580 table->OrigOffset = sfnt_offset; |
| 581 |
| 582 /* The offsets must be multiples of 4. */ |
| 583 woff_offset += ( table->CompLength + 3 ) & ~3; |
| 584 sfnt_offset += ( table->OrigLength + 3 ) & ~3; |
| 585 } |
| 586 |
| 587 /* |
| 588 * Final checks! |
| 589 * |
| 590 * We don't decode and check the metadata block. |
| 591 * We don't check table checksums either. |
| 592 * But other than those, I think we implement all |
| 593 * `MUST' checks from the spec. |
| 594 */ |
| 595 |
| 596 if ( woff.metaOffset ) |
| 597 { |
| 598 if ( woff.metaOffset != woff_offset || |
| 599 woff.metaOffset + woff.metaLength > woff.length ) |
| 600 { |
| 601 error = FT_THROW( Invalid_Table ); |
| 602 goto Exit; |
| 603 } |
| 604 |
| 605 /* We have padding only ... */ |
| 606 woff_offset += woff.metaLength; |
| 607 } |
| 608 |
| 609 if ( woff.privOffset ) |
| 610 { |
| 611 /* ... if it isn't the last block. */ |
| 612 woff_offset = ( woff_offset + 3 ) & ~3; |
| 613 |
| 614 if ( woff.privOffset != woff_offset || |
| 615 woff.privOffset + woff.privLength > woff.length ) |
| 616 { |
| 617 error = FT_THROW( Invalid_Table ); |
| 618 goto Exit; |
| 619 } |
| 620 |
| 621 /* No padding for the last block. */ |
| 622 woff_offset += woff.privLength; |
| 623 } |
| 624 |
| 625 if ( sfnt_offset != woff.totalSfntSize || |
| 626 woff_offset != woff.length ) |
| 627 { |
| 628 error = FT_THROW( Invalid_Table ); |
| 629 goto Exit; |
| 630 } |
| 631 |
| 632 /* Write the tables. */ |
| 633 |
| 634 for ( nn = 0; nn < woff.num_tables; nn++ ) |
| 635 { |
| 636 WOFF_Table table = tables + nn; |
| 637 |
| 638 |
| 639 /* Write SFNT table entry. */ |
| 640 WRITE_ULONG( sfnt_header, table->Tag ); |
| 641 WRITE_ULONG( sfnt_header, table->CheckSum ); |
| 642 WRITE_ULONG( sfnt_header, table->OrigOffset ); |
| 643 WRITE_ULONG( sfnt_header, table->OrigLength ); |
| 644 |
| 645 /* Write table data. */ |
| 646 if ( FT_STREAM_SEEK( table->Offset ) || |
| 647 FT_FRAME_ENTER( table->CompLength ) ) |
| 648 goto Exit; |
| 649 |
| 650 if ( table->CompLength == table->OrigLength ) |
| 651 { |
| 652 /* Uncompressed data; just copy. */ |
| 653 ft_memcpy( sfnt + table->OrigOffset, |
| 654 stream->cursor, |
| 655 table->OrigLength ); |
| 656 } |
| 657 else |
| 658 { |
| 659 #ifdef FT_CONFIG_OPTION_USE_ZLIB |
| 660 |
| 661 /* Uncompress with zlib. */ |
| 662 FT_ULong output_len = table->OrigLength; |
| 663 |
| 664 |
| 665 error = FT_Gzip_Uncompress( memory, |
| 666 sfnt + table->OrigOffset, &output_len, |
| 667 stream->cursor, table->CompLength ); |
| 668 if ( error ) |
| 669 goto Exit; |
| 670 if ( output_len != table->OrigLength ) |
| 671 { |
| 672 error = FT_THROW( Invalid_Table ); |
| 673 goto Exit; |
| 674 } |
| 675 |
| 676 #else /* !FT_CONFIG_OPTION_USE_ZLIB */ |
| 677 |
| 678 error = FT_THROW( Unimplemented_Feature ); |
| 679 goto Exit; |
| 680 |
| 681 #endif /* !FT_CONFIG_OPTION_USE_ZLIB */ |
| 682 } |
| 683 |
| 684 FT_FRAME_EXIT(); |
| 685 |
| 686 /* We don't check whether the padding bytes in the WOFF file are */ |
| 687 /* actually '\0'. For the output, however, we do set them properly. */ |
| 688 sfnt_offset = table->OrigOffset + table->OrigLength; |
| 689 while ( sfnt_offset & 3 ) |
| 690 { |
| 691 sfnt[sfnt_offset] = '\0'; |
| 692 sfnt_offset++; |
| 693 } |
| 694 } |
| 695 |
| 696 /* Ok! Finally ready. Swap out stream and return. */ |
| 697 FT_Stream_OpenMemory( sfnt_stream, sfnt, woff.totalSfntSize ); |
| 698 sfnt_stream->memory = stream->memory; |
| 699 sfnt_stream->close = sfnt_stream_close; |
| 700 |
| 701 FT_Stream_Free( |
| 702 face->root.stream, |
| 703 ( face->root.face_flags & FT_FACE_FLAG_EXTERNAL_STREAM ) != 0 ); |
| 704 |
| 705 face->root.stream = sfnt_stream; |
| 706 |
| 707 face->root.face_flags &= ~FT_FACE_FLAG_EXTERNAL_STREAM; |
| 708 |
| 709 Exit: |
| 710 FT_FREE( tables ); |
| 711 FT_FREE( indices ); |
| 712 |
| 713 if ( error ) |
| 714 { |
| 715 FT_FREE( sfnt ); |
| 716 FT_Stream_Close( sfnt_stream ); |
| 717 FT_FREE( sfnt_stream ); |
| 718 } |
| 719 |
| 720 return error; |
| 721 } |
| 722 |
| 723 |
| 724 #undef WRITE_USHORT |
| 725 #undef WRITE_ULONG |
| 726 |
| 727 |
352 /* Fill in face->ttc_header. If the font is not a TTC, it is */ | 728 /* Fill in face->ttc_header. If the font is not a TTC, it is */ |
353 /* synthesized into a TTC with one offset table. */ | 729 /* synthesized into a TTC with one offset table. */ |
354 static FT_Error | 730 static FT_Error |
355 sfnt_open_font( FT_Stream stream, | 731 sfnt_open_font( FT_Stream stream, |
356 TT_Face face ) | 732 TT_Face face ) |
357 { | 733 { |
358 FT_Memory memory = stream->memory; | 734 FT_Memory memory = stream->memory; |
359 FT_Error error; | 735 FT_Error error; |
360 FT_ULong tag, offset; | 736 FT_ULong tag, offset; |
361 | 737 |
362 static const FT_Frame_Field ttc_header_fields[] = | 738 static const FT_Frame_Field ttc_header_fields[] = |
363 { | 739 { |
364 #undef FT_STRUCTURE | 740 #undef FT_STRUCTURE |
365 #define FT_STRUCTURE TTC_HeaderRec | 741 #define FT_STRUCTURE TTC_HeaderRec |
366 | 742 |
367 FT_FRAME_START( 8 ), | 743 FT_FRAME_START( 8 ), |
368 FT_FRAME_LONG( version ), | 744 FT_FRAME_LONG( version ), |
369 FT_FRAME_LONG( count ), /* this is ULong in the specs */ | 745 FT_FRAME_LONG( count ), /* this is ULong in the specs */ |
370 FT_FRAME_END | 746 FT_FRAME_END |
371 }; | 747 }; |
372 | 748 |
373 | 749 |
374 face->ttc_header.tag = 0; | 750 face->ttc_header.tag = 0; |
375 face->ttc_header.version = 0; | 751 face->ttc_header.version = 0; |
376 face->ttc_header.count = 0; | 752 face->ttc_header.count = 0; |
377 | 753 |
| 754 retry: |
378 offset = FT_STREAM_POS(); | 755 offset = FT_STREAM_POS(); |
379 | 756 |
380 if ( FT_READ_ULONG( tag ) ) | 757 if ( FT_READ_ULONG( tag ) ) |
381 return error; | 758 return error; |
382 | 759 |
| 760 if ( tag == TTAG_wOFF ) |
| 761 { |
| 762 FT_TRACE2(( "sfnt_open_font: file is a WOFF; synthesizing SFNT\n" )); |
| 763 |
| 764 if ( FT_STREAM_SEEK( offset ) ) |
| 765 return error; |
| 766 |
| 767 error = woff_open_font( stream, face ); |
| 768 if ( error ) |
| 769 return error; |
| 770 |
| 771 /* Swap out stream and retry! */ |
| 772 stream = face->root.stream; |
| 773 goto retry; |
| 774 } |
| 775 |
383 if ( tag != 0x00010000UL && | 776 if ( tag != 0x00010000UL && |
384 tag != TTAG_ttcf && | 777 tag != TTAG_ttcf && |
385 tag != TTAG_OTTO && | 778 tag != TTAG_OTTO && |
386 tag != TTAG_true && | 779 tag != TTAG_true && |
387 tag != TTAG_typ1 && | 780 tag != TTAG_typ1 && |
388 tag != 0x00020000UL ) | 781 tag != 0x00020000UL ) |
389 { | 782 { |
390 FT_TRACE2(( " not a font using the SFNT container format\n" )); | 783 FT_TRACE2(( " not a font using the SFNT container format\n" )); |
391 return FT_THROW( Unknown_File_Format ); | 784 return FT_THROW( Unknown_File_Format ); |
392 } | 785 } |
(...skipping 82 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
475 } | 868 } |
476 | 869 |
477 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); | 870 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); |
478 | 871 |
479 FT_TRACE2(( "SFNT driver\n" )); | 872 FT_TRACE2(( "SFNT driver\n" )); |
480 | 873 |
481 error = sfnt_open_font( stream, face ); | 874 error = sfnt_open_font( stream, face ); |
482 if ( error ) | 875 if ( error ) |
483 return error; | 876 return error; |
484 | 877 |
| 878 /* Stream may have changed in sfnt_open_font. */ |
| 879 stream = face->root.stream; |
| 880 |
485 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); | 881 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); |
486 | 882 |
487 if ( face_index < 0 ) | 883 if ( face_index < 0 ) |
488 face_index = 0; | 884 face_index = 0; |
489 | 885 |
490 if ( face_index >= face->ttc_header.count ) | 886 if ( face_index >= face->ttc_header.count ) |
491 return FT_THROW( Invalid_Argument ); | 887 return FT_THROW( Invalid_Argument ); |
492 | 888 |
493 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) | 889 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) |
494 return error; | 890 return error; |
495 | 891 |
496 /* check that we have a valid TrueType file */ | 892 /* check that we have a valid TrueType file */ |
497 error = sfnt->load_font_dir( face, stream ); | 893 error = sfnt->load_font_dir( face, stream ); |
498 if ( error ) | 894 if ( error ) |
499 return error; | 895 return error; |
500 | 896 |
501 face->root.num_faces = face->ttc_header.count; | 897 face->root.num_faces = face->ttc_header.count; |
502 face->root.face_index = face_index; | 898 face->root.face_index = face_index; |
503 | 899 |
504 return error; | 900 return error; |
505 } | 901 } |
506 | 902 |
507 | 903 |
508 #define LOAD_( x ) \ | 904 #define LOAD_( x ) \ |
509 do { \ | 905 do \ |
| 906 { \ |
510 FT_TRACE2(( "`" #x "' " )); \ | 907 FT_TRACE2(( "`" #x "' " )); \ |
511 FT_TRACE3(( "-->\n" )); \ | 908 FT_TRACE3(( "-->\n" )); \ |
512 \ | 909 \ |
513 error = sfnt->load_ ## x( face, stream ); \ | 910 error = sfnt->load_ ## x( face, stream ); \ |
514 \ | 911 \ |
515 FT_TRACE2(( "%s\n", ( !error ) \ | 912 FT_TRACE2(( "%s\n", ( !error ) \ |
516 ? "loaded" \ | 913 ? "loaded" \ |
517 : FT_ERR_EQ( error, Table_Missing ) \ | 914 : FT_ERR_EQ( error, Table_Missing ) \ |
518 ? "missing" \ | 915 ? "missing" \ |
519 : "failed to load" )); \ | 916 : "failed to load" )); \ |
520 FT_TRACE3(( "\n" )); \ | 917 FT_TRACE3(( "\n" )); \ |
521 } while ( 0 ) | 918 } while ( 0 ) |
522 | 919 |
523 #define LOADM_( x, vertical ) \ | 920 #define LOADM_( x, vertical ) \ |
524 do { \ | 921 do \ |
| 922 { \ |
525 FT_TRACE2(( "`%s" #x "' ", \ | 923 FT_TRACE2(( "`%s" #x "' ", \ |
526 vertical ? "vertical " : "" )); \ | 924 vertical ? "vertical " : "" )); \ |
527 FT_TRACE3(( "-->\n" )); \ | 925 FT_TRACE3(( "-->\n" )); \ |
528 \ | 926 \ |
529 error = sfnt->load_ ## x( face, stream, vertical ); \ | 927 error = sfnt->load_ ## x( face, stream, vertical ); \ |
530 \ | 928 \ |
531 FT_TRACE2(( "%s\n", ( !error ) \ | 929 FT_TRACE2(( "%s\n", ( !error ) \ |
532 ? "loaded" \ | 930 ? "loaded" \ |
533 : FT_ERR_EQ( error, Table_Missing ) \ | 931 : FT_ERR_EQ( error, Table_Missing ) \ |
534 ? "missing" \ | 932 ? "missing" \ |
535 : "failed to load" )); \ | 933 : "failed to load" )); \ |
536 FT_TRACE3(( "\n" )); \ | 934 FT_TRACE3(( "\n" )); \ |
537 } while ( 0 ) | 935 } while ( 0 ) |
538 | 936 |
539 #define GET_NAME( id, field ) \ | 937 #define GET_NAME( id, field ) \ |
540 do { \ | 938 do \ |
| 939 { \ |
541 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ | 940 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ |
542 if ( error ) \ | 941 if ( error ) \ |
543 goto Exit; \ | 942 goto Exit; \ |
544 } while ( 0 ) | 943 } while ( 0 ) |
545 | 944 |
546 | 945 |
547 FT_LOCAL_DEF( FT_Error ) | 946 FT_LOCAL_DEF( FT_Error ) |
548 sfnt_load_face( FT_Stream stream, | 947 sfnt_load_face( FT_Stream stream, |
549 TT_Face face, | 948 TT_Face face, |
550 FT_Int face_index, | 949 FT_Int face_index, |
551 FT_Int num_params, | 950 FT_Int num_params, |
552 FT_Parameter* params ) | 951 FT_Parameter* params ) |
553 { | 952 { |
554 FT_Error error; | 953 FT_Error error; |
555 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | 954 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
556 FT_Error psnames_error; | 955 FT_Error psnames_error; |
557 #endif | 956 #endif |
558 FT_Bool has_outline; | 957 FT_Bool has_outline; |
559 FT_Bool is_apple_sbit; | 958 FT_Bool is_apple_sbit; |
| 959 FT_Bool is_apple_sbix; |
560 FT_Bool ignore_preferred_family = FALSE; | 960 FT_Bool ignore_preferred_family = FALSE; |
561 FT_Bool ignore_preferred_subfamily = FALSE; | 961 FT_Bool ignore_preferred_subfamily = FALSE; |
562 | 962 |
563 SFNT_Service sfnt = (SFNT_Service)face->sfnt; | 963 SFNT_Service sfnt = (SFNT_Service)face->sfnt; |
564 | 964 |
565 FT_UNUSED( face_index ); | 965 FT_UNUSED( face_index ); |
566 | 966 |
567 | 967 |
568 /* Check parameters */ | 968 /* Check parameters */ |
569 | 969 |
(...skipping 33 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
603 #ifdef FT_CONFIG_OPTION_INCREMENTAL | 1003 #ifdef FT_CONFIG_OPTION_INCREMENTAL |
604 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || | 1004 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || |
605 tt_face_lookup_table( face, TTAG_glyf ) != 0 || | 1005 tt_face_lookup_table( face, TTAG_glyf ) != 0 || |
606 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); | 1006 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); |
607 #else | 1007 #else |
608 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || | 1008 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || |
609 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); | 1009 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); |
610 #endif | 1010 #endif |
611 | 1011 |
612 is_apple_sbit = 0; | 1012 is_apple_sbit = 0; |
| 1013 is_apple_sbix = !face->goto_table( face, TTAG_sbix, stream, 0 ); |
| 1014 |
| 1015 /* Apple 'sbix' color bitmaps are rendered scaled and then the 'glyf' |
| 1016 * outline rendered on top. We don't support that yet, so just ignore |
| 1017 * the 'glyf' outline and advertise it as a bitmap-only font. */ |
| 1018 if ( is_apple_sbix ) |
| 1019 has_outline = FALSE; |
613 | 1020 |
614 /* if this font doesn't contain outlines, we try to load */ | 1021 /* if this font doesn't contain outlines, we try to load */ |
615 /* a `bhed' table */ | 1022 /* a `bhed' table */ |
616 if ( !has_outline && sfnt->load_bhed ) | 1023 if ( !has_outline && sfnt->load_bhed ) |
617 { | 1024 { |
618 LOAD_( bhed ); | 1025 LOAD_( bhed ); |
619 is_apple_sbit = FT_BOOL( !error ); | 1026 is_apple_sbit = FT_BOOL( !error ); |
620 } | 1027 } |
621 | 1028 |
622 /* load the font header (`head' table) if this isn't an Apple */ | 1029 /* load the font header (`head' table) if this isn't an Apple */ |
623 /* sbit font file */ | 1030 /* sbit font file */ |
624 if ( !is_apple_sbit ) | 1031 if ( !is_apple_sbit || is_apple_sbix ) |
625 { | 1032 { |
626 LOAD_( head ); | 1033 LOAD_( head ); |
627 if ( error ) | 1034 if ( error ) |
628 goto Exit; | 1035 goto Exit; |
629 } | 1036 } |
630 | 1037 |
631 if ( face->header.Units_Per_EM == 0 ) | 1038 if ( face->header.Units_Per_EM == 0 ) |
632 { | 1039 { |
633 error = FT_THROW( Invalid_Table ); | 1040 error = FT_THROW( Invalid_Table ); |
634 | 1041 |
(...skipping 63 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
698 { | 1105 { |
699 face->horizontal.number_Of_HMetrics = 0; | 1106 face->horizontal.number_Of_HMetrics = 0; |
700 error = FT_Err_Ok; | 1107 error = FT_Err_Ok; |
701 } | 1108 } |
702 #endif | 1109 #endif |
703 | 1110 |
704 } | 1111 } |
705 } | 1112 } |
706 | 1113 |
707 if ( error ) | 1114 if ( error ) |
708 goto Exit; | 1115 goto Exit; |
709 | 1116 |
710 /* try to load the `vhea' and `vmtx' tables */ | 1117 /* try to load the `vhea' and `vmtx' tables */ |
711 LOADM_( hhea, 1 ); | 1118 LOADM_( hhea, 1 ); |
712 if ( !error ) | 1119 if ( !error ) |
713 { | 1120 { |
714 LOADM_( hmtx, 1 ); | 1121 LOADM_( hmtx, 1 ); |
715 if ( !error ) | 1122 if ( !error ) |
716 face->vertical_info = 1; | 1123 face->vertical_info = 1; |
717 } | 1124 } |
718 | 1125 |
(...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
798 /* now set up root fields */ | 1205 /* now set up root fields */ |
799 { | 1206 { |
800 FT_Face root = &face->root; | 1207 FT_Face root = &face->root; |
801 FT_Long flags = root->face_flags; | 1208 FT_Long flags = root->face_flags; |
802 | 1209 |
803 | 1210 |
804 /*********************************************************************/ | 1211 /*********************************************************************/ |
805 /* */ | 1212 /* */ |
806 /* Compute face flags. */ | 1213 /* Compute face flags. */ |
807 /* */ | 1214 /* */ |
| 1215 if ( face->sbit_table_type == TT_SBIT_TABLE_TYPE_CBLC || |
| 1216 face->sbit_table_type == TT_SBIT_TABLE_TYPE_SBIX ) |
| 1217 flags |= FT_FACE_FLAG_COLOR; /* color glyphs */ |
| 1218 |
808 if ( has_outline == TRUE ) | 1219 if ( has_outline == TRUE ) |
809 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ | 1220 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ |
810 | 1221 |
811 /* The sfnt driver only supports bitmap fonts natively, thus we */ | 1222 /* The sfnt driver only supports bitmap fonts natively, thus we */ |
812 /* don't set FT_FACE_FLAG_HINTER. */ | 1223 /* don't set FT_FACE_FLAG_HINTER. */ |
813 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ | 1224 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ |
814 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ | 1225 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ |
815 | 1226 |
816 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | 1227 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES |
817 if ( !psnames_error && | 1228 if ( !psnames_error && |
(...skipping 108 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
926 if ( count > 0 ) | 1337 if ( count > 0 ) |
927 { | 1338 { |
928 FT_Memory memory = face->root.stream->memory; | 1339 FT_Memory memory = face->root.stream->memory; |
929 FT_UShort em_size = face->header.Units_Per_EM; | 1340 FT_UShort em_size = face->header.Units_Per_EM; |
930 FT_Short avgwidth = face->os2.xAvgCharWidth; | 1341 FT_Short avgwidth = face->os2.xAvgCharWidth; |
931 FT_Size_Metrics metrics; | 1342 FT_Size_Metrics metrics; |
932 | 1343 |
933 | 1344 |
934 if ( em_size == 0 || face->os2.version == 0xFFFFU ) | 1345 if ( em_size == 0 || face->os2.version == 0xFFFFU ) |
935 { | 1346 { |
936 avgwidth = 0; | 1347 avgwidth = 1; |
937 em_size = 1; | 1348 em_size = 1; |
938 } | 1349 } |
939 | 1350 |
940 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) | 1351 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) |
941 goto Exit; | 1352 goto Exit; |
942 | 1353 |
943 for ( i = 0; i < count; i++ ) | 1354 for ( i = 0; i < count; i++ ) |
944 { | 1355 { |
945 FT_Bitmap_Size* bsize = root->available_sizes + i; | 1356 FT_Bitmap_Size* bsize = root->available_sizes + i; |
946 | 1357 |
(...skipping 209 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1156 FT_FREE( face->root.available_sizes ); | 1567 FT_FREE( face->root.available_sizes ); |
1157 face->root.num_fixed_sizes = 0; | 1568 face->root.num_fixed_sizes = 0; |
1158 | 1569 |
1159 FT_FREE( face->postscript_name ); | 1570 FT_FREE( face->postscript_name ); |
1160 | 1571 |
1161 face->sfnt = 0; | 1572 face->sfnt = 0; |
1162 } | 1573 } |
1163 | 1574 |
1164 | 1575 |
1165 /* END */ | 1576 /* END */ |
OLD | NEW |