浏览代码

Creature animations in 16 bpp.

Michał W. Urbańczyk 15 年之前
父节点
当前提交
f76e28ee95
共有 8 个文件被更改,包括 268 次插入288 次删除
  1. 38 42
      client/CCreatureAnimation.cpp
  2. 4 0
      client/CCreatureAnimation.h
  3. 5 0
      client/GUIBase.cpp
  4. 9 0
      client/GUIBase.h
  5. 9 45
      client/GUIClasses.cpp
  6. 4 8
      client/GUIClasses.h
  7. 162 192
      client/SDL_Extensions.cpp
  8. 37 1
      client/SDL_Extensions.h

+ 38 - 42
client/CCreatureAnimation.cpp

@@ -2,6 +2,7 @@
 #include "../hch/CLodHandler.h"
 #include "../lib/VCMI_Lib.h"
 #include <assert.h>
+#include "SDL_Extensions.h"
 
 /*
  * CCreatureAnimation.cpp, part of VCMI engine
@@ -150,11 +151,10 @@ void CCreatureAnimation::playOnce(int type)
 	once = true;
 }
 
-int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, unsigned char animCount, bool IncrementFrame, bool yellowBorder, bool blueBorder, SDL_Rect * destRect)
-{
-	if(dest->format->BytesPerPixel<3)
-		return -1; //not enough depth
 
+template<int bpp>
+int CCreatureAnimation::nextFrameT(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool IncrementFrame /*= true*/, bool yellowBorder /*= false*/, bool blueBorder /*= false*/, SDL_Rect * destRect /*= NULL*/)
+{
 	//increasing frame numer
 	int SIndex = curFrame;
 	if(IncrementFrame)
@@ -167,7 +167,7 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
 		i, FullHeight,FullWidth,
 		TotalRowLength; // length of read segment
 	unsigned char SegmentType, SegmentLength;
-	
+
 	i=BaseOffset=SEntries[SIndex].offset;
 	int prSize=readNormalNr<4>(i,FDef);i+=4;//TODO use me
 	int defType2 = readNormalNr<4>(i,FDef);i+=4;
@@ -229,7 +229,7 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
 				}
 
 				int xB = (attacker ? ftcp%FullWidth : FullWidth - ftcp%FullWidth - 1) + x;
-				
+
 
 				unsigned char aCountMod = (animCount & 0x20) ? ((animCount & 0x1e)>>1)<<4 : 0x0f - ((animCount & 0x1e)>>1)<<4;
 
@@ -239,15 +239,8 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
 					{
 						if(!destRect || (destRect->x <= xB && destRect->x + destRect->w > xB ))
 						{
-							if (SegmentType == 0xFF)
-							{
-								putPixel(dest, xB + yB*dest->w, palette[FDef[BaseOffset+k]], FDef[BaseOffset+k], yellowBorder, blueBorder, aCountMod);
-							}
-							else
-							{
-								putPixel(dest, xB + yB*dest->w, palette[SegmentType], SegmentType, yellowBorder, blueBorder, aCountMod);
-							}
-
+							const ui8 colorNr = SegmentType == 0xff ? FDef[BaseOffset+k] : SegmentType;
+							putPixel<bpp>(dest, xB + yB*dest->w, palette[colorNr], colorNr, yellowBorder, blueBorder, aCountMod);
 						}
 					}
 					ftcp++; //increment pos
@@ -279,6 +272,19 @@ int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker
 	return 0;
 }
 
+int CCreatureAnimation::nextFrame(SDL_Surface *dest, int x, int y, bool attacker, unsigned char animCount, bool IncrementFrame, bool yellowBorder, bool blueBorder, SDL_Rect * destRect)
+{
+	switch(dest->format->BytesPerPixel)
+	{
+	case 2: return nextFrameT<2>(dest, x, y, attacker, animCount, IncrementFrame, yellowBorder, blueBorder, destRect);
+	case 3: return nextFrameT<3>(dest, x, y, attacker, animCount, IncrementFrame, yellowBorder, blueBorder, destRect);
+	case 4: return nextFrameT<4>(dest, x, y, attacker, animCount, IncrementFrame, yellowBorder, blueBorder, destRect);
+	default:
+		tlog1 << (int)dest->format->BitsPerPixel << " bpp is not supported!!!\n";
+		return -1;
+	}
+}
+
 int CCreatureAnimation::framesInGroup(int group) const
 {
 	if(frameGroups.find(group) == frameGroups.end())
@@ -291,6 +297,7 @@ CCreatureAnimation::~CCreatureAnimation()
 	delete [] FDef;
 }
 
