diff options
author | msarett <msarett@google.com> | 2016-04-25 06:40:26 -0700 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2016-04-25 06:40:26 -0700 |
commit | edf7fcd8b9e339800edb61ae422f8b6c1b77c3e8 (patch) | |
tree | 93be6103d394984eab3984a9ab5f32ff08ea69d8 | |
parent | 5d36360c47ed48c93e6928cc5de1a5ebd65b6eea (diff) |
Make SkDrawable an SkFlattenable
BUG=skia:
GOLD_TRYBOT_URL= https://gold.skia.org/search2?unt=true&query=source_type%3Dgm&master=false&issue=1911403004
Review URL: https://codereview.chromium.org/1911403004
-rw-r--r-- | include/core/SkDrawable.h | 8 | ||||
-rw-r--r-- | include/core/SkFlattenable.h | 1 | ||||
-rw-r--r-- | tests/FlattenDrawableTest.cpp | 281 |
3 files changed, 288 insertions, 2 deletions
diff --git a/include/core/SkDrawable.h b/include/core/SkDrawable.h index 2f0a62d8b5..6fec3fcf93 100644 --- a/include/core/SkDrawable.h +++ b/include/core/SkDrawable.h @@ -8,9 +8,10 @@ #ifndef SkDrawable_DEFINED #define SkDrawable_DEFINED -#include "SkRefCnt.h" +#include "SkFlattenable.h" class SkCanvas; +class SkMatrix; class SkPicture; struct SkRect; @@ -21,7 +22,7 @@ struct SkRect; * allow for clients of the drawable that may want to cache the results, the drawable must * change its generation ID whenever its internal state changes such that it will draw differently. */ -class SkDrawable : public SkRefCnt { +class SkDrawable : public SkFlattenable { public: SkDrawable(); @@ -58,6 +59,9 @@ public: */ void notifyDrawingChanged(); + SK_DEFINE_FLATTENABLE_TYPE(SkDrawable) + Factory getFactory() const override { return nullptr; } + protected: virtual SkRect onGetBounds() = 0; virtual void onDraw(SkCanvas*) = 0; diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h index 0ba83da087..260ea33dab 100644 --- a/include/core/SkFlattenable.h +++ b/include/core/SkFlattenable.h @@ -71,6 +71,7 @@ class SK_API SkFlattenable : public SkRefCnt { public: enum Type { kSkColorFilter_Type, + kSkDrawable_Type, kSkDrawLooper_Type, kSkImageFilter_Type, kSkMaskFilter_Type, diff --git a/tests/FlattenDrawableTest.cpp b/tests/FlattenDrawableTest.cpp new file mode 100644 index 0000000000..dd06b410b2 --- /dev/null +++ b/tests/FlattenDrawableTest.cpp @@ -0,0 +1,281 @@ +/* + * Copyright 2016 Google Inc. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#include "SkCanvas.h" +#include "SkDrawable.h" +#include "SkOnce.h" +#include "SkPictureRecorder.h" +#include "SkReadBuffer.h" +#include "SkRect.h" +#include "SkStream.h" +#include "SkWriteBuffer.h" +#include "Test.h" + +class IntDrawable : public SkDrawable { +public: + IntDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d) + : fA(a) + , fB(b) + , fC(c) + , fD(d) + {} + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writeUInt(fA); + buffer.writeUInt(fB); + buffer.writeUInt(fC); + buffer.writeUInt(fD); + } + + static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { + uint32_t a = buffer.readUInt(); + uint32_t b = buffer.readUInt(); + uint32_t c = buffer.readUInt(); + uint32_t d = buffer.readUInt(); + return sk_sp<IntDrawable>(new IntDrawable(a, b, c, d)); + } + + Factory getFactory() const override { return CreateProc; } + + uint32_t a() const { return fA; } + uint32_t b() const { return fB; } + uint32_t c() const { return fC; } + uint32_t d() const { return fD; } + + const char* getTypeName() const override { return "IntDrawable"; } + +protected: + SkRect onGetBounds() override { return SkRect::MakeEmpty(); } + void onDraw(SkCanvas*) override {} + +private: + uint32_t fA; + uint32_t fB; + uint32_t fC; + uint32_t fD; +}; + +class PaintDrawable : public SkDrawable { +public: + PaintDrawable(const SkPaint& paint) + : fPaint(paint) + {} + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writePaint(fPaint); + } + + static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { + SkPaint paint; + buffer.readPaint(&paint); + return sk_sp<PaintDrawable>(new PaintDrawable(paint)); + } + + Factory getFactory() const override { return CreateProc; } + + const SkPaint& paint() const { return fPaint; } + +protected: + SkRect onGetBounds() override { return SkRect::MakeEmpty(); } + void onDraw(SkCanvas*) override {} + +private: + SkPaint fPaint; +}; + +class CompoundDrawable : public SkDrawable { +public: + CompoundDrawable(uint32_t a, uint32_t b, uint32_t c, uint32_t d, const SkPaint& paint) + : fIntDrawable(new IntDrawable(a, b, c, d)) + , fPaintDrawable(new PaintDrawable(paint)) + {} + + CompoundDrawable(IntDrawable* intDrawable, PaintDrawable* paintDrawable) + : fIntDrawable(SkRef(intDrawable)) + , fPaintDrawable(SkRef(paintDrawable)) + {} + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writeFlattenable(fIntDrawable); + buffer.writeFlattenable(fPaintDrawable); + } + + static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { + SkAutoTUnref<SkFlattenable> intDrawable( + buffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + SkASSERT(intDrawable); + SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName())); + + SkAutoTUnref<SkFlattenable> paintDrawable( + buffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + SkASSERT(paintDrawable); + SkASSERT(!strcmp("PaintDrawable", paintDrawable->getTypeName())); + + return sk_sp<CompoundDrawable>(new CompoundDrawable((IntDrawable*) intDrawable.get(), + (PaintDrawable*) paintDrawable.get())); + } + + Factory getFactory() const override { return CreateProc; } + + IntDrawable* intDrawable() const { return fIntDrawable; } + PaintDrawable* paintDrawable() const { return fPaintDrawable; } + +protected: + SkRect onGetBounds() override { return SkRect::MakeEmpty(); } + void onDraw(SkCanvas*) override {} + +private: + SkAutoTUnref<IntDrawable> fIntDrawable; + SkAutoTUnref<PaintDrawable> fPaintDrawable; +}; + +class RootDrawable : public SkDrawable { +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) + : fCompoundDrawable(new CompoundDrawable(a, b, c, d, paint)) + , fIntDrawable(new IntDrawable(e, f, g, h)) + , fDrawable(SkRef(drawable)) + {} + + RootDrawable(CompoundDrawable* compoundDrawable, IntDrawable* intDrawable, + SkDrawable* drawable) + : fCompoundDrawable(SkRef(compoundDrawable)) + , fIntDrawable(SkRef(intDrawable)) + , fDrawable(SkRef(drawable)) + {} + + void flatten(SkWriteBuffer& buffer) const override { + buffer.writeFlattenable(fCompoundDrawable); + buffer.writeFlattenable(fIntDrawable); + buffer.writeFlattenable(fDrawable); + } + + static sk_sp<SkFlattenable> CreateProc(SkReadBuffer& buffer) { + SkAutoTUnref<SkFlattenable> compoundDrawable( + buffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + SkASSERT(compoundDrawable); + SkASSERT(!strcmp("CompoundDrawable", compoundDrawable->getTypeName())); + + SkAutoTUnref<SkFlattenable> intDrawable( + buffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + SkASSERT(intDrawable); + SkASSERT(!strcmp("IntDrawable", intDrawable->getTypeName())); + + SkAutoTUnref<SkFlattenable> drawable( + buffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + SkASSERT(drawable); + + return sk_sp<RootDrawable>(new RootDrawable((CompoundDrawable*) compoundDrawable.get(), + (IntDrawable*) intDrawable.get(), + (SkDrawable*) drawable.get())); + } + + Factory getFactory() const override { return CreateProc; } + + CompoundDrawable* compoundDrawable() const { return fCompoundDrawable; } + IntDrawable* intDrawable() const { return fIntDrawable; } + SkDrawable* drawable() const { return fDrawable; } + +protected: + SkRect onGetBounds() override { return SkRect::MakeEmpty(); } + void onDraw(SkCanvas*) override {} + +private: + SkAutoTUnref<CompoundDrawable> fCompoundDrawable; + SkAutoTUnref<IntDrawable> fIntDrawable; + SkAutoTUnref<SkDrawable> fDrawable; +}; + +static void register_test_drawables() { + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(IntDrawable) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(PaintDrawable) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(CompoundDrawable) + SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(RootDrawable) +} + +static void register_test_drawables_once() { + static SkOnce once; + once(register_test_drawables); +} + +DEF_TEST(FlattenDrawable, r) { + register_test_drawables_once(); + + // Create and serialize the test drawable + SkAutoTUnref<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4)); + SkPaint paint; + paint.setColor(SK_ColorBLUE); + SkAutoTUnref<RootDrawable> root(new RootDrawable(5, 6, 7, 8, paint, 9, 10, 11, 12, drawable)); + SkWriteBuffer writeBuffer; + writeBuffer.writeFlattenable(root); + + // Copy the contents of the write buffer into a read buffer + sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten()); + writeBuffer.writeToMemory(data->writable_data()); + SkReadBuffer readBuffer(data->data(), data->size()); + + // Deserialize and verify the drawable + SkAutoTUnref<SkDrawable> out((SkDrawable*) + readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + REPORTER_ASSERT(r, out); + REPORTER_ASSERT(r, !strcmp("RootDrawable", out->getTypeName())); + + RootDrawable* rootOut = (RootDrawable*) out.get(); + REPORTER_ASSERT(r, 5 == rootOut->compoundDrawable()->intDrawable()->a()); + REPORTER_ASSERT(r, 6 == rootOut->compoundDrawable()->intDrawable()->b()); + REPORTER_ASSERT(r, 7 == rootOut->compoundDrawable()->intDrawable()->c()); + REPORTER_ASSERT(r, 8 == rootOut->compoundDrawable()->intDrawable()->d()); + REPORTER_ASSERT(r, SK_ColorBLUE == + rootOut->compoundDrawable()->paintDrawable()->paint().getColor()); + REPORTER_ASSERT(r, 9 == rootOut->intDrawable()->a()); + REPORTER_ASSERT(r, 10 == rootOut->intDrawable()->b()); + REPORTER_ASSERT(r, 11 == rootOut->intDrawable()->c()); + REPORTER_ASSERT(r, 12 == rootOut->intDrawable()->d()); + + // Note that we can still recognize the generic drawable as an IntDrawable + SkDrawable* generic = rootOut->drawable(); + REPORTER_ASSERT(r, !strcmp("IntDrawable", generic->getTypeName())); + IntDrawable* integer = (IntDrawable*) generic; + REPORTER_ASSERT(r, 1 == integer->a()); + REPORTER_ASSERT(r, 2 == integer->b()); + REPORTER_ASSERT(r, 3 == integer->c()); + REPORTER_ASSERT(r, 4 == integer->d()); +} + +static sk_sp<SkFlattenable> custom_create_proc(SkReadBuffer& buffer) { + sk_sp<SkFlattenable> drawable = IntDrawable::CreateProc(buffer); + IntDrawable* intDrawable = (IntDrawable*) drawable.get(); + return sk_sp<IntDrawable>(new IntDrawable(intDrawable->a() + 1, intDrawable->b() + 1, + intDrawable->c() + 1, intDrawable->d() + 1)); +} + +DEF_TEST(FlattenCustomDrawable, r) { + // No need to register the drawables since we will be using a custom proc. + + // Create and serialize the test drawable + SkAutoTUnref<SkDrawable> drawable(new IntDrawable(1, 2, 3, 4)); + SkWriteBuffer writeBuffer; + writeBuffer.writeFlattenable(drawable); + + // Copy the contents of the write buffer into a read buffer + sk_sp<SkData> data = SkData::MakeUninitialized(writeBuffer.bytesWritten()); + writeBuffer.writeToMemory(data->writable_data()); + SkReadBuffer readBuffer(data->data(), data->size()); + + // Register a custom factory with the read buffer + readBuffer.setCustomFactory(SkString("IntDrawable"), &custom_create_proc); + + // Deserialize and verify the drawable + SkAutoTUnref<IntDrawable> out((IntDrawable*) + readBuffer.readFlattenable(SkFlattenable::kSkDrawable_Type)); + REPORTER_ASSERT(r, out); + REPORTER_ASSERT(r, 2 == out->a()); + REPORTER_ASSERT(r, 3 == out->b()); + REPORTER_ASSERT(r, 4 == out->c()); + REPORTER_ASSERT(r, 5 == out->d()); +} |