/* * Copyright 2006 The Android Open Source Project * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #ifndef SkFlattenable_DEFINED #define SkFlattenable_DEFINED #include "SkRefCnt.h" class SkReadBuffer; class SkWriteBuffer; #define SK_SUPPORT_LEGACY_DEEPFLATTENING /* * Flattening is straight-forward: * 1. call getFactory() so we have a function-ptr to recreate the subclass * 2. call flatten(buffer) to write out enough data for the factory to read * * Unflattening is easy for the caller: new_instance = factory(buffer) * * The complexity of supporting this is as follows. * * If your subclass wants to control unflattening, use this macro in your declaration: * SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS * This will provide a getFactory(), and require that the subclass implements CreateProc. * * For older buffers (before the DEEPFLATTENING change, the macros below declare * a thin factory DeepCreateProc. It checks the version of the buffer, and if it is pre-deep, * then it calls through to a (usually protected) constructor, passing the buffer. * If the buffer is newer, then it directly calls the "real" factory: CreateProc. */ #define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables(); #define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \ void flattenable::InitializeFlattenables() { #define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \ } #define SK_DECLARE_UNFLATTENABLE_OBJECT() \ virtual Factory getFactory() const SK_OVERRIDE { return NULL; } #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \ SkFlattenable::Registrar(#flattenable, flattenable::DeepCreateProc, \ flattenable::GetFlattenableType()); #define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \ private: \ static SkFlattenable* CreateProc(SkReadBuffer&); \ static SkFlattenable* DeepCreateProc(SkReadBuffer& buffer) { \ if (NeedsDeepUnflatten(buffer)) { \ return SkNEW_ARGS(flattenable, (buffer)); \ } \ return CreateProc(buffer); \ } \ friend class SkPrivateEffectInitializer; \ public: \ virtual Factory getFactory() const SK_OVERRIDE {return DeepCreateProc;} #else #define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \ SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \ flattenable::GetFlattenableType()); #define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable) \ private: \ static SkFlattenable* CreateProc(SkReadBuffer&); \ friend class SkPrivateEffectInitializer; \ public: \ virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; } #endif // If your subclass will *never* need to be unflattened, declare this. #define SK_DECLARE_NOT_FLATTENABLE_PROCS(flattenable) \ virtual Factory getFactory() const SK_OVERRIDE { return ReturnNullCreateProc; } /** For SkFlattenable derived objects with a valid type This macro should only be used in base class objects in core */ #define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \ static Type GetFlattenableType() { \ return k##flattenable##_Type; \ } /** \class SkFlattenable SkFlattenable is the base class for objects that need to be flattened into a data stream for either transport or as part of the key to the font cache. */ class SK_API SkFlattenable : public SkRefCnt { public: enum Type { kSkColorFilter_Type, kSkDrawLooper_Type, kSkImageFilter_Type, kSkMaskFilter_Type, kSkPathEffect_Type, kSkPixelRef_Type, kSkRasterizer_Type, kSkShader_Type, kSkUnused_Type, // used to be SkUnitMapper kSkXfermode_Type, }; SK_DECLARE_INST_COUNT(SkFlattenable) typedef SkFlattenable* (*Factory)(SkReadBuffer&); SkFlattenable() {} /** Implement this to return a factory function pointer that can be called to recreate your class given a buffer (previously written to by your override of flatten(). */ virtual Factory getFactory() const = 0; /** Returns the name of the object's class */ const char* getTypeName() const { return FactoryToName(getFactory()); } static Factory NameToFactory(const char name[]); static const char* FactoryToName(Factory); static bool NameToType(const char name[], Type* type); static void Register(const char name[], Factory, Type); class Registrar { public: Registrar(const char name[], Factory factory, Type type) { SkFlattenable::Register(name, factory, type); } }; /** * Override this if your subclass needs to record data that it will need to recreate itself * from its CreateProc (returned by getFactory()). */ virtual void flatten(SkWriteBuffer&) const {} protected: #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING static bool NeedsDeepUnflatten(const SkReadBuffer&); SkFlattenable(SkReadBuffer&) {} #endif static SkFlattenable* ReturnNullCreateProc(SkReadBuffer&) { return NULL; } private: static void InitializeFlattenablesIfNeeded(); friend class SkGraphics; typedef SkRefCnt INHERITED; }; #endif