• 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/SkReadBuffer.h"
15 #include "src/core/SkWriteBuffer.h"
16 #include "tests/Test.h"
17 
18 class IntDrawable : public SkDrawable {
19 public:
IntDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d)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 
flatten(SkWriteBuffer & buffer) const27     void flatten(SkWriteBuffer& buffer) const override {
28         buffer.writeUInt(fA);
29         buffer.writeUInt(fB);
30         buffer.writeUInt(fC);
31         buffer.writeUInt(fD);
32     }
33 
CreateProc(SkReadBuffer & buffer)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 
getFactory() const42     Factory getFactory() const override { return CreateProc; }
43 
a() const44     uint32_t a() const { return fA; }
b() const45     uint32_t b() const { return fB; }
c() const46     uint32_t c() const { return fC; }
d() const47     uint32_t d() const { return fD; }
48 
getTypeName() const49     const char* getTypeName() const override { return "IntDrawable"; }
50 
51 protected:
onGetBounds()52     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)53     void onDraw(SkCanvas*) override {}
54 
55 private:
56     uint32_t fA;
57     uint32_t fB;
58     uint32_t fC;
59     uint32_t fD;
60 };
61 
62 class PaintDrawable : public SkDrawable {
63 public:
PaintDrawable(const SkPaint & paint)64     PaintDrawable(const SkPaint& paint)
65         : fPaint(paint)
66     {}
67 
flatten(SkWriteBuffer & buffer) const68     void flatten(SkWriteBuffer& buffer) const override {
69         buffer.writePaint(fPaint);
70     }
71 
CreateProc(SkReadBuffer & buffer)72     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
73         SkPaint paint;
74         buffer.readPaint(&paint, nullptr);
75         return sk_sp<PaintDrawable>(new PaintDrawable(paint));
76     }
77 
getFactory() const78     Factory getFactory() const override { return CreateProc; }
79 
paint() const80     const SkPaint& paint() const { return fPaint; }
81 
getTypeName() const82     const char* getTypeName() const override { return "PaintDrawable"; }
83 
84 protected:
onGetBounds()85     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)86     void onDraw(SkCanvas*) override {}
87 
88 private:
89     SkPaint fPaint;
90 };
91 
92 class CompoundDrawable : public SkDrawable {
93 public:
CompoundDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d,const SkPaint & paint)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 
CompoundDrawable(IntDrawable * intDrawable,PaintDrawable * paintDrawable)99     CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
100         : fIntDrawable(SkRef(intDrawable))
101         , fPaintDrawable(SkRef(paintDrawable))
102     {}
103 
flatten(SkWriteBuffer & buffer) const104     void flatten(SkWriteBuffer& buffer) const override {
105         buffer.writeFlattenable(fIntDrawable.get());
106         buffer.writeFlattenable(fPaintDrawable.get());
107     }
108 
CreateProc(SkReadBuffer & buffer)109     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
110         sk_sp<SkFlattenable> intDrawable(
111                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
112         SkASSERT(intDrawable);
113         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
114 
115         sk_sp<SkFlattenable> paintDrawable(
116                 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 
getFactory() const124     Factory getFactory() const override { return CreateProc; }
125 
intDrawable() const126     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
paintDrawable() const127     PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
128 
getTypeName() const129     const char* getTypeName() const override { return "CompoundDrawable"; }
130 
131 protected:
onGetBounds()132     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)133     void onDraw(SkCanvas*) override {}
134 
135 private:
136     sk_sp<IntDrawable>   fIntDrawable;
137     sk_sp<PaintDrawable> fPaintDrawable;
138 };
139 
140 class RootDrawable : public SkDrawable {
141 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)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 
RootDrawable(CompoundDrawable * compoundDrawable,IntDrawable * intDrawable,SkDrawable * drawable)149     RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
150             SkDrawable* drawable)
151         : fCompoundDrawable(SkRef(compoundDrawable))
152         , fIntDrawable(SkRef(intDrawable))
153         , fDrawable(SkRef(drawable))
154     {}
155 
flatten(SkWriteBuffer & buffer) const156     void flatten(SkWriteBuffer& buffer) const override {
157         buffer.writeFlattenable(fCompoundDrawable.get());
158         buffer.writeFlattenable(fIntDrawable.get());
159         buffer.writeFlattenable(fDrawable.get());
160     }
161 
CreateProc(SkReadBuffer & buffer)162     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
163         sk_sp<SkFlattenable> compoundDrawable(
164                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
165         SkASSERT(compoundDrawable);
166         SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
167 
168         sk_sp<SkFlattenable> intDrawable(
169                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
170         SkASSERT(intDrawable);
171         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
172 
173         sk_sp<SkFlattenable> drawable(
174                 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 
getFactory() const182     Factory getFactory() const override { return CreateProc; }
183 
compoundDrawable() const184     CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
intDrawable() const185     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
drawable() const186     SkDrawable* drawable() const { return fDrawable.get(); }
187 
getTypeName() const188     const char* getTypeName() const override { return "RootDrawable"; }
189 
190 protected:
onGetBounds()191     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)192     void onDraw(SkCanvas*) override {}
193 
194 private:
195     sk_sp<CompoundDrawable> fCompoundDrawable;
196     sk_sp<IntDrawable>      fIntDrawable;
197     sk_sp<SkDrawable>       fDrawable;
198 };
199 
200 // Register these drawables for deserialization some time before main().
201 static struct Initializer {
InitializerInitializer202     Initializer() {
203         SK_REGISTER_FLATTENABLE(IntDrawable);
204         SK_REGISTER_FLATTENABLE(PaintDrawable);
205         SK_REGISTER_FLATTENABLE(CompoundDrawable);
206         SK_REGISTER_FLATTENABLE(RootDrawable);
207     }
208 } initializer;
209 
DEF_TEST(FlattenDrawable,r)210 DEF_TEST(FlattenDrawable, r) {
211     // Create and serialize the test drawable
212     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
213     SkPaint paint;
214     paint.setColor(SK_ColorBLUE);
215     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
216     SkBinaryWriteBuffer writeBuffer;
217     writeBuffer.writeFlattenable(root.get());
218 
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
225     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
226     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 }
250 
DEF_TEST(FlattenRecordedDrawable,r)251 DEF_TEST(FlattenRecordedDrawable, r) {
252     // Record a set of canvas draw commands
253     SkPictureRecorder recorder;
254     SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
255     SkPaint paint;
256     paint.setColor(SK_ColorGREEN);
257     canvas->drawPoint(42.0f, 17.0f, paint);
258     paint.setColor(SK_ColorRED);
259     canvas->drawPaint(paint);
260     SkPaint textPaint;
261     textPaint.setColor(SK_ColorBLUE);
262     canvas->drawString("TEXT", 467.0f, 100.0f, SkFont(), textPaint);
263 
264     // Draw some drawables as well
265     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);
272 
273     // Serialize the recorded drawable
274     sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
275     SkBinaryWriteBuffer writeBuffer;
276     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());
282 
283     // Deserialize and verify the drawable
284     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
285     REPORTER_ASSERT(r, out);
286     REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
287 }
288 
289 // be sure these constructs compile, don't assert, and return null
DEF_TEST(Flattenable_EmptyDeserialze,reporter)290 DEF_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 
303