diff options
Diffstat (limited to 'chromium/third_party/skia/src/core/SkWriter32.cpp')
-rw-r--r-- | chromium/third_party/skia/src/core/SkWriter32.cpp | 295 |
1 files changed, 51 insertions, 244 deletions
diff --git a/chromium/third_party/skia/src/core/SkWriter32.cpp b/chromium/third_party/skia/src/core/SkWriter32.cpp index e5befbafb40..00c46368b60 100644 --- a/chromium/third_party/skia/src/core/SkWriter32.cpp +++ b/chromium/third_party/skia/src/core/SkWriter32.cpp @@ -5,249 +5,19 @@ * found in the LICENSE file. */ -#include "SkWriter32.h" - -SkWriter32::SkWriter32(size_t minSize, void* storage, size_t storageSize) { - fMinSize = minSize; - fSize = 0; - fWrittenBeforeLastBlock = 0; - fHead = fTail = NULL; - - if (storageSize) { - this->reset(storage, storageSize); - } -} - -SkWriter32::~SkWriter32() { - this->reset(); -} - -void SkWriter32::reset() { - Block* block = fHead; - - if (this->isHeadExternallyAllocated()) { - SkASSERT(block); - // don't 'free' the first block, since it is owned by the caller - block = block->fNext; - } - while (block) { - Block* next = block->fNext; - sk_free(block); - block = next; - } - - fSize = 0; - fWrittenBeforeLastBlock = 0; - fHead = fTail = NULL; -} - -void SkWriter32::reset(void* storage, size_t storageSize) { - this->reset(); - - storageSize &= ~3; // trunc down to multiple of 4 - if (storageSize > 0 && SkIsAlign4((intptr_t)storage)) { - fHead = fTail = fExternalBlock.initFromStorage(storage, storageSize); - } -} - -SkWriter32::Block* SkWriter32::doReserve(size_t size) { - SkASSERT(SkAlign4(size) == size); - - Block* block = fTail; - SkASSERT(NULL == block || block->available() < size); - - if (NULL == block) { - SkASSERT(NULL == fHead); - fHead = fTail = block = Block::Create(SkMax32(size, fMinSize)); - SkASSERT(0 == fWrittenBeforeLastBlock); - } else { - fWrittenBeforeLastBlock = fSize; - - fTail = Block::Create(SkMax32(size, fMinSize)); - block->fNext = fTail; - block = fTail; - } - return block; -} - -uint32_t* SkWriter32::peek32(size_t offset) { - SkDEBUGCODE(this->validate();) - - SkASSERT(SkAlign4(offset) == offset); - SkASSERT(offset <= fSize); - - // try the fast case, where offset is within fTail - if (offset >= fWrittenBeforeLastBlock) { - return fTail->peek32(offset - fWrittenBeforeLastBlock); - } - - Block* block = fHead; - SkASSERT(NULL != block); - - while (offset >= block->fAllocatedSoFar) { - offset -= block->fAllocatedSoFar; - block = block->fNext; - SkASSERT(NULL != block); - } - return block->peek32(offset); -} - -void SkWriter32::rewindToOffset(size_t offset) { - if (offset >= fSize) { - return; - } - if (0 == offset) { - this->reset(); - return; - } - - SkDEBUGCODE(this->validate();) - - SkASSERT(SkAlign4(offset) == offset); - SkASSERT(offset <= fSize); - fSize = offset; - - // Try the fast case, where offset is within fTail - if (offset >= fWrittenBeforeLastBlock) { - fTail->fAllocatedSoFar = offset - fWrittenBeforeLastBlock; - } else { - // Similar to peek32, except that we free up any following blocks. - // We have to re-compute fWrittenBeforeLastBlock as well. - - size_t globalOffset = offset; - Block* block = fHead; - SkASSERT(NULL != block); - while (offset >= block->fAllocatedSoFar) { - offset -= block->fAllocatedSoFar; - block = block->fNext; - SkASSERT(NULL != block); - } - - // this has to be recomputed, since we may free up fTail - fWrittenBeforeLastBlock = globalOffset - offset; - - // update the size on the "last" block - block->fAllocatedSoFar = offset; - // end our list - fTail = block; - Block* next = block->fNext; - block->fNext = NULL; - // free up any trailing blocks - block = next; - while (block) { - Block* next = block->fNext; - sk_free(block); - block = next; - } - } - SkDEBUGCODE(this->validate();) -} - -void SkWriter32::flatten(void* dst) const { - const Block* block = fHead; - SkDEBUGCODE(size_t total = 0;) - - while (block) { - size_t allocated = block->fAllocatedSoFar; - memcpy(dst, block->base(), allocated); - dst = (char*)dst + allocated; - block = block->fNext; - - SkDEBUGCODE(total += allocated;) - SkASSERT(total <= fSize); - } - SkASSERT(total == fSize); -} - -uint32_t* SkWriter32::reservePad(size_t size) { - if (size > 0) { - size_t alignedSize = SkAlign4(size); - char* dst = (char*)this->reserve(alignedSize); - // Pad the last four bytes with zeroes in one step. - uint32_t* padding = (uint32_t*)(dst + (alignedSize - 4)); - *padding = 0; - return (uint32_t*) dst; - } - return this->reserve(0); -} - -void SkWriter32::writePad(const void* src, size_t size) { - if (size > 0) { - char* dst = (char*)this->reservePad(size); - // Copy the actual data. - memcpy(dst, src, size); - } -} - -#include "SkStream.h" - -size_t SkWriter32::readFromStream(SkStream* stream, size_t length) { - char scratch[1024]; - const size_t MAX = sizeof(scratch); - size_t remaining = length; - - while (remaining != 0) { - size_t n = remaining; - if (n > MAX) { - n = MAX; - } - size_t bytes = stream->read(scratch, n); - this->writePad(scratch, bytes); - remaining -= bytes; - if (bytes != n) { - break; - } - } - return length - remaining; -} - -bool SkWriter32::writeToStream(SkWStream* stream) { - const Block* block = fHead; - while (block) { - if (!stream->write(block->base(), block->fAllocatedSoFar)) { - return false; - } - block = block->fNext; - } - return true; -} - -#ifdef SK_DEBUG -void SkWriter32::validate() const { - SkASSERT(SkIsAlign4(fSize)); - - size_t accum = 0; - const Block* block = fHead; - while (block) { - SkASSERT(SkIsAlign4(block->fSizeOfBlock)); - SkASSERT(SkIsAlign4(block->fAllocatedSoFar)); - SkASSERT(block->fAllocatedSoFar <= block->fSizeOfBlock); - if (NULL == block->fNext) { - SkASSERT(fTail == block); - SkASSERT(fWrittenBeforeLastBlock == accum); - } - accum += block->fAllocatedSoFar; - SkASSERT(accum <= fSize); - block = block->fNext; - } - SkASSERT(accum == fSize); -} -#endif - -/////////////////////////////////////////////////////////////////////////////// - #include "SkReader32.h" #include "SkString.h" +#include "SkWriter32.h" /* * Strings are stored as: length[4-bytes] + string_data + '\0' + pad_to_mul_4 */ const char* SkReader32::readString(size_t* outLen) { - size_t len = this->readInt(); + size_t len = this->readU32(); const void* ptr = this->peek(); - // skip over teh string + '\0' and then pad to a multiple of 4 + // skip over the string + '\0' and then pad to a multiple of 4 size_t alignedSize = SkAlign4(len + 1); this->skip(alignedSize); @@ -274,17 +44,13 @@ void SkWriter32::writeString(const char str[], size_t len) { if ((long)len < 0) { len = strlen(str); } - this->write32(len); - // add 1 since we also write a terminating 0 - size_t alignedLen = SkAlign4(len + 1); - char* ptr = (char*)this->reserve(alignedLen); - { - // Write the terminating 0 and fill in the rest with zeroes - uint32_t* padding = (uint32_t*)(ptr + (alignedLen - 4)); - *padding = 0; - } - // Copy the string itself. - memcpy(ptr, str, len); + + // [ 4 byte len ] [ str ... ] [1 - 4 \0s] + uint32_t* ptr = this->reservePad(sizeof(uint32_t) + len + 1); + *ptr = SkToU32(len); + char* chars = (char*)(ptr + 1); + memcpy(chars, str, len); + chars[len] = '\0'; } size_t SkWriter32::WriteStringSize(const char* str, size_t len) { @@ -296,3 +62,44 @@ size_t SkWriter32::WriteStringSize(const char* str, size_t len) { // add 1 since we also write a terminating 0 return SkAlign4(lenBytes + len + 1); } + +void SkWriter32::growToAtLeast(size_t size) { + const bool wasExternal = (fExternal != NULL) && (fData == fExternal); + + fCapacity = 4096 + SkTMax(size, fCapacity + (fCapacity / 2)); + fInternal.realloc(fCapacity); + fData = fInternal.get(); + + if (wasExternal) { + // we were external, so copy in the data + memcpy(fData, fExternal, fUsed); + } + // Invalidate the snapshot, we know it is no longer useful. + fSnapshot.reset(NULL); +} + +SkData* SkWriter32::snapshotAsData() const { + // get a non const version of this, we are only conceptually const + SkWriter32& mutable_this = *const_cast<SkWriter32*>(this); + // we use size change detection to invalidate the cached data + if ((fSnapshot.get() != NULL) && (fSnapshot->size() != fUsed)) { + mutable_this.fSnapshot.reset(NULL); + } + if (fSnapshot.get() == NULL) { + uint8_t* buffer = NULL; + if ((fExternal != NULL) && (fData == fExternal)) { + // We need to copy to an allocated buffer before returning. + buffer = (uint8_t*)sk_malloc_throw(fUsed); + memcpy(buffer, fData, fUsed); + } else { + buffer = mutable_this.fInternal.detach(); + // prepare us to do copy on write, by pretending the data buffer + // is external and size limited + mutable_this.fData = buffer; + mutable_this.fCapacity = fUsed; + mutable_this.fExternal = buffer; + } + mutable_this.fSnapshot.reset(SkData::NewFromMalloc(buffer, fUsed)); + } + return SkRef(fSnapshot.get()); // Take an extra ref for the caller. +} |