mirror of
https://github.com/mkxp-z/mkxp-z.git
synced 2025-08-04 22:15:33 +02:00
Experimental giflib support
This commit is contained in:
parent
cc3392d896
commit
3b447e5efb
5 changed files with 111 additions and 5 deletions
13
meson.build
13
meson.build
|
@ -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
|
||||||
# ====================
|
# ====================
|
||||||
|
|
|
@ -11,3 +11,4 @@ option('no_preload_scripts', type: 'boolean', value: false, description: 'Disabl
|
||||||
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')
|
|
@ -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) \
|
||||||
|
@ -102,10 +106,21 @@ struct BitmapPrivate
|
||||||
* 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();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -79,6 +79,8 @@ public:
|
||||||
|
|
||||||
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);
|
||||||
|
|
||||||
|
|
|
@ -975,7 +975,6 @@ void Graphics::screenshot(const char *filename)
|
||||||
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++)
|
||||||
|
|
Loading…
Add table
Reference in a new issue