• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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/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/SkPathEffectBase.h"
15 #include "src/core/SkReadBuffer.h"
16 #include "src/core/SkWriteBuffer.h"
17 #include "tests/Test.h"
18 
19 class IntDrawable : public SkDrawable {
20 public:
IntDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d)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 
flatten(SkWriteBuffer & buffer) const28     void flatten(SkWriteBuffer& buffer) const override {
29         buffer.writeUInt(fA);
30         buffer.writeUInt(fB);
31         buffer.writeUInt(fC);
32         buffer.writeUInt(fD);
33     }
34 
CreateProc(SkReadBuffer & buffer)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 
getFactory() const43     Factory getFactory() const override { return CreateProc; }
44 
a() const45     uint32_t a() const { return fA; }
b() const46     uint32_t b() const { return fB; }
c() const47     uint32_t c() const { return fC; }
d() const48     uint32_t d() const { return fD; }
49 
getTypeName() const50     const char* getTypeName() const override { return "IntDrawable"; }
51 
52 protected:
onGetBounds()53     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)54     void onDraw(SkCanvas*) override {}
55 
56 private:
57     uint32_t fA;
58     uint32_t fB;
59     uint32_t fC;
60     uint32_t fD;
61 };
62 
63 class PaintDrawable : public SkDrawable {
64 public:
PaintDrawable(const SkPaint & paint)65     PaintDrawable(const SkPaint& paint)
66         : fPaint(paint)
67     {}
68 
flatten(SkWriteBuffer & buffer) const69     void flatten(SkWriteBuffer& buffer) const override {
70         buffer.writePaint(fPaint);
71     }
72 
CreateProc(SkReadBuffer & buffer)73     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
74         return sk_sp<PaintDrawable>(new PaintDrawable(buffer.readPaint()));
75     }
76 
getFactory() const77     Factory getFactory() const override { return CreateProc; }
78 
paint() const79     const SkPaint& paint() const { return fPaint; }
80 
getTypeName() const81     const char* getTypeName() const override { return "PaintDrawable"; }
82 
83 protected:
onGetBounds()84     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)85     void onDraw(SkCanvas*) override {}
86 
87 private:
88     SkPaint fPaint;
89 };
90 
91 class CompoundDrawable : public SkDrawable {
92 public:
CompoundDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d,const SkPaint & paint)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 
CompoundDrawable(IntDrawable * intDrawable,PaintDrawable * paintDrawable)98     CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
99         : fIntDrawable(SkRef(intDrawable))
100         , fPaintDrawable(SkRef(paintDrawable))
101     {}
102 
flatten(SkWriteBuffer & buffer) const103     void flatten(SkWriteBuffer& buffer) const override {
104         buffer.writeFlattenable(fIntDrawable.get());
105         buffer.writeFlattenable(fPaintDrawable.get());
106     }
107 
CreateProc(SkReadBuffer & buffer)108     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
109         sk_sp<SkFlattenable> intDrawable(
110                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
111         SkASSERT(intDrawable);
112         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
113 
114         sk_sp<SkFlattenable> paintDrawable(
115                 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 
getFactory() const123     Factory getFactory() const override { return CreateProc; }
124 
intDrawable() const125     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
paintDrawable() const126     PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
127 
getTypeName() const128     const char* getTypeName() const override { return "CompoundDrawable"; }
129 
130 protected:
onGetBounds()131     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)132     void onDraw(SkCanvas*) override {}
133 
134 private:
135     sk_sp<IntDrawable>   fIntDrawable;
136     sk_sp<PaintDrawable> fPaintDrawable;
137 };
138 
139 class RootDrawable : public SkDrawable {
140 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)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 
RootDrawable(CompoundDrawable * compoundDrawable,IntDrawable * intDrawable,SkDrawable * drawable)148     RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
149             SkDrawable* drawable)
150         : fCompoundDrawable(SkRef(compoundDrawable))
151         , fIntDrawable(SkRef(intDrawable))
152         , fDrawable(SkRef(drawable))
153     {}
154 
flatten(SkWriteBuffer & buffer) const155     void flatten(SkWriteBuffer& buffer) const override {
156         buffer.writeFlattenable(fCompoundDrawable.get());
157         buffer.writeFlattenable(fIntDrawable.get());
158         buffer.writeFlattenable(fDrawable.get());
159     }
160 
CreateProc(SkReadBuffer & buffer)161     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
162         sk_sp<SkFlattenable> compoundDrawable(
163                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
164         SkASSERT(compoundDrawable);
165         SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
166 
167         sk_sp<SkFlattenable> intDrawable(
168                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
169         SkASSERT(intDrawable);
170         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
171 
172         sk_sp<SkFlattenable> drawable(
173                 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 
getFactory() const181     Factory getFactory() const override { return CreateProc; }
182 
compoundDrawable() const183     CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
intDrawable() const184     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
drawable() const185     SkDrawable* drawable() const { return fDrawable.get(); }
186 
getTypeName() const187     const char* getTypeName() const override { return "RootDrawable"; }
188 
189 protected:
onGetBounds()190     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)191     void onDraw(SkCanvas*) override {}
192 
193 private:
194     sk_sp<CompoundDrawable> fCompoundDrawable;
195     sk_sp<IntDrawable>      fIntDrawable;
196     sk_sp<SkDrawable>       fDrawable;
197 };
198 
199 // Register these drawables for deserialization some time before main().
200 static struct Initializer {
InitializerInitializer201     Initializer() {
202         SK_REGISTER_FLATTENABLE(IntDrawable);
203         SK_REGISTER_FLATTENABLE(PaintDrawable);
204         SK_REGISTER_FLATTENABLE(CompoundDrawable);
205         SK_REGISTER_FLATTENABLE(RootDrawable);
206     }
207 } initializer;
208 
DEF_TEST(FlattenDrawable,r)209 DEF_TEST(FlattenDrawable, r) {
210     // Create and serialize the test drawable
211     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
212     SkPaint paint;
213     paint.setColor(SK_ColorBLUE);
214     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
215     SkBinaryWriteBuffer writeBuffer;
216     writeBuffer.writeFlattenable(root.get());
217 
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
224     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
225     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 }
249 
DEF_TEST(FlattenRecordedDrawable,r)250 DEF_TEST(FlattenRecordedDrawable, r) {
251     // Record a set of canvas draw commands
252     SkPictureRecorder recorder;
253     SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
254     SkPaint paint;
255     paint.setColor(SK_ColorGREEN);
256     canvas->drawPoint(42.0f, 17.0f, paint);
257     paint.setColor(SK_ColorRED);
258     canvas->drawPaint(paint);
259     SkPaint textPaint;
260     textPaint.setColor(SK_ColorBLUE);
261     canvas->drawString("TEXT", 467.0f, 100.0f, SkFont(), textPaint);
262 
263     // Draw some drawables as well
264     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);
271 
272     // Serialize the recorded drawable
273     sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
274     SkBinaryWriteBuffer writeBuffer;
275     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());
281 
282     // Deserialize and verify the drawable
283     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
284     REPORTER_ASSERT(r, out);
285     REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
286 }
287 
288 // be sure these constructs compile, don't assert, and return null
DEF_TEST(Flattenable_EmptyDeserialze,reporter)289 DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
290     auto data = SkData::MakeEmpty();
291 
292     #define test(name)  REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
293     test(SkPathEffectBase);
294     test(SkMaskFilter);
295     test(SkShaderBase); // todo: make this just be shader!
296     test(SkColorFilterBase);
297     test(SkImageFilter);
298     #undef test
299 }
300 
301