Home | History | Annotate | Download | only in tests
      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>
     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
     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 
     42 template<> 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 
     51 template<> 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 
     60 template<> 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 
     69 template<> 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 
     78 template<> 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 
     87 template<> 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 
     96 template<> 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 
    105 template<> 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 
    114 template<> 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 
    123 template<typename T, bool testInvalid> struct SerializationTestUtils {
    124     static void InvalidateData(unsigned char* data) {}
    125 };
    126 
    127 template<> struct SerializationTestUtils<SkString, true> {
    128     static void InvalidateData(unsigned char* data) {
    129         data[3] |= 0x80; // Reverse sign of 1st integer
    130     }
    131 };
    132 
    133 template<typename T, bool testInvalid>
    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>
    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>
    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>
    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 
    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 
    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 
    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 
    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 
    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