From c180844aee7ea6779e48fabdd9d3e489c1cf5a83 Mon Sep 17 00:00:00 2001 From: "p.kosyh" Date: Fri, 2 Oct 2009 17:18:09 +0000 Subject: [PATCH] anigif next stage.. --- Rules.make.standalone | 4 +- src/sdl-instead/SDL_anigif.c | 1485 +++++++++++++++++----------------- src/sdl-instead/SDL_anigif.h | 122 +-- src/sdl-instead/game.c | 2 + src/sdl-instead/graphics.c | 53 +- 5 files changed, 856 insertions(+), 810 deletions(-) diff --git a/Rules.make.standalone b/Rules.make.standalone index 0843ff9..88b5292 100644 --- a/Rules.make.standalone +++ b/Rules.make.standalone @@ -16,8 +16,8 @@ LUA_LFLAGS=$(shell pkg-config --libs lua5.1) # for arch linux, fedora (may be others) use this # -# LUA_CFLAGS=$(shell pkg-config --cflags lua) -# LUA_LFLAGS=$(shell pkg-config --libs lua) +LUA_CFLAGS=$(shell pkg-config --cflags lua) +LUA_LFLAGS=$(shell pkg-config --libs lua) # SDL_CFLAGS=$(shell sdl-config --cflags) diff --git a/src/sdl-instead/SDL_anigif.c b/src/sdl-instead/SDL_anigif.c index 7674743..f96366e 100644 --- a/src/sdl-instead/SDL_anigif.c +++ b/src/sdl-instead/SDL_anigif.c @@ -1,738 +1,747 @@ -/* - SDL_anigif: An example animated GIF image loading library for use with SDL - SDL_image Copyright (C) 1997-2006 Sam Lantinga - Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#include -#include -#include "SDL_anigif.h" - - - -/* Code from here to end of file has been adapted from XPaint: */ -/* +-------------------------------------------------------------------+ */ -/* | Copyright 1990, 1991, 1993 David Koblas. | */ -/* | Copyright 1996 Torsten Martinsen. | */ -/* | Permission to use, copy, modify, and distribute this software | */ -/* | and its documentation for any purpose and without fee is hereby | */ -/* | granted, provided that the above copyright notice appear in all | */ -/* | copies and that both that copyright notice and this permission | */ -/* | notice appear in supporting documentation. This software is | */ -/* | provided "as is" without express or implied warranty. | */ -/* +-------------------------------------------------------------------+ */ -/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */ -/* Animated GIF support by Doug McFadyen -- 10/19/06 */ - -#define MAXCOLORMAPSIZE 256 - -#define TRUE 1 -#define FALSE 0 - -#define CM_RED 0 -#define CM_GREEN 1 -#define CM_BLUE 2 - -#define MAX_LWZ_BITS 12 - -#define INTERLACE 0x40 -#define LOCALCOLORMAP 0x80 -#define BitSet(byte,bit) (((byte) & (bit)) == (bit)) -#define LM_to_uint(a,b) (((b)<<8)|(a)) - -#define SDL_SetError(t) ((void)0) /* We're not SDL so ignore error reporting */ - - -typedef struct -{ - unsigned int Width; - unsigned int Height; - unsigned char ColorMap[3][MAXCOLORMAPSIZE]; - unsigned int BitPixel; - unsigned int ColorResolution; - unsigned int Background; - unsigned int AspectRatio; -} gifscreen; - -typedef struct -{ - int transparent; - int delayTime; - int inputFlag; - int disposal; -} gif89; - -typedef struct -{ - /* global data */ - SDL_RWops* src; - gifscreen gs; - gif89 g89; - int zerodatablock; - /* AG_LoadGIF_RW data */ - unsigned char localColorMap[3][MAXCOLORMAPSIZE]; - /* GetCode data */ - unsigned char buf[280]; - int curbit, lastbit, done, lastbyte; - /* LWZReadByte data */ - int fresh, code, incode; - int codesize, setcodesize; - int maxcode, maxcodesize; - int firstcode, oldcode; - int clearcode, endcode; - int table[2][(1 << MAX_LWZ_BITS)]; - int stack[(1 << (MAX_LWZ_BITS))*2], *sp; -} gifdata; - - - -static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ); -static int DoExtension( gifdata* gd, int label ); -static int GetDataBlock( gifdata* gd, unsigned char* buf ); -static int GetCode( gifdata* gd, int code_size, int flag ); -static int LWZReadByte( gifdata* gd, int flag, int input_code_size ); -static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ); - - - -int AG_isGIF( SDL_RWops* src ) -{ - int isGIF = FALSE; - - if ( src ) - { - int start = SDL_RWtell( src ); - char magic[6]; - - if ( SDL_RWread(src,magic,sizeof(magic),1) ) - { - if ( (strncmp(magic,"GIF",3) == 0) && ((memcmp(magic+3,"87a",3) == 0) || (memcmp(magic+3,"89a",3) == 0)) ) - { - isGIF = TRUE; - } - } - - SDL_RWseek( src, start, SEEK_SET ); - } - - return isGIF; -} - -int AG_LoadGIF( const char* file, AG_Frame* frames, int size ) -{ - int n = 0; - - SDL_RWops* src = SDL_RWFromFile( file, "rb" ); - - if ( src ) - { - n = AG_LoadGIF_RW( src, frames, size ); - SDL_RWclose( src ); - } - - return n; -} - - - -void AG_FreeSurfaces( AG_Frame* frames, int nFrames ) -{ - int i; - - if ( frames ) - { - for ( i = 0; i < nFrames; i++ ) - { - if ( frames[i].surface ) - { - SDL_FreeSurface( frames[i].surface ); - frames[i].surface = NULL; - } - } - } -} - - - -int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ) -{ - int i; - int n = 0; - - if ( frames ) - { - for ( i = 0; i < nFrames; i++ ) - { - if ( frames[i].surface ) - { - SDL_Surface* surface = (frames[i].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[i].surface) : SDL_DisplayFormat(frames[i].surface); - - if ( surface ) - { - SDL_FreeSurface( frames[i].surface ); - frames[i].surface = surface; - n++; - } - } - } - } - - return n; -} - - - -int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ) -{ - int n = 0; - - if ( nFrames > 0 && frames && frames[0].surface ) - { - SDL_Surface* mainSurface = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[0].surface) : SDL_DisplayFormat(frames[0].surface); - const int newDispose = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? AG_DISPOSE_RESTORE_BACKGROUND : AG_DISPOSE_NONE; - - if ( mainSurface ) - { - int i; - int lastDispose = AG_DISPOSE_NA; - int iRestore = 0; - const Uint8 alpha = (frames[0].disposal == AG_DISPOSE_NONE) ? SDL_ALPHA_OPAQUE : SDL_ALPHA_TRANSPARENT; - - SDL_FillRect( mainSurface, NULL, SDL_MapRGBA(mainSurface->format,0,0,0,alpha) ); - - for ( i = 0; i < nFrames; i++ ) - { - if ( frames[i].surface ) - { - SDL_Surface* surface = SDL_ConvertSurface( mainSurface, mainSurface->format, mainSurface->flags ); - - if ( surface ) - { - SDL_Rect r; - - if ( lastDispose == AG_DISPOSE_NONE ) - SDL_BlitSurface( frames[i-1].surface, NULL, surface, NULL ); - - if ( lastDispose == AG_DISPOSE_RESTORE_PREVIOUS ) - SDL_BlitSurface( frames[iRestore].surface, NULL, surface, NULL ); - if ( frames[i].disposal != AG_DISPOSE_RESTORE_PREVIOUS ) - iRestore = i; - - r.x = (Sint16)frames[i].x; - r.y = (Sint16)frames[i].y; - SDL_BlitSurface( frames[i].surface, NULL, surface, &r ); - - SDL_FreeSurface( frames[i].surface ); - frames[i].surface = surface; - frames[i].x = frames[i].y = 0; - lastDispose = frames[i].disposal; - frames[i].disposal = newDispose; - n++; - } - } - } - - SDL_FreeSurface( mainSurface ); - } - } - - return n; -} - - - -int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames ) -{ - int start; - unsigned char buf[16]; - unsigned char c; - int useGlobalColormap; - int bitPixel; - int iFrame = 0; - char version[4]; - SDL_Surface* image = NULL; - gifdata* gd; - - if ( src == NULL ) - return 0; - - gd = malloc( sizeof(*gd) ); - memset( gd, 0, sizeof(*gd) ); - gd->src = src; - - start = SDL_RWtell( src ); - - if ( !SDL_RWread(src,buf,6,1) ) - { - SDL_SetError( "error reading magic number" ); - goto done; - } - - if ( strncmp((char*)buf,"GIF",3) != 0 ) - { - SDL_SetError( "not a GIF file" ); - goto done; - } - - strncpy( version, (char*)buf+3, 3 ); - version[3] = '\0'; - - if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) ) - { - SDL_SetError( "bad version number, not '87a' or '89a'" ); - goto done; - } - - gd->g89.transparent = -1; - gd->g89.delayTime = -1; - gd->g89.inputFlag = -1; - gd->g89.disposal = AG_DISPOSE_NA; - - if ( !SDL_RWread(src,buf,7,1) ) - { - SDL_SetError( "failed to read screen descriptor" ); - goto done; - } - - gd->gs.Width = LM_to_uint(buf[0],buf[1]); - gd->gs.Height = LM_to_uint(buf[2],buf[3]); - gd->gs.BitPixel = 2 << (buf[4] & 0x07); - gd->gs.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); - gd->gs.Background = buf[5]; - gd->gs.AspectRatio = buf[6]; - - if ( BitSet(buf[4],LOCALCOLORMAP) ) /* Global Colormap */ - { - if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) ) - { - SDL_SetError( "error reading global colormap" ); - goto done; - } - } - - do - { - if ( !SDL_RWread(src,&c,1,1) ) - { - SDL_SetError( "EOF / read error on image data" ); - goto done; - } - - if ( c == ';' ) /* GIF terminator */ - goto done; - - if ( c == '!' ) /* Extension */ - { - if ( !SDL_RWread(src,&c,1,1) ) - { - SDL_SetError( "EOF / read error on extention function code" ); - goto done; - } - DoExtension( gd, c ); - continue; - } - - if ( c != ',' ) /* Not a valid start character */ - continue; - - if ( !SDL_RWread(src,buf,9,1) ) - { - SDL_SetError( "couldn't read left/top/width/height" ); - goto done; - } - - useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP); - bitPixel = 1 << ((buf[8] & 0x07) + 1); - - if ( !useGlobalColormap ) - { - if ( ReadColorMap(gd,bitPixel,gd->localColorMap) ) - { - SDL_SetError( "error reading local colormap" ); - goto done; - } - image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), bitPixel, gd->localColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) ); - } - else - { - image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), gd->gs.BitPixel, gd->gs.ColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) ); - } - - if ( frames ) - { - if ( image == NULL ) - goto done; - - if ( gd->g89.transparent >= 0 ) - SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent ); - - frames[iFrame].surface = image; - frames[iFrame].x = LM_to_uint(buf[0], buf[1]); - frames[iFrame].y = LM_to_uint(buf[2], buf[3]); - frames[iFrame].disposal = gd->g89.disposal; - frames[iFrame].delay = gd->g89.delayTime*10; -/* gd->g89.transparent = -1; ** Hmmm, not sure if this should be reset for each frame? */ - } - - iFrame++; - } while ( iFrame < maxFrames || frames == NULL ); - -done: - if ( image == NULL ) - SDL_RWseek( src, start, SEEK_SET ); - - free( gd ); - - return iFrame; -} - - - -static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ) -{ - int i; - unsigned char rgb[3]; - int flag; - - flag = TRUE; - - for ( i = 0; i < number; ++i ) - { - if ( !SDL_RWread(gd->src,rgb,sizeof(rgb),1) ) - { - SDL_SetError( "bad colormap" ); - return 1; - } - - buffer[CM_RED][i] = rgb[0]; - buffer[CM_GREEN][i] = rgb[1]; - buffer[CM_BLUE][i] = rgb[2]; - flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]); - } - - return FALSE; -} - - - -static int DoExtension( gifdata* gd, int label ) -{ - unsigned char buf[256]; - - switch ( label ) - { - case 0x01: /* Plain Text Extension */ - break; - - case 0xff: /* Application Extension */ - break; - - case 0xfe: /* Comment Extension */ - while ( GetDataBlock(gd,buf) != 0 ) - ; - return FALSE; - - case 0xf9: /* Graphic Control Extension */ - (void)GetDataBlock( gd, buf ); - gd->g89.disposal = (buf[0] >> 2) & 0x7; - gd->g89.inputFlag = (buf[0] >> 1) & 0x1; - gd->g89.delayTime = LM_to_uint(buf[1],buf[2]); - if ( (buf[0] & 0x1) != 0 ) - gd->g89.transparent = buf[3]; - - while ( GetDataBlock(gd,buf) != 0 ) - ; - return FALSE; - } - - while ( GetDataBlock(gd,buf) != 0 ) - ; - - return FALSE; -} - - - -static int GetDataBlock( gifdata* gd, unsigned char* buf ) -{ - unsigned char count; - - if ( !SDL_RWread(gd->src,&count,1,1) ) - { - /* pm_message("error in getting DataBlock size" ); */ - return -1; - } - - gd->zerodatablock = count == 0; - - if ( (count != 0) && !SDL_RWread(gd->src,buf,count,1) ) - { - /* pm_message("error in reading DataBlock" ); */ - return -1; - } - - return count; -} - - - -static int GetCode( gifdata* gd, int code_size, int flag ) -{ - int i, j, ret; - int count; - - if ( flag ) - { - gd->curbit = 0; - gd->lastbit = 0; - gd->done = FALSE; - return 0; - } - - if ( (gd->curbit + code_size) >= gd->lastbit ) - { - if ( gd->done ) - { - if ( gd->curbit >= gd->lastbit ) - SDL_SetError( "ran off the end of my bits" ); - return -1; - } - - gd->buf[0] = gd->buf[gd->lastbyte - 2]; - gd->buf[1] = gd->buf[gd->lastbyte - 1]; - - if ( (count = GetDataBlock(gd, &gd->buf[2])) == 0 ) - gd->done = TRUE; - - gd->lastbyte = 2 + count; - gd->curbit = (gd->curbit - gd->lastbit) + 16; - gd->lastbit = (2 + count)*8; - } - - ret = 0; - for ( i = gd->curbit, j = 0; j < code_size; ++i, ++j ) - ret |= ((gd->buf[i / 8] & (1 << (i % 8))) != 0) << j; - - gd->curbit += code_size; - - return ret; -} - - - -static int LWZReadByte( gifdata* gd, int flag, int input_code_size ) -{ - int i, code, incode; - - if ( flag ) - { - gd->setcodesize = input_code_size; - gd->codesize = gd->setcodesize + 1; - gd->clearcode = 1 << gd->setcodesize; - gd->endcode = gd->clearcode + 1; - gd->maxcodesize = gd->clearcode*2; - gd->maxcode = gd->clearcode + 2; - - GetCode( gd, 0, TRUE ); - - gd->fresh = TRUE; - - for ( i = 0; i < gd->clearcode; ++i ) - { - gd->table[0][i] = 0; - gd->table[1][i] = i; - } - - for ( ; i < (1 << MAX_LWZ_BITS); ++i ) - gd->table[0][i] = gd->table[1][0] = 0; - - gd->sp = gd->stack; - return 0; - } - else if ( gd->fresh ) - { - gd->fresh = FALSE; - do - { - gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE ); - } while ( gd->firstcode == gd->clearcode ); - return gd->firstcode; - } - - if ( gd->sp > gd->stack ) - return *--gd->sp; - - while ( (code = GetCode(gd,gd->codesize,FALSE)) >= 0 ) - { - if ( code == gd->clearcode ) - { - for ( i = 0; i < gd->clearcode; ++i ) - { - gd->table[0][i] = 0; - gd->table[1][i] = i; - } - - for ( ; i < (1 << MAX_LWZ_BITS); ++i ) - gd->table[0][i] = gd->table[1][i] = 0; - - gd->codesize = gd->setcodesize + 1; - gd->maxcodesize = gd->clearcode*2; - gd->maxcode = gd->clearcode + 2; - gd->sp = gd->stack; - gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE ); - return gd->firstcode; - } - else if ( code == gd->endcode ) - { - int count; - unsigned char buf[260]; - - if ( gd->zerodatablock ) - return -2; - - while ( (count = GetDataBlock(gd,buf)) > 0 ) - ; - - if ( count != 0 ) - { - /* pm_message("missing EOD in data stream (common occurence)"); */ - } - return -2; - } - - incode = code; - - if ( code >= gd->maxcode ) - { - *gd->sp++ = gd->firstcode; - code = gd->oldcode; - } - - while ( code >= gd->clearcode ) - { - *gd->sp++ = gd->table[1][code]; - if ( code == gd->table[0][code] ) - SDL_SetError( "circular table entry BIG ERROR" ); - code = gd->table[0][code]; - } - - *gd->sp++ = gd->firstcode = gd->table[1][code]; - - if ( (code = gd->maxcode) < (1 << MAX_LWZ_BITS) ) - { - gd->table[0][code] = gd->oldcode; - gd->table[1][code] = gd->firstcode; - ++gd->maxcode; - if ( (gd->maxcode >= gd->maxcodesize) && (gd->maxcodesize < (1 << MAX_LWZ_BITS)) ) - { - gd->maxcodesize *= 2; - ++gd->codesize; - } - } - - gd->oldcode = incode; - - if ( gd->sp > gd->stack ) - return *--gd->sp; - } - - return code; -} - - - -static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ) -{ - SDL_Surface* image; - unsigned char c; - int i, v; - int xpos = 0, ypos = 0, pass = 0; - - /* Initialize the compression routines */ - if ( !SDL_RWread(gd->src,&c,1,1) ) - { - SDL_SetError( "EOF / read error on image data" ); - return NULL; - } - - if ( LWZReadByte(gd,TRUE,c) < 0 ) - { - SDL_SetError( "error reading image" ); - return NULL; - } - - /* If this is an "uninteresting picture" ignore it. */ - if ( ignore ) - { - while ( LWZReadByte(gd,FALSE,c) >= 0 ) - ; - return NULL; - } - - image = SDL_AllocSurface( SDL_SWSURFACE, len, height, 8, 0, 0, 0, 0 ); - - for ( i = 0; i < cmapSize; i++ ) - { - image->format->palette->colors[i].r = cmap[CM_RED][i]; - image->format->palette->colors[i].g = cmap[CM_GREEN][i]; - image->format->palette->colors[i].b = cmap[CM_BLUE][i]; - } - - while ( (v = LWZReadByte(gd,FALSE,c)) >= 0 ) - { - ((Uint8*)image->pixels)[xpos + ypos*image->pitch] = (Uint8)v; - ++xpos; - - if ( xpos == len ) - { - xpos = 0; - if ( interlace ) - { - switch ( pass ) - { - case 0: - case 1: ypos += 8; break; - case 2: ypos += 4; break; - case 3: ypos += 2; break; - } - - if ( ypos >= height ) - { - ++pass; - switch ( pass ) - { - case 1: ypos = 4; break; - case 2: ypos = 2; break; - case 3: ypos = 1; break; - default: goto fini; - } - } - } - else - { - ++ypos; - } - } - - if ( ypos >= height ) - break; - } - -fini: - return image; -} - +/* + SDL_anigif: An example animated GIF image loading library for use with SDL + SDL_image Copyright (C) 1997-2006 Sam Lantinga + Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#include +#include +#include "SDL_anigif.h" + + + +/* Code from here to end of file has been adapted from XPaint: */ +/* +-------------------------------------------------------------------+ */ +/* | Copyright 1990, 1991, 1993 David Koblas. | */ +/* | Copyright 1996 Torsten Martinsen. | */ +/* | Permission to use, copy, modify, and distribute this software | */ +/* | and its documentation for any purpose and without fee is hereby | */ +/* | granted, provided that the above copyright notice appear in all | */ +/* | copies and that both that copyright notice and this permission | */ +/* | notice appear in supporting documentation. This software is | */ +/* | provided "as is" without express or implied warranty. | */ +/* +-------------------------------------------------------------------+ */ +/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */ +/* Animated GIF support by Doug McFadyen -- 10/19/06 */ + +#define MAXCOLORMAPSIZE 256 + +#define TRUE 1 +#define FALSE 0 + +#define CM_RED 0 +#define CM_GREEN 1 +#define CM_BLUE 2 + +#define MAX_LWZ_BITS 12 + +#define INTERLACE 0x40 +#define LOCALCOLORMAP 0x80 +#define BitSet(byte,bit) (((byte) & (bit)) == (bit)) +#define LM_to_uint(a,b) (((b)<<8)|(a)) + +#define SDL_SetError(t) ((void)0) /* We're not SDL so ignore error reporting */ + + +typedef struct +{ + unsigned int Width; + unsigned int Height; + unsigned char ColorMap[3][MAXCOLORMAPSIZE]; + unsigned int BitPixel; + unsigned int ColorResolution; + unsigned int Background; + unsigned int AspectRatio; +} gifscreen; + +typedef struct +{ + int transparent; + int delayTime; + int inputFlag; + int disposal; +} gif89; + +typedef struct +{ + /* global data */ + SDL_RWops* src; + int loop; + gifscreen gs; + gif89 g89; + int zerodatablock; + /* AG_LoadGIF_RW data */ + unsigned char localColorMap[3][MAXCOLORMAPSIZE]; + /* GetCode data */ + unsigned char buf[280]; + int curbit, lastbit, done, lastbyte; + /* LWZReadByte data */ + int fresh, code, incode; + int codesize, setcodesize; + int maxcode, maxcodesize; + int firstcode, oldcode; + int clearcode, endcode; + int table[2][(1 << MAX_LWZ_BITS)]; + int stack[(1 << (MAX_LWZ_BITS))*2], *sp; +} gifdata; + + + +static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ); +static int DoExtension( gifdata* gd, int label ); +static int GetDataBlock( gifdata* gd, unsigned char* buf ); +static int GetCode( gifdata* gd, int code_size, int flag ); +static int LWZReadByte( gifdata* gd, int flag, int input_code_size ); +static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ); + + + +int AG_isGIF( SDL_RWops* src ) +{ + int isGIF = FALSE; + + if ( src ) + { + int start = SDL_RWtell( src ); + char magic[6]; + + if ( SDL_RWread(src,magic,sizeof(magic),1) ) + { + if ( (strncmp(magic,"GIF",3) == 0) && ((memcmp(magic+3,"87a",3) == 0) || (memcmp(magic+3,"89a",3) == 0)) ) + { + isGIF = TRUE; + } + } + + SDL_RWseek( src, start, SEEK_SET ); + } + + return isGIF; +} + +int AG_LoadGIF( const char* file, AG_Frame* frames, int size, int *loop ) +{ + int n = 0; + + SDL_RWops* src = SDL_RWFromFile( file, "rb" ); + + if ( src ) + { + n = AG_LoadGIF_RW( src, frames, size, loop ); + SDL_RWclose( src ); + } + + return n; +} + + + +void AG_FreeSurfaces( AG_Frame* frames, int nFrames ) +{ + int i; + + if ( frames ) + { + for ( i = 0; i < nFrames; i++ ) + { + if ( frames[i].surface ) + { + SDL_FreeSurface( frames[i].surface ); + frames[i].surface = NULL; + } + } + } +} + + + +int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ) +{ + int i; + int n = 0; + + if ( frames ) + { + for ( i = 0; i < nFrames; i++ ) + { + if ( frames[i].surface ) + { + SDL_Surface* surface = (frames[i].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[i].surface) : SDL_DisplayFormat(frames[i].surface); + + if ( surface ) + { + SDL_FreeSurface( frames[i].surface ); + frames[i].surface = surface; + n++; + } + } + } + } + + return n; +} + + + +int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ) +{ + int n = 0; + + if ( nFrames > 0 && frames && frames[0].surface ) + { + SDL_Surface* mainSurface = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[0].surface) : SDL_DisplayFormat(frames[0].surface); + const int newDispose = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? AG_DISPOSE_RESTORE_BACKGROUND : AG_DISPOSE_NONE; + + if ( mainSurface ) + { + int i; + int lastDispose = AG_DISPOSE_NA; + int iRestore = 0; + const Uint8 alpha = (frames[0].disposal == AG_DISPOSE_NONE) ? SDL_ALPHA_OPAQUE : SDL_ALPHA_TRANSPARENT; + + SDL_FillRect( mainSurface, NULL, SDL_MapRGBA(mainSurface->format,0,0,0,alpha) ); + + for ( i = 0; i < nFrames; i++ ) + { + if ( frames[i].surface ) + { + SDL_Surface* surface = SDL_ConvertSurface( mainSurface, mainSurface->format, mainSurface->flags ); + + if ( surface ) + { + SDL_Rect r; + + if ( lastDispose == AG_DISPOSE_NONE ) + SDL_BlitSurface( frames[i-1].surface, NULL, surface, NULL ); + + if ( lastDispose == AG_DISPOSE_RESTORE_PREVIOUS ) + SDL_BlitSurface( frames[iRestore].surface, NULL, surface, NULL ); + if ( frames[i].disposal != AG_DISPOSE_RESTORE_PREVIOUS ) + iRestore = i; + + r.x = (Sint16)frames[i].x; + r.y = (Sint16)frames[i].y; + SDL_BlitSurface( frames[i].surface, NULL, surface, &r ); + + SDL_FreeSurface( frames[i].surface ); + frames[i].surface = surface; + frames[i].x = frames[i].y = 0; + lastDispose = frames[i].disposal; + frames[i].disposal = newDispose; + n++; + } + } + } + + SDL_FreeSurface( mainSurface ); + } + } + + return n; +} + + + +int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames, int *loop) +{ + int start; + unsigned char buf[16]; + unsigned char c; + int useGlobalColormap; + int bitPixel; + int iFrame = 0; + char version[4]; + SDL_Surface* image = NULL; + gifdata* gd; + + if ( src == NULL ) + return 0; + + gd = malloc( sizeof(*gd) ); + memset( gd, 0, sizeof(*gd) ); + gd->src = src; + + start = SDL_RWtell( src ); + + if ( !SDL_RWread(src,buf,6,1) ) + { + SDL_SetError( "error reading magic number" ); + goto done; + } + + if ( strncmp((char*)buf,"GIF",3) != 0 ) + { + SDL_SetError( "not a GIF file" ); + goto done; + } + + strncpy( version, (char*)buf+3, 3 ); + version[3] = '\0'; + + if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) ) + { + SDL_SetError( "bad version number, not '87a' or '89a'" ); + goto done; + } + + gd->g89.transparent = -1; + gd->g89.delayTime = -1; + gd->g89.inputFlag = -1; + gd->g89.disposal = AG_DISPOSE_NA; + + if ( !SDL_RWread(src,buf,7,1) ) + { + SDL_SetError( "failed to read screen descriptor" ); + goto done; + } + + gd->gs.Width = LM_to_uint(buf[0],buf[1]); + gd->gs.Height = LM_to_uint(buf[2],buf[3]); + gd->gs.BitPixel = 2 << (buf[4] & 0x07); + gd->gs.ColorResolution = (((buf[4] & 0x70) >> 3) + 1); + gd->gs.Background = buf[5]; + gd->gs.AspectRatio = buf[6]; + + if ( BitSet(buf[4],LOCALCOLORMAP) ) /* Global Colormap */ + { + if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) ) + { + SDL_SetError( "error reading global colormap" ); + goto done; + } + } + + do + { + if ( !SDL_RWread(src,&c,1,1) ) + { + SDL_SetError( "EOF / read error on image data" ); + goto done; + } + + if ( c == ';' ) /* GIF terminator */ + goto done; + + if ( c == '!' ) /* Extension */ + { + if ( !SDL_RWread(src,&c,1,1) ) + { + SDL_SetError( "EOF / read error on extention function code" ); + goto done; + } + DoExtension( gd, c ); + continue; + } + + if ( c != ',' ) /* Not a valid start character */ + continue; + + if ( !SDL_RWread(src,buf,9,1) ) + { + SDL_SetError( "couldn't read left/top/width/height" ); + goto done; + } + + useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP); + bitPixel = 1 << ((buf[8] & 0x07) + 1); + + if ( !useGlobalColormap ) + { + if ( ReadColorMap(gd,bitPixel,gd->localColorMap) ) + { + SDL_SetError( "error reading local colormap" ); + goto done; + } + image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), bitPixel, gd->localColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) ); + } + else + { + image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), gd->gs.BitPixel, gd->gs.ColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) ); + } + + if ( frames ) + { + if ( image == NULL ) + goto done; + + if ( gd->g89.transparent >= 0 ) + SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent ); + + frames[iFrame].surface = image; + frames[iFrame].x = LM_to_uint(buf[0], buf[1]); + frames[iFrame].y = LM_to_uint(buf[2], buf[3]); + frames[iFrame].disposal = gd->g89.disposal; + frames[iFrame].delay = gd->g89.delayTime*10; +/* gd->g89.transparent = -1; ** Hmmm, not sure if this should be reset for each frame? */ + } + + iFrame++; + } while ( iFrame < maxFrames || frames == NULL ); + +done: + if ( image == NULL ) + SDL_RWseek( src, start, SEEK_SET ); + if (loop) + *loop = gd->loop; + free( gd ); + + return iFrame; +} + + + +static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] ) +{ + int i; + unsigned char rgb[3]; + int flag; + + flag = TRUE; + + for ( i = 0; i < number; ++i ) + { + if ( !SDL_RWread(gd->src,rgb,sizeof(rgb),1) ) + { + SDL_SetError( "bad colormap" ); + return 1; + } + + buffer[CM_RED][i] = rgb[0]; + buffer[CM_GREEN][i] = rgb[1]; + buffer[CM_BLUE][i] = rgb[2]; + flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]); + } + + return FALSE; +} + + + +static int DoExtension( gifdata* gd, int label ) +{ + unsigned char buf[256]; + switch ( label ) + { + case 0x01: /* Plain Text Extension */ + break; + case 0xff: /* Application Extension */ + if (GetDataBlock( gd, buf ) != 11) + break; + if (strncmp((char*)buf, "NETSCAPE2.0", 11)) + break; + if (GetDataBlock( gd, buf ) != 3) + break; + if (buf[0] != 1) + break; + gd->loop = buf[1] | (buf[2] << 8); + break; + + case 0xfe: /* Comment Extension */ + while ( GetDataBlock(gd,buf) != 0 ) + ; + return FALSE; + + case 0xf9: /* Graphic Control Extension */ + (void)GetDataBlock( gd, buf ); + gd->g89.disposal = (buf[0] >> 2) & 0x7; + gd->g89.inputFlag = (buf[0] >> 1) & 0x1; + gd->g89.delayTime = LM_to_uint(buf[1],buf[2]); + if ( (buf[0] & 0x1) != 0 ) + gd->g89.transparent = buf[3]; + + while ( GetDataBlock(gd,buf) != 0 ) + ; + return FALSE; + } + + while ( GetDataBlock(gd,buf) != 0 ) + ; + + return FALSE; +} + + + +static int GetDataBlock( gifdata* gd, unsigned char* buf ) +{ + unsigned char count; + + if ( !SDL_RWread(gd->src,&count,1,1) ) + { + /* pm_message("error in getting DataBlock size" ); */ + return -1; + } + + gd->zerodatablock = count == 0; + + if ( (count != 0) && !SDL_RWread(gd->src,buf,count,1) ) + { + /* pm_message("error in reading DataBlock" ); */ + return -1; + } + + return count; +} + + + +static int GetCode( gifdata* gd, int code_size, int flag ) +{ + int i, j, ret; + int count; + + if ( flag ) + { + gd->curbit = 0; + gd->lastbit = 0; + gd->done = FALSE; + return 0; + } + + if ( (gd->curbit + code_size) >= gd->lastbit ) + { + if ( gd->done ) + { + if ( gd->curbit >= gd->lastbit ) + SDL_SetError( "ran off the end of my bits" ); + return -1; + } + + gd->buf[0] = gd->buf[gd->lastbyte - 2]; + gd->buf[1] = gd->buf[gd->lastbyte - 1]; + + if ( (count = GetDataBlock(gd, &gd->buf[2])) == 0 ) + gd->done = TRUE; + + gd->lastbyte = 2 + count; + gd->curbit = (gd->curbit - gd->lastbit) + 16; + gd->lastbit = (2 + count)*8; + } + + ret = 0; + for ( i = gd->curbit, j = 0; j < code_size; ++i, ++j ) + ret |= ((gd->buf[i / 8] & (1 << (i % 8))) != 0) << j; + + gd->curbit += code_size; + + return ret; +} + + + +static int LWZReadByte( gifdata* gd, int flag, int input_code_size ) +{ + int i, code, incode; + + if ( flag ) + { + gd->setcodesize = input_code_size; + gd->codesize = gd->setcodesize + 1; + gd->clearcode = 1 << gd->setcodesize; + gd->endcode = gd->clearcode + 1; + gd->maxcodesize = gd->clearcode*2; + gd->maxcode = gd->clearcode + 2; + + GetCode( gd, 0, TRUE ); + + gd->fresh = TRUE; + + for ( i = 0; i < gd->clearcode; ++i ) + { + gd->table[0][i] = 0; + gd->table[1][i] = i; + } + + for ( ; i < (1 << MAX_LWZ_BITS); ++i ) + gd->table[0][i] = gd->table[1][0] = 0; + + gd->sp = gd->stack; + return 0; + } + else if ( gd->fresh ) + { + gd->fresh = FALSE; + do + { + gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE ); + } while ( gd->firstcode == gd->clearcode ); + return gd->firstcode; + } + + if ( gd->sp > gd->stack ) + return *--gd->sp; + + while ( (code = GetCode(gd,gd->codesize,FALSE)) >= 0 ) + { + if ( code == gd->clearcode ) + { + for ( i = 0; i < gd->clearcode; ++i ) + { + gd->table[0][i] = 0; + gd->table[1][i] = i; + } + + for ( ; i < (1 << MAX_LWZ_BITS); ++i ) + gd->table[0][i] = gd->table[1][i] = 0; + + gd->codesize = gd->setcodesize + 1; + gd->maxcodesize = gd->clearcode*2; + gd->maxcode = gd->clearcode + 2; + gd->sp = gd->stack; + gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE ); + return gd->firstcode; + } + else if ( code == gd->endcode ) + { + int count; + unsigned char buf[260]; + + if ( gd->zerodatablock ) + return -2; + + while ( (count = GetDataBlock(gd,buf)) > 0 ) + ; + + if ( count != 0 ) + { + /* pm_message("missing EOD in data stream (common occurence)"); */ + } + return -2; + } + + incode = code; + + if ( code >= gd->maxcode ) + { + *gd->sp++ = gd->firstcode; + code = gd->oldcode; + } + + while ( code >= gd->clearcode ) + { + *gd->sp++ = gd->table[1][code]; + if ( code == gd->table[0][code] ) + SDL_SetError( "circular table entry BIG ERROR" ); + code = gd->table[0][code]; + } + + *gd->sp++ = gd->firstcode = gd->table[1][code]; + + if ( (code = gd->maxcode) < (1 << MAX_LWZ_BITS) ) + { + gd->table[0][code] = gd->oldcode; + gd->table[1][code] = gd->firstcode; + ++gd->maxcode; + if ( (gd->maxcode >= gd->maxcodesize) && (gd->maxcodesize < (1 << MAX_LWZ_BITS)) ) + { + gd->maxcodesize *= 2; + ++gd->codesize; + } + } + + gd->oldcode = incode; + + if ( gd->sp > gd->stack ) + return *--gd->sp; + } + + return code; +} + + + +static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore ) +{ + SDL_Surface* image; + unsigned char c; + int i, v; + int xpos = 0, ypos = 0, pass = 0; + + /* Initialize the compression routines */ + if ( !SDL_RWread(gd->src,&c,1,1) ) + { + SDL_SetError( "EOF / read error on image data" ); + return NULL; + } + + if ( LWZReadByte(gd,TRUE,c) < 0 ) + { + SDL_SetError( "error reading image" ); + return NULL; + } + + /* If this is an "uninteresting picture" ignore it. */ + if ( ignore ) + { + while ( LWZReadByte(gd,FALSE,c) >= 0 ) + ; + return NULL; + } + + image = SDL_AllocSurface( SDL_SWSURFACE, len, height, 8, 0, 0, 0, 0 ); + + for ( i = 0; i < cmapSize; i++ ) + { + image->format->palette->colors[i].r = cmap[CM_RED][i]; + image->format->palette->colors[i].g = cmap[CM_GREEN][i]; + image->format->palette->colors[i].b = cmap[CM_BLUE][i]; + } + + while ( (v = LWZReadByte(gd,FALSE,c)) >= 0 ) + { + ((Uint8*)image->pixels)[xpos + ypos*image->pitch] = (Uint8)v; + ++xpos; + + if ( xpos == len ) + { + xpos = 0; + if ( interlace ) + { + switch ( pass ) + { + case 0: + case 1: ypos += 8; break; + case 2: ypos += 4; break; + case 3: ypos += 2; break; + } + + if ( ypos >= height ) + { + ++pass; + switch ( pass ) + { + case 1: ypos = 4; break; + case 2: ypos = 2; break; + case 3: ypos = 1; break; + default: goto fini; + } + } + } + else + { + ++ypos; + } + } + + if ( ypos >= height ) + break; + } + +fini: + return image; +} + diff --git a/src/sdl-instead/SDL_anigif.h b/src/sdl-instead/SDL_anigif.h index b7f41e2..1fe8c67 100644 --- a/src/sdl-instead/SDL_anigif.h +++ b/src/sdl-instead/SDL_anigif.h @@ -1,61 +1,61 @@ -/* - SDL_anigif: An example animated GIF image loading library for use with SDL - SDL_image Copyright (C) 1997-2006 Sam Lantinga - Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen - - This library is free software; you can redistribute it and/or - modify it under the terms of the GNU Lesser General Public - License as published by the Free Software Foundation; either - version 2.1 of the License, or (at your option) any later version. - - This library is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - Lesser General Public License for more details. - - You should have received a copy of the GNU Lesser General Public - License along with this library; if not, write to the Free Software - Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA -*/ - -#ifndef _SDL_ANIGIF_H -#define _SDL_ANIGIF_H - -#include -#ifdef __cplusplus - extern "C" { -#endif - - - -typedef struct -{ - SDL_Surface* surface; /* SDL surface for this frame */ - int x, y; /* Frame offset position */ - int disposal; /* Disposal code */ - int delay; /* Frame delay in ms */ - int user; /* User data (not used by aniGIF) */ -} AG_Frame; - -#define AG_DISPOSE_NA 0 /* No disposal specified */ -#define AG_DISPOSE_NONE 1 /* Do not dispose */ -#define AG_DISPOSE_RESTORE_BACKGROUND 2 /* Restore to background */ -#define AG_DISPOSE_RESTORE_PREVIOUS 3 /* Restore to previous */ - - - -extern DECLSPEC int AG_isGIF( SDL_RWops* src ); -extern DECLSPEC int AG_LoadGIF( const char* file, AG_Frame* frames, int maxFrames ); -extern DECLSPEC void AG_FreeSurfaces( AG_Frame* frames, int nFrames ); -extern DECLSPEC int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ); -extern DECLSPEC int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ); -extern DECLSPEC int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int size ); - - - -#ifdef __cplusplus - } -#endif -#include "close_code.h" - -#endif /* _SDL_ANIGIF_H */ +/* + SDL_anigif: An example animated GIF image loading library for use with SDL + SDL_image Copyright (C) 1997-2006 Sam Lantinga + Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen + + This library is free software; you can redistribute it and/or + modify it under the terms of the GNU Lesser General Public + License as published by the Free Software Foundation; either + version 2.1 of the License, or (at your option) any later version. + + This library is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + Lesser General Public License for more details. + + You should have received a copy of the GNU Lesser General Public + License along with this library; if not, write to the Free Software + Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA +*/ + +#ifndef _SDL_ANIGIF_H +#define _SDL_ANIGIF_H + +#include +#ifdef __cplusplus + extern "C" { +#endif + + + +typedef struct +{ + SDL_Surface* surface; /* SDL surface for this frame */ + int x, y; /* Frame offset position */ + int disposal; /* Disposal code */ + int delay; /* Frame delay in ms */ + int user; /* User data (not used by aniGIF) */ +} AG_Frame; + +#define AG_DISPOSE_NA 0 /* No disposal specified */ +#define AG_DISPOSE_NONE 1 /* Do not dispose */ +#define AG_DISPOSE_RESTORE_BACKGROUND 2 /* Restore to background */ +#define AG_DISPOSE_RESTORE_PREVIOUS 3 /* Restore to previous */ + + + +extern DECLSPEC int AG_isGIF( SDL_RWops* src ); +extern DECLSPEC int AG_LoadGIF( const char* file, AG_Frame* frames, int maxFrames, int *loop ); +extern DECLSPEC void AG_FreeSurfaces( AG_Frame* frames, int nFrames ); +extern DECLSPEC int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ); +extern DECLSPEC int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames ); +extern DECLSPEC int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int size, int *loop ); + + + +#ifdef __cplusplus + } +#endif +#include "close_code.h" + +#endif /* _SDL_ANIGIF_H */ diff --git a/src/sdl-instead/game.c b/src/sdl-instead/game.c index b45070f..75068bc 100644 --- a/src/sdl-instead/game.c +++ b/src/sdl-instead/game.c @@ -1182,8 +1182,10 @@ inv: if (new_pict || new_place) { img_t offscreen; game_cursor(CURSOR_CLEAR); + gfx_stop_gif(el_img(el_spic)); offscreen = gfx_screen(oldscreen); gfx_change_screen(offscreen); + gfx_start_gif(el_img(el_spic)); gfx_free_image(offscreen); // input_clear(); goto err; diff --git a/src/sdl-instead/graphics.c b/src/sdl-instead/graphics.c index 9610588..81edf3e 100644 --- a/src/sdl-instead/graphics.c +++ b/src/sdl-instead/graphics.c @@ -231,6 +231,7 @@ struct _anigif_t { struct _anigif_t *prev; int cur_frame; int nr_frames; + int loop; int x; int y; int drawn; @@ -254,7 +255,8 @@ static anigif_t anigif_find(anigif_t g) return NULL; } extern int timer_counter; -static void anigif_frame(anigif_t g) + +static void anigif_disposal(anigif_t g) { SDL_Rect dest; SDL_Rect clip; @@ -290,12 +292,24 @@ static void anigif_frame(anigif_t g) if (img) { /* draw bg */ SDL_BlitSurface(Surf(img), NULL, screen, &dest); } - dest.x = g->x; - dest.y = g->y; + SDL_SetClipRect(screen, &clip); +} + +static void anigif_frame(anigif_t g) +{ + SDL_Rect dest; + SDL_Rect clip; + + AG_Frame *frame; + frame = &g->frames[g->cur_frame]; + SDL_GetClipRect(screen, &clip); + + dest.x = g->x + frame->x; + dest.y = g->y + frame->y; dest.w = frame->surface->w; dest.h = frame->surface->h; - dest.x += frame->x; - dest.y += frame->y; + + SDL_SetClipRect(screen, &g->clip); SDL_BlitSurface(frame->surface, NULL, screen, &dest); g->delay = timer_counter; SDL_SetClipRect(screen, &clip); @@ -516,10 +530,12 @@ img_t gfx_load_image(char *filename) SDL_Surface *img; int nr; - nr = AG_LoadGIF(filename, NULL, 0); + nr = AG_LoadGIF(filename, NULL, 0, NULL); if (nr > 0) { /* anigif logic */ + int loop = 0; anigif_t agif = malloc(sizeof(struct _anigif_t) + nr * sizeof(AG_Frame)); - AG_LoadGIF(filename, agif->frames, nr); + AG_LoadGIF(filename, agif->frames, nr, &loop); + agif->loop = loop; agif->nr_frames = nr; agif->cur_frame = 0; agif->drawn = 0; @@ -608,17 +624,36 @@ int gfx_frame_gif(img_t img) { anigif_t ag; ag = is_anigif(img); + if (!ag) return 0; + if (!ag->drawn) return 0; + + if (ag->loop == -1) + return 0; + if ((timer_counter - ag->delay) < (ag->frames[ag->cur_frame].delay / HZ)) return 0; + + anigif_disposal(ag); ag->cur_frame ++; + if (ag->cur_frame >= ag->nr_frames) { - ag->cur_frame = 0; + if (!ag->loop || ag->loop > 1) + ag->cur_frame = 0; + else + ag->cur_frame --; /* last one */ + if (ag->loop) { + ag->loop --; + if (!ag->loop) + ag->loop = -1; /* disabled */ + } + } - anigif_frame(ag); + if (ag->loop != -1) + anigif_frame(ag); return 1; }