SkFlattenable.cpp revision 6bac947cd5bc460dd9166ada6310d678fd2e39f8
1#include "SkFlattenable.h"
2#include "SkTypeface.h"
3
4#include "SkMatrix.h"
5#include "SkRegion.h"
6
7void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
8    size_t size = matrix->unflatten(reader->peek());
9    SkASSERT(SkAlign4(size) == size);
10    (void)reader->skip(size);
11}
12
13void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
14    size_t size = matrix.flatten(NULL);
15    SkASSERT(SkAlign4(size) == size);
16    matrix.flatten(writer->reserve(size));
17}
18
19void SkReadRegion(SkReader32* reader, SkRegion* rgn) {
20    size_t size = rgn->unflatten(reader->peek());
21    SkASSERT(SkAlign4(size) == size);
22    (void)reader->skip(size);
23}
24
25void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
26    size_t size = rgn.flatten(NULL);
27    SkASSERT(SkAlign4(size) == size);
28    rgn.flatten(writer->reserve(size));
29}
30
31///////////////////////////////////////////////////////////////////////////////
32
33void SkFlattenable::flatten(SkFlattenableWriteBuffer&)
34{
35    /*  we don't write anything at the moment, but this allows our subclasses
36        to not know that, since we want them to always call INHERITED::flatten()
37        in their code.
38    */
39}
40
41///////////////////////////////////////////////////////////////////////////////
42///////////////////////////////////////////////////////////////////////////////
43
44SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
45    fRCArray = NULL;
46    fRCCount = 0;
47
48    fTFArray = NULL;
49    fTFCount = 0;
50
51    fFactoryTDArray = NULL;
52    fFactoryArray = NULL;
53    fFactoryCount = 0;
54}
55
56SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
57        INHERITED(data, 1024 * 1024) {
58    fRCArray = NULL;
59    fRCCount = 0;
60
61    fTFArray = NULL;
62    fTFCount = 0;
63
64    fFactoryTDArray = NULL;
65    fFactoryArray = NULL;
66    fFactoryCount = 0;
67}
68
69SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
70        : INHERITED(data, size) {
71    fRCArray = NULL;
72    fRCCount = 0;
73
74    fTFArray = NULL;
75    fTFCount = 0;
76
77    fFactoryTDArray = NULL;
78    fFactoryArray = NULL;
79    fFactoryCount = 0;
80}
81
82SkTypeface* SkFlattenableReadBuffer::readTypeface() {
83    uint32_t index = this->readU32();
84    if (0 == index || index > (unsigned)fTFCount) {
85        if (index) {
86            SkDebugf("====== typeface index %d\n", index);
87        }
88        return NULL;
89    } else {
90        SkASSERT(fTFArray);
91        return fTFArray[index - 1];
92    }
93}
94
95SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
96    uint32_t index = this->readU32();
97    if (0 == index || index > (unsigned)fRCCount) {
98        return NULL;
99    } else {
100        SkASSERT(fRCArray);
101        return fRCArray[index - 1];
102    }
103}
104
105SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
106    SkFlattenable::Factory factory = NULL;
107
108    if (fFactoryCount > 0) {
109        int32_t index = this->readU32();
110        if (0 == index) {
111            return NULL; // writer failed to give us the flattenable
112        }
113        index = -index; // we stored the negative of the index
114        index -= 1;     // we stored the index-base-1
115        SkASSERT(index < (unsigned)fFactoryCount);
116        factory = fFactoryArray[index];
117    } else if (fFactoryTDArray) {
118        const int32_t* peek = (const int32_t*)this->peek();
119        if (*peek <= 0) {
120            int32_t index = this->readU32();
121            if (0 == index) {
122                return NULL; // writer failed to give us the flattenable
123            }
124            index = -index; // we stored the negative of the index
125            index -= 1;     // we stored the index-base-1
126            factory = (*fFactoryTDArray)[index];
127        } else {
128            const char* name = this->readString();
129            factory = SkFlattenable::NameToFactory(name);
130            if (factory) {
131                SkASSERT(fFactoryTDArray->find(factory) < 0);
132                *fFactoryTDArray->append() = factory;
133            } else {
134//                SkDebugf("can't find factory for [%s]\n", name);
135            }
136            // if we didn't find a factory, that's our failure, not the writer's,
137            // so we fall through, so we can skip the sizeRecorded data.
138        }
139    } else {
140        factory = (SkFlattenable::Factory)readFunctionPtr();
141        if (NULL == factory) {
142            return NULL; // writer failed to give us the flattenable
143        }
144    }
145
146    // if we get here, factory may still be null, but if that is the case, the
147    // failure was ours, not the writer.
148    SkFlattenable* obj = NULL;
149    uint32_t sizeRecorded = this->readU32();
150    if (factory) {
151        uint32_t offset = this->offset();
152        obj = (*factory)(*this);
153        // check that we read the amount we expected
154        uint32_t sizeRead = this->offset() - offset;
155        if (sizeRecorded != sizeRead) {
156            // we could try to fix up the offset...
157            sk_throw();
158        }
159    } else {
160        // we must skip the remaining data
161        this->skip(sizeRecorded);
162    }
163    return obj;
164}
165
166void* SkFlattenableReadBuffer::readFunctionPtr() {
167    void* proc;
168    this->read(&proc, sizeof(proc));
169    return proc;
170}
171
172///////////////////////////////////////////////////////////////////////////////
173
174SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
175        INHERITED(minSize) {
176    fFlags = (Flags)0;
177    fRCSet = NULL;
178    fTFSet = NULL;
179    fFactorySet = NULL;
180}
181
182SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
183    SkSafeUnref(fRCSet);
184    SkSafeUnref(fTFSet);
185    SkSafeUnref(fFactorySet);
186}
187
188SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
189    SkRefCnt_SafeAssign(fRCSet, rec);
190    return rec;
191}
192
193SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
194    SkRefCnt_SafeAssign(fTFSet, rec);
195    return rec;
196}
197
198SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
199    SkRefCnt_SafeAssign(fFactorySet, rec);
200    return rec;
201}
202
203void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
204    if (NULL == obj || NULL == fTFSet) {
205        this->write32(0);
206    } else {
207        this->write32(fTFSet->add(obj));
208    }
209}
210
211void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
212    if (NULL == obj || NULL == fRCSet) {
213        this->write32(0);
214    } else {
215        this->write32(fRCSet->add(obj));
216    }
217}
218
219void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
220    /*
221     *  If we have a factoryset, then the first 32bits tell us...
222     *       0: failure to write the flattenable
223     *      <0: we store the negative of the (1-based) index
224     *      >0: the length of the name
225     *  If we don't have a factoryset, then the first "ptr" is either the
226     *  factory, or null for failure.
227     *
228     *  The distinction is important, since 0-index is 32bits (always), but a
229     *  0-functionptr might be 32 or 64 bits.
230     */
231
232    SkFlattenable::Factory factory = NULL;
233    if (flattenable) {
234        factory = flattenable->getFactory();
235    }
236    if (NULL == factory) {
237        if (fFactorySet) {
238            this->write32(0);
239        } else {
240            this->writeFunctionPtr(NULL);
241        }
242        return;
243    }
244
245    /*
246     *  We can write 1 of 3 versions of the flattenable:
247     *  1.  function-ptr : this is the fastest for the reader, but assumes that
248     *      the writer and reader are in the same process.
249     *  2.  index into fFactorySet : This is assumes the writer will later
250     *      resolve the function-ptrs into strings for its reader. SkPicture
251     *      does exactly this, by writing a table of names (matching the indices)
252     *      up front in its serialized form.
253     *  3.  names : Reuse fFactorySet to store indices, but only after we've
254     *      written the name the first time. SkGPipe uses this technique, as it
255     *      doesn't require the reader to be told to know the table of names
256     *      up front.
257     */
258    if (fFactorySet) {
259        if (this->inlineFactoryNames()) {
260            int index = fFactorySet->find(factory);
261            if (index) {
262                // we write the negative of the index, to distinguish it from
263                // the length of a string
264                this->write32(-index);
265            } else {
266                const char* name = SkFlattenable::FactoryToName(factory);
267                if (NULL == name) {
268                    this->write32(0);
269                    return;
270                }
271                this->writeString(name);
272                index = fFactorySet->add(factory);
273            }
274        } else {
275            // we write the negative of the index, to distinguish it from
276            // the length of a string
277            this->write32(-fFactorySet->add(factory));
278        }
279    } else {
280        this->writeFunctionPtr((void*)factory);
281    }
282
283    // make room for the size of the flatttened object
284    (void)this->reserve(sizeof(uint32_t));
285    // record the current size, so we can subtract after the object writes.
286    uint32_t offset = this->size();
287    // now flatten the object
288    flattenable->flatten(*this);
289    uint32_t objSize = this->size() - offset;
290    // record the obj's size
291    *this->peek32(offset - sizeof(uint32_t)) = objSize;
292}
293
294void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
295    *(void**)this->reserve(sizeof(void*)) = proc;
296}
297
298///////////////////////////////////////////////////////////////////////////////
299
300SkRefCntSet::~SkRefCntSet() {
301    // call this now, while our decPtr() is sill in scope
302    this->reset();
303}
304
305void SkRefCntSet::incPtr(void* ptr) {
306    ((SkRefCnt*)ptr)->ref();
307}
308
309void SkRefCntSet::decPtr(void* ptr) {
310    ((SkRefCnt*)ptr)->unref();
311}
312
313///////////////////////////////////////////////////////////////////////////////
314///////////////////////////////////////////////////////////////////////////////
315///////////////////////////////////////////////////////////////////////////////
316
317#define MAX_PAIR_COUNT  64
318
319struct Pair {
320    const char*             fName;
321    SkFlattenable::Factory  fFactory;
322};
323
324static int gCount;
325static Pair gPairs[MAX_PAIR_COUNT];
326
327void SkFlattenable::Register(const char name[], Factory factory) {
328    SkASSERT(name);
329    SkASSERT(factory);
330
331    static bool gOnce;
332    if (!gOnce) {
333        gCount = 0;
334        gOnce = true;
335    }
336
337    SkASSERT(gCount < MAX_PAIR_COUNT);
338
339    gPairs[gCount].fName = name;
340    gPairs[gCount].fFactory = factory;
341    gCount += 1;
342}
343
344SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
345    const Pair* pairs = gPairs;
346    for (int i = gCount - 1; i >= 0; --i) {
347        if (strcmp(pairs[i].fName, name) == 0) {
348            return pairs[i].fFactory;
349        }
350    }
351    return NULL;
352}
353
354const char* SkFlattenable::FactoryToName(Factory fact) {
355    const Pair* pairs = gPairs;
356    for (int i = gCount - 1; i >= 0; --i) {
357        if (pairs[i].fFactory == fact) {
358            return pairs[i].fName;
359        }
360    }
361    return NULL;
362}
363
364bool SkFlattenable::toDumpString(SkString* str) const {
365    return false;
366}
367
368