#include #include #include #include "Alloc.h" #include "Graphics.h" #include "Maths.h" void setRect( SDL_Rect& _r, int x, int y, int w, int h ) { _r.x = x; _r.y = y; _r.w = w; _r.h = h; } static SDL_Surface* RecreateSurfaceWithDimensions( SDL_Surface* surface, const int width, const int height ) { SDL_Surface* retval; SDL_BlendMode blend_mode; if (surface == NULL) { return NULL; } retval = SDL_CreateRGBSurface( surface->flags, width, height, surface->format->BitsPerPixel, surface->format->Rmask, surface->format->Gmask, surface->format->Bmask, surface->format->Amask ); if (retval == NULL) { return NULL; } SDL_GetSurfaceBlendMode(surface, &blend_mode); SDL_SetSurfaceBlendMode(retval, blend_mode); return retval; } static SDL_Surface* RecreateSurface(SDL_Surface* surface) { if (surface == NULL) { return NULL; } return RecreateSurfaceWithDimensions( surface, surface->w, surface->h ); } SDL_Surface* GetSubSurface( SDL_Surface* metaSurface, int x, int y, int width, int height ) { // Create an SDL_Rect with the area of the _surface SDL_Rect area; area.x = x; area.y = y; area.w = width; area.h = height; //Convert to the correct display format after nabbing the new _surface or we will slow things down. SDL_Surface* preSurface = RecreateSurfaceWithDimensions( metaSurface, width, height ); // Lastly, apply the area from the meta _surface onto the whole of the sub _surface. SDL_BlitSurface(metaSurface, &area, preSurface, 0); // Return the new Bitmap _surface return preSurface; } static void DrawPixel(SDL_Surface* surface, const int x, const int y, const SDL_Color color) { const SDL_PixelFormat* fmt = surface->format; const int bpp = fmt->BytesPerPixel; Uint32* pixel = (Uint32*) ((Uint8*) surface->pixels + y * surface->pitch + x * bpp); const Uint32 packed = (color.r << fmt->Rshift) | (color.g << fmt->Gshift) | (color.b << fmt->Bshift) | (color.a << fmt->Ashift); switch (bpp) { case 1: case 2: case 3: SDL_assert(0 && "Non-32-bit colors not supported!"); return; case 4: *pixel = packed; break; } } SDL_Color ReadPixel(const SDL_Surface* surface, const int x, const int y) { const SDL_PixelFormat* fmt = surface->format; const int bpp = surface->format->BytesPerPixel; const Uint32* pixel = (Uint32*) ((Uint8*) surface->pixels + y * surface->pitch + x * bpp); switch (bpp) { case 1: case 2: case 3: { SDL_assert(0 && "Non-32-bit colors not supported!"); const SDL_Color color = {0, 0, 0, 0}; return color; } case 4: { const SDL_Color color = { (Uint8) ((*pixel & fmt->Rmask) >> fmt->Rshift), (Uint8) ((*pixel & fmt->Gmask) >> fmt->Gshift), (Uint8) ((*pixel & fmt->Bmask) >> fmt->Bshift), (Uint8) ((*pixel & fmt->Amask) >> fmt->Ashift) }; return color; } } /* shouldn't happen, but avoids warnings */ const SDL_Color color = {0, 0, 0, 0}; return color; } SDL_Surface * ScaleSurface( SDL_Surface *_surface, int Width, int Height, SDL_Surface * Dest ) { if(!_surface || !Width || !Height) return 0; SDL_Surface *_ret; if(Dest == NULL) { _ret = RecreateSurfaceWithDimensions(_surface, Width, Height); if(_ret == NULL) { return NULL; } } else { _ret = Dest; } SDL_BlitScaled(_surface, NULL, _ret, NULL); return _ret; } SDL_Surface * FlipSurfaceVerticle(SDL_Surface* _src) { SDL_Surface * ret = RecreateSurface(_src); if(ret == NULL) { return NULL; } for(Sint32 y = 0; y < _src->h; y++) { for(Sint32 x = 0; x < _src->w; x++) { DrawPixel(ret, x ,(_src->h-1) - y ,ReadPixel(_src, x, y)); } } return ret; } void BlitSurfaceStandard( SDL_Surface* _src, SDL_Rect* _srcRect, SDL_Surface* _dest, SDL_Rect* _destRect ) { SDL_BlitSurface( _src, _srcRect, _dest, _destRect ); } void BlitSurfaceColoured( SDL_Surface* src, const SDL_Rect* src_rect, SDL_Surface* dest, SDL_Rect* dest_rect, const SDL_Color color ) { SDL_Surface* tempsurface = RecreateSurface(src); for (int x = 0; x < tempsurface->w; x++) { for (int y = 0; y < tempsurface->h; y++) { const SDL_Color pixel = ReadPixel(src, x, y); const float div1 = pixel.a / 255.0f; const float div2 = color.a / 255.0f; const Uint8 alpha = (div1 * div2) * 255.0f; const SDL_Color result = {color.r, color.g, color.b, alpha}; DrawPixel(tempsurface, x, y, result); } } SDL_BlitSurface(tempsurface, src_rect, dest, dest_rect); VVV_freefunc(SDL_FreeSurface, tempsurface); } void BlitSurfaceTinted( SDL_Surface* src, const SDL_Rect* src_rect, SDL_Surface* dest, SDL_Rect* dest_rect, const SDL_Color color ) { SDL_Surface* tempsurface = RecreateSurface(src); for (int x = 0; x < tempsurface->w; x++) { for (int y = 0; y < tempsurface->h; y++) { const SDL_Color pixel = ReadPixel(src, x, y); double red = pixel.r * 0.299; double green = pixel.g * 0.587; double blue = pixel.b * 0.114; const double gray = SDL_floor(red + green + blue + 0.5); red = gray * color.r / 255.0; green = gray * color.g / 255.0; blue = gray * color.b / 255.0; red = SDL_clamp(red, 0, 255); green = SDL_clamp(green, 0, 255); blue = SDL_clamp(blue, 0, 255); const float div1 = pixel.a / 255.0f; const float div2 = color.a / 255.0f; const Uint8 alpha = (div1 * div2) * 255.0f; const SDL_Color result = {(Uint8) red, (Uint8) green, (Uint8) blue, alpha}; DrawPixel(tempsurface, x, y, result); } } SDL_BlitSurface(tempsurface, src_rect, dest, dest_rect); VVV_freefunc(SDL_FreeSurface, tempsurface); } static int oldscrollamount = 0; static int scrollamount = 0; static bool isscrolling = 0; void UpdateFilter(void) { if (rand() % 4000 < 8) { isscrolling = true; } oldscrollamount = scrollamount; if(isscrolling == true) { scrollamount += 20; if(scrollamount > 240) { scrollamount = 0; oldscrollamount = 0; isscrolling = false; } } } SDL_Surface* ApplyFilter(SDL_Surface* src) { SDL_Surface* ret = RecreateSurface(src); const int red_offset = rand() % 4; for (int x = 0; x < ret->w; x++) { for (int y = 0; y < ret->h; y++) { const int sampley = (y + (int) graphics.lerp(oldscrollamount, scrollamount)) % 240; const SDL_Color pixel = ReadPixel(src, x, sampley); Uint8 green = pixel.g; Uint8 blue = pixel.b; const SDL_Color pixel_offset = ReadPixel(src, SDL_min(x + red_offset, 319), sampley); Uint8 red = pixel_offset.r; double mult; int tmp; /* needed to avoid char overflow */ if (isscrolling && sampley > 220 && ((rand() % 10) < 4)) { mult = 0.6; } else { mult = 0.2; } tmp = red + fRandom() * mult * 254; red = SDL_min(tmp, 255); tmp = green + fRandom() * mult * 254; green = SDL_min(tmp, 255); tmp = blue + fRandom() * mult * 254; blue = SDL_min(tmp, 255); if (y % 2 == 0) { red = (Uint8) (red / 1.2f); green = (Uint8) (green / 1.2f); blue = (Uint8) (blue / 1.2f); } int distX = (int) ((SDL_abs(160.0f - x) / 160.0f) * 16); int distY = (int) ((SDL_abs(120.0f - y) / 120.0f) * 32); red = SDL_max(red - (distX + distY), 0); green = SDL_max(green - (distX + distY), 0); blue = SDL_max(blue - (distX + distY), 0); const SDL_Color color = {red, green, blue, pixel.a}; DrawPixel(ret, x, y, color); } } return ret; } void FillRect( SDL_Surface* _surface, const int _x, const int _y, const int _w, const int _h, const int r, int g, int b ) { SDL_Rect rect = {_x, _y, _w, _h}; Uint32 color = SDL_MapRGB(_surface->format, r, g, b); SDL_FillRect(_surface, &rect, color); } void FillRect( SDL_Surface* _surface, const int r, int g, int b ) { Uint32 color = SDL_MapRGB(_surface->format, r, g, b); SDL_FillRect(_surface, NULL, color); } void FillRect( SDL_Surface* _surface, SDL_Rect& _rect, const int r, int g, int b ) { Uint32 color = SDL_MapRGB(_surface->format, r, g, b); SDL_FillRect(_surface, &_rect, color); } void FillRect(SDL_Surface* surface, const SDL_Rect rect, const SDL_Color color) { const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); SDL_FillRect(surface, &rect, mapped); } void FillRect(SDL_Surface* surface, const SDL_Color color) { const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); SDL_FillRect(surface, NULL, mapped); } void FillRect(SDL_Surface* surface, const int x, const int y, const int w, const int h, const SDL_Color color) { const SDL_Rect rect = {x, y, w, h}; const Uint32 mapped = SDL_MapRGBA(surface->format, color.r, color.g, color.b, color.a); SDL_FillRect(surface, &rect, mapped); } void FillRect(SDL_Surface* surface, const int r, const int g, const int b, const int a) { const Uint32 mapped = SDL_MapRGBA(surface->format, r, g, b, a); SDL_FillRect(surface, NULL, mapped); } void ClearSurface(SDL_Surface* surface) { SDL_FillRect(surface, NULL, 0x00000000); } void ScrollSurface( SDL_Surface* _src, int _pX, int _pY ) { SDL_Surface* part1 = NULL; SDL_Rect rect1; SDL_Rect rect2; //scrolling up; if(_pY < 0) { setRect(rect2, 0, 0, _src->w, _src->h - _pY); part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h); SDL_Rect destrect1; SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); setRect(destrect1, 0, _pY, _pX, _src->h); SDL_BlitSurface (part1, NULL, _src, &destrect1); } else if(_pY > 0) { setRect(rect1, 0, 0, _src->w, _src->h - _pY); part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h); SDL_Rect destrect1; SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); setRect(destrect1, _pX, _pY, _src->w, _src->h - _pY); SDL_BlitSurface (part1, NULL, _src, &destrect1); } //Right else if(_pX <= 0) { setRect(rect2, 0, 0, _src->w - _pX, _src->h ); part1 = GetSubSurface(_src, rect2.x, rect2.y, rect2.w, rect2.h); SDL_Rect destrect1; SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); setRect(destrect1, _pX, 0, _src->w - _pX, _src->h); SDL_BlitSurface (part1, NULL, _src, &destrect1); } else if(_pX > 0) { setRect(rect1, _pX, 0, _src->w - _pX, _src->h ); part1 = GetSubSurface(_src, rect1.x, rect1.y, rect1.w, rect1.h); SDL_Rect destrect1; SDL_SetSurfaceBlendMode(part1, SDL_BLENDMODE_NONE); setRect(destrect1, 0, 0, _src->w - _pX, _src->h); SDL_BlitSurface (part1, NULL, _src, &destrect1); } //Cleanup temp surface if (part1) { VVV_freefunc(SDL_FreeSurface, part1); } }