+template<int bpp>
 inline void CCreatureAnimation::putPixel(
 	SDL_Surface * dest,
 	const int & ftcp,
@@ -306,39 +313,21 @@ inline void CCreatureAnimation::putPixel(
 		Uint8 * p = (Uint8*)dest->pixels + ftcp*dest->format->BytesPerPixel;
 		if(palc > 7) //normal color
 		{
-			p[0] = color.B;
-			p[1] = color.G;
-			p[2] = color.R;
+			ColorPutter<bpp, 0>::PutColor(p, color.R, color.G, color.B);
 		}
 		else if((yellowBorder || blueBorder) && (palc == 6 || palc == 7)) //dark yellow border
 		{
 			if(blueBorder)
-			{
-				p[0] = 0x0f + animCount;
-				p[1] = 0x0f + animCount;
-				p[2] = 0;
-			}
+				ColorPutter<bpp, 0>::PutColor(p, 0, 0x0f + animCount, 0x0f + animCount);
 			else
-			{
-				p[0] = 0;
-				p[1] = 0x0f + animCount;
-				p[2] = 0x0f + animCount;
-			}
+				ColorPutter<bpp, 0>::PutColor(p, 0x0f + animCount, 0x0f + animCount, 0);
 		}
 		else if((yellowBorder || blueBorder) && (palc == 5)) //yellow border
 		{
 			if(blueBorder)
-			{
-				p[0] = color.R - 0xf0 + animCount;
-				p[1] = color.G - 0xf0 + animCount;
-				p[2] = color.B;
-			}
+				ColorPutter<bpp, 0>::PutColor(p, color.B, color.G - 0xf0 + animCount, color.R - 0xf0 + animCount); //shouldnt it be reversed? its bgr instead of rgb
 			else
-			{
-				p[0] = color.B;
-				p[1] = color.G - 0xf0 + animCount;
-				p[2] = color.R - 0xf0 + animCount;
-			}
+				ColorPutter<bpp, 0>::PutColor(p, color.R - 0xf0 + animCount, color.G - 0xf0 + animCount, color.B);
 		}
 		else if(palc < 5) //shadow
 		{ 
@@ -367,10 +356,17 @@ inline void CCreatureAnimation::putPixel(
 				alpha = 255;
 				break;
 			}
-			//alpha counted
-			p[0] = (p[0] * alpha)>>8;
-			p[1] = (p[1] * alpha)>>8;
-			p[2] = (p[2] * alpha)>>8;
+
+			if(bpp != 3 && bpp != 4)
+			{
+				ColorPutter<bpp, 0>::PutColor(p, 0, 0, 0, alpha);
+			}
+			else
+			{
+				p[0] = (p[0] * alpha)>>8;
+				p[1] = (p[1] * alpha)>>8;
+				p[2] = (p[2] * alpha)>>8;
+			}
 		}
 	}
 }

+ 4 - 0
client/CCreatureAnimation.h

@@ -43,6 +43,7 @@ private:
 		return ret;
 	}
 
