SkFlattenable.cpp revision 82065d667f64e232bcde2ad849756a6096fcbe6f
1#include "SkFlattenable.h"
2#include "SkTypeface.h"
3
4void SkFlattenable::flatten(SkFlattenableWriteBuffer&)
5{
6    /*  we don't write anything at the moment, but this allows our subclasses
7        to not know that, since we want them to always call INHERITED::flatten()
8        in their code.
9    */
10}
11
12///////////////////////////////////////////////////////////////////////////////
13///////////////////////////////////////////////////////////////////////////////
14
15SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
16    fRCArray = NULL;
17    fRCCount = 0;
18
19    fTFArray = NULL;
20    fTFCount = 0;
21
22    fFactoryArray = NULL;
23    fFactoryCount = 0;
24}
25
26SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
27        INHERITED(data, 1024 * 1024) {
28    fRCArray = NULL;
29    fRCCount = 0;
30
31    fTFArray = NULL;
32    fTFCount = 0;
33
34    fFactoryArray = NULL;
35    fFactoryCount = 0;
36}
37
38SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
39        : INHERITED(data, size) {
40    fRCArray = NULL;
41    fRCCount = 0;
42
43    fTFArray = NULL;
44    fTFCount = 0;
45
46    fFactoryArray = NULL;
47    fFactoryCount = 0;
48}
49
50SkTypeface* SkFlattenableReadBuffer::readTypeface() {
51    uint32_t index = this->readU32();
52    if (0 == index || index > (unsigned)fTFCount) {
53        if (index) {
54            SkDebugf("====== typeface index %d\n", index);
55        }
56        return NULL;
57    } else {
58        SkASSERT(fTFArray);
59        return fTFArray[index - 1];
60    }
61}
62
63SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
64    uint32_t index = this->readU32();
65    if (0 == index || index > (unsigned)fRCCount) {
66        return NULL;
67    } else {
68        SkASSERT(fRCArray);
69        return fRCArray[index - 1];
70    }
71}
72
73SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
74    SkFlattenable::Factory factory = NULL;
75
76    if (fFactoryCount > 0) {
77        uint32_t index = this->readU32();
78        if (index > 0) {
79            index -= 1;
80            SkASSERT(index < (unsigned)fFactoryCount);
81            factory = fFactoryArray[index];
82            // if we recorded an index, but failed to get a factory, we need
83            // to skip the flattened data in the buffer
84            if (NULL == factory) {
85                uint32_t size = this->readU32();
86                this->skip(size);
87                // fall through and return NULL for the object
88            }
89        }
90    } else {
91        factory = (SkFlattenable::Factory)readFunctionPtr();
92    }
93
94    SkFlattenable* obj = NULL;
95    if (factory) {
96        uint32_t sizeRecorded = this->readU32();
97        uint32_t offset = this->offset();
98        obj = (*factory)(*this);
99        // check that we read the amount we expected
100        uint32_t sizeRead = this->offset() - offset;
101        if (sizeRecorded != sizeRead) {
102            // we could try to fix up the offset...
103            sk_throw();
104        }
105    }
106    return obj;
107}
108
109void* SkFlattenableReadBuffer::readFunctionPtr() {
110    void* proc;
111    this->read(&proc, sizeof(proc));
112    return proc;
113}
114
115///////////////////////////////////////////////////////////////////////////////
116
117SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
118        INHERITED(minSize) {
119    fFlags = (Flags)0;
120    fRCRecorder = NULL;
121    fTFRecorder = NULL;
122    fFactoryRecorder = NULL;
123}
124
125SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
126    SkSafeUnref(fRCRecorder);
127    SkSafeUnref(fTFRecorder);
128    SkSafeUnref(fFactoryRecorder);
129}
130
131SkRefCntRecorder* SkFlattenableWriteBuffer::setRefCntRecorder(
132                                                    SkRefCntRecorder* rec) {
133    SkRefCnt_SafeAssign(fRCRecorder, rec);
134    return rec;
135}
136
137SkRefCntRecorder* SkFlattenableWriteBuffer::setTypefaceRecorder(
138                                                    SkRefCntRecorder* rec) {
139    SkRefCnt_SafeAssign(fTFRecorder, rec);
140    return rec;
141}
142
143SkFactoryRecorder* SkFlattenableWriteBuffer::setFactoryRecorder(
144                                                    SkFactoryRecorder* rec) {
145    SkRefCnt_SafeAssign(fFactoryRecorder, rec);
146    return rec;
147}
148
149void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
150    if (NULL == obj || NULL == fTFRecorder) {
151        this->write32(0);
152    } else {
153        this->write32(fTFRecorder->record(obj));
154    }
155}
156
157void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
158    if (NULL == obj || NULL == fRCRecorder) {
159        this->write32(0);
160    } else {
161        this->write32(fRCRecorder->record(obj));
162    }
163}
164
165void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
166    SkFlattenable::Factory factory = NULL;
167    if (flattenable) {
168        factory = flattenable->getFactory();
169    }
170
171    if (fFactoryRecorder) {
172        this->write32(fFactoryRecorder->record(factory));
173    } else {
174        this->writeFunctionPtr((void*)factory);
175    }
176
177    if (factory) {
178        // make room for the size of the flatttened object
179        (void)this->reserve(sizeof(uint32_t));
180        // record the current size, so we can subtract after the object writes.
181        uint32_t offset = this->size();
182        // now flatten the object
183        flattenable->flatten(*this);
184        uint32_t objSize = this->size() - offset;
185        // record the obj's size
186        *this->peek32(offset - sizeof(uint32_t)) = objSize;
187    }
188}
189
190void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
191    *(void**)this->reserve(sizeof(void*)) = proc;
192}
193
194///////////////////////////////////////////////////////////////////////////////
195
196SkRefCntRecorder::~SkRefCntRecorder() {
197    // call this now, while our decPtr() is sill in scope
198    this->reset();
199}
200
201void SkRefCntRecorder::incPtr(void* ptr) {
202    ((SkRefCnt*)ptr)->ref();
203}
204
205void SkRefCntRecorder::decPtr(void* ptr) {
206    ((SkRefCnt*)ptr)->unref();
207}
208
209///////////////////////////////////////////////////////////////////////////////
210///////////////////////////////////////////////////////////////////////////////
211///////////////////////////////////////////////////////////////////////////////
212
213#define MAX_PAIR_COUNT  64
214
215struct Pair {
216    const char*             fName;
217    SkFlattenable::Factory  fFactory;
218};
219
220static int gCount;
221static Pair gPairs[MAX_PAIR_COUNT];
222
223void SkFlattenable::Register(const char name[], Factory factory) {
224    SkASSERT(name);
225    SkASSERT(factory);
226
227    static bool gOnce;
228    if (!gOnce) {
229        gCount = 0;
230        gOnce = true;
231    }
232
233    SkASSERT(gCount < MAX_PAIR_COUNT);
234
235    gPairs[gCount].fName = name;
236    gPairs[gCount].fFactory = factory;
237    gCount += 1;
238}
239
240SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
241    const Pair* pairs = gPairs;
242    for (int i = gCount - 1; i >= 0; --i) {
243        if (strcmp(pairs[i].fName, name) == 0) {
244            return pairs[i].fFactory;
245        }
246    }
247    return NULL;
248}
249
250const char* SkFlattenable::FactoryToName(Factory fact) {
251    const Pair* pairs = gPairs;
252    for (int i = gCount - 1; i >= 0; --i) {
253        if (pairs[i].fFactory == fact) {
254            return pairs[i].fName;
255        }
256    }
257    return NULL;
258}
259
260bool SkFlattenable::toDumpString(SkString* str) const {
261    return false;
262}
263
264