1 /*	Public domain	*/
2 
3 #ifndef _AGAR_GUI_ANIM_H_
4 #define _AGAR_GUI_ANIM_H_
5 
6 #include <agar/gui/surface.h>
7 
8 #include <agar/gui/begin.h>
9 
10 enum ag_anim_type {
11 	AG_ANIM_PACKED,		/* Packed-pixel format */
12 	AG_ANIM_INDEXED		/* Indexed format */
13 };
14 
15 /* Animation frame. */
16 typedef struct ag_anim_frame {
17 	void *pixels;			/* Pixel data */
18 	Uint flags;
19 } AG_AnimFrame;
20 
21 /* Animated surface structure. */
22 typedef struct ag_anim {
23 	AG_Mutex lock;
24 	enum ag_anim_type type;		/* Type of animation */
25 	AG_PixelFormat *format;		/* Pixel format */
26 	Uint flags;
27 /* #define AG_SRCCOLORKEY 0x01 */
28 /* #define AG_SRCALPHA    0x02 */
29 #define AG_SAVED_ANIM_FLAGS (AG_SRCCOLORKEY|AG_SRCALPHA)
30 	Uint w, h;			/* Size in pixels */
31 	Uint n;				/* Number of frames */
32 	Uint pitch;			/* Scanline size in bytes */
33 	AG_AnimFrame *f;		/* Frame data */
34 	AG_Rect clipRect;		/* Clipping rect for blit as dst */
35 	double fpsOrig;			/* Original frames/second (hint) */
36 } AG_Anim;
37 
38 /* Animation instance (playback status). */
39 typedef struct ag_anim_state {
40 	AG_Mutex lock;
41 	AG_Anim *an;			/* Back pointer to anim */
42 	Uint flags;
43 #define AG_ANIM_LOOP	 0x01		/* Loop playback */
44 #define AG_ANIM_PINGPONG 0x02		/* Loop in ping-pong fashion */
45 #define AG_ANIM_REVERSE	 0x04		/* Playback in reverse */
46 	int play;			/* Animation is playing */
47 	int f;				/* Current frame# */
48 	double fps;			/* Effective frames/second */
49 	AG_Thread th;			/* Animation thread */
50 } AG_AnimState;
51 
52 __BEGIN_DECLS
53 AG_Anim    *AG_AnimNew(enum ag_anim_type, Uint, Uint, const AG_PixelFormat *,
54                        Uint);
55 AG_Anim    *AG_AnimEmpty(void);
56 AG_Anim    *AG_AnimIndexed(Uint, Uint, int, Uint);
57 AG_Anim    *AG_AnimRGB(Uint, Uint, int, Uint, Uint32, Uint32, Uint32);
58 AG_Anim    *AG_AnimRGBA(Uint, Uint, int, Uint, Uint32, Uint32, Uint32, Uint32);
59 AG_Anim    *AG_AnimFromPNGs(const char *);
60 AG_Anim    *AG_AnimFromJPEGs(const char *);
61 int         AG_AnimSetPalette(AG_Anim *, AG_Color *, Uint, Uint);
62 AG_Anim    *AG_AnimDup(const AG_Anim *);
63 int         AG_AnimResize(AG_Anim *, Uint, Uint);
64 void        AG_AnimFree(AG_Anim *);
65 
66 void        AG_AnimStateInit(AG_Anim *, AG_AnimState *);
67 void        AG_AnimStateDestroy(AG_Anim *, AG_AnimState *);
68 void        AG_AnimSetOrigFPS(AG_Anim *, double);
69 void        AG_AnimSetFPS(AG_AnimState *, double);
70 void        AG_AnimSetLoop(AG_AnimState *, int);
71 void        AG_AnimSetPingPong(AG_AnimState *, int);
72 void        AG_AnimSetAlpha(AG_Anim *, Uint, Uint8);
73 void        AG_AnimSetColorKey(AG_Anim *, Uint, Uint32);
74 
75 int         AG_AnimPlay(AG_AnimState *);
76 void        AG_AnimStop(AG_AnimState *);
77 
78 int         AG_AnimFrameNew(AG_Anim *, const AG_Surface *);
79 AG_Surface *AG_AnimFrameToSurface(AG_Anim *, int);
80 
81 #define AG_AnimStdRGB(w,h) \
82 	AG_AnimRGB((w),(h),agSurfaceFmt->BitsPerPixel,0, \
83 	    agSurfaceFmt->Rmask, \
84 	    agSurfaceFmt->Gmask, \
85 	    agSurfaceFmt->Bmask)
86 #define AG_AnimStdRGBA(w,h) \
87 	AG_AnimRGBA((w),(h),agSurfaceFmt->BitsPerPixel,0, \
88 	    agSurfaceFmt->Rmask, \
89 	    agSurfaceFmt->Gmask, \
90 	    agSurfaceFmt->Bmask, \
91 	    agSurfaceFmt->Amask)
92 
93 static __inline__ Uint32
AG_AnimGetPixel(const AG_Anim * an,const Uint8 * pSrc)94 AG_AnimGetPixel(const AG_Anim *an, const Uint8 *pSrc)
95 {
96 	switch (an->format->BytesPerPixel) {
97 	case 4:
98 		return (*(Uint32 *)pSrc);
99 	case 3:
100 #if AG_BYTEORDER == AG_BIG_ENDIAN
101 		return ((pSrc[0] << 16) +
102 		        (pSrc[1] << 8) +
103 		         pSrc[2]);
104 #else
105 		return  (pSrc[0] +
106 		        (pSrc[1] << 8) +
107 		        (pSrc[2] << 16));
108 #endif
109 	case 2:
110 		return (*(Uint16 *)pSrc);
111 	}
112 	return (*pSrc);
113 }
114 
115 static __inline__ void
AG_AnimPutPixel(AG_Anim * an,Uint8 * pDst,Uint32 cDst)116 AG_AnimPutPixel(AG_Anim *an, Uint8 *pDst, Uint32 cDst)
117 {
118 	switch (an->format->BytesPerPixel) {
119 	case 4:
120 		*(Uint32 *)pDst = cDst;
121 		break;
122 	case 3:
123 #if AG_BYTEORDER == AG_BIG_ENDIAN
124 		pDst[0] = (cDst>>16) & 0xff;
125 		pDst[1] = (cDst>>8) & 0xff;
126 		pDst[2] = cDst & 0xff;
127 #else
128 		pDst[2] = (cDst>>16) & 0xff;
129 		pDst[1] = (cDst>>8) & 0xff;
130 		pDst[0] = cDst & 0xff;
131 #endif
132 		break;
133 	case 2:
134 		*(Uint16 *)pDst = (Uint16)cDst;
135 		break;
136 	default:
137 		*pDst = (Uint8)cDst;
138 		break;
139 	}
140 }
141 
142 __END_DECLS
143 
144 #include <agar/gui/close.h>
145 #endif /* _AGAR_GUI_ANIM_H_ */
146