1 /////////////////////////////////////////
2 //
3 //   OpenLieroX
4 //
5 //   Auxiliary Software class library
6 //
7 //   based on the work of JasonB
8 //   enhanced by Dark Charlie and Albert Zeyer
9 //
10 //   code under LGPL
11 //
12 /////////////////////////////////////////
13 
14 
15 // Graphics primitives
16 // Created 12/11/01
17 // By Jason Boettcher
18 
19 
20 #ifndef __GFXPRIMITIVES_H__
21 #define __GFXPRIMITIVES_H__
22 
23 #include <SDL.h>
24 #include <SDL_image.h>
25 #include <string>
26 #include <assert.h>
27 
28 #include "Color.h"
29 #include "SmartPointer.h"
30 #include "Debug.h"
31 #include "CVec.h"
32 
33 
34 //
35 // Misc routines, defines and variables
36 //
37 
38 // Flags used for screen and new surfaces
39 extern	int		iSurfaceFormat;
40 
41 // Like in SDL_video.c in SDL_DisplayFormatAlpha
42 #define ALPHASURFACE_RMASK 0x00ff0000
43 #define ALPHASURFACE_GMASK 0x0000ff00
44 #define ALPHASURFACE_BMASK 0x000000ff
45 #define ALPHASURFACE_AMASK 0xff000000
46 
47 // Gradient direction
48 enum GradientDirection  {
49 	grdHorizontal,
50 	grdVertical
51 };
52 
53 
54 
55 void DumpPixelFormat(const SDL_PixelFormat* format);
56 bool PixelFormatEqual(const SDL_PixelFormat* fm1, const SDL_PixelFormat* fm2);
57 bool IsCorrectSurfaceFormat(const SDL_PixelFormat* format);
58 
59 
60 /////////////////////
61 // Locking and unlocking routines, must be called before doing anything with pixels
LockSurface(SDL_Surface * bmp)62 inline bool LockSurface(SDL_Surface * bmp)  {
63 	if (SDL_MUSTLOCK(bmp))
64 		return SDL_LockSurface(bmp) != -1;
65 	return true;
66 }
LockSurface(const SmartPointer<SDL_Surface> & bmp)67 inline bool LockSurface(const SmartPointer<SDL_Surface> & bmp)  {
68 	return LockSurface(bmp.get());
69 }
70 
UnlockSurface(SDL_Surface * bmp)71 inline void UnlockSurface(SDL_Surface * bmp)  {
72 	if (SDL_MUSTLOCK(bmp))
73 		SDL_UnlockSurface(bmp);
74 }
UnlockSurface(const SmartPointer<SDL_Surface> & bmp)75 inline void UnlockSurface(const SmartPointer<SDL_Surface> & bmp)  {
76 	UnlockSurface(bmp.get());
77 }
78 
79 #define LOCK_OR_QUIT(bmp)	{ if(!LockSurface(bmp)) return; }
80 #define LOCK_OR_FAIL(bmp)	{ if(!LockSurface(bmp)) return false; }
81 
82 
83 ////////////////////
84 // Returns number of bytes the surface takes in memory
GetSurfaceMemorySize(SDL_Surface * surf)85 inline size_t GetSurfaceMemorySize(SDL_Surface *surf)  {
86 	if (surf)
87 		return sizeof(SDL_Surface) + sizeof(SDL_PixelFormat) + surf->w * surf->h * surf->format->BytesPerPixel;
88 	else
89 		return 0;
90 }
91 
92 //
93 // Clipping routines
94 //
95 
96 /////////////////////
97 // Clip the line to the surface
98 bool ClipLine(SDL_Surface * dst, int * x1, int * y1, int * x2, int * y2);
ClipLine(const SmartPointer<SDL_Surface> & bmp,int * x1,int * y1,int * x2,int * y2)99 inline bool ClipLine(const SmartPointer<SDL_Surface> & bmp, int * x1, int * y1, int * x2, int * y2){
100 	return ClipLine(bmp.get(), x1, y1, x2, y2);
101 }
102 
103 class SDLRectBasic : public SDL_Rect {
104 public:
105 	typedef Sint16 Type;
106 	typedef Uint16 TypeS;
107 
SDLRectBasic()108 	SDLRectBasic() { this->SDL_Rect::x = this->SDL_Rect::y = this->SDL_Rect::w = this->SDL_Rect::h = 0; }
SDLRectBasic(const SDL_Rect & r)109 	SDLRectBasic(const SDL_Rect & r): SDL_Rect(r) {}
SDLRectBasic(Type _x,Type _y,TypeS _w,TypeS _h)110 	SDLRectBasic(Type _x, Type _y, TypeS _w, TypeS _h) { SDL_Rect::x = _x; SDL_Rect::y = _y; SDL_Rect::w = _w; SDL_Rect::h = _h; }
x()111 	Type& x() { return this->SDL_Rect::x; }
y()112 	Type& y() { return this->SDL_Rect::y; }
width()113 	TypeS& width() { return this->SDL_Rect::w; }
height()114 	TypeS& height() { return this->SDL_Rect::h; }
115 
x()116 	Type x() const { return this->SDL_Rect::x; }
y()117 	Type y() const { return this->SDL_Rect::y; }
width()118 	TypeS width() const { return this->SDL_Rect::w; }
height()119 	TypeS height() const { return this->SDL_Rect::h; }
120 };
121 
122 template<typename _Type, typename _TypeS>
123 class RefRectBasic {
124 public:
125 	typedef _Type Type;
126 	typedef _TypeS TypeS;
127 private:
128 	Type *m_x, *m_y;
129 	TypeS *m_w, *m_h;
130 public:
RefRectBasic()131 	RefRectBasic() : m_x(NULL), m_y(NULL), m_w(NULL), m_h(NULL) {
132 		// HINT: never use this constructor directly; it's only there to avoid some possible compiler-warnings
133 		assert(false);
134 	}
RefRectBasic(Type & x_,Type & y_,TypeS & w_,TypeS & h_)135 	RefRectBasic(Type& x_, Type& y_, TypeS& w_, TypeS& h_)
136 	: m_x(&x_), m_y(&y_), m_w(&w_), m_h(&h_) {}
137 
x()138 	Type& x() { return *m_x; }
y()139 	Type& y() { return *m_y; }
width()140 	TypeS& width() { return *m_w; }
height()141 	TypeS& height() { return *m_h; }
142 
x()143 	Type x() const { return *m_x; }
y()144 	Type y() const { return *m_y; }
width()145 	TypeS width() const { return *m_w; }
height()146 	TypeS height() const { return *m_h; }
147 };
148 
149 
150 // _RectBasic has to provide the following public members:
151 //		typedef ... Type; // type for x,y
152 //		typedef ... TypeS; // type for w,h
153 //		Type x();
154 //		Type y();
155 //		TypeS width();
156 //		TypeS height();
157 //		and the above as const
158 template<typename _RectBasic>
159 class OLXRect : public _RectBasic {
160 public:
161 
OLXRect(const _RectBasic & r)162 	OLXRect(const _RectBasic & r): _RectBasic(r) {}
163 
OLXRect(typename _RectBasic::Type x,typename _RectBasic::Type y,typename _RectBasic::TypeS w,typename _RectBasic::TypeS h)164 	OLXRect(typename _RectBasic::Type x, typename _RectBasic::Type y, typename _RectBasic::TypeS w, typename _RectBasic::TypeS h): _RectBasic(x, y, w, h) {}
165 
166 	class GetX2 {
167 	protected:
168 		const _RectBasic* base;
169 	public:
GetX2(const _RectBasic * b)170 		GetX2(const _RectBasic* b) : base(b) {}
Type()171 		operator typename _RectBasic::Type () const
172 		{ return base->x() + base->width(); }
173 	};
174 	class AssignX2 : public GetX2 {
175 	private:
176 		_RectBasic* base;
177 	public:
AssignX2(_RectBasic * b)178 		AssignX2(_RectBasic* b) : GetX2(b), base(b) {}
179 		AssignX2& operator=(const typename _RectBasic::Type& v)
180 		{ base->width() = v - base->x(); return *this; }
181 	};
182 
x2()183 	AssignX2 x2() { return AssignX2(this); }
x2()184 	GetX2 x2() const { return GetX2(this); }
185 
186 	class GetY2 {
187 	protected:
188 		const _RectBasic* base;
189 	public:
GetY2(const _RectBasic * b)190 		GetY2(const _RectBasic* b) : base(b) {}
Type()191 		operator typename _RectBasic::Type () const
192 		{ return base->y() + base->height(); }
193 	};
194 	class AssignY2 : public GetY2 {
195 	private:
196 		_RectBasic* base;
197 	public:
AssignY2(_RectBasic * b)198 		AssignY2(_RectBasic* b) : GetY2(b), base(b) {}
199 		AssignY2& operator=(const typename _RectBasic::Type& v)
200 		{ base->height() = v - base->y(); return *this; }
201 	};
y2()202 	AssignY2 y2() { return AssignY2(this); }
y2()203 	GetY2 y2() const { return GetY2(this); }
204 
205 	template<typename _ClipRect>
clipWith(const _ClipRect & clip)206 	bool clipWith(const _ClipRect& clip) {
207 		// Horizontal
208 		{
209 			typename OLXRect::Type orig_x2 = this->OLXRect::x2();
210 			this->OLXRect::x() = MAX( (typename OLXRect::Type)this->OLXRect::x(), (typename OLXRect::Type)clip.x() );
211 			this->OLXRect::x2() = MIN( orig_x2, (typename OLXRect::Type)clip.x2() );
212 			this->OLXRect::x2() = MAX( this->OLXRect::x(), (typename OLXRect::Type)this->OLXRect::x2() );
213 		}
214 
215 		// Vertical
216 		{
217 			typename OLXRect::Type orig_y2 = this->OLXRect::y2();
218 			this->OLXRect::y() = MAX( (typename OLXRect::Type)this->OLXRect::y(), (typename OLXRect::Type)clip.y() );
219 			this->OLXRect::y2() = MIN( orig_y2, (typename OLXRect::Type)clip.y2() );
220 			this->OLXRect::y2() = MAX( this->OLXRect::y(), (typename OLXRect::Type)this->OLXRect::y2() );
221 		}
222 
223 		return (this->OLXRect::width() && this->OLXRect::height());
224 	}
225 };
226 
227 
228 typedef OLXRect<SDLRectBasic> SDLRect;  // Use this for creating clipping rects from SDL
229 
230 template<typename _Type, typename _TypeS, typename _ClipRect>
ClipRefRectWith(_Type & x,_Type & y,_TypeS & w,_TypeS & h,const _ClipRect & clip)231 bool ClipRefRectWith(_Type& x, _Type& y, _TypeS& w, _TypeS& h, const _ClipRect& clip) {
232 	RefRectBasic<_Type, _TypeS> refrect = RefRectBasic<_Type, _TypeS>(x, y, w, h);
233 	return ((OLXRect<RefRectBasic<_Type, _TypeS> >&) refrect).clipWith(clip);
234 }
235 
236 template<typename _ClipRect>
ClipRefRectWith(SDL_Rect & rect,const _ClipRect & clip)237 bool ClipRefRectWith(SDL_Rect& rect, const _ClipRect& clip) {
238 	RefRectBasic<Sint16,Uint16> refrect(rect.x, rect.y, rect.w, rect.h);
239 	return OLXRect< RefRectBasic<Sint16,Uint16> >(refrect).clipWith(clip);
240 }
241 
242 
243 
244 /////////////////////////
245 // Performs one side (horizontal or vertical) clip
246 // c - x or y; d - width or height
247 template<typename T1, typename T2>
_OneSideClip(T1 & c,T2 & d,const T1 clip_c,const T2 clip_d)248 bool _OneSideClip(T1& c, T2& d, const T1 clip_c, const T2 clip_d)  {
249 	if (c < clip_c)  {
250 		d += c - clip_c;
251 		c = clip_c;
252 		if (d <= 0)  {
253 			d = 0;
254 			return false;
255 		}
256 	}
257 
258 	if (c + d >= clip_c + clip_d)  {
259 		if (c >= clip_c + clip_d)  {
260 			d = 0;
261 			return false;
262 		}
263 
264 		d = clip_c + clip_d - c;
265 	}
266 
267 	return true;
268 }
269 
270 template<typename T1, typename T2, typename T3, typename T4>
OneSideClip(T1 & c,T2 & d,const T3 clip_c,const T4 clip_d)271 bool OneSideClip(T1& c, T2& d, const T3 clip_c, const T4 clip_d)  {
272 	return _OneSideClip(c, d, (T1)clip_c, (T2)clip_d);
273 }
274 
275 ////////////////
276 // Create a SDL rect
MakeRect(int x,int y,int w,int h)277 inline SDL_Rect MakeRect(int x, int y, int w, int h)
278 {
279 	SDL_Rect r = {(SDLRect::Type) x, (SDLRect::Type) y, (SDLRect::TypeS) w, (SDLRect::TypeS) h};
280 	return r;
281 }
282 
283 ////////////////
284 // Returns true if the given point is in the given rect
PointInRect(int x,int y,const SDL_Rect & r)285 inline bool PointInRect(int x, int y, const SDL_Rect& r)
286 {
287 	return	(r.x <= x) && (x <= (r.x + r.w)) &&
288 			(r.y <= y) && (y <= (r.y + r.h));
289 }
290 
291 //////////////////////
292 // Returns true if rect1 contains rect2
ContainsRect(const SDL_Rect & rect1,const SDL_Rect & rect2)293 inline bool ContainsRect(const SDL_Rect& rect1, const SDL_Rect& rect2)
294 {
295 	return (rect1.x <= rect2.x) && (rect1.x + rect1.w >= rect2.x + rect2.w) &&
296 			(rect1.y <= rect2.y) && (rect1.y + rect1.h >= rect2.y + rect2.h);
297 }
298 
299 //
300 // Image loading and saving
301 //
302 
303 //////////////////
304 // Load an image
305 SmartPointer<SDL_Surface> LoadGameImage(const std::string& _filename, bool withalpha = false);
306 
307 /////////////////
308 // Loads an image and quits with error if could not load
309 #define		LOAD_IMAGE(bmp,name)			{ if (!Load_Image(bmp,name)) return false; }
310 #define		LOAD_IMAGE_WITHALPHA(bmp,name)	{ if (!Load_Image_WithAlpha(bmp,name)) return false; }
311 #define		LOAD_IMAGE_WITHALPHA2(bmp,name1,name2)	{ if (!Load_Image_WithAlpha(bmp,name1) && !Load_Image_WithAlpha(bmp,name2)) return false; }
312 #define		LOAD_IMAGE_WITHALPHA__OR(bmp,name,img)	{ if (!Load_Image_WithAlpha(bmp,name) && ((bmp = (img)).get() == NULL)) return false; }
313 
314 /////////////////
315 // Gets the colorkey from the surface
316 #define		COLORKEY(bmp) ((bmp)->format->colorkey)
317 
318 
319 /////////////////////
320 // Load an image, without alpha channel
Load_Image(SmartPointer<SDL_Surface> & bmp,const std::string & name)321 inline bool Load_Image(SmartPointer<SDL_Surface>& bmp, const std::string& name)  {
322 	bmp = LoadGameImage(name);
323 	if (bmp.get() == NULL)  {
324 		warnings << "could not load alpha-image " << name << endl;
325 		return false;
326 	}
327 	return true;
328 }
329 
330 ////////////////////
331 // Load an image with alpha channel
Load_Image_WithAlpha(SmartPointer<SDL_Surface> & bmp,const std::string & name)332 inline bool Load_Image_WithAlpha(SmartPointer<SDL_Surface>& bmp, const std::string& name)  {
333 	bmp = LoadGameImage(name, true);
334 	if (bmp.get() == NULL)  {
335 		warnings << "could not load image " << name << endl;
336 		return false;
337 	}
338 	return true;
339 }
340 
341 ///////////////////
342 // Save surface in the specified format
343 bool SaveSurface(SDL_Surface * image, const std::string& FileName, int Format, const std::string& Data);
SaveSurface(const SmartPointer<SDL_Surface> & image,const std::string & FileName,int Format,const std::string & Data)344 inline bool SaveSurface(const SmartPointer<SDL_Surface> & image, const std::string& FileName, int Format, const std::string& Data){
345 	return SaveSurface(image.get(), FileName, Format, Data);
346 }
347 
348 //
349 // Surface stuff
350 //
351 
352 //////////////////
353 // Creates a buffer with the same details as the screen
354 SmartPointer<SDL_Surface> gfxCreateSurface(int width, int height, bool forceSoftware = false);
355 
356 
357 ///////////////////
358 // Creates an ARGB 32bit surface if screen supports no alpha or a surface like screen
359 SmartPointer<SDL_Surface> gfxCreateSurfaceAlpha(int width, int height, bool forceSoftware = false);
360 
361 ////////////////////
362 // Destroys a surface
363 // Now with SmartPointer usage everywhere this function is forbidden!
364 /*
365 inline void gfxFreeSurface(const SmartPointer<SDL_Surface> & surf)  {
366 	if (surf == NULL)
367 		return;
368 
369 	#ifdef DEBUG_SMARTPTR
370 	printf("gfxFreeSurface() %p\n", surf.get() );
371 	#endif
372 	SDL_FreeSurface(surf);
373 	//surf = NULL; // That's a hack that won't fix anything
374 }
375 */
376 
377 //
378 // Image drawing
379 //
380 
381 ///////////////
382 // Copies one surface to another (not blitting, so the alpha values are kept!)
383 void CopySurface(SDL_Surface * dst, SDL_Surface * src, int sx, int sy, int dx, int dy, int w, int h);
CopySurface(SDL_Surface * dst,const SmartPointer<SDL_Surface> & src,int sx,int sy,int dx,int dy,int w,int h)384 inline void CopySurface(SDL_Surface * dst, const SmartPointer<SDL_Surface> & src, int sx, int sy, int dx, int dy, int w, int h){
385 	CopySurface(dst, src.get(), sx, sy, dx, dy, w, h);
386 }
387 
388 //////////////
389 // Draw the image with a huge amount of options
390 void DrawImageAdv(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, SDL_Rect& rDest, SDL_Rect& rSrc);
391 
DrawImageAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,SDL_Rect & rDest,SDL_Rect & rSrc)392 inline void DrawImageAdv(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, SDL_Rect& rDest, SDL_Rect& rSrc) {
393 	DrawImageAdv(bmpDest, bmpSrc.get(), rDest, rSrc);
394 }
395 
396 //////////////
397 // Draw the image with a huge amount of options
DrawImageAdv(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,int sx,int sy,int dx,int dy,int w,int h)398 inline void DrawImageAdv(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
399 	SDL_Rect r1 = { (SDLRect::Type) dx, (SDLRect::Type) dy, 0, 0 };
400 	SDL_Rect r2 = { (SDLRect::Type) sx, (SDLRect::Type) sy, (SDLRect::TypeS) w, (SDLRect::TypeS) h };
401 	DrawImageAdv( bmpDest, bmpSrc, r1, r2);
402 }
DrawImageAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)403 inline void DrawImageAdv(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
404 	DrawImageAdv(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
405 }
406 
407 
408 ///////////////
409 // Draw the image, with more options
DrawImageEx(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,int x,int y,int w,int h)410 inline void DrawImageEx(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int x, int y, int w, int h) {
411 	DrawImageAdv(bmpDest, bmpSrc, 0, 0, x, y, w, h);
412 }
DrawImageEx(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int x,int y,int w,int h)413 inline void DrawImageEx(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int x, int y, int w, int h) {
414 	DrawImageEx(bmpDest, bmpSrc.get(), x, y, w, h);
415 }
416 
417 ///////////////
418 // Simply draw the image
DrawImage(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,SDL_Rect & rDest)419 inline void DrawImage(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, SDL_Rect& rDest) {
420 	if(!bmpDest) {
421 		errors << "DrawImage: bmpDest not set" << endl;
422 		return;
423 	}
424 	if(!bmpSrc) {
425 		errors << "DrawImage: bmpSrc not set" << endl;
426 		return;
427 	}
428 	SDL_BlitSurface(bmpSrc, NULL, bmpDest, &rDest);
429 }
DrawImage(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,SDL_Rect & rDest)430 inline void DrawImage(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, SDL_Rect& rDest) {
431 	DrawImage(bmpDest, bmpSrc.get(), rDest);
432 }
433 
434 ///////////////
435 // Simply draw the image
DrawImage(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,int x,int y)436 inline void DrawImage(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int x, int y) {
437 	SDL_Rect r = { (SDLRect::Type) x, (SDLRect::Type) y, (SDLRect::TypeS) bmpSrc->w, (SDLRect::TypeS) bmpSrc->h };
438 	DrawImage( bmpDest, bmpSrc, r);
439 }
DrawImage(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int x,int y)440 inline void DrawImage(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int x, int y) {
441 	DrawImage(bmpDest, bmpSrc.get(), x, y);
442 }
443 
444 ///////////////
445 // Draws image mirror flipped
446 // WARNING: passing invalid source x/y/w/h causes a segfault
447 void DrawImageAdv_Mirror(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageAdv_Mirror(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)448 inline void DrawImageAdv_Mirror(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
449 	DrawImageAdv_Mirror(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
450 }
451 
452 void DrawImageAdv_MirrorVertical(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageAdv_MirrorVertical(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)453 inline void DrawImageAdv_MirrorVertical(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
454 	DrawImageAdv_MirrorVertical(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
455 }
456 
457 ////////////////
458 // Draws the image doubly stretched (fast)
459 void DrawImageStretch2(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageStretch2(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)460 inline void DrawImageStretch2(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
461 	DrawImageStretch2(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
462 }
463 
464 /////////////////
465 // Draws the image doubly stretched while checking for colorkey
466 void DrawImageStretch2Key(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageStretch2Key(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)467 inline void DrawImageStretch2Key(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
468 	DrawImageStretch2Key(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
469 }
470 
471 /////////////////
472 // Draws image doubly stretched, mirrored and checking for colorkey
473 // WARNING: passing invalid source x/y/w/h causes a segfault
474 void DrawImageStretchMirrorKey(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageStretchMirrorKey(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)475 inline void DrawImageStretchMirrorKey(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int w, int h) {
476 	DrawImageStretchMirrorKey(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
477 }
478 
GetCopiedImage(SDL_Surface * bmpSrc)479 inline SmartPointer<SDL_Surface> GetCopiedImage(SDL_Surface* bmpSrc) {
480 	SmartPointer<SDL_Surface> result = SDL_CreateRGBSurface(
481 															bmpSrc->flags,
482 															bmpSrc->w, bmpSrc->h,
483 															bmpSrc->format->BitsPerPixel,
484 															bmpSrc->format->Rmask,
485 															bmpSrc->format->Gmask,
486 															bmpSrc->format->Bmask,
487 															bmpSrc->format->Amask);
488 	if (result.get() == NULL) return NULL;
489 	CopySurface(result.get(), bmpSrc, 0, 0, 0, 0, bmpSrc->w, bmpSrc->h);
490 	return result;
491 }
GetCopiedImage(const SmartPointer<SDL_Surface> & bmpSrc)492 inline SmartPointer<SDL_Surface> GetCopiedImage(const SmartPointer<SDL_Surface> & bmpSrc) {
493 	return GetCopiedImage(bmpSrc.get());
494 }
495 
496 /////////////////
497 // Creates a new surface of the same size and draws the image mirror flipped onto it
GetMirroredImage(SDL_Surface * bmpSrc)498 inline SmartPointer<SDL_Surface> GetMirroredImage(SDL_Surface* bmpSrc)  {
499 	SmartPointer<SDL_Surface> result = SDL_CreateRGBSurface(
500 															bmpSrc->flags,
501 															bmpSrc->w, bmpSrc->h,
502 															bmpSrc->format->BitsPerPixel,
503 															bmpSrc->format->Rmask,
504 															bmpSrc->format->Gmask,
505 															bmpSrc->format->Bmask,
506 															bmpSrc->format->Amask);
507 	if (result.get() == NULL) return NULL;
508 	DrawImageAdv_Mirror(result.get(), bmpSrc, 0, 0, 0, 0, bmpSrc->w, bmpSrc->h);
509 	return result;
510 }
GetMirroredImage(const SmartPointer<SDL_Surface> & bmpSrc)511 inline SmartPointer<SDL_Surface> GetMirroredImage(const SmartPointer<SDL_Surface> & bmpSrc) {
512 	return GetMirroredImage(bmpSrc.get());
513 }
514 
515 /////////////////
516 // Draws a sprite doubly stretched but not so advanced
DrawImageStretch(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,int dx,int dy)517 inline void	DrawImageStretch(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int dx, int dy) {
518 	DrawImageStretch2(bmpDest,bmpSrc,0,0,dx,dy,bmpSrc->w,bmpSrc->h);
519 }
DrawImageStretch(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int dx,int dy)520 inline void	DrawImageStretch(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int dx, int dy) {
521 	DrawImageStretch(bmpDest, bmpSrc.get(), dx, dy);
522 }
523 
524 /////////////////
525 // Draws a sprite doubly stretched, with a colour key and not so advanced
DrawImageStretchKey(SDL_Surface * bmpDest,SDL_Surface * bmpSrc,int dx,int dy)526 inline void	DrawImageStretchKey(SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int dx, int dy) {
527 	DrawImageStretch2Key(bmpDest, bmpSrc, 0, 0, dx, dy, bmpSrc->w, bmpSrc->h);
528 }
DrawImageStretchKey(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int dx,int dy)529 inline void	DrawImageStretchKey(SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int dx, int dy) {
530 	DrawImageStretchKey(bmpDest, bmpSrc.get(), dx, dy);
531 }
532 
533 /////////////////
534 // Draws the image resized according to ratios
535 void DrawImageResizedAdv( SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, float xratio, float yratio);
536 void DrawImageResizedAdv( SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, int dw, int dh);
DrawImageResizedAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int sw,int sh,float xratio,float yratio)537 inline void DrawImageResizedAdv( SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, float xratio, float yratio) {
538 	DrawImageResizedAdv( bmpDest, bmpSrc.get(), sx, sy, dx, dy, sw, sh, xratio, yratio);
539 }
DrawImageResizedAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int sw,int sh,int dw,int dh)540 inline void DrawImageResizedAdv( SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, int dw, int dh) {
541 	DrawImageResizedAdv( bmpDest, bmpSrc.get(), sx, sy, dx, dy, sw, sh, dw, dh);
542 }
543 
544 /////////////////
545 // Draws the image nicely resampled, blur says how much the result should be blurred
546 void DrawImageResampledAdv( SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, float xratio, float yratio);
547 void DrawImageResampledAdv( SDL_Surface * bmpDest, SDL_Surface * bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, int dw, int dh);
DrawImageResampledAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int sw,int sh,float xratio,float yratio)548 inline void DrawImageResampledAdv( SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, float xratio, float yratio) {
549 	DrawImageResampledAdv( bmpDest, bmpSrc.get(), sx, sy, dx, dy, sw, sh, xratio, yratio );
550 }
DrawImageResampledAdv(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int sw,int sh,int dw,int dh)551 inline void DrawImageResampledAdv( SDL_Surface * bmpDest, const SmartPointer<SDL_Surface> & bmpSrc, int sx, int sy, int dx, int dy, int sw, int sh, int dw, int dh)  {
552 	DrawImageResampledAdv( bmpDest, bmpSrc.get(), sx, sy, dx, dy, sw, sh, dw, dh );
553 }
554 
555 //////////////////
556 // Draws the image in double size using the scale2x algorithm
557 void DrawImageScale2x(SDL_Surface* bmpDest, SDL_Surface* bmpSrc, int sx, int sy, int dx, int dy, int w, int h);
DrawImageScale2x(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int dx,int dy,int w,int h)558 inline void DrawImageScale2x(SDL_Surface* bmpDest, const SmartPointer<SDL_Surface>& bmpSrc, int sx, int sy, int dx, int dy, int w, int h)  {
559 	DrawImageScale2x(bmpDest, bmpSrc.get(), sx, sy, dx, dy, w, h);
560 }
561 
562 void DrawImageScaleHalf(SDL_Surface* bmpDest, SDL_Surface* bmpSrc);
563 
564 ///////////////////
565 // Tiles the source image onto the dest image
566 void DrawImageTiled(SDL_Surface *bmpDest, SDL_Surface *bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
567 void DrawImageTiledX(SDL_Surface *bmpDest, SDL_Surface *bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
568 void DrawImageTiledY(SDL_Surface *bmpDest, SDL_Surface *bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh);
569 
DrawImageTiled(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh)570 inline void DrawImageTiled(SDL_Surface *bmpDest, const SmartPointer<SDL_Surface>& bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh)  {
571 	DrawImageTiled(bmpDest, bmpSrc.get(), sx, sy, sw, sh, dx, dy, dw, dh);
572 }
DrawImageTiledX(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh)573 inline void DrawImageTiledX(SDL_Surface *bmpDest, const SmartPointer<SDL_Surface>& bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh)  {
574 	DrawImageTiledX(bmpDest, bmpSrc.get(), sx, sy, sw, sh, dx, dy, dw, dh);
575 }
576 
DrawImageTiledY(SDL_Surface * bmpDest,const SmartPointer<SDL_Surface> & bmpSrc,int sx,int sy,int sw,int sh,int dx,int dy,int dw,int dh)577 inline void DrawImageTiledY(SDL_Surface *bmpDest, const SmartPointer<SDL_Surface>& bmpSrc, int sx, int sy, int sw, int sh, int dx, int dy, int dw, int dh)  {
578 	DrawImageTiledX(bmpDest, bmpSrc.get(), sx, sy, sw, sh, dx, dy, dw, dh);
579 }
580 
581 SmartPointer<SDL_Surface> GenerateShadowSurface(SDL_Surface *object, unsigned char opacity = 96);
582 
583 //
584 // Pixel and color routines
585 //
586 
587 
588 ////////////////////
589 // Get address of a pixel
GetPixelAddr(const SDL_Surface * surf,int x,int y)590 inline Uint8 *GetPixelAddr(const SDL_Surface *surf, int x, int y) {
591 	return (Uint8 *)surf->pixels + y * surf->pitch + x * surf->format->BytesPerPixel;
592 }
593 
594 /////////////////
595 // Put pixel to a specified address
596 // WARNING: passing an invalid adress will cause a segfault
597 // NOTE: destination surface must be locked before calling this
PutPixelToAddr(Uint8 * p,Uint32 color,short bpp)598 inline void PutPixelToAddr(Uint8* p, Uint32 color, short bpp) {
599 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
600 	memcpy(p, (Uint8*)&color + 4 - bpp, bpp);
601 #else
602 	memcpy(p, &color, bpp);
603 #endif
604 }
605 
606 //////////////
607 // Pixel drawing
608 // WARNING: passing invalid coordinates will cause a segfault
609 // NOTE: bmpDest must be locked before calling this
PutPixel(SDL_Surface * bmpDest,int x,int y,Uint32 color)610 inline void PutPixel(SDL_Surface * bmpDest, int x, int y, Uint32 color) {
611 	PutPixelToAddr(
612 			(Uint8*)bmpDest->pixels + y * bmpDest->pitch + x * bmpDest->format->BytesPerPixel,
613 			color,
614 			bmpDest->format->BytesPerPixel);
615 }
616 
617 ////////////////
618 // Get a pixel from an 8bit address
619 // WARNING: passing invalid adress will cause a segfault
620 // NOTE: the surface must be locked before calling this
GetPixelFromAddr(Uint8 * p,short bpp)621 inline Uint32 GetPixelFromAddr(Uint8* p, short bpp) {
622 	Uint32 result;
623 	result = 0;
624 #if SDL_BYTEORDER == SDL_BIG_ENDIAN
625 	memcpy((Uint8*)&result + 4 - bpp, p, bpp);
626 #else
627 	memcpy(&result, p, bpp);
628 #endif
629 	return result;
630 }
631 
632 ////////////////
633 // Get a pixel from the surface
634 // WARNING: passing invalid coordinates will cause a segfault
635 // NOTE: bmpSrc must be locked before calling this
636 // This function doesn't have "const SmartPointer<SDL_Surface> &" interface because it will slow it down
GetPixel(SDL_Surface * bmpSrc,int x,int y)637 inline Uint32 GetPixel(SDL_Surface * bmpSrc, int x, int y) {
638 	return GetPixelFromAddr(
639 			(Uint8*)bmpSrc->pixels + y * bmpSrc->pitch + x * bmpSrc->format->BytesPerPixel,
640 			bmpSrc->format->BytesPerPixel);
641 }
642 
643 ////////////////
644 // Copy pixel from one surface to another, both surfaces must have same format
645 // WARNING: doesn't do clipping
646 // NOTE: dst must be locked before calling this
647 // This function doesn't have "const SmartPointer<SDL_Surface> &" interface because it will slow it down
CopyPixel_SameFormat(SDL_Surface * dst,SDL_Surface * src,int dx,int dy,int sx,int sy)648 inline void CopyPixel_SameFormat(
649 	SDL_Surface * dst, SDL_Surface * src,
650 	int dx, int dy, int sx, int sy) {
651 	memcpy(
652 		(Uint8*)dst->pixels + dy * dst->pitch + dx * dst->format->BytesPerPixel,
653 		(Uint8*)src->pixels + sy * src->pitch + sx * dst->format->BytesPerPixel,
654 		dst->format->BytesPerPixel);
655 }
656 
657 ////////////////
658 // Copy pixel from one surface to another, the coordinate on both surfaces is the same
659 // WARNING: doesn't do clipping
660 // WARNING: surfaces must have same format
661 // NOTE: dst must be locked before calling his
662 // This function doesn't have "const SmartPointer<SDL_Surface> &" interface because it will slow it down
CopyPixel_SameFormat(SDL_Surface * dst,SDL_Surface * src,int x,int y)663 inline void CopyPixel_SameFormat(
664 	SDL_Surface * dst, SDL_Surface * src, int x, int y) {
665 	CopyPixel_SameFormat(dst, src, x, y, x, y);
666 }
667 
668 
669 ////////////////
670 // Put pixel alpha blended with the background
671 // WARNING: passing invalid coordinates will cause a segfault
672 // NOTE: dst must be locked before calling this
673 void PutPixelA(SDL_Surface * bmpDest, int x, int y, Uint32 colour, Uint8 a);
674 
675 
676 ////////////////
677 // Extract 4 colour components from a packed int
GetColour4(Uint32 pixel,SDL_PixelFormat * format,Uint8 * r,Uint8 * g,Uint8 * b,Uint8 * a)678 inline void GetColour4(Uint32 pixel, SDL_PixelFormat* format, Uint8 *r, Uint8 *g, Uint8 *b, Uint8 *a) {
679 	SDL_GetRGBA(pixel, format, r, g, b, a);
680 }
681 
682 ///////////////
683 // Extract 3 colour components from a packed int
GetColour3(Uint32 pixel,SDL_PixelFormat * format,Uint8 * r,Uint8 * g,Uint8 * b)684 inline void GetColour3(Uint32 pixel, SDL_PixelFormat* format, Uint8 *r, Uint8 *g, Uint8 *b) {
685 	SDL_GetRGB(pixel, format, r, g, b);
686 }
687 
688 ////////////////
689 // Returns true if the color is considered as (partly) transparent on the surface
IsTransparent(SDL_Surface * surf,Uint32 color)690 inline bool IsTransparent(SDL_Surface * surf, Uint32 color)  {
691 	if((surf->flags & SDL_SRCALPHA) && ((color & surf->format->Amask) != surf->format->Amask))
692 		return true;
693 
694 	// TODO: should this check be done, if SDL_SRCALPHA was set? SDL/OpenGL possibly will ignore it
695 	if((surf->flags & SDL_SRCCOLORKEY) && (EqualRGB(color, COLORKEY(surf), surf->format)))
696 		return true;
697 
698 	return false;
699 }
700 
701 
702 
703 
704 //
705 // Solid drawing
706 //
707 
708 
709 ///////////////////
710 // Draw horizontal line
711 void	DrawHLine(SDL_Surface * bmpDest, int x, int x2, int y, Color colour);
712 
713 ///////////////////
714 // Draw vertical line
715 void	DrawVLine(SDL_Surface * bmpDest, int y, int y2, int x, Color colour);
716 
717 ///////////////////
718 // Draw a line
719 void	DrawLine(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Color color);
720 
721 //////////////////
722 // Draw the line nicely antialiased
723 void	AntiAliasedLine(SDL_Surface * dst, int x1, int y1, int x2, int y2, Color color, void (*proc)(SDL_Surface *, int, int, Uint32, Uint8));
724 
725 /////////////////////
726 // Draws a filled rectangle
727 void	DrawRectFill(SDL_Surface * bmpDest, int x, int y, int x2, int y2, Color color);
728 
729 ////////////////////
730 // Very fast routine for drawing 2x2 rects
731 void DrawRectFill2x2(SDL_Surface *bmpDest, int x, int y, Color color);
732 void DrawRectFill2x2_NoClip(SDL_Surface *bmpDest, int x, int y, Color color);
733 
734 // x,y is center
735 void DrawCircleFilled(SDL_Surface* bmpDest, int x, int y, int rx, int ry, Color color);
736 
737 // draws a cross ("X")
738 void DrawCross(SDL_Surface* bmpDest, int x, int y, int w, int h, Color c);
739 
740 // draw a simple loading animation
741 enum LoadingAniType { LAT_CIRCLES, LAT_CAKE };
742 void DrawLoadingAni(SDL_Surface* bmpDest, int x, int y, int rx, int ry, Color fg, Color bg, LoadingAniType type);
743 
744 struct ScopedBackgroundLoadingAni {
745 	struct Data; Data* data;
746 	ScopedBackgroundLoadingAni(int x, int y, int rx, int ry, Color fg, Color bg, LoadingAniType type = LAT_CIRCLES);
747 	~ScopedBackgroundLoadingAni();
748 };
749 
750 
751 /////////////////////
752 // Draws a simple linear gradient
753 void DrawLinearGradient(SDL_Surface *bmpDest, int x, int y, int w, int h, Color cl1, Color cl2, GradientDirection dir);
754 
755 ////////////////////
756 // Fills the surface with specified colour
FillSurface(SDL_Surface * dst,Color colour)757 inline void FillSurface(SDL_Surface * dst, Color colour) {
758 	if (dst->clip_rect.w > 0 && dst->clip_rect.h > 0)
759 		SDL_FillRect(dst, NULL, colour.get(dst->format));
760 }
761 
FillSurface(SDL_Surface * dst,Uint32 colour)762 inline void FillSurface(SDL_Surface * dst, Uint32 colour) {
763 	if (dst->clip_rect.w > 0 && dst->clip_rect.h > 0)
764 		SDL_FillRect(dst, NULL, colour);
765 }
766 
767 ////////////////////
768 // Fills the whole surface with a transparent color
FillSurfaceTransparent(SDL_Surface * dst)769 inline void FillSurfaceTransparent(SDL_Surface * dst)  {
770 	// check alpha first as it has priority (if set, colorkey is ignored)
771 	if (dst->flags & SDL_SRCALPHA)
772 		FillSurface(dst, SDL_MapRGBA(dst->format, 255, 0, 255, SDL_ALPHA_TRANSPARENT));
773 	else if (dst->flags & SDL_SRCCOLORKEY)
774 		FillSurface(dst, COLORKEY(dst));
775 	else
776 		warnings("There's no possibility to make this surface transparent!\n");
777 }
778 
779 
780 ////////////////////
781 // Draws a rectangle
DrawRect(SDL_Surface * bmpDest,int x,int y,int x2,int y2,Color colour)782 inline void	DrawRect(SDL_Surface * bmpDest, int x, int y, int x2, int y2, Color colour) {
783 	DrawHLine(bmpDest, x, x2, y, colour);
784 	DrawHLine(bmpDest, x, x2, y2, colour);
785 	DrawVLine(bmpDest, y, y2, x, colour);
786 	DrawVLine(bmpDest, y, y2, x2, colour);
787 }
788 
789 ///////////////////
790 // Draws a rectangle with transparency
DrawRectFillA(SDL_Surface * bmpDest,int x,int y,int x2,int y2,Uint32 color,Uint8 alpha)791 inline void DrawRectFillA(SDL_Surface * bmpDest, int x, int y, int x2, int y2, Uint32 color, Uint8 alpha)  {
792 	Color col(bmpDest->format, color); col.a = alpha;
793 	DrawRectFill(bmpDest, x, y, x2, y2, col);
794 }
795 
DrawRectFillA(SDL_Surface * bmpDest,int x,int y,int x2,int y2,Color color,Uint8 alpha)796 inline void DrawRectFillA(SDL_Surface * bmpDest, int x, int y, int x2, int y2, Color color, Uint8 alpha)  {
797 	color.a = alpha;
798 	DrawRectFill(bmpDest, x, y, x2, y2, color);
799 }
800 
801 //////////////////
802 // Draw a triangle
DrawTriangle(SDL_Surface * bmpDest,int x1,int y1,int x2,int y2,int x3,int y3,Color colour)803 inline void DrawTriangle(SDL_Surface * bmpDest, int x1, int y1, int x2, int y2, int x3, int y3, Color colour) {
804 	DrawLine(bmpDest, x1, y1, x2, y2, colour);
805 	DrawLine(bmpDest, x2, y2, x3, y3, colour);
806 	DrawLine(bmpDest, x3, y3, x1, y1, colour);
807 }
808 
809 
810 
811 //
812 // Special lines (rope, laser sight, beam)
813 //
814 
815 void	DrawRope(SDL_Surface * bmp, int x1, int y1, int x2, int y2, Color color);
816 void	DrawBeam(SDL_Surface * bmp, int x1, int y1, int x2, int y2, Color color);
817 void	DrawLaserSight(SDL_Surface * bmp, int x1, int y1, int x2, int y2, Color color);
818 
819 
820 //
821 // Colorkey handling
822 //
823 
824 // sets alpha in a safe way for both non-alpha-surfaces and alpha-surfaces
825 // for non-alpha surfaces, it uses SDL_SetAlpha
826 // for real alphablended surfaces, that means this multiplies a/255 to each a-value
827 void SetPerSurfaceAlpha(SDL_Surface * dst, Uint8 a);
828 
829 // set colorkey for both alpha-blended and non-alpha surfaces
830 // for non-alpha surfaces, SDL_SetAlpha is used
831 // for alpha surfaces, it applies to every pixel
832 void SetColorKey(SDL_Surface * dst, Uint8 r, Uint8 g, Uint8 b);
833 
834 //////////////////
835 // Set's the game's default color key (pink) to the surface
836 // Works for both alpha and nonalpha surfaces
837 void SetColorKey(SDL_Surface * dst);
838 
839 //////////////////
840 // Resets the alpha-channel and the colorkey
841 void ResetAlpha(SDL_Surface * dst);
842 
843 
844 struct ScopedSurfaceClip {
845 	SDL_Rect oldclip;
846 	SDL_Surface* surf;
847 
ScopedSurfaceClipScopedSurfaceClip848 	ScopedSurfaceClip(SDL_Surface* s, const SDL_Rect& rect) {
849 		surf = s;
850 		SDL_GetClipRect(s, &oldclip);
851 		SDL_SetClipRect(s, &rect);
852 	}
~ScopedSurfaceClipScopedSurfaceClip853 	~ScopedSurfaceClip() {
854 		SDL_SetClipRect(surf, &oldclip);
855 	}
856 };
857 
858 
859 
860 #endif  //  __GFXPRIMITIVES_H__
861