| Index: include/core/SkFlattenable.h
|
| diff --git a/include/core/SkFlattenable.h b/include/core/SkFlattenable.h
|
| index 58e69fd416cb049b56d881942f6f77ebb676e93d..ec0242eb403cd88e187a5dfaac3e416ec5dfbe5e 100644
|
| --- a/include/core/SkFlattenable.h
|
| +++ b/include/core/SkFlattenable.h
|
| @@ -16,7 +16,7 @@ class SkFlattenableReadBuffer;
|
| class SkFlattenableWriteBuffer;
|
|
|
| #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
|
| - SkFlattenable::Registrar(#flattenable, flattenable::CreateProc);
|
| + SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, flattenable::IsA);
|
|
|
| #define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
|
|
|
| @@ -29,11 +29,34 @@ class SkFlattenableWriteBuffer;
|
| #define SK_DECLARE_UNFLATTENABLE_OBJECT() \
|
| virtual Factory getFactory() SK_OVERRIDE { return NULL; }
|
|
|
| -#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
|
| +/** For SkFlattenable derived objects with a valid type
|
| + This macros would typically be used by virtual classes, which need a type, but can't
|
| + be constructed or serialized directly without going through a derived class
|
| + */
|
| +#define SK_DEFINE_FLATTENABLE_TYPE_CHECKING_PROCS(flattenable) \
|
| + static const char* GetTypeName() { \
|
| + return #flattenable; \
|
| + } \
|
| + static bool IsA(const char* name) { \
|
| + return (strcmp(flattenable::GetTypeName(), name) == 0) || INHERITED::IsA(name); \
|
| + } \
|
| + virtual const char* getTypeName() SK_OVERRIDE { \
|
| + return flattenable::GetTypeName(); \
|
| + }
|
| +
|
| +/** For SkFlattenable derived classes defined within the skia library
|
| + */
|
| +#define SK_DEFINE_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
|
| virtual Factory getFactory() SK_OVERRIDE { return CreateProc; } \
|
| static SkFlattenable* CreateProc(SkFlattenableReadBuffer& buffer) { \
|
| return SkNEW_ARGS(flattenable, (buffer)); \
|
| - }
|
| + } \
|
| + SK_DEFINE_FLATTENABLE_TYPE_CHECKING_PROCS(flattenable)
|
| +
|
| +/** Deprecated, remove once noone is using it anymore
|
| + */
|
| +#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \
|
| + SK_DEFINE_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)
|
|
|
| /** \class SkFlattenable
|
|
|
| @@ -43,9 +66,11 @@ class SkFlattenableWriteBuffer;
|
| */
|
| class SK_API SkFlattenable : public SkRefCnt {
|
| public:
|
| +
|
| SK_DECLARE_INST_COUNT(SkFlattenable)
|
|
|
| typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
|
| + typedef bool (*TypeCheck)(const char*);
|
|
|
| SkFlattenable() {}
|
|
|
| @@ -57,12 +82,44 @@ public:
|
|
|
| static Factory NameToFactory(const char name[]);
|
| static const char* FactoryToName(Factory);
|
| - static void Register(const char name[], Factory);
|
| +
|
| + static void Register(const char name[], Factory, TypeCheck);
|
| +
|
| + /** Returns the class id
|
| + GetTypeName() methods on classes descending from SkFlattenable will return
|
| + the name associated with that class, which is a stringified version of
|
| + the class' name. Typically, SK_DEFINE_FLATTENABLE_TYPE_CHECKING_PROCS()
|
| + will define GetTypeName(), getFlattenableType() and IsA() in the derived class.
|
| + * Note that SK_DEFINE_FLATTENABLE_TYPE_CHECKING_PROCS() is included in
|
| + SK_DEFINE_FLATTENABLE_DESERIALIZATION_PROCS(), so most classes will have
|
| + these declared by default.
|
| + */
|
| + static const char* GetTypeName() { return "SkFlattenable"; }
|
| +
|
| + /** Returns the name of the object's class
|
| + */
|
| + virtual const char* getTypeName() = 0;
|
| +
|
| + /** Returns whether this class is itself or inherits from a class with this type name.
|
| + * (SkFlattenable is the root of this type checking system.)
|
| + */
|
| + static bool IsA(const char* name) {
|
| + return strcmp(GetTypeName(), name) == 0;
|
| + }
|
| +
|
| + /** Checks if typeA is a typeB
|
| + * For example, if typeA is "SkImageFilter" and typeB is "SkFlattenable", this would return true
|
| + * Inversely, if typeA is "SkFlattenable" and typeB is "SkImageFilter", this would return false
|
| + */
|
| + static bool TypeIsA(const char* nameA, const char* nameB) {
|
| + TypeCheck typeCheck = NameToTypeCheck(nameA);
|
| + return typeCheck ? (*typeCheck)(nameB) : false;
|
| + }
|
|
|
| class Registrar {
|
| public:
|
| - Registrar(const char name[], Factory factory) {
|
| - SkFlattenable::Register(name, factory);
|
| + Registrar(const char name[], Factory factory, TypeCheck typeCheck) {
|
| + SkFlattenable::Register(name, factory, typeCheck);
|
| }
|
| };
|
|
|
| @@ -75,7 +132,8 @@ protected:
|
| virtual void flatten(SkFlattenableWriteBuffer&) const;
|
|
|
| private:
|
| - static void InitializeFlattenables();
|
| + static void InitializeFlattenablesIfNeeded();
|
| + static TypeCheck NameToTypeCheck(const char name[]);
|
|
|
| friend class SkGraphics;
|
| friend class SkFlattenableWriteBuffer;
|
|
|