1
2 /*
3 * Copyright 2012 Google Inc.
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 #include "SkOrderedWriteBuffer.h"
10 #include "SkBitmap.h"
11 #include "SkData.h"
12 #include "SkPixelRef.h"
13 #include "SkPtrRecorder.h"
14 #include "SkStream.h"
15 #include "SkTypeface.h"
16
SkOrderedWriteBuffer(size_t minSize)17 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize)
18 : INHERITED()
19 , fFactorySet(NULL)
20 , fNamedFactorySet(NULL)
21 , fWriter(minSize)
22 , fBitmapHeap(NULL)
23 , fTFSet(NULL)
24 , fBitmapEncoder(NULL) {
25 }
26
SkOrderedWriteBuffer(size_t minSize,void * storage,size_t storageSize)27 SkOrderedWriteBuffer::SkOrderedWriteBuffer(size_t minSize, void* storage, size_t storageSize)
28 : INHERITED()
29 , fFactorySet(NULL)
30 , fNamedFactorySet(NULL)
31 , fWriter(minSize, storage, storageSize)
32 , fBitmapHeap(NULL)
33 , fTFSet(NULL)
34 , fBitmapEncoder(NULL) {
35 }
36
~SkOrderedWriteBuffer()37 SkOrderedWriteBuffer::~SkOrderedWriteBuffer() {
38 SkSafeUnref(fFactorySet);
39 SkSafeUnref(fNamedFactorySet);
40 SkSafeUnref(fBitmapHeap);
41 SkSafeUnref(fTFSet);
42 }
43
writeByteArray(const void * data,size_t size)44 void SkOrderedWriteBuffer::writeByteArray(const void* data, size_t size) {
45 fWriter.write32(size);
46 fWriter.writePad(data, size);
47 }
48
writeBool(bool value)49 void SkOrderedWriteBuffer::writeBool(bool value) {
50 fWriter.writeBool(value);
51 }
52
writeFixed(SkFixed value)53 void SkOrderedWriteBuffer::writeFixed(SkFixed value) {
54 fWriter.write32(value);
55 }
56
writeScalar(SkScalar value)57 void SkOrderedWriteBuffer::writeScalar(SkScalar value) {
58 fWriter.writeScalar(value);
59 }
60
writeScalarArray(const SkScalar * value,uint32_t count)61 void SkOrderedWriteBuffer::writeScalarArray(const SkScalar* value, uint32_t count) {
62 fWriter.write32(count);
63 fWriter.write(value, count * sizeof(SkScalar));
64 }
65
writeInt(int32_t value)66 void SkOrderedWriteBuffer::writeInt(int32_t value) {
67 fWriter.write32(value);
68 }
69
writeIntArray(const int32_t * value,uint32_t count)70 void SkOrderedWriteBuffer::writeIntArray(const int32_t* value, uint32_t count) {
71 fWriter.write32(count);
72 fWriter.write(value, count * sizeof(int32_t));
73 }
74
writeUInt(uint32_t value)75 void SkOrderedWriteBuffer::writeUInt(uint32_t value) {
76 fWriter.write32(value);
77 }
78
write32(int32_t value)79 void SkOrderedWriteBuffer::write32(int32_t value) {
80 fWriter.write32(value);
81 }
82
writeString(const char * value)83 void SkOrderedWriteBuffer::writeString(const char* value) {
84 fWriter.writeString(value);
85 }
86
writeEncodedString(const void * value,size_t byteLength,SkPaint::TextEncoding encoding)87 void SkOrderedWriteBuffer::writeEncodedString(const void* value, size_t byteLength,
88 SkPaint::TextEncoding encoding) {
89 fWriter.writeInt(encoding);
90 fWriter.writeInt(byteLength);
91 fWriter.write(value, byteLength);
92 }
93
94
writeColor(const SkColor & color)95 void SkOrderedWriteBuffer::writeColor(const SkColor& color) {
96 fWriter.write32(color);
97 }
98
writeColorArray(const SkColor * color,uint32_t count)99 void SkOrderedWriteBuffer::writeColorArray(const SkColor* color, uint32_t count) {
100 fWriter.write32(count);
101 fWriter.write(color, count * sizeof(SkColor));
102 }
103
writePoint(const SkPoint & point)104 void SkOrderedWriteBuffer::writePoint(const SkPoint& point) {
105 fWriter.writeScalar(point.fX);
106 fWriter.writeScalar(point.fY);
107 }
108
writePointArray(const SkPoint * point,uint32_t count)109 void SkOrderedWriteBuffer::writePointArray(const SkPoint* point, uint32_t count) {
110 fWriter.write32(count);
111 fWriter.write(point, count * sizeof(SkPoint));
112 }
113
writeMatrix(const SkMatrix & matrix)114 void SkOrderedWriteBuffer::writeMatrix(const SkMatrix& matrix) {
115 fWriter.writeMatrix(matrix);
116 }
117
writeIRect(const SkIRect & rect)118 void SkOrderedWriteBuffer::writeIRect(const SkIRect& rect) {
119 fWriter.write(&rect, sizeof(SkIRect));
120 }
121
writeRect(const SkRect & rect)122 void SkOrderedWriteBuffer::writeRect(const SkRect& rect) {
123 fWriter.writeRect(rect);
124 }
125
writeRegion(const SkRegion & region)126 void SkOrderedWriteBuffer::writeRegion(const SkRegion& region) {
127 fWriter.writeRegion(region);
128 }
129
writePath(const SkPath & path)130 void SkOrderedWriteBuffer::writePath(const SkPath& path) {
131 fWriter.writePath(path);
132 }
133
writeStream(SkStream * stream,size_t length)134 size_t SkOrderedWriteBuffer::writeStream(SkStream* stream, size_t length) {
135 fWriter.write32(length);
136 size_t bytesWritten = fWriter.readFromStream(stream, length);
137 if (bytesWritten < length) {
138 fWriter.reservePad(length - bytesWritten);
139 }
140 return bytesWritten;
141 }
142
writeToStream(SkWStream * stream)143 bool SkOrderedWriteBuffer::writeToStream(SkWStream* stream) {
144 return fWriter.writeToStream(stream);
145 }
146
writeBitmap(const SkBitmap & bitmap)147 void SkOrderedWriteBuffer::writeBitmap(const SkBitmap& bitmap) {
148 // Record information about the bitmap in one of three ways, in order of priority:
149 // 1. If there is an SkBitmapHeap, store it in the heap. The client can avoid serializing the
150 // bitmap entirely or serialize it later as desired.
151 // 2. Write an encoded version of the bitmap. Afterwards the width and height are written, so
152 // a reader without a decoder can draw a dummy bitmap of the right size.
153 // A. If the bitmap has an encoded representation, write it to the stream.
154 // B. If there is a function for encoding bitmaps, use it.
155 // 3. Call SkBitmap::flatten.
156 // For an encoded bitmap, write the size first. Otherwise store a 0 so the reader knows not to
157 // decode.
158 if (fBitmapHeap != NULL) {
159 SkASSERT(NULL == fBitmapEncoder);
160 // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
161 this->writeUInt(0);
162 int32_t slot = fBitmapHeap->insert(bitmap);
163 fWriter.write32(slot);
164 // crbug.com/155875
165 // The generation ID is not required information. We write it to prevent collisions
166 // in SkFlatDictionary. It is possible to get a collision when a previously
167 // unflattened (i.e. stale) instance of a similar flattenable is in the dictionary
168 // and the instance currently being written is re-using the same slot from the
169 // bitmap heap.
170 fWriter.write32(bitmap.getGenerationID());
171 return;
172 }
173 bool encoded = false;
174 // Before attempting to encode the SkBitmap, check to see if there is already an encoded
175 // version.
176 SkPixelRef* ref = bitmap.pixelRef();
177 if (ref != NULL) {
178 SkAutoDataUnref data(ref->refEncodedData());
179 if (data.get() != NULL) {
180 // Write the length to indicate that the bitmap was encoded successfully, followed
181 // by the actual data. This must match the case where fBitmapEncoder is used so the
182 // reader need not know the difference.
183 this->writeUInt(data->size());
184 fWriter.writePad(data->data(), data->size());
185 encoded = true;
186 }
187 }
188 if (fBitmapEncoder != NULL && !encoded) {
189 SkASSERT(NULL == fBitmapHeap);
190 SkDynamicMemoryWStream stream;
191 if (fBitmapEncoder(&stream, bitmap)) {
192 uint32_t offset = fWriter.bytesWritten();
193 // Write the length to indicate that the bitmap was encoded successfully, followed
194 // by the actual data. This must match the case where the original data is used so the
195 // reader need not know the difference.
196 size_t length = stream.getOffset();
197 this->writeUInt(length);
198 if (stream.read(fWriter.reservePad(length), 0, length)) {
199 encoded = true;
200 } else {
201 // Writing the stream failed, so go back to original state to store another way.
202 fWriter.rewindToOffset(offset);
203 }
204 }
205 }
206 if (encoded) {
207 // Write the width and height in case the reader does not have a decoder.
208 this->writeInt(bitmap.width());
209 this->writeInt(bitmap.height());
210 } else {
211 // Bitmap was not encoded. Record a zero, implying that the reader need not decode.
212 this->writeUInt(0);
213 bitmap.flatten(*this);
214 }
215 }
216
writeTypeface(SkTypeface * obj)217 void SkOrderedWriteBuffer::writeTypeface(SkTypeface* obj) {
218 if (NULL == obj || NULL == fTFSet) {
219 fWriter.write32(0);
220 } else {
221 fWriter.write32(fTFSet->add(obj));
222 }
223 }
224
setFactoryRecorder(SkFactorySet * rec)225 SkFactorySet* SkOrderedWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
226 SkRefCnt_SafeAssign(fFactorySet, rec);
227 if (fNamedFactorySet != NULL) {
228 fNamedFactorySet->unref();
229 fNamedFactorySet = NULL;
230 }
231 return rec;
232 }
233
setNamedFactoryRecorder(SkNamedFactorySet * rec)234 SkNamedFactorySet* SkOrderedWriteBuffer::setNamedFactoryRecorder(SkNamedFactorySet* rec) {
235 SkRefCnt_SafeAssign(fNamedFactorySet, rec);
236 if (fFactorySet != NULL) {
237 fFactorySet->unref();
238 fFactorySet = NULL;
239 }
240 return rec;
241 }
242
setTypefaceRecorder(SkRefCntSet * rec)243 SkRefCntSet* SkOrderedWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
244 SkRefCnt_SafeAssign(fTFSet, rec);
245 return rec;
246 }
247
setBitmapHeap(SkBitmapHeap * bitmapHeap)248 void SkOrderedWriteBuffer::setBitmapHeap(SkBitmapHeap* bitmapHeap) {
249 SkRefCnt_SafeAssign(fBitmapHeap, bitmapHeap);
250 if (bitmapHeap != NULL) {
251 SkASSERT(NULL == fBitmapEncoder);
252 fBitmapEncoder = NULL;
253 }
254 }
255
setBitmapEncoder(SkSerializationHelpers::EncodeBitmap bitmapEncoder)256 void SkOrderedWriteBuffer::setBitmapEncoder(SkSerializationHelpers::EncodeBitmap bitmapEncoder) {
257 fBitmapEncoder = bitmapEncoder;
258 if (bitmapEncoder != NULL) {
259 SkASSERT(NULL == fBitmapHeap);
260 SkSafeUnref(fBitmapHeap);
261 fBitmapHeap = NULL;
262 }
263 }
264
writeFlattenable(SkFlattenable * flattenable)265 void SkOrderedWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
266 /*
267 * If we have a factoryset, then the first 32bits tell us...
268 * 0: failure to write the flattenable
269 * >0: (1-based) index into the SkFactorySet or SkNamedFactorySet
270 * If we don't have a factoryset, then the first "ptr" is either the
271 * factory, or null for failure.
272 *
273 * The distinction is important, since 0-index is 32bits (always), but a
274 * 0-functionptr might be 32 or 64 bits.
275 */
276
277 SkFlattenable::Factory factory = NULL;
278 if (flattenable) {
279 factory = flattenable->getFactory();
280 }
281 if (NULL == factory) {
282 if (fFactorySet != NULL || fNamedFactorySet != NULL) {
283 this->write32(0);
284 } else {
285 this->writeFunctionPtr(NULL);
286 }
287 return;
288 }
289
290 /*
291 * We can write 1 of 3 versions of the flattenable:
292 * 1. function-ptr : this is the fastest for the reader, but assumes that
293 * the writer and reader are in the same process.
294 * 2. index into fFactorySet : This is assumes the writer will later
295 * resolve the function-ptrs into strings for its reader. SkPicture
296 * does exactly this, by writing a table of names (matching the indices)
297 * up front in its serialized form.
298 * 3. index into fNamedFactorySet. fNamedFactorySet will also store the
299 * name. SkGPipe uses this technique so it can write the name to its
300 * stream before writing the flattenable.
301 */
302 if (fFactorySet) {
303 this->write32(fFactorySet->add(factory));
304 } else if (fNamedFactorySet) {
305 int32_t index = fNamedFactorySet->find(factory);
306 this->write32(index);
307 if (0 == index) {
308 return;
309 }
310 } else {
311 this->writeFunctionPtr((void*)factory);
312 }
313
314 // make room for the size of the flattened object
315 (void)fWriter.reserve(sizeof(uint32_t));
316 // record the current size, so we can subtract after the object writes.
317 uint32_t offset = fWriter.size();
318 // now flatten the object
319 flattenObject(flattenable, *this);
320 uint32_t objSize = fWriter.size() - offset;
321 // record the obj's size
322 *fWriter.peek32(offset - sizeof(uint32_t)) = objSize;
323 }
324