| #include "SkFlattenable.h" |
| #include "SkTypeface.h" |
| |
| #include "SkMatrix.h" |
| #include "SkRegion.h" |
| |
| void SkReadMatrix(SkReader32* reader, SkMatrix* matrix) { |
| size_t size = matrix->unflatten(reader->peek()); |
| SkASSERT(SkAlign4(size) == size); |
| (void)reader->skip(size); |
| } |
| |
| void SkWriteMatrix(SkWriter32* writer, const SkMatrix& matrix) { |
| size_t size = matrix.flatten(NULL); |
| SkASSERT(SkAlign4(size) == size); |
| matrix.flatten(writer->reserve(size)); |
| } |
| |
| void SkReadRegion(SkReader32* reader, SkRegion* rgn) { |
| size_t size = rgn->unflatten(reader->peek()); |
| SkASSERT(SkAlign4(size) == size); |
| (void)reader->skip(size); |
| } |
| |
| void SkWriteRegion(SkWriter32* writer, const SkRegion& rgn) { |
| size_t size = rgn.flatten(NULL); |
| SkASSERT(SkAlign4(size) == size); |
| rgn.flatten(writer->reserve(size)); |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| 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; |
| fRCSet = NULL; |
| fTFSet = NULL; |
| fFactorySet = NULL; |
| } |
| |
| SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { |
| SkSafeUnref(fRCSet); |
| SkSafeUnref(fTFSet); |
| SkSafeUnref(fFactorySet); |
| } |
| |
| SkRefCntSet* SkFlattenableWriteBuffer::setRefCntRecorder(SkRefCntSet* rec) { |
| SkRefCnt_SafeAssign(fRCSet, rec); |
| return rec; |
| } |
| |
| SkRefCntSet* SkFlattenableWriteBuffer::setTypefaceRecorder(SkRefCntSet* rec) { |
| SkRefCnt_SafeAssign(fTFSet, rec); |
| return rec; |
| } |
| |
| SkFactorySet* SkFlattenableWriteBuffer::setFactoryRecorder(SkFactorySet* rec) { |
| SkRefCnt_SafeAssign(fFactorySet, rec); |
| return rec; |
| } |
| |
| void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) { |
| if (NULL == obj || NULL == fTFSet) { |
| this->write32(0); |
| } else { |
| this->write32(fTFSet->add(obj)); |
| } |
| } |
| |
| void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) { |
| if (NULL == obj || NULL == fRCSet) { |
| this->write32(0); |
| } else { |
| this->write32(fRCSet->add(obj)); |
| } |
| } |
| |
| void SkFlattenableWriteBuffer::writeFlattenable(SkFlattenable* flattenable) { |
| SkFlattenable::Factory factory = NULL; |
| if (flattenable) { |
| factory = flattenable->getFactory(); |
| } |
| |
| if (fFactorySet) { |
| this->write32(fFactorySet->add(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; |
| } |
| |
| /////////////////////////////////////////////////////////////////////////////// |
| |
| SkRefCntSet::~SkRefCntSet() { |
| // call this now, while our decPtr() is sill in scope |
| this->reset(); |
| } |
| |
| void SkRefCntSet::incPtr(void* ptr) { |
| ((SkRefCnt*)ptr)->ref(); |
| } |
| |
| void SkRefCntSet::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; |
| } |
| |