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 "include/core/SkCanvas.h"
9 #include "include/core/SkColor.h"
10 #include "include/core/SkData.h"
11 #include "include/core/SkDrawable.h"
12 #include "include/core/SkFlattenable.h"
13 #include "include/core/SkFont.h"
14 #include "include/core/SkImageFilter.h"
15 #include "include/core/SkMaskFilter.h"
16 #include "include/core/SkPaint.h"
17 #include "include/core/SkPictureRecorder.h"
18 #include "include/core/SkRect.h"
19 #include "include/core/SkRefCnt.h"
20 #include "include/core/SkTypes.h"
21 #include "src/core/SkPathEffectBase.h"
22 #include "src/core/SkReadBuffer.h"
23 #include "src/core/SkWriteBuffer.h"
24 #include "src/effects/colorfilters/SkColorFilterBase.h"
25 #include "src/shaders/SkShaderBase.h"
26 #include "tests/Test.h"
27 #include "tools/fonts/FontToolUtils.h"
28
29 #include <cstdint>
30 #include <cstring>
31
32 class IntDrawable : public SkDrawable {
33 public:
IntDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d)34 IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
35 : fA(a)
36 , fB(b)
37 , fC(c)
38 , fD(d)
39 {}
40
flatten(SkWriteBuffer & buffer) const41 void flatten(SkWriteBuffer& buffer) const override {
42 buffer.writeUInt(fA);
43 buffer.writeUInt(fB);
44 buffer.writeUInt(fC);
45 buffer.writeUInt(fD);
46 }
47
CreateProc(SkReadBuffer & buffer)48 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
49 uint32_t a = buffer.readUInt();
50 uint32_t b = buffer.readUInt();
51 uint32_t c = buffer.readUInt();
52 uint32_t d = buffer.readUInt();
53 return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d));
54 }
55
getFactory() const56 Factory getFactory() const override { return CreateProc; }
57
a() const58 uint32_t a() const { return fA; }
b() const59 uint32_t b() const { return fB; }
c() const60 uint32_t c() const { return fC; }
d() const61 uint32_t d() const { return fD; }
62
getTypeName() const63 const char* getTypeName() const override { return "IntDrawable"; }
64
65 protected:
onGetBounds()66 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)67 void onDraw(SkCanvas*) override {}
68
69 private:
70 uint32_t fA;
71 uint32_t fB;
72 uint32_t fC;
73 uint32_t fD;
74 };
75
76 class PaintDrawable : public SkDrawable {
77 public:
PaintDrawable(const SkPaint & paint)78 PaintDrawable(const SkPaint& paint)
79 : fPaint(paint)
80 {}
81
flatten(SkWriteBuffer & buffer) const82 void flatten(SkWriteBuffer& buffer) const override {
83 buffer.writePaint(fPaint);
84 }
85
CreateProc(SkReadBuffer & buffer)86 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
87 return sk_sp<PaintDrawable>(new PaintDrawable(buffer.readPaint()));
88 }
89
getFactory() const90 Factory getFactory() const override { return CreateProc; }
91
paint() const92 const SkPaint& paint() const { return fPaint; }
93
getTypeName() const94 const char* getTypeName() const override { return "PaintDrawable"; }
95
96 protected:
onGetBounds()97 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)98 void onDraw(SkCanvas*) override {}
99
100 private:
101 SkPaint fPaint;
102 };
103
104 class CompoundDrawable : public SkDrawable {
105 public:
CompoundDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d,const SkPaint & paint)106 CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint)
107 : fIntDrawable(new IntDrawable(a, b, c, d))
108 , fPaintDrawable(new PaintDrawable(paint))
109 {}
110
CompoundDrawable(IntDrawable * intDrawable,PaintDrawable * paintDrawable)111 CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
112 : fIntDrawable(SkRef(intDrawable))
113 , fPaintDrawable(SkRef(paintDrawable))
114 {}
115
flatten(SkWriteBuffer & buffer) const116 void flatten(SkWriteBuffer& buffer) const override {
117 buffer.writeFlattenable(fIntDrawable.get());
118 buffer.writeFlattenable(fPaintDrawable.get());
119 }
120
CreateProc(SkReadBuffer & buffer)121 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
122 sk_sp<SkFlattenable> intDrawable(
123 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
124 SkASSERT(intDrawable);
125 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
126
127 sk_sp<SkFlattenable> paintDrawable(
128 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
129 SkASSERT(paintDrawable);
130 SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName()));
131
132 return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(),
133 (PaintDrawable*) paintDrawable.get()));
134 }
135
getFactory() const136 Factory getFactory() const override { return CreateProc; }
137
intDrawable() const138 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
paintDrawable() const139 PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
140
getTypeName() const141 const char* getTypeName() const override { return "CompoundDrawable"; }
142
143 protected:
onGetBounds()144 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)145 void onDraw(SkCanvas*) override {}
146
147 private:
148 sk_sp<IntDrawable> fIntDrawable;
149 sk_sp<PaintDrawable> fPaintDrawable;
150 };
151
152 class RootDrawable : public SkDrawable {
153 public:
RootDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d,const SkPaint & paint,uint32_t e,uint32_t f,uint32_t g,uint32_t h,SkDrawable * drawable)154 RootDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint,
155 uint32_t e, uint32_t f, uint32_t g, uint32_t h, SkDrawable* drawable)
156 : fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint))
157 , fIntDrawable(new IntDrawable(e, f, g, h))
158 , fDrawable(SkRef(drawable))
159 {}
160
RootDrawable(CompoundDrawable * compoundDrawable,IntDrawable * intDrawable,SkDrawable * drawable)161 RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
162 SkDrawable* drawable)
163 : fCompoundDrawable(SkRef(compoundDrawable))
164 , fIntDrawable(SkRef(intDrawable))
165 , fDrawable(SkRef(drawable))
166 {}
167
flatten(SkWriteBuffer & buffer) const168 void flatten(SkWriteBuffer& buffer) const override {
169 buffer.writeFlattenable(fCompoundDrawable.get());
170 buffer.writeFlattenable(fIntDrawable.get());
171 buffer.writeFlattenable(fDrawable.get());
172 }
173
CreateProc(SkReadBuffer & buffer)174 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
175 sk_sp<SkFlattenable> compoundDrawable(
176 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
177 SkASSERT(compoundDrawable);
178 SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
179
180 sk_sp<SkFlattenable> intDrawable(
181 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
182 SkASSERT(intDrawable);
183 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
184
185 sk_sp<SkFlattenable> drawable(
186 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
187 SkASSERT(drawable);
188
189 return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(),
190 (IntDrawable*) intDrawable.get(),
191 (SkDrawable*) drawable.get()));
192 }
193
getFactory() const194 Factory getFactory() const override { return CreateProc; }
195
compoundDrawable() const196 CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
intDrawable() const197 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
drawable() const198 SkDrawable* drawable() const { return fDrawable.get(); }
199
getTypeName() const200 const char* getTypeName() const override { return "RootDrawable"; }
201
202 protected:
onGetBounds()203 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)204 void onDraw(SkCanvas*) override {}
205
206 private:
207 sk_sp<CompoundDrawable> fCompoundDrawable;
208 sk_sp<IntDrawable> fIntDrawable;
209 sk_sp<SkDrawable> fDrawable;
210 };
211
212 // Register these drawables for deserialization some time before main().
213 static struct Initializer {
InitializerInitializer214 Initializer() {
215 SK_REGISTER_FLATTENABLE(IntDrawable);
216 SK_REGISTER_FLATTENABLE(PaintDrawable);
217 SK_REGISTER_FLATTENABLE(CompoundDrawable);
218 SK_REGISTER_FLATTENABLE(RootDrawable);
219 }
220 } initializer;
221
DEF_TEST(FlattenDrawable,r)222 DEF_TEST(FlattenDrawable, r) {
223 // Create and serialize the test drawable
224 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
225 SkPaint paint;
226 paint.setColor(SK_ColorBLUE);
227 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
228 SkBinaryWriteBuffer writeBuffer({});
229 writeBuffer.writeFlattenable(root.get());
230
231 // Copy the contents of the write buffer into a read buffer
232 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
233 writeBuffer.writeToMemory(data->writable_data());
234 SkReadBuffer readBuffer(data->data(), data->size());
235
236 // Deserialize and verify the drawable
237 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
238 REPORTER_ASSERT(r, out);
239 REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
240
241 RootDrawable* rootOut = (RootDrawable*) out.get();
242 REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
243 REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
244 REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
245 REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
246 REPORTER_ASSERT(r, SK_ColorBLUE ==
247 rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
248 REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
249 REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
250 REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
251 REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
252
253 // Note that we can still recognize the generic drawable as an IntDrawable
254 SkDrawable* generic = rootOut->drawable();
255 REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
256 IntDrawable* integer = (IntDrawable*) generic;
257 REPORTER_ASSERT(r, 1 == integer->a());
258 REPORTER_ASSERT(r, 2 == integer->b());
259 REPORTER_ASSERT(r, 3 == integer->c());
260 REPORTER_ASSERT(r, 4 == integer->d());
261 }
262
DEF_TEST(FlattenRecordedDrawable,r)263 DEF_TEST(FlattenRecordedDrawable, r) {
264 // Record a set of canvas draw commands
265 SkPictureRecorder recorder;
266 SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
267 SkPaint paint;
268 paint.setColor(SK_ColorGREEN);
269 canvas->drawPoint(42.0f, 17.0f, paint);
270 paint.setColor(SK_ColorRED);
271 canvas->drawPaint(paint);
272 SkPaint textPaint;
273 textPaint.setColor(SK_ColorBLUE);
274 canvas->drawString("TEXT", 467.0f, 100.0f, ToolUtils::DefaultFont(), textPaint);
275
276 // Draw some drawables as well
277 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
278 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
279 canvas->drawDrawable(root.get(), 747.0f, 242.0f);
280 sk_sp<PaintDrawable> paintDrawable(new PaintDrawable(paint));
281 canvas->drawDrawable(paintDrawable.get(), 500.0, 500.0f);
282 sk_sp<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
283 canvas->drawDrawable(comDrawable.get(), 10.0f, 10.0f);
284
285 // Serialize the recorded drawable
286 sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
287 SkBinaryWriteBuffer writeBuffer({});
288 writeBuffer.writeFlattenable(recordedDrawable.get());
289
290 // Copy the contents of the write buffer into a read buffer
291 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
292 writeBuffer.writeToMemory(data->writable_data());
293 SkReadBuffer readBuffer(data->data(), data->size());
294
295 // Deserialize and verify the drawable
296 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
297 REPORTER_ASSERT(r, out);
298 REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
299 }
300
301 // be sure these constructs compile, don't assert, and return null
DEF_TEST(Flattenable_EmptyDeserialze,reporter)302 DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
303 auto data = SkData::MakeEmpty();
304
305 #define test(name) REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
306 test(SkPathEffectBase);
307 test(SkMaskFilter);
308 test(SkShaderBase); // todo: make this just be shader!
309 test(SkColorFilterBase);
310 test(SkImageFilter);
311 #undef test
312 }
313
314