+	template<int bpp>
 	void putPixel(
                 SDL_Surface * dest,
                 const int & ftcp,
@@ -68,6 +69,9 @@ public:
 	void setType(int type); //sets type of animation and cleares framecount
 	int getType() const; //returns type of animation
 
+
+	template<int bpp>
+	int nextFrameT(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next 
 	int nextFrame(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool incrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next 
 	int nextFrameMiddle(SDL_Surface * dest, int x, int y, bool attacker, unsigned char animCount, bool IncrementFrame = true, bool yellowBorder = false, bool blueBorder = false, SDL_Rect * destRect = NULL); //0 - success, any other - error //print next 
 	void incrementFrame();

+ 5 - 0
client/GUIBase.cpp

@@ -982,4 +982,9 @@ CIntObject * moveChild(CIntObject *obj, CIntObject *from, CIntObject *to, bool a
 Rect Rect::createCentered( int w, int h )
 {
 	return Rect(screen->w/2 - w/2, screen->h/2 - h/2, w, h);
+}
+
+Rect Rect::around(const Rect &r, int width /*= 1*/) /*creates rect around another */
+{
+	return Rect(r.x - width, r.y - width, r.w + width * 2, r.h + width * 2);
 }

+ 9 - 0
client/GUIBase.h

@@ -138,7 +138,16 @@ struct Rect : public SDL_Rect
 		w = r.w;
 		h = r.h;
 	}
+	explicit Rect(const SDL_Surface * const &surf)
+	{
+		x = y = 0;
+		w = surf->w;
+		h = surf->h;
+	}
+
 	static Rect createCentered(int w, int h);
+	static Rect around(const Rect &r, int width = 1); //creates rect around another
+
 	bool isIn(int qx, int qy) const //determines if given point lies inside rect
 	{
 		if (qx > x   &&   qx<x+w   &&   qy>y   &&   qy<y+h)

+ 9 - 45
client/GUIClasses.cpp

@@ -988,51 +988,22 @@ void CSelectableComponent::clickLeft(tribool down, bool previousState)
 			onSelect();
 	}
 }
-void CSelectableComponent::init(SDL_Surface * Border)
+void CSelectableComponent::init()
 {
-	SDL_Surface * symb = SComponent::getImg();
-	myBitmap = CSDL_Ext::newSurface(symb->w+2,symb->h+2,screen);
-	SDL_SetColorKey(myBitmap,SDL_SRCCOLORKEY,SDL_MapRGB(myBitmap->format,0,255,255));
-	blitAt(symb,1,1,myBitmap);
-	if (Border) //use custom border
-	{
-		border = Border;
-		customB = true;
-	}
-	else //we need to draw border
-	{
-		customB = false;
-		border = CSDL_Ext::newSurface(symb->w+2,symb->h+2,screen);
-		SDL_FillRect(border,NULL,0x00FFFF);
-		for (int i=0;i<border->w;i++)
-		{
-			SDL_PutPixelWithoutRefresh(border,i,0,239,215,123);
-			SDL_PutPixelWithoutRefresh(border,i,(border->h)-1,239,215,123);
-		}
-		for (int i=0;i<border->h;i++)
-		{
-			SDL_PutPixelWithoutRefresh(border,0,i,239,215,123);
-			SDL_PutPixelWithoutRefresh(border,(border->w)-1,i,239,215,123);
-		}
-		SDL_SetColorKey(border,SDL_SRCCOLORKEY,SDL_MapRGB(border->format,0,255,255));
-	}
 	selected = false;
 }
-CSelectableComponent::CSelectableComponent(const Component &c, boost::function<void()> OnSelect, SDL_Surface * Border)
+CSelectableComponent::CSelectableComponent(const Component &c, boost::function<void()> OnSelect)
 :SComponent(c),onSelect(OnSelect)
 {
-	init(Border);
+	init();
 }
-CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect, SDL_Surface * Border)
+CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect)
 :SComponent(Type,Sub,Val),onSelect(OnSelect)
 {
-	init(Border);
+	init();
 }
 CSelectableComponent::~CSelectableComponent()
 {
-	SDL_FreeSurface(myBitmap);
-	if (!customB)
-		SDL_FreeSurface(border);
 }
 void CSelectableComponent::activate()
 {
@@ -1046,20 +1017,10 @@ void CSelectableComponent::deactivate()
 	SComponent::deactivate();
 	deactivateLClick();
 }
-SDL_Surface * CSelectableComponent::getImg()
-{
-	return myBitmap;
-}
 void CSelectableComponent::select(bool on)
 {
 	if(on != selected)
 	{
-		SDL_FillRect(myBitmap,NULL,0x000000);
-		blitAt(SComponent::getImg(),1,1,myBitmap);
-		if (on)
-		{
-			blitAt(border,0,0,myBitmap);
-		}
 		selected = on;
 		return;
 	}
@@ -1070,7 +1031,10 @@ void CSelectableComponent::select(bool on)
 }
 void CSelectableComponent::show(SDL_Surface * to)
 {
-	blitAt(myBitmap,pos.x,pos.y,to);
+	blitAt(getImg(),pos.x,pos.y,to);
+	if(selected)
+		CSDL_Ext::drawBorder(to, Rect::around(Rect(getImg())), int3(239,215,123));
+	
 	printAtMiddleWB(subtitle,pos.x+pos.w/2,pos.y+pos.h+25,FONT_SMALL,12,zwykly,to);
 }
 

