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 SkData;
14class SkReadBuffer;
15class SkWriteBuffer;
16
17struct SkSerialProcs;
18struct SkDeserialProcs;
19
20/*
21 *  Flattening is straight-forward:
22 *      1. call getFactory() so we have a function-ptr to recreate the subclass
23 *      2. call flatten(buffer) to write out enough data for the factory to read
24 *
25 *  Unflattening is easy for the caller: new_instance = factory(buffer)
26 *
27 *  The complexity of supporting this is as follows.
28 *
29 *  If your subclass wants to control unflattening, use this macro in your declaration:
30 *      SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS
31 *  This will provide a getFactory(), and require that the subclass implements CreateProc.
32 *
33 *  For older buffers (before the DEEPFLATTENING change, the macros below declare
34 *  a thin factory DeepCreateProc. It checks the version of the buffer, and if it is pre-deep,
35 *  then it calls through to a (usually protected) constructor, passing the buffer.
36 *  If the buffer is newer, then it directly calls the "real" factory: CreateProc.
37 */
38
39#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
40
41#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
42    void flattenable::InitializeFlattenables() {
43
44#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
45    }
46
47#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
48    SkFlattenable::Register(#flattenable, flattenable::CreateProc, \
49                            flattenable::GetFlattenableType());
50
51#define SK_DECLARE_PUBLIC_FLATTENABLE_DESERIALIZATION_PROCS(flattenable)    \
52    private:                                                                \
53    static sk_sp<SkFlattenable> CreateProc(SkReadBuffer&);                        \
54    friend class SkFlattenable::PrivateInitializer;                         \
55    public:                                                                 \
56    Factory getFactory() const override { return CreateProc; }
57
58/** For SkFlattenable derived objects with a valid type
59    This macro should only be used in base class objects in core
60  */
61#define SK_DEFINE_FLATTENABLE_TYPE(flattenable) \
62    static Type GetFlattenableType() {          \
63        return k##flattenable##_Type;           \
64    }                                           \
65    Type getFlattenableType() const override {  \
66        return k##flattenable##_Type;           \
67    }                                           \
68    static sk_sp<flattenable> Deserialize(const void* data, size_t size,                \
69                                          const SkDeserialProcs* procs = nullptr) {     \
70        return sk_sp<flattenable>(static_cast<flattenable*>(                            \
71                                  SkFlattenable::Deserialize(                           \
72                                  k##flattenable##_Type, data, size, procs).release()));\
73    }
74
75/** \class SkFlattenable
76
77 SkFlattenable is the base class for objects that need to be flattened
78 into a data stream for either transport or as part of the key to the
79 font cache.
80 */
81class SK_API SkFlattenable : public SkRefCnt {
82public:
83    enum Type {
84        kSkColorFilter_Type,
85        kSkDrawable_Type,
86        kSkDrawLooper_Type,
87        kSkImageFilter_Type,
88        kSkMaskFilter_Type,
89        kSkPathEffect_Type,
90        kSkPixelRef_Type,
91        kSkUnused_Type4,    // used to be SkRasterizer
92        kSkShaderBase_Type,
93        kSkUnused_Type,     // used to be SkUnitMapper
94        kSkUnused_Type2,
95        kSkUnused_Type3,    // used to be SkNormalSource
96    };
97
98    typedef sk_sp<SkFlattenable> (*Factory)(SkReadBuffer&);
99
100    SkFlattenable() {}
101
102    /** Implement this to return a factory function pointer that can be called
103     to recreate your class given a buffer (previously written to by your
104     override of flatten().
105     */
106    virtual Factory getFactory() const = 0;
107
108    /**
109     *  Returns the name of the object's class.
110     *
111     *  Subclasses should override this function if they intend to provide
112     *  support for flattening without using the global registry.
113     *
114     *  If the flattenable is registered, there is no need to override.
115     */
116    virtual const char* getTypeName() const { return FactoryToName(getFactory()); }
117
118    static Factory NameToFactory(const char name[]);
119    static const char* FactoryToName(Factory);
120    static bool NameToType(const char name[], Type* type);
121
122    static void Register(const char name[], Factory, Type);
123
124    /**
125     *  Override this if your subclass needs to record data that it will need to recreate itself
126     *  from its CreateProc (returned by getFactory()).
127     *
128     *  DEPRECATED public : will move to protected ... use serialize() instead
129     */
130    virtual void flatten(SkWriteBuffer&) const {}
131
132    virtual Type getFlattenableType() const = 0;
133
134    //
135    // public ways to serialize / deserialize
136    //
137    sk_sp<SkData> serialize(const SkSerialProcs* = nullptr) const;
138    static sk_sp<SkFlattenable> Deserialize(Type, const void* data, size_t length,
139                                            const SkDeserialProcs* procs = nullptr);
140
141protected:
142    class PrivateInitializer {
143    public:
144        static void InitCore();
145        static void InitEffects();
146    };
147
148private:
149    static void InitializeFlattenablesIfNeeded();
150    static void Finalize();
151
152    friend class SkGraphics;
153
154    typedef SkRefCnt INHERITED;
155};
156
157#endif
158