xref: /aosp_15_r20/external/skia/tests/FlattenDrawableTest.cpp (revision c8dee2aa9b3f27cf6c858bd81872bdeb2c07ed17)
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