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