+ 4 - 8
client/GUIClasses.h

@@ -166,7 +166,7 @@ public:
 	virtual ~SComponent(){}; //d-tor
 
 	void clickRight(tribool down, bool previousState); //call-in
-	virtual SDL_Surface * getImg();
+	SDL_Surface * getImg();
 	virtual void show(SDL_Surface * to);
 	virtual void activate();
 	virtual void deactivate();
@@ -186,21 +186,17 @@ class CSelectableComponent : public SComponent, public KeyShortcut
 {
 public:
 	bool selected; //if true, this component is selected
-
-	bool customB; //TODO: comment me
-	SDL_Surface * border, *myBitmap;
 	boost::function<void()> onSelect; //function called on selection change
 
 	void clickLeft(tribool down, bool previousState); //call-in
-	void init(SDL_Surface * Border);
-	CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect = 0, SDL_Surface * Border=NULL); //c-tor
-	CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0, SDL_Surface * Border=NULL); //c-tor
+	void init();
+	CSelectableComponent(Etype Type, int Sub, int Val, boost::function<void()> OnSelect = 0); //c-tor
+	CSelectableComponent(const Component &c, boost::function<void()> OnSelect = 0); //c-tor
 	~CSelectableComponent(); //d-tor
 	virtual void show(SDL_Surface * to);
 	void activate();
 	void deactivate();
 	void select(bool on);
-	SDL_Surface * getImg(); //returns myBitmap
 };
 class CGarrisonInt;
 class CGarrisonSlot : public CIntObject

+ 162 - 192
client/SDL_Extensions.cpp

@@ -24,71 +24,143 @@
 
 
 template<int bpp, int incrementPtr>
-struct ColorPutter
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
 {
-	static void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
-	{
-		if(incrementPtr == 0)
-		{
-			ptr[0] = B;
-			ptr[1] = G;
-			ptr[2] = R;
-		}
-		else if(incrementPtr == 1)
-		{
-			*ptr++ = B;
-			*ptr++ = G;
-			*ptr++ = R;
+	PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
+}
 
-			if(bpp == 4)
-				*ptr++ = 0;
-		}
-		else if(incrementPtr == -1)
-		{
-			if(bpp == 4)
-				*(--ptr) = 0;
+template<int bpp, int incrementPtr>
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const SDL_Color & Color)
+{
+	PutColor(ptr, Color.r, Color.g, Color.b);
+}
 
-			*(--ptr) = R;
-			*(--ptr) = G;
-			*(--ptr) = B;
-		}
-		else
-		{
-			assert(0);
-		}
+template<int bpp, int incrementPtr>
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+{
+	switch (A)
+	{
+	case 255:
+		ptr += bpp * incrementPtr;
+		return;
+	case 0:
+		PutColor(ptr, R, G, B);
+		return;
+	case 128:  // optimized
+		PutColor(ptr,	((Uint16)R + (Uint16)ptr[2]) >> 1, 
+			((Uint16)G + (Uint16)ptr[1]) >> 1, 
+			((Uint16)B + (Uint16)ptr[0]) >> 1);
+		return;
+	default:
+		PutColor(ptr, R, G, B, A);
+		return;
 	}
+}
 
