src/blitter/blitter.hpp
branchgamebalance
changeset 9913 e79cd19772dd
parent 9912 1ac8aac92385
equal deleted inserted replaced
9912:1ac8aac92385 9913:e79cd19772dd
     1 /* $Id$ */
       
     2 
       
     3 /** @file blitter.hpp */
       
     4 
       
     5 #ifndef BLITTER_HPP
       
     6 #define BLITTER_HPP
       
     7 
       
     8 #include "../spriteloader/spriteloader.hpp"
       
     9 #include "../spritecache.h"
       
    10 #include <string>
       
    11 #include <map>
       
    12 
       
    13 enum BlitterMode {
       
    14 	BM_NORMAL,
       
    15 	BM_COLOUR_REMAP,
       
    16 	BM_TRANSPARENT,
       
    17 };
       
    18 
       
    19 /**
       
    20  * How all blitters should look like. Extend this class to make your own.
       
    21  */
       
    22 class Blitter {
       
    23 public:
       
    24 	struct BlitterParams {
       
    25 		const void *sprite;      ///< Pointer to the sprite how ever the encoder stored it
       
    26 		const byte *remap;       ///< XXX -- Temporary storage for remap array
       
    27 
       
    28 		int skip_left, skip_top; ///< How much pixels of the source to skip on the left and top (based on zoom of dst)
       
    29 		int width, height;       ///< The width and height in pixels that needs to be drawn to dst
       
    30 		int sprite_width;        ///< Real width of the sprite
       
    31 		int sprite_height;       ///< Real height of the sprite
       
    32 		int left, top;           ///< The offset in the 'dst' in pixels to start drawing
       
    33 
       
    34 		void *dst;               ///< Destination buffer
       
    35 		int pitch;               ///< The pitch of the destination buffer
       
    36 	};
       
    37 
       
    38 	typedef void *AllocatorProc(size_t size);
       
    39 
       
    40 	/**
       
    41 	 * Get the screen depth this blitter works for.
       
    42 	 *  This is either: 8, 16, 24 or 32.
       
    43 	 */
       
    44 	virtual uint8 GetScreenDepth() = 0;
       
    45 
       
    46 	/**
       
    47 	 * Draw an image to the screen, given an amount of params defined above.
       
    48 	 */
       
    49 	virtual void Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom) = 0;
       
    50 
       
    51 	/**
       
    52 	 * Convert a sprite from the loader to our own format.
       
    53 	 */
       
    54 	virtual Sprite *Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator) = 0;
       
    55 
       
    56 	virtual ~Blitter() { }
       
    57 };
       
    58 
       
    59 /**
       
    60  * The base factory, keeping track of all blitters.
       
    61  */
       
    62 class BlitterFactoryBase {
       
    63 private:
       
    64 	char *name;
       
    65 	typedef std::map<std::string, BlitterFactoryBase *> Blitters;
       
    66 
       
    67 	static Blitters &GetBlitters()
       
    68 	{
       
    69 		static Blitters &s_blitters = *new Blitters();
       
    70 		return s_blitters;
       
    71 	}
       
    72 
       
    73 	static Blitter **GetActiveBlitter()
       
    74 	{
       
    75 		static Blitter *s_blitter = NULL;
       
    76 		return &s_blitter;
       
    77 	}
       
    78 
       
    79 protected:
       
    80 	/**
       
    81 	 * Register a blitter internally, based on his name.
       
    82 	 * @param name the name of the blitter.
       
    83 	 * @note an assert() will be trigger if 2 blitters with the same name try to register.
       
    84 	 */
       
    85 	void RegisterBlitter(const char *name)
       
    86 	{
       
    87 		/* Don't register nameless Blitters */
       
    88 		if (name == NULL) return;
       
    89 
       
    90 		this->name = strdup(name);
       
    91 		std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(name, this));
       
    92 		assert(P.second);
       
    93 	}
       
    94 
       
    95 public:
       
    96 	BlitterFactoryBase() :
       
    97 		name(NULL)
       
    98 	{}
       
    99 
       
   100 	virtual ~BlitterFactoryBase() { if (this->name != NULL) GetBlitters().erase(this->name); free(this->name); }
       
   101 
       
   102 	/**
       
   103 	 * Find the requested blitter and return his class.
       
   104 	 * @param name the blitter to select.
       
   105 	 * @post Sets the blitter so GetCurrentBlitter() returns it too.
       
   106 	 */
       
   107 	static Blitter *SelectBlitter(const char *name)
       
   108 	{
       
   109 		if (GetBlitters().size() == 0) return NULL;
       
   110 
       
   111 		Blitters::iterator it = GetBlitters().begin();
       
   112 		for (; it != GetBlitters().end(); it++) {
       
   113 			BlitterFactoryBase *b = (*it).second;
       
   114 			if (strcasecmp(name, b->name) == 0) {
       
   115 				Blitter *newb = b->CreateInstance();
       
   116 				*GetActiveBlitter() = newb;
       
   117 				return newb;
       
   118 			}
       
   119 		}
       
   120 		return NULL;
       
   121 	}
       
   122 
       
   123 	/**
       
   124 	 * Get the current active blitter (always set by calling SelectBlitter).
       
   125 	 */
       
   126 	static Blitter *GetCurrentBlitter()
       
   127 	{
       
   128 		return *GetActiveBlitter();
       
   129 	}
       
   130 
       
   131 
       
   132 	static char *GetBlittersInfo(char *p, const char *last)
       
   133 	{
       
   134 		p += snprintf(p, last - p, "List of blitters:\n");
       
   135 		Blitters::iterator it = GetBlitters().begin();
       
   136 		for (; it != GetBlitters().end(); it++) {
       
   137 			BlitterFactoryBase *b = (*it).second;
       
   138 			p += snprintf(p, last - p, "%18s: %s\n", b->name, b->GetDescription());
       
   139 		}
       
   140 		p += snprintf(p, last - p, "\n");
       
   141 
       
   142 		return p;
       
   143 	}
       
   144 
       
   145 	/**
       
   146 	 * Get a nice description of the blitter-class.
       
   147 	 */
       
   148 	virtual const char *GetDescription() = 0;
       
   149 
       
   150 	/**
       
   151 	 * Create an instance of this Blitter-class.
       
   152 	 */
       
   153 	virtual Blitter *CreateInstance() = 0;
       
   154 };
       
   155 
       
   156 /**
       
   157  * A template factory, so ->GetName() works correctly. This because else some compiler will complain.
       
   158  */
       
   159 template <class T>
       
   160 class BlitterFactory: public BlitterFactoryBase {
       
   161 public:
       
   162 	BlitterFactory() { this->RegisterBlitter(((T *)this)->GetName()); }
       
   163 
       
   164 	/**
       
   165 	 * Get the long, human readable, name for the Blitter-class.
       
   166 	 */
       
   167 	const char *GetName();
       
   168 };
       
   169 
       
   170 #endif /* BLITTER_HPP */