Home | History | Annotate | Download | only in tests
      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 "SkCanvas.h"
      9 #include "SkDrawable.h"
     10 #include "SkOnce.h"
     11 #include "SkPictureRecorder.h"
     12 #include "SkReadBuffer.h"
     13 #include "SkRect.h"
     14 #include "SkStream.h"
     15 #include "SkWriteBuffer.h"
     16 #include "Test.h"
     17 
     18 class IntDrawable : public SkDrawable {
     19 public:
     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 
     27     void flatten(SkWriteBuffer& buffer) const override {
     28         buffer.writeUInt(fA);
     29         buffer.writeUInt(fB);
     30         buffer.writeUInt(fC);
     31         buffer.writeUInt(fD);
     32     }
     33 
     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 
     42     Factory getFactory() const override { return CreateProc; }
     43 
     44     uint32_t a() const { return fA; }
     45     uint32_t b() const { return fB; }
     46     uint32_t c() const { return fC; }
     47     uint32_t d() const { return fD; }
     48 
     49     const char* getTypeName() const override { return "IntDrawable"; }
     50 
     51 protected:
     52     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
     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:
     64     PaintDrawable(const SkPaint& paint)
     65         : fPaint(paint)
     66     {}
     67 
     68     void flatten(SkWriteBuffer& buffer) const override {
     69         buffer.writePaint(fPaint);
     70     }
     71 
     72     static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) {
     73         SkPaint paint;
     74         buffer.readPaint(&paint);
     75         return sk_sp<PaintDrawable>(new PaintDrawable(paint));
     76     }
     77 
     78     Factory getFactory() const override { return CreateProc; }
     79 
     80     const SkPaint& paint() const { return fPaint; }
     81 
     82     const char* getTypeName() const override { return "PaintDrawable"; }
     83 
     84 protected:
     85     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
     86     void onDraw(SkCanvas*) override {}
     87 
     88 private:
     89     SkPaint fPaint;
     90 };
     91 
     92 class CompoundDrawable : public SkDrawable {
     93 public:
     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 
     99     CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable)
    100         : fIntDrawable(SkRef(intDrawable))
    101         , fPaintDrawable(SkRef(paintDrawable))
    102     {}
    103 
    104     void flatten(SkWriteBuffer& buffer) const override {
    105         buffer.writeFlattenable(fIntDrawable.get());
    106         buffer.writeFlattenable(fPaintDrawable.get());
    107     }
    108 
    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 
    124     Factory getFactory() const override { return CreateProc; }
    125 
    126     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
    127     PaintDrawable* paintDrawable() const { return fPaintDrawable.get(); }
    128 
    129     const char* getTypeName() const override { return "CompoundDrawable"; }
    130 
    131 protected:
    132     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
    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:
    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 
    149     RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable,
    150             SkDrawable* drawable)
    151         : fCompoundDrawable(SkRef(compoundDrawable))
    152         , fIntDrawable(SkRef(intDrawable))
    153         , fDrawable(SkRef(drawable))
    154     {}
    155 
    156     void flatten(SkWriteBuffer& buffer) const override {
    157         buffer.writeFlattenable(fCompoundDrawable.get());
    158         buffer.writeFlattenable(fIntDrawable.get());
    159         buffer.writeFlattenable(fDrawable.get());
    160     }
    161 
    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 
    182     Factory getFactory() const override { return CreateProc; }
    183 
    184     CompoundDrawable* compoundDrawable() const { return fCompoundDrawable.get(); }
    185     IntDrawable* intDrawable() const { return fIntDrawable.get(); }
    186     SkDrawable* drawable() const { return fDrawable.get(); }
    187 
    188     const char* getTypeName() const override { return "RootDrawable"; }
    189 
    190 protected:
    191     SkRect onGetBounds() override { return SkRect::MakeEmpty(); }
    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 static void register_test_drawables(SkReadBuffer& buffer) {
    201     buffer.setCustomFactory(SkString("IntDrawable"), IntDrawable::CreateProc);
    202     buffer.setCustomFactory(SkString("PaintDrawable"), PaintDrawable::CreateProc);
    203     buffer.setCustomFactory(SkString("CompoundDrawable"), CompoundDrawable::CreateProc);
    204     buffer.setCustomFactory(SkString("RootDrawable"), RootDrawable::CreateProc);
    205 }
    206 
    207 DEF_TEST(FlattenDrawable, r) {
    208     // Create and serialize the test drawable
    209     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
    210     SkPaint paint;
    211     paint.setColor(SK_ColorBLUE);
    212     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
    213     SkBinaryWriteBuffer writeBuffer;
    214     writeBuffer.writeFlattenable(root.get());
    215 
    216     // Copy the contents of the write buffer into a read buffer
    217     sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
    218     writeBuffer.writeToMemory(data->writable_data());
    219     SkReadBuffer readBuffer(data->data(), data->size());
    220     register_test_drawables(readBuffer);
    221 
    222     // Deserialize and verify the drawable
    223     sk_sp<SkDrawable> out((SkDrawable*)readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type));
    224     REPORTER_ASSERT(r, out);
    225     REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName()));
    226 
    227     RootDrawable* rootOut = (RootDrawable*) out.get();
    228     REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a());
    229     REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b());
    230     REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c());
    231     REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d());
    232     REPORTER_ASSERT(r, SK_ColorBLUE ==
    233             rootOut->compoundDrawable()->paintDrawable()->paint().getColor());
    234     REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a());
    235     REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b());
    236     REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c());
    237     REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d());
    238 
    239     // Note that we can still recognize the generic drawable as an IntDrawable
    240     SkDrawable* generic = rootOut->drawable();
    241     REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName()));
    242     IntDrawable* integer = (IntDrawable*) generic;
    243     REPORTER_ASSERT(r, 1 == integer->a());
    244     REPORTER_ASSERT(r, 2 == integer->b());
    245     REPORTER_ASSERT(r, 3 == integer->c());
    246     REPORTER_ASSERT(r, 4 == integer->d());
    247 }
    248 
    249 DEF_TEST(FlattenRecordedDrawable, r) {
    250     // Record a set of canvas draw commands
    251     SkPictureRecorder recorder;
    252     SkCanvas* canvas = recorder.beginRecording(1000.0f, 1000.0f);
    253     SkPaint paint;
    254     paint.setColor(SK_ColorGREEN);
    255     canvas->drawPoint(42.0f, 17.0f, paint);
    256     paint.setColor(SK_ColorRED);
    257     canvas->drawPaint(paint);
    258     SkPaint textPaint;
    259     textPaint.setColor(SK_ColorBLUE);
    260     canvas->drawString("TEXT", 467.0f, 100.0f, textPaint);
    261 
    262     // Draw some drawables as well
    263     sk_sp<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4));
    264     sk_sp<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable.get()));
    265     canvas->drawDrawable(root.get(), 747.0f, 242.0f);
    266     sk_sp<PaintDrawable> paintDrawable(new PaintDrawable(paint));
    267     canvas->drawDrawable(paintDrawable.get(), 500.0, 500.0f);
    268     sk_sp<CompoundDrawable> comDrawable(new CompoundDrawable(13, 14, 15, 16, textPaint));
    269     canvas->drawDrawable(comDrawable.get(), 10.0f, 10.0f);
    270 
    271     // Serialize the recorded drawable
    272     sk_sp<SkDrawable> recordedDrawable = recorder.finishRecordingAsDrawable();
    273     SkBinaryWriteBuffer writeBuffer;
    274     writeBuffer.writeFlattenable(recordedDrawable.get());
    275 
    276     // Copy the contents of the write buffer into a read buffer
    277     sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten());
    278     writeBuffer.writeToMemory(data->writable_data());
    279     SkReadBuffer readBuffer(data->data(), data->size());
    280     register_test_drawables(readBuffer);
    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
    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(SkPathEffect);
    294     test(SkMaskFilter);
    295     test(SkShaderBase); // todo: make this just be shader!
    296     test(SkColorFilter);
    297     test(SkImageFilter);
    298     test(SkDrawLooper);
    299     #undef test
    300 }
    301 
    302