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