1 /* 2 * Copyright 2016 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 "Resources.h" 9 #include "SkCanvas.h" 10 #include "SkPipe.h" 11 #include "SkPaint.h" 12 #include "SkStream.h" 13 #include "SkSurface.h" 14 #include "Test.h" 15 16 #include "SkNullCanvas.h" 17 #include "SkAutoPixmapStorage.h" 18 #include "SkPictureRecorder.h" 19 20 static void drain(SkPipeDeserializer* deserial, SkDynamicMemoryWStream* stream) { 21 std::unique_ptr<SkCanvas> canvas = SkMakeNullCanvas(); 22 sk_sp<SkData> data = stream->detachAsData(); 23 deserial->playback(data->data(), data->size(), canvas.get()); 24 } 25 26 static bool deep_equal(SkImage* a, SkImage* b) { 27 if (a->width() != b->width() || a->height() != b->height()) { 28 return false; 29 } 30 31 const SkImageInfo info = SkImageInfo::MakeN32Premul(a->width(), a->height()); 32 SkAutoPixmapStorage pmapA, pmapB; 33 pmapA.alloc(info); 34 pmapB.alloc(info); 35 36 if (!a->readPixels(pmapA, 0, 0) || !b->readPixels(pmapB, 0, 0)) { 37 return false; 38 } 39 40 for (int y = 0; y < info.height(); ++y) { 41 if (memcmp(pmapA.addr32(0, y), pmapB.addr32(0, y), info.width() * sizeof(SkPMColor))) { 42 return false; 43 } 44 } 45 return true; 46 } 47 48 DEF_TEST(Pipe_image_draw_first, reporter) { 49 sk_sp<SkImage> img = GetResourceAsImage("mandrill_128.png"); 50 SkASSERT(img.get()); 51 52 SkPipeSerializer serializer; 53 SkPipeDeserializer deserializer; 54 55 SkDynamicMemoryWStream stream; 56 SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 57 wc->drawImage(img, 0, 0, nullptr); 58 serializer.endWrite(); 59 size_t offset0 = stream.bytesWritten(); 60 REPORTER_ASSERT(reporter, offset0 > 100); // the raw image must be sorta big 61 drain(&deserializer, &stream); 62 63 // try drawing the same image again -- it should be much smaller 64 wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 65 wc->drawImage(img, 0, 0, nullptr); 66 size_t offset1 = stream.bytesWritten(); 67 serializer.endWrite(); 68 REPORTER_ASSERT(reporter, offset1 <= 32); 69 drain(&deserializer, &stream); 70 71 // try serializing the same image directly, again it should be small 72 sk_sp<SkData> data = serializer.writeImage(img.get()); 73 size_t offset2 = data->size(); 74 REPORTER_ASSERT(reporter, offset2 <= 32); 75 auto img1 = deserializer.readImage(data.get()); 76 REPORTER_ASSERT(reporter, deep_equal(img.get(), img1.get())); 77 78 // try serializing the same image directly (again), check that it is the same! 79 data = serializer.writeImage(img.get()); 80 size_t offset3 = data->size(); 81 REPORTER_ASSERT(reporter, offset3 <= 32); 82 auto img2 = deserializer.readImage(data.get()); 83 REPORTER_ASSERT(reporter, img1.get() == img2.get()); 84 } 85 86 DEF_TEST(Pipe_image_draw_second, reporter) { 87 sk_sp<SkImage> img = GetResourceAsImage("mandrill_128.png"); 88 SkASSERT(img.get()); 89 90 SkPipeSerializer serializer; 91 SkPipeDeserializer deserializer; 92 SkDynamicMemoryWStream stream; 93 94 sk_sp<SkData> data = serializer.writeImage(img.get()); 95 size_t offset0 = data->size(); 96 REPORTER_ASSERT(reporter, offset0 > 100); // the raw image must be sorta big 97 auto img1 = deserializer.readImage(data.get()); 98 99 // The 2nd image should be nice and small 100 data = serializer.writeImage(img.get()); 101 size_t offset1 = data->size(); 102 REPORTER_ASSERT(reporter, offset1 <= 16); 103 auto img2 = deserializer.readImage(data.get()); 104 REPORTER_ASSERT(reporter, img1.get() == img2.get()); 105 106 // Now try drawing the image, it should also be small 107 SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 108 wc->drawImage(img, 0, 0, nullptr); 109 serializer.endWrite(); 110 size_t offset2 = stream.bytesWritten(); 111 REPORTER_ASSERT(reporter, offset2 <= 16); 112 } 113 114 DEF_TEST(Pipe_picture_draw_first, reporter) { 115 sk_sp<SkPicture> picture = []() { 116 SkPictureRecorder rec; 117 SkCanvas* c = rec.beginRecording(SkRect::MakeWH(100, 100)); 118 for (int i = 0; i < 100; ++i) { 119 c->drawColor(i); 120 } 121 return rec.finishRecordingAsPicture(); 122 }(); 123 SkPipeSerializer serializer; 124 SkPipeDeserializer deserializer; 125 126 SkDynamicMemoryWStream stream; 127 SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 128 wc->drawPicture(picture); 129 serializer.endWrite(); 130 size_t offset0 = stream.bytesWritten(); 131 REPORTER_ASSERT(reporter, offset0 > 100); // the raw picture must be sorta big 132 drain(&deserializer, &stream); 133 134 // try drawing the same picture again -- it should be much smaller 135 wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 136 wc->drawPicture(picture); 137 size_t offset1 = stream.bytesWritten(); 138 serializer.endWrite(); 139 REPORTER_ASSERT(reporter, offset1 <= 16); 140 drain(&deserializer, &stream); 141 142 // try writing the picture directly, it should also be small 143 sk_sp<SkData> data = serializer.writePicture(picture.get()); 144 size_t offset2 = data->size(); 145 REPORTER_ASSERT(reporter, offset2 <= 16); 146 auto pic1 = deserializer.readPicture(data.get()); 147 148 // try writing the picture directly, it should also be small 149 data = serializer.writePicture(picture.get()); 150 size_t offset3 = data->size(); 151 REPORTER_ASSERT(reporter, offset3 == offset2); 152 auto pic2 = deserializer.readPicture(data.get()); 153 REPORTER_ASSERT(reporter, pic1.get() == pic2.get()); 154 } 155 156 DEF_TEST(Pipe_picture_draw_second, reporter) { 157 sk_sp<SkPicture> picture = []() { 158 SkPictureRecorder rec; 159 SkCanvas* c = rec.beginRecording(SkRect::MakeWH(100, 100)); 160 for (int i = 0; i < 100; ++i) { 161 c->drawColor(i); 162 } 163 return rec.finishRecordingAsPicture(); 164 }(); 165 SkPipeSerializer serializer; 166 SkPipeDeserializer deserializer; 167 SkDynamicMemoryWStream stream; 168 169 sk_sp<SkData> data = serializer.writePicture(picture.get()); 170 size_t offset0 = data->size(); 171 REPORTER_ASSERT(reporter, offset0 > 100); // the raw picture must be sorta big 172 auto pic1 = deserializer.readPicture(data.get()); 173 174 // The 2nd picture should be nice and small 175 data = serializer.writePicture(picture.get()); 176 size_t offset1 = data->size(); 177 REPORTER_ASSERT(reporter, offset1 <= 16); 178 auto pic2 = deserializer.readPicture(data.get()); 179 SkASSERT(pic1.get() == pic2.get()); 180 181 // Now try drawing the image, it should also be small 182 SkCanvas* wc = serializer.beginWrite(SkRect::MakeWH(100, 100), &stream); 183 wc->drawPicture(picture); 184 serializer.endWrite(); 185 size_t offset2 = stream.bytesWritten(); 186 REPORTER_ASSERT(reporter, offset2 <= 16); 187 } 188