00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022 #include "surface.h"
00023 #include <SDL.h>
00024 #include <SDL_endian.h>
00025 #include <SDL_gfxPrimitives.h>
00026 #include <SDL_image.h>
00027 #include <SDL_rotozoom.h>
00028 #include "../tool/debug.h"
00029 #include "../tool/error.h"
00030 #include "../tool/i18n.h"
00031 #include "../include/base.h"
00032
00038 Surface::Surface(){
00039 surface = NULL;
00040 autoFree = true;
00041 }
00042
00048 Surface::Surface(SDL_Surface *sdl_surface){
00049 surface = sdl_surface;
00050 autoFree = true;
00051 }
00052
00061 Surface::Surface(const Point2i &size, Uint32 flags, bool useAlpha){
00062 surface = NULL;
00063 autoFree = true;
00064 NewSurface(size, flags, useAlpha);
00065 }
00066
00072 Surface::Surface(const std::string &filename){
00073 surface = NULL;
00074 autoFree = true;
00075 if( !ImgLoad(filename) )
00076 Error( Format("Unable to open image file : %s", filename.c_str() ) );
00077 }
00078
00084 Surface::Surface(const Surface &src){
00085 surface = src.surface;
00086 autoFree = true;
00087 if( !IsNull() )
00088 surface->refcount++;
00089 }
00090
00096 Surface::~Surface(){
00097 AutoFree();
00098 }
00099
00100 Surface &Surface::operator=(const Surface & src){
00101 AutoFree();
00102 surface = src.surface;
00103 if( !IsNull() )
00104 surface->refcount++;
00105
00106 return *this;
00107 }
00108
00114 void Surface::Free(){
00115 if( !IsNull() ){
00116 SDL_FreeSurface( surface );
00117 surface = NULL;
00118 }
00119 }
00120
00121 void Surface::AutoFree(){
00122 if( autoFree )
00123 Free();
00124 }
00125
00132 void Surface::SetAutoFree( bool newAutoFree ){
00133 autoFree = newAutoFree;
00134 }
00135
00141 SDL_Surface *Surface::GetSurface(){
00142 return surface;
00143 }
00144
00151 void Surface::SetSurface(SDL_Surface *newSurface, bool freePrevious){
00152 if( freePrevious )
00153 Free();
00154
00155 surface = newSurface;
00156 }
00157
00165 void Surface::NewSurface(const Point2i &size, Uint32 flags, bool useAlpha){
00166 Uint32 alphaMask;
00167 Uint32 redMask;
00168 Uint32 greenMask;
00169 Uint32 blueMask;
00170
00171 if( autoFree )
00172 Free();
00173
00174 #if SDL_BYTEORDER == SDL_LIL_ENDIAN
00175 redMask = 0xff000000;
00176 greenMask = 0x00ff0000;
00177 blueMask = 0x0000ff00;
00178 alphaMask = 0x000000ff;
00179 #else
00180 redMask = 0x000000ff;
00181 greenMask = 0x0000ff00;
00182 blueMask = 0x00ff0000;
00183 alphaMask = 0xff000000;
00184 #endif
00185
00186 if( !useAlpha )
00187 alphaMask = 0;
00188
00189 surface = SDL_CreateRGBSurface(flags, size.x, size.y, 32,
00190 redMask, greenMask, blueMask, alphaMask );
00191
00192 if( surface == NULL )
00193 Error( std::string("Can't create SDL RGBA surface: ") + SDL_GetError() );
00194 }
00195
00200 int Surface::SetAlpha(Uint32 flags, Uint8 alpha){
00201 return SDL_SetAlpha( surface, flags, alpha );
00202 }
00203
00208 int Surface::Lock(){
00209 return SDL_LockSurface( surface );
00210 }
00211
00216 void Surface::Unlock(){
00217 SDL_UnlockSurface( surface );
00218 }
00219
00220 int Surface::Blit(const Surface& src, SDL_Rect *srcRect, SDL_Rect *dstRect){
00221 return SDL_BlitSurface( src.surface, srcRect, surface, dstRect );
00222 }
00223
00229 int Surface::Blit(const Surface& src){
00230 return Blit(src, NULL, NULL);
00231 }
00232
00239 int Surface::Blit(const Surface& src, const Point2i &dst){
00240 SDL_Rect dstRect = GetSDLRect( dst );;
00241
00242 return Blit(src, NULL, &dstRect);
00243 }
00244
00252 int Surface::Blit(const Surface& src, const Rectanglei &srcRect, const Point2i &dstPoint){
00253 SDL_Rect sdlSrcRect = GetSDLRect( srcRect );
00254 SDL_Rect sdlDstRect = GetSDLRect( dstPoint );
00255
00256 return Blit(src, &sdlSrcRect, &sdlDstRect);
00257 }
00258
00264 int Surface::SetColorKey(Uint32 flag, Uint32 key){
00265 return SDL_SetColorKey( surface, flag, key );
00266 }
00267
00277 int Surface::SetColorKey(Uint32 flag, Uint8 r, Uint8 g, Uint8 b, Uint8 a){
00278 return SetColorKey( flag, MapRGBA(r, g, b, a) );
00279 }
00280
00288 void Surface::GetRGBA(Uint32 color, Uint8 &r, Uint8 &g, Uint8 &b, Uint8 &a) const
00289 {
00290 SDL_GetRGBA(color, surface->format, &r, &g, &b, &a);
00291 }
00292
00299 Uint32 Surface::MapRGBA(Uint8 r, Uint8 g, Uint8 b, Uint8 a) const
00300 {
00301 return SDL_MapRGBA(surface->format, r, g, b, a);
00302 }
00303
00308 Color Surface::GetColor(Uint32 color) const
00309 {
00310 Uint8 r, g, b, a;
00311 GetRGBA(color, r, g, b, a);
00312 return Color(r, g, b, a);
00313 }
00314
00319 Uint32 Surface::MapColor(Color color) const
00320 {
00321 return MapRGBA(color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00322 }
00323
00327 void Surface::SetClipRect(const Rectanglei &rect){
00328 SDL_Rect sdlRect = GetSDLRect( rect );
00329 SDL_SetClipRect( surface, &sdlRect );
00330 }
00331
00332 void Surface::Flip(){
00333 SDL_Flip( surface );
00334 }
00335
00336 int Surface::BoxColor(const Rectanglei &rect, const Color &color){
00337 if( rect.IsSizeZero() )
00338 return 0;
00339
00340 Point2i ptBR = rect.GetBottomRightPoint();
00341
00342 return boxRGBA( surface, rect.GetPositionX(), rect.GetPositionY(), ptBR.GetX(), ptBR.GetY(), color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00343 }
00344
00345 int Surface::RectangleColor(const Rectanglei &rect, const Color &color, const uint &border_size)
00346 {
00347 if( rect.IsSizeZero() )
00348 return 0;
00349
00350 Point2i ptBR = rect.GetBottomRightPoint();
00351
00352 if (border_size == 1)
00353 return rectangleRGBA( surface, rect.GetPositionX(), rect.GetPositionY(), ptBR.GetX(), ptBR.GetY(), color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00354
00355
00356 boxRGBA (surface,
00357 rect.GetPositionX(), rect.GetPositionY(), ptBR.GetX(), rect.GetPositionY()+border_size,
00358 color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00359
00360
00361 boxRGBA (surface,
00362 rect.GetPositionX(), ptBR.GetY() - border_size, ptBR.GetX(), ptBR.GetY(),
00363 color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00364
00365
00366 boxRGBA (surface,
00367 rect.GetPositionX(), rect.GetPositionY() + border_size, rect.GetPositionX()+border_size, ptBR.GetY()-border_size,
00368 color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00369
00370
00371 boxRGBA (surface,
00372 ptBR.GetX() - border_size, rect.GetPositionY() + border_size, ptBR.GetX(), ptBR.GetY()-border_size,
00373 color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00374
00375 return 1;
00376 }
00377
00378 int Surface::VlineColor(const uint &x1, const uint &y1, const uint &y2, const Color &color){
00379 return vlineRGBA( surface, x1, y1, y2, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00380 }
00381
00382 int Surface::LineColor(const uint &x1, const uint &x2, const uint &y1, const uint &y2, const Color &color){
00383 return lineRGBA( surface, x1, y1, x2, y2, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00384 }
00385
00386 int Surface::AALineColor(const uint &x1, const uint &x2, const uint &y1, const uint &y2, const Color &color){
00387 return aalineRGBA( surface, x1, y1, x2, y2, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00388 }
00389
00390 int Surface::CircleColor(const uint &x, const uint &y, const uint &rad, const Color &color){
00391 return circleRGBA( surface, x, y, rad, color.GetRed(), color.GetGreen(), color.GetBlue(), color.GetAlpha() );
00392 }
00393
00398 int Surface::Fill(Uint32 color) const {
00399 return SDL_FillRect( surface, NULL, color);
00400 }
00401
00402 int Surface::Fill(const Color &color) const{
00403 return Fill( MapColor(color) );
00404 }
00405
00411 int Surface::FillRect(const Rectanglei &dstRect, Uint32 color) const{
00412 SDL_Rect sdlDstRect = GetSDLRect( dstRect );
00413
00414 return SDL_FillRect( surface, &sdlDstRect, color);
00415 }
00416
00422 int Surface::FillRect(const Rectanglei &dstRect, const Color &color) const{
00423
00424 return FillRect( dstRect, MapColor(color) );
00425 }
00426
00431 int Surface::ImgLoad(std::string filename){
00432 AutoFree();
00433 surface = IMG_Load( filename.c_str() );
00434
00435 return !IsNull();
00436 }
00437
00447 static const double ratio_deg_to_rad = 180 / M_PI;
00448 Surface Surface::RotoZoom(double angle, double zoomx, double zoomy, int smooth){
00449 Surface newSurf;
00450
00451 newSurf.SetSurface( rotozoomSurfaceXY(surface, angle * ratio_deg_to_rad , zoomx, zoomy, smooth) );
00452
00453 if( newSurf.IsNull() )
00454 Error( "Unable to make a rotozoom on the surface !" );
00455
00456 return newSurf;
00457 }
00458
00462 Surface Surface::DisplayFormatAlpha(){
00463 Surface newSurf;
00464
00465 newSurf.SetSurface( SDL_DisplayFormatAlpha( surface ) );
00466
00467 if( newSurf.IsNull() )
00468 Error( "Unable to convert the surface to a surface compatible with the display format with alpha." );
00469
00470 return newSurf;
00471 }
00472
00476 Surface Surface::DisplayFormat(){
00477 Surface newSurf;
00478
00479 newSurf.SetSurface( SDL_DisplayFormat( surface ) );
00480
00481 if( newSurf.IsNull() )
00482 Error( "Unable to convert the surface to a surface compatible with the display format." );
00483
00484 return newSurf;
00485 }
00486
00487
00495 Uint32 Surface::GetPixel(int x, int y){
00496 int bpp = surface->format->BytesPerPixel;
00497
00498 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00499
00500 switch(bpp) {
00501 case 1:
00502 return *p;
00503
00504 case 2:
00505 return *(Uint16 *)p;
00506
00507 case 3:
00508 if(SDL_BYTEORDER == SDL_BIG_ENDIAN)
00509 return p[0] << 16 | p[1] << 8 | p[2];
00510 else
00511 return p[0] | p[1] << 8 | p[2] << 16;
00512
00513 case 4:
00514 return *(Uint32 *)p;
00515
00516 default:
00517 Error("Unknow bpp!");
00518 return 0;
00519 }
00520 }
00521
00528 void Surface::PutPixel(int x, int y, Uint32 pixel){
00529 int bpp = surface->format->BytesPerPixel;
00530
00531 Uint8 *p = (Uint8 *)surface->pixels + y * surface->pitch + x * bpp;
00532
00533 switch(bpp) {
00534 case 1:
00535 *p = pixel;
00536 break;
00537
00538 case 2:
00539 *(Uint16 *)p = pixel;
00540 break;
00541
00542 case 3:
00543 if(SDL_BYTEORDER == SDL_BIG_ENDIAN) {
00544 p[0] = (pixel >> 16) & 0xff;
00545 p[1] = (pixel >> 8) & 0xff;
00546 p[2] = pixel & 0xff;
00547 } else {
00548 p[0] = pixel & 0xff;
00549 p[1] = (pixel >> 8) & 0xff;
00550 p[2] = (pixel >> 16) & 0xff;
00551 }
00552 break;
00553
00554 case 4:
00555 *(Uint32 *)p = pixel;
00556 break;
00557 }
00558 }
00559
00560 SDL_Rect Surface::GetSDLRect(const Rectanglei &r) const
00561 {
00562 SDL_Rect sdlRect;
00563
00564 sdlRect.x = r.GetPositionX();
00565 sdlRect.y = r.GetPositionY();
00566 sdlRect.w = r.GetSizeX();
00567 sdlRect.h = r.GetSizeY();
00568
00569 return sdlRect;
00570 }
00571
00572 SDL_Rect Surface::GetSDLRect(const Point2i &pt) const
00573 {
00574 SDL_Rect sdlRect;
00575
00576 sdlRect.x = pt.GetX();
00577 sdlRect.y = pt.GetY();
00578 sdlRect.w = 0;
00579 sdlRect.h = 0;
00580
00581 return sdlRect;
00582 }