• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
SkReadMatrix(SkReader32 * reader,SkMatrix * matrix)14 void 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 
SkWriteMatrix(SkWriter32 * writer,const SkMatrix & matrix)20 void 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 
SkReadRegion(SkReader32 * reader,SkRegion * rgn)26 void 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 
SkWriteRegion(SkWriter32 * writer,const SkRegion & rgn)32 void 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 
flatten(SkFlattenableWriteBuffer &)40 void 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 
SkFlattenableReadBuffer()51 SkFlattenableReadBuffer::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 
SkFlattenableReadBuffer(const void * data)64 SkFlattenableReadBuffer::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 
SkFlattenableReadBuffer(const void * data,size_t size)78 SkFlattenableReadBuffer::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 
readTypeface()92 SkTypeface* 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 
readRefCnt()105 SkRefCnt* 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 
readFlattenable()115 SkFlattenable* 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 
readFunctionPtr()213 void* SkFlattenableReadBuffer::readFunctionPtr() {
214     void* proc;
215     this->read(&proc, sizeof(proc));
216     return proc;
217 }
218 
219 ///////////////////////////////////////////////////////////////////////////////
220 
SkFlattenableWriteBuffer(size_t minSize)221 SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
222         INHERITED(minSize) {
223     fFlags = (Flags)0;
224     fRCSet = NULL;
225     fTFSet = NULL;
226     fFactorySet = NULL;
227 }
228 
~SkFlattenableWriteBuffer()229 SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
230     SkSafeUnref(fRCSet);
231     SkSafeUnref(fTFSet);
232     SkSafeUnref(fFactorySet);
233 }
234 
setRefCntRecorder(SkRefCntSet * rec)235 SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
236     SkRefCnt_SafeAssign(fRCSet, rec);
237     return rec;
238 }
239 
setTypefaceRecorder(SkRefCntSet * rec)240 SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
241     SkRefCnt_SafeAssign(fTFSet, rec);
242     return rec;
243 }
244 
setFactoryRecorder(SkFactorySet * rec)245 SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
246     SkRefCnt_SafeAssign(fFactorySet, rec);
247     return rec;
248 }
249 
writeTypeface(SkTypeface * obj)250 void 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 
writeRefCnt(SkRefCnt * obj)258 void 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 
writeFlattenable(SkFlattenable * flattenable)266 void 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 
writeFunctionPtr(void * proc)341 void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
342     *(void**)this->reserve(sizeof(void*)) = proc;
343 }
344 
345 ///////////////////////////////////////////////////////////////////////////////
346 
~SkRefCntSet()347 SkRefCntSet::~SkRefCntSet() {
348     // call this now, while our decPtr() is sill in scope
349     this->reset();
350 }
351 
incPtr(void * ptr)352 void SkRefCntSet::incPtr(void* ptr) {
353     ((SkRefCnt*)ptr)->ref();
354 }
355 
decPtr(void * ptr)356 void SkRefCntSet::decPtr(void* ptr) {
357     ((SkRefCnt*)ptr)->unref();
358 }
359 
360 ///////////////////////////////////////////////////////////////////////////////
361 ///////////////////////////////////////////////////////////////////////////////
362 ///////////////////////////////////////////////////////////////////////////////
363 
364 #define MAX_PAIR_COUNT  64
365 
366 struct Pair {
367     const char*             fName;
368     SkFlattenable::Factory  fFactory;
369 };
370 
371 static int gCount;
372 static Pair gPairs[MAX_PAIR_COUNT];
373 
Register(const char name[],Factory factory)374 void 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)
report_no_entries(const char * functionName)392 static 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 
NameToFactory(const char name[])401 SkFlattenable::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 
FactoryToName(Factory fact)414 const 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 
toDumpString(SkString * str) const427 bool SkFlattenable::toDumpString(SkString* str) const {
428     return false;
429 }
430