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