aboutsummaryrefslogtreecommitdiffhomepage
path: root/include/core/SkFlattenable.h
blob: 679f640d3c4012a7868486f9a02bdef4b3325d5f (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
/*
 * 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