| /* | 
 |  * 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 "SkPtrRecorder.h" | 
 | #include "SkReadBuffer.h" | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | #ifdef SK_SUPPORT_LEGACY_DEEPFLATTENING | 
 | bool SkFlattenable::NeedsDeepUnflatten(const SkReadBuffer& buffer) { | 
 |     return buffer.isVersionLT(SkReadBuffer::kFlattenCreateProc_Version); | 
 | } | 
 | #endif | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | 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; | 
 | } | 
 |  | 
 | /////////////////////////////////////////////////////////////////////////////// | 
 |  | 
 | 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_ENTRY_COUNT  1024 | 
 |  | 
 | struct Entry { | 
 |     const char*             fName; | 
 |     SkFlattenable::Factory  fFactory; | 
 |     SkFlattenable::Type     fType; | 
 | }; | 
 |  | 
 | static int gCount; | 
 | static Entry gEntries[MAX_ENTRY_COUNT]; | 
 |  | 
 | void SkFlattenable::Register(const char name[], Factory factory, SkFlattenable::Type type) { | 
 |     SkASSERT(name); | 
 |     SkASSERT(factory); | 
 |  | 
 |     static bool gOnce = false; | 
 |     if (!gOnce) { | 
 |         gCount = 0; | 
 |         gOnce = true; | 
 |     } | 
 |  | 
 |     SkASSERT(gCount < MAX_ENTRY_COUNT); | 
 |  | 
 |     gEntries[gCount].fName = name; | 
 |     gEntries[gCount].fFactory = factory; | 
 |     gEntries[gCount].fType = type; | 
 |     gCount += 1; | 
 | } | 
 |  | 
 | #ifdef SK_DEBUG | 
 | static void report_no_entries(const char* functionName) { | 
 |     if (!gCount) { | 
 |         SkDebugf("%s has no registered name/factory/type entries." | 
 |                  " Call SkFlattenable::InitializeFlattenablesIfNeeded() before using gEntries", | 
 |                  functionName); | 
 |     } | 
 | } | 
 | #endif | 
 |  | 
 | SkFlattenable::Factory SkFlattenable::NameToFactory(const char name[]) { | 
 |     InitializeFlattenablesIfNeeded(); | 
 | #ifdef SK_DEBUG | 
 |     report_no_entries(__FUNCTION__); | 
 | #endif | 
 |     const Entry* entries = gEntries; | 
 |     for (int i = gCount - 1; i >= 0; --i) { | 
 |         if (strcmp(entries[i].fName, name) == 0) { | 
 |             return entries[i].fFactory; | 
 |         } | 
 |     } | 
 |     return NULL; | 
 | } | 
 |  | 
 | bool SkFlattenable::NameToType(const char name[], SkFlattenable::Type* type) { | 
 |     SkASSERT(type); | 
 |     InitializeFlattenablesIfNeeded(); | 
 | #ifdef SK_DEBUG | 
 |     report_no_entries(__FUNCTION__); | 
 | #endif | 
 |     const Entry* entries = gEntries; | 
 |     for (int i = gCount - 1; i >= 0; --i) { | 
 |         if (strcmp(entries[i].fName, name) == 0) { | 
 |             *type = entries[i].fType; | 
 |             return true; | 
 |         } | 
 |     } | 
 |     return false; | 
 | } | 
 |  | 
 | const char* SkFlattenable::FactoryToName(Factory fact) { | 
 |     InitializeFlattenablesIfNeeded(); | 
 | #ifdef SK_DEBUG | 
 |     report_no_entries(__FUNCTION__); | 
 | #endif | 
 |     const Entry* entries = gEntries; | 
 |     for (int i = gCount - 1; i >= 0; --i) { | 
 |         if (entries[i].fFactory == fact) { | 
 |             return entries[i].fName; | 
 |         } | 
 |     } | 
 |     return NULL; | 
 | } |