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