From f76e28ee95a6bf67f921be299be8dd36095c5b7a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Micha=C5=82=20W=2E=20Urba=C5=84czyk?= Date: Thu, 12 Aug 2010 05:22:48 +0000 Subject: [PATCH] Creature animations in 16 bpp. --- client/CCreatureAnimation.cpp | 80 ++++---- client/CCreatureAnimation.h | 4 + client/GUIBase.cpp | 5 + client/GUIBase.h | 9 + client/GUIClasses.cpp | 54 +---- client/GUIClasses.h | 12 +- client/SDL_Extensions.cpp | 362 ++++++++++++++++------------------ client/SDL_Extensions.h | 38 +++- 8 files changed, 272 insertions(+), 292 deletions(-) diff --git a/client/CCreatureAnimation.cpp b/client/CCreatureAnimation.cpp index efc9a6554..ee78aedba 100644 --- a/client/CCreatureAnimation.cpp +++ b/client/CCreatureAnimation.cpp @@ -2,6 +2,7 @@ #include "../hch/CLodHandler.h" #include "../lib/VCMI_Lib.h" #include +#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 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(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 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::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::PutColor(p, 0, 0x0f + animCount, 0x0f + animCount); else - { - p[0] = 0; - p[1] = 0x0f + animCount; - p[2] = 0x0f + animCount; - } + ColorPutter::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::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::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::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; + } } } } diff --git a/client/CCreatureAnimation.h b/client/CCreatureAnimation.h index 260dc7ebf..0fb1d18bc 100644 --- a/client/CCreatureAnimation.h +++ b/client/CCreatureAnimation.h @@ -43,6 +43,7 @@ private: return ret; } + template 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 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(); diff --git a/client/GUIBase.cpp b/client/GUIBase.cpp index c682054d6..29c5271e6 100644 --- a/client/GUIBase.cpp +++ b/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); } \ No newline at end of file diff --git a/client/GUIBase.h b/client/GUIBase.h index 364d1536a..936b34653 100644 --- a/client/GUIBase.h +++ b/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 && qxy && qyw+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;iw;i++) - { - SDL_PutPixelWithoutRefresh(border,i,0,239,215,123); - SDL_PutPixelWithoutRefresh(border,i,(border->h)-1,239,215,123); - } - for (int i=0;ih;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 OnSelect, SDL_Surface * Border) +CSelectableComponent::CSelectableComponent(const Component &c, boost::function OnSelect) :SComponent(c),onSelect(OnSelect) { - init(Border); + init(); } -CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function OnSelect, SDL_Surface * Border) +CSelectableComponent::CSelectableComponent(Etype Type, int Sub, int Val, boost::function 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); } diff --git a/client/GUIClasses.h b/client/GUIClasses.h index 97787fbbf..3dc1978e9 100644 --- a/client/GUIClasses.h +++ b/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 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 OnSelect = 0, SDL_Surface * Border=NULL); //c-tor - CSelectableComponent(const Component &c, boost::function OnSelect = 0, SDL_Surface * Border=NULL); //c-tor + void init(); + CSelectableComponent(Etype Type, int Sub, int Val, boost::function OnSelect = 0); //c-tor + CSelectableComponent(const Component &c, boost::function 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 diff --git a/client/SDL_Extensions.cpp b/client/SDL_Extensions.cpp index 2d2a2fe92..f79da5a99 100644 --- a/client/SDL_Extensions.cpp +++ b/client/SDL_Extensions.cpp @@ -24,71 +24,143 @@ template -struct ColorPutter +STRONG_INLINE void ColorPutter::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color) { - static void PutColor(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B) + PutColor(ptr, Color.r, Color.g, Color.b, Color.unused); +} + +template +STRONG_INLINE void ColorPutter::PutColor(Uint8 *&ptr, const SDL_Color & Color) +{ + PutColor(ptr, Color.r, Color.g, Color.b); +} + +template +STRONG_INLINE void ColorPutter::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A) +{ + switch (A) { - if(incrementPtr == 0) - { - 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); - } + 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 +STRONG_INLINE void ColorPutter::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 +STRONG_INLINE void ColorPutter::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 -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; + + 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 +} + +template +STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlphaSwitch(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A) +{ + switch (A) { - 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 - - if(incrementPtr == 1) - ptr += 2; //bpp + case 255: + ptr += 2 * incrementPtr; + return; + case 0: + PutColor(ptr, R, G, B); + return; + default: + PutColor(ptr, R, G, B, A); + return; } +} - static void PutColor(Uint8 *&ptr, const SDL_Color & Color) - { - PutColor(ptr, Color.r, Color.g, Color.b); - } -}; +template +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; -Uint8 *getPxPtr(const SDL_Surface * const &srf, const int & x, const int & y); -const TColorPutter getPutterFor(SDL_Surface * const &dest, bool incrementing); + 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 +STRONG_INLINE void ColorPutter<2, incrementPtr>::PutColorAlpha(Uint8 *&ptr, const SDL_Color & Color) +{ + PutColor(ptr, Color.r, Color.g, Color.b, Color.unused); +} + +template +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 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) { - for(int y=h; y; y--, colory+=src->pitch, py+=dst->pitch) + Uint8 *color = colory; + Uint8 *p = py; + + 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: - // ~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) - { - 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; - - 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: - 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::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::PutColor; \ + if(incrementing > 0) \ + return ColorPutter::PutColor; \ + else if(incrementing == 0) \ + return ColorPutter::PutColor; \ else \ - return ColorPutter::PutColor; \ + return ColorPutter::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; } diff --git a/client/SDL_Extensions.h b/client/SDL_Extensions.h index e802787c3..d83a0579d 100644 --- a/client/SDL_Extensions.h +++ b/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 +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 +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 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 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 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