1 #include "SkFlattenable.h"
2 #include "SkTypeface.h"
3
4 #include "SkMatrix.h"
5 #include "SkRegion.h"
6
SkReadMatrix(SkReader32 * reader,SkMatrix * matrix)7 void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) {
8 size_t size = matrix->unflatten(reader->peek());
9 SkASSERT(SkAlign4(size) == size);
10 (void)reader->skip(size);
11 }
12
SkWriteMatrix(SkWriter32 * writer,const SkMatrix & matrix)13 void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) {
14 size_t size = matrix.flatten(NULL);
15 SkASSERT(SkAlign4(size) == size);
16 matrix.flatten(writer->reserve(size));
17 }
18
SkReadRegion(SkReader32 * reader,SkRegion * rgn)19 void SkReadRegion(SkReader32* reader, SkRegion* rgn) {
20 size_t size = rgn->unflatten(reader->peek());
21 SkASSERT(SkAlign4(size) == size);
22 (void)reader->skip(size);
23 }
24
SkWriteRegion(SkWriter32 * writer,const SkRegion & rgn)25 void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) {
26 size_t size = rgn.flatten(NULL);
27 SkASSERT(SkAlign4(size) == size);
28 rgn.flatten(writer->reserve(size));
29 }
30
31 ///////////////////////////////////////////////////////////////////////////////
32
flatten(SkFlattenableWriteBuffer &)33 void SkFlattenable::flatten(SkFlattenableWriteBuffer&)
34 {
35 /* we don't write anything at the moment, but this allows our subclasses
36 to not know that, since we want them to always call INHERITED::flatten()
37 in their code.
38 */
39 }
40
41 ///////////////////////////////////////////////////////////////////////////////
42 ///////////////////////////////////////////////////////////////////////////////
43
SkFlattenableReadBuffer()44 SkFlattenableReadBuffer::SkFlattenableReadBuffer() {
45 fRCArray = NULL;
46 fRCCount = 0;
47
48 fTFArray = NULL;
49 fTFCount = 0;
50
51 fFactoryArray = NULL;
52 fFactoryCount = 0;
53 }
54
SkFlattenableReadBuffer(const void * data)55 SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) :
56 INHERITED(data, 1024 * 1024) {
57 fRCArray = NULL;
58 fRCCount = 0;
59
60 fTFArray = NULL;
61 fTFCount = 0;
62
63 fFactoryArray = NULL;
64 fFactoryCount = 0;
65 }
66
SkFlattenableReadBuffer(const void * data,size_t size)67 SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size)
68 : INHERITED(data, size) {
69 fRCArray = NULL;
70 fRCCount = 0;
71
72 fTFArray = NULL;
73 fTFCount = 0;
74
75 fFactoryArray = NULL;
76 fFactoryCount = 0;
77 }
78
readTypeface()79 SkTypeface* SkFlattenableReadBuffer::readTypeface() {
80 uint32_t index = this->readU32();
81 if (0 == index || index > (unsigned)fTFCount) {
82 if (index) {
83 SkDebugf("====== typeface index %d\n", index);
84 }
85 return NULL;
86 } else {
87 SkASSERT(fTFArray);
88 return fTFArray[index - 1];
89 }
90 }
91
readRefCnt()92 SkRefCnt* SkFlattenableReadBuffer::readRefCnt() {
93 uint32_t index = this->readU32();
94 if (0 == index || index > (unsigned)fRCCount) {
95 return NULL;
96 } else {
97 SkASSERT(fRCArray);
98 return fRCArray[index - 1];
99 }
100 }
101
readFlattenable()102 SkFlattenable* SkFlattenableReadBuffer::readFlattenable() {
103 SkFlattenable::Factory factory = NULL;
104
105 if (fFactoryCount > 0) {
106 uint32_t index = this->readU32();
107 if (index > 0) {
108 index -= 1;
109 SkASSERT(index < (unsigned)fFactoryCount);
110 factory = fFactoryArray[index];
111 // if we recorded an index, but failed to get a factory, we need
112 // to skip the flattened data in the buffer
113 if (NULL == factory) {
114 uint32_t size = this->readU32();
115 this->skip(size);
116 // fall through and return NULL for the object
117 }
118 }
119 } else {
120 factory = (SkFlattenable::Factory)readFunctionPtr();
121 }
122
123 SkFlattenable* obj = NULL;
124 if (factory) {
125 uint32_t sizeRecorded = this->readU32();
126 uint32_t offset = this->offset();
127 obj = (*factory)(*this);
128 // check that we read the amount we expected
129 uint32_t sizeRead = this->offset() - offset;
130 if (sizeRecorded != sizeRead) {
131 // we could try to fix up the offset...
132 sk_throw();
133 }
134 }
135 return obj;
136 }
137
readFunctionPtr()138 void* SkFlattenableReadBuffer::readFunctionPtr() {
139 void* proc;
140 this->read(&proc, sizeof(proc));
141 return proc;
142 }
143
144 ///////////////////////////////////////////////////////////////////////////////
145
SkFlattenableWriteBuffer(size_t minSize)146 SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) :
147 INHERITED(minSize) {
148 fFlags = (Flags)0;
149 fRCSet = NULL;
150 fTFSet = NULL;
151 fFactorySet = NULL;
152 }
153
~SkFlattenableWriteBuffer()154 SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() {
155 SkSafeUnref(fRCSet);
156 SkSafeUnref(fTFSet);
157 SkSafeUnref(fFactorySet);
158 }
159
setRefCntRecorder(SkRefCntSet * rec)160 SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) {
161 SkRefCnt_SafeAssign(fRCSet, rec);
162 return rec;
163 }
164
setTypefaceRecorder(SkRefCntSet * rec)165 SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) {
166 SkRefCnt_SafeAssign(fTFSet, rec);
167 return rec;
168 }
169
setFactoryRecorder(SkFactorySet * rec)170 SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) {
171 SkRefCnt_SafeAssign(fFactorySet, rec);
172 return rec;
173 }
174
writeTypeface(SkTypeface * obj)175 void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) {
176 if (NULL == obj || NULL == fTFSet) {
177 this->write32(0);
178 } else {
179 this->write32(fTFSet->add(obj));
180 }
181 }
182
writeRefCnt(SkRefCnt * obj)183 void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) {
184 if (NULL == obj || NULL == fRCSet) {
185 this->write32(0);
186 } else {
187 this->write32(fRCSet->add(obj));
188 }
189 }
190
writeFlattenable(SkFlattenable * flattenable)191 void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) {
192 SkFlattenable::Factory factory = NULL;
193 if (flattenable) {
194 factory = flattenable->getFactory();
195 }
196
197 if (fFactorySet) {
198 this->write32(fFactorySet->add(factory));
199 } else {
200 this->writeFunctionPtr((void*)factory);
201 }
202
203 if (factory) {
204 // make room for the size of the flatttened object
205 (void)this->reserve(sizeof(uint32_t));
206 // record the current size, so we can subtract after the object writes.
207 uint32_t offset = this->size();
208 // now flatten the object
209 flattenable->flatten(*this);
210 uint32_t objSize = this->size() - offset;
211 // record the obj's size
212 *this->peek32(offset - sizeof(uint32_t)) = objSize;
213 }
214 }
215
writeFunctionPtr(void * proc)216 void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) {
217 *(void**)this->reserve(sizeof(void*)) = proc;
218 }
219
220 ///////////////////////////////////////////////////////////////////////////////
221
~SkRefCntSet()222 SkRefCntSet::~SkRefCntSet() {
223 // call this now, while our decPtr() is sill in scope
224 this->reset();
225 }
226
incPtr(void * ptr)227 void SkRefCntSet::incPtr(void* ptr) {
228 ((SkRefCnt*)ptr)->ref();
229 }
230
decPtr(void * ptr)231 void SkRefCntSet::decPtr(void* ptr) {
232 ((SkRefCnt*)ptr)->unref();
233 }
234
235 ///////////////////////////////////////////////////////////////////////////////
236 ///////////////////////////////////////////////////////////////////////////////
237 ///////////////////////////////////////////////////////////////////////////////
238
239 #define MAX_PAIR_COUNT 64
240
241 struct Pair {
242 const char* fName;
243 SkFlattenable::Factory fFactory;
244 };
245
246 static int gCount;
247 static Pair gPairs[MAX_PAIR_COUNT];
248
Register(const char name[],Factory factory)249 void SkFlattenable::Register(const char name[], Factory factory) {
250 SkASSERT(name);
251 SkASSERT(factory);
252
253 static bool gOnce;
254 if (!gOnce) {
255 gCount = 0;
256 gOnce = true;
257 }
258
259 SkASSERT(gCount < MAX_PAIR_COUNT);
260
261 gPairs[gCount].fName = name;
262 gPairs[gCount].fFactory = factory;
263 gCount += 1;
264 }
265
NameToFactory(const char name[])266 SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) {
267 const Pair* pairs = gPairs;
268 for (int i = gCount - 1; i >= 0; --i) {
269 if (strcmp(pairs[i].fName, name) == 0) {
270 return pairs[i].fFactory;
271 }
272 }
273 return NULL;
274 }
275
FactoryToName(Factory fact)276 const char* SkFlattenable::FactoryToName(Factory fact) {
277 const Pair* pairs = gPairs;
278 for (int i = gCount - 1; i >= 0; --i) {
279 if (pairs[i].fFactory == fact) {
280 return pairs[i].fName;
281 }
282 }
283 return NULL;
284 }
285
toDumpString(SkString * str) const286 bool SkFlattenable::toDumpString(SkString* str) const {
287 return false;
288 }
289
290