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
drain(SkPipeDeserializer * deserial,SkDynamicMemoryWStream * stream)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
deep_equal(SkImage * a,SkImage * b)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
DEF_TEST(Pipe_image_draw_first,reporter)48 DEF_TEST(Pipe_image_draw_first, reporter) {
49 sk_sp<SkImage> img = GetResourceAsImage("images/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
DEF_TEST(Pipe_image_draw_second,reporter)86 DEF_TEST(Pipe_image_draw_second, reporter) {
87 sk_sp<SkImage> img = GetResourceAsImage("images/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
DEF_TEST(Pipe_picture_draw_first,reporter)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
DEF_TEST(Pipe_picture_draw_second,reporter)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