SkWriter32.h revision 5a7c6be72b940dde8ff6ad2485a09aecd56a2660
1 2/* 3 * Copyright 2008 The Android Open Source Project 4 * 5 * Use of this source code is governed by a BSD-style license that can be 6 * found in the LICENSE file. 7 */ 8 9 10#ifndef SkWriter32_DEFINED 11#define SkWriter32_DEFINED 12 13#include "SkTypes.h" 14 15#include "SkScalar.h" 16#include "SkPath.h" 17#include "SkPoint.h" 18#include "SkRect.h" 19#include "SkMatrix.h" 20#include "SkRegion.h" 21 22class SkStream; 23class SkWStream; 24 25class SkWriter32 : SkNoncopyable { 26public: 27 /** 28 * The caller can specify an initial block of storage, which the caller manages. 29 * SkWriter32 will not attempt to free this in its destructor. It is up to the 30 * implementation to decide if, and how much, of the storage to utilize, and it 31 * is possible that it may be ignored entirely. 32 */ 33 SkWriter32(size_t minSize, void* initialStorage, size_t storageSize); 34 35 SkWriter32(size_t minSize) 36 : fMinSize(minSize), 37 fSize(0), 38 fSingleBlock(NULL), 39 fSingleBlockSize(0), 40 fHead(NULL), 41 fTail(NULL), 42 fHeadIsExternalStorage(false) {} 43 44 ~SkWriter32(); 45 46 /** 47 * Returns the single block backing the writer, or NULL if the memory is 48 * to be dynamically allocated. 49 */ 50 void* getSingleBlock() const { return fSingleBlock; } 51 52 // return the current offset (will always be a multiple of 4) 53 uint32_t bytesWritten() const { return fSize; } 54 // DEPRECATED: use byetsWritten instead 55 uint32_t size() const { return this->bytesWritten(); } 56 57 void reset(); 58 uint32_t* reserve(size_t size); // size MUST be multiple of 4 59 60 /** 61 * Specify the single block to back the writer, rathern than dynamically 62 * allocating the memory. If block == NULL, then the writer reverts to 63 * dynamic allocation (and resets). 64 */ 65 void reset(void* block, size_t size); 66 67 bool writeBool(bool value) { 68 this->writeInt(value); 69 return value; 70 } 71 72 void writeInt(int32_t value) { 73 *(int32_t*)this->reserve(sizeof(value)) = value; 74 } 75 76 void write8(int32_t value) { 77 *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; 78 } 79 80 void write16(int32_t value) { 81 *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; 82 } 83 84 void write32(int32_t value) { 85 *(int32_t*)this->reserve(sizeof(value)) = value; 86 } 87 88 void writePtr(void* ptr) { 89 // Since we "know" that we're always 4-byte aligned, we can tell the 90 // compiler that here, by assigning to an int32 ptr. 91 int32_t* addr = (int32_t*)this->reserve(sizeof(void*)); 92 if (4 == sizeof(void*)) { 93 *(void**)addr = ptr; 94 } else { 95 memcpy(addr, &ptr, sizeof(void*)); 96 } 97 } 98 99 void writeScalar(SkScalar value) { 100 *(SkScalar*)this->reserve(sizeof(value)) = value; 101 } 102 103 void writePoint(const SkPoint& pt) { 104 *(SkPoint*)this->reserve(sizeof(pt)) = pt; 105 } 106 107 void writeRect(const SkRect& rect) { 108 *(SkRect*)this->reserve(sizeof(rect)) = rect; 109 } 110 111 void writePath(const SkPath& path) { 112 size_t size = path.writeToMemory(NULL); 113 SkASSERT(SkAlign4(size) == size); 114 path.writeToMemory(this->reserve(size)); 115 } 116 117 void writeMatrix(const SkMatrix& matrix) { 118 size_t size = matrix.writeToMemory(NULL); 119 SkASSERT(SkAlign4(size) == size); 120 matrix.writeToMemory(this->reserve(size)); 121 } 122 123 void writeRegion(const SkRegion& rgn) { 124 size_t size = rgn.writeToMemory(NULL); 125 SkASSERT(SkAlign4(size) == size); 126 rgn.writeToMemory(this->reserve(size)); 127 } 128 129 // write count bytes (must be a multiple of 4) 130 void writeMul4(const void* values, size_t size) { 131 this->write(values, size); 132 } 133 134 /** 135 * Write size bytes from values. size must be a multiple of 4, though 136 * values need not be 4-byte aligned. 137 */ 138 void write(const void* values, size_t size) { 139 SkASSERT(SkAlign4(size) == size); 140 // if we could query how much is avail in the current block, we might 141 // copy that much, and then alloc the rest. That would reduce the waste 142 // in the current block 143 memcpy(this->reserve(size), values, size); 144 } 145 146 /** 147 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be 148 * filled in with zeroes. 149 */ 150 uint32_t* reservePad(size_t size); 151 152 /** 153 * Write size bytes from src, and pad to 4 byte alignment with zeroes. 154 */ 155 void writePad(const void* src, size_t size); 156 157 /** 158 * Writes a string to the writer, which can be retrieved with 159 * SkReader32::readString(). 160 * The length can be specified, or if -1 is passed, it will be computed by 161 * calling strlen(). The length must be < 0xFFFF 162 */ 163 void writeString(const char* str, size_t len = (size_t)-1); 164 165 /** 166 * Computes the size (aligned to multiple of 4) need to write the string 167 * in a call to writeString(). If the length is not specified, it will be 168 * computed by calling strlen(). 169 */ 170 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 171 172 // return the address of the 4byte int at the specified offset (which must 173 // be a multiple of 4. This does not allocate any new space, so the returned 174 // address is only valid for 1 int. 175 uint32_t* peek32(size_t offset); 176 177 /** 178 * Move the cursor back to offset bytes from the beginning. 179 * This has the same restrictions as peek32: offset must be <= size() and 180 * offset must be a multiple of 4. 181 */ 182 void rewindToOffset(size_t offset); 183 184 // copy into a single buffer (allocated by caller). Must be at least size() 185 void flatten(void* dst) const; 186 187 // read from the stream, and write up to length bytes. Return the actual 188 // number of bytes written. 189 size_t readFromStream(SkStream*, size_t length); 190 191 bool writeToStream(SkWStream*); 192 193private: 194 size_t fMinSize; 195 uint32_t fSize; 196 197 char* fSingleBlock; 198 uint32_t fSingleBlockSize; 199 200 struct Block; 201 Block* fHead; 202 Block* fTail; 203 204 bool fHeadIsExternalStorage; 205 206 Block* newBlock(size_t bytes); 207 208 SkDEBUGCODE(void validate() const;) 209}; 210 211/** 212 * Helper class to allocated SIZE bytes as part of the writer, and to provide 213 * that storage to the constructor as its initial storage buffer. 214 * 215 * This wrapper ensures proper alignment rules are met for the storage. 216 */ 217template <size_t SIZE> class SkSWriter32 : public SkWriter32 { 218public: 219 SkSWriter32(size_t minSize) : SkWriter32(minSize, fData.fStorage, SIZE) {} 220 221private: 222 union { 223 void* fPtrAlignment; 224 double fDoubleAlignment; 225 char fStorage[SIZE]; 226 } fData; 227}; 228 229#endif 230