blob: 0d164aa76bb0bd1b8f8989143964dd68a8dc7cb2 [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"
Mike Reedec9d0e82021-05-21 17:42:14 -040014#include "src/core/SkPathEffectBase.h"
Mike Kleinc0bd9f92019-04-23 12:05:21 -050015#include "src/core/SkReadBuffer.h"
16#include "src/core/SkWriteBuffer.h"
17#include "tests/Test.h"
msarettedf7fcd2016-04-25 06:40:26 -070018
19class IntDrawable : public SkDrawable {
20public:
21 IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
22 : fA(a)
23 , fB(b)
24 , fC(c)
25 , fD(d)
26 {}
27
28 void flatten(SkWriteBuffer& buffer) const override {
29 buffer.writeUInt(fA);
30 buffer.writeUInt(fB);
31 buffer.writeUInt(fC);
32 buffer.writeUInt(fD);
33 }
34
35 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
36 uint32_t a = buffer.readUInt();
37 uint32_t b = buffer.readUInt();
38 uint32_t c = buffer.readUInt();
39 uint32_t d = buffer.readUInt();
40 return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d));
41 }
42
43 Factory getFactory() const override { return CreateProc; }
44
45 uint32_t a() const { return fA; }
46 uint32_t b() const { return fB; }
47 uint32_t c() const { return fC; }
48 uint32_t d() const { return fD; }
49
50 const char* getTypeName() const override { return "IntDrawable"; }
51
52protected:
53 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
54 void onDraw(SkCanvas*) override {}
55
56private:
57 uint32_t fA;
58 uint32_t fB;
59 uint32_t fC;
60 uint32_t fD;
61};
62
63class PaintDrawable : public SkDrawable {
64public:
65 PaintDrawable(const SkPaint& paint)
66 : fPaint(paint)
67 {}
68
69 void flatten(SkWriteBuffer& buffer) const override {
70 buffer.writePaint(fPaint);
71 }
72
73 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
Mike Reed22cada02021-08-09 10:46:33 -040074 return sk_sp<PaintDrawable>(new PaintDrawable(buffer.readPaint()));
msarettedf7fcd2016-04-25 06:40:26 -070075 }
76
77 Factory getFactory() const override { return CreateProc; }
78
79 const SkPaint& paint() const { return fPaint; }
80
msarett002c92b2016-04-26 08:20:14 -070081 const char* getTypeName() const override { return "PaintDrawable"; }
82
msarettedf7fcd2016-04-25 06:40:26 -070083protected:
84 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
85 void onDraw(SkCanvas*) override {}
86
87private:
88 SkPaint fPaint;
89};
90
91class CompoundDrawable : public SkDrawable {
92public:
93 CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint)
94 : fIntDrawable(new IntDrawable(a, b, c, d))
95 , fPaintDrawable(new PaintDrawable(paint))
96 {}
97
98 CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
99 : fIntDrawable(SkRef(intDrawable))
100 , fPaintDrawable(SkRef(paintDrawable))
101 {}
102
103 void flatten(SkWriteBuffer& buffer) const override {
Hal Canary342b7ac2016-11-04 11:49:42 -0400104 buffer.writeFlattenable(fIntDrawable.get());
105 buffer.writeFlattenable(fPaintDrawable.get());
msarettedf7fcd2016-04-25 06:40:26 -0700106 }
107
108 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
Hal Canary342b7ac2016-11-04 11:49:42 -0400109 sk_sp<SkFlattenable> intDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700110 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
111 SkASSERT(intDrawable);
112 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
113
Hal Canary342b7ac2016-11-04 11:49:42 -0400114 sk_sp<SkFlattenable> paintDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700115 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
116 SkASSERT(paintDrawable);
117 SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName()));
118
119 return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(),
120 (PaintDrawable*) paintDrawable.get()));
121 }
122
123 Factory getFactory() const override { return CreateProc; }
124
Hal Canary342b7ac2016-11-04 11:49:42 -0400125 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
126 PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
msarettedf7fcd2016-04-25 06:40:26 -0700127
msarett002c92b2016-04-26 08:20:14 -0700128 const char* getTypeName() const override { return "CompoundDrawable"; }
129
msarettedf7fcd2016-04-25 06:40:26 -0700130protected:
131 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
132 void onDraw(SkCanvas*) override {}
133
134private:
Hal Canary342b7ac2016-11-04 11:49:42 -0400135 sk_sp<IntDrawable> fIntDrawable;
136 sk_sp<PaintDrawable> fPaintDrawable;
msarettedf7fcd2016-04-25 06:40:26 -0700137};
138
139class RootDrawable : public SkDrawable {
140public:
141 RootDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint,
142 uint32_t e, uint32_t f, uint32_t g, uint32_t h, SkDrawable* drawable)
143 : fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint))
144 , fIntDrawable(new IntDrawable(e, f, g, h))
145 , fDrawable(SkRef(drawable))
146 {}
147
148 RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
149 SkDrawable* drawable)
150 : fCompoundDrawable(SkRef(compoundDrawable))
151 , fIntDrawable(SkRef(intDrawable))
152 , fDrawable(SkRef(drawable))
153 {}
154
155 void flatten(SkWriteBuffer& buffer) const override {
Hal Canary342b7ac2016-11-04 11:49:42 -0400156 buffer.writeFlattenable(fCompoundDrawable.get());
157 buffer.writeFlattenable(fIntDrawable.get());
158 buffer.writeFlattenable(fDrawable.get());
msarettedf7fcd2016-04-25 06:40:26 -0700159 }
160
161 static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
Hal Canary342b7ac2016-11-04 11:49:42 -0400162 sk_sp<SkFlattenable> compoundDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700163 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
164 SkASSERT(compoundDrawable);
165 SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
166
Hal Canary342b7ac2016-11-04 11:49:42 -0400167 sk_sp<SkFlattenable> intDrawable(
msarettedf7fcd2016-04-25 06:40:26 -0700168 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
169 SkASSERT(intDrawable);
170 SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
171
Hal Canary342b7ac2016-11-04 11:49:42 -0400172 sk_sp<SkFlattenable> drawable(
msarettedf7fcd2016-04-25 06:40:26 -0700173 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
174 SkASSERT(drawable);
175
176 return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(),
177 (IntDrawable*) intDrawable.get(),
178 (SkDrawable*) drawable.get()));
179 }
180
181 Factory getFactory() const override { return CreateProc; }
182
Hal Canary342b7ac2016-11-04 11:49:42 -0400183 CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
184 IntDrawable* intDrawable() const { return fIntDrawable.get(); }
185 SkDrawable* drawable() const { return fDrawable.get(); }
msarettedf7fcd2016-04-25 06:40:26 -0700186
msarett002c92b2016-04-26 08:20:14 -0700187 const char* getTypeName() const override { return "RootDrawable"; }
188
msarettedf7fcd2016-04-25 06:40:26 -0700189protected:
190 SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
191 void onDraw(SkCanvas*) override {}
192
193private:
Hal Canary342b7ac2016-11-04 11:49:42 -0400194 sk_sp<CompoundDrawable> fCompoundDrawable;
195 sk_sp<IntDrawable> fIntDrawable;
196 sk_sp<SkDrawable> fDrawable;
msarettedf7fcd2016-04-25 06:40:26 -0700197};
198
Mike Klein4c683fc2018-10-19 17:35:02 -0400199// Register these drawables for deserialization some time before main().
200static struct Initializer {
201 Initializer() {
Brian Salomon23356442018-11-30 15:33:19 -0500202 SK_REGISTER_FLATTENABLE(IntDrawable);
203 SK_REGISTER_FLATTENABLE(PaintDrawable);
204 SK_REGISTER_FLATTENABLE(CompoundDrawable);
205 SK_REGISTER_FLATTENABLE(RootDrawable);
Mike Klein4c683fc2018-10-19 17:35:02 -0400206 }
207} initializer;
msarettedf7fcd2016-04-25 06:40:26 -0700208
209DEF_TEST(FlattenDrawable, r) {
msarettedf7fcd2016-04-25 06:40:26 -0700210 // Create and serialize the test drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400211 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
msarettedf7fcd2016-04-25 06:40:26 -0700212 SkPaint paint;
213 paint.setColor(SK_ColorBLUE);
Hal Canary342b7ac2016-11-04 11:49:42 -0400214 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
brianosmanfad98562016-05-04 11:06:28 -0700215 SkBinaryWriteBuffer writeBuffer;
Hal Canary342b7ac2016-11-04 11:49:42 -0400216 writeBuffer.writeFlattenable(root.get());
msarettedf7fcd2016-04-25 06:40:26 -0700217
218 // Copy the contents of the write buffer into a read buffer
219 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
220 writeBuffer.writeToMemory(data->writable_data());
221 SkReadBuffer readBuffer(data->data(), data->size());
222
223 // Deserialize and verify the drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400224 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
msarettedf7fcd2016-04-25 06:40:26 -0700225 REPORTER_ASSERT(r, out);
226 REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
227
228 RootDrawable* rootOut = (RootDrawable*) out.get();
229 REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
230 REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
231 REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
232 REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
233 REPORTER_ASSERT(r, SK_ColorBLUE ==
234 rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
235 REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
236 REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
237 REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
238 REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
239
240 // Note that we can still recognize the generic drawable as an IntDrawable
241 SkDrawable* generic = rootOut->drawable();
242 REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
243 IntDrawable* integer = (IntDrawable*) generic;
244 REPORTER_ASSERT(r, 1 == integer->a());
245 REPORTER_ASSERT(r, 2 == integer->b());
246 REPORTER_ASSERT(r, 3 == integer->c());
247 REPORTER_ASSERT(r, 4 == integer->d());
248}
msarett95416f42016-04-27 13:51:20 -0700249
250DEF_TEST(FlattenRecordedDrawable, r) {
251 // Record a set of canvas draw commands
252 SkPictureRecorder recorder;
253 SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
msarett95416f42016-04-27 13:51:20 -0700254 SkPaint paint;
Mike Reed3661bc92017-02-22 13:21:42 -0500255 paint.setColor(SK_ColorGREEN);
256 canvas->drawPoint(42.0f, 17.0f, paint);
msarett95416f42016-04-27 13:51:20 -0700257 paint.setColor(SK_ColorRED);
258 canvas->drawPaint(paint);
259 SkPaint textPaint;
260 textPaint.setColor(SK_ColorBLUE);
Mike Reed1af9b482019-01-07 11:01:57 -0500261 canvas->drawString("TEXT", 467.0f, 100.0f, SkFont(), textPaint);
msarett95416f42016-04-27 13:51:20 -0700262
263 // Draw some drawables as well
Hal Canary342b7ac2016-11-04 11:49:42 -0400264 sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
265 sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
266 canvas->drawDrawable(root.get(), 747.0f, 242.0f);
267 sk_sp<PaintDrawable> paintDrawable(new PaintDrawable(paint));
268 canvas->drawDrawable(paintDrawable.get(), 500.0, 500.0f);
269 sk_sp<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
270 canvas->drawDrawable(comDrawable.get(), 10.0f, 10.0f);
msarett95416f42016-04-27 13:51:20 -0700271
272 // Serialize the recorded drawable
273 sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
brianosmanfad98562016-05-04 11:06:28 -0700274 SkBinaryWriteBuffer writeBuffer;
msarett95416f42016-04-27 13:51:20 -0700275 writeBuffer.writeFlattenable(recordedDrawable.get());
276
277 // Copy the contents of the write buffer into a read buffer
278 sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
279 writeBuffer.writeToMemory(data->writable_data());
280 SkReadBuffer readBuffer(data->data(), data->size());
msarett95416f42016-04-27 13:51:20 -0700281
282 // Deserialize and verify the drawable
Hal Canary342b7ac2016-11-04 11:49:42 -0400283 sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
msarett95416f42016-04-27 13:51:20 -0700284 REPORTER_ASSERT(r, out);
285 REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
286}
Mike Reed80747ef2018-01-23 15:29:32 -0500287
288// be sure these constructs compile, don't assert, and return null
289DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
290 auto data = SkData::MakeEmpty();
291
292 #define test(name) REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
Mike Reedec9d0e82021-05-21 17:42:14 -0400293 test(SkPathEffectBase);
Mike Reed80747ef2018-01-23 15:29:32 -0500294 test(SkMaskFilter);
295 test(SkShaderBase); // todo: make this just be shader!
Mike Reedb11e6272020-06-24 16:56:33 -0400296 test(SkColorFilterBase);
Mike Reed80747ef2018-01-23 15:29:32 -0500297 test(SkImageFilter);
Mike Reed80747ef2018-01-23 15:29:32 -0500298 #undef test
299}
300