#include using namespace Upp; #include "SDLCtrl.h" SDLSurface::SDLSurface() { surface = 0; delIn = true; } SDLSurface::SDLSurface(SDL_Surface *_surface, bool _del) { surface = _surface; delIn = _del; } SDLSurface::SDLSurface(int width, int height, int bpp) { surface = SDL_CreateRGBSurface(0, width, height, bpp, 0x0000FF, 0x00FF00, 0xFF0000, 0); delIn = true; } bool SDLSurface::CreateRGB(int width, int height, int bpp) { if (!delIn) return false; if (surface) SDL_FreeSurface(surface); return surface = SDL_CreateRGBSurface(0, width, height, bpp, 0x0000FF, 0x00FF00, 0xFF0000, 0); } bool SDLSurface::LoadBMP(const char *filename) { if (!delIn) return false; if (surface) SDL_FreeSurface(surface); return surface = SDL_LoadBMP(filename); } bool SDLSurface::Resize(int width, int height) { if (!delIn) return false; int bpp; if (surface) { bpp = GetBpp(); SDL_FreeSurface(surface); } else bpp = 0; return surface = SDL_CreateRGBSurface(0, width, height, bpp, 0x0000FF, 0x00FF00, 0xFF0000, 0); } SDLSurface::~SDLSurface() { if (delIn && surface) SDL_FreeSurface(surface); } inline Uint32 SDLSurface::GetColor(Color color) { return SDL_MapRGB(surface->format, color.GetR(), color.GetG(), color.GetB()); } void SDLSurface::Lock() { SDL_LockSurface(surface); } void SDLSurface::Unlock() { SDL_UnlockSurface(surface); } void ToSDL_Rect(SDL_Rect &sdlrect, Rect &rect) { sdlrect.x = rect.left; sdlrect.y = rect.top; sdlrect.w = rect.GetWidth(); sdlrect.h = rect.GetHeight(); } bool SDLSurface::Blit(SDLSurface &surf, Rect source, Rect dest) { SDL_Rect sdlsource, *psdlsource; SDL_Rect sdldest, *psdldest; if (!IsNull(source)) { ToSDL_Rect(sdlsource, source); psdlsource = &sdlsource; } else psdlsource = 0; if (!IsNull(dest)) { ToSDL_Rect(sdldest, dest); psdldest = &sdldest; } else psdldest = 0; if (0 != SDL_BlitSurface(surf.surface, psdlsource, surface, psdldest)) return false; if (0 != SDL_Flip(surface)) return false; return true; } void SDLSurface::DrawPixel(int x, int y, Color color) { Uint32 scolor = GetColor(color); byte *pixelpos = GetPixelPos(x, y); if (pixelpos) memcpy(pixelpos, &scolor, surface->format->BytesPerPixel); } Color SDLSurface::GetPixel(int x, int y) { Uint32 scolor; byte *pixelpos = GetPixelPos(x, y); if (!pixelpos) return Null; memcpy(&scolor, pixelpos, surface->format->BytesPerPixel); Uint8 r, g, b; SDL_GetRGB(scolor, surface->format, &r, &g, &b); return Color(r, g, b); } byte SDLSurface::GetPixelByte(int x, int y) { byte *pixelpos = GetPixelPos(x, y); if (!pixelpos) return 0; return *pixelpos; } void SDLSurface::DrawImage(Image img, int x0, int y0, Color transparent) { for(int y = 0; y < img.GetHeight(); y++) { for(int x = 0; x < img.GetWidth(); x++) { if (img[y][x] != transparent) DrawPixel(x + x0, y + y0, img[y][x]); } } } // Bresenham's line algorithm void SDLSurface::DrawLine1(int x0, int y0, int x1, int y1, Color color) { Uint32 pixel = GetColor(color); bool steep = abs(y1 - y0) > abs(x1 - x0); if (steep) { Swap(x0, y0); Swap(x1, y1); } if (x0 > x1) { Swap(x0, x1); Swap(y0, y1); } int deltax = x1 - x0; int deltay = abs(y1 - y0); int error = deltax/2; int ystep; int y = y0; if (y0 < y1) ystep = 1; else ystep = -1; for (int x = x0; x < x1; ++x) { if (steep) DrawPixel(y, x, pixel); else DrawPixel(x, y, pixel); error = error - deltay; if (error < 0) { y = y + ystep; error = error + deltax; } } } void SDLSurface::DrawLine(int x0, int y0, int x1, int y1, int thick, Color color) { if (x0 == x1) { if (y1 < y0) Swap(y0, y1); int t = thick/2; FillRect(x0-t, y0, thick, y1-y0, color); } else if (y0 == y1) { if (x1 < x0) Swap(x0, x1); int t = thick/2; FillRect(x0, y0-t, x1-x0, thick, color); } else DrawLine1(x0, y0, x1, y1, color); // Pending } void SDLSurface::DrawRect(int x, int y, int width, int height, int thick, Color color) { FillRect(x, y, width, thick, color); FillRect(x, y+thick, thick, height-2*thick, color); FillRect(x+width-thick, y+thick, thick, height-2*thick, color); FillRect(x, y+height-thick, width, thick, color); } void SDLSurface::FillRect(int x, int y, int width, int height, Color color) { SDL_Rect rect = {x, y, width, height}; Uint32 pixel = GetColor(color); SDL_FillRect(surface, &rect, pixel); } void SDLSurface::DrawCircle1(int x0, int y0, int radius, Color color) { Uint32 pixel = GetColor(color); int f = 1 - radius; int ddF_x = 1; int ddF_y = -2 * radius; int x = 0; int y = radius; DrawPixel(x0, y0 + radius, pixel); DrawPixel(x0, y0 - radius, pixel); DrawPixel(x0 + radius, y0, pixel); DrawPixel(x0 - radius, y0, pixel); while(x < y) { ddF_x = 2*x + 1; ddF_y = -2*y; f = x*x + y*y - radius*radius + 2*x - y + 1; if(f >= 0) { y--; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x; DrawPixel(x0 + x, y0 + y, pixel); DrawPixel(x0 - x, y0 + y, pixel); DrawPixel(x0 + x, y0 - y, pixel); DrawPixel(x0 - x, y0 - y, pixel); DrawPixel(x0 + y, y0 + x, pixel); DrawPixel(x0 - y, y0 + x, pixel); DrawPixel(x0 + y, y0 - x, pixel); DrawPixel(x0 - y, y0 - x, pixel); } } void SDLSurface::DrawCircle(int x0, int y0, int radius, int thick, Color color) { for (int i = 0; i < thick; ++i) DrawCircle1(x0, y0, radius - i, color); } void SDLSurface::FillCircle(int cx, int cy, int radius, Color color) { Uint32 pixel = GetColor(color); int bpp = surface->format->BytesPerPixel; double r = double(radius); for (double dy = 1; dy <= r; dy += 1.0) { double dx = floor(sqrt((2.0 * r * dy) - (dy * dy))); int x = int(cx - dx); Uint8 *target_pixel_a = GetPixelPos(x, int(cy + r - dy)); Uint8 *target_pixel_b = GetPixelPos(x, int(cy - r + dy));; for (; x <= cx + dx; x++) { memcpy(target_pixel_a, &pixel, bpp); memcpy(target_pixel_b, &pixel, bpp); target_pixel_a += bpp; target_pixel_b += bpp; } } }