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