truelight@7433: /* $Id$ */ truelight@7433: truelight@7433: #ifndef BLITTER_FACTORY_HPP truelight@7433: #define BLITTER_FACTORY_HPP truelight@7433: truelight@7433: #include "base.hpp" truelight@7433: #include truelight@7433: #include truelight@7433: truelight@7433: /** truelight@7433: * The base factory, keeping track of all blitters. truelight@7433: */ truelight@7433: class BlitterFactoryBase { truelight@7433: private: truelight@7433: char *name; truelight@7433: typedef std::map Blitters; truelight@7433: truelight@7433: static Blitters &GetBlitters() truelight@7433: { truelight@7433: static Blitters &s_blitters = *new Blitters(); truelight@7433: return s_blitters; truelight@7433: } truelight@7433: truelight@7433: static Blitter **GetActiveBlitter() truelight@7433: { truelight@7433: static Blitter *s_blitter = NULL; truelight@7433: return &s_blitter; truelight@7433: } truelight@7433: truelight@7433: protected: truelight@7433: /** truelight@7433: * Register a blitter internally, based on his name. truelight@7433: * @param name the name of the blitter. truelight@7433: * @note an assert() will be trigger if 2 blitters with the same name try to register. truelight@7433: */ truelight@7433: void RegisterBlitter(const char *name) truelight@7433: { truelight@7433: /* Don't register nameless Blitters */ truelight@7433: if (name == NULL) return; truelight@7433: truelight@7433: this->name = strdup(name); truelight@7750: #if !defined(NDEBUG) truelight@7750: /* NDEBUG disables asserts and gives a warning: unused variable 'P' */ truelight@7750: std::pair P = truelight@7750: #endif /* !NDEBUG */ truelight@7750: GetBlitters().insert(Blitters::value_type(name, this)); truelight@7433: assert(P.second); truelight@7433: } truelight@7433: truelight@7433: public: truelight@7433: BlitterFactoryBase() : truelight@7433: name(NULL) truelight@7433: {} truelight@7433: truelight@7433: virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); } truelight@7433: truelight@7433: /** truelight@7433: * Find the requested blitter and return his class. truelight@7433: * @param name the blitter to select. truelight@7433: * @post Sets the blitter so GetCurrentBlitter() returns it too. truelight@7433: */ truelight@7433: static Blitter *SelectBlitter(const char *name) truelight@7433: { truelight@7433: if (GetBlitters().size() == 0) return NULL; truelight@7433: truelight@7433: Blitters::iterator it = GetBlitters().begin(); truelight@7433: for (; it != GetBlitters().end(); it++) { truelight@7433: BlitterFactoryBase *b = (*it).second; truelight@7433: if (strcasecmp(name, b->name) == 0) { truelight@7433: Blitter *newb = b->CreateInstance(); rubidium@7587: delete *GetActiveBlitter(); truelight@7433: *GetActiveBlitter() = newb; truelight@7433: return newb; truelight@7433: } truelight@7433: } truelight@7433: return NULL; truelight@7433: } truelight@7433: truelight@7433: /** truelight@7433: * Get the current active blitter (always set by calling SelectBlitter). truelight@7433: */ truelight@7433: static Blitter *GetCurrentBlitter() truelight@7433: { truelight@7433: return *GetActiveBlitter(); truelight@7433: } truelight@7433: truelight@7433: truelight@7433: static char *GetBlittersInfo(char *p, const char *last) truelight@7433: { truelight@7433: p += snprintf(p, last - p, "List of blitters:\n"); truelight@7433: Blitters::iterator it = GetBlitters().begin(); truelight@7433: for (; it != GetBlitters().end(); it++) { truelight@7433: BlitterFactoryBase *b = (*it).second; truelight@7433: p += snprintf(p, last - p, "%18s: %s\n", b->name, b->GetDescription()); truelight@7433: } truelight@7433: p += snprintf(p, last - p, "\n"); truelight@7433: truelight@7433: return p; truelight@7433: } truelight@7433: truelight@7433: /** truelight@7433: * Get a nice description of the blitter-class. truelight@7433: */ truelight@7433: virtual const char *GetDescription() = 0; truelight@7433: truelight@7433: /** truelight@7433: * Create an instance of this Blitter-class. truelight@7433: */ truelight@7433: virtual Blitter *CreateInstance() = 0; truelight@7433: }; truelight@7433: truelight@7433: /** truelight@7433: * A template factory, so ->GetName() works correctly. This because else some compiler will complain. truelight@7433: */ truelight@7433: template truelight@7433: class BlitterFactory: public BlitterFactoryBase { truelight@7433: public: truelight@7433: BlitterFactory() { this->RegisterBlitter(((T *)this)->GetName()); } truelight@7433: truelight@7433: /** truelight@7433: * Get the long, human readable, name for the Blitter-class. truelight@7433: */ truelight@7433: const char *GetName(); truelight@7433: }; truelight@7433: truelight@7433: #endif /* BLITTER_FACTORY_HPP */