| 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 |