SkFlattenable.cpp revision 6bac947cd5bc460dd9166ada6310d678fd2e39f8
1#include "SkFlattenable.h" 2#include "SkTypeface.h" 3 4#include "SkMatrix.h" 5#include "SkRegion.h" 6 7void 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 13void 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 19void 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 25void 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 33void 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 44SkFlattenableReadBuffer::SkFlattenableReadBuffer() { 45 fRCArray = NULL; 46 fRCCount = 0; 47 48 fTFArray = NULL; 49 fTFCount = 0; 50 51 fFactoryTDArray = NULL; 52 fFactoryArray = NULL; 53 fFactoryCount = 0; 54} 55 56SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) : 57 INHERITED(data, 1024 * 1024) { 58 fRCArray = NULL; 59 fRCCount = 0; 60 61 fTFArray = NULL; 62 fTFCount = 0; 63 64 fFactoryTDArray = NULL; 65 fFactoryArray = NULL; 66 fFactoryCount = 0; 67} 68 69SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size) 70 : INHERITED(data, size) { 71 fRCArray = NULL; 72 fRCCount = 0; 73 74 fTFArray = NULL; 75 fTFCount = 0; 76 77 fFactoryTDArray = NULL; 78 fFactoryArray = NULL; 79 fFactoryCount = 0; 80} 81 82SkTypeface* SkFlattenableReadBuffer::readTypeface() { 83 uint32_t index = this->readU32(); 84 if (0 == index || index > (unsigned)fTFCount) { 85 if (index) { 86 SkDebugf("====== typeface index %d\n", index); 87 } 88 return NULL; 89 } else { 90 SkASSERT(fTFArray); 91 return fTFArray[index - 1]; 92 } 93} 94 95SkRefCnt* SkFlattenableReadBuffer::readRefCnt() { 96 uint32_t index = this->readU32(); 97 if (0 == index || index > (unsigned)fRCCount) { 98 return NULL; 99 } else { 100 SkASSERT(fRCArray); 101 return fRCArray[index - 1]; 102 } 103} 104 105SkFlattenable* SkFlattenableReadBuffer::readFlattenable() { 106 SkFlattenable::Factory factory = NULL; 107 108 if (fFactoryCount > 0) { 109 int32_t index = this->readU32(); 110 if (0 == index) { 111 return NULL; // writer failed to give us the flattenable 112 } 113 index = -index; // we stored the negative of the index 114 index -= 1; // we stored the index-base-1 115 SkASSERT(index < (unsigned)fFactoryCount); 116 factory = fFactoryArray[index]; 117 } else if (fFactoryTDArray) { 118 const int32_t* peek = (const int32_t*)this->peek(); 119 if (*peek <= 0) { 120 int32_t index = this->readU32(); 121 if (0 == index) { 122 return NULL; // writer failed to give us the flattenable 123 } 124 index = -index; // we stored the negative of the index 125 index -= 1; // we stored the index-base-1 126 factory = (*fFactoryTDArray)[index]; 127 } else { 128 const char* name = this->readString(); 129 factory = SkFlattenable::NameToFactory(name); 130 if (factory) { 131 SkASSERT(fFactoryTDArray->find(factory) < 0); 132 *fFactoryTDArray->append() = factory; 133 } else { 134// SkDebugf("can't find factory for [%s]\n", name); 135 } 136 // if we didn't find a factory, that's our failure, not the writer's, 137 // so we fall through, so we can skip the sizeRecorded data. 138 } 139 } else { 140 factory = (SkFlattenable::Factory)readFunctionPtr(); 141 if (NULL == factory) { 142 return NULL; // writer failed to give us the flattenable 143 } 144 } 145 146 // if we get here, factory may still be null, but if that is the case, the 147 // failure was ours, not the writer. 148 SkFlattenable* obj = NULL; 149 uint32_t sizeRecorded = this->readU32(); 150 if (factory) { 151 uint32_t offset = this->offset(); 152 obj = (*factory)(*this); 153 // check that we read the amount we expected 154 uint32_t sizeRead = this->offset() - offset; 155 if (sizeRecorded != sizeRead) { 156 // we could try to fix up the offset... 157 sk_throw(); 158 } 159 } else { 160 // we must skip the remaining data 161 this->skip(sizeRecorded); 162 } 163 return obj; 164} 165 166void* SkFlattenableReadBuffer::readFunctionPtr() { 167 void* proc; 168 this->read(&proc, sizeof(proc)); 169 return proc; 170} 171 172/////////////////////////////////////////////////////////////////////////////// 173 174SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) : 175 INHERITED(minSize) { 176 fFlags = (Flags)0; 177 fRCSet = NULL; 178 fTFSet = NULL; 179 fFactorySet = NULL; 180} 181 182SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { 183 SkSafeUnref(fRCSet); 184 SkSafeUnref(fTFSet); 185 SkSafeUnref(fFactorySet); 186} 187 188SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) { 189 SkRefCnt_SafeAssign(fRCSet, rec); 190 return rec; 191} 192 193SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { 194 SkRefCnt_SafeAssign(fTFSet, rec); 195 return rec; 196} 197 198SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { 199 SkRefCnt_SafeAssign(fFactorySet, rec); 200 return rec; 201} 202 203void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) { 204 if (NULL == obj || NULL == fTFSet) { 205 this->write32(0); 206 } else { 207 this->write32(fTFSet->add(obj)); 208 } 209} 210 211void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) { 212 if (NULL == obj || NULL == fRCSet) { 213 this->write32(0); 214 } else { 215 this->write32(fRCSet->add(obj)); 216 } 217} 218 219void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { 220 /* 221 * If we have a factoryset, then the first 32bits tell us... 222 * 0: failure to write the flattenable 223 * <0: we store the negative of the (1-based) index 224 * >0: the length of the name 225 * If we don't have a factoryset, then the first "ptr" is either the 226 * factory, or null for failure. 227 * 228 * The distinction is important, since 0-index is 32bits (always), but a 229 * 0-functionptr might be 32 or 64 bits. 230 */ 231 232 SkFlattenable::Factory factory = NULL; 233 if (flattenable) { 234 factory = flattenable->getFactory(); 235 } 236 if (NULL == factory) { 237 if (fFactorySet) { 238 this->write32(0); 239 } else { 240 this->writeFunctionPtr(NULL); 241 } 242 return; 243 } 244 245 /* 246 * We can write 1 of 3 versions of the flattenable: 247 * 1. function-ptr : this is the fastest for the reader, but assumes that 248 * the writer and reader are in the same process. 249 * 2. index into fFactorySet : This is assumes the writer will later 250 * resolve the function-ptrs into strings for its reader. SkPicture 251 * does exactly this, by writing a table of names (matching the indices) 252 * up front in its serialized form. 253 * 3. names : Reuse fFactorySet to store indices, but only after we've 254 * written the name the first time. SkGPipe uses this technique, as it 255 * doesn't require the reader to be told to know the table of names 256 * up front. 257 */ 258 if (fFactorySet) { 259 if (this->inlineFactoryNames()) { 260 int index = fFactorySet->find(factory); 261 if (index) { 262 // we write the negative of the index, to distinguish it from 263 // the length of a string 264 this->write32(-index); 265 } else { 266 const char* name = SkFlattenable::FactoryToName(factory); 267 if (NULL == name) { 268 this->write32(0); 269 return; 270 } 271 this->writeString(name); 272 index = fFactorySet->add(factory); 273 } 274 } else { 275 // we write the negative of the index, to distinguish it from 276 // the length of a string 277 this->write32(-fFactorySet->add(factory)); 278 } 279 } else { 280 this->writeFunctionPtr((void*)factory); 281 } 282 283 // make room for the size of the flatttened object 284 (void)this->reserve(sizeof(uint32_t)); 285 // record the current size, so we can subtract after the object writes. 286 uint32_t offset = this->size(); 287 // now flatten the object 288 flattenable->flatten(*this); 289 uint32_t objSize = this->size() - offset; 290 // record the obj's size 291 *this->peek32(offset - sizeof(uint32_t)) = objSize; 292} 293 294void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) { 295 *(void**)this->reserve(sizeof(void*)) = proc; 296} 297 298/////////////////////////////////////////////////////////////////////////////// 299 300SkRefCntSet::~SkRefCntSet() { 301 // call this now, while our decPtr() is sill in scope 302 this->reset(); 303} 304 305void SkRefCntSet::incPtr(void* ptr) { 306 ((SkRefCnt*)ptr)->ref(); 307} 308 309void SkRefCntSet::decPtr(void* ptr) { 310 ((SkRefCnt*)ptr)->unref(); 311} 312 313/////////////////////////////////////////////////////////////////////////////// 314/////////////////////////////////////////////////////////////////////////////// 315/////////////////////////////////////////////////////////////////////////////// 316 317#define MAX_PAIR_COUNT 64 318 319struct Pair { 320 const char* fName; 321 SkFlattenable::Factory fFactory; 322}; 323 324static int gCount; 325static Pair gPairs[MAX_PAIR_COUNT]; 326 327void SkFlattenable::Register(const char name[], Factory factory) { 328 SkASSERT(name); 329 SkASSERT(factory); 330 331 static bool gOnce; 332 if (!gOnce) { 333 gCount = 0; 334 gOnce = true; 335 } 336 337 SkASSERT(gCount < MAX_PAIR_COUNT); 338 339 gPairs[gCount].fName = name; 340 gPairs[gCount].fFactory = factory; 341 gCount += 1; 342} 343 344SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { 345 const Pair* pairs = gPairs; 346 for (int i = gCount - 1; i >= 0; --i) { 347 if (strcmp(pairs[i].fName, name) == 0) { 348 return pairs[i].fFactory; 349 } 350 } 351 return NULL; 352} 353 354const char* SkFlattenable::FactoryToName(Factory fact) { 355 const Pair* pairs = gPairs; 356 for (int i = gCount - 1; i >= 0; --i) { 357 if (pairs[i].fFactory == fact) { 358 return pairs[i].fName; 359 } 360 } 361 return NULL; 362} 363 364bool SkFlattenable::toDumpString(SkString* str) const { 365 return false; 366} 367 368