OLD | NEW |
1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 // This is the implementation of decompression of the proposed WOFF Ultra | 5 // This is the implementation of decompression of the proposed WOFF Ultra |
6 // Condensed file format. | 6 // Condensed file format. |
7 | 7 |
8 #include <cassert> | 8 #include <cassert> |
9 #include <cstdlib> | 9 #include <cstdlib> |
10 #include <vector> | 10 #include <vector> |
(...skipping 27 matching lines...) Expand all Loading... |
38 | 38 |
39 const size_t kSfntHeaderSize = 12; | 39 const size_t kSfntHeaderSize = 12; |
40 const size_t kSfntEntrySize = 16; | 40 const size_t kSfntEntrySize = 16; |
41 const size_t kCheckSumAdjustmentOffset = 8; | 41 const size_t kCheckSumAdjustmentOffset = 8; |
42 | 42 |
43 const size_t kEndPtsOfContoursOffset = 10; | 43 const size_t kEndPtsOfContoursOffset = 10; |
44 const size_t kCompositeGlyphBegin = 10; | 44 const size_t kCompositeGlyphBegin = 10; |
45 | 45 |
46 // Note that the byte order is big-endian, not the same as ots.cc | 46 // Note that the byte order is big-endian, not the same as ots.cc |
47 #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) | 47 #define TAG(a, b, c, d) ((a << 24) | (b << 16) | (c << 8) | d) |
48 #define UNTAG(t) (t >> 24), (t >> 16), (t >> 8), (t >> 0) | 48 #define CHR(t) (t >> 24), (t >> 16), (t >> 8), (t >> 0) |
49 | 49 |
50 const unsigned int kWoff2FlagsTransform = 1 << 5; | 50 const unsigned int kWoff2FlagsTransform = 1 << 5; |
51 | 51 |
52 const uint32_t kKnownTags[] = { | 52 const uint32_t kKnownTags[] = { |
53 TAG('c', 'm', 'a', 'p'), // 0 | 53 TAG('c', 'm', 'a', 'p'), // 0 |
54 TAG('h', 'e', 'a', 'd'), // 1 | 54 TAG('h', 'e', 'a', 'd'), // 1 |
55 TAG('h', 'h', 'e', 'a'), // 2 | 55 TAG('h', 'h', 'e', 'a'), // 2 |
56 TAG('h', 'm', 't', 'x'), // 3 | 56 TAG('h', 'm', 't', 'x'), // 3 |
57 TAG('m', 'a', 'x', 'p'), // 4 | 57 TAG('m', 'a', 'x', 'p'), // 4 |
58 TAG('n', 'a', 'm', 'e'), // 5 | 58 TAG('n', 'a', 'm', 'e'), // 5 |
(...skipping 706 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
765 StoreU32(dst, kSfntHeaderSize + i * kSfntEntrySize + 4, checksum); | 765 StoreU32(dst, kSfntHeaderSize + i * kSfntEntrySize + 4, checksum); |
766 file_checksum += checksum; // The addition is mod 2^32 | 766 file_checksum += checksum; // The addition is mod 2^32 |
767 } | 767 } |
768 file_checksum += ComputeChecksum(dst, | 768 file_checksum += ComputeChecksum(dst, |
769 kSfntHeaderSize + kSfntEntrySize * n_tables); | 769 kSfntHeaderSize + kSfntEntrySize * n_tables); |
770 uint32_t checksum_adjustment = 0xb1b0afba - file_checksum; | 770 uint32_t checksum_adjustment = 0xb1b0afba - file_checksum; |
771 StoreU32(dst, adjustment_offset, checksum_adjustment); | 771 StoreU32(dst, adjustment_offset, checksum_adjustment); |
772 return true; | 772 return true; |
773 } | 773 } |
774 | 774 |
| 775 bool Woff2Uncompress(uint8_t* dst_buf, size_t dst_size, |
| 776 const uint8_t* src_buf, size_t src_size) { |
| 777 size_t uncompressed_size = dst_size; |
| 778 int ok = BrotliDecompressBuffer(src_size, src_buf, |
| 779 &uncompressed_size, dst_buf); |
| 780 if (!ok || uncompressed_size != dst_size) { |
| 781 return OTS_FAILURE(); |
| 782 } |
| 783 return true; |
| 784 } |
| 785 |
775 bool ReadTableDirectory(ots::OpenTypeFile* file, | 786 bool ReadTableDirectory(ots::OpenTypeFile* file, |
776 ots::Buffer* buffer, std::vector<Table>* tables, | 787 ots::Buffer* buffer, std::vector<Table>* tables, |
777 size_t num_tables) { | 788 size_t num_tables) { |
778 for (size_t i = 0; i < num_tables; ++i) { | 789 for (size_t i = 0; i < num_tables; ++i) { |
779 Table* table = &tables->at(i); | 790 Table* table = &tables->at(i); |
780 uint8_t flag_byte; | 791 uint8_t flag_byte; |
781 if (!buffer->ReadU8(&flag_byte)) { | 792 if (!buffer->ReadU8(&flag_byte)) { |
782 return OTS_FAILURE_MSG("Failed to read the flags of table directory entry
%d", i); | 793 return OTS_FAILURE_MSG("Failed to read the flags of table directory entry
%d", i); |
783 } | 794 } |
784 uint32_t tag; | 795 uint32_t tag; |
785 if ((flag_byte & 0x3f) == 0x3f) { | 796 if ((flag_byte & 0x3f) == 0x3f) { |
786 if (!buffer->ReadU32(&tag)) { | 797 if (!buffer->ReadU32(&tag)) { |
787 return OTS_FAILURE_MSG("Failed to read the tag of table directory entry
%d", i); | 798 return OTS_FAILURE_MSG("Failed to read the tag of table directory entry
%d", i); |
788 } | 799 } |
789 } else { | 800 } else { |
790 tag = kKnownTags[flag_byte & 0x3f]; | 801 tag = kKnownTags[flag_byte & 0x3f]; |
791 } | 802 } |
792 // Bits 6 and 7 are reserved and must be 0. | 803 // Bits 6 and 7 are reserved and must be 0. |
793 if ((flag_byte & 0xc0) != 0) { | 804 if ((flag_byte & 0xc0) != 0) { |
794 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry %
d", i); | 805 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry %
d", i); |
795 } | 806 } |
796 uint32_t flags = 0; | 807 uint32_t flags = 0; |
797 // Always transform the glyf and loca tables | 808 // Always transform the glyf and loca tables |
798 if (tag == TAG('g', 'l', 'y', 'f') || | 809 if (tag == TAG('g', 'l', 'y', 'f') || |
799 tag == TAG('l', 'o', 'c', 'a')) { | 810 tag == TAG('l', 'o', 'c', 'a')) { |
800 flags |= kWoff2FlagsTransform; | 811 flags |= kWoff2FlagsTransform; |
801 } | 812 } |
802 uint32_t dst_length; | 813 uint32_t dst_length; |
803 if (!ReadBase128(buffer, &dst_length)) { | 814 if (!ReadBase128(buffer, &dst_length)) { |
804 return OTS_FAILURE_MSG("Failed to read 'origLength' for table '%c%c%c%c'",
UNTAG(tag)); | 815 return OTS_FAILURE_MSG("Failed to read 'origLength' for table '%c%c%c%c'",
CHR(tag)); |
805 } | 816 } |
806 uint32_t transform_length = dst_length; | 817 uint32_t transform_length = dst_length; |
807 if ((flags & kWoff2FlagsTransform) != 0) { | 818 if ((flags & kWoff2FlagsTransform) != 0) { |
808 if (!ReadBase128(buffer, &transform_length)) { | 819 if (!ReadBase128(buffer, &transform_length)) { |
809 return OTS_FAILURE_MSG("Failed to read 'transformLength' for table '%c%c
%c%c'", UNTAG(tag)); | 820 return OTS_FAILURE_MSG("Failed to read 'transformLength' for table '%c%c
%c%c'", CHR(tag)); |
810 } | |
811 | |
812 if (tag == TAG('l', 'o', 'c', 'a') && transform_length != 0) { | |
813 return OTS_FAILURE_MSG("The 'transformLength' of 'loca' table must be ze
ro: %d", transform_length); | |
814 } | 821 } |
815 } | 822 } |
816 // Disallow huge numbers (> 1GB) for sanity. | 823 // Disallow huge numbers (> 1GB) for sanity. |
817 if (transform_length > 1024 * 1024 * 1024 || | 824 if (transform_length > 1024 * 1024 * 1024 || |
818 dst_length > 1024 * 1024 * 1024) { | 825 dst_length > 1024 * 1024 * 1024) { |
819 return OTS_FAILURE_MSG("'origLength' or 'transformLength' > 1GB"); | 826 return OTS_FAILURE_MSG("'origLength' or 'transformLength' > 1GB"); |
820 } | 827 } |
821 table->tag = tag; | 828 table->tag = tag; |
822 table->flags = flags; | 829 table->flags = flags; |
823 table->transform_length = transform_length; | 830 table->transform_length = transform_length; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1006 for (uint16_t i = 0; i < num_tables; ++i) { | 1013 for (uint16_t i = 0; i < num_tables; ++i) { |
1007 total_size += tables.at(i).transform_length; | 1014 total_size += tables.at(i).transform_length; |
1008 if (total_size > std::numeric_limits<uint32_t>::max()) { | 1015 if (total_size > std::numeric_limits<uint32_t>::max()) { |
1009 return OTS_FAILURE(); | 1016 return OTS_FAILURE(); |
1010 } | 1017 } |
1011 } | 1018 } |
1012 // Enforce same 30M limit on uncompressed tables as OTS | 1019 // Enforce same 30M limit on uncompressed tables as OTS |
1013 if (total_size > 30 * 1024 * 1024) { | 1020 if (total_size > 30 * 1024 * 1024) { |
1014 return OTS_FAILURE(); | 1021 return OTS_FAILURE(); |
1015 } | 1022 } |
1016 size_t uncompressed_size = static_cast<size_t>(total_size); | 1023 const size_t total_size_size_t = static_cast<size_t>(total_size); |
1017 uncompressed_buf.resize(uncompressed_size); | 1024 uncompressed_buf.resize(total_size_size_t); |
1018 const uint8_t* compressed_buf = data + compressed_offset; | 1025 const uint8_t* src_buf = data + compressed_offset; |
1019 if (!BrotliDecompressBuffer(compressed_length, compressed_buf, | 1026 if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t, |
1020 &uncompressed_size, &uncompressed_buf[0])) { | 1027 src_buf, compressed_length)) { |
1021 return OTS_FAILURE_MSG("Failed to uncompress font data"); | 1028 return OTS_FAILURE_MSG("Failed to uncompress font data"); |
1022 } | 1029 } |
1023 if (uncompressed_size != static_cast<size_t>(total_size)) { | |
1024 return OTS_FAILURE_MSG("Decompressed font data size does not match the sum o
f 'origLength' and 'transformLength'"); | |
1025 } | |
1026 transform_buf = &uncompressed_buf[0]; | 1030 transform_buf = &uncompressed_buf[0]; |
1027 | 1031 |
1028 for (uint16_t i = 0; i < num_tables; ++i) { | 1032 for (uint16_t i = 0; i < num_tables; ++i) { |
1029 const Table* table = &tables.at(i); | 1033 const Table* table = &tables.at(i); |
1030 uint32_t flags = table->flags; | 1034 uint32_t flags = table->flags; |
1031 size_t transform_length = table->transform_length; | 1035 size_t transform_length = table->transform_length; |
1032 | 1036 |
1033 if ((flags & kWoff2FlagsTransform) == 0) { | 1037 if ((flags & kWoff2FlagsTransform) == 0) { |
1034 if (transform_length != table->dst_length) { | 1038 if (transform_length != table->dst_length) { |
1035 return OTS_FAILURE(); | 1039 return OTS_FAILURE(); |
1036 } | 1040 } |
1037 if (static_cast<uint64_t>(table->dst_offset) + transform_length > | 1041 if (static_cast<uint64_t>(table->dst_offset) + transform_length > |
1038 result_length) { | 1042 result_length) { |
1039 return OTS_FAILURE(); | 1043 return OTS_FAILURE(); |
1040 } | 1044 } |
1041 std::memcpy(result + table->dst_offset, transform_buf, | 1045 std::memcpy(result + table->dst_offset, transform_buf, |
1042 transform_length); | 1046 transform_length); |
1043 } else { | 1047 } else { |
1044 if (!ReconstructTransformed(file, tables, table->tag, | 1048 if (!ReconstructTransformed(file, tables, table->tag, |
1045 transform_buf, transform_length, result, result_length)) { | 1049 transform_buf, transform_length, result, result_length)) { |
1046 return OTS_FAILURE_MSG("Failed to reconstruct '%c%c%c%c' table", UNTAG(t
able->tag)); | 1050 return OTS_FAILURE_MSG("Failed to reconstruct '%c%c%c%c' table", CHR(tab
le->tag)); |
1047 } | 1051 } |
1048 } | 1052 } |
1049 | 1053 |
1050 transform_buf += transform_length; | 1054 transform_buf += transform_length; |
1051 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { | 1055 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { |
1052 return OTS_FAILURE(); | 1056 return OTS_FAILURE(); |
1053 } | 1057 } |
1054 } | 1058 } |
1055 | 1059 |
1056 return FixChecksums(sorted_tables, result); | 1060 return FixChecksums(sorted_tables, result); |
1057 } | 1061 } |
1058 | 1062 |
1059 } // namespace ots | 1063 } // namespace ots |
1060 | 1064 |
1061 #undef TABLE_NAME | 1065 #undef TABLE_NAME |
OLD | NEW |