SkFlattenable.h revision a2ca41e3afdd8fad5e0e924dec029f33918e0a67
1
2/*
3 * Copyright 2006 The Android Open Source Project
4 *
5 * Use of this source code is governed by a BSD-style license that can be
6 * found in the LICENSE file.
7 */
8
9
10#ifndef SkFlattenable_DEFINED
11#define SkFlattenable_DEFINED
12
13#include "SkRefCnt.h"
14#include "SkBitmap.h"
15#include "SkReader32.h"
16#include "SkTDArray.h"
17#include "SkWriter32.h"
18
19class SkFlattenableReadBuffer;
20class SkFlattenableWriteBuffer;
21class SkString;
22
23#if SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
24
25#define SK_DEFINE_FLATTENABLE_REGISTRAR(flattenable) \
26    static SkFlattenable::Registrar g##flattenable##Reg(#flattenable, \
27                                                       flattenable::CreateProc);
28#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
29    static SkFlattenable::Registrar g##flattenable##Reg(#flattenable, \
30                                                       flattenable::CreateProc);
31
32#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP()
33#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable)
34#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END
35
36#else
37
38#define SK_DEFINE_FLATTENABLE_REGISTRAR(flattenable)
39#define SK_DEFINE_FLATTENABLE_REGISTRAR_ENTRY(flattenable) \
40        SkFlattenable::Registrar(#flattenable, flattenable::CreateProc);
41
42#define SK_DECLARE_FLATTENABLE_REGISTRAR_GROUP() static void InitializeFlattenables();
43
44#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_START(flattenable) \
45    void flattenable::InitializeFlattenables() {
46
47#define SK_DEFINE_FLATTENABLE_REGISTRAR_GROUP_END \
48    }
49
50#endif
51
52/** \class SkFlattenable
53
54 SkFlattenable is the base class for objects that need to be flattened
55 into a data stream for either transport or as part of the key to the
56 font cache.
57 */
58class SK_API SkFlattenable : public SkRefCnt {
59public:
60    typedef SkFlattenable* (*Factory)(SkFlattenableReadBuffer&);
61
62    SkFlattenable() {}
63
64    /** Implement this to return a factory function pointer that can be called
65     to recreate your class given a buffer (previously written to by your
66     override of flatten().
67     */
68    virtual Factory getFactory() = 0;
69    /** Override this to write data specific to your subclass into the buffer,
70     being sure to call your super-class' version first. This data will later
71     be passed to your Factory function, returned by getFactory().
72     */
73    virtual void flatten(SkFlattenableWriteBuffer&);
74
75    static Factory NameToFactory(const char name[]);
76    static const char* FactoryToName(Factory);
77    static void Register(const char name[], Factory);
78
79    class Registrar {
80    public:
81        Registrar(const char name[], Factory factory) {
82            SkFlattenable::Register(name, factory);
83        }
84    };
85
86protected:
87    SkFlattenable(SkFlattenableReadBuffer&) {}
88
89private:
90#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS
91    static void InitializeFlattenables();
92#endif
93
94    friend class SkGraphics;
95};
96
97// helpers for matrix and region
98
99class SkMatrix;
100extern void SkReadMatrix(SkReader32*, SkMatrix*);
101extern void SkWriteMatrix(SkWriter32*, const SkMatrix&);
102
103class SkRegion;
104extern void SkReadRegion(SkReader32*, SkRegion*);
105extern void SkWriteRegion(SkWriter32*, const SkRegion&);
106
107///////////////////////////////////////////////////////////////////////////////
108///////////////////////////////////////////////////////////////////////////////
109
110class SkTypeface;
111
112class SkFlattenableReadBuffer : public SkReader32 {
113public:
114    SkFlattenableReadBuffer();
115    explicit SkFlattenableReadBuffer(const void* data);
116    SkFlattenableReadBuffer(const void* data, size_t size);
117
118    void setRefCntArray(SkRefCnt* array[], int count) {
119        fRCArray = array;
120        fRCCount = count;
121    }
122
123    void setTypefaceArray(SkTypeface* array[], int count) {
124        fTFArray = array;
125        fTFCount = count;
126    }
127
128    /**
129     *  Call this with a pre-loaded array of Factories, in the same order as
130     *  were created/written by the writer. SkPicture uses this.
131     */
132    void setFactoryPlayback(SkFlattenable::Factory array[], int count) {
133        fFactoryTDArray = NULL;
134        fFactoryArray = array;
135        fFactoryCount = count;
136    }
137
138    /**
139     *  Call this with an initially empty array, so the reader can cache each
140     *  factory it sees by name. Used by the pipe code in conjunction with
141     *  the writer's kInlineFactoryNames_Flag.
142     */
143    void setFactoryArray(SkTDArray<SkFlattenable::Factory>* array) {
144        fFactoryTDArray = array;
145        fFactoryArray = NULL;
146        fFactoryCount = 0;
147    }
148
149    SkTypeface* readTypeface();
150    SkRefCnt* readRefCnt();
151    void* readFunctionPtr();
152    SkFlattenable* readFlattenable();
153
154private:
155    SkRefCnt** fRCArray;
156    int        fRCCount;
157
158    SkTypeface** fTFArray;
159    int        fTFCount;
160
161    SkTDArray<SkFlattenable::Factory>* fFactoryTDArray;
162    SkFlattenable::Factory* fFactoryArray;
163    int                     fFactoryCount;
164
165    typedef SkReader32 INHERITED;
166};
167
168///////////////////////////////////////////////////////////////////////////////
169
170#include "SkPtrRecorder.h"
171
172/**
173 *  Subclass of SkTPtrSet specialed to call ref() and unref() when the
174 *  base class's incPtr() and decPtr() are called. This makes it a valid owner
175 *  of each ptr, which is released when the set is reset or destroyed.
176 */
177class SkRefCntSet : public SkTPtrSet<SkRefCnt*> {
178public:
179    virtual ~SkRefCntSet();
180
181protected:
182    // overrides
183    virtual void incPtr(void*);
184    virtual void decPtr(void*);
185};
186
187class SkFactorySet : public SkTPtrSet<SkFlattenable::Factory> {};
188
189class SkFlattenableWriteBuffer : public SkWriter32 {
190public:
191    SkFlattenableWriteBuffer(size_t minSize);
192    virtual ~SkFlattenableWriteBuffer();
193
194    void writeTypeface(SkTypeface*);
195    void writeRefCnt(SkRefCnt*);
196    void writeFunctionPtr(void*);
197    void writeFlattenable(SkFlattenable* flattenable);
198
199    SkRefCntSet* getTypefaceRecorder() const { return fTFSet; }
200    SkRefCntSet* setTypefaceRecorder(SkRefCntSet*);
201
202    SkRefCntSet* getRefCntRecorder() const { return fRCSet; }
203    SkRefCntSet* setRefCntRecorder(SkRefCntSet*);
204
205    SkFactorySet* getFactoryRecorder() const { return fFactorySet; }
206    SkFactorySet* setFactoryRecorder(SkFactorySet*);
207
208    enum Flags {
209        kCrossProcess_Flag       = 0x01,
210        /**
211         *  Instructs the writer to inline Factory names as there are seen the
212         *  first time (after that we store an index). The pipe code uses this.
213         */
214        kInlineFactoryNames_Flag = 0x02,
215    };
216    Flags getFlags() const { return (Flags)fFlags; }
217    void setFlags(Flags flags) { fFlags = flags; }
218
219    bool isCrossProcess() const {
220        return SkToBool(fFlags & kCrossProcess_Flag);
221    }
222    bool inlineFactoryNames() const {
223        return SkToBool(fFlags & kInlineFactoryNames_Flag);
224    }
225
226    bool persistBitmapPixels() const {
227        return (fFlags & kCrossProcess_Flag) != 0;
228    }
229
230    bool persistTypeface() const { return (fFlags & kCrossProcess_Flag) != 0; }
231
232private:
233    uint32_t        fFlags;
234    SkRefCntSet*    fTFSet;
235    SkRefCntSet*    fRCSet;
236    SkFactorySet*   fFactorySet;
237
238    typedef SkWriter32 INHERITED;
239};
240
241#endif
242
243