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