2011-12-14 00:23:17 +03:00
# pragma once
2011-12-22 16:05:19 +03:00
# include <SDL_video.h>
# include <SDL_ttf.h>
# include "../../lib/int3.h"
# include "../FontBase.h"
# include "Geometries.h"
2009-04-16 14:14:13 +03:00
2009-04-15 17:03:31 +03:00
/*
* SDL_Extensions . h , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
2009-04-16 14:14:13 +03:00
*/
2010-08-12 08:22:48 +03:00
//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
2011-02-06 19:26:27 +02:00
# elif __GNUC__
2012-05-15 11:47:11 +03:00
# define STRONG_INLINE inline __attribute__((always_inline))
2010-08-12 08:22:48 +03:00
# else
# define STRONG_INLINE inline
# endif
2011-11-17 03:24:27 +03:00
# if SDL_VERSION_ATLEAST(1,3,0)
# define SDL_GetKeyState SDL_GetKeyboardState
# endif
2010-08-05 14:02:18 +03:00
struct Rect ;
2009-05-25 02:21:55 +03:00
extern SDL_Surface * screen , * screen2 , * screenBuf ;
2009-04-16 14:14:13 +03:00
void blitAt ( SDL_Surface * src , int x , int y , SDL_Surface * dst = screen ) ;
2009-06-17 12:38:03 +03:00
void blitAt ( SDL_Surface * src , const SDL_Rect & pos , SDL_Surface * dst = screen ) ;
2009-04-16 14:14:13 +03:00
void updateRect ( SDL_Rect * rect , SDL_Surface * scr = screen ) ;
bool isItIn ( const SDL_Rect * rect , int x , int y ) ;
2009-04-17 17:01:22 +03:00
2011-12-22 16:05:19 +03:00
namespace Colors
{
2012-02-16 20:10:58 +03:00
SDL_Color createColor ( Uint8 r , Uint8 g , Uint8 b , Uint8 a = 0 ) ;
2011-12-22 16:05:19 +03:00
const SDL_Color Jasmine = createColor ( 229 , 215 , 123 , 0 ) ; // http://en.wikipedia.org/wiki/Jasmine_%28color%29
const SDL_Color Cornsilk = createColor ( 255 , 243 , 222 , 0 ) ; // http://en.wikipedia.org/wiki/Shades_of_white
const SDL_Color MetallicGold = createColor ( 173 , 142 , 66 ) ; // http://en.wikipedia.org/wiki/Gold_%28color%29
const SDL_Color Maize = createColor ( 242 , 226 , 110 ) ; // http://en.wikipedia.org/wiki/Maize_%28color%29
}
2009-06-26 18:41:19 +03:00
template < typename IntType >
std : : string makeNumberShort ( IntType number ) //the output is a string containing at most 5 characters [4 if positive] (eg. intead 10000 it gives 10k)
{
int initialLength ;
bool negative = ( number < 0 ) ;
std : : ostringstream ost , rets ;
ost < < number ;
initialLength = ost . str ( ) . size ( ) ;
if ( negative )
{
if ( initialLength < = 4 )
return ost . str ( ) ;
}
else
{
if ( initialLength < = 5 )
return ost . str ( ) ;
}
2011-12-14 00:23:17 +03:00
//make the number int
2009-06-26 18:41:19 +03:00
char symbol [ ] = { ' G ' , ' M ' , ' k ' } ;
if ( negative ) number = ( - number ) ; //absolute value
for ( int divisor = 1000000000 , it = 0 ; divisor > 1 ; divisor / = 1000 , + + it )
{
if ( number > = divisor )
{
if ( negative ) rets < < ' - ' ;
rets < < ( number / divisor ) < < symbol [ it ] ;
return rets . str ( ) ;
}
}
2012-04-22 10:32:45 +03:00
throw std : : runtime_error ( " We shouldn't be here - makeNumberShort " ) ;
2009-06-26 18:41:19 +03:00
}
2010-08-05 14:02:18 +03:00
typedef void ( * TColorPutter ) ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B ) ;
2010-08-12 08:22:48 +03:00
typedef void ( * TColorPutterAlpha ) ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B , const Uint8 & A ) ;
2010-08-05 14:02:18 +03:00
2009-06-26 18:41:19 +03:00
2009-04-16 14:14:13 +03:00
inline SDL_Rect genRect ( const int & hh , const int & ww , const int & xx , const int & yy )
{
SDL_Rect ret ;
ret . h = hh ;
ret . w = ww ;
ret . x = xx ;
ret . y = yy ;
return ret ;
}
2010-08-05 14:02:18 +03:00
2011-02-06 19:26:27 +02:00
//TODO: inlining will work only if functions are defined in each compilation unit (like placing them in headers)
//however here PutColor defined in SDL_Extensions.cpp, but used in CAnimation.cpp and CCreatureAnimation.cpp
2010-08-12 08:22:48 +03:00
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 ) ;
2011-02-20 11:24:53 +02:00
static STRONG_INLINE void PutColorRow ( Uint8 * & ptr , const SDL_Color & Color , size_t count ) ;
2010-08-12 08:22:48 +03:00
} ;
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 ) ;
2011-02-20 11:24:53 +02:00
static STRONG_INLINE void PutColorRow ( Uint8 * & ptr , const SDL_Color & Color , size_t count ) ;
2010-08-12 08:22:48 +03:00
} ;
2010-08-05 14:02:18 +03:00
typedef void ( * BlitterWithRotationVal ) ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ;
2009-04-16 14:14:13 +03:00
namespace CSDL_Ext
{
2010-08-23 18:16:40 +03:00
void blitSurface ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect ) ;
2010-08-23 19:13:30 +03:00
void fillRect ( SDL_Surface * dst , SDL_Rect * dstrect , Uint32 color ) ;
2009-04-16 14:14:13 +03:00
extern SDL_Surface * std32bppSurface ;
2010-08-05 14:02:18 +03:00
void SDL_PutPixelWithoutRefresh ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A = 255 ) ;
void SDL_PutPixelWithoutRefreshIfInSurf ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A = 255 ) ;
2009-04-16 14:14:13 +03:00
SDL_Surface * rotate01 ( SDL_Surface * toRot ) ; //vertical flip
SDL_Surface * hFlip ( SDL_Surface * toRot ) ; //horizontal flip
SDL_Surface * rotate02 ( SDL_Surface * toRot ) ; //rotate 90 degrees left
SDL_Surface * rotate03 ( SDL_Surface * toRot ) ; //rotate 180 degrees
2009-04-17 17:01:22 +03:00
SDL_Cursor * SurfaceToCursor ( SDL_Surface * image , int hx , int hy ) ; //creates cursor from bitmap
2009-04-16 14:14:13 +03:00
Uint32 SDL_GetPixel ( SDL_Surface * surface , const int & x , const int & y , bool colorByte = false ) ;
2009-04-17 17:01:22 +03:00
SDL_Color SDL_GetPixelColor ( SDL_Surface * surface , int x , int y ) ; //returns color of pixel at given position
2009-06-07 01:47:23 +03:00
void alphaTransform ( SDL_Surface * src ) ; //adds transparency and shadows (partial handling only; see examples of using for details)
2010-02-18 14:44:59 +02:00
bool isTransparent ( SDL_Surface * srf , int x , int y ) ; //checks if surface is transparent at given position
2009-12-22 23:53:50 +02:00
2010-08-12 08:22:48 +03:00
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
2010-08-05 14:02:18 +03:00
BlitterWithRotationVal getBlitterWithRotation ( SDL_Surface * dest ) ;
BlitterWithRotationVal getBlitterWithRotationAndAlpha ( SDL_Surface * dest ) ;
template < int bpp > void blitWithRotateClip ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipVal ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipWithAlpha ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotateClipValWithAlpha ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation ) ; //srcRect is not used, works with 8bpp sources and 24bpp dests preserving clip_rect
template < int bpp > void blitWithRotate1 ( 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 blitWithRotate2 ( 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 blitWithRotate3 ( 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 blitWithRotate1WithAlpha ( 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 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
2009-12-22 23:53:50 +02:00
2010-08-12 08:22:48 +03:00
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
2009-05-28 05:58:29 +03:00
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
2009-04-16 14:14:13 +03:00
Uint32 colorToUint32 ( const SDL_Color * color ) ; //little endian only
2009-08-17 11:50:31 +03:00
2011-12-22 16:05:19 +03:00
void printAtWB ( const std : : string & text , int x , int y , EFonts font , int charpr , SDL_Color kolor = Colors : : Cornsilk , SDL_Surface * dst = screen ) ;
void printAt ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor = Colors : : Cornsilk , SDL_Surface * dst = screen ) ;
void printTo ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor = Colors : : Cornsilk , SDL_Surface * dst = screen ) ;
void printAtMiddle ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor = Colors : : Cornsilk , SDL_Surface * dst = screen ) ;
void printAtMiddleWB ( const std : : string & text , int x , int y , EFonts font , int charpr , SDL_Color kolor = Colors : : Jasmine , SDL_Surface * dst = screen ) ;
2009-08-17 11:50:31 +03:00
2009-04-16 14:14:13 +03:00
void update ( SDL_Surface * what = screen ) ; //updates whole surface (default - main screen)
2009-09-20 15:47:40 +03:00
void drawBorder ( SDL_Surface * sur , int x , int y , int w , int h , const int3 & color ) ;
void drawBorder ( SDL_Surface * sur , const SDL_Rect & r , const int3 & color ) ;
2011-12-22 16:05:19 +03:00
void drawDashedBorder ( SDL_Surface * sur , const Rect & r , const int3 & color ) ;
2011-12-14 00:23:17 +03:00
void setPlayerColor ( SDL_Surface * sur , ui8 player ) ; //sets correct color of flags; -1 for neutral
2009-04-16 14:14:13 +03:00
std : : string processStr ( std : : string str , std : : vector < std : : string > & tor ) ; //replaces %s in string
SDL_Surface * newSurface ( int w , int h , SDL_Surface * mod = screen ) ; //creates new surface, with flags/format same as in surface given
SDL_Surface * copySurface ( SDL_Surface * mod ) ; //returns copy of given surface
2010-07-15 20:13:17 +03:00
void VflipSurf ( SDL_Surface * surf ) ; //fluipis given surface by vertical axis
2010-08-17 15:48:34 +03:00
void applyEffect ( SDL_Surface * surf , const SDL_Rect * rect , int mode ) ; //mode: 0 - sepia, 1 - grayscale
2012-04-09 05:53:50 +03:00
std : : string trimToFit ( std : : string text , int widthLimit , EFonts font ) ;
2009-04-16 14:14:13 +03:00
} ;
2012-05-15 11:47:11 +03:00
template < int bpp , int incrementPtr >
STRONG_INLINE void ColorPutter < bpp , incrementPtr > : : PutColorAlpha ( Uint8 * & ptr , const SDL_Color & Color )
{
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 )
{
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 ;
}
}
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 )
{
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 bpp , int incrementPtr >
STRONG_INLINE void ColorPutter < bpp , incrementPtr > : : PutColorRow ( Uint8 * & ptr , const SDL_Color & Color , size_t count )
{
Uint32 pixel = ( ( Uint32 ) Color . b < < 0 ) + ( ( Uint32 ) Color . g < < 8 ) + ( ( Uint32 ) Color . r < < 16 ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
memcpy ( ptr , & pixel , bpp ) ;
if ( incrementPtr = = - 1 )
ptr - = bpp ;
if ( incrementPtr = = 1 )
ptr + = bpp ;
}
}
template < int incrementPtr >
STRONG_INLINE void ColorPutter < 2 , incrementPtr > : : 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 )
{
case 255 :
ptr + = 2 * incrementPtr ;
return ;
case 0 :
PutColor ( ptr , R , G , B ) ;
return ;
default :
PutColor ( ptr , R , G , B , A ) ;
return ;
}
}
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 ) ;
}
template < int incrementPtr >
STRONG_INLINE void ColorPutter < 2 , incrementPtr > : : PutColorRow ( Uint8 * & ptr , const SDL_Color & Color , size_t count )
{
//drop least significant bits of 24 bpp encoded color
Uint16 pixel = ( Color . b > > 3 ) + ( ( Color . g > > 2 ) < < 5 ) + ( ( Color . r > > 3 ) < < 11 ) ;
for ( size_t i = 0 ; i < count ; i + + )
{
memcpy ( ptr , & pixel , 2 ) ;
if ( incrementPtr = = - 1 )
ptr - = 2 ;
if ( incrementPtr = = 1 )
ptr + = 2 ;
}
}