Chromium Code Reviews| Index: third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
| diff --git a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
| index 874b7d06e12a3f288ac7c7d56ac845b6f1a6bcfa..1d53d47486886a9f6ab030f6ae4063d2b27aebd7 100644 |
| --- a/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
| +++ b/third_party/WebKit/Source/platform/image-decoders/ImageDecoder.cpp |
| @@ -107,12 +107,57 @@ std::unique_ptr<ImageDecoder> ImageDecoder::create(SniffResult sniffResult, Alph |
| return nullptr; |
| } |
| +namespace { |
|
Peter Kasting
2016/08/16 20:12:25
Instead of adding all this, why not just use FastS
f(malita)
2016/08/16 21:54:03
I wasn't familiar with FastSharedBufferReader, goo
|
| + |
| +constexpr size_t kLongestSignatureLength = sizeof("RIFF????WEBPVP") - 1; |
| +static_assert(kLongestSignatureLength == 14, "kLongestSignatureLength mismatch"); |
| + |
| +// Offers contiguous access to the first LEN bytes in the buffer. |
| +// If the first segment is large enough to hold all the requested data, we use a pointer to |
| +// the actual segment data. |
| +// Otherwise, we copy/consolidate the data in a local buffer. |
| +template <typename T, size_t LEN> |
| +class SpeculativeSegmentReader { |
| + STACK_ALLOCATED(); |
| +public: |
| + SpeculativeSegmentReader(const T& data, size_t (*accessSegment)(const T&, const char*&, size_t)) |
| + { |
| + m_dataLen = accessSegment(data, m_data, 0); |
| + if (!m_dataLen || m_dataLen >= LEN) { |
| + // We either don't have any data, or the first segment is large enough. |
| + // Either way, we don't need a copy: just use the actual/contiguous segment data. |
| + return; |
| + } |
| + |
| + // The signature is fragmented: we need to make a copy. |
| + std::copy(m_data, m_data + m_dataLen, m_buffer); |
| + m_data = m_buffer; |
| + |
| + do { |
| + const char* segmentData; |
| + const size_t segmentLen = accessSegment(data, segmentData, m_dataLen); |
| + if (!segmentLen) |
| + break; |
| + const size_t usableLen = std::min(segmentLen, LEN - m_dataLen); |
| + std::copy(segmentData, segmentData + usableLen, m_buffer + m_dataLen); |
| + m_dataLen += usableLen; |
| + } while (m_dataLen < LEN); |
| + } |
| + |
| + const char* data() const { return m_data; } |
| + size_t dataLen() const { return m_dataLen; } |
| + |
| +private: |
| + const char* m_data; |
| + size_t m_dataLen; |
| + char m_buffer[LEN]; |
| +}; |
| + |
| +} // anonymous ns |
| + |
| ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, size_t length) |
| { |
| - const size_t longestSignatureLength = sizeof("RIFF????WEBPVP") - 1; |
| - DCHECK_EQ(14u, longestSignatureLength); |
| - |
| - if (length < longestSignatureLength) |
| + if (length < kLongestSignatureLength) |
| return SniffResult::InsufficientData; |
| if (matchesJPEGSignature(contents)) |
| return SniffResult::JPEG; |
| @@ -131,16 +176,20 @@ ImageDecoder::SniffResult ImageDecoder::determineImageType(const char* contents, |
| ImageDecoder::SniffResult ImageDecoder::determineImageType(const SharedBuffer& data) |
| { |
| - const char* contents; |
| - const size_t length = data.getSomeData<size_t>(contents); |
| - return determineImageType(contents, length); |
| + const SpeculativeSegmentReader<SharedBuffer, kLongestSignatureLength> sniffer(data, |
| + [] (const SharedBuffer& data, const char*& segmentData, size_t offset) -> size_t { |
| + return data.getSomeData<size_t>(segmentData, offset); |
| + }); |
| + return determineImageType(sniffer.data(), sniffer.dataLen()); |
| } |
| ImageDecoder::SniffResult ImageDecoder::determineImageType(const SegmentReader& data) |
| { |
| - const char* contents; |
| - const size_t length = data.getSomeData(contents, 0); |
| - return determineImageType(contents, length); |
| + const SpeculativeSegmentReader<SegmentReader, kLongestSignatureLength> sniffer(data, |
| + [] (const SegmentReader& data, const char*& segmentData, size_t offset) -> size_t { |
| + return data.getSomeData(segmentData, offset); |
| + }); |
| + return determineImageType(sniffer.data(), sniffer.dataLen()); |
| } |
| size_t ImageDecoder::frameCount() |