#include "SkFlattenable.h" #include "SkTypeface.h" void SkFlattenable::flatten(SkFlattenableWriteBuffer&) { /* we don't write anything at the moment, but this allows our subclasses to not know that, since we want them to always call INHERITED::flatten() in their code. */ } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// SkFlattenableReadBuffer::SkFlattenableReadBuffer() { fRCArray = NULL; fRCCount = 0; fTFArray = NULL; fTFCount = 0; fFactoryArray = NULL; fFactoryCount = 0; } SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data) : INHERITED(data, 1024 * 1024) { fRCArray = NULL; fRCCount = 0; fTFArray = NULL; fTFCount = 0; fFactoryArray = NULL; fFactoryCount = 0; } SkFlattenableReadBuffer::SkFlattenableReadBuffer(const void* data, size_t size) : INHERITED(data, size) { fRCArray = NULL; fRCCount = 0; fTFArray = NULL; fTFCount = 0; fFactoryArray = NULL; fFactoryCount = 0; } SkTypeface* SkFlattenableReadBuffer::readTypeface() { uint32_t index = this->readU32(); if (0 == index || index > (unsigned)fTFCount) { if (index) { SkDebugf("====== typeface index %d\n", index); } return NULL; } else { SkASSERT(fTFArray); return fTFArray[index - 1]; } } SkRefCnt* SkFlattenableReadBuffer::readRefCnt() { uint32_t index = this->readU32(); if (0 == index || index > (unsigned)fRCCount) { return NULL; } else { SkASSERT(fRCArray); return fRCArray[index - 1]; } } SkFlattenable* SkFlattenableReadBuffer::readFlattenable() { SkFlattenable::Factory factory = NULL; if (fFactoryCount > 0) { uint32_t index = this->readU32(); if (index > 0) { index -= 1; SkASSERT(index < (unsigned)fFactoryCount); factory = fFactoryArray[index]; // if we recorded an index, but failed to get a factory, we need // to skip the flattened data in the buffer if (NULL == factory) { uint32_t size = this->readU32(); this->skip(size); // fall through and return NULL for the object } } } else { factory = (SkFlattenable::Factory)readFunctionPtr(); } SkFlattenable* obj = NULL; if (factory) { uint32_t sizeRecorded = this->readU32(); uint32_t offset = this->offset(); obj = (*factory)(*this); // check that we read the amount we expected uint32_t sizeRead = this->offset() - offset; if (sizeRecorded != sizeRead) { // we could try to fix up the offset... sk_throw(); } } return obj; } void* SkFlattenableReadBuffer::readFunctionPtr() { void* proc; this->read(&proc, sizeof(proc)); return proc; } /////////////////////////////////////////////////////////////////////////////// SkFlattenableWriteBuffer::SkFlattenableWriteBuffer(size_t minSize) : INHERITED(minSize) { fFlags = (Flags)0; fRCRecorder = NULL; fTFRecorder = NULL; fFactoryRecorder = NULL; } SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { fRCRecorder->safeUnref(); fTFRecorder->safeUnref(); fFactoryRecorder->safeUnref(); } SkRefCntRecorder* SkFlattenableWriteBuffer::setRefCntRecorder( SkRefCntRecorder* rec) { SkRefCnt_SafeAssign(fRCRecorder, rec); return rec; } SkRefCntRecorder* SkFlattenableWriteBuffer::setTypefaceRecorder( SkRefCntRecorder* rec) { SkRefCnt_SafeAssign(fTFRecorder, rec); return rec; } SkFactoryRecorder* SkFlattenableWriteBuffer::setFactoryRecorder( SkFactoryRecorder* rec) { SkRefCnt_SafeAssign(fFactoryRecorder, rec); return rec; } void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) { if (NULL == obj || NULL == fTFRecorder) { this->write32(0); } else { this->write32(fTFRecorder->record(obj)); } } void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) { if (NULL == obj || NULL == fRCRecorder) { this->write32(0); } else { this->write32(fRCRecorder->record(obj)); } } void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { SkFlattenable::Factory factory = NULL; if (flattenable) { factory = flattenable->getFactory(); } if (fFactoryRecorder) { this->write32(fFactoryRecorder->record(factory)); } else { this->writeFunctionPtr((void*)factory); } if (factory) { // make room for the size of the flatttened object (void)this->reserve(sizeof(uint32_t)); // record the current size, so we can subtract after the object writes. uint32_t offset = this->size(); // now flatten the object flattenable->flatten(*this); uint32_t objSize = this->size() - offset; // record the obj's size *this->peek32(offset - sizeof(uint32_t)) = objSize; } } void SkFlattenableWriteBuffer::writeFunctionPtr(void* proc) { *(void**)this->reserve(sizeof(void*)) = proc; } /////////////////////////////////////////////////////////////////////////////// SkRefCntRecorder::~SkRefCntRecorder() { // call this now, while our decPtr() is sill in scope this->reset(); } void SkRefCntRecorder::incPtr(void* ptr) { ((SkRefCnt*)ptr)->ref(); } void SkRefCntRecorder::decPtr(void* ptr) { ((SkRefCnt*)ptr)->unref(); } /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////////// #define MAX_PAIR_COUNT 64 struct Pair { const char* fName; SkFlattenable::Factory fFactory; }; static int gCount; static Pair gPairs[MAX_PAIR_COUNT]; void SkFlattenable::Register(const char name[], Factory factory) { SkASSERT(name); SkASSERT(factory); static bool gOnce; if (!gOnce) { gCount = 0; gOnce = true; } SkASSERT(gCount < MAX_PAIR_COUNT); gPairs[gCount].fName = name; gPairs[gCount].fFactory = factory; gCount += 1; } SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { const Pair* pairs = gPairs; for (int i = gCount - 1; i >= 0; --i) { if (strcmp(pairs[i].fName, name) == 0) { return pairs[i].fFactory; } } return NULL; } const char* SkFlattenable::FactoryToName(Factory fact) { const Pair* pairs = gPairs; for (int i = gCount - 1; i >= 0; --i) { if (pairs[i].fFactory == fact) { return pairs[i].fName; } } return NULL; } bool SkFlattenable::toDumpString(SkString* str) const { return false; }