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
This commit is contained in:
parent
5d36360c47
commit
edf7fcd8b9
@ -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;
|
||||
|
@ -71,6 +71,7 @@ class SK_API SkFlattenable : public SkRefCnt {
|
||||
public:
|
||||
enum Type {
|
||||
kSkColorFilter_Type,
|
||||
kSkDrawable_Type,
|
||||
kSkDrawLooper_Type,
|
||||
kSkImageFilter_Type,
|
||||
kSkMaskFilter_Type,
|
||||
|
281
tests/FlattenDrawableTest.cpp
Normal file
281
tests/FlattenDrawableTest.cpp
Normal file
@ -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());
|
||||
}
|
Loading…
Reference in New Issue
Block a user