aboutsummaryrefslogtreecommitdiffhomepage
path: root/src/core
diff options
context:
space:
mode:
authorGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-18 22:27:21 +0000
committerGravatar bungeman@google.com <bungeman@google.com@2bbb7eff-a529-9590-31e7-b0007b416f81>2013-07-18 22:27:21 +0000
commiteacb54e174f3b6aa999087d4ce0b879bfe5829c1 (patch)
treef4dd077d6a37670da1eebd82dc987e0fb15541b8 /src/core
parentb835652599356556401b68ac26b57044160a7289 (diff)
Add a detachAsStream to SkDynamicMemoryWStream.
R=reed@google.com Review URL: https://codereview.chromium.org/19677002 git-svn-id: http://skia.googlecode.com/svn/trunk@10171 2bbb7eff-a529-9590-31e7-b0007b416f81
Diffstat (limited to 'src/core')
-rw-r--r--src/core/SkStream.cpp132
1 files changed, 132 insertions, 0 deletions
diff --git a/src/core/SkStream.cpp b/src/core/SkStream.cpp
index 91de88adac..b251905633 100644
--- a/src/core/SkStream.cpp
+++ b/src/core/SkStream.cpp
@@ -661,6 +661,138 @@ void SkDynamicMemoryWStream::invalidateCopy() {
}
}
+class SkBlockMemoryRefCnt : public SkRefCnt {
+public:
+ explicit SkBlockMemoryRefCnt(SkDynamicMemoryWStream::Block* head) : fHead(head) { }
+
+ virtual ~SkBlockMemoryRefCnt() {
+ SkDynamicMemoryWStream::Block* block = fHead;
+ while (block != NULL) {
+ SkDynamicMemoryWStream::Block* next = block->fNext;
+ sk_free(block);
+ block = next;
+ }
+ }
+
+ SkDynamicMemoryWStream::Block* const fHead;
+};
+
+class SkBlockMemoryStream : public SkStreamAsset {
+public:
+ SkBlockMemoryStream(SkDynamicMemoryWStream::Block* head, size_t size)
+ : fBlockMemory(SkNEW_ARGS(SkBlockMemoryRefCnt, (head))), fCurrent(head)
+ , fSize(size) , fOffset(0), fCurrentOffset(0) { }
+
+ SkBlockMemoryStream(SkBlockMemoryRefCnt* headRef, size_t size)
+ : fBlockMemory(SkRef(headRef)), fCurrent(fBlockMemory->fHead)
+ , fSize(size) , fOffset(0), fCurrentOffset(0) { }
+
+ virtual size_t read(void* buffer, size_t rawCount) SK_OVERRIDE {
+ size_t count = rawCount;
+ if (fOffset + count > fSize) {
+ count = fSize - fOffset;
+ }
+ size_t bytesLeftToRead = count;
+ while (fCurrent != NULL) {
+ size_t bytesLeftInCurrent = fCurrent->written() - fCurrentOffset;
+ size_t bytesFromCurrent = bytesLeftToRead <= bytesLeftInCurrent
+ ? bytesLeftToRead : bytesLeftInCurrent;
+ if (buffer) {
+ memcpy(buffer, fCurrent->start() + fCurrentOffset, bytesFromCurrent);
+ }
+ if (bytesLeftToRead <= bytesFromCurrent) {
+ fCurrentOffset += bytesFromCurrent;
+ fOffset += count;
+ return count;
+ }
+ bytesLeftToRead -= bytesFromCurrent;
+ buffer = SkTAddOffset<void>(buffer, bytesFromCurrent);
+ fCurrent = fCurrent->fNext;
+ fCurrentOffset = 0;
+ }
+ SkASSERT(false);
+ return 0;
+ }
+
+ virtual bool isAtEnd() const SK_OVERRIDE {
+ return fOffset == fSize;
+ }
+
+ virtual bool rewind() SK_OVERRIDE {
+ fCurrent = fBlockMemory->fHead;
+ fOffset = 0;
+ fCurrentOffset = 0;
+ return true;
+ }
+
+ virtual SkBlockMemoryStream* duplicate() const SK_OVERRIDE {
+ return SkNEW_ARGS(SkBlockMemoryStream, (fBlockMemory.get(), fSize));
+ }
+
+ virtual size_t getPosition() const SK_OVERRIDE {
+ return fOffset;
+ }
+
+ virtual bool seek(size_t position) SK_OVERRIDE {
+ // If possible, skip forward.
+ if (position >= fOffset) {
+ size_t skipAmount = position - fOffset;
+ return this->skip(skipAmount) == skipAmount;
+ }
+ // If possible, move backward within the current block.
+ size_t moveBackAmount = fOffset - position;
+ if (moveBackAmount <= fCurrentOffset) {
+ fCurrentOffset -= moveBackAmount;
+ fOffset -= moveBackAmount;
+ return true;
+ }
+ // Otherwise rewind and move forward.
+ return this->rewind() && this->skip(position) == position;
+ }
+
+ virtual bool move(long offset) SK_OVERRIDE {
+ return seek(fOffset + offset);
+ }
+
+ virtual SkBlockMemoryStream* fork() const SK_OVERRIDE {
+ SkAutoTUnref<SkBlockMemoryStream> that(this->duplicate());
+ that->fCurrent = this->fCurrent;
+ that->fOffset = this->fOffset;
+ that->fCurrentOffset = this->fCurrentOffset;
+ return that.detach();
+ }
+
+ virtual size_t getLength() const SK_OVERRIDE {
+ return fSize;
+ }
+
+ virtual const void* getMemoryBase() SK_OVERRIDE {
+ if (NULL == fBlockMemory->fHead->fNext) {
+ return fBlockMemory->fHead->start();
+ }
+ return NULL;
+ }
+
+private:
+ SkAutoTUnref<SkBlockMemoryRefCnt> const fBlockMemory;
+ SkDynamicMemoryWStream::Block const * fCurrent;
+ size_t const fSize;
+ size_t fOffset;
+ size_t fCurrentOffset;
+};
+
+SkStreamAsset* SkDynamicMemoryWStream::detatchAsStream() {
+ if (fCopy) {
+ SkMemoryStream* stream = SkNEW_ARGS(SkMemoryStream, (fCopy));
+ this->reset();
+ return stream;
+ }
+ SkBlockMemoryStream* stream = SkNEW_ARGS(SkBlockMemoryStream, (fHead, fBytesWritten));
+ fHead = 0;
+ this->reset();
+ return stream;
+}
+
///////////////////////////////////////////////////////////////////////////////
void SkDebugWStream::newline()