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