2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2007-06-06 21:26:28 +03:00
# include "SDL_Extensions.h"
2012-05-17 13:44:48 +03:00
# include "SDL_Pixels.h"
2011-12-14 00:23:17 +03:00
2011-12-22 16:05:19 +03:00
# include "../CGameInfo.h"
# include "../CMessage.h"
# include "../CDefHandler.h"
# include "../Graphics.h"
2014-05-21 19:04:34 +03:00
# include "../CMT.h"
2008-02-22 19:47:14 +02:00
2012-11-20 20:53:45 +03:00
const SDL_Color Colors : : YELLOW = { 229 , 215 , 123 , 0 } ;
const SDL_Color Colors : : WHITE = { 255 , 243 , 222 , 0 } ;
const SDL_Color Colors : : METALLIC_GOLD = { 173 , 142 , 66 , 0 } ;
2012-12-19 20:24:53 +03:00
const SDL_Color Colors : : GREEN = { 0 , 255 , 0 , 0 } ;
2014-07-02 21:20:54 +03:00
const SDL_Color Colors : : DEFAULT_KEY_COLOR = { 0 , 255 , 255 , 0 } ;
2012-11-11 15:23:31 +03:00
2014-06-01 18:31:37 +03:00
# if (SDL_MAJOR_VERSION == 2)
void SDL_UpdateRect ( SDL_Surface * surface , int x , int y , int w , int h )
{
Rect rect ( x , y , w , h ) ;
if ( 0 ! = SDL_UpdateTexture ( screenTexture , & rect , surface - > pixels , surface - > pitch ) )
logGlobal - > errorStream ( ) < < __FUNCTION__ < < " SDL_UpdateTexture " < < SDL_GetError ( ) ;
SDL_RenderClear ( mainRenderer ) ;
if ( 0 ! = SDL_RenderCopy ( mainRenderer , screenTexture , NULL , NULL ) )
logGlobal - > errorStream ( ) < < __FUNCTION__ < < " SDL_RenderCopy " < < SDL_GetError ( ) ;
SDL_RenderPresent ( mainRenderer ) ;
}
# endif // VCMI_SDL1
2007-09-30 19:16:00 +03:00
SDL_Surface * CSDL_Ext : : newSurface ( int w , int h , SDL_Surface * mod ) //creates new surface, with flags/format same as in surface given
{
2012-06-15 20:08:19 +03:00
SDL_Surface * ret = SDL_CreateRGBSurface ( mod - > flags , w , h , mod - > format - > BitsPerPixel , mod - > format - > Rmask , mod - > format - > Gmask , mod - > format - > Bmask , mod - > format - > Amask ) ;
if ( mod - > format - > palette )
{
assert ( ret - > format - > palette ) ;
assert ( ret - > format - > palette - > ncolors = = mod - > format - > palette - > ncolors ) ;
memcpy ( ret - > format - > palette - > colors , mod - > format - > palette - > colors , mod - > format - > palette - > ncolors * sizeof ( SDL_Color ) ) ;
}
return ret ;
2007-09-30 19:16:00 +03:00
}
SDL_Surface * CSDL_Ext : : copySurface ( SDL_Surface * mod ) //returns copy of given surface
{
2008-02-09 16:44:32 +02:00
//return SDL_DisplayFormat(mod);
return SDL_ConvertSurface ( mod , mod - > format , mod - > flags ) ;
2007-09-30 19:16:00 +03:00
}
2009-06-26 18:41:19 +03:00
2012-05-18 20:35:46 +03:00
template < int bpp >
SDL_Surface * CSDL_Ext : : createSurfaceWithBpp ( int width , int height )
{
2012-08-06 10:34:37 +03:00
Uint32 rMask = 0 , gMask = 0 , bMask = 0 , aMask = 0 ;
2012-05-18 20:35:46 +03:00
Channels : : px < bpp > : : r . set ( ( Uint8 * ) & rMask , 255 ) ;
Channels : : px < bpp > : : g . set ( ( Uint8 * ) & gMask , 255 ) ;
Channels : : px < bpp > : : b . set ( ( Uint8 * ) & bMask , 255 ) ;
Channels : : px < bpp > : : a . set ( ( Uint8 * ) & aMask , 255 ) ;
2012-05-19 19:22:34 +03:00
return SDL_CreateRGBSurface ( SDL_SWSURFACE , width , height , bpp * 8 , rMask , gMask , bMask , aMask ) ;
2012-05-18 20:35:46 +03:00
}
2007-06-19 18:25:42 +03:00
bool isItIn ( const SDL_Rect * rect , int x , int y )
{
2010-08-28 17:52:20 +03:00
return ( x > rect - > x & & x < rect - > x + rect - > w ) & & ( y > rect - > y & & y < rect - > y + rect - > h ) ;
2007-06-19 18:25:42 +03:00
}
2009-02-08 17:39:26 +02:00
2007-07-23 15:13:33 +03:00
void blitAt ( SDL_Surface * src , int x , int y , SDL_Surface * dst )
2007-06-19 18:25:42 +03:00
{
2008-08-13 03:44:31 +03:00
if ( ! dst ) dst = screen ;
2007-07-11 13:27:42 +03:00
SDL_Rect pom = genRect ( src - > h , src - > w , x , y ) ;
2013-06-26 14:18:27 +03:00
CSDL_Ext : : blitSurface ( src , nullptr , dst , & pom ) ;
2008-01-24 00:15:33 +02:00
}
2009-06-26 18:41:19 +03:00
2009-06-17 12:38:03 +03:00
void blitAt ( SDL_Surface * src , const SDL_Rect & pos , SDL_Surface * dst )
2008-01-24 00:15:33 +02:00
{
2012-11-13 14:52:23 +03:00
if ( src )
blitAt ( src , pos . x , pos . y , dst ) ;
2008-01-24 00:15:33 +02:00
}
2009-06-26 18:41:19 +03:00
2009-05-17 05:43:36 +03:00
// Vertical flip
2013-11-06 16:42:58 +03:00
SDL_Surface * CSDL_Ext : : verticalFlip ( SDL_Surface * toRot )
2007-06-06 21:26:28 +03:00
{
2008-02-06 15:50:40 +02:00
SDL_Surface * ret = SDL_ConvertSurface ( toRot , toRot - > format , toRot - > flags ) ;
2009-05-17 05:43:36 +03:00
const int bpp = ret - > format - > BytesPerPixel ;
2013-11-06 16:42:58 +03:00
char * src = reinterpret_cast < char * > ( toRot - > pixels ) ;
char * dst = reinterpret_cast < char * > ( ret - > pixels ) ;
2009-05-17 05:43:36 +03:00
2013-11-06 16:42:58 +03:00
for ( int i = 0 ; i < ret - > h ; i + + )
2007-06-06 21:26:28 +03:00
{
2013-11-06 16:42:58 +03:00
char * srcPxl = src ;
char * dstPxl = dst + ret - > w * bpp ;
if ( bpp = = 1 )
2007-06-06 21:26:28 +03:00
{
2013-11-06 16:42:58 +03:00
// much faster for 8-bit surfaces (majority of our data)
std : : reverse_copy ( src , src + ret - > pitch , dst ) ;
}
else
{
for ( int j = 0 ; j < ret - > w ; j + + )
2007-06-06 21:26:28 +03:00
{
2013-11-06 16:42:58 +03:00
dstPxl - = bpp ;
std : : copy ( srcPxl , srcPxl + bpp , dstPxl ) ;
srcPxl + = bpp ;
2007-06-06 21:26:28 +03:00
}
}
2013-11-06 16:42:58 +03:00
src + = toRot - > pitch ;
dst + = ret - > pitch ;
2007-06-06 21:26:28 +03:00
}
return ret ;
}
2013-11-06 16:42:58 +03:00
// Horizontal flip
SDL_Surface * CSDL_Ext : : horizontalFlip ( SDL_Surface * toRot )
2007-06-06 21:26:28 +03:00
{
2008-02-06 15:50:40 +02:00
SDL_Surface * ret = SDL_ConvertSurface ( toRot , toRot - > format , toRot - > flags ) ;
2013-11-06 16:42:58 +03:00
char * src = reinterpret_cast < char * > ( toRot - > pixels ) ;
char * dst = reinterpret_cast < char * > ( ret - > pixels ) + ret - > h * ret - > pitch ;
for ( int i = 0 ; i < ret - > h ; i + + )
2007-06-26 15:38:58 +03:00
{
2013-11-06 16:42:58 +03:00
dst - = ret - > pitch ;
std : : copy ( src , src + toRot - > pitch , dst ) ;
src + = toRot - > pitch ;
2007-06-26 15:38:58 +03:00
}
2007-06-06 21:26:28 +03:00
return ret ;
2013-11-06 16:42:58 +03:00
} ;
2008-02-06 15:50:40 +02:00
Uint32 CSDL_Ext : : SDL_GetPixel ( SDL_Surface * surface , const int & x , const int & y , bool colorByte )
2007-06-19 17:41:03 +03:00
{
2012-05-17 13:44:48 +03:00
int bpp = surface - > format - > BytesPerPixel ;
/* Here p is the address to the pixel we want to retrieve */
Uint8 * p = ( Uint8 * ) surface - > pixels + y * surface - > pitch + x * bpp ;
2007-06-19 17:41:03 +03:00
2012-05-17 13:44:48 +03:00
switch ( bpp )
2008-12-23 15:59:03 +02:00
{
2012-05-17 13:44:48 +03:00
case 1 :
2007-06-25 17:55:45 +03:00
if ( colorByte )
return colorToUint32 ( surface - > format - > palette - > colors + ( * p ) ) ;
else
return * p ;
2007-06-19 17:41:03 +03:00
2012-05-17 13:44:48 +03:00
case 2 :
return * ( Uint16 * ) p ;
2007-06-19 17:41:03 +03:00
2012-05-17 13:44:48 +03:00
case 3 :
return p [ 0 ] | p [ 1 ] < < 8 | p [ 2 ] < < 16 ;
case 4 :
return * ( Uint32 * ) p ;
default :
return 0 ; // shouldn't happen, but avoids warnings
}
2007-06-25 17:55:45 +03:00
}
2009-06-07 01:47:23 +03:00
void CSDL_Ext : : alphaTransform ( SDL_Surface * src )
2007-06-25 17:55:45 +03:00
{
2009-07-27 15:29:10 +03:00
assert ( src - > format - > BitsPerPixel = = 8 ) ;
2013-01-10 21:53:49 +03:00
SDL_Color colors [ ] =
{
{ 0 , 0 , 0 , 0 } , { 0 , 0 , 0 , 32 } , { 0 , 0 , 0 , 64 } ,
{ 0 , 0 , 0 , 128 } , { 0 , 0 , 0 , 128 }
} ;
2008-08-02 18:08:03 +03:00
2013-01-10 21:53:49 +03:00
for ( size_t i = 0 ; i < ARRAY_COUNT ( colors ) ; i + + )
{
SDL_Color & palColor = src - > format - > palette - > colors [ i ] ;
palColor = colors [ i ] ;
}
SDL_SetColorKey ( src , SDL_SRCCOLORKEY , 0 ) ;
2007-06-25 17:55:45 +03:00
}
2009-03-26 19:55:10 +02:00
2009-12-22 23:53:50 +02:00
static void prepareOutRect ( SDL_Rect * src , SDL_Rect * dst , const SDL_Rect & clip_rect )
2009-03-26 19:55:10 +02:00
{
2009-12-22 23:53:50 +02:00
const int xoffset = std : : max ( clip_rect . x - dst - > x , 0 ) ,
yoffset = std : : max ( clip_rect . y - dst - > y , 0 ) ;
src - > x + = xoffset ;
src - > y + = yoffset ;
dst - > x + = xoffset ;
dst - > y + = yoffset ;
src - > w = dst - > w = std : : max ( 0 , std : : min ( dst - > w - xoffset , clip_rect . x + clip_rect . w - dst - > x ) ) ;
src - > h = dst - > h = std : : max ( 0 , std : : min ( dst - > h - yoffset , clip_rect . y + clip_rect . h - dst - > y ) ) ;
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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
{
if ( ! rotation )
{
2010-08-23 18:16:40 +03:00
CSDL_Ext : : blitSurface ( src , srcRect , dst , dstRect ) ;
2009-12-22 23:53:50 +02:00
}
else
{
2013-11-07 15:48:41 +03:00
static void ( * blitWithRotate [ ] ) ( const SDL_Surface * , const SDL_Rect * , SDL_Surface * , const SDL_Rect * ) = { blitWithRotate1 < bpp > , blitWithRotate2 < bpp > , blitWithRotate3 < bpp > } ;
2009-12-22 23:53:50 +02:00
prepareOutRect ( srcRect , dstRect , dst - > clip_rect ) ;
blitWithRotate [ rotation - 1 ] ( src , srcRect , dst , dstRect ) ;
}
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : blitWithRotateClipVal ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation )
{
2010-08-05 14:02:18 +03:00
blitWithRotateClip < bpp > ( src , & srcRect , dst , & dstRect , rotation ) ;
2009-12-22 23:53:50 +02:00
}
2012-02-16 20:10:58 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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
{
if ( ! rotation )
{
blit8bppAlphaTo24bpp ( src , srcRect , dst , dstRect ) ;
}
else
{
2013-11-07 15:48:41 +03:00
static void ( * blitWithRotate [ ] ) ( const SDL_Surface * , const SDL_Rect * , SDL_Surface * , const SDL_Rect * ) = { blitWithRotate1WithAlpha < bpp > , blitWithRotate2WithAlpha < bpp > , blitWithRotate3WithAlpha < bpp > } ;
2009-12-22 23:53:50 +02:00
prepareOutRect ( srcRect , dstRect , dst - > clip_rect ) ;
blitWithRotate [ rotation - 1 ] ( src , srcRect , dst , dstRect ) ;
}
}
2012-02-16 20:10:58 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : blitWithRotateClipValWithAlpha ( SDL_Surface * src , SDL_Rect srcRect , SDL_Surface * dst , SDL_Rect dstRect , ui8 rotation )
{
2010-08-05 14:02:18 +03:00
blitWithRotateClipWithAlpha < bpp > ( src , & srcRect , dst , & dstRect , rotation ) ;
2009-03-26 19:55:10 +02:00
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-06-14 02:25:15 +03:00
void CSDL_Ext : : 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 24/32 bpp dests
2008-11-30 02:15:38 +02:00
{
2010-08-05 14:02:18 +03:00
Uint8 * sp = getPxPtr ( src , src - > w - srcRect - > w - srcRect - > x , srcRect - > y ) ;
2009-05-27 07:10:35 +03:00
Uint8 * dporg = ( Uint8 * ) dst - > pixels + dstRect - > y * dst - > pitch + ( dstRect - > x + dstRect - > w ) * bpp ;
const SDL_Color * const colors = src - > format - > palette - > colors ;
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg + = dst - > pitch )
2008-11-30 02:15:38 +02:00
{
2009-05-27 07:10:35 +03:00
Uint8 * dp = dporg ;
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , - 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2008-11-30 02:15:38 +02:00
2009-12-22 23:53:50 +02:00
sp + = src - > w - dstRect - > w ;
}
2009-01-09 15:03:47 +02:00
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-05-28 02:21:34 +03:00
void CSDL_Ext : : 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 24/32 bpp dests
2008-11-30 02:15:38 +02:00
{
2010-08-05 14:02:18 +03:00
Uint8 * sp = getPxPtr ( src , srcRect - > x , src - > h - srcRect - > h - srcRect - > y ) ;
2009-05-28 02:21:34 +03:00
Uint8 * dporg = ( Uint8 * ) dst - > pixels + ( dstRect - > y + dstRect - > h - 1 ) * dst - > pitch + dstRect - > x * bpp ;
const SDL_Color * const colors = src - > format - > palette - > colors ;
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg - = dst - > pitch )
2008-11-30 02:15:38 +02:00
{
2009-05-28 02:21:34 +03:00
Uint8 * dp = dporg ;
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2009-05-28 02:21:34 +03:00
2009-01-09 15:03:47 +02:00
sp + = src - > w - dstRect - > w ;
}
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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 24/32 bpp dests
2009-01-09 15:03:47 +02:00
{
2012-11-11 15:23:31 +03:00
Uint8 * sp = ( Uint8 * ) src - > pixels + ( src - > h - srcRect - > h - srcRect - > y ) * src - > pitch + ( src - > w - srcRect - > w - srcRect - > x ) ;
Uint8 * dporg = ( Uint8 * ) dst - > pixels + ( dstRect - > y + dstRect - > h - 1 ) * dst - > pitch + ( dstRect - > x + dstRect - > w ) * bpp ;
const SDL_Color * const colors = src - > format - > palette - > colors ;
2012-02-16 20:10:58 +03:00
2012-11-11 15:23:31 +03:00
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg - = dst - > pitch )
{
Uint8 * dp = dporg ;
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , - 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2012-02-16 20:10:58 +03:00
2009-12-22 23:53:50 +02:00
sp + = src - > w - dstRect - > w ;
2012-11-11 15:23:31 +03:00
}
2008-11-30 02:15:38 +02:00
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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 24/32 bpp dests
2008-11-30 02:15:38 +02:00
{
2009-12-22 23:53:50 +02:00
Uint8 * sp = ( Uint8 * ) src - > pixels + srcRect - > y * src - > pitch + ( src - > w - srcRect - > w - srcRect - > x ) ;
Uint8 * dporg = ( Uint8 * ) dst - > pixels + dstRect - > y * dst - > pitch + ( dstRect - > x + dstRect - > w ) * bpp ;
2009-05-28 02:43:47 +03:00
const SDL_Color * const colors = src - > format - > palette - > colors ;
2009-12-22 23:53:50 +02:00
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg + = dst - > pitch )
2008-11-30 02:15:38 +02:00
{
2009-05-28 02:43:47 +03:00
Uint8 * dp = dporg ;
2009-12-22 23:53:50 +02:00
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
{
if ( * sp )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , - 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2009-12-22 23:53:50 +02:00
else
dp - = bpp ;
}
2009-05-28 02:43:47 +03:00
2009-01-09 15:03:47 +02:00
sp + = src - > w - dstRect - > w ;
2009-12-22 23:53:50 +02:00
}
}
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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 24/32 bpp dests
{
Uint8 * sp = ( Uint8 * ) src - > pixels + ( src - > h - srcRect - > h - srcRect - > y ) * src - > pitch + srcRect - > x ;
Uint8 * dporg = ( Uint8 * ) dst - > pixels + ( dstRect - > y + dstRect - > h - 1 ) * dst - > pitch + dstRect - > x * bpp ;
const SDL_Color * const colors = src - > format - > palette - > colors ;
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg - = dst - > pitch )
{
Uint8 * dp = dporg ;
2009-05-28 02:43:47 +03:00
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
2008-11-30 02:15:38 +02:00
{
2009-12-22 23:53:50 +02:00
if ( * sp )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2009-12-22 23:53:50 +02:00
else
dp + = bpp ;
2008-11-30 02:15:38 +02:00
}
2009-12-22 23:53:50 +02:00
sp + = src - > w - dstRect - > w ;
2008-11-30 02:15:38 +02:00
}
}
2007-06-25 17:55:45 +03:00
2010-08-05 14:02:18 +03:00
template < int bpp >
2009-12-22 23:53:50 +02:00
void CSDL_Ext : : 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 24/32 bpp dests
2009-01-09 15:03:47 +02:00
{
2009-12-22 23:53:50 +02:00
Uint8 * sp = ( Uint8 * ) src - > pixels + ( src - > h - srcRect - > h - srcRect - > y ) * src - > pitch + ( src - > w - srcRect - > w - srcRect - > x ) ;
Uint8 * dporg = ( Uint8 * ) dst - > pixels + ( dstRect - > y + dstRect - > h - 1 ) * dst - > pitch + ( dstRect - > x + dstRect - > w ) * bpp ;
const SDL_Color * const colors = src - > format - > palette - > colors ;
for ( int i = dstRect - > h ; i > 0 ; i - - , dporg - = dst - > pitch )
{
Uint8 * dp = dporg ;
for ( int j = dstRect - > w ; j > 0 ; j - - , sp + + )
{
if ( * sp )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , - 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2009-12-22 23:53:50 +02:00
else
dp - = bpp ;
}
sp + = src - > w - dstRect - > w ;
}
2009-01-09 15:03:47 +02:00
}
2010-08-12 08:22:48 +03:00
template < int bpp >
int CSDL_Ext : : blit8bppAlphaTo24bppT ( const SDL_Surface * src , const SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect )
2008-02-09 16:44:32 +02:00
{
2010-08-05 14:02:18 +03:00
if ( src & & src - > format - > BytesPerPixel = = 1 & & dst & & ( bpp = = 3 | | bpp = = 4 | | bpp = = 2 ) ) //everything's ok
2008-02-09 16:44:32 +02:00
{
2008-02-10 19:44:51 +02:00
SDL_Rect fulldst ;
int srcx , srcy , w , h ;
2008-02-09 16:44:32 +02:00
2008-02-10 19:44:51 +02:00
/* Make sure the surfaces aren't locked */
2008-12-23 15:59:03 +02:00
if ( ! src | | ! dst )
{
2013-06-26 14:18:27 +03:00
SDL_SetError ( " SDL_UpperBlit: passed a nullptr surface " ) ;
2009-05-28 05:58:29 +03:00
return - 1 ;
2008-02-10 19:44:51 +02:00
}
2008-12-23 15:59:03 +02:00
if ( src - > locked | | dst - > locked )
{
2008-02-10 19:44:51 +02:00
SDL_SetError ( " Surfaces must not be locked during blit " ) ;
2009-05-28 05:58:29 +03:00
return - 1 ;
2008-02-10 19:44:51 +02:00
}
2008-02-09 16:44:32 +02:00
2013-06-26 14:18:27 +03:00
/* If the destination rectangle is nullptr, use the entire dest surface */
if ( dstRect = = nullptr )
2008-12-23 15:59:03 +02:00
{
fulldst . x = fulldst . y = 0 ;
2008-02-10 19:44:51 +02:00
dstRect = & fulldst ;
2008-02-09 16:44:32 +02:00
}
2008-02-10 19:44:51 +02:00
/* clip the source rectangle to the source surface */
2009-02-08 17:39:26 +02:00
if ( srcRect )
2008-11-30 02:15:38 +02:00
{
int maxw , maxh ;
2008-08-02 18:08:03 +03:00
2008-02-10 19:44:51 +02:00
srcx = srcRect - > x ;
w = srcRect - > w ;
2008-12-23 15:59:03 +02:00
if ( srcx < 0 )
{
2009-05-28 05:58:29 +03:00
w + = srcx ;
2008-02-10 19:44:51 +02:00
dstRect - > x - = srcx ;
srcx = 0 ;
2008-02-09 16:44:32 +02:00
}
2008-02-10 19:44:51 +02:00
maxw = src - > w - srcx ;
if ( maxw < w )
w = maxw ;
srcy = srcRect - > y ;
h = srcRect - > h ;
2008-12-23 15:59:03 +02:00
if ( srcy < 0 )
{
2008-02-10 19:44:51 +02:00
h + = srcy ;
dstRect - > y - = srcy ;
srcy = 0 ;
2008-02-09 16:44:32 +02:00
}
2008-02-10 19:44:51 +02:00
maxh = src - > h - srcy ;
if ( maxh < h )
h = maxh ;
2008-08-02 18:08:03 +03:00
2009-02-08 17:39:26 +02:00
}
else
2008-11-30 02:15:38 +02:00
{
2009-10-01 23:00:21 +03:00
srcx = srcy = 0 ;
2008-02-10 19:44:51 +02:00
w = src - > w ;
h = src - > h ;
2008-02-09 16:44:32 +02:00
}
2008-02-10 19:44:51 +02:00
/* clip the destination rectangle against the clip rectangle */
2008-02-09 16:44:32 +02:00
{
2010-08-05 14:02:18 +03:00
SDL_Rect * clip = & dst - > clip_rect ;
2008-02-10 19:44:51 +02:00
int dx , dy ;
dx = clip - > x - dstRect - > x ;
2008-12-23 15:59:03 +02:00
if ( dx > 0 )
{
2008-02-10 19:44:51 +02:00
w - = dx ;
dstRect - > x + = dx ;
srcx + = dx ;
}
dx = dstRect - > x + w - clip - > x - clip - > w ;
if ( dx > 0 )
w - = dx ;
dy = clip - > y - dstRect - > y ;
2008-12-23 15:59:03 +02:00
if ( dy > 0 )
{
2008-02-10 19:44:51 +02:00
h - = dy ;
dstRect - > y + = dy ;
srcy + = dy ;
}
dy = dstRect - > y + h - clip - > y - clip - > h ;
if ( dy > 0 )
h - = dy ;
2008-02-09 16:44:32 +02:00
}
2008-02-10 19:44:51 +02:00
if ( w > 0 & & h > 0 )
2008-02-09 16:44:32 +02:00
{
2009-05-23 23:13:09 +03:00
dstRect - > w = w ;
dstRect - > h = h ;
2008-02-09 16:44:32 +02:00
2008-08-07 15:29:53 +03:00
if ( SDL_LockSurface ( dst ) )
return - 1 ; //if we cannot lock the surface
2009-05-23 23:13:09 +03:00
const SDL_Color * colors = src - > format - > palette - > colors ;
Uint8 * colory = ( Uint8 * ) src - > pixels + srcy * src - > pitch + srcx ;
Uint8 * py = ( Uint8 * ) dst - > pixels + dstRect - > y * dst - > pitch + dstRect - > x * bpp ;
2010-08-12 08:22:48 +03:00
for ( int y = h ; y ; y - - , colory + = src - > pitch , py + = dst - > pitch )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
Uint8 * color = colory ;
Uint8 * p = py ;
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
for ( int x = w ; x ; x - - )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
const SDL_Color & tbc = colors [ * color + + ] ; //color to blit
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2010-08-12 08:22:48 +03:00
ColorPutter < bpp , + 1 > : : PutColorAlphaSwitch ( p , tbc . r , tbc . g , tbc . b , tbc . unused ) ;
2014-05-21 19:04:34 +03:00
# else
ColorPutter < bpp , + 1 > : : PutColorAlphaSwitch ( p , tbc . r , tbc . g , tbc . b , tbc . a ) ;
# endif // 0
2010-08-05 14:02:18 +03:00
}
}
2008-08-07 15:29:53 +03:00
SDL_UnlockSurface ( dst ) ;
2008-02-09 16:44:32 +02:00
}
}
2008-02-10 19:44:51 +02:00
return 0 ;
2007-06-27 23:17:58 +03:00
}
2010-08-12 08:22:48 +03:00
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 :
2013-04-09 17:31:36 +03:00
logGlobal - > errorStream ( ) < < ( int ) dst - > format - > BitsPerPixel < < " bpp is not supported!!! " ;
2010-08-12 08:22:48 +03:00
return - 1 ;
}
}
2007-06-25 17:55:45 +03:00
Uint32 CSDL_Ext : : colorToUint32 ( const SDL_Color * color )
{
Uint32 ret = 0 ;
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2007-06-25 17:55:45 +03:00
ret + = color - > unused ;
2014-05-21 19:04:34 +03:00
# else
ret + = color - > a ;
# endif // 0
2008-01-30 16:19:35 +02:00
ret < < = 8 ; //*=256
2007-06-25 17:55:45 +03:00
ret + = color - > b ;
2008-01-30 16:19:35 +02:00
ret < < = 8 ; //*=256
2007-06-25 17:55:45 +03:00
ret + = color - > g ;
2008-01-30 16:19:35 +02:00
ret < < = 8 ; //*=256
2007-06-25 17:55:45 +03:00
ret + = color - > r ;
return ret ;
}
2007-07-12 14:41:31 +03:00
void CSDL_Ext : : update ( SDL_Surface * what )
{
2014-06-01 18:31:37 +03:00
# ifdef VCMI_SDL1
if ( what )
SDL_UpdateRect ( what , 0 , 0 , what - > w , what - > h ) ;
# else
if ( ! what )
return ;
2014-06-01 20:09:47 +03:00
if ( 0 ! = SDL_UpdateTexture ( screenTexture , nullptr , what - > pixels , what - > pitch ) )
2014-06-01 18:31:37 +03:00
logGlobal - > errorStream ( ) < < __FUNCTION__ < < " SDL_UpdateTexture " < < SDL_GetError ( ) ;
# endif // VCMI_SDL1
2007-07-12 14:41:31 +03:00
}
2009-09-20 15:47:40 +03:00
void CSDL_Ext : : drawBorder ( SDL_Surface * sur , int x , int y , int w , int h , const int3 & color )
2008-04-04 20:30:53 +03:00
{
2011-04-29 03:50:54 +03:00
for ( int i = 0 ; i < w ; i + + )
2008-04-04 20:30:53 +03:00
{
2011-04-29 03:50:54 +03:00
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x + i , y , color . x , color . y , color . z ) ;
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x + i , y + h - 1 , color . x , color . y , color . z ) ;
2008-04-04 20:30:53 +03:00
}
2011-04-29 03:50:54 +03:00
for ( int i = 0 ; i < h ; i + + )
2008-04-04 20:30:53 +03:00
{
2011-04-29 03:50:54 +03:00
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x , y + i , color . x , color . y , color . z ) ;
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x + w - 1 , y + i , color . x , color . y , color . z ) ;
2008-04-04 20:30:53 +03:00
}
}
2009-09-20 15:47:40 +03:00
void CSDL_Ext : : drawBorder ( SDL_Surface * sur , const SDL_Rect & r , const int3 & color )
{
drawBorder ( sur , r . x , r . y , r . w , r . h , color ) ;
}
2011-12-22 16:05:19 +03:00
void CSDL_Ext : : drawDashedBorder ( SDL_Surface * sur , const Rect & r , const int3 & color )
2010-08-05 14:02:18 +03:00
{
const int y1 = r . y , y2 = r . y + r . h - 1 ;
for ( int i = 0 ; i < r . w ; i + + )
{
const int x = r . x + i ;
if ( i % 4 | | ( i = = 0 ) )
{
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x , y1 , color . x , color . y , color . z ) ;
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x , y2 , color . x , color . y , color . z ) ;
}
}
const int x1 = r . x , x2 = r . x + r . w - 1 ;
for ( int i = 0 ; i < r . h ; i + + )
{
const int y = r . y + i ;
if ( ( i % 4 ) | | ( i = = 0 ) )
{
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x1 , y , color . x , color . y , color . z ) ;
SDL_PutPixelWithoutRefreshIfInSurf ( sur , x2 , y , color . x , color . y , color . z ) ;
}
}
}
2013-03-03 20:06:03 +03:00
void CSDL_Ext : : setPlayerColor ( SDL_Surface * sur , PlayerColor player )
2007-07-16 13:03:54 +03:00
{
2013-03-03 20:06:03 +03:00
if ( player = = PlayerColor : : UNFLAGGABLE )
2007-10-07 19:01:53 +03:00
return ;
2007-07-16 13:03:54 +03:00
if ( sur - > format - > BitsPerPixel = = 8 )
{
2013-03-03 20:06:03 +03:00
SDL_Color * color = ( player = = PlayerColor : : NEUTRAL
2010-03-21 00:17:19 +02:00
? graphics - > neutralColor
2013-03-03 20:06:03 +03:00
: & graphics - > playerColors [ player . getNum ( ) ] ) ;
2010-03-21 00:17:19 +02:00
SDL_SetColors ( sur , color , 5 , 1 ) ;
2007-07-16 13:03:54 +03:00
}
2010-03-21 00:17:19 +02:00
else
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Warning, setPlayerColor called on not 8bpp surface! " ;
2007-08-06 07:03:34 +03:00
}
2007-08-17 20:42:21 +03:00
2012-05-28 22:29:32 +03:00
TColorPutter CSDL_Ext : : getPutterFor ( SDL_Surface * const & dest , int incrementing )
2010-08-05 14:02:18 +03:00
{
# define CASE_BPP(BytesPerPixel) \
case BytesPerPixel : \
2010-08-12 08:22:48 +03:00
if ( incrementing > 0 ) \
return ColorPutter < BytesPerPixel , 1 > : : PutColor ; \
else if ( incrementing = = 0 ) \
return ColorPutter < BytesPerPixel , 0 > : : PutColor ; \
2010-08-05 14:02:18 +03:00
else \
2010-08-12 08:22:48 +03:00
return ColorPutter < BytesPerPixel , - 1 > : : PutColor ; \
2010-08-05 14:02:18 +03:00
break ;
switch ( dest - > format - > BytesPerPixel )
{
CASE_BPP ( 2 )
CASE_BPP ( 3 )
CASE_BPP ( 4 )
default :
2013-04-09 17:31:36 +03:00
logGlobal - > errorStream ( ) < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported! " ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-08-05 14:02:18 +03:00
}
}
2012-05-28 22:29:32 +03:00
TColorPutterAlpha CSDL_Ext : : getPutterAlphaFor ( SDL_Surface * const & dest , int incrementing )
2010-08-12 08:22:48 +03:00
{
switch ( dest - > format - > BytesPerPixel )
{
CASE_BPP ( 2 )
CASE_BPP ( 3 )
CASE_BPP ( 4 )
default :
2013-04-09 17:31:36 +03:00
logGlobal - > errorStream ( ) < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported! " ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-08-12 08:22:48 +03:00
}
# undef CASE_BPP
}
2012-05-19 19:22:34 +03:00
Uint8 * CSDL_Ext : : getPxPtr ( const SDL_Surface * const & srf , const int x , const int y )
2010-08-05 14:02:18 +03:00
{
return ( Uint8 * ) srf - > pixels + y * srf - > pitch + x * srf - > format - > BytesPerPixel ;
}
2007-09-14 16:11:10 +03:00
std : : string CSDL_Ext : : processStr ( std : : string str , std : : vector < std : : string > & tor )
{
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; ( i < tor . size ( ) ) & & ( boost : : find_first ( str , " %s " ) ) ; + + i )
2007-09-14 16:11:10 +03:00
{
boost : : replace_first ( str , " %s " , tor [ i ] ) ;
}
return str ;
2008-02-06 15:50:40 +02:00
}
2010-02-18 14:34:44 +02:00
bool CSDL_Ext : : isTransparent ( SDL_Surface * srf , int x , int y )
{
2012-01-19 17:33:22 +03:00
if ( x < 0 | | y < 0 | | x > = srf - > w | | y > = srf - > h )
return true ;
2013-04-03 19:28:50 +03:00
SDL_Color color ;
2014-05-21 19:04:34 +03:00
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2013-04-03 19:28:50 +03:00
SDL_GetRGBA ( SDL_GetPixel ( srf , x , y ) , srf - > format , & color . r , & color . g , & color . b , & color . unused ) ;
2014-05-21 19:04:34 +03:00
# else
SDL_GetRGBA ( SDL_GetPixel ( srf , x , y ) , srf - > format , & color . r , & color . g , & color . b , & color . a ) ;
# endif // 0
2013-04-03 19:28:50 +03:00
// color is considered transparent here if
// a) image has aplha: less than 50% transparency
// b) no alpha: color is cyan
if ( srf - > format - > Amask )
2014-05-23 13:51:38 +03:00
# ifdef VCMI_SDL1
2013-04-03 19:28:50 +03:00
return color . unused < 128 ; // almost transparent
2014-05-21 19:04:34 +03:00
# else
return color . a < 128 ; // almost transparent
# endif // 0
2010-02-18 14:34:44 +02:00
else
2013-04-03 19:28:50 +03:00
return ( color . r = = 0 & & color . g = = 255 & & color . b = = 255 ) ;
2010-02-18 14:34:44 +02:00
}
2010-07-15 20:13:17 +03:00
void CSDL_Ext : : VflipSurf ( SDL_Surface * surf )
{
char buf [ 4 ] ; //buffer
int bpp = surf - > format - > BytesPerPixel ;
for ( int y = 0 ; y < surf - > h ; + + y )
{
char * base = ( char * ) surf - > pixels + y * surf - > pitch ;
for ( int x = 0 ; x < surf - > w / 2 ; + + x )
{
memcpy ( buf , base + x * bpp , bpp ) ;
memcpy ( base + x * bpp , base + ( surf - > w - x - 1 ) * bpp , bpp ) ;
memcpy ( base + ( surf - > w - x - 1 ) * bpp , buf , bpp ) ;
}
}
}
2010-08-05 14:02:18 +03:00
void CSDL_Ext : : SDL_PutPixelWithoutRefresh ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A /*= 255*/ )
{
Uint8 * p = getPxPtr ( ekran , x , y ) ;
getPutterFor ( ekran , false ) ( p , R , G , B ) ;
2012-05-19 19:22:34 +03:00
switch ( ekran - > format - > BytesPerPixel )
{
case 2 : Channels : : px < 2 > : : a . set ( p , A ) ; break ;
case 3 : Channels : : px < 3 > : : a . set ( p , A ) ; break ;
case 4 : Channels : : px < 4 > : : a . set ( p , A ) ; break ;
}
2010-08-05 14:02:18 +03:00
}
void CSDL_Ext : : SDL_PutPixelWithoutRefreshIfInSurf ( SDL_Surface * ekran , const int & x , const int & y , const Uint8 & R , const Uint8 & G , const Uint8 & B , Uint8 A /*= 255*/ )
{
2012-06-13 16:04:06 +03:00
const SDL_Rect & rect = ekran - > clip_rect ;
if ( x > = rect . x & & x < rect . w + rect . x
& & y > = rect . y & & y < rect . h + rect . y )
2010-08-05 14:02:18 +03:00
SDL_PutPixelWithoutRefresh ( ekran , x , y , R , G , B , A ) ;
}
BlitterWithRotationVal CSDL_Ext : : getBlitterWithRotation ( SDL_Surface * dest )
{
switch ( dest - > format - > BytesPerPixel )
{
case 2 : return blitWithRotateClipVal < 2 > ;
case 3 : return blitWithRotateClipVal < 3 > ;
case 4 : return blitWithRotateClipVal < 4 > ;
default :
2013-04-09 17:31:36 +03:00
logGlobal - > errorStream ( ) < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported!!! " ;
2010-08-05 14:02:18 +03:00
break ;
}
assert ( 0 ) ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-08-05 14:02:18 +03:00
}
BlitterWithRotationVal CSDL_Ext : : getBlitterWithRotationAndAlpha ( SDL_Surface * dest )
{
switch ( dest - > format - > BytesPerPixel )
{
case 2 : return blitWithRotateClipValWithAlpha < 2 > ;
case 3 : return blitWithRotateClipValWithAlpha < 3 > ;
case 4 : return blitWithRotateClipValWithAlpha < 4 > ;
default :
2013-04-09 17:31:36 +03:00
logGlobal - > errorStream ( ) < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported!!! " ;
2010-08-05 14:02:18 +03:00
break ;
}
assert ( 0 ) ;
2013-06-26 14:18:27 +03:00
return nullptr ;
2010-08-05 14:02:18 +03:00
}
2012-05-17 13:44:48 +03:00
template < int bpp >
void CSDL_Ext : : applyEffectBpp ( SDL_Surface * surf , const SDL_Rect * rect , int mode )
2010-08-17 15:48:34 +03:00
{
switch ( mode )
{
case 0 : //sepia
{
const int sepiaDepth = 20 ;
const int sepiaIntensity = 30 ;
for ( int xp = rect - > x ; xp < rect - > x + rect - > w ; + + xp )
{
for ( int yp = rect - > y ; yp < rect - > y + rect - > h ; + + yp )
{
2012-05-17 13:44:48 +03:00
Uint8 * pixel = ( ui8 * ) surf - > pixels + yp * surf - > pitch + xp * surf - > format - > BytesPerPixel ;
int r = Channels : : px < bpp > : : r . get ( pixel ) ;
int g = Channels : : px < bpp > : : g . get ( pixel ) ;
int b = Channels : : px < bpp > : : b . get ( pixel ) ;
int gray = 0.299 * r + 0.587 * g + 0.114 * b ;
2010-08-17 15:48:34 +03:00
2012-05-17 13:44:48 +03:00
r = g = b = gray ;
2012-02-16 20:10:58 +03:00
r = r + ( sepiaDepth * 2 ) ;
g = g + sepiaDepth ;
2010-08-17 15:48:34 +03:00
2012-02-16 20:10:58 +03:00
if ( r > 255 ) r = 255 ;
if ( g > 255 ) g = 255 ;
if ( b > 255 ) b = 255 ;
2010-08-17 15:48:34 +03:00
2012-02-16 20:10:58 +03:00
// Darken blue color to increase sepia effect
b - = sepiaIntensity ;
2010-08-17 15:48:34 +03:00
2012-02-16 20:10:58 +03:00
// normalize if out of bounds
if ( b < 0 ) b = 0 ;
2010-08-17 15:48:34 +03:00
2012-05-17 13:44:48 +03:00
Channels : : px < bpp > : : r . set ( pixel , r ) ;
Channels : : px < bpp > : : g . set ( pixel , g ) ;
Channels : : px < bpp > : : b . set ( pixel , b ) ;
2010-08-17 15:48:34 +03:00
}
}
}
break ;
case 1 : //grayscale
{
for ( int xp = rect - > x ; xp < rect - > x + rect - > w ; + + xp )
{
for ( int yp = rect - > y ; yp < rect - > y + rect - > h ; + + yp )
{
2012-05-17 13:44:48 +03:00
Uint8 * pixel = ( ui8 * ) surf - > pixels + yp * surf - > pitch + xp * surf - > format - > BytesPerPixel ;
int r = Channels : : px < bpp > : : r . get ( pixel ) ;
int g = Channels : : px < bpp > : : g . get ( pixel ) ;
int b = Channels : : px < bpp > : : b . get ( pixel ) ;
2010-08-17 15:48:34 +03:00
2012-05-17 13:44:48 +03:00
int gray = 0.299 * r + 0.587 * g + 0.114 * b ;
vstd : : amax ( gray , 255 ) ;
2010-08-17 15:48:34 +03:00
2012-05-17 13:44:48 +03:00
Channels : : px < bpp > : : r . set ( pixel , gray ) ;
Channels : : px < bpp > : : g . set ( pixel , gray ) ;
Channels : : px < bpp > : : b . set ( pixel , gray ) ;
2010-08-17 15:48:34 +03:00
}
}
}
break ;
default :
2012-05-20 00:38:01 +03:00
throw std : : runtime_error ( " Unsupported effect! " ) ;
2010-08-17 15:48:34 +03:00
}
}
2012-05-17 13:44:48 +03:00
void CSDL_Ext : : applyEffect ( SDL_Surface * surf , const SDL_Rect * rect , int mode )
{
switch ( surf - > format - > BytesPerPixel )
{
case 2 : applyEffectBpp < 2 > ( surf , rect , mode ) ; break ;
case 3 : applyEffectBpp < 3 > ( surf , rect , mode ) ; break ;
case 4 : applyEffectBpp < 4 > ( surf , rect , mode ) ; break ;
}
}
2012-06-15 20:08:19 +03:00
template < int bpp >
void scaleSurfaceFastInternal ( SDL_Surface * surf , SDL_Surface * ret )
{
const float factorX = float ( surf - > w ) / float ( ret - > w ) ,
2012-11-11 15:23:31 +03:00
factorY = float ( surf - > h ) / float ( ret - > h ) ;
2012-06-15 20:08:19 +03:00
for ( int y = 0 ; y < ret - > h ; y + + )
{
for ( int x = 0 ; x < ret - > w ; x + + )
{
//coordinates we want to calculate
int origX = floor ( factorX * x ) ,
2012-11-11 15:23:31 +03:00
origY = floor ( factorY * y ) ;
2012-06-15 20:08:19 +03:00
// Get pointers to source pixels
Uint8 * srcPtr = ( Uint8 * ) surf - > pixels + origY * surf - > pitch + origX * bpp ;
Uint8 * destPtr = ( Uint8 * ) ret - > pixels + y * ret - > pitch + x * bpp ;
memcpy ( destPtr , srcPtr , bpp ) ;
}
}
}
SDL_Surface * CSDL_Ext : : scaleSurfaceFast ( SDL_Surface * surf , int width , int height )
{
if ( ! surf | | ! width | | ! height )
return nullptr ;
//Same size? return copy - this should more be faster
if ( width = = surf - > w & & height = = surf - > h )
return copySurface ( surf ) ;
SDL_Surface * ret = newSurface ( width , height , surf ) ;
switch ( surf - > format - > BytesPerPixel )
{
case 1 : scaleSurfaceFastInternal < 1 > ( surf , ret ) ; break ;
case 2 : scaleSurfaceFastInternal < 2 > ( surf , ret ) ; break ;
case 3 : scaleSurfaceFastInternal < 3 > ( surf , ret ) ; break ;
case 4 : scaleSurfaceFastInternal < 4 > ( surf , ret ) ; break ;
}
return ret ;
}
2012-05-20 00:38:01 +03:00
template < int bpp >
void scaleSurfaceInternal ( SDL_Surface * surf , SDL_Surface * ret )
{
const float factorX = float ( surf - > w - 1 ) / float ( ret - > w ) ,
2012-11-11 15:23:31 +03:00
factorY = float ( surf - > h - 1 ) / float ( ret - > h ) ;
2012-05-20 00:38:01 +03:00
for ( int y = 0 ; y < ret - > h ; y + + )
{
for ( int x = 0 ; x < ret - > w ; x + + )
{
//coordinates we want to interpolate
2012-06-15 20:08:19 +03:00
float origX = factorX * x ,
2012-11-11 15:23:31 +03:00
origY = factorY * y ;
2012-05-20 00:38:01 +03:00
float x1 = floor ( origX ) , x2 = floor ( origX + 1 ) ,
2012-11-11 15:23:31 +03:00
y1 = floor ( origY ) , y2 = floor ( origY + 1 ) ;
2012-05-20 14:03:21 +03:00
//assert( x1 >= 0 && y1 >= 0 && x2 < surf->w && y2 < surf->h);//All pixels are in range
2012-05-20 00:38:01 +03:00
// Calculate weights of each source pixel
float w11 = ( ( origX - x1 ) * ( origY - y1 ) ) ;
float w12 = ( ( origX - x1 ) * ( y2 - origY ) ) ;
float w21 = ( ( x2 - origX ) * ( origY - y1 ) ) ;
float w22 = ( ( x2 - origX ) * ( y2 - origY ) ) ;
2012-05-20 14:03:21 +03:00
//assert( w11 + w12 + w21 + w22 > 0.99 && w11 + w12 + w21 + w22 < 1.01);//total weight is ~1.0
2012-05-20 00:38:01 +03:00
// Get pointers to source pixels
Uint8 * p11 = ( Uint8 * ) surf - > pixels + int ( y1 ) * surf - > pitch + int ( x1 ) * bpp ;
Uint8 * p12 = p11 + bpp ;
Uint8 * p21 = p11 + surf - > pitch ;
Uint8 * p22 = p21 + bpp ;
// Calculate resulting channels
# define PX(X, PTR) Channels::px<bpp>::X.get(PTR)
int resR = PX ( r , p11 ) * w11 + PX ( r , p12 ) * w12 + PX ( r , p21 ) * w21 + PX ( r , p22 ) * w22 ;
int resG = PX ( g , p11 ) * w11 + PX ( g , p12 ) * w12 + PX ( g , p21 ) * w21 + PX ( g , p22 ) * w22 ;
int resB = PX ( b , p11 ) * w11 + PX ( b , p12 ) * w12 + PX ( b , p21 ) * w21 + PX ( b , p22 ) * w22 ;
int resA = PX ( a , p11 ) * w11 + PX ( a , p12 ) * w12 + PX ( a , p21 ) * w21 + PX ( a , p22 ) * w22 ;
2012-05-20 14:03:21 +03:00
//assert(resR < 256 && resG < 256 && resB < 256 && resA < 256);
2012-05-20 00:38:01 +03:00
# undef PX
Uint8 * dest = ( Uint8 * ) ret - > pixels + y * ret - > pitch + x * bpp ;
Channels : : px < bpp > : : r . set ( dest , resR ) ;
Channels : : px < bpp > : : g . set ( dest , resG ) ;
Channels : : px < bpp > : : b . set ( dest , resB ) ;
Channels : : px < bpp > : : a . set ( dest , resA ) ;
}
}
}
2012-05-20 14:03:21 +03:00
// scaling via bilinear interpolation algorithm.
// NOTE: best results are for scaling in range 50%...200%.
// And upscaling looks awful right now - should be fixed somehow
2012-05-20 00:38:01 +03:00
SDL_Surface * CSDL_Ext : : scaleSurface ( SDL_Surface * surf , int width , int height )
{
if ( ! surf | | ! width | | ! height )
return nullptr ;
2012-05-20 14:03:21 +03:00
2012-05-20 00:38:01 +03:00
if ( surf - > format - > palette )
2012-06-15 20:08:19 +03:00
return scaleSurfaceFast ( surf , width , height ) ;
2012-05-20 00:38:01 +03:00
2012-05-20 14:03:21 +03:00
//Same size? return copy - this should more be faster
if ( width = = surf - > w & & height = = surf - > h )
return copySurface ( surf ) ;
2012-05-20 00:38:01 +03:00
SDL_Surface * ret = newSurface ( width , height , surf ) ;
switch ( surf - > format - > BytesPerPixel )
{
case 2 : scaleSurfaceInternal < 2 > ( surf , ret ) ; break ;
case 3 : scaleSurfaceInternal < 3 > ( surf , ret ) ; break ;
case 4 : scaleSurfaceInternal < 4 > ( surf , ret ) ; break ;
}
return ret ;
}
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : blitSurface ( SDL_Surface * src , SDL_Rect * srcRect , SDL_Surface * dst , SDL_Rect * dstRect )
{
if ( dst ! = screen )
{
SDL_BlitSurface ( src , srcRect , dst , dstRect ) ;
}
else
{
SDL_Rect betterDst ;
if ( dstRect )
{
betterDst = * dstRect ;
}
else
{
2011-12-22 16:05:19 +03:00
betterDst = Rect ( 0 , 0 , dst - > w , dst - > h ) ;
2010-08-23 18:16:40 +03:00
}
SDL_BlitSurface ( src , srcRect , dst , & betterDst ) ;
}
}
2010-08-17 15:48:34 +03:00
2010-08-23 19:13:30 +03:00
void CSDL_Ext : : fillRect ( SDL_Surface * dst , SDL_Rect * dstrect , Uint32 color )
{
SDL_Rect newRect ;
if ( dstrect )
{
newRect = * dstrect ;
}
else
{
2011-12-22 16:05:19 +03:00
newRect = Rect ( 0 , 0 , dst - > w , dst - > h ) ;
2010-08-23 19:13:30 +03:00
}
SDL_FillRect ( dst , & newRect , color ) ;
}
2014-07-05 00:46:55 +03:00
void CSDL_Ext : : fillRectBlack ( SDL_Surface * dst , SDL_Rect * dstrect )
{
const Uint32 black = SDL_MapRGB ( dst - > format , 0 , 0 , 0 ) ;
fillRect ( dst , dstrect , black ) ;
}
2012-07-21 23:16:54 +03:00
void CSDL_Ext : : fillTexture ( SDL_Surface * dst , SDL_Surface * src )
{
SDL_Rect srcRect ;
SDL_Rect dstRect ;
SDL_GetClipRect ( src , & srcRect ) ;
SDL_GetClipRect ( dst , & dstRect ) ;
2012-08-28 19:28:21 +03:00
for ( int y = dstRect . y ; y < dstRect . y + dstRect . h ; y + = srcRect . h )
2012-07-21 23:16:54 +03:00
{
2012-08-28 19:28:21 +03:00
for ( int x = dstRect . x ; x < dstRect . x + dstRect . w ; x + = srcRect . w )
2012-07-21 23:16:54 +03:00
{
2012-08-28 19:28:21 +03:00
int xLeft = std : : min < int > ( srcRect . w , dstRect . x + dstRect . w - x ) ;
int yLeft = std : : min < int > ( srcRect . h , dstRect . y + dstRect . h - y ) ;
Rect currentDest ( x , y , xLeft , yLeft ) ;
2012-07-21 23:16:54 +03:00
SDL_BlitSurface ( src , & srcRect , dst , & currentDest ) ;
}
}
}
2013-07-07 11:27:27 +03:00
SDL_Color CSDL_Ext : : makeColor ( ui8 r , ui8 g , ui8 b , ui8 a )
{
SDL_Color ret = { r , g , b , a } ;
return ret ;
}
2014-07-02 18:41:30 +03:00
void CSDL_Ext : : startTextInput ( SDL_Rect * where )
{
# ifndef VCMI_SDL1
if ( SDL_IsTextInputActive ( ) = = SDL_FALSE )
{
SDL_StartTextInput ( ) ;
}
SDL_SetTextInputRect ( where ) ;
# endif
}
void CSDL_Ext : : stopTextInput ( )
{
# ifndef VCMI_SDL1
if ( SDL_IsTextInputActive ( ) = = SDL_TRUE )
{
SDL_StopTextInput ( ) ;
}
# endif
}
2014-07-02 21:20:54 +03:00
STRONG_INLINE static uint32_t mapColor ( SDL_Surface * surface , SDL_Color color )
{
# ifdef VCMI_SDL1
return SDL_MapRGB ( surface - > format , color . r , color . g , color . b ) ;
# else
return SDL_MapRGBA ( surface - > format , color . r , color . g , color . b , color . a ) ;
# endif
}
void CSDL_Ext : : setColorKey ( SDL_Surface * surface , SDL_Color color )
{
uint32_t key = mapColor ( surface , color ) ;
SDL_SetColorKey ( surface , SDL_SRCCOLORKEY , key ) ;
}
void CSDL_Ext : : setDefaultColorKey ( SDL_Surface * surface )
{
setColorKey ( surface , Colors : : DEFAULT_KEY_COLOR ) ;
}
void CSDL_Ext : : setDefaultColorKeyPresize ( SDL_Surface * surface )
{
uint32_t key = mapColor ( surface , Colors : : DEFAULT_KEY_COLOR ) ;
auto & color = surface - > format - > palette - > colors [ key ] ;
// set color key only if exactly such color was found
if ( color . r = = Colors : : DEFAULT_KEY_COLOR . r & & color . g = = Colors : : DEFAULT_KEY_COLOR . g & & color . b = = Colors : : DEFAULT_KEY_COLOR . b )
SDL_SetColorKey ( surface , SDL_SRCCOLORKEY , key ) ;
}
2014-07-02 18:41:30 +03:00
2012-05-18 20:35:46 +03:00
template SDL_Surface * CSDL_Ext : : createSurfaceWithBpp < 2 > ( int , int ) ;
template SDL_Surface * CSDL_Ext : : createSurfaceWithBpp < 3 > ( int , int ) ;
2012-11-11 15:23:31 +03:00
template SDL_Surface * CSDL_Ext : : createSurfaceWithBpp < 4 > ( int , int ) ;