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