SkFlattenable.cpp revision e9e08cc7b29f97ee9e823e68c3daf0f55c84b21a
1#include "SkFlattenable.h" 2#include "SkTypeface.h" 3 4void 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 15SkFlattenableReadBuffer::SkFlattenableReadBuffer() { 16 fRCArray = NULL; 17 fRCCount = 0; 18 19 fTFArray = NULL; 20 fTFCount = 0; 21 22 fFactoryArray = NULL; 23 fFactoryCount = 0; 24} 25 26SkFlattenableReadBuffer::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 38SkFlattenableReadBuffer::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 50SkTypeface* 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 63SkRefCnt* 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 73SkFlattenable* 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 109void* SkFlattenableReadBuffer::readFunctionPtr() { 110 void* proc; 111 this->read(&proc, sizeof(proc)); 112 return proc; 113} 114 115/////////////////////////////////////////////////////////////////////////////// 116 117SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) : 118 INHERITED(minSize) { 119 fFlags = (Flags)0; 120 fRCSet = NULL; 121 fTFSet = NULL; 122 fFactorySet = NULL; 123} 124 125SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { 126 SkSafeUnref(fRCSet); 127 SkSafeUnref(fTFSet); 128 SkSafeUnref(fFactorySet); 129} 130 131SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) { 132 SkRefCnt_SafeAssign(fRCSet, rec); 133 return rec; 134} 135 136SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { 137 SkRefCnt_SafeAssign(fTFSet, rec); 138 return rec; 139} 140 141SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { 142 SkRefCnt_SafeAssign(fFactorySet, rec); 143 return rec; 144} 145 146void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) { 147 if (NULL == obj || NULL == fTFSet) { 148 this->write32(0); 149 } else { 150 this->write32(fTFSet->add(obj)); 151 } 152} 153 154void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) { 155 if (NULL == obj || NULL == fRCSet) { 156 this->write32(0); 157 } else { 158 this->write32(fRCSet->add(obj)); 159 } 160} 161 162void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { 163 SkFlattenable::Factory factory = NULL; 164 if (flattenable) { 165 factory = flattenable->getFactory(); 166 } 167 168 if (fFactorySet) { 169 this->write32(fFactorySet->add(factory)); 170 } else { 171 this->writeFunctionPtr((void*)factory); 172 } 173 174 if (factory) { 175 // make room for the size of the flatttened object 176 (void)this->reserve(sizeof(uint32_t)); 177 // record the current size, so we can subtract after the object writes. 178 uint32_t offset = this->size(); 179 // now flatten the object 180 flattenable->flatten(*this); 181 uint32_t objSize = this->size() - offset; 182 // record the obj's size 183 *this->peek32(offset - sizeof(uint32_t)) = objSize; 184 } 185} 186 187void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) { 188 *(void**)this->reserve(sizeof(void*)) = proc; 189} 190 191/////////////////////////////////////////////////////////////////////////////// 192 193SkRefCntSet::~SkRefCntSet() { 194 // call this now, while our decPtr() is sill in scope 195 this->reset(); 196} 197 198void SkRefCntSet::incPtr(void* ptr) { 199 ((SkRefCnt*)ptr)->ref(); 200} 201 202void SkRefCntSet::decPtr(void* ptr) { 203 ((SkRefCnt*)ptr)->unref(); 204} 205 206/////////////////////////////////////////////////////////////////////////////// 207/////////////////////////////////////////////////////////////////////////////// 208/////////////////////////////////////////////////////////////////////////////// 209 210#define MAX_PAIR_COUNT 64 211 212struct Pair { 213 const char* fName; 214 SkFlattenable::Factory fFactory; 215}; 216 217static int gCount; 218static Pair gPairs[MAX_PAIR_COUNT]; 219 220void SkFlattenable::Register(const char name[], Factory factory) { 221 SkASSERT(name); 222 SkASSERT(factory); 223 224 static bool gOnce; 225 if (!gOnce) { 226 gCount = 0; 227 gOnce = true; 228 } 229 230 SkASSERT(gCount < MAX_PAIR_COUNT); 231 232 gPairs[gCount].fName = name; 233 gPairs[gCount].fFactory = factory; 234 gCount += 1; 235} 236 237SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { 238 const Pair* pairs = gPairs; 239 for (int i = gCount - 1; i >= 0; --i) { 240 if (strcmp(pairs[i].fName, name) == 0) { 241 return pairs[i].fFactory; 242 } 243 } 244 return NULL; 245} 246 247const char* SkFlattenable::FactoryToName(Factory fact) { 248 const Pair* pairs = gPairs; 249 for (int i = gCount - 1; i >= 0; --i) { 250 if (pairs[i].fFactory == fact) { 251 return pairs[i].fName; 252 } 253 } 254 return NULL; 255} 256 257bool SkFlattenable::toDumpString(SkString* str) const { 258 return false; 259} 260 261