180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/* 380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Copyright 2008 The Android Open Source Project 480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Use of this source code is governed by a BSD-style license that can be 680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * found in the LICENSE file. 780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#ifndef SkWriter32_DEFINED 1180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#define SkWriter32_DEFINED 1280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkTypes.h" 1480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 1580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkScalar.h" 1680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPath.h" 1780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkPoint.h" 1880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRect.h" 19363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger#include "SkRRect.h" 2080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkMatrix.h" 2180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#include "SkRegion.h" 2280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkStream; 2480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkWStream; 2580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 2680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruclass SkWriter32 : SkNoncopyable { 27d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger struct BlockHeader; 2880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 2980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 3080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * The caller can specify an initial block of storage, which the caller manages. 3180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SkWriter32 will not attempt to free this in its destructor. It is up to the 3280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * implementation to decide if, and how much, of the storage to utilize, and it 3380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * is possible that it may be ignored entirely. 3480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 3580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkWriter32(size_t minSize, void* initialStorage, size_t storageSize); 3680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 3780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkWriter32(size_t minSize) 38d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger : fHead(NULL) 39d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fTail(NULL) 40d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fMinSize(minSize) 41d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fSize(0) 42d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger , fWrittenBeforeLastBlock(0) 43d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger {} 4480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru ~SkWriter32(); 4680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 4780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // return the current offset (will always be a multiple of 4) 4880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t bytesWritten() const { return fSize; } 4958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // DEPRECATED: use bytesWritten instead TODO(mtklein): clean up 5080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t size() const { return this->bytesWritten(); } 5180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 5258190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // Returns true if we've written only into the storage passed into constructor or reset. 5358190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger // (You may be able to use this to avoid a call to flatten.) 5458190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger bool wroteOnlyToStorage() const { 5558190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger return fHead == &fExternalBlock && this->bytesWritten() <= fExternalBlock.fSizeOfBlock; 5658190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger } 5758190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger 5858190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void reset(); 5958190644c30e1c4aa8e527f3503c58f841e0fcf3Derek Sollenberger void reset(void* storage, size_t size); 6080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 61d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // size MUST be multiple of 4 62d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger uint32_t* reserve(size_t size) { 63d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(SkAlign4(size) == size); 64d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 65d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* block = fTail; 66d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger if (NULL == block || block->available() < size) { 67d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block = this->doReserve(size); 68d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 69d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger fSize += size; 70d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return block->alloc(size); 71d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 72d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 7380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool writeBool(bool value) { 7480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->writeInt(value); 7580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru return value; 7680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 7780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 7880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeInt(int32_t value) { 7980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(int32_t*)this->reserve(sizeof(value)) = value; 8080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void write8(int32_t value) { 8380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; 8480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 8680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void write16(int32_t value) { 8780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; 8880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 8980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void write32(int32_t value) { 9180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(int32_t*)this->reserve(sizeof(value)) = value; 9280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 9380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 9480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writePtr(void* ptr) { 9580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // Since we "know" that we're always 4-byte aligned, we can tell the 9680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // compiler that here, by assigning to an int32 ptr. 9780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru int32_t* addr = (int32_t*)this->reserve(sizeof(void*)); 9880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru if (4 == sizeof(void*)) { 9980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(void**)addr = ptr; 10080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } else { 10180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(addr, &ptr, sizeof(void*)); 10280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeScalar(SkScalar value) { 10680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(SkScalar*)this->reserve(sizeof(value)) = value; 10780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 10880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 10980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writePoint(const SkPoint& pt) { 11080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(SkPoint*)this->reserve(sizeof(pt)) = pt; 11180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 11380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeRect(const SkRect& rect) { 11480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru *(SkRect*)this->reserve(sizeof(rect)) = rect; 11580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 11680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 117fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger void writeIRect(const SkIRect& rect) { 118fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger *(SkIRect*)this->reserve(sizeof(rect)) = rect; 119fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger } 120fa0ab893eb60a41aac6945ab26d2b3a7e38443c4Derek Sollenberger 121363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger void writeRRect(const SkRRect& rrect) { 122363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); 123363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger } 124363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 12580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writePath(const SkPath& path) { 12680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t size = path.writeToMemory(NULL); 12780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkAlign4(size) == size); 12880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru path.writeToMemory(this->reserve(size)); 12980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeMatrix(const SkMatrix& matrix) { 13280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t size = matrix.writeToMemory(NULL); 13380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkAlign4(size) == size); 13480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru matrix.writeToMemory(this->reserve(size)); 13580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 13680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 13780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeRegion(const SkRegion& rgn) { 13880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t size = rgn.writeToMemory(NULL); 13980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkAlign4(size) == size); 14080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru rgn.writeToMemory(this->reserve(size)); 14180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // write count bytes (must be a multiple of 4) 14480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeMul4(const void* values, size_t size) { 14580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru this->write(values, size); 14680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 14780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 14880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 14980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Write size bytes from values. size must be a multiple of 4, though 15080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * values need not be 4-byte aligned. 15180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 15280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void write(const void* values, size_t size) { 15380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkASSERT(SkAlign4(size) == size); 15480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // if we could query how much is avail in the current block, we might 15580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // copy that much, and then alloc the rest. That would reduce the waste 15680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // in the current block 15780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru memcpy(this->reserve(size), values, size); 15880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } 15980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 16180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be 16280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * filled in with zeroes. 16380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 16480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t* reservePad(size_t size); 16580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 16680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 16780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Write size bytes from src, and pad to 4 byte alignment with zeroes. 16880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 16980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writePad(const void* src, size_t size); 17080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 17280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Writes a string to the writer, which can be retrieved with 17380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * SkReader32::readString(). 17480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * The length can be specified, or if -1 is passed, it will be computed by 17580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * calling strlen(). The length must be < 0xFFFF 17680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 17780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void writeString(const char* str, size_t len = (size_t)-1); 17880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 17980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 18080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Computes the size (aligned to multiple of 4) need to write the string 18180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * in a call to writeString(). If the length is not specified, it will be 18280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * computed by calling strlen(). 18380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 18480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 18580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 18680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // return the address of the 4byte int at the specified offset (which must 18780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // be a multiple of 4. This does not allocate any new space, so the returned 18880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // address is only valid for 1 int. 18980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru uint32_t* peek32(size_t offset); 19080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru /** 19280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Move the cursor back to offset bytes from the beginning. 19380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This has the same restrictions as peek32: offset must be <= size() and 19480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * offset must be a multiple of 4. 19580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 19680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void rewindToOffset(size_t offset); 19780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 19880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // copy into a single buffer (allocated by caller). Must be at least size() 19980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void flatten(void* dst) const; 20080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // read from the stream, and write up to length bytes. Return the actual 20280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru // number of bytes written. 20380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru size_t readFromStream(SkStream*, size_t length); 20480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru bool writeToStream(SkWStream*); 20680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 20780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 208d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger struct Block { 209d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* fNext; 210d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger char* fBasePtr; 211d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger size_t fSizeOfBlock; // total space allocated (after this) 212d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger size_t fAllocatedSoFar; // space used so far 213d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 214d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger size_t available() const { return fSizeOfBlock - fAllocatedSoFar; } 215d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger char* base() { return fBasePtr; } 216d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger const char* base() const { return fBasePtr; } 217d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 218d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger uint32_t* alloc(size_t size) { 219d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(SkAlign4(size) == size); 220d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(this->available() >= size); 221d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger void* ptr = this->base() + fAllocatedSoFar; 222d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger fAllocatedSoFar += size; 223d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(fAllocatedSoFar <= fSizeOfBlock); 224d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return (uint32_t*)ptr; 225d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 22680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 227d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger uint32_t* peek32(size_t offset) { 228d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(offset <= fAllocatedSoFar + 4); 229d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger void* ptr = this->base() + offset; 230d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return (uint32_t*)ptr; 231d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 232d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 233d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger void rewind() { 234d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger fNext = NULL; 235d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger fAllocatedSoFar = 0; 236d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // keep fSizeOfBlock as is 237d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 238d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 239d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger static Block* Create(size_t size) { 240d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(SkIsAlign4(size)); 241d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* block = (Block*)sk_malloc_throw(sizeof(Block) + size); 242d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fNext = NULL; 243d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fBasePtr = (char*)(block + 1); 244d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fSizeOfBlock = size; 245d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fAllocatedSoFar = 0; 246d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return block; 247d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 248d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 249d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* initFromStorage(void* storage, size_t size) { 250d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(SkIsAlign4((intptr_t)storage)); 251d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger SkASSERT(SkIsAlign4(size)); 252d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* block = this; 253d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fNext = NULL; 254d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fBasePtr = (char*)storage; 255d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fSizeOfBlock = size; 256d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger block->fAllocatedSoFar = 0; 257d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return block; 258d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 259d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger }; 26080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 261d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger enum { 262d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger MIN_BLOCKSIZE = sizeof(SkWriter32::Block) + sizeof(intptr_t) 263d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger }; 264d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 265d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block fExternalBlock; 266d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* fHead; 267d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* fTail; 268d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger size_t fMinSize; 269d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger uint32_t fSize; 270363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger // sum of bytes written in all blocks *before* fTail 271363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger uint32_t fWrittenBeforeLastBlock; 272363e546ed626b6dbbc42f5db87b3594bc0b5944bDerek Sollenberger 273d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger bool isHeadExternallyAllocated() const { 274d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger return fHead == &fExternalBlock; 275d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger } 27680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 27780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru Block* newBlock(size_t bytes); 27880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 279d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger // only call from reserve() 280d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger Block* doReserve(size_t bytes); 281d686ac77c2c485c4a3302eda9c1de597a6f8c568Derek Sollenberger 28280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkDEBUGCODE(void validate() const;) 28380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 28480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 28580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru/** 28680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * Helper class to allocated SIZE bytes as part of the writer, and to provide 28780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * that storage to the constructor as its initial storage buffer. 28880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * 28980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru * This wrapper ensures proper alignment rules are met for the storage. 29080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru */ 29180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querutemplate <size_t SIZE> class SkSWriter32 : public SkWriter32 { 29280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Querupublic: 29380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {} 29480bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 29580bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queruprivate: 29680bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru union { 29780bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru void* fPtrAlignment; 29880bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru double fDoubleAlignment; 29980bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru char fStorage[SIZE]; 30080bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru } fData; 30180bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru}; 30280bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru 30380bacfeb4bda06541e8695bd502229727bccfeaJean-Baptiste Queru#endif 304