• 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/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/SkColorFilterBase.h"
22 #include "src/core/SkPathEffectBase.h"
23 #include "src/core/SkReadBuffer.h"
24 #include "src/core/SkWriteBuffer.h"
25 #include "src/shaders/SkShaderBase.h"
26 #include "tests/Test.h"
27 
28 #include <cstdint>
29 #include <string>
30 
31 class IntDrawable : public SkDrawable {
32 public:
IntDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d)33     IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d)
34         : fA(a)
35         , fB(b)
36         , fC(c)
37         , fD(d)
38     {}
39 
flatten(SkWriteBuffer & buffer) const40     void flatten(SkWriteBuffer& buffer) const override {
41         buffer.writeUInt(fA);
42         buffer.writeUInt(fB);
43         buffer.writeUInt(fC);
44         buffer.writeUInt(fD);
45     }
46 
CreateProc(SkReadBuffer & buffer)47     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
48         uint32_t a = buffer.readUInt();
49         uint32_t b = buffer.readUInt();
50         uint32_t c = buffer.readUInt();
51         uint32_t d = buffer.readUInt();
52         return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d));
53     }
54 
getFactory() const55     Factory getFactory() const override { return CreateProc; }
56 
a() const57     uint32_t a() const { return fA; }
b() const58     uint32_t b() const { return fB; }
c() const59     uint32_t c() const { return fC; }
d() const60     uint32_t d() const { return fD; }
61 
getTypeName() const62     const char* getTypeName() const override { return "IntDrawable"; }
63 
64 protected:
onGetBounds()65     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)66     void onDraw(SkCanvas*) override {}
67 
68 private:
69     uint32_t fA;
70     uint32_t fB;
71     uint32_t fC;
72     uint32_t fD;
73 };
74 
75 class PaintDrawable : public SkDrawable {
76 public:
PaintDrawable(const SkPaint & paint)77     PaintDrawable(const SkPaint& paint)
78         : fPaint(paint)
79     {}
80 
flatten(SkWriteBuffer & buffer) const81     void flatten(SkWriteBuffer& buffer) const override {
82         buffer.writePaint(fPaint);
83     }
84 
CreateProc(SkReadBuffer & buffer)85     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
86         return sk_sp<PaintDrawable>(new PaintDrawable(buffer.readPaint()));
87     }
88 
getFactory() const89     Factory getFactory() const override { return CreateProc; }
90 
paint() const91     const SkPaint& paint() const { return fPaint; }
92 
getTypeName() const93     const char* getTypeName() const override { return "PaintDrawable"; }
94 
95 protected:
onGetBounds()96     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)97     void onDraw(SkCanvas*) override {}
98 
99 private:
100     SkPaint fPaint;
101 };
102 
103 class CompoundDrawable : public SkDrawable {
104 public:
CompoundDrawable(uint32_t a,uint32_t b,uint32_t c,uint32_t d,const SkPaint & paint)105     CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint)
106         : fIntDrawable(new IntDrawable(a, b, c, d))
107         , fPaintDrawable(new PaintDrawable(paint))
108     {}
109 
CompoundDrawable(IntDrawable * intDrawable,PaintDrawable * paintDrawable)110     CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
111         : fIntDrawable(SkRef(intDrawable))
112         , fPaintDrawable(SkRef(paintDrawable))
113     {}
114 
flatten(SkWriteBuffer & buffer) const115     void flatten(SkWriteBuffer& buffer) const override {
116         buffer.writeFlattenable(fIntDrawable.get());
117         buffer.writeFlattenable(fPaintDrawable.get());
118     }
119 
CreateProc(SkReadBuffer & buffer)120     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
121         sk_sp<SkFlattenable> intDrawable(
122                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
123         SkASSERT(intDrawable);
124         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
125 
126         sk_sp<SkFlattenable> paintDrawable(
127                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
128         SkASSERT(paintDrawable);
129         SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName()));
130 
131         return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(),
132                                                             (PaintDrawable*) paintDrawable.get()));
133     }
134 
getFactory() const135     Factory getFactory() const override { return CreateProc; }
136 
intDrawable() const137     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
paintDrawable() const138     PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
139 
getTypeName() const140     const char* getTypeName() const override { return "CompoundDrawable"; }
141 
142 protected:
onGetBounds()143     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)144     void onDraw(SkCanvas*) override {}
145 
146 private:
147     sk_sp<IntDrawable>   fIntDrawable;
148     sk_sp<PaintDrawable> fPaintDrawable;
149 };
150 
151 class RootDrawable : public SkDrawable {
152 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)153     RootDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint,
154                    uint32_t e, uint32_t f, uint32_t g, uint32_t h, SkDrawable* drawable)
155         : fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint))
156         , fIntDrawable(new IntDrawable(e, f, g, h))
157         , fDrawable(SkRef(drawable))
158     {}
159 
RootDrawable(CompoundDrawable * compoundDrawable,IntDrawable * intDrawable,SkDrawable * drawable)160     RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
161             SkDrawable* drawable)
162         : fCompoundDrawable(SkRef(compoundDrawable))
163         , fIntDrawable(SkRef(intDrawable))
164         , fDrawable(SkRef(drawable))
165     {}
166 
flatten(SkWriteBuffer & buffer) const167     void flatten(SkWriteBuffer& buffer) const override {
168         buffer.writeFlattenable(fCompoundDrawable.get());
169         buffer.writeFlattenable(fIntDrawable.get());
170         buffer.writeFlattenable(fDrawable.get());
171     }
172 
CreateProc(SkReadBuffer & buffer)173     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
174         sk_sp<SkFlattenable> compoundDrawable(
175                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
176         SkASSERT(compoundDrawable);
177         SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName()));
178 
179         sk_sp<SkFlattenable> intDrawable(
180                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
181         SkASSERT(intDrawable);
182         SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName()));
183 
184         sk_sp<SkFlattenable> drawable(
185                 buffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
186         SkASSERT(drawable);
187 
188         return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(),
189                                                     (IntDrawable*) intDrawable.get(),
190                                                     (SkDrawable*) drawable.get()));
191     }
192 
getFactory() const193     Factory getFactory() const override { return CreateProc; }
194 
compoundDrawable() const195     CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
intDrawable() const196     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
drawable() const197     SkDrawable* drawable() const { return fDrawable.get(); }
198 
getTypeName() const199     const char* getTypeName() const override { return "RootDrawable"; }
200 
201 protected:
onGetBounds()202     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
onDraw(SkCanvas *)203     void onDraw(SkCanvas*) override {}
204 
205 private:
206     sk_sp<CompoundDrawable> fCompoundDrawable;
207     sk_sp<IntDrawable>      fIntDrawable;
208     sk_sp<SkDrawable>       fDrawable;
209 };
210 
211 // Register these drawables for deserialization some time before main().
212 static struct Initializer {
InitializerInitializer213     Initializer() {
214         SK_REGISTER_FLATTENABLE(IntDrawable);
215         SK_REGISTER_FLATTENABLE(PaintDrawable);
216         SK_REGISTER_FLATTENABLE(CompoundDrawable);
217         SK_REGISTER_FLATTENABLE(RootDrawable);
218     }
219 } initializer;
220 
DEF_TEST(FlattenDrawable,r)221 DEF_TEST(FlattenDrawable, r) {
222     // Create and serialize the test drawable
223     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
224     SkPaint paint;
225     paint.setColor(SK_ColorBLUE);
226     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
227     SkBinaryWriteBuffer writeBuffer;
228     writeBuffer.writeFlattenable(root.get());
229 
230     // Copy the contents of the write buffer into a read buffer
231     sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
232     writeBuffer.writeToMemory(data->writable_data());
233     SkReadBuffer readBuffer(data->data(), data->size());
234 
235     // Deserialize and verify the drawable
236     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
237     REPORTER_ASSERT(r, out);
238     REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
239 
240     RootDrawable* rootOut = (RootDrawable*) out.get();
241     REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
242     REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
243     REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
244     REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
245     REPORTER_ASSERT(r, SK_ColorBLUE ==
246             rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
247     REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
248     REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
249     REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
250     REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
251 
252     // Note that we can still recognize the generic drawable as an IntDrawable
253     SkDrawable* generic = rootOut->drawable();
254     REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
255     IntDrawable* integer = (IntDrawable*) generic;
256     REPORTER_ASSERT(r, 1 == integer->a());
257     REPORTER_ASSERT(r, 2 == integer->b());
258     REPORTER_ASSERT(r, 3 == integer->c());
259     REPORTER_ASSERT(r, 4 == integer->d());
260 }
261 
DEF_TEST(FlattenRecordedDrawable,r)262 DEF_TEST(FlattenRecordedDrawable, r) {
263     // Record a set of canvas draw commands
264     SkPictureRecorder recorder;
265     SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
266     SkPaint paint;
267     paint.setColor(SK_ColorGREEN);
268     canvas->drawPoint(42.0f, 17.0f, paint);
269     paint.setColor(SK_ColorRED);
270     canvas->drawPaint(paint);
271     SkPaint textPaint;
272     textPaint.setColor(SK_ColorBLUE);
273     canvas->drawString("TEXT", 467.0f, 100.0f, SkFont(), textPaint);
274 
275     // Draw some drawables as well
276     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
277     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
278     canvas->drawDrawable(root.get(), 747.0f, 242.0f);
279     sk_sp<PaintDrawable> paintDrawable(new PaintDrawable(paint));
280     canvas->drawDrawable(paintDrawable.get(), 500.0, 500.0f);
281     sk_sp<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
282     canvas->drawDrawable(comDrawable.get(), 10.0f, 10.0f);
283 
284     // Serialize the recorded drawable
285     sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
286     SkBinaryWriteBuffer writeBuffer;
287     writeBuffer.writeFlattenable(recordedDrawable.get());
288 
289     // Copy the contents of the write buffer into a read buffer
290     sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
291     writeBuffer.writeToMemory(data->writable_data());
292     SkReadBuffer readBuffer(data->data(), data->size());
293 
294     // Deserialize and verify the drawable
295     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
296     REPORTER_ASSERT(r, out);
297     REPORTER_ASSERT(r, !strcmp("SkRecordedDrawable", out->getTypeName()));
298 }
299 
300 // be sure these constructs compile, don't assert, and return null
DEF_TEST(Flattenable_EmptyDeserialze,reporter)301 DEF_TEST(Flattenable_EmptyDeserialze, reporter) {
302     auto data = SkData::MakeEmpty();
303 
304     #define test(name)  REPORTER_ASSERT(reporter, !name::Deserialize(data->data(), data->size()))
305     test(SkPathEffectBase);
306     test(SkMaskFilter);
307     test(SkShaderBase); // todo: make this just be shader!
308     test(SkColorFilterBase);
309     test(SkImageFilter);
310     #undef test
311 }
312 
313