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
19static const uint32_t kArraySize = 64;
20static const int kBitmapSize = 256;
21
22template<typename T>
23static 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
32template<typename T> struct SerializationUtils {
33    // Generic case for flattenables
34    static void Write(SkWriteBuffer& writer, const T* flattenable) {
35        writer.writeFlattenable(flattenable);
36    }
37    static void Read(SkValidatingReadBuffer& reader, T** flattenable) {
38        *flattenable = (T*)reader.readFlattenable(T::GetFlattenableType());
39    }
40};
41
42template<> struct SerializationUtils<SkMatrix> {
43    static void Write(SkWriteBuffer& writer, const SkMatrix* matrix) {
44        writer.writeMatrix(*matrix);
45    }
46    static void Read(SkValidatingReadBuffer& reader, SkMatrix* matrix) {
47        reader.readMatrix(matrix);
48    }
49};
50
51template<> struct SerializationUtils<SkPath> {
52    static void Write(SkWriteBuffer& writer, const SkPath* path) {
53        writer.writePath(*path);
54    }
55    static void Read(SkValidatingReadBuffer& reader, SkPath* path) {
56        reader.readPath(path);
57    }
58};
59
60template<> struct SerializationUtils<SkRegion> {
61    static void Write(SkWriteBuffer& writer, const SkRegion* region) {
62        writer.writeRegion(*region);
63    }
64    static void Read(SkValidatingReadBuffer& reader, SkRegion* region) {
65        reader.readRegion(region);
66    }
67};
68
69template<> struct SerializationUtils<SkString> {
70    static void Write(SkWriteBuffer& writer, const SkString* string) {
71        writer.writeString(string->c_str());
72    }
73    static void Read(SkValidatingReadBuffer& reader, SkString* string) {
74        reader.readString(string);
75    }
76};
77
78template<> struct SerializationUtils<unsigned char> {
79    static void Write(SkWriteBuffer& writer, unsigned char* data, uint32_t arraySize) {
80        writer.writeByteArray(data, arraySize);
81    }
82    static bool Read(SkValidatingReadBuffer& reader, unsigned char* data, uint32_t arraySize) {
83        return reader.readByteArray(data, arraySize);
84    }
85};
86
87template<> struct SerializationUtils<SkColor> {
88    static void Write(SkWriteBuffer& writer, SkColor* data, uint32_t arraySize) {
89        writer.writeColorArray(data, arraySize);
90    }
91    static bool Read(SkValidatingReadBuffer& reader, SkColor* data, uint32_t arraySize) {
92        return reader.readColorArray(data, arraySize);
93    }
94};
95
96template<> struct SerializationUtils<int32_t> {
97    static void Write(SkWriteBuffer& writer, int32_t* data, uint32_t arraySize) {
98        writer.writeIntArray(data, arraySize);
99    }
100    static bool Read(SkValidatingReadBuffer& reader, int32_t* data, uint32_t arraySize) {
101        return reader.readIntArray(data, arraySize);
102    }
103};
104
105template<> struct SerializationUtils<SkPoint> {
106    static void Write(SkWriteBuffer& writer, SkPoint* data, uint32_t arraySize) {
107        writer.writePointArray(data, arraySize);
108    }
109    static bool Read(SkValidatingReadBuffer& reader, SkPoint* data, uint32_t arraySize) {
110        return reader.readPointArray(data, arraySize);
111    }
112};
113
114template<> struct SerializationUtils<SkScalar> {
115    static void Write(SkWriteBuffer& writer, SkScalar* data, uint32_t arraySize) {
116        writer.writeScalarArray(data, arraySize);
117    }
118    static bool Read(SkValidatingReadBuffer& reader, SkScalar* data, uint32_t arraySize) {
119        return reader.readScalarArray(data, arraySize);
120    }
121};
122
123template<typename T, bool testInvalid> struct SerializationTestUtils {
124    static void InvalidateData(unsigned char* data) {}
125};
126
127template<> struct SerializationTestUtils<SkString, true> {
128    static void InvalidateData(unsigned char* data) {
129        data[3] |= 0x80; // Reverse sign of 1st integer
130    }
131};
132
133template<typename T, bool testInvalid>
134static 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
164template<typename T>
165static void TestObjectSerialization(T* testObj, skiatest::Reporter* reporter) {
166    TestObjectSerializationNoAlign<T, false>(testObj, reporter);
167    TestAlignment(testObj, reporter);
168}
169
170template<typename T>
171static 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
209template<typename T>
210static 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
234static 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
262static 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
268static 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
294static 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
320DEF_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