Index: src/codec/SkRawCodec.cpp |
diff --git a/src/codec/SkRawCodec.cpp b/src/codec/SkRawCodec.cpp |
index f400b19d89ed0b4eb6a6dba3afedc316d9bf8e5e..21fb3621954c6b7dd06cfd8bd1320482885ce67a 100644 |
--- a/src/codec/SkRawCodec.cpp |
+++ b/src/codec/SkRawCodec.cpp |
@@ -164,7 +164,9 @@ class SkRawStream : public ::piex::StreamInterface { |
public: |
// Note that this call will take the ownership of stream. |
explicit SkRawStream(SkStream* stream) |
- : fStream(stream), fWholeStreamRead(false) {} |
+ : fStream(stream) |
+ , fWholeStreamRead(false) |
+ , fIsSeekable(fStream->peekData() != nullptr) {} |
msarett
2016/02/01 16:23:43
I think maybe this is a mix of two suggestions.
I
scroggo
2016/02/01 16:40:18
That is correct.
|
~SkRawStream() override {} |
@@ -174,6 +176,17 @@ public: |
* abandon current object after the function call. |
*/ |
SkMemoryStream* transferBuffer(size_t offset, size_t size) { |
+ if (fIsSeekable) { |
+ size_t sum; |
+ if (!safe_add_to_size_t(offset, size, &sum)) { |
+ return nullptr; |
+ } |
+ SkAutoTUnref<SkData> data(SkData::NewWithCopy( |
+ static_cast<const uint8_t*>(fStream->peekData()->data()) + offset, size)); |
+ fStream.free(); |
+ return new SkMemoryStream(data); |
+ } |
+ |
SkAutoTUnref<SkData> data(SkData::NewUninitialized(size)); |
if (offset > fStreamBuffer.bytesWritten()) { |
// If the offset is not buffered, read from fStream directly and skip the buffering. |
@@ -211,46 +224,58 @@ public: |
// For PIEX |
::piex::Error GetData(const size_t offset, const size_t length, |
uint8* data) override { |
- if (offset == 0 && length == 0) { |
- return ::piex::Error::kOk; |
- } |
- size_t sum; |
- if (!safe_add_to_size_t(offset, length, &sum) || !this->bufferMoreData(sum)) { |
- return ::piex::Error::kFail; |
- } |
- if (!fStreamBuffer.read(data, offset, length)) { |
- return ::piex::Error::kFail; |
- } |
- return ::piex::Error::kOk; |
+ return read(offset, length, static_cast<void*>(data)) ? |
+ ::piex::Error::kOk : ::piex::Error::kFail; |
} |
// For dng_stream |
uint64 getLength() { |
- if (!this->bufferMoreData(kReadToEnd)) { // read whole stream |
- ThrowReadFile(); |
+ if (fIsSeekable) { |
+ return fStream->getLength(); |
+ } else { |
+ if (!this->bufferMoreData(kReadToEnd)) { // read whole stream |
+ ThrowReadFile(); |
+ } |
+ return fStreamBuffer.bytesWritten(); |
} |
- return fStreamBuffer.bytesWritten(); |
} |
// For dng_stream |
- void read(void* data, uint32 count, uint64 offset) { |
- if (count == 0 && offset == 0) { |
- return; |
- } |
+ void dngRead(void* data, uint32 count, uint64 offset) { |
size_t sum; |
if (!safe_add_to_size_t(static_cast<uint64>(count), offset, &sum) || |
- !this->bufferMoreData(sum)) { |
+ !read(static_cast<size_t>(offset), static_cast<size_t>(count), data)) { |
ThrowReadFile(); |
} |
+ } |
- if (!fStreamBuffer.read(data, static_cast<size_t>(offset), count)) { |
- ThrowReadFile(); |
+private: |
+ bool read(size_t offset, size_t length, void* data) { |
+ if (offset == 0 && length == 0) { |
+ return true; |
+ } |
+ |
+ size_t sum; |
+ if (!safe_add_to_size_t(offset, length, &sum)) { |
+ return false; |
+ } |
+ |
+ if (fIsSeekable) { |
+ if (sum > fStream->getLength()) { |
+ return false; |
+ } |
+ |
+ return fStream->seek(offset) && |
+ (fStream->read(data, length) == length); |
+ } else { |
+ return this->bufferMoreData(sum) && fStreamBuffer.read(data, offset, length); |
} |
} |
-private: |
// Note: if the newSize == kReadToEnd (0), this function will read to the end of stream. |
bool bufferMoreData(size_t newSize) { |
+ SkASSERT(!fIsSeekable); |
+ |
if (newSize == kReadToEnd) { |
if (fWholeStreamRead) { // already read-to-end. |
return true; |
@@ -278,6 +303,7 @@ private: |
SkAutoTDelete<SkStream> fStream; |
bool fWholeStreamRead; |
+ bool fIsSeekable; |
SkDynamicMemoryWStream fStreamBuffer; |
@@ -291,7 +317,7 @@ public: |
uint64 DoGetLength() override { return fRawStream->getLength(); } |
void DoRead(void* data, uint32 count, uint64 offset) override { |
- fRawStream->read(data, count, offset); |
+ fRawStream->dngRead(data, count, offset); |
} |
private: |