| /* | 
 |  * Copyright 2016 Google Inc. | 
 |  * | 
 |  * Use of this source code is governed by a BSD-style license that can be | 
 |  * found in the LICENSE file. | 
 |  */ | 
 |  | 
 | #include "Resources.h" | 
 | #include "SkCanvas.h" | 
 | #include "SkPipe.h" | 
 | #include "SkPaint.h" | 
 | #include "SkStream.h" | 
 | #include "SkSurface.h" | 
 | #include "Test.h" | 
 |  | 
 | #include "SkNullCanvas.h" | 
 | #include "SkAutoPixmapStorage.h" | 
 | #include "SkPictureRecorder.h" | 
 |  | 
 | static void drain(SkPipeDeserializer* deserial, SkDynamicMemoryWStream* stream) { | 
 |     std::unique_ptr<SkCanvas> canvas = SkMakeNullCanvas(); | 
 |     sk_sp<SkData> data = stream->detachAsData(); | 
 |     deserial->playback(data->data(), data->size(), canvas.get()); | 
 | } | 
 |  | 
 | static bool deep_equal(SkImage* a, SkImage* b) { | 
 |     if (a->width() != b->width() || a->height() != b->height()) { | 
 |         return false; | 
 |     } | 
 |  | 
 |     const SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height()); | 
 |     SkAutoPixmapStorage pmapA, pmapB; | 
 |     pmapA.alloc(info); | 
 |     pmapB.alloc(info); | 
 |  | 
 |     if (!a->readPixels(pmapA, 0, 0) || !b->readPixels(pmapB, 0, 0)) { | 
 |         return false; | 
 |     } | 
 |  | 
 |     for (int y = 0; y < info.height(); ++y) { | 
 |         if (memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), info.width() * sizeof(SkPMColor))) { | 
 |             return false; | 
 |         } | 
 |     } | 
 |     return true; | 
 | } | 
 |  | 
 | DEF_TEST(Pipe_image_draw_first, reporter) { | 
 |     sk_sp<SkImage> img = GetResourceAsImage("images/mandrill_128.png"); | 
 |     SkASSERT(img.get()); | 
 |  | 
 |     SkPipeSerializer serializer; | 
 |     SkPipeDeserializer deserializer; | 
 |  | 
 |     SkDynamicMemoryWStream stream; | 
 |     SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawImage(img, 0, 0, nullptr); | 
 |     serializer.endWrite(); | 
 |     size_t offset0 = stream.bytesWritten(); | 
 |     REPORTER_ASSERT(reporter, offset0 > 100);   // the raw image must be sorta big | 
 |     drain(&deserializer, &stream); | 
 |  | 
 |     // try drawing the same image again -- it should be much smaller | 
 |     wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawImage(img, 0, 0, nullptr); | 
 |     size_t offset1 = stream.bytesWritten(); | 
 |     serializer.endWrite(); | 
 |     REPORTER_ASSERT(reporter, offset1 <= 32); | 
 |     drain(&deserializer, &stream); | 
 |  | 
 |     // try serializing the same image directly, again it should be small | 
 |     sk_sp<SkData> data = serializer.writeImage(img.get()); | 
 |     size_t offset2 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset2 <= 32); | 
 |     auto img1 = deserializer.readImage(data.get()); | 
 |     REPORTER_ASSERT(reporter, deep_equal(img.get(), img1.get())); | 
 |  | 
 |     // try serializing the same image directly (again), check that it is the same! | 
 |     data = serializer.writeImage(img.get()); | 
 |     size_t offset3 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset3 <= 32); | 
 |     auto img2 = deserializer.readImage(data.get()); | 
 |     REPORTER_ASSERT(reporter, img1.get() == img2.get()); | 
 | } | 
 |  | 
 | DEF_TEST(Pipe_image_draw_second, reporter) { | 
 |     sk_sp<SkImage> img = GetResourceAsImage("images/mandrill_128.png"); | 
 |     SkASSERT(img.get()); | 
 |  | 
 |     SkPipeSerializer serializer; | 
 |     SkPipeDeserializer deserializer; | 
 |     SkDynamicMemoryWStream stream; | 
 |  | 
 |     sk_sp<SkData> data = serializer.writeImage(img.get()); | 
 |     size_t offset0 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset0 > 100);   // the raw image must be sorta big | 
 |     auto img1 = deserializer.readImage(data.get()); | 
 |  | 
 |     // The 2nd image should be nice and small | 
 |     data = serializer.writeImage(img.get()); | 
 |     size_t offset1 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset1 <= 16); | 
 |     auto img2 = deserializer.readImage(data.get()); | 
 |     REPORTER_ASSERT(reporter, img1.get() == img2.get()); | 
 |  | 
 |     // Now try drawing the image, it should also be small | 
 |     SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawImage(img, 0, 0, nullptr); | 
 |     serializer.endWrite(); | 
 |     size_t offset2 = stream.bytesWritten(); | 
 |     REPORTER_ASSERT(reporter, offset2 <= 16); | 
 | } | 
 |  | 
 | DEF_TEST(Pipe_picture_draw_first, reporter) { | 
 |     sk_sp<SkPicture> picture = []() { | 
 |         SkPictureRecorder rec; | 
 |         SkCanvas* c = rec.beginRecording(SkRect::MakeWH(100, 100)); | 
 |         for (int i = 0; i < 100; ++i) { | 
 |             c->drawColor(i); | 
 |         } | 
 |         return rec.finishRecordingAsPicture(); | 
 |     }(); | 
 |     SkPipeSerializer serializer; | 
 |     SkPipeDeserializer deserializer; | 
 |  | 
 |     SkDynamicMemoryWStream stream; | 
 |     SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawPicture(picture); | 
 |     serializer.endWrite(); | 
 |     size_t offset0 = stream.bytesWritten(); | 
 |     REPORTER_ASSERT(reporter, offset0 > 100);   // the raw picture must be sorta big | 
 |     drain(&deserializer, &stream); | 
 |  | 
 |     // try drawing the same picture again -- it should be much smaller | 
 |     wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawPicture(picture); | 
 |     size_t offset1 = stream.bytesWritten(); | 
 |     serializer.endWrite(); | 
 |     REPORTER_ASSERT(reporter, offset1 <= 16); | 
 |     drain(&deserializer, &stream); | 
 |  | 
 |     // try writing the picture directly, it should also be small | 
 |     sk_sp<SkData> data = serializer.writePicture(picture.get()); | 
 |     size_t offset2 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset2 <= 16); | 
 |     auto pic1 = deserializer.readPicture(data.get()); | 
 |  | 
 |     // try writing the picture directly, it should also be small | 
 |     data = serializer.writePicture(picture.get()); | 
 |     size_t offset3 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset3 == offset2); | 
 |     auto pic2 = deserializer.readPicture(data.get()); | 
 |     REPORTER_ASSERT(reporter, pic1.get() == pic2.get()); | 
 | } | 
 |  | 
 | DEF_TEST(Pipe_picture_draw_second, reporter) { | 
 |     sk_sp<SkPicture> picture = []() { | 
 |         SkPictureRecorder rec; | 
 |         SkCanvas* c = rec.beginRecording(SkRect::MakeWH(100, 100)); | 
 |         for (int i = 0; i < 100; ++i) { | 
 |             c->drawColor(i); | 
 |         } | 
 |         return rec.finishRecordingAsPicture(); | 
 |     }(); | 
 |     SkPipeSerializer serializer; | 
 |     SkPipeDeserializer deserializer; | 
 |     SkDynamicMemoryWStream stream; | 
 |  | 
 |     sk_sp<SkData> data = serializer.writePicture(picture.get()); | 
 |     size_t offset0 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset0 > 100);   // the raw picture must be sorta big | 
 |     auto pic1 = deserializer.readPicture(data.get()); | 
 |  | 
 |     // The 2nd picture should be nice and small | 
 |     data = serializer.writePicture(picture.get()); | 
 |     size_t offset1 = data->size(); | 
 |     REPORTER_ASSERT(reporter, offset1 <= 16); | 
 |     auto pic2 = deserializer.readPicture(data.get()); | 
 |     SkASSERT(pic1.get() == pic2.get()); | 
 |  | 
 |     // Now try drawing the image, it should also be small | 
 |     SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); | 
 |     wc->drawPicture(picture); | 
 |     serializer.endWrite(); | 
 |     size_t offset2 = stream.bytesWritten(); | 
 |     REPORTER_ASSERT(reporter, offset2 <= 16); | 
 | } |