-	static void PutColor(Uint8 *&ptr, const SDL_Color & Color)
+template<int bpp, int incrementPtr>
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+{
+	PutColor(ptr,	(((Uint32)ptr[2]-(Uint32)R)*(Uint32)A) >> 8 + (Uint32)R, 
+		(((Uint32)ptr[1]-(Uint32)G)*(Uint32)A) >> 8 + (Uint32)G, 
+		(((Uint32)ptr[0]-(Uint32)B)*(Uint32)A) >> 8 + (Uint32)B);
+}
+
+
+template<int bpp, int incrementPtr>
+STRONG_INLINE void ColorPutter<bpp, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
+{
+	if(incrementPtr == 0)
 	{
-		PutColor(ptr, Color.r, Color.g, Color.b);
+		ptr[0] = B;
+		ptr[1] = G;
+		ptr[2] = R;
 	}
-};
+	else if(incrementPtr == 1)
+	{
+		*ptr++ = B;
+		*ptr++ = G;
+		*ptr++ = R;
+
+		if(bpp == 4)
+			*ptr++ = 0;
+	}
+	else if(incrementPtr == -1)
+	{
+		if(bpp == 4)
+			*(--ptr) = 0;
 
+		*(--ptr) = R;
+		*(--ptr) = G;
+		*(--ptr) = B;
+	}
+	else
+	{
+		assert(0);
+	}
+}
 
 template <int incrementPtr>
-struct ColorPutter<2, incrementPtr>
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
 {
-	static void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B)
-	{
-		if(incrementPtr == -1)
-			ptr -= 2;
+	if(incrementPtr == -1)
+		ptr -= 2;
 
-		Uint16 * const px = (Uint16*)ptr;
-		*px = (B>>3) + ((G>>2) << 5) + ((R>>3) << 11); //drop least significant bits of 24 bpp encoded color
+	Uint16 * const px = (Uint16*)ptr;
+	*px = (B>>3) + ((G>>2) << 5) + ((R>>3) << 11); //drop least significant bits of 24 bpp encoded color
 
-		if(incrementPtr == 1)
-			ptr += 2; //bpp
-	}
+	if(incrementPtr == 1)
+		ptr += 2; //bpp
+}
 
-	static void PutColor(Uint8 *&ptr, const SDL_Color & Color)
+template <int incrementPtr>
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+{
+	switch (A)
 	{
-		PutColor(ptr, Color.r, Color.g, Color.b);
+	case 255:
+		ptr += 2 * incrementPtr;
+		return;
+	case 0:
+		PutColor(ptr, R, G, B);
+		return;
+	default:
+		PutColor(ptr, R, G, B, A);
+		return;
 	}
-};
+}
 
-Uint8 *getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y);
-const TColorPutter getPutterFor(SDL_Surface  * const &dest, bool incrementing);
+template <int incrementPtr>
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A)
+{
+	const int rbit = 5, gbit = 6, bbit = 5; //bits per color
+	const int rmask = 0xF800, gmask = 0x7E0, bmask = 0x1F;
+	const int rshift = 11, gshift = 5, bshift = 0;
+
+	const Uint8 r5 = (*((Uint16 *)ptr) & rmask) >> rshift,
+		b5 = (*((Uint16 *)ptr) & bmask) >> bshift,
+		g5 = (*((Uint16 *)ptr) & gmask) >> gshift;
+
+	const Uint32 r8 = (r5 << (8 - rbit)) | (r5 >> (2*rbit - 8)),
+		g8 = (g5 << (8 - gbit)) | (g5 >> (2*gbit - 8)),
+		b8 = (b5 << (8 - bbit)) | (b5 >> (2*bbit - 8));
+
+	PutColor(ptr, 
+		(((r8-R)*A) >> 8) + R,
+		(((g8-G)*A) >> 8) + G,
+		(((b8-B)*A) >> 8) + B);
+}
 
+template <int incrementPtr>
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color)
+{
+	PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
+}
+
+template <int incrementPtr>
+STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColor(Uint8 *&ptr, const SDL_Color & Color)
+{
+	PutColor(ptr, Color.r, Color.g, Color.b);
+}
 
 SDL_Surface * CSDL_Ext::newSurface(int w, int h, SDL_Surface * mod) //creates new surface, with flags/format same as in surface given
 {
@@ -780,11 +852,9 @@ void CSDL_Ext::blitWithRotate3WithAlpha(const SDL_Surface *src, const SDL_Rect *
 		sp += src->w - dstRect->w;
 	}
 }
