diff options
Diffstat (limited to 'chromium/third_party/skia/include/core/SkWriter32.h')
-rw-r--r-- | chromium/third_party/skia/include/core/SkWriter32.h | 255 |
1 files changed, 115 insertions, 140 deletions
diff --git a/chromium/third_party/skia/include/core/SkWriter32.h b/chromium/third_party/skia/include/core/SkWriter32.h index 9fb1f7b85b6..cadcaa7853d 100644 --- a/chromium/third_party/skia/include/core/SkWriter32.h +++ b/chromium/third_party/skia/include/core/SkWriter32.h @@ -10,74 +10,96 @@ #ifndef SkWriter32_DEFINED #define SkWriter32_DEFINED -#include "SkTypes.h" - -#include "SkScalar.h" +#include "SkData.h" +#include "SkMatrix.h" #include "SkPath.h" #include "SkPoint.h" -#include "SkRect.h" #include "SkRRect.h" -#include "SkMatrix.h" +#include "SkRect.h" #include "SkRegion.h" - -class SkStream; -class SkWStream; +#include "SkScalar.h" +#include "SkStream.h" +#include "SkTemplates.h" +#include "SkTypes.h" class SkWriter32 : SkNoncopyable { - struct BlockHeader; public: /** * The caller can specify an initial block of storage, which the caller manages. - * SkWriter32 will not attempt to free this in its destructor. It is up to the - * implementation to decide if, and how much, of the storage to utilize, and it - * is possible that it may be ignored entirely. + * + * SkWriter32 will try to back reserve and write calls with this external storage until the + * first time an allocation doesn't fit. From then it will use dynamically allocated storage. + * This used to be optional behavior, but pipe now relies on it. */ - SkWriter32(size_t minSize, void* initialStorage, size_t storageSize); - - SkWriter32(size_t minSize) - : fHead(NULL) - , fTail(NULL) - , fMinSize(minSize) - , fSize(0) - , fWrittenBeforeLastBlock(0) - {} - - ~SkWriter32(); + SkWriter32(void* external = NULL, size_t externalBytes = 0) { + this->reset(external, externalBytes); + } // return the current offset (will always be a multiple of 4) - size_t bytesWritten() const { return fSize; } + size_t bytesWritten() const { return fUsed; } SK_ATTR_DEPRECATED("use bytesWritten") size_t size() const { return this->bytesWritten(); } - // Returns true if we've written only into the storage passed into constructor or reset. - // (You may be able to use this to avoid a call to flatten.) - bool wroteOnlyToStorage() const { - return fHead == &fExternalBlock && this->bytesWritten() <= fExternalBlock.fSizeOfBlock; + void reset(void* external = NULL, size_t externalBytes = 0) { + SkASSERT(SkIsAlign4((uintptr_t)external)); + SkASSERT(SkIsAlign4(externalBytes)); + + fSnapshot.reset(NULL); + fData = (uint8_t*)external; + fCapacity = externalBytes; + fUsed = 0; + fExternal = external; } - void reset(); - void reset(void* storage, size_t size); + // Returns the current buffer. + // The pointer may be invalidated by any future write calls. + const uint32_t* contiguousArray() const { + return (uint32_t*)fData; + } // size MUST be multiple of 4 uint32_t* reserve(size_t size) { SkASSERT(SkAlign4(size) == size); - - Block* block = fTail; - if (NULL == block || block->available() < size) { - block = this->doReserve(size); + size_t offset = fUsed; + size_t totalRequired = fUsed + size; + if (totalRequired > fCapacity) { + this->growToAtLeast(totalRequired); } - fSize += size; - return block->alloc(size); + fUsed = totalRequired; + return (uint32_t*)(fData + offset); + } + + /** + * Read a T record at offset, which must be a multiple of 4. Only legal if the record + * was written atomically using the write methods below. + */ + template<typename T> + const T& readTAt(size_t offset) const { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset < fUsed); + return *(T*)(fData + offset); + } + + /** + * Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record + * was written atomically using the write methods below. + */ + template<typename T> + void overwriteTAt(size_t offset, const T& value) { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset < fUsed); + SkASSERT(fSnapshot.get() == NULL); + *(T*)(fData + offset) = value; } bool writeBool(bool value) { - this->writeInt(value); + this->write32(value); return value; } void writeInt(int32_t value) { - *(int32_t*)this->reserve(sizeof(value)) = value; + this->write32(value); } void write8(int32_t value) { @@ -92,15 +114,8 @@ public: *(int32_t*)this->reserve(sizeof(value)) = value; } - void writePtr(void* ptr) { - // Since we "know" that we're always 4-byte aligned, we can tell the - // compiler that here, by assigning to an int32 ptr. - int32_t* addr = (int32_t*)this->reserve(sizeof(void*)); - if (4 == sizeof(void*)) { - *(void**)addr = ptr; - } else { - memcpy(addr, &ptr, sizeof(void*)); - } + void writePtr(void* value) { + *(void**)this->reserve(sizeof(value)) = value; } void writeScalar(SkScalar value) { @@ -152,9 +167,6 @@ public: */ void write(const void* values, size_t size) { SkASSERT(SkAlign4(size) == size); - // if we could query how much is avail in the current block, we might - // copy that much, and then alloc the rest. That would reduce the waste - // in the current block memcpy(this->reserve(size), values, size); } @@ -162,12 +174,22 @@ public: * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be * filled in with zeroes. */ - uint32_t* reservePad(size_t size); + uint32_t* reservePad(size_t size) { + size_t alignedSize = SkAlign4(size); + uint32_t* p = this->reserve(alignedSize); + if (alignedSize != size) { + SkASSERT(alignedSize >= 4); + p[alignedSize / 4 - 1] = 0; + } + return p; + } /** * Write size bytes from src, and pad to 4 byte alignment with zeroes. */ - void writePad(const void* src, size_t size); + void writePad(const void* src, size_t size) { + memcpy(this->reservePad(size), src, size); + } /** * Writes a string to the writer, which can be retrieved with @@ -186,103 +208,52 @@ public: */ static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); - // return the address of the 4byte int at the specified offset (which must - // be a multiple of 4. This does not allocate any new space, so the returned - // address is only valid for 1 int. - uint32_t* peek32(size_t offset); - /** * Move the cursor back to offset bytes from the beginning. - * This has the same restrictions as peek32: offset must be <= size() and - * offset must be a multiple of 4. + * offset must be a multiple of 4 no greater than size(). */ - void rewindToOffset(size_t offset); + void rewindToOffset(size_t offset) { + SkASSERT(SkAlign4(offset) == offset); + SkASSERT(offset <= bytesWritten()); + fUsed = offset; + } // copy into a single buffer (allocated by caller). Must be at least size() - void flatten(void* dst) const; + void flatten(void* dst) const { + memcpy(dst, fData, fUsed); + } + + bool writeToStream(SkWStream* stream) const { + return stream->write(fData, fUsed); + } // read from the stream, and write up to length bytes. Return the actual // number of bytes written. - size_t readFromStream(SkStream*, size_t length); - - bool writeToStream(SkWStream*); - -private: - struct Block { - Block* fNext; - char* fBasePtr; - size_t fSizeOfBlock; // total space allocated (after this) - size_t fAllocatedSoFar; // space used so far - - size_t available() const { return fSizeOfBlock - fAllocatedSoFar; } - char* base() { return fBasePtr; } - const char* base() const { return fBasePtr; } - - uint32_t* alloc(size_t size) { - SkASSERT(SkAlign4(size) == size); - SkASSERT(this->available() >= size); - void* ptr = this->base() + fAllocatedSoFar; - fAllocatedSoFar += size; - SkASSERT(fAllocatedSoFar <= fSizeOfBlock); - return (uint32_t*)ptr; - } - - uint32_t* peek32(size_t offset) { - SkASSERT(offset <= fAllocatedSoFar + 4); - void* ptr = this->base() + offset; - return (uint32_t*)ptr; - } - - void rewind() { - fNext = NULL; - fAllocatedSoFar = 0; - // keep fSizeOfBlock as is - } - - static Block* Create(size_t size) { - SkASSERT(SkIsAlign4(size)); - Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); - block->fNext = NULL; - block->fBasePtr = (char*)(block + 1); - block->fSizeOfBlock = size; - block->fAllocatedSoFar = 0; - return block; - } - - Block* initFromStorage(void* storage, size_t size) { - SkASSERT(SkIsAlign4((intptr_t)storage)); - SkASSERT(SkIsAlign4(size)); - Block* block = this; - block->fNext = NULL; - block->fBasePtr = (char*)storage; - block->fSizeOfBlock = size; - block->fAllocatedSoFar = 0; - return block; - } - }; - - enum { - MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t) - }; - - Block fExternalBlock; - Block* fHead; - Block* fTail; - size_t fMinSize; - size_t fSize; - // sum of bytes written in all blocks *before* fTail - size_t fWrittenBeforeLastBlock; - - bool isHeadExternallyAllocated() const { - return fHead == &fExternalBlock; + size_t readFromStream(SkStream* stream, size_t length) { + return stream->read(this->reservePad(length), length); } - Block* newBlock(size_t bytes); - - // only call from reserve() - Block* doReserve(size_t bytes); - - SkDEBUGCODE(void validate() const;) + /** + * Captures a snapshot of the data as it is right now, and return it. + * Multiple calls without intervening writes may return the same SkData, + * but this is not guaranteed. + * Future appends will not affect the returned buffer. + * It is illegal to call overwriteTAt after this without an intervening + * append. It may cause the snapshot buffer to be corrupted. + * Callers must unref the returned SkData. + * This is not thread safe, it should only be called on the writing thread, + * the result however can be shared across threads. + */ + SkData* snapshotAsData() const; +private: + void growToAtLeast(size_t size); + + uint8_t* fData; // Points to either fInternal or fExternal. + size_t fCapacity; // Number of bytes we can write to fData. + size_t fUsed; // Number of bytes written. + void* fExternal; // Unmanaged memory block. + SkAutoTMalloc<uint8_t> fInternal; // Managed memory block. + SkAutoTUnref<SkData> fSnapshot; // Holds the result of last asData. }; /** @@ -293,7 +264,9 @@ private: */ template <size_t SIZE> class SkSWriter32 : public SkWriter32 { public: - SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {} + SkSWriter32() { this->reset(); } + + void reset() {this->INHERITED::reset(fData.fStorage, SIZE); } private: union { @@ -301,6 +274,8 @@ private: double fDoubleAlignment; char fStorage[SIZE]; } fData; + + typedef SkWriter32 INHERITED; }; #endif |