1 /*
2 * Copyright 2013 Google Inc.
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8 #include "SkBitmapDevice.h"
9 #include "SkBitmapSource.h"
10 #include "SkCanvas.h"
11 #include "SkMallocPixelRef.h"
12 #include "SkPictureRecorder.h"
13 #include "SkTemplates.h"
14 #include "SkWriteBuffer.h"
15 #include "SkValidatingReadBuffer.h"
16 #include "SkXfermodeImageFilter.h"
17 #include "Test.h"
18
19 static const uint32_t kArraySize = 64;
20 static const int kBitmapSize = 256;
21
22 template<typename T>
TestAlignment(T * testObj,skiatest::Reporter * reporter)23 static void TestAlignment(T* testObj, skiatest::Reporter* reporter) {
24 // Test memory read/write functions directly
25 unsigned char dataWritten[1024];
26 size_t bytesWrittenToMemory = testObj->writeToMemory(dataWritten);
27 REPORTER_ASSERT(reporter, SkAlign4(bytesWrittenToMemory) == bytesWrittenToMemory);
28 size_t bytesReadFromMemory = testObj->readFromMemory(dataWritten, bytesWrittenToMemory);
29 REPORTER_ASSERT(reporter, SkAlign4(bytesReadFromMemory) == bytesReadFromMemory);
30 }
31
32 template<typename T> struct SerializationUtils {
33 // Generic case for flattenables
WriteSerializationUtils34 static void Write(SkWriteBuffer& writer, const T* flattenable) {
35 writer.writeFlattenable(flattenable);
36 }
ReadSerializationUtils37 static void Read(SkValidatingReadBuffer& reader, T** flattenable) {
38 *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType());
39 }
40 };
41
42 template<> struct SerializationUtils<SkMatrix> {
WriteSerializationUtils43 static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) {
44 writer.writeMatrix(*matrix);
45 }
ReadSerializationUtils46 static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) {
47 reader.readMatrix(matrix);
48 }
49 };
50
51 template<> struct SerializationUtils<SkPath> {
WriteSerializationUtils52 static void Write(SkWriteBuffer& writer, const SkPath* path) {
53 writer.writePath(*path);
54 }
ReadSerializationUtils55 static void Read(SkValidatingReadBuffer& reader, SkPath* path) {
56 reader.readPath(path);
57 }
58 };
59
60 template<> struct SerializationUtils<SkRegion> {
WriteSerializationUtils61 static void Write(SkWriteBuffer& writer, const SkRegion* region) {
62 writer.writeRegion(*region);
63 }
ReadSerializationUtils64 static void Read(SkValidatingReadBuffer& reader, SkRegion* region) {
65 reader.readRegion(region);
66 }
67 };
68
69 template<> struct SerializationUtils<SkString> {
WriteSerializationUtils70 static void Write(SkWriteBuffer& writer, const SkString* string) {
71 writer.writeString(string->c_str());
72 }
ReadSerializationUtils73 static void Read(SkValidatingReadBuffer& reader, SkString* string) {
74 reader.readString(string);
75 }
76 };
77
78 template<> struct SerializationUtils<unsigned char> {
WriteSerializationUtils79 static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) {
80 writer.writeByteArray(data, arraySize);
81 }
ReadSerializationUtils82 static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) {
83 return reader.readByteArray(data, arraySize);
84 }
85 };
86
87 template<> struct SerializationUtils<SkColor> {
WriteSerializationUtils88 static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) {
89 writer.writeColorArray(data, arraySize);
90 }
ReadSerializationUtils91 static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) {
92 return reader.readColorArray(data, arraySize);
93 }
94 };
95
96 template<> struct SerializationUtils<int32_t> {
WriteSerializationUtils97 static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) {
98 writer.writeIntArray(data, arraySize);
99 }
ReadSerializationUtils100 static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) {
101 return reader.readIntArray(data, arraySize);
102 }
103 };
104
105 template<> struct SerializationUtils<SkPoint> {
WriteSerializationUtils106 static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) {
107 writer.writePointArray(data, arraySize);
108 }
ReadSerializationUtils109 static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) {
110 return reader.readPointArray(data, arraySize);
111 }
112 };
113
114 template<> struct SerializationUtils<SkScalar> {
WriteSerializationUtils115 static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) {
116 writer.writeScalarArray(data, arraySize);
117 }
ReadSerializationUtils118 static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) {
119 return reader.readScalarArray(data, arraySize);
120 }
121 };
122
123 template<typename T, bool testInvalid> struct SerializationTestUtils {
InvalidateDataSerializationTestUtils124 static void InvalidateData(unsigned char* data) {}
125 };
126
127 template<> struct SerializationTestUtils<SkString, true> {
InvalidateDataSerializationTestUtils128 static void InvalidateData(unsigned char* data) {
129 data[3] |= 0x80; // Reverse sign of 1st integer
130 }
131 };
132
133 template<typename T, bool testInvalid>
TestObjectSerializationNoAlign(T * testObj,skiatest::Reporter * reporter)134 static void TestObjectSerializationNoAlign(T* testObj, skiatest::Reporter* reporter) {
135 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
136 SerializationUtils<T>::Write(writer, testObj);
137 size_t bytesWritten = writer.bytesWritten();
138 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
139
140 unsigned char dataWritten[1024];
141 writer.writeToMemory(dataWritten);
142
143 SerializationTestUtils<T, testInvalid>::InvalidateData(dataWritten);
144
145 // Make sure this fails when it should (test with smaller size, but still multiple of 4)
146 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4);
147 T obj;
148 SerializationUtils<T>::Read(buffer, &obj);
149 REPORTER_ASSERT(reporter, !buffer.isValid());
150
151 // Make sure this succeeds when it should
152 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten);
153 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0));
154 T obj2;
155 SerializationUtils<T>::Read(buffer2, &obj2);
156 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0));
157 // This should have succeeded, since there are enough bytes to read this
158 REPORTER_ASSERT(reporter, buffer2.isValid() == !testInvalid);
159 // Note: This following test should always succeed, regardless of whether the buffer is valid,
160 // since if it is invalid, it will simply skip to the end, as if it had read the whole buffer.
161 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten);
162 }
163
164 template<typename T>
TestObjectSerialization(T * testObj,skiatest::Reporter * reporter)165 static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) {
166 TestObjectSerializationNoAlign<T, false>(testObj, reporter);
167 TestAlignment(testObj, reporter);
168 }
169
170 template<typename T>
TestFlattenableSerialization(T * testObj,bool shouldSucceed,skiatest::Reporter * reporter)171 static T* TestFlattenableSerialization(T* testObj, bool shouldSucceed,
172 skiatest::Reporter* reporter) {
173 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
174 SerializationUtils<T>::Write(writer, testObj);
175 size_t bytesWritten = writer.bytesWritten();
176 REPORTER_ASSERT(reporter, SkAlign4(bytesWritten) == bytesWritten);
177
178 unsigned char dataWritten[1024];
179 SkASSERT(bytesWritten <= sizeof(dataWritten));
180 writer.writeToMemory(dataWritten);
181
182 // Make sure this fails when it should (test with smaller size, but still multiple of 4)
183 SkValidatingReadBuffer buffer(dataWritten, bytesWritten - 4);
184 T* obj = NULL;
185 SerializationUtils<T>::Read(buffer, &obj);
186 REPORTER_ASSERT(reporter, !buffer.isValid());
187 REPORTER_ASSERT(reporter, NULL == obj);
188
189 // Make sure this succeeds when it should
190 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten);
191 const unsigned char* peekBefore = static_cast<const unsigned char*>(buffer2.skip(0));
192 T* obj2 = NULL;
193 SerializationUtils<T>::Read(buffer2, &obj2);
194 const unsigned char* peekAfter = static_cast<const unsigned char*>(buffer2.skip(0));
195 if (shouldSucceed) {
196 // This should have succeeded, since there are enough bytes to read this
197 REPORTER_ASSERT(reporter, buffer2.isValid());
198 REPORTER_ASSERT(reporter, static_cast<size_t>(peekAfter - peekBefore) == bytesWritten);
199 REPORTER_ASSERT(reporter, NULL != obj2);
200 } else {
201 // If the deserialization was supposed to fail, make sure it did
202 REPORTER_ASSERT(reporter, !buffer.isValid());
203 REPORTER_ASSERT(reporter, NULL == obj2);
204 }
205
206 return obj2; // Return object to perform further validity tests on it
207 }
208
209 template<typename T>
TestArraySerialization(T * data,skiatest::Reporter * reporter)210 static void TestArraySerialization(T* data, skiatest::Reporter* reporter) {
211 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
212 SerializationUtils<T>::Write(writer, data, kArraySize);
213 size_t bytesWritten = writer.bytesWritten();
214 // This should write the length (in 4 bytes) and the array
215 REPORTER_ASSERT(reporter, (4 + kArraySize * sizeof(T)) == bytesWritten);
216
217 unsigned char dataWritten[1024];
218 writer.writeToMemory(dataWritten);
219
220 // Make sure this fails when it should
221 SkValidatingReadBuffer buffer(dataWritten, bytesWritten);
222 T dataRead[kArraySize];
223 bool success = SerializationUtils<T>::Read(buffer, dataRead, kArraySize / 2);
224 // This should have failed, since the provided size was too small
225 REPORTER_ASSERT(reporter, !success);
226
227 // Make sure this succeeds when it should
228 SkValidatingReadBuffer buffer2(dataWritten, bytesWritten);
229 success = SerializationUtils<T>::Read(buffer2, dataRead, kArraySize);
230 // This should have succeeded, since there are enough bytes to read this
231 REPORTER_ASSERT(reporter, success);
232 }
233
TestBitmapSerialization(const SkBitmap & validBitmap,const SkBitmap & invalidBitmap,bool shouldSucceed,skiatest::Reporter * reporter)234 static void TestBitmapSerialization(const SkBitmap& validBitmap,
235 const SkBitmap& invalidBitmap,
236 bool shouldSucceed,
237 skiatest::Reporter* reporter) {
238 SkAutoTUnref<SkBitmapSource> validBitmapSource(SkBitmapSource::Create(validBitmap));
239 SkAutoTUnref<SkBitmapSource> invalidBitmapSource(SkBitmapSource::Create(invalidBitmap));
240 SkAutoTUnref<SkXfermode> mode(SkXfermode::Create(SkXfermode::kSrcOver_Mode));
241 SkAutoTUnref<SkXfermodeImageFilter> xfermodeImageFilter(
242 SkXfermodeImageFilter::Create(mode, invalidBitmapSource, validBitmapSource));
243
244 SkAutoTUnref<SkImageFilter> deserializedFilter(
245 TestFlattenableSerialization<SkImageFilter>(
246 xfermodeImageFilter, shouldSucceed, reporter));
247
248 // Try to render a small bitmap using the invalid deserialized filter
249 // to make sure we don't crash while trying to render it
250 if (shouldSucceed) {
251 SkBitmap bitmap;
252 bitmap.allocN32Pixels(24, 24);
253 SkCanvas canvas(bitmap);
254 canvas.clear(0x00000000);
255 SkPaint paint;
256 paint.setImageFilter(deserializedFilter);
257 canvas.clipRect(SkRect::MakeXYWH(0, 0, SkIntToScalar(24), SkIntToScalar(24)));
258 canvas.drawBitmap(bitmap, 0, 0, &paint);
259 }
260 }
261
setup_bitmap_for_canvas(SkBitmap * bitmap)262 static bool setup_bitmap_for_canvas(SkBitmap* bitmap) {
263 SkImageInfo info = SkImageInfo::Make(
264 kBitmapSize, kBitmapSize, kN32_SkColorType, kPremul_SkAlphaType);
265 return bitmap->allocPixels(info);
266 }
267
make_checkerboard_bitmap(SkBitmap & bitmap)268 static bool make_checkerboard_bitmap(SkBitmap& bitmap) {
269 bool success = setup_bitmap_for_canvas(&bitmap);
270
271 SkCanvas canvas(bitmap);
272 canvas.clear(0x00000000);
273 SkPaint darkPaint;
274 darkPaint.setColor(0xFF804020);
275 SkPaint lightPaint;
276 lightPaint.setColor(0xFF244484);
277 const int i = kBitmapSize / 8;
278 const SkScalar f = SkIntToScalar(i);
279 for (int y = 0; y < kBitmapSize; y += i) {
280 for (int x = 0; x < kBitmapSize; x += i) {
281 canvas.save();
282 canvas.translate(SkIntToScalar(x), SkIntToScalar(y));
283 canvas.drawRect(SkRect::MakeXYWH(0, 0, f, f), darkPaint);
284 canvas.drawRect(SkRect::MakeXYWH(f, 0, f, f), lightPaint);
285 canvas.drawRect(SkRect::MakeXYWH(0, f, f, f), lightPaint);
286 canvas.drawRect(SkRect::MakeXYWH(f, f, f, f), darkPaint);
287 canvas.restore();
288 }
289 }
290
291 return success;
292 }
293
drawSomething(SkCanvas * canvas)294 static bool drawSomething(SkCanvas* canvas) {
295 SkPaint paint;
296 SkBitmap bitmap;
297 bool success = make_checkerboard_bitmap(bitmap);
298
299 canvas->save();
300 canvas->scale(0.5f, 0.5f);
301 canvas->drawBitmap(bitmap, 0, 0, NULL);
302 canvas->restore();
303
304 const char beforeStr[] = "before circle";
305 const char afterStr[] = "after circle";
306
307 paint.setAntiAlias(true);
308
309 paint.setColor(SK_ColorRED);
310 canvas->drawData(beforeStr, sizeof(beforeStr));
311 canvas->drawCircle(SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/3), paint);
312 canvas->drawData(afterStr, sizeof(afterStr));
313 paint.setColor(SK_ColorBLACK);
314 paint.setTextSize(SkIntToScalar(kBitmapSize/3));
315 canvas->drawText("Picture", 7, SkIntToScalar(kBitmapSize/2), SkIntToScalar(kBitmapSize/4), paint);
316
317 return success;
318 }
319
DEF_TEST(Serialization,reporter)320 DEF_TEST(Serialization, reporter) {
321 // Test matrix serialization
322 {
323 SkMatrix matrix = SkMatrix::I();
324 TestObjectSerialization(&matrix, reporter);
325 }
326
327 // Test path serialization
328 {
329 SkPath path;
330 TestObjectSerialization(&path, reporter);
331 }
332
333 // Test region serialization
334 {
335 SkRegion region;
336 TestObjectSerialization(®ion, reporter);
337 }
338
339 // Test string serialization
340 {
341 SkString string("string");
342 TestObjectSerializationNoAlign<SkString, false>(&string, reporter);
343 TestObjectSerializationNoAlign<SkString, true>(&string, reporter);
344 }
345
346 // Test rrect serialization
347 {
348 // SkRRect does not initialize anything.
349 // An uninitialized SkRRect can be serialized,
350 // but will branch on uninitialized data when deserialized.
351 SkRRect rrect;
352 SkRect rect = SkRect::MakeXYWH(1, 2, 20, 30);
353 SkVector corners[4] = { {1, 2}, {2, 3}, {3,4}, {4,5} };
354 rrect.setRectRadii(rect, corners);
355 TestAlignment(&rrect, reporter);
356 }
357
358 // Test readByteArray
359 {
360 unsigned char data[kArraySize] = { 1, 2, 3 };
361 TestArraySerialization(data, reporter);
362 }
363
364 // Test readColorArray
365 {
366 SkColor data[kArraySize] = { SK_ColorBLACK, SK_ColorWHITE, SK_ColorRED };
367 TestArraySerialization(data, reporter);
368 }
369
370 // Test readIntArray
371 {
372 int32_t data[kArraySize] = { 1, 2, 4, 8 };
373 TestArraySerialization(data, reporter);
374 }
375
376 // Test readPointArray
377 {
378 SkPoint data[kArraySize] = { {6, 7}, {42, 128} };
379 TestArraySerialization(data, reporter);
380 }
381
382 // Test readScalarArray
383 {
384 SkScalar data[kArraySize] = { SK_Scalar1, SK_ScalarHalf, SK_ScalarMax };
385 TestArraySerialization(data, reporter);
386 }
387
388 // Test invalid deserializations
389 {
390 SkImageInfo info = SkImageInfo::MakeN32Premul(kBitmapSize, kBitmapSize);
391
392 SkBitmap validBitmap;
393 validBitmap.setInfo(info);
394
395 // Create a bitmap with a really large height
396 info.fHeight = 1000000000;
397 SkBitmap invalidBitmap;
398 invalidBitmap.setInfo(info);
399
400 // The deserialization should succeed, and the rendering shouldn't crash,
401 // even when the device fails to initialize, due to its size
402 TestBitmapSerialization(validBitmap, invalidBitmap, true, reporter);
403 }
404
405 // Test simple SkPicture serialization
406 {
407 SkPictureRecorder recorder;
408 bool didDraw = drawSomething(recorder.beginRecording(kBitmapSize, kBitmapSize, NULL, 0));
409 REPORTER_ASSERT(reporter, didDraw);
410 SkAutoTUnref<SkPicture> pict(recorder.endRecording());
411
412 // Serialize picture
413 SkWriteBuffer writer(SkWriteBuffer::kValidation_Flag);
414 pict->flatten(writer);
415 size_t size = writer.bytesWritten();
416 SkAutoTMalloc<unsigned char> data(size);
417 writer.writeToMemory(static_cast<void*>(data.get()));
418
419 // Deserialize picture
420 SkValidatingReadBuffer reader(static_cast<void*>(data.get()), size);
421 SkAutoTUnref<SkPicture> readPict(
422 SkPicture::CreateFromBuffer(reader));
423 REPORTER_ASSERT(reporter, NULL != readPict.get());
424 }
425 }
426