blob: e1074e050ae18bc7228b5111bb56181f108b8a23 [file] [log] [blame]
msarettedf7fcd2016-04-25 06:40:26 -07001/*
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
Mike Kleinc0bd9f92019-04-23 12:05:21 -05008#include "include/core/SkCanvas.h"
9#include "include/core/SkDrawable.h"
10#include "include/core/SkFont.h"
11#include "include/core/SkPictureRecorder.h"
12#include "include/core/SkRect.h"
13#include "include/core/SkStream.h"
14#include "src/core/SkReadBuffer.h"
15#include "src/core/SkWriteBuffer.h"
16#include "tests/Test.h"
msarettedf7fcd2016-04-25 06:40:26 -070017
18class IntDrawable : public SkDrawable {
19public:
20 IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
21 : fA(a)
22 , fB(b)
23 , fC(c)
24 , fD(d)
25 {}
26
27 void flatten(SkWriteBuffer& buffer) const override {
28 buffer.writeUInt(fA);
29 buffer.writeUInt(fB);
30 buffer.writeUInt(fC);
31 buffer.writeUInt(fD);
32 }
33
34 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
35 uint32_t a = buffer.readUInt();
36 uint32_t b = buffer.readUInt();
37 uint32_t c = buffer.readUInt();
38 uint32_t d = buffer.readUInt();
39 return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d));
40 }
41
42 Factory getFactory() const override { return CreateProc; }
43
44 uint32_t a() const { return fA; }
45 uint32_t b() const { return fB; }
46 uint32_t c() const { return fC; }
47 uint32_t d() const { return fD; }
48
49 const char* getTypeName() const override { return "IntDrawable"; }
50
51protected:
52 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
53 void onDraw(SkCanvas*) override {}
54
55private:
56 uint32_t fA;
57 uint32_t fB;
58 uint32_t fC;
59 uint32_t fD;
60};
61
62class PaintDrawable : public SkDrawable {
63public:
64 PaintDrawable(const SkPaint& paint)
65 : fPaint(paint)
66 {}
67
68 void flatten(SkWriteBuffer& buffer) const override {
69 buffer.writePaint(fPaint);
70 }
71
72 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
73 SkPaint paint;
Mike Reed31ba6fe2019-01-14 17:36:54 -050074 buffer.readPaint(&paint, nullptr);
msarettedf7fcd2016-04-25 06:40:26 -070075 return sk_sp<PaintDrawable>(new PaintDrawable(paint));
76 }
77
78 Factory getFactory() const override { return CreateProc; }
79
80 const SkPaint& paint() const { return fPaint; }
81
msarett002c92b2016-04-26 08:20:14 -070082 const char* getTypeName() const override { return "PaintDrawable"; }
83
msarettedf7fcd2016-04-25 06:40:26 -070084protected:
85 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
86 void onDraw(SkCanvas*) override {}
87
88private:
89 SkPaint fPaint;
90};
91
92class CompoundDrawable : public SkDrawable {
93public:
94 CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint)
95 : fIntDrawable(new IntDrawable(a, b, c, d))
96 , fPaintDrawable(new PaintDrawable(paint))
97 {}
98
99 CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
100 : fIntDrawable(SkRef(intDrawable))
101 , fPaintDrawable(SkRef(paintDrawable))
102 {}
103
104 void flatten(SkWriteBuffer& buffer) const override {
Hal Canary342b7ac2016-11-04 11:49:42 -0400105 buffer.writeFlattenable(fIntDrawable.get());
106 buffer.writeFlattenable(fPaintDrawable.get());
msarettedf7fcd2016-04-25 06:40:26 -0700107 }
108
109 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
Hal Canary342b7ac2016-11-04 11:49:42 -0400110 sk_sp<SkFlattenable> intDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700111 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
112 SkASSERT(intDrawable);
113 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
114
Hal Canary342b7ac2016-11-04 11:49:42 -0400115 sk_sp<SkFlattenable> paintDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700116 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
117 SkASSERT(paintDrawable);
118 SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName()));
119
120 return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(),
121 (PaintDrawable*) paintDrawable.get()));
122 }
123
124 Factory getFactory() const override { return CreateProc; }
125
Hal Canary342b7ac2016-11-04 11:49:42 -0400126 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
127 PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
msarettedf7fcd2016-04-25 06:40:26 -0700128
msarett002c92b2016-04-26 08:20:14 -0700129 const char* getTypeName() const override { return "CompoundDrawable"; }
130
msarettedf7fcd2016-04-25 06:40:26 -0700131protected:
132 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
133 void onDraw(SkCanvas*) override {}
134
135private:
Hal Canary342b7ac2016-11-04 11:49:42 -0400136 sk_sp<IntDrawable> fIntDrawable;
137 sk_sp<PaintDrawable> fPaintDrawable;
msarettedf7fcd2016-04-25 06:40:26 -0700138};
139
140class RootDrawable : public SkDrawable {
141public:
142 RootDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint,
143 uint32_t e, uint32_t f, uint32_t g, uint32_t h, SkDrawable* drawable)
144 : fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint))
145 , fIntDrawable(new IntDrawable(e, f, g, h))
146 , fDrawable(SkRef(drawable))
147 {}
148
149 RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
150 SkDrawable* drawable)
151 : fCompoundDrawable(SkRef(compoundDrawable))
152 , fIntDrawable(SkRef(intDrawable))
153 , fDrawable(SkRef(drawable))
154 {}
155
156 void flatten(SkWriteBuffer& buffer) const override {
Hal Canary342b7ac2016-11-04 11:49:42 -0400157 buffer.writeFlattenable(fCompoundDrawable.get());
158 buffer.writeFlattenable(fIntDrawable.get());
159 buffer.writeFlattenable(fDrawable.get());
msarettedf7fcd2016-04-25 06:40:26 -0700160 }
161
162 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
Hal Canary342b7ac2016-11-04 11:49:42 -0400163 sk_sp<SkFlattenable> compoundDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700164 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
165 SkASSERT(compoundDrawable);
166 SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
167
Hal Canary342b7ac2016-11-04 11:49:42 -0400168 sk_sp<SkFlattenable> intDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700169 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
170 SkASSERT(intDrawable);
171 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
172
Hal Canary342b7ac2016-11-04 11:49:42 -0400173 sk_sp<SkFlattenable> drawable(
msarettedf7fcd2016-04-25 06:40:26 -0700174 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
175 SkASSERT(drawable);
176
177 return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(),
178 (IntDrawable*) intDrawable.get(),
179 (SkDrawable*) drawable.get()));
180 }
181
182 Factory getFactory() const override { return CreateProc; }
183
Hal Canary342b7ac2016-11-04 11:49:42 -0400184 CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
185 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
186 SkDrawable* drawable() const { return fDrawable.get(); }
msarettedf7fcd2016-04-25 06:40:26 -0700187
msarett002c92b2016-04-26 08:20:14 -0700188 const char* getTypeName() const override { return "RootDrawable"; }
189
msarettedf7fcd2016-04-25 06:40:26 -0700190protected:
191 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
192 void onDraw(SkCanvas*) override {}
193
194private:
Hal Canary342b7ac2016-11-04 11:49:42 -0400195 sk_sp<CompoundDrawable> fCompoundDrawable;
196 sk_sp<IntDrawable> fIntDrawable;
197 sk_sp<SkDrawable> fDrawable;
msarettedf7fcd2016-04-25 06:40:26 -0700198};
199
Mike Klein4c683fc2018-10-19 17:35:02 -0400200// Register these drawables for deserialization some time before main().
201static struct Initializer {
202 Initializer() {
Brian Salomon23356442018-11-30 15:33:19 -0500203 SK_REGISTER_FLATTENABLE(IntDrawable);
204 SK_REGISTER_FLATTENABLE(PaintDrawable);
205 SK_REGISTER_FLATTENABLE(CompoundDrawable);
206 SK_REGISTER_FLATTENABLE(RootDrawable);
Mike Klein4c683fc2018-10-19 17:35:02 -0400207 }
208} initializer;
msarettedf7fcd2016-04-25 06:40:26 -0700209
210DEF_TEST(FlattenDrawable, r) {
msarettedf7fcd2016-04-25 06:40:26 -0700211 // Create and serialize the test drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400212 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
msarettedf7fcd2016-04-25 06:40:26 -0700213 SkPaint paint;
214 paint.setColor(SK_ColorBLUE);
Hal Canary342b7ac2016-11-04 11:49:42 -0400215 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
brianosmanfad98562016-05-04 11:06:28 -0700216 SkBinaryWriteBuffer writeBuffer;
Hal Canary342b7ac2016-11-04 11:49:42 -0400217 writeBuffer.writeFlattenable(root.get());
msarettedf7fcd2016-04-25 06:40:26 -0700218
219 // Copy the contents of the write buffer into a read buffer
220 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
221 writeBuffer.writeToMemory(data->writable_data());
222 SkReadBuffer readBuffer(data->data(), data->size());
223
224 // Deserialize and verify the drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400225 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
msarettedf7fcd2016-04-25 06:40:26 -0700226 REPORTER_ASSERT(r, out);
227 REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
228
229 RootDrawable* rootOut = (RootDrawable*) out.get();
230 REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
231 REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
232 REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
233 REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
234 REPORTER_ASSERT(r, SK_ColorBLUE ==
235 rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
236 REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
237 REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
238 REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
239 REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
240
241 // Note that we can still recognize the generic drawable as an IntDrawable
242 SkDrawable* generic = rootOut->drawable();
243 REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
244 IntDrawable* integer = (IntDrawable*) generic;
245 REPORTER_ASSERT(r, 1 == integer->a());
246 REPORTER_ASSERT(r, 2 == integer->b());
247 REPORTER_ASSERT(r, 3 == integer->c());
248 REPORTER_ASSERT(r, 4 == integer->d());
249}
msarett95416f42016-04-27 13:51:20 -0700250
251DEF_TEST(FlattenRecordedDrawable, r) {
252 // Record a set of canvas draw commands
253 SkPictureRecorder recorder;
254 SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
msarett95416f42016-04-27 13:51:20 -0700255 SkPaint paint;
Mike Reed3661bc92017-02-22 13:21:42 -0500256 paint.setColor(SK_ColorGREEN);
257 canvas->drawPoint(42.0f, 17.0f, paint);
msarett95416f42016-04-27 13:51:20 -0700258 paint.setColor(SK_ColorRED);
259 canvas->drawPaint(paint);
260 SkPaint textPaint;
261 textPaint.setColor(SK_ColorBLUE);
Mike Reed1af9b482019-01-07 11:01:57 -0500262 canvas->drawString("TEXT", 467.0f, 100.0f, SkFont(), textPaint);
msarett95416f42016-04-27 13:51:20 -0700263
264 // Draw some drawables as well
Hal Canary342b7ac2016-11-04 11:49:42 -0400265 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
266 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
267 canvas->drawDrawable(root.get(), 747.0f, 242.0f);
268 sk_sp<PaintDrawable> paintDrawable(new PaintDrawable(paint));
269 canvas->drawDrawable(paintDrawable.get(), 500.0, 500.0f);
270 sk_sp<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
271 canvas->drawDrawable(comDrawable.get(), 10.0f, 10.0f);
msarett95416f42016-04-27 13:51:20 -0700272
273 // Serialize the recorded drawable
274 sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
brianosmanfad98562016-05-04 11:06:28 -0700275 SkBinaryWriteBuffer writeBuffer;
msarett95416f42016-04-27 13:51:20 -0700276 writeBuffer.writeFlattenable(recordedDrawable.get());
277
278 // Copy the contents of the write buffer into a read buffer
279 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
280 writeBuffer.writeToMemory(data->writable_data());
281 SkReadBuffer readBuffer(data->data(), data->size());
msarett95416f42016-04-27 13:51:20 -0700282
283 // Deserialize and verify the drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400284 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
msarett95416f42016-04-27 13:51:20 -0700285 REPORTER_ASSERT(r, out);
286 REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
287}
Mike Reed80747ef2018-01-23 15:29:32 -0500288
289// be sure these constructs compile, don't assert, and return null
290DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
291 auto data = SkData::MakeEmpty();
292
293 #define test(name) REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
294 test(SkPathEffect);
295 test(SkMaskFilter);
296 test(SkShaderBase); // todo: make this just be shader!
297 test(SkColorFilter);
298 test(SkImageFilter);
299 test(SkDrawLooper);
300 #undef test
301}
302