X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=lib%2Fvideo%2Fsurface.cpp;h=bcb8dc8660e100bb9ec4cd04427076467646ed09;hb=5cbc442143d66a117c0a50e3bfb7969b622be2a8;hp=b609f7a9b19c1c710924d5a4234d13c840158a01;hpb=580daade35c151e51a90560fe0cac8c7e1b05ca7;p=supertux.git diff --git a/lib/video/surface.cpp b/lib/video/surface.cpp index b609f7a9b..bcb8dc866 100644 --- a/lib/video/surface.cpp +++ b/lib/video/surface.cpp @@ -26,6 +26,7 @@ #include "SDL_image.h" #include "../video/surface.h" +#include "../video/screen.h" #include "../app/globals.h" #include "../app/setup.h" @@ -193,9 +194,23 @@ Surface::reload() { w = impl->w; h = impl->h; + for(std::vector::iterator i = + data.applied_filters.begin(); i != data.applied_filters.end(); + i++) + impl->apply_filter(i->type, i->color); } } +void Surface::apply_filter(int filter, Color color) +{ +impl->apply_filter(filter, color); + +SurfaceData::Filter apply_filter; +apply_filter.type = filter; +apply_filter.color = color; +data.applied_filters.push_back(apply_filter); +} + Surface::~Surface() { #ifdef DEBUG @@ -246,6 +261,50 @@ Surface::resize(int w_, int h_) } } +void +apply_filter_to_surface(SDL_Surface* surface, int filter, Color color) +{ +if(filter == HORIZONTAL_FLIP_FILTER) + { + SDL_Surface* sur_copy = sdl_surface_from_sdl_surface(surface, true); + SDL_BlitSurface(surface, NULL, sur_copy, NULL); + SDL_SetAlpha(sur_copy,0,0); + + SDL_Rect src, dst; + src.y = dst.y = 0; + src.w = dst.w = 1; + src.h = dst.h = sur_copy->h; + for(int x = 0; x < sur_copy->w; x++) + { + src.x = x; dst.x = sur_copy->w - x; + SDL_BlitSurface(sur_copy, &src, surface, &dst); + } + + SDL_FreeSurface(sur_copy); + } +else if(filter == MASK_FILTER) + { + SDL_Surface* sur_copy = sdl_surface_from_sdl_surface(surface, true); + + Uint8 r,g,b,a; + + SDL_LockSurface(sur_copy); + for(int x = 0; x < sur_copy->w; x++) + for(int y = 0; y < sur_copy->h; y++) + { + SDL_GetRGBA(getpixel(sur_copy,x,y), sur_copy->format, &r,&g,&b,&a); + if(a != 0) + { + putpixel(sur_copy, x,y, color.map_rgba(sur_copy)); + } + } + SDL_UnlockSurface(sur_copy); + + SDL_BlitSurface(sur_copy, NULL, surface, NULL); + SDL_FreeSurface(sur_copy); + } +} + SDL_Surface* sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, bool use_alpha) { @@ -330,6 +389,7 @@ SDL_Surface* SuperTux::sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, bool use_alpha) { SDL_Surface* sdl_surface; +#if 0 Uint32 saved_flags; Uint8 saved_alpha; @@ -341,18 +401,21 @@ SuperTux::sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, bool use_alpha) { SDL_SetAlpha(sdl_surf, 0, 0); } +#endif if(use_alpha == false && !use_gl) sdl_surface = SDL_DisplayFormat(sdl_surf); else sdl_surface = SDL_DisplayFormatAlpha(sdl_surf); +#if 0 /* Restore the alpha blending attributes */ if ( (saved_flags & SDL_SRCALPHA) == SDL_SRCALPHA ) { SDL_SetAlpha(sdl_surface, saved_flags, saved_alpha); } +#endif if (sdl_surface == NULL) Termination::abort("Can't covert to display format", "SURFACE"); @@ -568,7 +631,21 @@ SurfaceOpenGL::draw(float x, float y, Uint8 alpha, Uint32 effect) glBegin(GL_QUADS); - if(effect & VERTICAL_FLIP) + if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP) + { + glTexCoord2f(0, 0); + glVertex2f((float)w+x, (float)h+y); + + glTexCoord2f((float)w / pw, 0); + glVertex2f(x, (float)h+y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f(x, y); + + glTexCoord2f(0, (float)h / ph); + glVertex2f((float)w+x, y); + } + else if(effect & VERTICAL_FLIP) { glTexCoord2f(0, 0); glVertex2f(x, (float)h+y); @@ -582,6 +659,20 @@ SurfaceOpenGL::draw(float x, float y, Uint8 alpha, Uint32 effect) glTexCoord2f(0, (float)h / ph); glVertex2f(x, y); } + else if(effect & HORIZONTAL_FLIP) + { + glTexCoord2f(0, 0); + glVertex2f((float)w+x, y); + + glTexCoord2f((float)w / pw, 0); + glVertex2f(x, y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f(x, (float)h+y); + + glTexCoord2f(0, (float)h / ph); + glVertex2f((float)w+x, (float)h+y); + } else { glTexCoord2f(0, 0); @@ -625,7 +716,21 @@ SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, glBegin(GL_QUADS); - if(effect & VERTICAL_FLIP) + if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP) + { + glTexCoord2f(sx / pw, (float)(sy+h) / ph); + glVertex2f((float)w+x, (float)h+y); + + glTexCoord2f((sx+w) / pw, (sy+h) / ph); + glVertex2f(x, (float)h+y); + + glTexCoord2f((float)(sx + w) / pw, sy / ph); + glVertex2f(x, y); + + glTexCoord2f(sx / pw, sy / ph); + glVertex2f((float)w+x, y); + } + else if(effect & VERTICAL_FLIP) { glTexCoord2f(sx / pw, sy / ph); glVertex2f(x, y); @@ -639,6 +744,20 @@ SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, glTexCoord2f(sx / pw, (float)(sy+h) / ph); glVertex2f(x, h+y); } + else if(effect & HORIZONTAL_FLIP) + { + glTexCoord2f(sx / pw, sy / ph); + glVertex2f((float)w+x, y); + + glTexCoord2f((float)(sx + w) / pw, sy / ph); + glVertex2f(x, y); + + glTexCoord2f((sx+w) / pw, (sy+h) / ph); + glVertex2f(x, (float)h+y); + + glTexCoord2f(sx / pw, (float)(sy+h) / ph); + glVertex2f((float)w+x, (float)h+y); + } else { glTexCoord2f(sx / pw, (float)(sy+h) / ph); @@ -684,7 +803,21 @@ SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uin glBegin(GL_QUADS); - if(effect & VERTICAL_FLIP) + if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP) + { + glTexCoord2f(0, 0); + glVertex2f((float)sw+x, (float)sh+y); + + glTexCoord2f((float)w / pw, 0); + glVertex2f(x, (float)sh+y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f(x, y); + + glTexCoord2f(0, (float)h / ph); + glVertex2f((float)sw+x, y); + } + else if(effect & VERTICAL_FLIP) { glTexCoord2f(0, 0); glVertex2f(x, (float)sh+y); @@ -698,6 +831,20 @@ SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uin glTexCoord2f(0, (float)h / ph); glVertex2f(x, y); } + else if(effect & HORIZONTAL_FLIP) + { + glTexCoord2f(0, 0); + glVertex2f((float)sw+x, y); + + glTexCoord2f((float)w / pw, 0); + glVertex2f(x, y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f(x, (float)sh+y); + + glTexCoord2f(0, (float)h / ph); + glVertex2f((float)sw+x, (float)sh+y); + } else { glTexCoord2f(0, 0); @@ -720,6 +867,16 @@ SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uin return 0; } +void +SurfaceOpenGL::apply_filter(int filter, Color color) +{ + ::apply_filter_to_surface(sdl_surface, filter, color); + create_gl(sdl_surface,&gl_texture); + + w = sdl_surface->w; + h = sdl_surface->h; +} + #endif SurfaceSDL::SurfaceSDL(SDL_Surface* surf, bool use_alpha) @@ -763,13 +920,29 @@ SurfaceSDL::draw(float x, float y, Uint8 alpha, Uint32 effect) if(effect & SEMI_TRANSPARENT) alpha = 128; - if(effect & VERTICAL_FLIP) // FIXME: feel free to replace this hack + if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP) + { + // FIXME: this hack is damn slow. Just keep it cause it isn't that used. + for(float sx = 0; sx < w; sx++) + for(float sy = 0; sy < h; sy++) + if(draw_part(sx, sy, x+(w-sx), y+(h-sy), 1, 1, alpha, NONE_EFFECT) == -2) + return -2; + return 0; + } + else if(effect & VERTICAL_FLIP) // FIXME: feel free to replace this hack { for(float sy = 0; sy < h; sy++) if(draw_part(0, sy, x, y+(h-sy), w, 1, alpha, NONE_EFFECT) == -2) return -2; return 0; } + else if(effect & HORIZONTAL_FLIP) // FIXME: feel free to replace this hack + { + for(float sx = 0; sx < w; sx++) + if(draw_part(sx, 0, x+(w-sx), y, 1, h, alpha, NONE_EFFECT) == -2) + return -2; + return 0; + } if(alpha != 255) { @@ -820,23 +993,39 @@ SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Ui if(effect & SEMI_TRANSPARENT) alpha = 128; - if(effect & VERTICAL_FLIP) // FIXME: feel free to replace this hack + if(effect & VERTICAL_FLIP & HORIZONTAL_FLIP) + { + // FIXME: this hack is damn slow. Just keep it cause it isn't that used. + for(float sx_ = 0; sx_ < w; sx++) + for(float sy_ = 0; sy_ < h; sy++) + if(draw_part(sx_, sy_, sx+(w-sx_), sy+(h-sy_), 1, 1, alpha, NONE_EFFECT) == -2) + return -2; + return 0; + } + else if(effect & VERTICAL_FLIP) // FIXME: feel free to replace this hack { for(float sy_ = sy; sy_ < h; sy_++) if(draw_part(sx, sy_, x, y+(h-sy_), w, 1, alpha, NONE_EFFECT) == -2) return -2; return 0; } + else if(effect & HORIZONTAL_FLIP) // FIXME: feel free to replace this hack + { + for(float sx_ = 0; sx_ < w; sx_++) + if(draw_part(sx_, 0, sx+(w-sx_), sy, 1, h, alpha, NONE_EFFECT) == -2) + return -2; + return 0; + } if(alpha != 255) { /* Create a Surface, make it using colorkey, blit surface into temp, apply alpha to temp sur, blit the temp into the screen */ /* Note: this has to be done, since SDL doesn't allow to set alpha to surfaces that - already have an alpha mask yet... */ + already have an alpha mask, yet... */ SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags, - sdl_surface->w, sdl_surface->h, sdl_surface->format->BitsPerPixel, + (int)w, (int)h, sdl_surface->format->BitsPerPixel, sdl_surface->format->Rmask, sdl_surface->format->Gmask, sdl_surface->format->Bmask, 0); @@ -845,7 +1034,7 @@ SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Ui SDL_SetColorKey(sdl_surface_copy, SDL_SRCCOLORKEY, colorkey); - SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL); + SDL_BlitSurface(sdl_surface, &src, sdl_surface_copy, NULL); SDL_SetAlpha(sdl_surface_copy ,SDL_SRCALPHA,alpha); int ret = SDL_BlitSurface(sdl_surface_copy, NULL, screen, &dest); @@ -890,6 +1079,15 @@ SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uint32 return ret; } +void +SurfaceSDL::apply_filter(int filter, Color color) +{ + ::apply_filter_to_surface(sdl_surface, filter, color); + + w = sdl_surface->w; + h = sdl_surface->h; +} + SurfaceSDL::~SurfaceSDL() {}