1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/gfx/skia/trunk/include/core/SkWriter32.h Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,281 @@ 1.4 + 1.5 +/* 1.6 + * Copyright 2008 The Android Open Source Project 1.7 + * 1.8 + * Use of this source code is governed by a BSD-style license that can be 1.9 + * found in the LICENSE file. 1.10 + */ 1.11 + 1.12 + 1.13 +#ifndef SkWriter32_DEFINED 1.14 +#define SkWriter32_DEFINED 1.15 + 1.16 +#include "SkData.h" 1.17 +#include "SkMatrix.h" 1.18 +#include "SkPath.h" 1.19 +#include "SkPoint.h" 1.20 +#include "SkRRect.h" 1.21 +#include "SkRect.h" 1.22 +#include "SkRegion.h" 1.23 +#include "SkScalar.h" 1.24 +#include "SkStream.h" 1.25 +#include "SkTemplates.h" 1.26 +#include "SkTypes.h" 1.27 + 1.28 +class SkWriter32 : SkNoncopyable { 1.29 +public: 1.30 + /** 1.31 + * The caller can specify an initial block of storage, which the caller manages. 1.32 + * 1.33 + * SkWriter32 will try to back reserve and write calls with this external storage until the 1.34 + * first time an allocation doesn't fit. From then it will use dynamically allocated storage. 1.35 + * This used to be optional behavior, but pipe now relies on it. 1.36 + */ 1.37 + SkWriter32(void* external = NULL, size_t externalBytes = 0) { 1.38 + this->reset(external, externalBytes); 1.39 + } 1.40 + 1.41 + // return the current offset (will always be a multiple of 4) 1.42 + size_t bytesWritten() const { return fUsed; } 1.43 + 1.44 + SK_ATTR_DEPRECATED("use bytesWritten") 1.45 + size_t size() const { return this->bytesWritten(); } 1.46 + 1.47 + void reset(void* external = NULL, size_t externalBytes = 0) { 1.48 + SkASSERT(SkIsAlign4((uintptr_t)external)); 1.49 + SkASSERT(SkIsAlign4(externalBytes)); 1.50 + 1.51 + fSnapshot.reset(NULL); 1.52 + fData = (uint8_t*)external; 1.53 + fCapacity = externalBytes; 1.54 + fUsed = 0; 1.55 + fExternal = external; 1.56 + } 1.57 + 1.58 + // Returns the current buffer. 1.59 + // The pointer may be invalidated by any future write calls. 1.60 + const uint32_t* contiguousArray() const { 1.61 + return (uint32_t*)fData; 1.62 + } 1.63 + 1.64 + // size MUST be multiple of 4 1.65 + uint32_t* reserve(size_t size) { 1.66 + SkASSERT(SkAlign4(size) == size); 1.67 + size_t offset = fUsed; 1.68 + size_t totalRequired = fUsed + size; 1.69 + if (totalRequired > fCapacity) { 1.70 + this->growToAtLeast(totalRequired); 1.71 + } 1.72 + fUsed = totalRequired; 1.73 + return (uint32_t*)(fData + offset); 1.74 + } 1.75 + 1.76 + /** 1.77 + * Read a T record at offset, which must be a multiple of 4. Only legal if the record 1.78 + * was written atomically using the write methods below. 1.79 + */ 1.80 + template<typename T> 1.81 + const T& readTAt(size_t offset) const { 1.82 + SkASSERT(SkAlign4(offset) == offset); 1.83 + SkASSERT(offset < fUsed); 1.84 + return *(T*)(fData + offset); 1.85 + } 1.86 + 1.87 + /** 1.88 + * Overwrite a T record at offset, which must be a multiple of 4. Only legal if the record 1.89 + * was written atomically using the write methods below. 1.90 + */ 1.91 + template<typename T> 1.92 + void overwriteTAt(size_t offset, const T& value) { 1.93 + SkASSERT(SkAlign4(offset) == offset); 1.94 + SkASSERT(offset < fUsed); 1.95 + SkASSERT(fSnapshot.get() == NULL); 1.96 + *(T*)(fData + offset) = value; 1.97 + } 1.98 + 1.99 + bool writeBool(bool value) { 1.100 + this->write32(value); 1.101 + return value; 1.102 + } 1.103 + 1.104 + void writeInt(int32_t value) { 1.105 + this->write32(value); 1.106 + } 1.107 + 1.108 + void write8(int32_t value) { 1.109 + *(int32_t*)this->reserve(sizeof(value)) = value & 0xFF; 1.110 + } 1.111 + 1.112 + void write16(int32_t value) { 1.113 + *(int32_t*)this->reserve(sizeof(value)) = value & 0xFFFF; 1.114 + } 1.115 + 1.116 + void write32(int32_t value) { 1.117 + *(int32_t*)this->reserve(sizeof(value)) = value; 1.118 + } 1.119 + 1.120 + void writePtr(void* value) { 1.121 + *(void**)this->reserve(sizeof(value)) = value; 1.122 + } 1.123 + 1.124 + void writeScalar(SkScalar value) { 1.125 + *(SkScalar*)this->reserve(sizeof(value)) = value; 1.126 + } 1.127 + 1.128 + void writePoint(const SkPoint& pt) { 1.129 + *(SkPoint*)this->reserve(sizeof(pt)) = pt; 1.130 + } 1.131 + 1.132 + void writeRect(const SkRect& rect) { 1.133 + *(SkRect*)this->reserve(sizeof(rect)) = rect; 1.134 + } 1.135 + 1.136 + void writeIRect(const SkIRect& rect) { 1.137 + *(SkIRect*)this->reserve(sizeof(rect)) = rect; 1.138 + } 1.139 + 1.140 + void writeRRect(const SkRRect& rrect) { 1.141 + rrect.writeToMemory(this->reserve(SkRRect::kSizeInMemory)); 1.142 + } 1.143 + 1.144 + void writePath(const SkPath& path) { 1.145 + size_t size = path.writeToMemory(NULL); 1.146 + SkASSERT(SkAlign4(size) == size); 1.147 + path.writeToMemory(this->reserve(size)); 1.148 + } 1.149 + 1.150 + void writeMatrix(const SkMatrix& matrix) { 1.151 + size_t size = matrix.writeToMemory(NULL); 1.152 + SkASSERT(SkAlign4(size) == size); 1.153 + matrix.writeToMemory(this->reserve(size)); 1.154 + } 1.155 + 1.156 + void writeRegion(const SkRegion& rgn) { 1.157 + size_t size = rgn.writeToMemory(NULL); 1.158 + SkASSERT(SkAlign4(size) == size); 1.159 + rgn.writeToMemory(this->reserve(size)); 1.160 + } 1.161 + 1.162 + // write count bytes (must be a multiple of 4) 1.163 + void writeMul4(const void* values, size_t size) { 1.164 + this->write(values, size); 1.165 + } 1.166 + 1.167 + /** 1.168 + * Write size bytes from values. size must be a multiple of 4, though 1.169 + * values need not be 4-byte aligned. 1.170 + */ 1.171 + void write(const void* values, size_t size) { 1.172 + SkASSERT(SkAlign4(size) == size); 1.173 + memcpy(this->reserve(size), values, size); 1.174 + } 1.175 + 1.176 + /** 1.177 + * Reserve size bytes. Does not need to be 4 byte aligned. The remaining space (if any) will be 1.178 + * filled in with zeroes. 1.179 + */ 1.180 + uint32_t* reservePad(size_t size) { 1.181 + size_t alignedSize = SkAlign4(size); 1.182 + uint32_t* p = this->reserve(alignedSize); 1.183 + if (alignedSize != size) { 1.184 + SkASSERT(alignedSize >= 4); 1.185 + p[alignedSize / 4 - 1] = 0; 1.186 + } 1.187 + return p; 1.188 + } 1.189 + 1.190 + /** 1.191 + * Write size bytes from src, and pad to 4 byte alignment with zeroes. 1.192 + */ 1.193 + void writePad(const void* src, size_t size) { 1.194 + memcpy(this->reservePad(size), src, size); 1.195 + } 1.196 + 1.197 + /** 1.198 + * Writes a string to the writer, which can be retrieved with 1.199 + * SkReader32::readString(). 1.200 + * The length can be specified, or if -1 is passed, it will be computed by 1.201 + * calling strlen(). The length must be < max size_t. 1.202 + * 1.203 + * If you write NULL, it will be read as "". 1.204 + */ 1.205 + void writeString(const char* str, size_t len = (size_t)-1); 1.206 + 1.207 + /** 1.208 + * Computes the size (aligned to multiple of 4) need to write the string 1.209 + * in a call to writeString(). If the length is not specified, it will be 1.210 + * computed by calling strlen(). 1.211 + */ 1.212 + static size_t WriteStringSize(const char* str, size_t len = (size_t)-1); 1.213 + 1.214 + /** 1.215 + * Move the cursor back to offset bytes from the beginning. 1.216 + * offset must be a multiple of 4 no greater than size(). 1.217 + */ 1.218 + void rewindToOffset(size_t offset) { 1.219 + SkASSERT(SkAlign4(offset) == offset); 1.220 + SkASSERT(offset <= bytesWritten()); 1.221 + fUsed = offset; 1.222 + } 1.223 + 1.224 + // copy into a single buffer (allocated by caller). Must be at least size() 1.225 + void flatten(void* dst) const { 1.226 + memcpy(dst, fData, fUsed); 1.227 + } 1.228 + 1.229 + bool writeToStream(SkWStream* stream) const { 1.230 + return stream->write(fData, fUsed); 1.231 + } 1.232 + 1.233 + // read from the stream, and write up to length bytes. Return the actual 1.234 + // number of bytes written. 1.235 + size_t readFromStream(SkStream* stream, size_t length) { 1.236 + return stream->read(this->reservePad(length), length); 1.237 + } 1.238 + 1.239 + /** 1.240 + * Captures a snapshot of the data as it is right now, and return it. 1.241 + * Multiple calls without intervening writes may return the same SkData, 1.242 + * but this is not guaranteed. 1.243 + * Future appends will not affect the returned buffer. 1.244 + * It is illegal to call overwriteTAt after this without an intervening 1.245 + * append. It may cause the snapshot buffer to be corrupted. 1.246 + * Callers must unref the returned SkData. 1.247 + * This is not thread safe, it should only be called on the writing thread, 1.248 + * the result however can be shared across threads. 1.249 + */ 1.250 + SkData* snapshotAsData() const; 1.251 +private: 1.252 + void growToAtLeast(size_t size); 1.253 + 1.254 + uint8_t* fData; // Points to either fInternal or fExternal. 1.255 + size_t fCapacity; // Number of bytes we can write to fData. 1.256 + size_t fUsed; // Number of bytes written. 1.257 + void* fExternal; // Unmanaged memory block. 1.258 + SkAutoTMalloc<uint8_t> fInternal; // Managed memory block. 1.259 + SkAutoTUnref<SkData> fSnapshot; // Holds the result of last asData. 1.260 +}; 1.261 + 1.262 +/** 1.263 + * Helper class to allocated SIZE bytes as part of the writer, and to provide 1.264 + * that storage to the constructor as its initial storage buffer. 1.265 + * 1.266 + * This wrapper ensures proper alignment rules are met for the storage. 1.267 + */ 1.268 +template <size_t SIZE> class SkSWriter32 : public SkWriter32 { 1.269 +public: 1.270 + SkSWriter32() { this->reset(); } 1.271 + 1.272 + void reset() {this->INHERITED::reset(fData.fStorage, SIZE); } 1.273 + 1.274 +private: 1.275 + union { 1.276 + void* fPtrAlignment; 1.277 + double fDoubleAlignment; 1.278 + char fStorage[SIZE]; 1.279 + } fData; 1.280 + 1.281 + typedef SkWriter32 INHERITED; 1.282 +}; 1.283 + 1.284 +#endif