blob: 1ebaac4da860993fca7061add986496fb3161f85 [file] [log] [blame]
djsollen@google.com2b2ede32012-04-12 13:24:04 +00001
2/*
djsollen@google.comc73dd5c2012-08-07 15:54:32 +00003 * Copyright 2012 Google Inc.
djsollen@google.com2b2ede32012-04-12 13:24:04 +00004 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
scroggo@google.comf8d7d272013-02-22 21:38:35 +00009#include "SkBitmap.h"
scroggo@google.com49ce11b2013-04-25 18:29:32 +000010#include "SkErrorInternals.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000011#include "SkOrderedReadBuffer.h"
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000012#include "SkStream.h"
djsollen@google.com2b2ede32012-04-12 13:24:04 +000013#include "SkTypeface.h"
14
djsollen@google.com21830d92012-08-07 19:49:41 +000015SkOrderedReadBuffer::SkOrderedReadBuffer() : INHERITED() {
16 fMemoryPtr = NULL;
djsollen@google.com2b2ede32012-04-12 13:24:04 +000017
djsollen@google.com21830d92012-08-07 19:49:41 +000018 fBitmapStorage = NULL;
19 fTFArray = NULL;
20 fTFCount = 0;
21
22 fFactoryTDArray = NULL;
23 fFactoryArray = NULL;
24 fFactoryCount = 0;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000025 fBitmapDecoder = NULL;
scroggo@google.comc6e5fcb2013-07-08 22:00:17 +000026#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
27 fDecodedBitmapIndex = -1;
28#endif // DEBUG_NON_DETERMINISTIC_ASSERT
djsollen@google.com21830d92012-08-07 19:49:41 +000029}
30
31SkOrderedReadBuffer::SkOrderedReadBuffer(const void* data, size_t size) : INHERITED() {
djsollen@google.com2b2ede32012-04-12 13:24:04 +000032 fReader.setMemory(data, size);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000033 fMemoryPtr = NULL;
34
djsollen@google.com21830d92012-08-07 19:49:41 +000035 fBitmapStorage = NULL;
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000036 fTFArray = NULL;
37 fTFCount = 0;
38
39 fFactoryTDArray = NULL;
40 fFactoryArray = NULL;
41 fFactoryCount = 0;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000042 fBitmapDecoder = NULL;
scroggo@google.comc6e5fcb2013-07-08 22:00:17 +000043#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
44 fDecodedBitmapIndex = -1;
45#endif // DEBUG_NON_DETERMINISTIC_ASSERT
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000046}
47
48SkOrderedReadBuffer::SkOrderedReadBuffer(SkStream* stream) {
49 const size_t length = stream->getLength();
50 fMemoryPtr = sk_malloc_throw(length);
51 stream->read(fMemoryPtr, length);
52 fReader.setMemory(fMemoryPtr, length);
djsollen@google.com21830d92012-08-07 19:49:41 +000053
54 fBitmapStorage = NULL;
55 fTFArray = NULL;
56 fTFCount = 0;
57
58 fFactoryTDArray = NULL;
59 fFactoryArray = NULL;
60 fFactoryCount = 0;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +000061 fBitmapDecoder = NULL;
scroggo@google.comc6e5fcb2013-07-08 22:00:17 +000062#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
63 fDecodedBitmapIndex = -1;
64#endif // DEBUG_NON_DETERMINISTIC_ASSERT
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000065}
66
67SkOrderedReadBuffer::~SkOrderedReadBuffer() {
68 sk_free(fMemoryPtr);
djsollen@google.com21830d92012-08-07 19:49:41 +000069 SkSafeUnref(fBitmapStorage);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +000070}
71
72bool SkOrderedReadBuffer::readBool() {
73 return fReader.readBool();
74}
75
76SkColor SkOrderedReadBuffer::readColor() {
77 return fReader.readInt();
78}
79
80SkFixed SkOrderedReadBuffer::readFixed() {
81 return fReader.readS32();
82}
83
84int32_t SkOrderedReadBuffer::readInt() {
85 return fReader.readInt();
86}
87
88SkScalar SkOrderedReadBuffer::readScalar() {
89 return fReader.readScalar();
90}
91
92uint32_t SkOrderedReadBuffer::readUInt() {
93 return fReader.readU32();
94}
95
96int32_t SkOrderedReadBuffer::read32() {
97 return fReader.readInt();
98}
99
djsollen@google.com77687512013-05-21 16:17:14 +0000100void SkOrderedReadBuffer::readString(SkString* string) {
101 size_t len;
102 const char* strContents = fReader.readString(&len);
103 string->set(strContents, len);
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000104}
105
106void* SkOrderedReadBuffer::readEncodedString(size_t* length, SkPaint::TextEncoding encoding) {
humper@google.com0e515772013-01-07 19:54:40 +0000107 SkDEBUGCODE(int32_t encodingType = ) fReader.readInt();
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000108 SkASSERT(encodingType == encoding);
109 *length = fReader.readInt();
110 void* data = sk_malloc_throw(*length);
111 memcpy(data, fReader.skip(SkAlign4(*length)), *length);
112 return data;
113}
114
115void SkOrderedReadBuffer::readPoint(SkPoint* point) {
116 point->fX = fReader.readScalar();
117 point->fY = fReader.readScalar();
118}
119
120void SkOrderedReadBuffer::readMatrix(SkMatrix* matrix) {
121 fReader.readMatrix(matrix);
122}
123
124void SkOrderedReadBuffer::readIRect(SkIRect* rect) {
125 memcpy(rect, fReader.skip(sizeof(SkIRect)), sizeof(SkIRect));
126}
127
128void SkOrderedReadBuffer::readRect(SkRect* rect) {
129 memcpy(rect, fReader.skip(sizeof(SkRect)), sizeof(SkRect));
130}
131
132void SkOrderedReadBuffer::readRegion(SkRegion* region) {
133 fReader.readRegion(region);
134}
135
136void SkOrderedReadBuffer::readPath(SkPath* path) {
137 fReader.readPath(path);
138}
139
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000140bool SkOrderedReadBuffer::readArray(void* value, size_t size, size_t elementSize) {
141 const size_t count = this->getArrayCount();
142 if (count == size) {
143 (void)fReader.skip(sizeof(uint32_t)); // Skip array count
144 const size_t byteLength = count * elementSize;
145 memcpy(value, fReader.skip(SkAlign4(byteLength)), byteLength);
146 return true;
147 }
148 SkASSERT(false);
149 fReader.skip(fReader.available());
150 return false;
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000151}
152
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000153bool SkOrderedReadBuffer::readByteArray(void* value, size_t size) {
154 return readArray(static_cast<unsigned char*>(value), size, sizeof(unsigned char));
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000155}
156
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000157bool SkOrderedReadBuffer::readColorArray(SkColor* colors, size_t size) {
158 return readArray(colors, size, sizeof(SkColor));
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000159}
160
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000161bool SkOrderedReadBuffer::readIntArray(int32_t* values, size_t size) {
162 return readArray(values, size, sizeof(int32_t));
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000163}
164
commit-bot@chromium.org02512882013-10-31 18:37:50 +0000165bool SkOrderedReadBuffer::readPointArray(SkPoint* points, size_t size) {
166 return readArray(points, size, sizeof(SkPoint));
167}
168
169bool SkOrderedReadBuffer::readScalarArray(SkScalar* values, size_t size) {
170 return readArray(values, size, sizeof(SkScalar));
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000171}
172
173uint32_t SkOrderedReadBuffer::getArrayCount() {
174 return *(uint32_t*)fReader.peek();
175}
176
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000177void SkOrderedReadBuffer::readBitmap(SkBitmap* bitmap) {
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000178 const int width = this->readInt();
179 const int height = this->readInt();
180 // The writer stored a boolean value to determine whether an SkBitmapHeap was used during
181 // writing.
182 if (this->readBool()) {
183 // An SkBitmapHeap was used for writing. Read the index from the stream and find the
184 // corresponding SkBitmap in fBitmapStorage.
185 const uint32_t index = fReader.readU32();
186 fReader.readU32(); // bitmap generation ID (see SkOrderedWriteBuffer::writeBitmap)
187 if (fBitmapStorage) {
188 *bitmap = *fBitmapStorage->getBitmap(index);
189 fBitmapStorage->releaseRef(index);
190 return;
scroggo@google.com0cb7df92013-04-30 02:37:56 +0000191 } else {
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000192 // The bitmap was stored in a heap, but there is no way to access it. Set an error and
193 // fall through to use a place holder bitmap.
194 SkErrorInternals::SetError(kParseError_SkError, "SkOrderedWriteBuffer::writeBitmap "
195 "stored the SkBitmap in an SkBitmapHeap, but "
196 "SkOrderedReadBuffer has no SkBitmapHeapReader to "
197 "retrieve the SkBitmap.");
scroggo@google.com0cb7df92013-04-30 02:37:56 +0000198 }
199 } else {
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000200 // The writer stored false, meaning the SkBitmap was not stored in an SkBitmapHeap.
201 const size_t length = this->readUInt();
202 if (length > 0) {
scroggo@google.comc6e5fcb2013-07-08 22:00:17 +0000203#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
204 fDecodedBitmapIndex++;
205#endif // DEBUG_NON_DETERMINISTIC_ASSERT
scroggo@google.com2d76d932013-05-31 14:39:54 +0000206 // A non-zero size means the SkBitmap was encoded. Read the data and pixel
207 // offset.
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000208 const void* data = this->skip(length);
scroggo@google.com2d76d932013-05-31 14:39:54 +0000209 const int32_t xOffset = fReader.readS32();
210 const int32_t yOffset = fReader.readS32();
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000211 if (fBitmapDecoder != NULL && fBitmapDecoder(data, length, bitmap)) {
scroggo@google.com719a3732013-05-16 19:35:39 +0000212 if (bitmap->width() == width && bitmap->height() == height) {
scroggo@google.comc6e5fcb2013-07-08 22:00:17 +0000213#ifdef DEBUG_NON_DETERMINISTIC_ASSERT
214 if (0 != xOffset || 0 != yOffset) {
215 SkDebugf("SkOrderedReadBuffer::readBitmap: heights match,"
216 " but offset is not zero. \nInfo about the bitmap:"
217 "\n\tIndex: %d\n\tDimensions: [%d %d]\n\tEncoded"
218 " data size: %d\n\tOffset: (%d, %d)\n",
219 fDecodedBitmapIndex, width, height, length, xOffset,
220 yOffset);
221 }
222#endif // DEBUG_NON_DETERMINISTIC_ASSERT
scroggo@google.com2d76d932013-05-31 14:39:54 +0000223 // If the width and height match, there should be no offset.
224 SkASSERT(0 == xOffset && 0 == yOffset);
scroggo@google.com719a3732013-05-16 19:35:39 +0000225 return;
226 }
227
228 // This case can only be reached if extractSubset was called, so
scroggo@google.com02076832013-12-16 20:02:03 +0000229 // the recorded width and height must be smaller than or equal to
scroggo@google.com719a3732013-05-16 19:35:39 +0000230 // the encoded width and height.
scroggo@google.com02076832013-12-16 20:02:03 +0000231 // FIXME (scroggo): This assert assumes that our decoder and the
232 // sources encoder agree on the width and height which may not
233 // always be the case. Removing until it can be investigated
234 // further.
235 //SkASSERT(width <= bitmap->width() && height <= bitmap->height());
scroggo@google.com719a3732013-05-16 19:35:39 +0000236
scroggo@google.com719a3732013-05-16 19:35:39 +0000237 SkBitmap subsetBm;
scroggo@google.com2d76d932013-05-31 14:39:54 +0000238 SkIRect subset = SkIRect::MakeXYWH(xOffset, yOffset, width, height);
scroggo@google.com719a3732013-05-16 19:35:39 +0000239 if (bitmap->extractSubset(&subsetBm, subset)) {
240 bitmap->swap(subsetBm);
241 return;
242 }
scroggo@google.com0cb7df92013-04-30 02:37:56 +0000243 }
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000244 // This bitmap was encoded when written, but we are unable to decode, possibly due to
245 // not having a decoder.
246 SkErrorInternals::SetError(kParseError_SkError,
247 "Could not decode bitmap. Resulting bitmap will be red.");
scroggo@google.com0cb7df92013-04-30 02:37:56 +0000248 } else {
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000249 // A size of zero means the SkBitmap was simply flattened.
250 bitmap->unflatten(*this);
251 return;
scroggo@google.com5a7c6be2012-10-04 21:46:08 +0000252 }
djsollen@google.com21830d92012-08-07 19:49:41 +0000253 }
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000254 // Could not read the SkBitmap. Use a placeholder bitmap.
reed@google.com9ebcac52014-01-24 18:53:42 +0000255 bitmap->allocPixels(SkImageInfo::MakeN32Premul(width, height));
scroggo@google.com2983ddd2013-05-07 14:45:40 +0000256 bitmap->eraseColor(SK_ColorRED);
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000257}
258
259SkTypeface* SkOrderedReadBuffer::readTypeface() {
djsollen@google.comc73dd5c2012-08-07 15:54:32 +0000260
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000261 uint32_t index = fReader.readU32();
262 if (0 == index || index > (unsigned)fTFCount) {
263 if (index) {
264 SkDebugf("====== typeface index %d\n", index);
265 }
266 return NULL;
267 } else {
268 SkASSERT(fTFArray);
269 return fTFArray[index - 1];
270 }
271}
272
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000273SkFlattenable* SkOrderedReadBuffer::readFlattenable(SkFlattenable::Type ft) {
reed@google.com35348222013-10-16 13:05:06 +0000274 //
commit-bot@chromium.orgc0b7e102013-10-23 17:06:21 +0000275 // TODO: confirm that ft matches the factory we decide to use
reed@google.com35348222013-10-16 13:05:06 +0000276 //
277
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000278 SkFlattenable::Factory factory = NULL;
279
280 if (fFactoryCount > 0) {
281 int32_t index = fReader.readU32();
282 if (0 == index) {
283 return NULL; // writer failed to give us the flattenable
284 }
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000285 index -= 1; // we stored the index-base-1
286 SkASSERT(index < fFactoryCount);
287 factory = fFactoryArray[index];
288 } else if (fFactoryTDArray) {
scroggo@google.com0c3e5fe2012-08-01 19:34:20 +0000289 int32_t index = fReader.readU32();
290 if (0 == index) {
291 return NULL; // writer failed to give us the flattenable
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000292 }
scroggo@google.com0c3e5fe2012-08-01 19:34:20 +0000293 index -= 1; // we stored the index-base-1
294 factory = (*fFactoryTDArray)[index];
djsollen@google.com2b2ede32012-04-12 13:24:04 +0000295 } else {
296 factory = (SkFlattenable::Factory)readFunctionPtr();
297 if (NULL == factory) {
298 return NULL; // writer failed to give us the flattenable
299 }
300 }
301
302 // if we get here, factory may still be null, but if that is the case, the
303 // failure was ours, not the writer.
304 SkFlattenable* obj = NULL;
305 uint32_t sizeRecorded = fReader.readU32();
306 if (factory) {
307 uint32_t offset = fReader.offset();
308 obj = (*factory)(*this);
309 // check that we read the amount we expected
310 uint32_t sizeRead = fReader.offset() - offset;
311 if (sizeRecorded != sizeRead) {
312 // we could try to fix up the offset...
313 sk_throw();
314 }
315 } else {
316 // we must skip the remaining data
317 fReader.skip(sizeRecorded);
318 }
319 return obj;
320}