-
-int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
+template<int bpp>
+int CSDL_Ext::blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
 {
-	const int bpp = dst->format->BytesPerPixel;
-
 	if (src && src->format->BytesPerPixel==1 && dst && (bpp==3 || bpp==4 || bpp==2)) //everything's ok
 	{
 		SDL_Rect fulldst;
@@ -886,141 +956,15 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * src
 			Uint8 *colory = (Uint8*)src->pixels + srcy*src->pitch + srcx;
 			Uint8 *py = (Uint8*)dst->pixels + dstRect->y*dst->pitch + dstRect->x*bpp;
 
-			if(dst->format->Rshift==16)	//such as screen
-			{
-				for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
-				{
-					Uint8 *color = colory;
-					Uint8 *p = py;
-
-					for(int x=w; x; x--, p += bpp)
-					{
-						const SDL_Color tbc = colors[*color++]; //color to blit
-
-						switch (tbc.unused)
-						{
-							case 255:
-								// ~59% of calls
-								break;
-							case 0:
-								// ~37% of calls
-								p[0] = tbc.b;
-								p[1] = tbc.g;
-								p[2] = tbc.r;
-								break;
-							case 128:  // optimized
-								// ~3.5% of calls
-								p[0] = ((Uint16)tbc.b + (Uint16)p[0]) >> 1;
-								p[1] = ((Uint16)tbc.g + (Uint16)p[1]) >> 1;
-								p[2] = ((Uint16)tbc.r + (Uint16)p[2]) >> 1;
-								break;
-							default:
-								// ~0.5% of calls
-								p[0] = ((((Uint32)p[0]-(Uint32)tbc.b)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.b);
-								p[1] = ((((Uint32)p[1]-(Uint32)tbc.g)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.g);
-								p[2] = ((((Uint32)p[2]-(Uint32)tbc.r)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.r);
-								//p[2] = ((Uint32)tbc.unused*(Uint32)p[2] + (Uint32)tbc.r*(Uint32)(255-tbc.unused))>>8; //red
-								//p[1] = ((Uint32)tbc.unused*(Uint32)p[1] + (Uint32)tbc.g*(Uint32)(255-tbc.unused))>>8; //green
-								//p[0] = ((Uint32)tbc.unused*(Uint32)p[0] + (Uint32)tbc.b*(Uint32)(255-tbc.unused))>>8; //blue
-								break;
-						}
-					}
-				}
-			}
-			else if(dst->format->Rshift==0)	//like in most surfaces
+			for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
 			{
-				for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
-				{
-					Uint8 *color = colory;
-					Uint8 *p = py;
-
-					for(int x=w; x; x--, p += bpp)
-					{
-						const SDL_Color tbc = colors[*color++]; //color to blit
-
-						// According analyze, the values of tbc.unused are fixed,
-						// and the approximate ratios are as following:
-						//
-						// tbc.unused	numbers
-						// 192			    2679
-						// 164			  326907
-						// 82			  705590
-						// 214			 1292625
-						// 128			 4842923
-						// 0			72138078
-						// 255			77547326
-						//
-						// By making use of such characteristic, we may implement a
-						// very fast algorithm for heroes3 without loose much quality.
-						switch (tbc.unused)
-						{
-							case 255:
-								break;
-							case 0:
-								p[0] = tbc.r;
-								p[1] = tbc.g;
-								p[2] = tbc.b;
-								break;
-							case 128:  // optimized
-								p[0] = ((Uint16)tbc.r + (Uint16)p[0]) >> 1;
-								p[1] = ((Uint16)tbc.g + (Uint16)p[1]) >> 1;
-								p[2] = ((Uint16)tbc.b + (Uint16)p[2]) >> 1;
-								break;
-							default:
-								p[0] = ((((Uint32)p[0]-(Uint32)tbc.r)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.r);
-								p[1] = ((((Uint32)p[1]-(Uint32)tbc.g)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.g);
-								p[2] = ((((Uint32)p[2]-(Uint32)tbc.b)*(Uint32)tbc.unused) >> 8 + (Uint32)tbc.b);
-								//p[0] = ((Uint32)tbc.unused*(Uint32)p[0] + (Uint32)tbc.r*(Uint32)(255-tbc.unused))>>8; //red
-								//p[1] = ((Uint32)tbc.unused*(Uint32)p[1] + (Uint32)tbc.g*(Uint32)(255-tbc.unused))>>8; //green
-								//p[2] = ((Uint32)tbc.unused*(Uint32)p[2] + (Uint32)tbc.b*(Uint32)(255-tbc.unused))>>8; //blue
-								break;
-						}
-					}
-				}
-			}
-			else if(dst->format->Rshift == 11)
-			{
-				const int rbit = 5, gbit = 6, bbit = 5; //bits per color
-				const int rmask = 0xF800, gmask = 0x7E0, bmask = 0x1F;
-				const int rshift = 11, gshift = 5, bshift = 0;
+				Uint8 *color = colory;
+				Uint8 *p = py;
 
-				for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch)
+				for(int x = w; x; x--)
 				{
-					Uint8 *color = colory;
-					Uint8 *p = py;
-
-					for(int x=w; x; x--, p += bpp)
-					{
-						const SDL_Color tbc = colors[*color++]; //color to blit
-						switch (tbc.unused)
-						{
-						case 255:
-							break;
-						case 0:
-							ColorPutter<2, 0>::PutColor(p, tbc.r,tbc.g,tbc.b);
-							break;
-// 						case 128:  // optimized
-// 							ColorPutter<2, 0>::PutColor(p, tbc.r,tbc.g,tbc.b);
-// // 							p[0] = ((Uint16)tbc.r + (Uint16)p[0]) >> 1;
-// // 							p[1] = ((Uint16)tbc.g + (Uint16)p[1]) >> 1;
-// // 							p[2] = ((Uint16)tbc.b + (Uint16)p[2]) >> 1;
-// 							break;
-						default:
-							const Uint8 r5 = (*((Uint16 *)p) & rmask) >> rshift,
-								b5 = (*((Uint16 *)p) & bmask) >> bshift,
-								g5 = (*((Uint16 *)p) & gmask) >> gshift;
-
-							const Uint32 r8 = (r5 << (8 - rbit)) | (r5 >> (2*rbit - 8)),
-								g8 = (g5 << (8 - gbit)) | (g5 >> (2*gbit - 8)),
-								b8 = (b5 << (8 - bbit)) | (b5 >> (2*bbit - 8));
-
-							ColorPutter<2, 0>::PutColor(p, 
-								(((r8-tbc.r)*tbc.unused) >> 8) + tbc.r,
-								(((g8-tbc.g)*tbc.unused) >> 8) + tbc.g,
-								(((b8-tbc.b)*tbc.unused) >> 8) + tbc.b);
-							break;
-						}
-					}
+					const SDL_Color &tbc = colors[*color++]; //color to blit
+					ColorPutter<bpp, +1>::PutColorAlphaSwitch(p, tbc.r, tbc.g, tbc.b, tbc.unused);
 				}
 			}
 			SDL_UnlockSurface(dst);
@@ -1029,6 +973,19 @@ int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * src
 	return 0;
 }
 
+int CSDL_Ext::blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect)
+{
+	switch(dst->format->BytesPerPixel)
+	{
+	case 2: return blit8bppAlphaTo24bppT<2>(src, srcRect, dst, dstRect);
+	case 3: return blit8bppAlphaTo24bppT<3>(src, srcRect, dst, dstRect);
+	case 4: return blit8bppAlphaTo24bppT<4>(src, srcRect, dst, dstRect);
+	default:
+		tlog1 << (int)dst->format->BitsPerPixel << " bpp is not supported!!!\n";
+		return -1;
+	}
+}
+
 Uint32 CSDL_Ext::colorToUint32(const SDL_Color * color)
 {
 	Uint32 ret = 0;
@@ -1123,14 +1080,16 @@ int readNormalNr (std::istream &in, int bytCon)
 	return ret;
 }
 
-const TColorPutter getPutterFor(SDL_Surface * const &dest, bool incrementing)
+const TColorPutter CSDL_Ext::getPutterFor(SDL_Surface * const &dest, int incrementing)
 {
 #define CASE_BPP(BytesPerPixel)							\
 case BytesPerPixel:									\
-	if(incrementing)									\
-	return ColorPutter<BytesPerPixel, 1>::PutColor;	\
+	if(incrementing > 0)								\
+		return ColorPutter<BytesPerPixel, 1>::PutColor;	\
+	else if(incrementing == 0)							\
+		return ColorPutter<BytesPerPixel, 0>::PutColor;	\
 	else												\
-	return ColorPutter<BytesPerPixel, 0>::PutColor;	\
+		return ColorPutter<BytesPerPixel, -1>::PutColor;\
 	break;
 
 	switch(dest->format->BytesPerPixel)
@@ -1140,15 +1099,26 @@ case BytesPerPixel:									\
 		CASE_BPP(4)
 	default:
 		tlog1 << (int)dest->format->BitsPerPixel << "bpp is not supported!\n";
-		break;
+		return NULL;
 	}
-#undef CASE_BPP
 
-	assert(0);
-	return NULL;
 }
 
-Uint8 * getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y)
+const TColorPutterAlpha CSDL_Ext::getPutterAlphaFor(SDL_Surface * const &dest, int incrementing)
+{
+	switch(dest->format->BytesPerPixel)
+	{
+		CASE_BPP(2)
+		CASE_BPP(3)
+		CASE_BPP(4)
+	default:
+		tlog1 << (int)dest->format->BitsPerPixel << "bpp is not supported!\n";
+		return NULL;
+	}
+#undef CASE_BPP
+}
+
+Uint8 * CSDL_Ext::getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y)
 {
 	return (Uint8 *)srf->pixels + y * srf->pitch + x * srf->format->BytesPerPixel;
 }

+ 37 - 1
client/SDL_Extensions.h

@@ -18,6 +18,15 @@
  *
  */
 
+
+//A macro to force inlining some of our functions. Compiler (at least MSVC) is not so smart here-> without that displaying is MUCH slower
+#ifdef _MSC_VER
+	#define STRONG_INLINE __forceinline
+#else
+	//TODO: GCC counterpart?
+	#define STRONG_INLINE inline
+#endif
+
 struct Rect;
 
 extern SDL_Surface * screen, *screen2, *screenBuf;
@@ -68,6 +77,7 @@ std::string makeNumberShort(IntType number) //the output is a string containing
 }
 
 typedef void (*TColorPutter)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
