1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Creature animations in 16 bpp.

This commit is contained in:
Michał W. Urbańczyk 2010-08-12 05:22:48 +00:00
parent afe84deb03
commit f76e28ee95
8 changed files with 272 additions and 292 deletions

View File

@ -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;
}
}
}
}

View File

@ -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();

View File

@ -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);
}

View File

@ -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)

View File

@ -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);
}

View File

@ -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

View File

@ -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)
PutColor(ptr, Color.r, Color.g, Color.b, Color.unused);
}
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);
}
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)
{
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<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;
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 <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)
{
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 <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;
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 <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)
{
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<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;
}

View File

@ -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