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 :
14 0 : void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
15 0 : size_t size = matrix->unflatten(reader->peek());
16 0 : SkASSERT(SkAlign4(size) == size);
17 0 : (void)reader->skip(size);
18 0 : }
19 :
20 0 : void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
21 0 : size_t size = matrix.flatten(NULL);
22 0 : SkASSERT(SkAlign4(size) == size);
23 0 : matrix.flatten(writer->reserve(size));
24 0 : }
25 :
26 0 : void SkReadRegion(SkReader32* reader, SkRegion* rgn) {
27 0 : size_t size = rgn->unflatten(reader->peek());
28 0 : SkASSERT(SkAlign4(size) == size);
29 0 : (void)reader->skip(size);
30 0 : }
31 :
32 0 : void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
33 0 : size_t size = rgn.flatten(NULL);
34 0 : SkASSERT(SkAlign4(size) == size);
35 0 : rgn.flatten(writer->reserve(size));
36 0 : }
37 :
38 : ///////////////////////////////////////////////////////////////////////////////
39 :
40 0 : 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 0 : }
47 :
48 : ///////////////////////////////////////////////////////////////////////////////
49 : ///////////////////////////////////////////////////////////////////////////////
50 :
51 0 : SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
52 0 : fRCArray = NULL;
53 0 : fRCCount = 0;
54 :
55 0 : fTFArray = NULL;
56 0 : fTFCount = 0;
57 :
58 0 : fFactoryTDArray = NULL;
59 0 : fFactoryArray = NULL;
60 0 : fFactoryCount = 0;
61 0 : }
62 :
63 0 : SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
64 0 : INHERITED(data, 1024 * 1024) {
65 0 : fRCArray = NULL;
66 0 : fRCCount = 0;
67 :
68 0 : fTFArray = NULL;
69 0 : fTFCount = 0;
70 :
71 0 : fFactoryTDArray = NULL;
72 0 : fFactoryArray = NULL;
73 0 : fFactoryCount = 0;
74 0 : }
75 :
76 0 : SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
77 0 : : INHERITED(data, size) {
78 0 : fRCArray = NULL;
79 0 : fRCCount = 0;
80 :
81 0 : fTFArray = NULL;
82 0 : fTFCount = 0;
83 :
84 0 : fFactoryTDArray = NULL;
85 0 : fFactoryArray = NULL;
86 0 : fFactoryCount = 0;
87 0 : }
88 :
89 0 : SkTypeface* SkFlattenableReadBuffer::readTypeface() {
90 0 : uint32_t index = this->readU32();
91 0 : if (0 == index || index > (unsigned)fTFCount) {
92 0 : if (index) {
93 0 : SkDebugf("====== typeface index %d\n", index);
94 : }
95 0 : return NULL;
96 : } else {
97 0 : SkASSERT(fTFArray);
98 0 : return fTFArray[index - 1];
99 : }
100 : }
101 :
102 0 : SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
103 0 : uint32_t index = this->readU32();
104 0 : if (0 == index || index > (unsigned)fRCCount) {
105 0 : return NULL;
106 : } else {
107 0 : SkASSERT(fRCArray);
108 0 : return fRCArray[index - 1];
109 : }
110 : }
111 :
112 0 : SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
113 0 : SkFlattenable::Factory factory = NULL;
114 :
115 0 : if (fFactoryCount > 0) {
116 0 : int32_t index = this->readU32();
117 0 : if (0 == index) {
118 0 : return NULL; // writer failed to give us the flattenable
119 : }
120 0 : index = -index; // we stored the negative of the index
121 0 : index -= 1; // we stored the index-base-1
122 0 : SkASSERT(index < fFactoryCount);
123 0 : factory = fFactoryArray[index];
124 0 : } else if (fFactoryTDArray) {
125 0 : const int32_t* peek = (const int32_t*)this->peek();
126 0 : if (*peek <= 0) {
127 0 : int32_t index = this->readU32();
128 0 : if (0 == index) {
129 0 : return NULL; // writer failed to give us the flattenable
130 : }
131 0 : index = -index; // we stored the negative of the index
132 0 : index -= 1; // we stored the index-base-1
133 0 : factory = (*fFactoryTDArray)[index];
134 : } else {
135 0 : const char* name = this->readString();
136 0 : factory = SkFlattenable::NameToFactory(name);
137 0 : if (factory) {
138 0 : SkASSERT(fFactoryTDArray->find(factory) < 0);
139 0 : *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 0 : factory = (SkFlattenable::Factory)readFunctionPtr();
148 0 : if (NULL == factory) {
149 0 : 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 0 : SkFlattenable* obj = NULL;
156 0 : uint32_t sizeRecorded = this->readU32();
157 0 : if (factory) {
158 0 : uint32_t offset = this->offset();
159 0 : obj = (*factory)(*this);
160 : // check that we read the amount we expected
161 0 : uint32_t sizeRead = this->offset() - offset;
162 0 : if (sizeRecorded != sizeRead) {
163 : // we could try to fix up the offset...
164 0 : sk_throw();
165 : }
166 : } else {
167 : // we must skip the remaining data
168 0 : this->skip(sizeRecorded);
169 : }
170 0 : return obj;
171 : }
172 :
173 0 : void* SkFlattenableReadBuffer::readFunctionPtr() {
174 : void* proc;
175 0 : this->read(&proc, sizeof(proc));
176 0 : return proc;
177 : }
178 :
179 : ///////////////////////////////////////////////////////////////////////////////
180 :
181 0 : SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
182 0 : INHERITED(minSize) {
183 0 : fFlags = (Flags)0;
184 0 : fRCSet = NULL;
185 0 : fTFSet = NULL;
186 0 : fFactorySet = NULL;
187 0 : }
188 :
189 0 : SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
190 0 : SkSafeUnref(fRCSet);
191 0 : SkSafeUnref(fTFSet);
192 0 : SkSafeUnref(fFactorySet);
193 0 : }
194 :
195 0 : SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
196 0 : SkRefCnt_SafeAssign(fRCSet, rec);
197 0 : return rec;
198 : }
199 :
200 0 : SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
201 0 : SkRefCnt_SafeAssign(fTFSet, rec);
202 0 : return rec;
203 : }
204 :
205 0 : SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
206 0 : SkRefCnt_SafeAssign(fFactorySet, rec);
207 0 : return rec;
208 : }
209 :
210 0 : void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
211 0 : if (NULL == obj || NULL == fTFSet) {
212 0 : this->write32(0);
213 : } else {
214 0 : this->write32(fTFSet->add(obj));
215 : }
216 0 : }
217 :
218 0 : void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
219 0 : if (NULL == obj || NULL == fRCSet) {
220 0 : this->write32(0);
221 : } else {
222 0 : this->write32(fRCSet->add(obj));
223 : }
224 0 : }
225 :
226 0 : void 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 0 : SkFlattenable::Factory factory = NULL;
240 0 : if (flattenable) {
241 0 : factory = flattenable->getFactory();
242 : }
243 0 : if (NULL == factory) {
244 0 : if (fFactorySet) {
245 0 : this->write32(0);
246 : } else {
247 0 : this->writeFunctionPtr(NULL);
248 : }
249 0 : 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 0 : if (fFactorySet) {
266 0 : if (this->inlineFactoryNames()) {
267 0 : int index = fFactorySet->find(factory);
268 0 : if (index) {
269 : // we write the negative of the index, to distinguish it from
270 : // the length of a string
271 0 : this->write32(-index);
272 : } else {
273 0 : const char* name = SkFlattenable::FactoryToName(factory);
274 0 : if (NULL == name) {
275 0 : this->write32(0);
276 0 : return;
277 : }
278 0 : this->writeString(name);
279 0 : 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 0 : this->write32(-(int)fFactorySet->add(factory));
285 : }
286 : } else {
287 0 : this->writeFunctionPtr((void*)factory);
288 : }
289 :
290 : // make room for the size of the flatttened object
291 0 : (void)this->reserve(sizeof(uint32_t));
292 : // record the current size, so we can subtract after the object writes.
293 0 : uint32_t offset = this->size();
294 : // now flatten the object
295 0 : flattenable->flatten(*this);
296 0 : uint32_t objSize = this->size() - offset;
297 : // record the obj's size
298 0 : *this->peek32(offset - sizeof(uint32_t)) = objSize;
299 : }
300 :
301 0 : void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
302 0 : *(void**)this->reserve(sizeof(void*)) = proc;
303 0 : }
304 :
305 : ///////////////////////////////////////////////////////////////////////////////
306 :
307 0 : SkRefCntSet::~SkRefCntSet() {
308 : // call this now, while our decPtr() is sill in scope
309 0 : this->reset();
310 0 : }
311 :
312 0 : void SkRefCntSet::incPtr(void* ptr) {
313 0 : ((SkRefCnt*)ptr)->ref();
314 0 : }
315 :
316 0 : void SkRefCntSet::decPtr(void* ptr) {
317 0 : ((SkRefCnt*)ptr)->unref();
318 0 : }
319 :
320 : ///////////////////////////////////////////////////////////////////////////////
321 : ///////////////////////////////////////////////////////////////////////////////
322 : ///////////////////////////////////////////////////////////////////////////////
323 :
324 : #define MAX_PAIR_COUNT 64
325 :
326 : struct Pair {
327 : const char* fName;
328 : SkFlattenable::Factory fFactory;
329 : };
330 :
331 : static int gCount;
332 : static Pair gPairs[MAX_PAIR_COUNT];
333 :
334 40992 : void SkFlattenable::Register(const char name[], Factory factory) {
335 40992 : SkASSERT(name);
336 40992 : SkASSERT(factory);
337 :
338 : static bool gOnce;
339 40992 : if (!gOnce) {
340 1464 : gCount = 0;
341 1464 : gOnce = true;
342 : }
343 :
344 40992 : SkASSERT(gCount < MAX_PAIR_COUNT);
345 :
346 40992 : gPairs[gCount].fName = name;
347 40992 : gPairs[gCount].fFactory = factory;
348 40992 : gCount += 1;
349 40992 : }
350 :
351 : #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
352 : static 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 :
361 0 : SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
362 : #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
363 : report_no_entries(__FUNCTION__);
364 : #endif
365 0 : const Pair* pairs = gPairs;
366 0 : for (int i = gCount - 1; i >= 0; --i) {
367 0 : if (strcmp(pairs[i].fName, name) == 0) {
368 0 : return pairs[i].fFactory;
369 : }
370 : }
371 0 : return NULL;
372 : }
373 :
374 0 : const char* SkFlattenable::FactoryToName(Factory fact) {
375 : #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG)
376 : report_no_entries(__FUNCTION__);
377 : #endif
378 0 : const Pair* pairs = gPairs;
379 0 : for (int i = gCount - 1; i >= 0; --i) {
380 0 : if (pairs[i].fFactory == fact) {
381 0 : return pairs[i].fName;
382 : }
383 : }
384 0 : return NULL;
385 : }
386 :
387 0 : bool SkFlattenable::toDumpString(SkString* str) const {
388 0 : return false;
389 : }
|