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 CHR(t) (t >> 24), (t >> 16), (t >> 8), (t >> 0) | 48 #define UNTAG(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 | |
786 bool ReadTableDirectory(ots::OpenTypeFile* file, | 775 bool ReadTableDirectory(ots::OpenTypeFile* file, |
787 ots::Buffer* buffer, std::vector<Table>* tables, | 776 ots::Buffer* buffer, std::vector<Table>* tables, |
788 size_t num_tables) { | 777 size_t num_tables) { |
789 for (size_t i = 0; i < num_tables; ++i) { | 778 for (size_t i = 0; i < num_tables; ++i) { |
790 Table* table = &tables->at(i); | 779 Table* table = &tables->at(i); |
791 uint8_t flag_byte; | 780 uint8_t flag_byte; |
792 if (!buffer->ReadU8(&flag_byte)) { | 781 if (!buffer->ReadU8(&flag_byte)) { |
793 return OTS_FAILURE_MSG("Failed to read the flags of table directory entry
%d", i); | 782 return OTS_FAILURE_MSG("Failed to read the flags of table directory entry
%d", i); |
794 } | 783 } |
795 uint32_t tag; | 784 uint32_t tag; |
796 if ((flag_byte & 0x3f) == 0x3f) { | 785 if ((flag_byte & 0x3f) == 0x3f) { |
797 if (!buffer->ReadU32(&tag)) { | 786 if (!buffer->ReadU32(&tag)) { |
798 return OTS_FAILURE_MSG("Failed to read the tag of table directory entry
%d", i); | 787 return OTS_FAILURE_MSG("Failed to read the tag of table directory entry
%d", i); |
799 } | 788 } |
800 } else { | 789 } else { |
801 tag = kKnownTags[flag_byte & 0x3f]; | 790 tag = kKnownTags[flag_byte & 0x3f]; |
802 } | 791 } |
803 // Bits 6 and 7 are reserved and must be 0. | 792 // Bits 6 and 7 are reserved and must be 0. |
804 if ((flag_byte & 0xc0) != 0) { | 793 if ((flag_byte & 0xc0) != 0) { |
805 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry %
d", i); | 794 return OTS_FAILURE_MSG("Bits 6 and 7 are not 0 for table directory entry %
d", i); |
806 } | 795 } |
807 uint32_t flags = 0; | 796 uint32_t flags = 0; |
808 // Always transform the glyf and loca tables | 797 // Always transform the glyf and loca tables |
809 if (tag == TAG('g', 'l', 'y', 'f') || | 798 if (tag == TAG('g', 'l', 'y', 'f') || |
810 tag == TAG('l', 'o', 'c', 'a')) { | 799 tag == TAG('l', 'o', 'c', 'a')) { |
811 flags |= kWoff2FlagsTransform; | 800 flags |= kWoff2FlagsTransform; |
812 } | 801 } |
813 uint32_t dst_length; | 802 uint32_t dst_length; |
814 if (!ReadBase128(buffer, &dst_length)) { | 803 if (!ReadBase128(buffer, &dst_length)) { |
815 return OTS_FAILURE_MSG("Failed to read 'origLength' for table '%c%c%c%c'",
CHR(tag)); | 804 return OTS_FAILURE_MSG("Failed to read 'origLength' for table '%c%c%c%c'",
UNTAG(tag)); |
816 } | 805 } |
817 uint32_t transform_length = dst_length; | 806 uint32_t transform_length = dst_length; |
818 if ((flags & kWoff2FlagsTransform) != 0) { | 807 if ((flags & kWoff2FlagsTransform) != 0) { |
819 if (!ReadBase128(buffer, &transform_length)) { | 808 if (!ReadBase128(buffer, &transform_length)) { |
820 return OTS_FAILURE_MSG("Failed to read 'transformLength' for table '%c%c
%c%c'", CHR(tag)); | 809 return OTS_FAILURE_MSG("Failed to read 'transformLength' for table '%c%c
%c%c'", UNTAG(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); |
821 } | 814 } |
822 } | 815 } |
823 // Disallow huge numbers (> 1GB) for sanity. | 816 // Disallow huge numbers (> 1GB) for sanity. |
824 if (transform_length > 1024 * 1024 * 1024 || | 817 if (transform_length > 1024 * 1024 * 1024 || |
825 dst_length > 1024 * 1024 * 1024) { | 818 dst_length > 1024 * 1024 * 1024) { |
826 return OTS_FAILURE_MSG("'origLength' or 'transformLength' > 1GB"); | 819 return OTS_FAILURE_MSG("'origLength' or 'transformLength' > 1GB"); |
827 } | 820 } |
828 table->tag = tag; | 821 table->tag = tag; |
829 table->flags = flags; | 822 table->flags = flags; |
830 table->transform_length = transform_length; | 823 table->transform_length = transform_length; |
(...skipping 182 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1013 for (uint16_t i = 0; i < num_tables; ++i) { | 1006 for (uint16_t i = 0; i < num_tables; ++i) { |
1014 total_size += tables.at(i).transform_length; | 1007 total_size += tables.at(i).transform_length; |
1015 if (total_size > std::numeric_limits<uint32_t>::max()) { | 1008 if (total_size > std::numeric_limits<uint32_t>::max()) { |
1016 return OTS_FAILURE(); | 1009 return OTS_FAILURE(); |
1017 } | 1010 } |
1018 } | 1011 } |
1019 // Enforce same 30M limit on uncompressed tables as OTS | 1012 // Enforce same 30M limit on uncompressed tables as OTS |
1020 if (total_size > 30 * 1024 * 1024) { | 1013 if (total_size > 30 * 1024 * 1024) { |
1021 return OTS_FAILURE(); | 1014 return OTS_FAILURE(); |
1022 } | 1015 } |
1023 const size_t total_size_size_t = static_cast<size_t>(total_size); | 1016 size_t uncompressed_size = static_cast<size_t>(total_size); |
1024 uncompressed_buf.resize(total_size_size_t); | 1017 uncompressed_buf.resize(uncompressed_size); |
1025 const uint8_t* src_buf = data + compressed_offset; | 1018 const uint8_t* compressed_buf = data + compressed_offset; |
1026 if (!Woff2Uncompress(&uncompressed_buf[0], total_size_size_t, | 1019 if (!BrotliDecompressBuffer(compressed_length, compressed_buf, |
1027 src_buf, compressed_length)) { | 1020 &uncompressed_size, &uncompressed_buf[0])) { |
1028 return OTS_FAILURE_MSG("Failed to uncompress font data"); | 1021 return OTS_FAILURE_MSG("Failed to uncompress font data"); |
1029 } | 1022 } |
| 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 } |
1030 transform_buf = &uncompressed_buf[0]; | 1026 transform_buf = &uncompressed_buf[0]; |
1031 | 1027 |
1032 for (uint16_t i = 0; i < num_tables; ++i) { | 1028 for (uint16_t i = 0; i < num_tables; ++i) { |
1033 const Table* table = &tables.at(i); | 1029 const Table* table = &tables.at(i); |
1034 uint32_t flags = table->flags; | 1030 uint32_t flags = table->flags; |
1035 size_t transform_length = table->transform_length; | 1031 size_t transform_length = table->transform_length; |
1036 | 1032 |
1037 if ((flags & kWoff2FlagsTransform) == 0) { | 1033 if ((flags & kWoff2FlagsTransform) == 0) { |
1038 if (transform_length != table->dst_length) { | 1034 if (transform_length != table->dst_length) { |
1039 return OTS_FAILURE(); | 1035 return OTS_FAILURE(); |
1040 } | 1036 } |
1041 if (static_cast<uint64_t>(table->dst_offset) + transform_length > | 1037 if (static_cast<uint64_t>(table->dst_offset) + transform_length > |
1042 result_length) { | 1038 result_length) { |
1043 return OTS_FAILURE(); | 1039 return OTS_FAILURE(); |
1044 } | 1040 } |
1045 std::memcpy(result + table->dst_offset, transform_buf, | 1041 std::memcpy(result + table->dst_offset, transform_buf, |
1046 transform_length); | 1042 transform_length); |
1047 } else { | 1043 } else { |
1048 if (!ReconstructTransformed(file, tables, table->tag, | 1044 if (!ReconstructTransformed(file, tables, table->tag, |
1049 transform_buf, transform_length, result, result_length)) { | 1045 transform_buf, transform_length, result, result_length)) { |
1050 return OTS_FAILURE_MSG("Failed to reconstruct '%c%c%c%c' table", CHR(tab
le->tag)); | 1046 return OTS_FAILURE_MSG("Failed to reconstruct '%c%c%c%c' table", UNTAG(t
able->tag)); |
1051 } | 1047 } |
1052 } | 1048 } |
1053 | 1049 |
1054 transform_buf += transform_length; | 1050 transform_buf += transform_length; |
1055 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { | 1051 if (transform_buf > &uncompressed_buf[0] + uncompressed_buf.size()) { |
1056 return OTS_FAILURE(); | 1052 return OTS_FAILURE(); |
1057 } | 1053 } |
1058 } | 1054 } |
1059 | 1055 |
1060 return FixChecksums(sorted_tables, result); | 1056 return FixChecksums(sorted_tables, result); |
1061 } | 1057 } |
1062 | 1058 |
1063 } // namespace ots | 1059 } // namespace ots |
1064 | 1060 |
1065 #undef TABLE_NAME | 1061 #undef TABLE_NAME |
OLD | NEW |