• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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