+typedef void (*TColorPutterAlpha)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
 
 
 inline SDL_Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy)
@@ -80,6 +90,27 @@ inline SDL_Rect genRect(const int & hh, const int & ww, const int & xx, const in
 	return ret;
 }
 
+
+template<int bpp, int incrementPtr>
+struct ColorPutter
+{
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
+	static STRONG_INLINE void PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color);
+};
+
+template <int incrementPtr>
+struct ColorPutter<2, incrementPtr>
+{
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
+	static STRONG_INLINE void PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
+	static STRONG_INLINE void PutColor(Uint8 *&ptr, const SDL_Color & Color);
+	static STRONG_INLINE void PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color);
+};
+
 typedef void (*BlitterWithRotationVal)(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);
 
 namespace CSDL_Ext
@@ -100,6 +131,10 @@ namespace CSDL_Ext
 	void alphaTransform(SDL_Surface * src); //adds transparency and shadows (partial handling only; see examples of using for details)
 	bool isTransparent(SDL_Surface * srf, int x, int y); //checks if surface is transparent at given position
 
+
+	Uint8 *getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y);
+	const TColorPutter getPutterFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
+	const TColorPutterAlpha getPutterAlphaFor(SDL_Surface  * const &dest, int incrementing); //incrementing: -1, 0, 1
 	BlitterWithRotationVal getBlitterWithRotation(SDL_Surface *dest);
 	BlitterWithRotationVal getBlitterWithRotationAndAlpha(SDL_Surface *dest);
 
@@ -116,7 +151,8 @@ namespace CSDL_Ext
 	template<int bpp> void blitWithRotate2WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests
 	template<int bpp> void blitWithRotate3WithAlpha(const SDL_Surface *src, const SDL_Rect * srcRect, SDL_Surface * dst, const SDL_Rect * dstRect);//srcRect is not used, works with 8bpp sources and 24bpp dests
 
-
+	template<int bpp>
+	int blit8bppAlphaTo24bppT(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
 	int blit8bppAlphaTo24bpp(const SDL_Surface * src, const SDL_Rect * srcRect, SDL_Surface * dst, SDL_Rect * dstRect); //blits 8 bpp surface with alpha channel to 24 bpp surface
 	Uint32 colorToUint32(const SDL_Color * color); //little endian only