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