2009-05-20 13:08:56 +03:00
# include "../stdafx.h"
2007-06-06 21:26:28 +03:00
# include "SDL_Extensions.h"
2008-08-02 18:08:03 +03:00
# include "SDL_ttf.h"
2007-07-14 18:24:42 +03:00
# include "CGameInfo.h"
2007-06-25 17:55:45 +03:00
# include <iostream>
2007-07-14 18:24:42 +03:00
# include <utility>
# include <algorithm>
2007-08-29 15:18:31 +03:00
# include "CMessage.h"
2007-09-14 16:11:10 +03:00
# include <boost/algorithm/string.hpp>
2010-12-20 23:22:53 +02:00
# include "CDefHandler.h"
2008-03-04 15:59:34 +02:00
# include <map>
2009-05-20 13:08:56 +03:00
# include "Graphics.h"
2010-08-05 14:02:18 +03:00
# include "GUIBase.h"
2008-02-22 19:47:14 +02:00
2009-04-15 17:03:31 +03:00
/*
* SDL_Extensions . cpp , 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
*
*/
2010-08-05 14:02:18 +03:00
template < int bpp , int incrementPtr >
2010-08-12 08:22:48 +03:00
STRONG_INLINE void ColorPutter < bpp , incrementPtr > : : PutColorAlpha ( Uint8 * & ptr , const SDL_Color & Color )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
PutColor ( ptr , Color . r , Color . g , Color . b , Color . unused ) ;
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
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 ) ;
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
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 ;
2010-08-05 14:02:18 +03:00
}
2010-08-12 08:22:48 +03:00
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
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 )
{
2011-02-06 19:26:27 +02:00
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 ) ;
2010-08-12 08:22:48 +03:00
}
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 )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
ptr [ 0 ] = B ;
ptr [ 1 ] = G ;
ptr [ 2 ] = R ;
2010-08-05 14:02:18 +03:00
}
2010-08-12 08:22:48 +03:00
else if ( incrementPtr = = 1 )
{
* ptr + + = B ;
* ptr + + = G ;
* ptr + + = R ;
if ( bpp = = 4 )
* ptr + + = 0 ;
}
else if ( incrementPtr = = - 1 )
{
if ( bpp = = 4 )
* ( - - ptr ) = 0 ;
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
* ( - - ptr ) = R ;
* ( - - ptr ) = G ;
* ( - - ptr ) = B ;
}
else
{
assert ( 0 ) ;
}
}
2010-08-05 14:02:18 +03:00
2011-02-20 11:24:53 +02:00
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 ;
}
}
2010-08-05 14:02:18 +03:00
template < int incrementPtr >
2010-08-12 08:22:48 +03:00
STRONG_INLINE void ColorPutter < 2 , incrementPtr > : : PutColor ( Uint8 * & ptr , const Uint8 & R , const Uint8 & G , const Uint8 & B )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
if ( incrementPtr = = - 1 )
ptr - = 2 ;
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
Uint16 * const px = ( Uint16 * ) ptr ;
* px = ( B > > 3 ) + ( ( G > > 2 ) < < 5 ) + ( ( R > > 3 ) < < 11 ) ; //drop least significant bits of 24 bpp encoded color
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
if ( incrementPtr = = 1 )
ptr + = 2 ; //bpp
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
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 )
2010-08-05 14:02:18 +03:00
{
2010-08-12 08:22:48 +03:00
case 255 :
ptr + = 2 * incrementPtr ;
return ;
case 0 :
PutColor ( ptr , R , G , B ) ;
return ;
default :
PutColor ( ptr , R , G , B , A ) ;
return ;
2010-08-05 14:02:18 +03:00
}
2010-08-12 08:22:48 +03:00
}
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 ) ;
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
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 ) ;
}
2010-08-05 14:02:18 +03:00
2010-08-12 08:22:48 +03:00
template < int incrementPtr >
STRONG_INLINE void ColorPutter < 2 , incrementPtr > : : PutColor ( Uint8 * & ptr , const SDL_Color & Color )
{
PutColor ( ptr , Color . r , Color . g , Color . b ) ;
}
2010-08-05 14:02:18 +03:00
2011-02-20 11:24:53 +02:00
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 ;
}
}
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
{
return SDL_CreateRGBSurface ( mod - > flags , w , h , mod - > format - > BitsPerPixel , mod - > format - > Rmask , mod - > format - > Gmask , mod - > format - > Bmask , mod - > format - > Amask ) ;
}
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
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 ) ;
2010-08-23 18:16:40 +03:00
CSDL_Ext : : blitSurface ( src , NULL , 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
{
blitAt ( src , pos . x , pos . y , dst ) ;
}
2009-06-26 18:41:19 +03:00
2007-06-13 17:02:43 +03:00
SDL_Color genRGB ( int r , int g , int b , int a = 0 )
{
SDL_Color ret ;
ret . b = b ;
ret . g = g ;
ret . r = r ;
ret . unused = a ;
return ret ;
}
2009-06-26 18:41:19 +03:00
2007-07-28 12:44:10 +03:00
void updateRect ( SDL_Rect * rect , SDL_Surface * scr )
2007-06-13 17:02:43 +03:00
{
SDL_UpdateRect ( scr , rect - > x , rect - > y , rect - > w , rect - > h ) ;
}
2009-06-26 18:41:19 +03:00
2010-02-04 17:50:59 +02:00
void printAtMiddleWB ( const std : : string & text , int x , int y , TTF_Font * font , int charpr , SDL_Color kolor , SDL_Surface * dst )
2007-08-24 11:27:32 +03:00
{
2010-07-06 05:10:26 +03:00
std : : vector < std : : string > ws = CMessage : : breakText ( text , charpr ) ;
2007-08-24 11:27:32 +03:00
std : : vector < SDL_Surface * > wesu ;
2010-07-06 05:10:26 +03:00
wesu . resize ( ws . size ( ) ) ;
2008-12-23 15:59:03 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
{
2010-07-06 05:10:26 +03:00
wesu [ i ] = TTF_RenderText_Blended ( font , ws [ i ] . c_str ( ) , kolor ) ;
2008-12-23 15:59:03 +02:00
}
2007-08-24 11:27:32 +03:00
int tox = 0 , toy = 0 ;
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2007-08-24 11:27:32 +03:00
{
toy + = wesu [ i ] - > h ;
if ( tox < wesu [ i ] - > w )
tox = wesu [ i ] - > w ;
}
int evx , evy = y - ( toy / 2 ) ;
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2007-08-24 11:27:32 +03:00
{
evx = ( x - ( tox / 2 ) ) + ( ( tox - wesu [ i ] - > w ) / 2 ) ;
2007-12-22 20:04:34 +02:00
blitAt ( wesu [ i ] , evx , evy , dst ) ;
2007-08-24 11:27:32 +03:00
evy + = wesu [ i ] - > h ;
}
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2008-05-23 22:50:11 +03:00
SDL_FreeSurface ( wesu [ i ] ) ;
2010-02-04 17:50:59 +02:00
}
2009-06-26 18:41:19 +03:00
2010-02-04 17:50:59 +02:00
void printAtWB ( const std : : string & text , int x , int y , TTF_Font * font , int charpr , SDL_Color kolor , SDL_Surface * dst )
2008-05-23 22:50:11 +03:00
{
2010-07-06 05:10:26 +03:00
std : : vector < std : : string > ws = CMessage : : breakText ( text , charpr ) ;
2008-05-23 22:50:11 +03:00
std : : vector < SDL_Surface * > wesu ;
2010-07-06 05:10:26 +03:00
wesu . resize ( ws . size ( ) ) ;
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2010-07-06 05:10:26 +03:00
wesu [ i ] = TTF_RenderText_Blended ( font , ws [ i ] . c_str ( ) , kolor ) ;
2008-05-23 22:50:11 +03:00
int evy = y ;
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2008-05-23 22:50:11 +03:00
{
blitAt ( wesu [ i ] , x , evy , dst ) ;
evy + = wesu [ i ] - > h ;
}
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < wesu . size ( ) ; + + i )
2007-08-24 11:27:32 +03:00
SDL_FreeSurface ( wesu [ i ] ) ;
}
2010-02-04 17:50:59 +02:00
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : printAtWB ( const std : : string & text , int x , int y , EFonts font , int charpr , SDL_Color kolor , SDL_Surface * dst )
2010-02-02 18:24:53 +02:00
{
2010-02-04 17:50:59 +02:00
if ( graphics - > fontsTrueType [ font ] )
{
printAtWB ( text , x , y , graphics - > fontsTrueType [ font ] , charpr , kolor , dst ) ;
return ;
}
2010-02-02 18:24:53 +02:00
const Font * f = graphics - > fonts [ font ] ;
2010-07-06 05:10:26 +03:00
std : : vector < std : : string > ws = CMessage : : breakText ( text , charpr ) ;
2010-02-02 18:24:53 +02:00
int cury = y ;
2010-07-06 05:10:26 +03:00
for ( size_t i = 0 ; i < ws . size ( ) ; + + i )
2010-02-02 18:24:53 +02:00
{
2010-08-23 18:16:40 +03:00
printAt ( ws [ i ] , x , cury , font , kolor , dst ) ;
2010-02-02 18:24:53 +02:00
cury + = f - > height ;
}
}
2009-06-26 18:41:19 +03:00
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : printAtMiddleWB ( const std : : string & text , int x , int y , EFonts font , int charpr , SDL_Color kolor /*=tytulowy*/ , SDL_Surface * dst /*=screen*/ )
2009-08-17 11:50:31 +03:00
{
2010-02-04 17:50:59 +02:00
if ( graphics - > fontsTrueType [ font ] )
{
printAtMiddleWB ( text , x , y , graphics - > fontsTrueType [ font ] , charpr , kolor , dst ) ;
return ;
}
2009-08-17 11:50:31 +03:00
const Font * f = graphics - > fonts [ font ] ;
2010-07-06 05:10:26 +03:00
std : : vector < std : : string > ws = CMessage : : breakText ( text , charpr ) ;
int totalHeight = ws . size ( ) * f - > height ;
2009-08-17 11:50:31 +03:00
int cury = y - totalHeight / 2 ;
2010-07-06 05:10:26 +03:00
for ( size_t i = 0 ; i < ws . size ( ) ; + + i )
2009-08-17 11:50:31 +03:00
{
2010-08-23 18:16:40 +03:00
printAt ( ws [ i ] , x - f - > getWidth ( ws [ i ] . c_str ( ) ) / 2 , cury , font , kolor , dst ) ;
2009-08-17 11:50:31 +03:00
cury + = f - > height ;
}
}
2010-08-23 18:16:40 +03:00
void printAtMiddle ( const std : : string & text , int x , int y , TTF_Font * font , SDL_Color kolor , SDL_Surface * dst , unsigned char quality = 2 )
2007-07-10 11:40:09 +03:00
{
2007-08-07 14:54:50 +03:00
if ( text . length ( ) = = 0 ) return ;
2007-07-10 11:40:09 +03:00
SDL_Surface * temp ;
switch ( quality )
{
case 0 :
temp = TTF_RenderText_Solid ( font , text . c_str ( ) , kolor ) ;
break ;
case 1 :
SDL_Color tem ;
tem . b = 0xff - kolor . b ;
tem . g = 0xff - kolor . g ;
tem . r = 0xff - kolor . r ;
tem . unused = 0xff - kolor . unused ;
temp = TTF_RenderText_Shaded ( font , text . c_str ( ) , kolor , tem ) ;
break ;
case 2 :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
default :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
}
2011-02-20 11:24:53 +02:00
SDL_Rect dstRect = genRect ( temp - > h , temp - > w , x - ( temp - > w / 2 ) , y - ( temp - > h / 2 ) ) ;
CSDL_Ext : : blitSurface ( temp , NULL , dst , & dstRect ) ;
2007-07-10 11:40:09 +03:00
SDL_FreeSurface ( temp ) ;
2010-02-04 17:50:59 +02:00
}
2009-06-26 18:41:19 +03:00
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : printAtMiddle ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor /*=zwykly*/ , SDL_Surface * dst /*=screen*/ )
2009-08-17 11:50:31 +03:00
{
2010-02-04 17:50:59 +02:00
if ( graphics - > fontsTrueType [ font ] )
{
printAtMiddle ( text , x , y , graphics - > fontsTrueType [ font ] , kolor , dst ) ;
return ;
}
2009-08-17 11:50:31 +03:00
const Font * f = graphics - > fonts [ font ] ;
int nx = x - f - > getWidth ( text . c_str ( ) ) / 2 ,
ny = y - f - > height / 2 ;
2010-08-23 18:16:40 +03:00
printAt ( text , nx , ny , font , kolor , dst ) ;
2009-08-17 11:50:31 +03:00
}
2010-02-04 17:50:59 +02:00
void printAt ( const std : : string & text , int x , int y , TTF_Font * font , SDL_Color kolor , SDL_Surface * dst , unsigned char quality = 2 , bool refresh = false )
2009-04-03 18:55:26 +03:00
{
if ( text . length ( ) = = 0 )
return ;
SDL_Surface * temp ;
switch ( quality )
{
case 0 :
temp = TTF_RenderText_Solid ( font , text . c_str ( ) , kolor ) ;
break ;
case 1 :
SDL_Color tem ;
tem . b = 0xff - kolor . b ;
tem . g = 0xff - kolor . g ;
tem . r = 0xff - kolor . r ;
tem . unused = 0xff - kolor . unused ;
temp = TTF_RenderText_Shaded ( font , text . c_str ( ) , kolor , tem ) ;
break ;
case 2 :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
default :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
}
2011-02-20 11:24:53 +02:00
SDL_Rect dstRect = genRect ( temp - > h , temp - > w , x , y ) ;
CSDL_Ext : : blitSurface ( temp , NULL , dst , & dstRect ) ;
2009-04-14 15:47:09 +03:00
if ( refresh )
SDL_UpdateRect ( dst , x , y , temp - > w , temp - > h ) ;
2009-04-03 18:55:26 +03:00
SDL_FreeSurface ( temp ) ;
2010-02-04 17:50:59 +02:00
}
2009-04-14 15:47:09 +03:00
2010-08-05 14:02:18 +03:00
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : printAt ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor /*=zwykly*/ , SDL_Surface * dst /*=screen*/ )
2009-08-17 11:50:31 +03:00
{
2009-08-22 16:59:15 +03:00
if ( ! text . size ( ) )
return ;
2010-08-23 18:16:40 +03:00
2010-02-04 17:50:59 +02:00
if ( graphics - > fontsTrueType [ font ] )
{
printAt ( text , x , y , graphics - > fontsTrueType [ font ] , kolor , dst ) ;
return ;
}
2009-08-22 16:59:15 +03:00
2009-08-17 11:50:31 +03:00
assert ( dst ) ;
assert ( font < Graphics : : FONTS_NUMBER ) ;
2010-08-05 14:02:18 +03:00
//assume BGR dst surface, TODO - make it general in a tidy way
assert ( dst - > format - > Rshift > dst - > format - > Gshift ) ;
assert ( dst - > format - > Gshift > dst - > format - > Bshift ) ;
2009-08-17 11:50:31 +03:00
const Font * f = graphics - > fonts [ font ] ;
const Uint8 bpp = dst - > format - > BytesPerPixel ;
Uint8 * px = NULL ;
Uint8 * src = NULL ;
2010-08-05 14:02:18 +03:00
TColorPutter colorPutter = getPutterFor ( dst , false ) ;
2009-08-17 11:50:31 +03:00
2009-08-22 16:59:15 +03:00
//if text is in {} braces, we'll ommit them
const int first = ( text [ 0 ] = = ' { ' ? 1 : 0 ) ;
const int beyondEnd = ( text [ text . size ( ) - 1 ] = = ' } ' ? text . size ( ) - 1 : text . size ( ) ) ;
2009-08-17 11:50:31 +03:00
2009-08-22 16:59:15 +03:00
for ( int txti = first ; txti < beyondEnd ; txti + + )
2009-08-17 11:50:31 +03:00
{
const unsigned char c = text [ txti ] ;
x + = f - > chars [ c ] . unknown1 ;
2010-08-23 18:16:40 +03:00
for ( int i = std : : max ( 0 , - y ) ; i < f - > height & & ( y + i ) < ( dst - > h - 1 ) ; i + + )
2009-08-17 11:50:31 +03:00
{
px = ( Uint8 * ) dst - > pixels ;
px + = ( y + i ) * dst - > pitch + x * bpp ;
2010-02-04 17:50:59 +02:00
src = f - > chars [ c ] . pixels ;
src + = i * f - > chars [ c ] . width ; //if we have reached end of surface in previous line
2010-08-23 18:16:40 +03:00
for ( int j = std : : max ( 0 , - x ) ; j < f - > chars [ c ] . width & & ( j + x ) < ( dst - > w - 1 ) ; j + + )
2009-08-17 11:50:31 +03:00
{
switch ( * src )
{
case 1 : //black "shadow"
memset ( px , 0 , bpp ) ;
break ;
case 255 : //text colour
2010-08-05 14:02:18 +03:00
colorPutter ( px , kolor . r , kolor . g , kolor . b ) ;
2009-08-17 11:50:31 +03:00
break ;
}
src + + ;
px + = bpp ;
}
}
x + = f - > chars [ c ] . width ;
x + = f - > chars [ c ] . unknown2 ;
}
}
2010-02-04 17:50:59 +02:00
void printTo ( const std : : string & text , int x , int y , TTF_Font * font , SDL_Color kolor , SDL_Surface * dst , unsigned char quality = 2 )
2008-01-12 13:32:40 +02:00
{
if ( text . length ( ) = = 0 )
return ;
SDL_Surface * temp ;
switch ( quality )
{
case 0 :
temp = TTF_RenderText_Solid ( font , text . c_str ( ) , kolor ) ;
break ;
case 1 :
SDL_Color tem ;
tem . b = 0xff - kolor . b ;
tem . g = 0xff - kolor . g ;
tem . r = 0xff - kolor . r ;
tem . unused = 0xff - kolor . unused ;
temp = TTF_RenderText_Shaded ( font , text . c_str ( ) , kolor , tem ) ;
break ;
case 2 :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
default :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
}
2011-02-20 11:24:53 +02:00
SDL_Rect dstRect = genRect ( temp - > h , temp - > w , x - temp - > w , y - temp - > h ) ;
CSDL_Ext : : blitSurface ( temp , NULL , dst , & dstRect ) ;
2008-09-16 18:23:44 +03:00
SDL_UpdateRect ( dst , x - temp - > w , y - temp - > h , temp - > w , temp - > h ) ;
2008-01-12 13:32:40 +02:00
SDL_FreeSurface ( temp ) ;
2010-02-04 17:50:59 +02:00
}
2008-05-27 16:16:35 +03:00
2010-08-23 18:16:40 +03:00
void CSDL_Ext : : printTo ( const std : : string & text , int x , int y , EFonts font , SDL_Color kolor /*=zwykly*/ , SDL_Surface * dst /*=screen*/ )
2009-08-17 11:50:31 +03:00
{
2010-02-04 17:50:59 +02:00
if ( graphics - > fontsTrueType [ font ] )
{
printTo ( text , x , y , graphics - > fontsTrueType [ font ] , kolor , dst ) ;
return ;
}
2009-08-17 11:50:31 +03:00
const Font * f = graphics - > fonts [ font ] ;
2010-08-23 18:16:40 +03:00
printAt ( text , x - f - > getWidth ( text . c_str ( ) ) , y - f - > height , font , kolor , dst ) ;
2009-08-17 11:50:31 +03:00
}
2010-02-04 17:50:59 +02:00
void printToWR ( const std : : string & text , int x , int y , TTF_Font * font , SDL_Color kolor , SDL_Surface * dst , unsigned char quality = 2 )
2008-05-27 16:16:35 +03:00
{
if ( text . length ( ) = = 0 )
return ;
SDL_Surface * temp ;
switch ( quality )
{
case 0 :
temp = TTF_RenderText_Solid ( font , text . c_str ( ) , kolor ) ;
break ;
case 1 :
SDL_Color tem ;
tem . b = 0xff - kolor . b ;
tem . g = 0xff - kolor . g ;
tem . r = 0xff - kolor . r ;
tem . unused = 0xff - kolor . unused ;
temp = TTF_RenderText_Shaded ( font , text . c_str ( ) , kolor , tem ) ;
break ;
case 2 :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
default :
temp = TTF_RenderText_Blended ( font , text . c_str ( ) , kolor ) ;
break ;
}
2011-02-20 11:24:53 +02:00
SDL_Rect dstRect = genRect ( temp - > h , temp - > w , x - temp - > w , y - temp - > h ) ;
CSDL_Ext : : blitSurface ( temp , NULL , dst , & dstRect ) ;
2008-05-27 16:16:35 +03:00
SDL_FreeSurface ( temp ) ;
2010-02-04 17:50:59 +02:00
}
2008-05-27 16:16:35 +03:00
2009-05-17 05:43:36 +03:00
// Vertical flip
2008-11-28 14:11:31 +02:00
SDL_Surface * CSDL_Ext : : rotate01 ( 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 bpl = ret - > pitch ;
const int bpp = ret - > format - > BytesPerPixel ;
for ( int i = 0 ; i < ret - > h ; i + + ) {
char * src = ( char * ) toRot - > pixels + i * bpl ;
char * dst = ( char * ) ret - > pixels + i * bpl ;
for ( int j = 0 ; j < ret - > w ; j + + ) {
for ( int k = 0 ; k < bpp ; k + + ) {
dst [ j * bpp + k ] = src [ ( ret - > w - j - 1 ) * bpp + k ] ;
2007-06-06 21:26:28 +03:00
}
}
}
2009-05-17 05:43:36 +03:00
2007-06-06 21:26:28 +03:00
return ret ;
}
2009-05-17 05:43:36 +03:00
// Horizontal flip
2007-06-07 04:22:06 +03:00
SDL_Surface * CSDL_Ext : : hFlip ( SDL_Surface * toRot )
{
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
int bpl = ret - > pitch ;
for ( int i = 0 ; i < ret - > h ; i + + ) {
memcpy ( ( char * ) ret - > pixels + i * bpl , ( char * ) toRot - > pixels + ( ret - > h - i - 1 ) * bpl , bpl ) ;
2007-06-07 04:22:06 +03:00
}
2009-05-17 05:43:36 +03:00
2007-06-07 04:22:06 +03:00
return ret ;
} ;
2007-06-06 21:26:28 +03:00
///**************/
///Rotates toRot surface by 90 degrees left
///**************/
SDL_Surface * CSDL_Ext : : rotate02 ( SDL_Surface * toRot )
{
2008-02-06 15:50:40 +02:00
SDL_Surface * ret = SDL_ConvertSurface ( toRot , toRot - > format , toRot - > flags ) ;
2007-06-25 17:55:45 +03:00
//SDL_SetColorKey(ret, SDL_SRCCOLORKEY, toRot->format->colorkey);
2007-06-06 21:26:28 +03:00
for ( int i = 0 ; i < ret - > w ; + + i )
{
for ( int j = 0 ; j < ret - > h ; + + j )
{
{
Uint8 * p = ( Uint8 * ) toRot - > pixels + i * toRot - > pitch + j * toRot - > format - > BytesPerPixel ;
2008-08-02 18:08:03 +03:00
/*
2007-11-20 19:52:22 +02:00
# if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
2008-11-28 14:11:31 +02:00
SDL_PutPixelWithoutRefresh ( ret , i , j , p [ 0 ] , p [ 1 ] , p [ 2 ] ) ;
2007-11-20 19:52:22 +02:00
# else
2008-08-02 18:08:03 +03:00
*/
2008-11-28 14:11:31 +02:00
SDL_PutPixelWithoutRefresh ( ret , i , j , p [ 2 ] , p [ 1 ] , p [ 0 ] ) ;
2008-08-02 18:08:03 +03:00
//#endif
2007-06-06 21:26:28 +03:00
}
}
}
return ret ;
}
///*************/
///Rotates toRot surface by 180 degrees
///*************/
SDL_Surface * CSDL_Ext : : rotate03 ( SDL_Surface * toRot )
{
2008-02-06 15:50:40 +02:00
SDL_Surface * ret = SDL_ConvertSurface ( toRot , toRot - > format , toRot - > flags ) ;
2007-06-25 17:55:45 +03:00
//SDL_SetColorKey(ret, SDL_SRCCOLORKEY, toRot->format->colorkey);
2007-06-26 15:38:58 +03:00
if ( ret - > format - > BytesPerPixel ! = 1 )
2007-06-06 21:26:28 +03:00
{
2007-06-26 15:38:58 +03:00
for ( int i = 0 ; i < ret - > w ; + + i )
2007-06-06 21:26:28 +03:00
{
2007-06-26 15:38:58 +03:00
for ( int j = 0 ; j < ret - > h ; + + j )
2007-06-06 21:26:28 +03:00
{
{
2007-06-26 15:38:58 +03:00
Uint8 * p = ( Uint8 * ) toRot - > pixels + ( ret - > h - j - 1 ) * toRot - > pitch + ( ret - > w - i - 1 ) * toRot - > format - > BytesPerPixel + 2 ;
2008-08-02 18:08:03 +03:00
/*
2007-11-20 19:52:22 +02:00
# if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
2008-11-28 14:11:31 +02:00
SDL_PutPixelWithoutRefresh ( ret , i , j , p [ 0 ] , p [ 1 ] , p [ 2 ] , 0 ) ;
2007-11-20 19:52:22 +02:00
# else
2008-08-02 18:08:03 +03:00
*/
2008-11-28 14:11:31 +02:00
SDL_PutPixelWithoutRefresh ( ret , i , j , p [ 2 ] , p [ 1 ] , p [ 0 ] , 0 ) ;
2008-08-02 18:08:03 +03:00
//#endif
2007-06-06 21:26:28 +03:00
}
}
}
}
2007-06-26 15:38:58 +03:00
else
{
for ( int i = 0 ; i < ret - > w ; + + i )
{
for ( int j = 0 ; j < ret - > h ; + + j )
{
Uint8 * p = ( Uint8 * ) toRot - > pixels + ( ret - > h - j - 1 ) * toRot - > pitch + ( ret - > w - i - 1 ) * toRot - > format - > BytesPerPixel ;
( * ( ( Uint8 * ) ret - > pixels + j * ret - > pitch + i * ret - > format - > BytesPerPixel ) ) = * p ;
}
}
}
2007-06-06 21:26:28 +03:00
return ret ;
}
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
{
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 ;
2008-12-23 15:59:03 +02:00
switch ( bpp )
{
2007-06-19 17:41:03 +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
case 2 :
return * ( Uint16 * ) p ;
case 3 :
2008-08-02 18:08:03 +03:00
/*
2007-11-20 19:52:22 +02:00
# if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
2007-06-19 17:41:03 +03:00
return p [ 0 ] < < 16 | p [ 1 ] < < 8 | p [ 2 ] ;
2007-11-20 19:52:22 +02:00
# else
2008-08-02 18:08:03 +03:00
*/
2007-06-19 17:41:03 +03:00
return p [ 0 ] | p [ 1 ] < < 8 | p [ 2 ] < < 16 ;
2008-08-02 18:08:03 +03:00
//#endif
2007-06-19 17:41:03 +03:00
case 4 :
return * ( Uint32 * ) p ;
default :
2009-02-08 17:39:26 +02:00
return 0 ; // shouldn't happen, but avoids warnings
2007-06-19 17:41:03 +03:00
}
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 ) ;
SDL_Color colors [ ] = { { 0 , 0 , 0 , 255 } , { 0 , 0 , 0 , 214 } , { 0 , 0 , 0 , 164 } , { 0 , 0 , 0 , 82 } , { 0 , 0 , 0 , 128 } ,
{ 255 , 0 , 0 , 0 } , { 255 , 0 , 0 , 0 } , { 255 , 0 , 0 , 0 } , { 0 , 0 , 0 , 192 } , { 0 , 0 , 0 , 192 } } ;
2008-08-02 18:08:03 +03:00
2009-07-27 15:29:10 +03:00
SDL_SetColors ( src , colors , 0 , ARRAY_COUNT ( colors ) ) ;
SDL_SetColorKey ( src , SDL_SRCCOLORKEY , SDL_MapRGBA ( src - > format , 0 , 0 , 0 , 255 ) ) ;
2007-06-25 17:55:45 +03:00
}
2008-11-30 02:15:38 +02: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
{
2010-08-05 14:02:18 +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
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
{
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
}
2010-08-05 14:02:18 +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
{
2010-08-05 14:02:18 +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
if ( ! rotation )
{
blit8bppAlphaTo24bpp ( src , srcRect , dst , dstRect ) ;
}
else
{
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 : : 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
{
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 + + )
2010-08-05 14:02:18 +03:00
ColorPutter < bpp , - 1 > : : PutColor ( dp , colors [ * sp ] ) ;
2009-12-22 23:53:50 +02:00
sp + = src - > w - dstRect - > w ;
}
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 )
{
2008-02-10 19:44:51 +02:00
SDL_SetError ( " SDL_UpperBlit: passed a NULL 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
2008-02-10 19:44:51 +02:00
/* If the destination rectangle is NULL, use the entire dest surface */
2008-12-23 15:59:03 +02:00
if ( dstRect = = NULL )
{
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
ColorPutter < bpp , + 1 > : : PutColorAlphaSwitch ( p , tbc . r , tbc . g , tbc . b , tbc . unused ) ;
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 :
tlog1 < < ( int ) dst - > format - > BitsPerPixel < < " bpp is not supported!!! \n " ;
return - 1 ;
}
}
2007-06-25 17:55:45 +03:00
Uint32 CSDL_Ext : : colorToUint32 ( const SDL_Color * color )
{
Uint32 ret = 0 ;
ret + = color - > unused ;
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 )
{
2007-08-21 16:48:18 +03:00
if ( what )
SDL_UpdateRect ( what , 0 , 0 , what - > w , what - > h ) ;
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 ) ;
}
2010-08-05 14:02:18 +03:00
void CSDL_Ext : : drawDashedBorder ( SDL_Surface * sur , const Rect & r , const int3 & color )
{
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 ) ;
}
}
}
2007-10-07 19:01:53 +03:00
void CSDL_Ext : : setPlayerColor ( SDL_Surface * sur , unsigned char player )
2007-07-16 13:03:54 +03:00
{
2007-10-07 19:01:53 +03:00
if ( player = = 254 )
return ;
2007-07-16 13:03:54 +03:00
if ( sur - > format - > BitsPerPixel = = 8 )
{
2010-03-21 00:17:19 +02:00
SDL_Color * color = ( player = = 255
? graphics - > neutralColor
: & graphics - > playerColors [ player ] ) ;
SDL_SetColors ( sur , color , 5 , 1 ) ;
2007-07-16 13:03:54 +03:00
}
2010-03-21 00:17:19 +02:00
else
tlog3 < < " Warning, setPlayerColor called on not 8bpp surface! \n " ;
2007-08-06 07:03:34 +03:00
}
int readNormalNr ( std : : istream & in , int bytCon )
{
int ret = 0 ;
int amp = 1 ;
unsigned char byte ;
if ( in . good ( ) )
{
for ( int i = 0 ; i < bytCon ; i + + )
{
in . read ( ( char * ) & byte , 1 ) ;
ret + = byte * amp ;
2008-01-30 16:19:35 +02:00
amp < < = 8 ;
2007-08-06 07:03:34 +03:00
}
}
else return - 1 ;
return ret ;
}
2007-08-17 20:42:21 +03:00
2010-08-12 08:22:48 +03:00
const 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 :
tlog1 < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported! \n " ;
2010-08-12 08:22:48 +03:00
return NULL ;
2010-08-05 14:02:18 +03:00
}
}
2010-08-12 08:22:48 +03:00
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 )
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 )
{
if ( srf - > format - > BytesPerPixel = = 1 )
{
return ( ( ui8 * ) srf - > pixels ) [ x + srf - > pitch * y ] = = 0 ;
}
else
{
assert ( ! " isTransparent called with non-8bpp surface! " ) ;
}
2010-08-05 14:02:18 +03:00
return false ;
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 ) ;
//needed?
if ( ekran - > format - > BytesPerPixel = = 4 )
p [ 3 ] = A ;
}
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*/ )
{
2011-04-29 03:50:54 +03:00
if ( x > = 0 & & x < ekran - > w & & y > = 0 & & y < ekran - > h )
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 :
tlog1 < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported!!! \n " ;
break ;
}
assert ( 0 ) ;
return NULL ;
}
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 :
tlog1 < < ( int ) dest - > format - > BitsPerPixel < < " bpp is not supported!!! \n " ;
break ;
}
assert ( 0 ) ;
return NULL ;
}
2010-08-17 15:48:34 +03:00
void CSDL_Ext : : applyEffect ( SDL_Surface * surf , const SDL_Rect * rect , int mode )
{
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 )
{
unsigned char * pixels = ( unsigned char * ) surf - > pixels + yp * surf - > pitch + xp * surf - > format - > BytesPerPixel ;
int b = pixels [ 0 ] ;
int g = pixels [ 1 ] ;
int r = pixels [ 2 ] ;
int gry = ( r + g + b ) / 3 ;
r = g = b = gry ;
r = r + ( sepiaDepth * 2 ) ;
g = g + sepiaDepth ;
if ( r > 255 ) r = 255 ;
if ( g > 255 ) g = 255 ;
if ( b > 255 ) b = 255 ;
// Darken blue color to increase sepia effect
b - = sepiaIntensity ;
// normalize if out of bounds
if ( b < 0 ) b = 0 ;
if ( b > 255 ) b = 255 ;
pixels [ 0 ] = b ;
pixels [ 1 ] = g ;
pixels [ 2 ] = r ;
}
}
}
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 )
{
unsigned char * pixels = ( unsigned char * ) surf - > pixels + yp * surf - > pitch + xp * surf - > format - > BytesPerPixel ;
int b = pixels [ 0 ] ;
int g = pixels [ 1 ] ;
int r = pixels [ 2 ] ;
int gry = ( r + g + b ) / 3 ;
pixels [ 0 ] = pixels [ 1 ] = pixels [ 2 ] = gry ;
}
}
}
break ;
default :
throw std : : string ( " Unsuppoerted efftct! " ) ;
}
}
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
{
betterDst = Rect ( 0 , 0 , dst - > w , dst - > h ) ;
}
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
{
newRect = Rect ( 0 , 0 , dst - > w , dst - > h ) ;
}
SDL_FillRect ( dst , & newRect , color ) ;
}
2008-02-06 15:50:40 +02:00
SDL_Surface * CSDL_Ext : : std32bppSurface = NULL ;
2011-02-06 19:26:27 +02:00
2011-02-20 11:24:53 +02:00
//instantiation of templates used in CAnimation and CCreatureAnimation, required for correct linking
template struct ColorPutter < 2 , - 1 > ;
template struct ColorPutter < 3 , - 1 > ;
template struct ColorPutter < 4 , - 1 > ;
template struct ColorPutter < 2 , 0 > ;
template struct ColorPutter < 3 , 0 > ;
template struct ColorPutter < 4 , 0 > ;
template struct ColorPutter < 2 , 1 > ;
template struct ColorPutter < 3 , 1 > ;
template struct ColorPutter < 4 , 1 > ;