#include "surface.h" #include "gif.c" struct jSurface_s { Uint8 *data; Uint16 w, h; }; // Constructor Surface::Surface(const char *filename, jSurface dest) { surface = loadSurface(filename); destSurface = dest; texture = nullptr; loadPalette(filename); transparentColor = 0; } // Constructor Surface::Surface(int width, int height, SDL_Texture *tex) { surface = newSurface(width, height); destSurface = nullptr; texture = tex; clearPalette(0); transparentColor = 0; } // Destructor Surface::~Surface() { deleteSurface(surface); deleteSurface(destSurface); } // Crea una surface jSurface Surface::newSurface(int w, int h) { jSurface surf = (jSurface)malloc(sizeof(jSurface_s)); surf->w = w; surf->h = h; surf->data = (Uint8 *)malloc(w * h); return surf; } // Borra una surface void Surface::deleteSurface(jSurface surf) { if (surf == nullptr) { return; } if (surf->data != nullptr) { free(surf->data); } free(surf); } // Establece una surface de destino donde hacer el blit void Surface::setDest(jSurface surf) { destSurface = surf; } // Establece una textura donde hacer el flip void Surface::setTexture(SDL_Texture *tex) { texture = tex; } // Crea una surface a partir de un fichero .gif jSurface Surface::loadSurface(const char *filename) { FILE *f = fopen(filename, "rb"); if (!f) { return nullptr; } fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); Uint8 *buffer = (Uint8 *)malloc(size); fread(buffer, size, 1, f); fclose(f); Uint16 w, h; Uint8 *pixels = LoadGif(buffer, &w, &h); if (pixels == nullptr) { return nullptr; } jSurface surf = (jSurface)malloc(sizeof(jSurface_s)); surf->w = w; surf->h = h; surf->data = pixels; free(buffer); return surf; } // Carga una palette desde un fichero .gif void Surface::loadPalette(const char *filename) { FILE *f = fopen(filename, "rb"); if (!f) { return; } fseek(f, 0, SEEK_END); long size = ftell(f); fseek(f, 0, SEEK_SET); Uint8 *buffer = (Uint8 *)malloc(size); fread(buffer, size, 1, f); fclose(f); Uint32 *pal = LoadPalette(buffer); if (pal == nullptr) { return; } free(buffer); for (int i = 0; i < 256; ++i) { palette[i] = pal[i]; } } // Cambia un color de la palette void Surface::setPaletteColor(int index, Uint32 color) { palette[index] = color; } // Limpia la surface void Surface::cls(Uint8 color) { for (int i = 0; i < surface->w * surface->h; ++i) { surface->data[i] = color; } } // Volca la surface a una textura void Surface::flip(SDL_Texture *texture) { Uint32 *pixels; int pitch; SDL_LockTexture(texture, nullptr, (void **)&pixels, &pitch); for (int i = 0; i < surface->w * surface->h; ++i) { pixels[i] = palette[surface->data[i]]; } SDL_UnlockTexture(texture); } // Escribe pixels en destSurface void Surface::putPixel(int x, int y, Uint8 color) { // if (x < 0 || y < 0 || x >= jDestSurf->w || y >= jDestSurf->h || color == transparentColor) if (x < 0 || y < 0 || x >= destSurface->w || y >= destSurface->h) { return; } destSurface->data[x + y * destSurface->w] = color; } // Lee pixels en surface Uint8 Surface::getPixel(int x, int y) { return surface->data[x + y * surface->w]; } // Copia pixels desde surface a destSurface void Surface::blit(int dx, int dy, int sx, int sy, int w, int h) { if (surface == nullptr) { return; } for (int iy = 0; iy < h; ++iy) { for (int ix = 0; ix < w; ++ix) { putPixel(dx + ix, dy + iy, getPixel(sx + ix, sy + iy)); } } } // Limpia la paleta void Surface::clearPalette(Uint32 color) { for (int i = 0; i < 256; ++i) { palette[i] = color; } }