X-Git-Url: https://git.verplant.org/?a=blobdiff_plain;f=lib%2Fvideo%2Fsurface.cpp;h=73dc131b4bf0b73b78bf7f28237746b5a21ca6e4;hb=1028ce017d6809007e39a8f7c034a0d62bfe3052;hp=8550573fb526c4b9a99339e6f7ae443702ca1564;hpb=edaacb3651cf0560314dd008d7243be4b3b2f8c6;p=supertux.git diff --git a/lib/video/surface.cpp b/lib/video/surface.cpp index 8550573fb..73dc131b4 100644 --- a/lib/video/surface.cpp +++ b/lib/video/surface.cpp @@ -25,9 +25,10 @@ #include "SDL.h" #include "SDL_image.h" -#include "video/surface.h" -#include "app/globals.h" -#include "app/setup.h" +#include "../video/surface.h" +#include "../video/screen.h" +#include "../app/globals.h" +#include "../app/setup.h" using namespace SuperTux; @@ -46,7 +47,7 @@ SurfaceData::SurfaceData(SDL_Surface* temp, bool use_alpha_) temp->format->Bmask, temp->format->Amask); if(!surface) - st_abort("No memory left.", ""); + Termination::abort("No memory left.", ""); SDL_SetAlpha(temp,0,0); SDL_BlitSurface(temp, NULL, surface, NULL); } @@ -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) { @@ -199,6 +197,11 @@ Surface::reload() } } +void Surface::apply_mask(Color color) +{ +impl->apply_mask(color); +} + Surface::~Surface() { #ifdef DEBUG @@ -249,6 +252,32 @@ Surface::resize(int w_, int h_) } } +void +apply_filter_to_surface(SDL_Surface* surface, int filter, Color color) +{ +if(filter == MASK_FILTER) + { + Uint8 r,g,b,a; + SDL_Rect rect; + rect.w = rect.h = 1; + SDL_LockSurface(surface); + for(int x = 0; x < surface->w; x++) + for(int y = 0; y < surface->h; y++) + { +// SDL_LockSurface(surface); + SDL_GetRGBA(getpixel(surface,x,y), surface->format, &r,&g,&b,&a); +// SDL_UnlockSurface(surface); + if(a != 0) + { + putpixel(surface, x,y, color.map_rgba(surface)); +// rect.x = x; rect.y = y; +// SDL_FillRect(surface, &rect, color.map_rgba(surface)); + } + } + SDL_UnlockSurface(surface); + } +} + SDL_Surface* sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, bool use_alpha) { @@ -260,7 +289,7 @@ sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, temp = IMG_Load(file.c_str()); if (temp == NULL) - st_abort("Can't load", file); + Termination::abort("Can't load", file); /* Set source rectangle for conv: */ @@ -291,7 +320,7 @@ sdl_surface_part_from_file(const std::string& file, int x, int y, int w, int h, sdl_surface = SDL_DisplayFormatAlpha(conv); if (sdl_surface == NULL) - st_abort("Can't covert to display format", file); + Termination::abort("Can't covert to display format", file); if (use_alpha == false && !use_gl) SDL_SetAlpha(sdl_surface, 0, 0); @@ -311,7 +340,7 @@ sdl_surface_from_file(const std::string& file, bool use_alpha) temp = IMG_Load(file.c_str()); if (temp == NULL) - st_abort("Can't load", file); + Termination::abort("Can't load", file); if(use_alpha == false && !use_gl) sdl_surface = SDL_DisplayFormat(temp); @@ -319,7 +348,7 @@ sdl_surface_from_file(const std::string& file, bool use_alpha) sdl_surface = SDL_DisplayFormatAlpha(temp); if (sdl_surface == NULL) - st_abort("Can't covert to display format", file); + Termination::abort("Can't covert to display format", file); if (use_alpha == false && !use_gl) SDL_SetAlpha(sdl_surface, 0, 0); @@ -358,7 +387,7 @@ SuperTux::sdl_surface_from_sdl_surface(SDL_Surface* sdl_surf, bool use_alpha) } if (sdl_surface == NULL) - st_abort("Can't covert to display format", "SURFACE"); + Termination::abort("Can't covert to display format", "SURFACE"); if (use_alpha == false && !use_gl) SDL_SetAlpha(sdl_surface, 0, 0); @@ -373,10 +402,10 @@ 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) - st_abort("Cannot create surface for the gradient", "SURFACE"); + Termination::abort("Cannot create surface for the gradient", "SURFACE"); if(top == bottom) { @@ -571,7 +600,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 +628,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 +685,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 +713,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 +750,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 +835,16 @@ SurfaceOpenGL::draw_stretched(float x, float y, int sw, int sh, Uint8 alpha) return 0; } -#endif + +void +SurfaceOpenGL::apply_mask(Color color) +{ + ::apply_filter_to_surface(sdl_surface, MASK_FILTER, color); + create_gl(sdl_surface,&gl_texture); + + w = sdl_surface->w; + h = sdl_surface->h; +} #endif @@ -743,13 +889,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,13 +962,29 @@ 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) { @@ -839,9 +1017,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 +1027,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 +1039,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_mask(Color color) +{ + ::apply_filter_to_surface(sdl_surface, MASK_FILTER, color); + + w = sdl_surface->w; + h = sdl_surface->h; +} SurfaceSDL::~SurfaceSDL() {}