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 "SkData.h" 14 #include "SkMatrix.h" 15 #include "SkPath.h" 16 #include "SkPoint.h" 17 #include "SkRRect.h" 18 #include "SkRect.h" 19 #include "SkRegion.h" 20 #include "SkScalar.h" 21 #include "SkStream.h" 22 #include "SkTemplates.h" 23 #include "SkTypes.h" 24 25 class SK_API SkWriter32 : SkNoncopyable { 26 public: 27 /** 28 * The caller can specify an initial block of storage, which the caller manages. 29 * 30 * SkWriter32 will try to back reserve and write calls with this external storage until the 31 * first time an allocation doesn't fit. From then it will use dynamically allocated storage. 32 * This used to be optional behavior, but pipe now relies on it. 33 */ 34 SkWriter32(void* external = NULL, size_t externalBytes = 0) { 35 this->reset(external, externalBytes); 36 } 37 38 // return the current offset (will always be a multiple of 4) 39 size_t bytesWritten() const { return fUsed; } 40 41 SK_ATTR_DEPRECATED("use bytesWritten") 42 size_t size() const { return this->bytesWritten(); } 43 44 void reset(void* external = NULL, size_t externalBytes = 0) { 45 SkASSERT(SkIsAlign4((uintptr_t)external)); 46 SkASSERT(SkIsAlign4(externalBytes)); 47 48 fSnapshot.reset(NULL); 49 fData = (uint8_t*)external; 50 fCapacity = externalBytes; 51 fUsed = 0; 52 fExternal = external; 53 } 54 55 // Returns the current buffer. 56 // The pointer may be invalidated by any future write calls. 57 const uint32_t* contiguousArray() const { 58 return (uint32_t*)fData; 59 } 60 61 // size MUST be multiple of 4 62 uint32_t* reserve(size_t size) { 63 SkASSERT(SkAlign4(size) == size); 64 size_t offset = fUsed; 65 size_t totalRequired = fUsed + size; 66 if (totalRequired > fCapacity) { 67 this->growToAtLeast(totalRequired); 68 } 69 fUsed = totalRequired; 70 return (uint32_t*)(fData + offset); 71 } 72 73 /** 74 * Read a T record at offset, which must be a multiple of 4. Only legal if the record 75 * was written atomically using the write methods below. 76 */ 77 template<typename T> 78 const T& readTAt(size_t offset) const { 79 SkASSERT(SkAlign4(offset) == offset); 80 SkASSERT(offset < fUsed); 81 return *(T*)(fData + offset); 82 } 83 84 /** 85 * Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record 86 * was written atomically using the write methods below. 87 */ 88 template<typename T> 89 void overwriteTAt(size_t offset, const T& value) { 90 SkASSERT(SkAlign4(offset) == offset); 91 SkASSERT(offset < fUsed); 92 SkASSERT(fSnapshot.get() == NULL); 93 *(T*)(fData + offset) = value; 94 } 95 96 bool writeBool(bool value) { 97 this->write32(value); 98 return value; 99 } 100 101 void writeInt(int32_t value) { 102 this->write32(value); 103 } 104 105 void write8(int32_t value) { 106 *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; 107 } 108 109 void write16(int32_t value) { 110 *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; 111 } 112 113 void write32(int32_t value) { 114 *(int32_t*)this->reserve(sizeof(value)) = value; 115 } 116 117 void writePtr(void* value) { 118 *(void**)this->reserve(sizeof(value)) = value; 119 } 120 121 void writeScalar(SkScalar value) { 122 *(SkScalar*)this->reserve(sizeof(value)) = value; 123 } 124 125 void writePoint(const SkPoint& pt) { 126 *(SkPoint*)this->reserve(sizeof(pt)) = pt; 127 } 128 129 void writeRect(const SkRect& rect) { 130 *(SkRect*)this->reserve(sizeof(rect)) = rect; 131 } 132 133 void writeIRect(const SkIRect& rect) { 134 *(SkIRect*)this->reserve(sizeof(rect)) = rect; 135 } 136 137 void writeRRect(const SkRRect& rrect) { 138 rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); 139 } 140 141 void writePath(const SkPath& path) { 142 size_t size = path.writeToMemory(NULL); 143 SkASSERT(SkAlign4(size) == size); 144 path.writeToMemory(this->reserve(size)); 145 } 146 147 void writeMatrix(const SkMatrix& matrix) { 148 size_t size = matrix.writeToMemory(NULL); 149 SkASSERT(SkAlign4(size) == size); 150 matrix.writeToMemory(this->reserve(size)); 151 } 152 153 void writeRegion(const SkRegion& rgn) { 154 size_t size = rgn.writeToMemory(NULL); 155 SkASSERT(SkAlign4(size) == size); 156 rgn.writeToMemory(this->reserve(size)); 157 } 158 159 // write count bytes (must be a multiple of 4) 160 void writeMul4(const void* values, size_t size) { 161 this->write(values, size); 162 } 163 164 /** 165 * Write size bytes from values. size must be a multiple of 4, though 166 * values need not be 4-byte aligned. 167 */ 168 void write(const void* values, size_t size) { 169 SkASSERT(SkAlign4(size) == size); 170 memcpy(this->reserve(size), values, size); 171 } 172 173 /** 174 * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be 175 * filled in with zeroes. 176 */ 177 uint32_t* reservePad(size_t size) { 178 size_t alignedSize = SkAlign4(size); 179 uint32_t* p = this->reserve(alignedSize); 180 if (alignedSize != size) { 181 SkASSERT(alignedSize >= 4); 182 p[alignedSize / 4 - 1] = 0; 183 } 184 return p; 185 } 186 187 /** 188 * Write size bytes from src, and pad to 4 byte alignment with zeroes. 189 */ 190 void writePad(const void* src, size_t size) { 191 memcpy(this->reservePad(size), src, size); 192 } 193 194 /** 195 * Writes a string to the writer, which can be retrieved with 196 * SkReader32::readString(). 197 * The length can be specified, or if -1 is passed, it will be computed by 198 * calling strlen(). The length must be < max size_t. 199 * 200 * If you write NULL, it will be read as "". 201 */ 202 void writeString(const char* str, size_t len = (size_t)-1); 203 204 /** 205 * Computes the size (aligned to multiple of 4) need to write the string 206 * in a call to writeString(). If the length is not specified, it will be 207 * computed by calling strlen(). 208 */ 209 static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 210 211 /** 212 * Move the cursor back to offset bytes from the beginning. 213 * offset must be a multiple of 4 no greater than size(). 214 */ 215 void rewindToOffset(size_t offset) { 216 SkASSERT(SkAlign4(offset) == offset); 217 SkASSERT(offset <= bytesWritten()); 218 fUsed = offset; 219 } 220 221 // copy into a single buffer (allocated by caller). Must be at least size() 222 void flatten(void* dst) const { 223 memcpy(dst, fData, fUsed); 224 } 225 226 bool writeToStream(SkWStream* stream) const { 227 return stream->write(fData, fUsed); 228 } 229 230 // read from the stream, and write up to length bytes. Return the actual 231 // number of bytes written. 232 size_t readFromStream(SkStream* stream, size_t length) { 233 return stream->read(this->reservePad(length), length); 234 } 235 236 /** 237 * Captures a snapshot of the data as it is right now, and return it. 238 * Multiple calls without intervening writes may return the same SkData, 239 * but this is not guaranteed. 240 * Future appends will not affect the returned buffer. 241 * It is illegal to call overwriteTAt after this without an intervening 242 * append. It may cause the snapshot buffer to be corrupted. 243 * Callers must unref the returned SkData. 244 * This is not thread safe, it should only be called on the writing thread, 245 * the result however can be shared across threads. 246 */ 247 SkData* snapshotAsData() const; 248 private: 249 void growToAtLeast(size_t size); 250 251 uint8_t* fData; // Points to either fInternal or fExternal. 252 size_t fCapacity; // Number of bytes we can write to fData. 253 size_t fUsed; // Number of bytes written. 254 void* fExternal; // Unmanaged memory block. 255 SkAutoTMalloc<uint8_t> fInternal; // Managed memory block. 256 SkAutoTUnref<SkData> fSnapshot; // Holds the result of last asData. 257 }; 258 259 /** 260 * Helper class to allocated SIZE bytes as part of the writer, and to provide 261 * that storage to the constructor as its initial storage buffer. 262 * 263 * This wrapper ensures proper alignment rules are met for the storage. 264 */ 265 template <size_t SIZE> class SkSWriter32 : public SkWriter32 { 266 public: 267 SkSWriter32() { this->reset(); } 268 269 void reset() {this->INHERITED::reset(fData.fStorage, SIZE); } 270 271 private: 272 union { 273 void* fPtrAlignment; 274 double fDoubleAlignment; 275 char fStorage[SIZE]; 276 } fData; 277 278 typedef SkWriter32 INHERITED; 279 }; 280 281 #endif 282