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:
parent
afe84deb03
commit
f76e28ee95
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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);
|
||||
}
|
@ -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)
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user