X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=lib%2Fvideo%2Fsurface.cpp;h=bcb8dc8660e100bb9ec4cd04427076467646ed09;hb=5cbc442143d66a117c0a50e3bfb7969b622be2a8;hp=57cc4d270f372b4b8df9570a2f4651dc412f10e8;hpb=c5cbd36c2e01d8c807c8c931ca44fb7c1b48ad18;p=supertux.git diff --git a/lib/video/surface.cpp b/lib/video/surface.cpp index 57cc4d270..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" @@ -173,11 +174,8 @@ Surface::Surface(const std::string& file, int x, int y, int w, int h, bool use_a } Surface::Surface(Color top_background, Color bottom_background, int w_, int h_) - : data(top_background, bottom_background, 0, 0), w(0), h(0) + : data(top_background, bottom_background, w_, h_), w(0), h(0) { - // FIXME: Gradient surfaces currently don't accept width/height - // If nonzero values are passed to data.create(), supertux - // crashes. impl = data.create(); if (impl) { @@ -196,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 @@ -249,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) { @@ -333,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; @@ -344,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"); @@ -373,7 +433,7 @@ sdl_surface_from_gradient(Color top, Color bottom, int w, int h) sdl_surface = SDL_CreateRGBSurface(screen->flags, w, h, screen->format->BitsPerPixel, screen->format->Rmask, - screen->format->Gmask, screen->format->Bmask, screen->format->Amask); + screen->format->Gmask, screen->format->Bmask, 0); if(sdl_surface == NULL) Termination::abort("Cannot create surface for the gradient", "SURFACE"); @@ -571,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); @@ -585,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); @@ -628,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); @@ -642,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); @@ -665,32 +781,84 @@ SurfaceOpenGL::draw_part(float sx, float sy, float x, float y, float w, float h, return 0; } -#if 0 int -SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha) +SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uint32 effect) { - float pw = power_of_two(int(this->w)); - float ph = power_of_two(int(this->h)); + if(effect & SEMI_TRANSPARENT) + alpha = 128; - glBindTexture(GL_TEXTURE_2D, gl_texture); + float pw = power_of_two(sw); + float ph = power_of_two(sh); + if(effect & SEMI_TRANSPARENT) + alpha = 128; + + glEnable(GL_TEXTURE_2D); glEnable(GL_BLEND); glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); glColor4ub(alpha, alpha, alpha, alpha); - glEnable(GL_TEXTURE_2D); - + glBindTexture(GL_TEXTURE_2D, gl_texture); glBegin(GL_QUADS); - glTexCoord2f(0, 0); - glVertex2f(x, y); - glTexCoord2f((float)w / pw, 0); - glVertex2f(sw+x, y); - glTexCoord2f((float)w / pw, (float)h / ph); glVertex2f((float)sw+x, (float)sh+y); - glVertex2f(sw +x, sh+y); - glTexCoord2f(0, (float)h / ph); - glVertex2f(x, sh+y); + + 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); + + glTexCoord2f((float)w / pw, 0); + glVertex2f((float)sw+x, (float)sh+y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f((float)sw+x, y); + + 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); + glVertex2f(x, y); + + glTexCoord2f((float)w / pw, 0); + glVertex2f((float)sw+x, y); + + glTexCoord2f((float)w / pw, (float)h / ph); + glVertex2f((float)sw+x, (float)sh+y); + + glTexCoord2f(0, (float)h / ph); + glVertex2f(x, (float)sh+y); + } glEnd(); glDisable(GL_TEXTURE_2D); @@ -698,7 +866,16 @@ SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha) return 0; } -#endif + +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 @@ -743,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) { @@ -800,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); @@ -825,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); @@ -839,9 +1048,8 @@ SurfaceSDL::draw_part(float sx, float sy, float x, float y, float w, float h, Ui return ret; } -#if 0 int -SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool update) +SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, Uint32 effect) { SDL_Rect dest; @@ -850,9 +1058,8 @@ SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool u dest.w = (int)sw; dest.h = (int)sh; - if(alpha != 255) - SDL_SetAlpha(sdl_surface ,SDL_SRCALPHA,alpha); - + if(effect & SEMI_TRANSPARENT) + alpha = 128; SDL_Surface* sdl_surface_copy = SDL_CreateRGBSurface (sdl_surface->flags, sw, sh, sdl_surface->format->BitsPerPixel, @@ -863,15 +1070,23 @@ SurfaceSDL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha, bool u SDL_BlitSurface(sdl_surface, NULL, sdl_surface_copy, NULL); SDL_SoftStretch(sdl_surface_copy, NULL, sdl_surface_copy, &dest); + if(alpha != 255) + SDL_SetAlpha(sdl_surface_copy,SDL_SRCALPHA,alpha); + int ret = SDL_BlitSurface(sdl_surface_copy,NULL,screen,&dest); SDL_FreeSurface(sdl_surface_copy); - if (update == UPDATE) - update_rect(screen, dest.x, dest.y, dest.w, dest.h); - return ret; } -#endif + +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() {}