aboutsummaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorGravatar msarett <msarett@google.com>2016-04-25 06:40:26 -0700
committerGravatar Commit bot <commit-bot@chromium.org>2016-04-25 06:40:26 -0700
commitedf7fcd8b9e339800edb61ae422f8b6c1b77c3e8 (patch)
tree93be6103d394984eab3984a9ab5f32ff08ea69d8
parent5d36360c47ed48c93e6928cc5de1a5ebd65b6eea (diff)
Make SkDrawable an SkFlattenable
-rw-r--r--include/core/SkDrawable.h8
-rw-r--r--include/core/SkFlattenable.h1
-rw-r--r--tests/FlattenDrawableTest.cpp281
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());
+}