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 "SkBitmap.h"
10#include "SkErrorInternals.h"
11#include "SkReadBuffer.h"
12#include "SkStream.h"
13#include "SkTypeface.h"
14
15static uint32_t default_flags() {
16    uint32_t flags = 0;
17#ifdef SK_SCALAR_IS_FLOAT
18    flags |= SkReadBuffer::kScalarIsFloat_Flag;
19#endif
20    if (8 == sizeof(void*)) {
21        flags |= SkReadBuffer::kPtrIs64Bit_Flag;
22    }
23    return flags;
24}
25
26SkReadBuffer::SkReadBuffer() {
27    fFlags = default_flags();
28    fVersion = 0;
29    fMemoryPtr = NULL;
30
31    fBitmapStorage = NULL;
32    fTFArray = NULL;
33    fTFCount = 0;
34
35    fFactoryTDArray = NULL;
36    fFactoryArray = NULL;
37    fFactoryCount = 0;
38    fBitmapDecoder = NULL;
39#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
40    fDecodedBitmapIndex = -1;
41#endif // DEBUG_NON_DETERMINISTIC_ASSERT
42}
43
44SkReadBuffer::SkReadBuffer(const void* data, size_t size) {
45    fFlags = default_flags();
46    fVersion = 0;
47    fReader.setMemory(data, size);
48    fMemoryPtr = NULL;
49
50    fBitmapStorage = NULL;
51    fTFArray = NULL;
52    fTFCount = 0;
53
54    fFactoryTDArray = NULL;
55    fFactoryArray = NULL;
56    fFactoryCount = 0;
57    fBitmapDecoder = NULL;
58#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
59    fDecodedBitmapIndex = -1;
60#endif // DEBUG_NON_DETERMINISTIC_ASSERT
61}
62
63SkReadBuffer::SkReadBuffer(SkStream* stream) {
64    fFlags = default_flags();
65    fVersion = 0;
66    const size_t length = stream->getLength();
67    fMemoryPtr = sk_malloc_throw(length);
68    stream->read(fMemoryPtr, length);
69    fReader.setMemory(fMemoryPtr, length);
70
71    fBitmapStorage = NULL;
72    fTFArray = NULL;
73    fTFCount = 0;
74
75    fFactoryTDArray = NULL;
76    fFactoryArray = NULL;
77    fFactoryCount = 0;
78    fBitmapDecoder = NULL;
79#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
80    fDecodedBitmapIndex = -1;
81#endif // DEBUG_NON_DETERMINISTIC_ASSERT
82}
83
84SkReadBuffer::~SkReadBuffer() {
85    sk_free(fMemoryPtr);
86    SkSafeUnref(fBitmapStorage);
87}
88
89bool SkReadBuffer::readBool() {
90    return fReader.readBool();
91}
92
93SkColor SkReadBuffer::readColor() {
94    return fReader.readInt();
95}
96
97SkFixed SkReadBuffer::readFixed() {
98    return fReader.readS32();
99}
100
101int32_t SkReadBuffer::readInt() {
102    return fReader.readInt();
103}
104
105SkScalar SkReadBuffer::readScalar() {
106    return fReader.readScalar();
107}
108
109uint32_t SkReadBuffer::readUInt() {
110    return fReader.readU32();
111}
112
113int32_t SkReadBuffer::read32() {
114    return fReader.readInt();
115}
116
117void SkReadBuffer::readString(SkString* string) {
118    size_t len;
119    const char* strContents = fReader.readString(&len);
120    string->set(strContents, len);
121}
122
123void* SkReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
124    SkDEBUGCODE(int32_t encodingType = ) fReader.readInt();
125    SkASSERT(encodingType == encoding);
126    *length =  fReader.readInt();
127    void* data = sk_malloc_throw(*length);
128    memcpy(data, fReader.skip(SkAlign4(*length)), *length);
129    return data;
130}
131
132void SkReadBuffer::readPoint(SkPoint* point) {
133    point->fX = fReader.readScalar();
134    point->fY = fReader.readScalar();
135}
136
137void SkReadBuffer::readMatrix(SkMatrix* matrix) {
138    fReader.readMatrix(matrix);
139}
140
141void SkReadBuffer::readIRect(SkIRect* rect) {
142    memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect));
143}
144
145void SkReadBuffer::readRect(SkRect* rect) {
146    memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect));
147}
148
149void SkReadBuffer::readRegion(SkRegion* region) {
150    fReader.readRegion(region);
151}
152
153void SkReadBuffer::readPath(SkPath* path) {
154    fReader.readPath(path);
155}
156
157bool SkReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
158    const size_t count = this->getArrayCount();
159    if (count == size) {
160        (void)fReader.skip(sizeof(uint32_t)); // Skip array count
161        const size_t byteLength = count * elementSize;
162        memcpy(value, fReader.skip(SkAlign4(byteLength)), byteLength);
163        return true;
164    }
165    SkASSERT(false);
166    fReader.skip(fReader.available());
167    return false;
168}
169
170bool SkReadBuffer::readByteArray(void* value, size_t size) {
171    return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
172}
173
174bool SkReadBuffer::readColorArray(SkColor* colors, size_t size) {
175    return readArray(colors, size, sizeof(SkColor));
176}
177
178bool SkReadBuffer::readIntArray(int32_t* values, size_t size) {
179    return readArray(values, size, sizeof(int32_t));
180}
181
182bool SkReadBuffer::readPointArray(SkPoint* points, size_t size) {
183    return readArray(points, size, sizeof(SkPoint));
184}
185
186bool SkReadBuffer::readScalarArray(SkScalar* values, size_t size) {
187    return readArray(values, size, sizeof(SkScalar));
188}
189
190uint32_t SkReadBuffer::getArrayCount() {
191    return *(uint32_t*)fReader.peek();
192}
193
194bool SkReadBuffer::readBitmap(SkBitmap* bitmap) {
195    const int width = this->readInt();
196    const int height = this->readInt();
197    // The writer stored a boolean value to determine whether an SkBitmapHeap was used during
198    // writing.
199    if (this->readBool()) {
200        // An SkBitmapHeap was used for writing. Read the index from the stream and find the
201        // corresponding SkBitmap in fBitmapStorage.
202        const uint32_t index = this->readUInt();
203        this->readUInt(); // bitmap generation ID (see SkWriteBuffer::writeBitmap)
204        if (fBitmapStorage) {
205            *bitmap = *fBitmapStorage->getBitmap(index);
206            fBitmapStorage->releaseRef(index);
207            return true;
208        } else {
209            // The bitmap was stored in a heap, but there is no way to access it. Set an error and
210            // fall through to use a place holder bitmap.
211            SkErrorInternals::SetError(kParseError_SkError, "SkWriteBuffer::writeBitmap "
212                                       "stored the SkBitmap in an SkBitmapHeap, but "
213                                       "SkReadBuffer has no SkBitmapHeapReader to "
214                                       "retrieve the SkBitmap.");
215        }
216    } else {
217        // The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
218        const size_t length = this->readUInt();
219        if (length > 0) {
220#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
221            fDecodedBitmapIndex++;
222#endif // DEBUG_NON_DETERMINISTIC_ASSERT
223            // A non-zero size means the SkBitmap was encoded. Read the data and pixel
224            // offset.
225            const void* data = this->skip(length);
226            const int32_t xOffset = this->readInt();
227            const int32_t yOffset = this->readInt();
228            if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
229                if (bitmap->width() == width && bitmap->height() == height) {
230#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
231                    if (0 != xOffset || 0 != yOffset) {
232                        SkDebugf("SkReadBuffer::readBitmap: heights match,"
233                                 " but offset is not zero. \nInfo about the bitmap:"
234                                 "\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded"
235                                 " data size: %d\n\tOffset: (%d, %d)\n",
236                                 fDecodedBitmapIndex, width, height, length, xOffset,
237                                 yOffset);
238                    }
239#endif // DEBUG_NON_DETERMINISTIC_ASSERT
240                    // If the width and height match, there should be no offset.
241                    SkASSERT(0 == xOffset && 0 == yOffset);
242                    return true;
243                }
244
245                // This case can only be reached if extractSubset was called, so
246                // the recorded width and height must be smaller than or equal to
247                // the encoded width and height.
248                // FIXME (scroggo): This assert assumes that our decoder and the
249                // sources encoder agree on the width and height which may not
250                // always be the case. Removing until it can be investigated
251                // further.
252                //SkASSERT(width <= bitmap->width() && height <= bitmap->height());
253
254                SkBitmap subsetBm;
255                SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height);
256                if (bitmap->extractSubset(&subsetBm, subset)) {
257                    bitmap->swap(subsetBm);
258                    return true;
259                }
260            }
261            // This bitmap was encoded when written, but we are unable to decode, possibly due to
262            // not having a decoder.
263            SkErrorInternals::SetError(kParseError_SkError,
264                                       "Could not decode bitmap. Resulting bitmap will be red.");
265        } else {
266            // A size of zero means the SkBitmap was simply flattened.
267            if (this->isVersionLT(kNoMoreBitmapFlatten_Version)) {
268                SkBitmap tmp;
269                tmp.legacyUnflatten(*this);
270                // just throw this guy away
271            } else {
272                if (SkBitmap::ReadRawPixels(this, bitmap)) {
273                    return true;
274                }
275            }
276        }
277    }
278    // Could not read the SkBitmap. Use a placeholder bitmap.
279    bitmap->setInfo(SkImageInfo::MakeUnknown(width, height));
280    return false;
281}
282
283SkTypeface* SkReadBuffer::readTypeface() {
284
285    uint32_t index = fReader.readU32();
286    if (0 == index || index > (unsigned)fTFCount) {
287        if (index) {
288            SkDebugf("====== typeface index %d\n", index);
289        }
290        return NULL;
291    } else {
292        SkASSERT(fTFArray);
293        return fTFArray[index - 1];
294    }
295}
296
297SkFlattenable* SkReadBuffer::readFlattenable(SkFlattenable::Type ft) {
298    //
299    // TODO: confirm that ft matches the factory we decide to use
300    //
301
302    SkFlattenable::Factory factory = NULL;
303
304    if (fFactoryCount > 0) {
305        int32_t index = fReader.readU32();
306        if (0 == index) {
307            return NULL; // writer failed to give us the flattenable
308        }
309        index -= 1;     // we stored the index-base-1
310        SkASSERT(index < fFactoryCount);
311        factory = fFactoryArray[index];
312    } else if (fFactoryTDArray) {
313        int32_t index = fReader.readU32();
314        if (0 == index) {
315            return NULL; // writer failed to give us the flattenable
316        }
317        index -= 1;     // we stored the index-base-1
318        factory = (*fFactoryTDArray)[index];
319    } else {
320        factory = (SkFlattenable::Factory)readFunctionPtr();
321        if (NULL == factory) {
322            return NULL; // writer failed to give us the flattenable
323        }
324    }
325
326    // if we get here, factory may still be null, but if that is the case, the
327    // failure was ours, not the writer.
328    SkFlattenable* obj = NULL;
329    uint32_t sizeRecorded = fReader.readU32();
330    if (factory) {
331        size_t offset = fReader.offset();
332        obj = (*factory)(*this);
333        // check that we read the amount we expected
334        size_t sizeRead = fReader.offset() - offset;
335        if (sizeRecorded != sizeRead) {
336            // we could try to fix up the offset...
337            sk_throw();
338        }
339    } else {
340        // we must skip the remaining data
341        fReader.skip(sizeRecorded);
342    }
343    return obj;
344}
345
346/**
347 *  Needs to follow the same pattern as readFlattenable(), but explicitly skip whatever data
348 *  has been written.
349 */
350void SkReadBuffer::skipFlattenable() {
351    if (fFactoryCount > 0) {
352        if (0 == fReader.readU32()) {
353            return;
354        }
355    } else if (fFactoryTDArray) {
356        if (0 == fReader.readU32()) {
357            return;
358        }
359    } else {
360        if (NULL == this->readFunctionPtr()) {
361            return;
362        }
363    }
364    uint32_t sizeRecorded = fReader.readU32();
365    fReader.skip(sizeRecorded);
366}
367