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