SkFlattenable.cpp revision 9245498e40399199ed6d32aa67fe028b634cc582
15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)/*
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Copyright 2011 Google Inc.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) *
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * Use of this source code is governed by a BSD-style license that can be
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) * found in the LICENSE file.
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) */
8868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)#include "SkFlattenable.h"
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkTypeface.h"
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkMatrix.h"
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "SkRegion.h"
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size = matrix->unflatten(reader->peek());
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(SkAlign4(size) == size);
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)reader->skip(size);
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size = matrix.flatten(NULL);
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(SkAlign4(size) == size);
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    matrix.flatten(writer->reserve(size));
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkReadRegion(SkReader32* reader, SkRegion* rgn) {
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    size_t size = rgn->unflatten(reader->peek());
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(SkAlign4(size) == size);
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    (void)reader->skip(size);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)    size_t size = rgn.flatten(NULL);
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    SkASSERT(SkAlign4(size) == size);
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    rgn.flatten(writer->reserve(size));
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void SkFlattenable::flatten(SkFlattenableWriteBuffer&)
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    /*  we don't write anything at the moment, but this allows our subclasses
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        to not know that, since we want them to always call INHERITED::flatten()
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        in their code.
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    */
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)///////////////////////////////////////////////////////////////////////////////
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fRCArray = NULL;
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fRCCount = 0;
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fTFArray = NULL;
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fTFCount = 0;
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fFactoryTDArray = NULL;
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    fFactoryArray = NULL;
60    fFactoryCount = 0;
61}
62
63SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
64        INHERITED(data, 1024 * 1024) {
65    fRCArray = NULL;
66    fRCCount = 0;
67
68    fTFArray = NULL;
69    fTFCount = 0;
70
71    fFactoryTDArray = NULL;
72    fFactoryArray = NULL;
73    fFactoryCount = 0;
74}
75
76SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
77        : INHERITED(data, size) {
78    fRCArray = NULL;
79    fRCCount = 0;
80
81    fTFArray = NULL;
82    fTFCount = 0;
83
84    fFactoryTDArray = NULL;
85    fFactoryArray = NULL;
86    fFactoryCount = 0;
87}
88
89SkTypeface* SkFlattenableReadBuffer::readTypeface() {
90    uint32_t index = this->readU32();
91    if (0 == index || index > (unsigned)fTFCount) {
92        if (index) {
93            SkDebugf("====== typeface index %d\n", index);
94        }
95        return NULL;
96    } else {
97        SkASSERT(fTFArray);
98        return fTFArray[index - 1];
99    }
100}
101
102SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
103    uint32_t index = this->readU32();
104    if (0 == index || index > (unsigned)fRCCount) {
105        return NULL;
106    } else {
107        SkASSERT(fRCArray);
108        return fRCArray[index - 1];
109    }
110}
111
112SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
113    SkFlattenable::Factory factory = NULL;
114
115    if (fFactoryCount > 0) {
116        int32_t index = this->readU32();
117        if (0 == index) {
118            return NULL; // writer failed to give us the flattenable
119        }
120        index = -index; // we stored the negative of the index
121        index -= 1;     // we stored the index-base-1
122        SkASSERT(index < fFactoryCount);
123        factory = fFactoryArray[index];
124    } else if (fFactoryTDArray) {
125        const int32_t* peek = (const int32_t*)this->peek();
126        if (*peek <= 0) {
127            int32_t index = this->readU32();
128            if (0 == index) {
129                return NULL; // writer failed to give us the flattenable
130            }
131            index = -index; // we stored the negative of the index
132            index -= 1;     // we stored the index-base-1
133            factory = (*fFactoryTDArray)[index];
134        } else {
135            const char* name = this->readString();
136            factory = SkFlattenable::NameToFactory(name);
137            if (factory) {
138                SkASSERT(fFactoryTDArray->find(factory) < 0);
139                *fFactoryTDArray->append() = factory;
140            } else {
141//                SkDebugf("can't find factory for [%s]\n", name);
142            }
143            // if we didn't find a factory, that's our failure, not the writer's,
144            // so we fall through, so we can skip the sizeRecorded data.
145        }
146    } else {
147        factory = (SkFlattenable::Factory)readFunctionPtr();
148        if (NULL == factory) {
149            return NULL; // writer failed to give us the flattenable
150        }
151    }
152
153    // if we get here, factory may still be null, but if that is the case, the
154    // failure was ours, not the writer.
155    SkFlattenable* obj = NULL;
156    uint32_t sizeRecorded = this->readU32();
157    if (factory) {
158        uint32_t offset = this->offset();
159        obj = (*factory)(*this);
160        // check that we read the amount we expected
161        uint32_t sizeRead = this->offset() - offset;
162        if (sizeRecorded != sizeRead) {
163            // we could try to fix up the offset...
164            sk_throw();
165        }
166    } else {
167        // we must skip the remaining data
168        this->skip(sizeRecorded);
169    }
170    return obj;
171}
172
173void* SkFlattenableReadBuffer::readFunctionPtr() {
174    void* proc;
175    this->read(&proc, sizeof(proc));
176    return proc;
177}
178
179///////////////////////////////////////////////////////////////////////////////
180
181SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
182        INHERITED(minSize) {
183    fFlags = (Flags)0;
184    fRCSet = NULL;
185    fTFSet = NULL;
186    fFactorySet = NULL;
187}
188
189SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
190    SkSafeUnref(fRCSet);
191    SkSafeUnref(fTFSet);
192    SkSafeUnref(fFactorySet);
193}
194
195SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
196    SkRefCnt_SafeAssign(fRCSet, rec);
197    return rec;
198}
199
200SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
201    SkRefCnt_SafeAssign(fTFSet, rec);
202    return rec;
203}
204
205SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
206    SkRefCnt_SafeAssign(fFactorySet, rec);
207    return rec;
208}
209
210void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
211    if (NULL == obj || NULL == fTFSet) {
212        this->write32(0);
213    } else {
214        this->write32(fTFSet->add(obj));
215    }
216}
217
218void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
219    if (NULL == obj || NULL == fRCSet) {
220        this->write32(0);
221    } else {
222        this->write32(fRCSet->add(obj));
223    }
224}
225
226void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
227    /*
228     *  If we have a factoryset, then the first 32bits tell us...
229     *       0: failure to write the flattenable
230     *      <0: we store the negative of the (1-based) index
231     *      >0: the length of the name
232     *  If we don't have a factoryset, then the first "ptr" is either the
233     *  factory, or null for failure.
234     *
235     *  The distinction is important, since 0-index is 32bits (always), but a
236     *  0-functionptr might be 32 or 64 bits.
237     */
238
239    SkFlattenable::Factory factory = NULL;
240    if (flattenable) {
241        factory = flattenable->getFactory();
242    }
243    if (NULL == factory) {
244        if (fFactorySet) {
245            this->write32(0);
246        } else {
247            this->writeFunctionPtr(NULL);
248        }
249        return;
250    }
251
252    /*
253     *  We can write 1 of 3 versions of the flattenable:
254     *  1.  function-ptr : this is the fastest for the reader, but assumes that
255     *      the writer and reader are in the same process.
256     *  2.  index into fFactorySet : This is assumes the writer will later
257     *      resolve the function-ptrs into strings for its reader. SkPicture
258     *      does exactly this, by writing a table of names (matching the indices)
259     *      up front in its serialized form.
260     *  3.  names : Reuse fFactorySet to store indices, but only after we've
261     *      written the name the first time. SkGPipe uses this technique, as it
262     *      doesn't require the reader to be told to know the table of names
263     *      up front.
264     */
265    if (fFactorySet) {
266        if (this->inlineFactoryNames()) {
267            int index = fFactorySet->find(factory);
268            if (index) {
269                // we write the negative of the index, to distinguish it from
270                // the length of a string
271                this->write32(-index);
272            } else {
273                const char* name = SkFlattenable::FactoryToName(factory);
274                if (NULL == name) {
275                    this->write32(0);
276                    return;
277                }
278                this->writeString(name);
279                index = fFactorySet->add(factory);
280            }
281        } else {
282            // we write the negative of the index, to distinguish it from
283            // the length of a string
284            this->write32(-(int)fFactorySet->add(factory));
285        }
286    } else {
287        this->writeFunctionPtr((void*)factory);
288    }
289
290    // make room for the size of the flatttened object
291    (void)this->reserve(sizeof(uint32_t));
292    // record the current size, so we can subtract after the object writes.
293    uint32_t offset = this->size();
294    // now flatten the object
295    flattenable->flatten(*this);
296    uint32_t objSize = this->size() - offset;
297    // record the obj's size
298    *this->peek32(offset - sizeof(uint32_t)) = objSize;
299}
300
301void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
302    *(void**)this->reserve(sizeof(void*)) = proc;
303}
304
305///////////////////////////////////////////////////////////////////////////////
306
307SkRefCntSet::~SkRefCntSet() {
308    // call this now, while our decPtr() is sill in scope
309    this->reset();
310}
311
312void SkRefCntSet::incPtr(void* ptr) {
313    ((SkRefCnt*)ptr)->ref();
314}
315
316void SkRefCntSet::decPtr(void* ptr) {
317    ((SkRefCnt*)ptr)->unref();
318}
319
320///////////////////////////////////////////////////////////////////////////////
321///////////////////////////////////////////////////////////////////////////////
322///////////////////////////////////////////////////////////////////////////////
323
324#define MAX_PAIR_COUNT  64
325
326struct Pair {
327    const char*             fName;
328    SkFlattenable::Factory  fFactory;
329};
330
331static int gCount;
332static Pair gPairs[MAX_PAIR_COUNT];
333
334void SkFlattenable::Register(const char name[], Factory factory) {
335    SkASSERT(name);
336    SkASSERT(factory);
337
338    static bool gOnce;
339    if (!gOnce) {
340        gCount = 0;
341        gOnce = true;
342    }
343
344    SkASSERT(gCount < MAX_PAIR_COUNT);
345
346    gPairs[gCount].fName = name;
347    gPairs[gCount].fFactory = factory;
348    gCount += 1;
349}
350
351#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
352static void report_no_entries(const char* functionName) {
353    if (!gCount) {
354        SkDebugf("%s has no registered name/factory pairs."
355                 " Call SkGraphics::Init() at process initialization time.",
356                 functionName);
357    }
358}
359#endif
360
361SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
362#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
363    report_no_entries(__FUNCTION__);
364#endif
365    const Pair* pairs = gPairs;
366    for (int i = gCount - 1; i >= 0; --i) {
367        if (strcmp(pairs[i].fName, name) == 0) {
368            return pairs[i].fFactory;
369        }
370    }
371    return NULL;
372}
373
374const char* SkFlattenable::FactoryToName(Factory fact) {
375#if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
376    report_no_entries(__FUNCTION__);
377#endif
378    const Pair* pairs = gPairs;
379    for (int i = gCount - 1; i >= 0; --i) {
380        if (pairs[i].fFactory == fact) {
381            return pairs[i].fName;
382        }
383    }
384    return NULL;
385}
386
387bool SkFlattenable::toDumpString(SkString* str) const {
388    return false;
389}
390