Experimental giflib support

This commit is contained in:
Inori 2019-09-05 17:54:28 -04:00 committed by Inori
parent cc3392d896
commit 3b447e5efb
5 changed files with 111 additions and 5 deletions

View file

@ -28,6 +28,19 @@ if discord_libpath != ''
endif endif
endif endif
# GIFLIB
gif = false
gif_prefix = get_option('giflib_prefix')
if gif_prefix != ''
giflib = compiler.find_library('gif', required: false, dirs: gif_prefix+'/lib')
if giflib.found() == true
add_project_arguments(['-I@0@/include'.format(gif_prefix), '-DHAVE_GIFLIB'], language: 'cpp')
ext_dependencies += giflib
gif = true
endif
endif
# ==================== # ====================
# Main source # Main source
# ==================== # ====================

View file

@ -10,4 +10,5 @@ option('default_framerate', type: 'boolean', value: false, description: 'Disable
option('no_preload_scripts', type: 'boolean', value: false, description: 'Disable the preloadScript configuration option') option('no_preload_scripts', type: 'boolean', value: false, description: 'Disable the preloadScript configuration option')
option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup') option('workdir_current', type: 'boolean', value: false, description: 'Keep current directory on startup')
option('discord_sdk_path', type: 'string', value: '', description: 'Path to Discord GameSDK') option('discord_sdk_path', type: 'string', value: '', description: 'Path to Discord GameSDK')
option('giflib_prefix', type: 'string', value: '', description: 'Path to the prefix where giflib is installed')

View file

@ -44,6 +44,10 @@
#include "font.h" #include "font.h"
#include "eventthread.h" #include "eventthread.h"
#ifdef HAVE_GIFLIB
#include <gif_lib.h>
#endif
#define GUARD_MEGA \ #define GUARD_MEGA \
{ \ { \
if (p->megaSurface) \ if (p->megaSurface) \
@ -101,11 +105,22 @@ struct BitmapPrivate
* in the texture and blit to it directly, saving * in the texture and blit to it directly, saving
* ourselves the expensive blending calculation */ * ourselves the expensive blending calculation */
pixman_region16_t tainted; pixman_region16_t tainted;
/* If the image is a gif, its frames are located here. */
#ifdef HAVE_GIFLIB
SDL_Surface* gifSurfaces[256];
int nFrames;
int currentFrame;
#endif
BitmapPrivate(Bitmap *self) BitmapPrivate(Bitmap *self)
: self(self), : self(self),
megaSurface(0), megaSurface(0),
surface(0) surface(0),
#ifdef HAVE_GIFLIB
nFrames(1),
currentFrame(0)
#endif
{ {
format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888); format = SDL_AllocFormat(SDL_PIXELFORMAT_ABGR8888);
@ -117,6 +132,10 @@ struct BitmapPrivate
{ {
SDL_FreeFormat(format); SDL_FreeFormat(format);
pixman_region_fini(&tainted); pixman_region_fini(&tainted);
#ifdef HAVE_GIFLIB
if (nFrames > 1)
for (int i = 0; i < nFrames; i++) SDL_FreeSurface(gifSurfaces[i]);
#endif
} }
void allocSurface() void allocSurface()
@ -251,6 +270,53 @@ struct BitmapOpenHandler : FileSystem::OpenHandler
Bitmap::Bitmap(const char *filename) Bitmap::Bitmap(const char *filename)
{ {
BitmapOpenHandler handler; BitmapOpenHandler handler;
// If the file is a gif, try opening it with giflib first
// and read every frame
#ifdef HAVE_GIFLIB
char *extension = strrchr((char*)filename, '.');
int *rc{};
if (extension && !strcmp((extension+1), "gif"))
{
GifFileType *gif = DGifOpenFileName(filename, rc);
if (rc && DGifSlurp(gif) == GIF_OK)
{
p->nFrames = gif->ImageCount;
int colorReso = gif->SColorResolution;
for (int i = 0; i < p->nFrames; i++)
{
SDL_Surface *frame = SDL_CreateRGBSurface(0,
gif->SWidth,
gif->SHeight,
colorReso,
p->format->Rmask,
p->format->Gmask,
p->format->Bmask,
p->format->Amask);
if (frame)
{
memcpy(frame->pixels,
gif->SavedImages[i].RasterBits,
frame->w*frame->h*(colorReso/8));
p->gifSurfaces[i] = frame;
}
else
{
for (int b = i; b >= 0; b--)
{
SDL_FreeSurface(p->gifSurfaces[b]);
p->gifSurfaces[b] = 0;
}
break;
}
}
GifFreeSavedImages(gif);
handler.surf = p->gifSurfaces[0];
}
}
if (!handler.surf)
#endif
shState->fileSystem().openRead(handler, filename); shState->fileSystem().openRead(handler, filename);
SDL_Surface *imgSurf = handler.surf; SDL_Surface *imgSurf = handler.surf;
@ -814,6 +880,31 @@ void Bitmap::clear()
p->onModified(); p->onModified();
} }
void Bitmap::update()
{
#ifdef HAVE_GIFLIB
if (p->nFrames < 2) return;
guardDisposed();
GUARD_MEGA;
if (p->currentFrame >= p->nFrames)
{
p->currentFrame = 0;
}
else
{
p->currentFrame++;
}
SDL_Surface *surf = p->gifSurfaces[p->currentFrame];
replaceRaw(surf->pixels, surf->w, surf->h);
#else
return;
#endif
}
static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int y) static uint32_t &getPixelAt(SDL_Surface *surf, SDL_PixelFormat *form, int x, int y)
{ {
size_t offset = x*form->BytesPerPixel + y*surf->pitch; size_t offset = x*form->BytesPerPixel + y*surf->pitch;
@ -902,6 +993,7 @@ void Bitmap::replaceRaw(void *pixel_data, int w, int h)
TEXFBO::fini(buf); TEXFBO::fini(buf);
taintArea(IntRect(0,0,w,h)); taintArea(IntRect(0,0,w,h));
p->onModified();
} }

View file

@ -78,6 +78,8 @@ public:
void radialBlur(int angle, int divisions); void radialBlur(int angle, int divisions);
void clear(); void clear();
void update();
Color getPixel(int x, int y) const; Color getPixel(int x, int y) const;
void setPixel(int x, int y, const Color &color); void setPixel(int x, int y, const Color &color);

View file

@ -974,8 +974,7 @@ void Graphics::screenshot(const char *filename)
#ifdef __WIN32__ #ifdef __WIN32__
SDL_Surface *img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0,0,0,0); SDL_Surface *img = SDL_CreateRGBSurface(SDL_SWSURFACE, w, h, 32, 0,0,0,0);
if (!img) throw Exception(Exception::SDLError, "%s", SDL_GetError()); if (!img) throw Exception(Exception::SDLError, "%s", SDL_GetError());
glReadBuffer(GL_FRONT);
glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_BYTE, img->pixels); glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_BYTE, img->pixels);
#else #else
SDL_Surface *tmp, *img; SDL_Surface *tmp, *img;
@ -988,7 +987,6 @@ void Graphics::screenshot(const char *filename)
throw Exception(Exception::SDLError, "%s", SDL_GetError()); throw Exception(Exception::SDLError, "%s", SDL_GetError());
} }
glReadBuffer(GL_FRONT);
glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_BYTE, tmp->pixels); glReadPixels(0,0,w,h,GL_BGRA,GL_UNSIGNED_BYTE, tmp->pixels);
for (int i = 0; i < h; i++) for (int i = 0; i < h; i++)