/* * Copyright 2011 Google Inc. * * Use of this source code is governed by a BSD-style license that can be * found in the LICENSE file. */ #include "SkFlattenable.h" #include "SkTypeface.h" SK_DEFINE_INST_COUNT(SkFlattenable) /////////////////////////////////////////////////////////////////////////////// void SkFlattenable::flatten(SkFlattenableWriteBuffer&) const { /* 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; fFactoryTDArray = NULL; fFactoryArray = NULL; fFactoryCount = 0; // Set default values. These should be explicitly set by our client // via setFlags() if the buffer came from serialization. fFlags = 0; #ifdef SK_SCALAR_IS_FLOAT fFlags |= kScalarIsFloat_Flag; #endif if (8 == sizeof(void*)) { fFlags |= kPtrIs64Bit_Flag; } } /////////////////////////////////////////////////////////////////////////////// SkNamedFactorySet::SkNamedFactorySet() : fNextAddedFactory(0) {} uint32_t SkNamedFactorySet::find(SkFlattenable::Factory factory) { uint32_t index = fFactorySet.find(factory); if (index > 0) { return index; } const char* name = SkFlattenable::FactoryToName(factory); if (NULL == name) { return 0; } *fNames.append() = name; return fFactorySet.add(factory); } const char* SkNamedFactorySet::getNextAddedFactoryName() { if (fNextAddedFactory < fNames.count()) { return fNames[fNextAddedFactory++]; } return NULL; } /////////////////////////////////////////////////////////////////////////////// SkFlattenableWriteBuffer::SkFlattenableWriteBuffer() { fFlags = (Flags)0; fRCSet = NULL; fTFSet = NULL; fFactorySet = NULL; fNamedFactorySet = NULL; } SkFlattenableWriteBuffer::~SkFlattenableWriteBuffer() { SkSafeUnref(fRCSet); SkSafeUnref(fTFSet); SkSafeUnref(fFactorySet); SkSafeUnref(fNamedFactorySet); } 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); if (fNamedFactorySet != NULL) { fNamedFactorySet->unref(); fNamedFactorySet = NULL; } return rec; } SkNamedFactorySet* SkFlattenableWriteBuffer::setNamedFactoryRecorder( SkNamedFactorySet* rec) { SkRefCnt_SafeAssign(fNamedFactorySet, rec); if (fFactorySet != NULL) { fFactorySet->unref(); fFactorySet = NULL; } return rec; } void SkFlattenableWriteBuffer::writeRefCnt(SkRefCnt* obj) { SkASSERT(!isCrossProcess()); if (NULL == obj || NULL == fRCSet) { this->write32(0); } else { this->write32(fRCSet->add(obj)); } } void SkFlattenableWriteBuffer::writeTypeface(SkTypeface* obj) { if (NULL == obj || NULL == fTFSet) { this->write32(0); } else { this->write32(fTFSet->add(obj)); } } /////////////////////////////////////////////////////////////////////////////// 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 1024 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; } #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) static void report_no_entries(const char* functionName) { if (!gCount) { SkDebugf("%s has no registered name/factory pairs." " Call SkGraphics::Init() at process initialization time.", functionName); } } #endif SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) report_no_entries(__FUNCTION__); #endif 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) { #if !SK_ALLOW_STATIC_GLOBAL_INITIALIZERS && defined(SK_DEBUG) report_no_entries(__FUNCTION__); #endif const Pair* pairs = gPairs; for (int i = gCount - 1; i >= 0; --i) { if (pairs[i].fFactory == fact) { return pairs[i].fName; } } return NULL; }