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