1/*
2 * Copyright 2006 The Android Open Source Project
3 *
4 * Use of this source code is governed by a BSD-style license that can be
5 * found in the LICENSE file.
6 */
7
8#ifndef SkFlattenable_DEFINED
9#define SkFlattenable_DEFINED
10
11#include "SkRefCnt.h"
12
13class SkReadBuffer;
14class SkWriteBuffer;
15
16#define SK_SUPPORT_LEGACY_DEEPFLATTENING
17
18/*
19 *  Flattening is straight-forward:
20 *      1. call getFactory() so we have a function-ptr to recreate the subclass
21 *      2. call flatten(buffer) to write out enough data for the factory to read
22 *
23 *  Unflattening is easy for the caller: new_instance = factory(buffer)
24 *
25 *  The complexity of supporting this is as follows.
26 *
27 *  If your subclass wants to control unflattening, use this macro in your declaration:
28 *      SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS
29 *  This will provide a getFactory(), and require that the subclass implements CreateProc.
30 *
31 *  For older buffers (before the DEEPFLATTENING change, the macros below declare
32 *  a thin factory DeepCreateProc. It checks the version of the buffer, and if it is pre-deep,
33 *  then it calls through to a (usually protected) constructor, passing the buffer.
34 *  If the buffer is newer, then it directly calls the "real" factory: CreateProc.
35 */
36
37#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
38
39#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
40    void flattenable::InitializeFlattenables() {
41
42#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
43    }
44
45#define SK_DECLARE_UNFLATTENABLE_OBJECT() \
46    virtual Factory getFactory() const SK_OVERRIDE { return NULL; }
47
48#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
49#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
50    SkFlattenable::Registrar(#flattenable, flattenable::DeepCreateProc, \
51                             flattenable::GetFlattenableType());
52
53#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
54    private:                                                                \
55    static SkFlattenable* CreateProc(SkReadBuffer&);                        \
56    static SkFlattenable* DeepCreateProc(SkReadBuffer& buffer) {            \
57        if (NeedsDeepUnflatten(buffer)) {                                   \
58            return SkNEW_ARGS(flattenable, (buffer));                       \
59        }                                                                   \
60        return CreateProc(buffer);                                          \
61    }                                                                       \
62    friend class SkPrivateEffectInitializer;                                \
63    public:                                                                 \
64    virtual Factory getFactory() const SK_OVERRIDE {return DeepCreateProc;}
65#else
66#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
67    SkFlattenable::Registrar(#flattenable, flattenable::CreateProc, \
68                             flattenable::GetFlattenableType());
69
70#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
71    private:                                                                \
72    static SkFlattenable* CreateProc(SkReadBuffer&);                        \
73    friend class SkPrivateEffectInitializer;                                \
74    public:                                                                 \
75    virtual Factory getFactory() const SK_OVERRIDE { return CreateProc; }
76#endif
77
78// If your subclass will *never* need to be unflattened, declare this.
79#define SK_DECLARE_NOT_FLATTENABLE_PROCS(flattenable)   \
80    virtual Factory getFactory() const SK_OVERRIDE { return ReturnNullCreateProc; }
81
82/** For SkFlattenable derived objects with a valid type
83    This macro should only be used in base class objects in core
84  */
85#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \
86    static Type GetFlattenableType() { \
87        return k##flattenable##_Type; \
88    }
89
90/** \class SkFlattenable
91
92 SkFlattenable is the base class for objects that need to be flattened
93 into a data stream for either transport or as part of the key to the
94 font cache.
95 */
96class SK_API SkFlattenable : public SkRefCnt {
97public:
98    enum Type {
99        kSkColorFilter_Type,
100        kSkDrawLooper_Type,
101        kSkImageFilter_Type,
102        kSkMaskFilter_Type,
103        kSkPathEffect_Type,
104        kSkPixelRef_Type,
105        kSkRasterizer_Type,
106        kSkShader_Type,
107        kSkUnused_Type,     // used to be SkUnitMapper
108        kSkXfermode_Type,
109    };
110
111    SK_DECLARE_INST_COUNT(SkFlattenable)
112
113    typedef SkFlattenable* (*Factory)(SkReadBuffer&);
114
115    SkFlattenable() {}
116
117    /** Implement this to return a factory function pointer that can be called
118     to recreate your class given a buffer (previously written to by your
119     override of flatten().
120     */
121    virtual Factory getFactory() const = 0;
122
123    /** Returns the name of the object's class
124      */
125    const char* getTypeName() const { return FactoryToName(getFactory()); }
126
127    static Factory NameToFactory(const char name[]);
128    static const char* FactoryToName(Factory);
129    static bool NameToType(const char name[], Type* type);
130
131    static void Register(const char name[], Factory, Type);
132
133    class Registrar {
134    public:
135        Registrar(const char name[], Factory factory, Type type) {
136            SkFlattenable::Register(name, factory, type);
137        }
138    };
139
140    /**
141     *  Override this if your subclass needs to record data that it will need to recreate itself
142     *  from its CreateProc (returned by getFactory()).
143     */
144    virtual void flatten(SkWriteBuffer&) const {}
145
146protected:
147#ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING
148    static bool NeedsDeepUnflatten(const SkReadBuffer&);
149    SkFlattenable(SkReadBuffer&) {}
150#endif
151
152    static SkFlattenable* ReturnNullCreateProc(SkReadBuffer&) {
153        return NULL;
154    }
155
156private:
157    static void InitializeFlattenablesIfNeeded();
158
159    friend class SkGraphics;
160
161    typedef SkRefCnt INHERITED;
162};
163
164#endif
165