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