summaryrefslogtreecommitdiffstats
path: root/chromium/third_party/skia/include/core/SkWriter32.h
diff options
context:
space:
mode:
Diffstat (limited to 'chromium/third_party/skia/include/core/SkWriter32.h')
-rw-r--r--chromium/third_party/skia/include/core/SkWriter32.h255
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