1 /*
2 *	SDL Graphics Extension
3 *	Pixel, surface and color functions
4 *
5 *	Started 990815 (split from sge_draw 010611)
6 *
7 *	License: LGPL v2+ (see the file LICENSE)
8 *	(c)1999-2001 Anders Lindstr�m
9 */
10 
11 /*********************************************************************
12  *  This library is free software; you can redistribute it and/or    *
13  *  modify it under the terms of the GNU Library General Public      *
14  *  License as published by the Free Software Foundation; either     *
15  *  version 2 of the License, or (at your option) any later version. *
16  *********************************************************************/
17 
18 /*
19 *  Some of this code is taken from the "Introduction to SDL" and
20 *  John Garrison's PowerPak
21 */
22 
23 #include "SDL.h"
24 #include <math.h>
25 #include <string.h>
26 #include <stdarg.h>
27 #include "sge_surface.h"
28 
29 
30 /* Globals used for sge_Update/sge_Lock */
31 Uint8 _sge_update=1;
32 Uint8 _sge_lock=1;
33 
34 
35 /**********************************************************************************/
36 /**                            Misc. functions                                   **/
37 /**********************************************************************************/
38 
39 //==================================================================================
40 // Turns off automatic update (to avoid tearing).
41 //==================================================================================
sge_Update_OFF(void)42 void sge_Update_OFF(void)
43 {
44 	_sge_update=0;
45 }
46 
47 //==================================================================================
48 // Turns on automatic update (default)
49 //==================================================================================
sge_Update_ON(void)50 void sge_Update_ON(void)
51 {
52 	_sge_update=1;
53 }
54 
55 //==================================================================================
56 // Turns off automatic locking of surfaces
57 //==================================================================================
sge_Lock_OFF(void)58 void sge_Lock_OFF(void)
59 {
60 	_sge_lock=0;
61 }
62 
63 //==================================================================================
64 // Turns on automatic locking (default)
65 //==================================================================================
sge_Lock_ON(void)66 void sge_Lock_ON(void)
67 {
68 	_sge_lock=1;
69 }
70 
71 //==================================================================================
72 // Returns update&locking mode (1-on and 0-off)
73 //==================================================================================
sge_getUpdate(void)74 Uint8 sge_getUpdate(void)
75 {
76   return _sge_update;
77 }
sge_getLock(void)78 Uint8 sge_getLock(void)
79 {
80   return _sge_lock;
81 }
82 
83 
84 //==================================================================================
85 // SDL_UpdateRect does nothing if any part of the rectangle is outside the surface
86 // --- This version always work
87 //==================================================================================
sge_UpdateRect(SDL_Surface * screen,Sint16 x,Sint16 y,Uint16 w,Uint16 h)88 void sge_UpdateRect(SDL_Surface *screen, Sint16 x, Sint16 y, Uint16 w, Uint16 h)
89 {
90 	if(_sge_update!=1 || screen != SDL_GetVideoSurface()){return;}
91 
92 	if(x>=screen->w || y>=screen->h){return;}
93 
94 	Sint16 a,b;
95 
96 	a=w; b=h;
97 
98 
99 	if(x < 0){x=0;}
100 	if(y < 0){y=0;}
101 
102 	if(a+x > screen->w){a=screen->w-x;}
103 	if(b+y > screen->h){b=screen->h-y;}
104 
105 	SDL_UpdateRect(screen,x,y,a,b);
106 }
107 
108 
109 //==================================================================================
110 // Creates a 32bit (8/8/8/8) alpha surface
111 // Map colors with sge_MapAlpha() and then use the Uint32 color versions of
112 // SGEs routines
113 //==================================================================================
sge_CreateAlphaSurface(Uint32 flags,int width,int height)114 SDL_Surface *sge_CreateAlphaSurface(Uint32 flags, int width, int height)
115 {
116 	return SDL_CreateRGBSurface(flags,width,height,32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
117 }
118 
119 
120 //==================================================================================
121 // Returns the Uint32 color value for a 32bit (8/8/8/8) alpha surface
122 //==================================================================================
sge_MapAlpha(Uint8 R,Uint8 G,Uint8 B,Uint8 A)123 Uint32 sge_MapAlpha(Uint8 R, Uint8 G, Uint8 B, Uint8 A)
124 {
125 	Uint32 color=0;
126 
127 	color|=R<<24;
128 	color|=G<<16;
129 	color|=B<<8;
130 	color|=A;
131 
132 	return color;
133 }
134 
135 
136 //==================================================================================
137 // Sets an SDL error string
138 // Accepts formated argument - like printf()
139 // SDL_SetError() also does this, but it does not use standard syntax (why?)
140 //==================================================================================
sge_SetError(const char * format,...)141 void sge_SetError(const char *format, ...)
142 {
143 	char buf[256];
144 
145 	va_list ap;
146 
147 	#ifdef __WIN32__
148 	va_start((va_list*)ap, format); //Stupid w32 crosscompiler
149 	#else
150 	va_start(ap, format);
151 	#endif
152 
153 	vsprintf(buf, format, ap);
154 	va_end(ap);
155 
156 	SDL_SetError(buf);
157 }
158 
159 
160 
161 /**********************************************************************************/
162 /**                            Pixel functions                                   **/
163 /**********************************************************************************/
164 
165 //==================================================================================
166 // Fast put pixel
167 //==================================================================================
_PutPixel(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)168 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
169 {
170 	if(x>=sge_clip_xmin(surface) && x<=sge_clip_xmax(surface) && y>=sge_clip_ymin(surface) && y<=sge_clip_ymax(surface)){
171 		switch (surface->format->BytesPerPixel) {
172 			case 1: { /* Assuming 8-bpp */
173 				*((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
174 			}
175 			break;
176 
177 			case 2: { /* Probably 15-bpp or 16-bpp */
178 				*((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
179 			}
180 			break;
181 
182 			case 3: { /* Slow 24-bpp mode, usually not used */
183 				Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
184 
185   				/* Gack - slow, but endian correct */
186 				*(pix+surface->format->Rshift/8) = color>>surface->format->Rshift;
187   				*(pix+surface->format->Gshift/8) = color>>surface->format->Gshift;
188   				*(pix+surface->format->Bshift/8) = color>>surface->format->Bshift;
189 				*(pix+surface->format->Ashift/8) = color>>surface->format->Ashift;
190 			}
191 			break;
192 
193 			case 4: { /* Probably 32-bpp */
194 				*((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
195 			}
196 			break;
197 		}
198 	}
199 
200 }
201 
202 
203 //==================================================================================
204 // Fast put pixel (RGB)
205 //==================================================================================
_PutPixel(SDL_Surface * surface,Sint16 x,Sint16 y,Uint8 R,Uint8 G,Uint8 B)206 void _PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint8 R, Uint8 G, Uint8 B)
207 {
208 	_PutPixel(surface,x,y, SDL_MapRGB(surface->format, R, G, B));
209 }
210 
211 
212 //==================================================================================
213 // Fastest put pixel functions (don't mess up indata, thank you)
214 //==================================================================================
_PutPixel8(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)215 void _PutPixel8(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
216 {
217 	*((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
218 }
_PutPixel16(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)219 void _PutPixel16(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
220 {
221 	*((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
222 }
_PutPixel24(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)223 void _PutPixel24(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
224 {
225 	Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
226 
227   	/* Gack - slow, but endian correct */
228 	*(pix+surface->format->Rshift/8) = color>>surface->format->Rshift;
229   	*(pix+surface->format->Gshift/8) = color>>surface->format->Gshift;
230   	*(pix+surface->format->Bshift/8) = color>>surface->format->Bshift;
231 	*(pix+surface->format->Ashift/8) = color>>surface->format->Ashift;
232 }
_PutPixel32(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)233 void _PutPixel32(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
234 {
235 	*((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
236 }
_PutPixelX(SDL_Surface * dest,Sint16 x,Sint16 y,Uint32 color)237 void _PutPixelX(SDL_Surface *dest,Sint16 x,Sint16 y,Uint32 color)
238 {
239 	switch ( dest->format->BytesPerPixel ) {
240 	case 1:
241 		*((Uint8 *)dest->pixels + y*dest->pitch + x) = color;
242 		break;
243 	case 2:
244 		*((Uint16 *)dest->pixels + y*dest->pitch/2 + x) = color;
245 		break;
246 	case 3:
247 		_PutPixel24(dest,x,y,color);
248 		break;
249 	case 4:
250 		*((Uint32 *)dest->pixels + y*dest->pitch/4 + x) = color;
251 		break;
252 	}
253 }
254 
255 
256 //==================================================================================
257 // Safe put pixel
258 //==================================================================================
sge_PutPixel(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color)259 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
260 {
261 
262 	if ( SDL_MUSTLOCK(surface) && _sge_lock ) {
263 		if ( SDL_LockSurface(surface) < 0 ) {
264 			return;
265 		}
266 	}
267 
268 	_PutPixel(surface, x, y, color);
269 
270 	if ( SDL_MUSTLOCK(surface) && _sge_lock ) {
271 		SDL_UnlockSurface(surface);
272 	}
273 
274 	if(_sge_update!=1){return;}
275 	sge_UpdateRect(surface, x, y, 1, 1);
276 }
277 
278 
279 //==================================================================================
280 // Safe put pixel (RGB)
281 //==================================================================================
sge_PutPixel(SDL_Surface * surface,Sint16 x,Sint16 y,Uint8 R,Uint8 G,Uint8 B)282 void sge_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint8 R, Uint8 G, Uint8 B)
283 {
284   sge_PutPixel(surface,x,y, SDL_MapRGB(surface->format, R, G, B));
285 }
286 
287 
288 //==================================================================================
289 // Calculate y pitch offset
290 // (the y pitch offset is constant for the same y coord and surface)
291 //==================================================================================
sge_CalcYPitch(SDL_Surface * dest,Sint16 y)292 Sint32 sge_CalcYPitch(SDL_Surface *dest,Sint16 y)
293 {
294 	if(y>=sge_clip_ymin(dest) && y<=sge_clip_ymax(dest)){
295 		switch ( dest->format->BytesPerPixel ) {
296 		case 1:
297 			return y*dest->pitch;
298 			break;
299 		case 2:
300 			return y*dest->pitch/2;
301 			break;
302 		case 3:
303 			return y*dest->pitch;
304 			break;
305 		case 4:
306 			return y*dest->pitch/4;
307 			break;
308 		}
309 	}
310 
311 	return -1;
312 }
313 
314 
315 //==================================================================================
316 // Put pixel with precalculated y pitch offset
317 //==================================================================================
sge_pPutPixel(SDL_Surface * surface,Sint16 x,Sint32 ypitch,Uint32 color)318 void sge_pPutPixel(SDL_Surface *surface, Sint16 x, Sint32 ypitch, Uint32 color)
319 {
320 	if(x>=sge_clip_xmin(surface) && x<=sge_clip_xmax(surface) && ypitch>=0){
321 		switch (surface->format->BytesPerPixel) {
322 			case 1: { /* Assuming 8-bpp */
323 				*((Uint8 *)surface->pixels + ypitch + x) = color;
324 			}
325 			break;
326 
327 			case 2: { /* Probably 15-bpp or 16-bpp */
328 				*((Uint16 *)surface->pixels + ypitch + x) = color;
329 			}
330 			break;
331 
332 			case 3: { /* Slow 24-bpp mode, usually not used */
333   				/* Gack - slow, but endian correct */
334   				Uint8 *pix = (Uint8 *)surface->pixels + ypitch + x*3;
335 
336 				*(pix+surface->format->Rshift/8) = color>>surface->format->Rshift;
337   				*(pix+surface->format->Gshift/8) = color>>surface->format->Gshift;
338   				*(pix+surface->format->Bshift/8) = color>>surface->format->Bshift;
339 				*(pix+surface->format->Ashift/8) = color>>surface->format->Ashift;
340 			}
341 			break;
342 
343 			case 4: { /* Probably 32-bpp */
344 				*((Uint32 *)surface->pixels + ypitch + x) = color;
345 			}
346 			break;
347 		}
348 	}
349 }
350 
351 
352 //==================================================================================
353 // Get pixel
354 //==================================================================================
sge_GetPixel(SDL_Surface * surface,Sint16 x,Sint16 y)355 Uint32 sge_GetPixel(SDL_Surface *surface, Sint16 x, Sint16 y)
356 {
357 	switch (surface->format->BytesPerPixel) {
358 		case 1: { /* Assuming 8-bpp */
359 			return *((Uint8 *)surface->pixels + y*surface->pitch + x);
360 		}
361 		break;
362 
363 		case 2: { /* Probably 15-bpp or 16-bpp */
364 			return *((Uint16 *)surface->pixels + y*surface->pitch/2 + x);
365 		}
366 		break;
367 
368 		case 3: { /* Slow 24-bpp mode, usually not used */
369 			Uint8 *pix;
370 			int shift;
371 			Uint32 color=0;
372 
373 			pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
374 			shift = surface->format->Rshift;
375 			color = *(pix+shift/8)<<shift;
376 			shift = surface->format->Gshift;
377 			color|= *(pix+shift/8)<<shift;
378 			shift = surface->format->Bshift;
379 			color|= *(pix+shift/8)<<shift;
380 			shift = surface->format->Ashift;
381 			color|= *(pix+shift/8)<<shift;
382 			return color;
383 		}
384 		break;
385 
386 		case 4: { /* Probably 32-bpp */
387 			return *((Uint32 *)surface->pixels + y*surface->pitch/4 + x);
388 		}
389 		break;
390 	}
391 	return 0;
392 }
393 
394 
395 //==================================================================================
396 // Put pixel with alpha blending
397 //==================================================================================
_PutPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)398 void _PutPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
399 {
400 	if(x>=sge_clip_xmin(surface) && x<=sge_clip_xmax(surface) && y>=sge_clip_ymin(surface) && y<=sge_clip_ymax(surface)){
401 		Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
402 		Uint32 R,G,B,A=0;
403 
404 		switch (surface->format->BytesPerPixel) {
405 			case 1: { /* Assuming 8-bpp */
406 				if( alpha == 255 ){
407 					*((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
408 				}else{
409 					Uint8 *pixel = (Uint8 *)surface->pixels + y*surface->pitch + x;
410 
411 					Uint8 dR = surface->format->palette->colors[*pixel].r;
412 					Uint8 dG = surface->format->palette->colors[*pixel].g;
413 					Uint8 dB = surface->format->palette->colors[*pixel].b;
414 					Uint8 sR = surface->format->palette->colors[color].r;
415 					Uint8 sG = surface->format->palette->colors[color].g;
416 					Uint8 sB = surface->format->palette->colors[color].b;
417 
418 					dR = dR + ((sR-dR)*alpha >> 8);
419 					dG = dG + ((sG-dG)*alpha >> 8);
420 					dB = dB + ((sB-dB)*alpha >> 8);
421 
422 					*pixel = SDL_MapRGB(surface->format, dR, dG, dB);
423 				}
424 			}
425 			break;
426 
427 			case 2: { /* Probably 15-bpp or 16-bpp */
428 				if( alpha == 255 ){
429 					*((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
430 				}else{
431 					Uint16 *pixel = (Uint16 *)surface->pixels + y*surface->pitch/2 + x;
432 					Uint32 dc = *pixel;
433 
434 					R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask;
435 					G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask;
436 					B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask;
437 					if( Amask )
438 						A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask;
439 
440 					*pixel= R | G | B | A;
441 				}
442 			}
443 			break;
444 
445 			case 3: { /* Slow 24-bpp mode, usually not used */
446 				Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
447 				Uint8 rshift8=surface->format->Rshift/8;
448 				Uint8 gshift8=surface->format->Gshift/8;
449 				Uint8 bshift8=surface->format->Bshift/8;
450 				Uint8 ashift8=surface->format->Ashift/8;
451 
452 
453 				if( alpha == 255 ){
454   					*(pix+rshift8) = color>>surface->format->Rshift;
455   					*(pix+gshift8) = color>>surface->format->Gshift;
456   					*(pix+bshift8) = color>>surface->format->Bshift;
457 					*(pix+ashift8) = color>>surface->format->Ashift;
458 				}else{
459 					Uint8 dR, dG, dB, dA=0;
460 					Uint8 sR, sG, sB, sA=0;
461 
462 					pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
463 
464 					dR = *((pix)+rshift8);
465             		dG = *((pix)+gshift8);
466             		dB = *((pix)+bshift8);
467 					dA = *((pix)+ashift8);
468 
469 					sR = (color>>surface->format->Rshift)&0xff;
470 					sG = (color>>surface->format->Gshift)&0xff;
471 					sB = (color>>surface->format->Bshift)&0xff;
472 					sA = (color>>surface->format->Ashift)&0xff;
473 
474 					dR = dR + ((sR-dR)*alpha >> 8);
475 					dG = dG + ((sG-dG)*alpha >> 8);
476 					dB = dB + ((sB-dB)*alpha >> 8);
477 					dA = dA + ((sA-dA)*alpha >> 8);
478 
479 					*((pix)+rshift8) = dR;
480             		*((pix)+gshift8) = dG;
481             		*((pix)+bshift8) = dB;
482 					*((pix)+ashift8) = dA;
483 				}
484 			}
485 			break;
486 
487 			case 4: { /* Probably 32-bpp */
488 				if( alpha == 255 ){
489 					*((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
490 				}else{
491 					Uint32 *pixel = (Uint32 *)surface->pixels + y*surface->pitch/4 + x;
492 					Uint32 dc = *pixel;
493 
494 					R = ((dc & Rmask) + (( (color & Rmask) - (dc & Rmask) ) * alpha >> 8)) & Rmask;
495 					G = ((dc & Gmask) + (( (color & Gmask) - (dc & Gmask) ) * alpha >> 8)) & Gmask;
496 					B = ((dc & Bmask) + (( (color & Bmask) - (dc & Bmask) ) * alpha >> 8)) & Bmask;
497 					if( Amask )
498 						A = ((dc & Amask) + (( (color & Amask) - (dc & Amask) ) * alpha >> 8)) & Amask;
499 
500 					*pixel = R | G | B | A;
501 				}
502 			}
503 			break;
504 		}
505 	}
506 }
507 
sge_PutPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)508 void sge_PutPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
509 {
510 	if ( SDL_MUSTLOCK(surface) && _sge_lock )
511 		if ( SDL_LockSurface(surface) < 0 )
512 			return;
513 
514 	_PutPixelAlpha(surface,x,y,color,alpha);
515 
516 	/* unlock the display */
517 	if (SDL_MUSTLOCK(surface) && _sge_lock) {
518 		SDL_UnlockSurface(surface);
519 	}
520 
521 	if(_sge_update!=1){return;}
522 	sge_UpdateRect(surface, x, y, 1, 1);
523 }
524 
525 
_PutPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)526 void _PutPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
527 {
528   _PutPixelAlpha(surface,x,y, SDL_MapRGB(surface->format, R, G, B),alpha);
529 }
sge_PutPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)530 void sge_PutPixelAlpha(SDL_Surface *surface, Sint16 x, Sint16 y, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
531 {
532   sge_PutPixelAlpha(surface,x,y, SDL_MapRGB(surface->format, R, G, B), alpha);
533 }
534 
535 
536 
537 /**********************************************************************************/
538 /**                            Block functions                                   **/
539 /**********************************************************************************/
540 
541 //==================================================================================
542 // The sge_write_block* functions copies the given block (a surface line) directly
543 // to the surface. This is *much* faster then using the put pixel functions to
544 // update a line. The block consist of Surface->w (the width of the surface) numbers
545 // of color values. Note the difference in byte size for the block elements for
546 // different color dephts. 24 bpp is slow and not included!
547 //==================================================================================
sge_write_block8(SDL_Surface * Surface,Uint8 * block,Sint16 y)548 void sge_write_block8(SDL_Surface *Surface, Uint8 *block, Sint16 y)
549 {
550 	memcpy(	(Uint8 *)Surface->pixels + y*Surface->pitch, block, sizeof(Uint8)*Surface->w );
551 }
sge_write_block16(SDL_Surface * Surface,Uint16 * block,Sint16 y)552 void sge_write_block16(SDL_Surface *Surface, Uint16 *block, Sint16 y)
553 {
554 	memcpy(	(Uint16 *)Surface->pixels + y*Surface->pitch/2, block, sizeof(Uint16)*Surface->w );
555 }
sge_write_block32(SDL_Surface * Surface,Uint32 * block,Sint16 y)556 void sge_write_block32(SDL_Surface *Surface, Uint32 *block, Sint16 y)
557 {
558 	memcpy(	(Uint32 *)Surface->pixels + y*Surface->pitch/4, block, sizeof(Uint32)*Surface->w );
559 }
560 
561 
562 //==================================================================================
563 // ...and get
564 //==================================================================================
sge_read_block8(SDL_Surface * Surface,Uint8 * block,Sint16 y)565 void sge_read_block8(SDL_Surface *Surface, Uint8 *block, Sint16 y)
566 {
567 	memcpy(	block,(Uint8 *)Surface->pixels + y*Surface->pitch, sizeof(Uint8)*Surface->w );
568 }
sge_read_block16(SDL_Surface * Surface,Uint16 * block,Sint16 y)569 void sge_read_block16(SDL_Surface *Surface, Uint16 *block, Sint16 y)
570 {
571 	memcpy(	block,(Uint16 *)Surface->pixels + y*Surface->pitch/2, sizeof(Uint16)*Surface->w );
572 }
sge_read_block32(SDL_Surface * Surface,Uint32 * block,Sint16 y)573 void sge_read_block32(SDL_Surface *Surface, Uint32 *block, Sint16 y)
574 {
575 	memcpy(	block,(Uint32 *)Surface->pixels + y*Surface->pitch/4, sizeof(Uint32)*Surface->w );
576 }
577 
578 
579 
580 /**********************************************************************************/
581 /**                       Blitting/surface functions                             **/
582 /**********************************************************************************/
583 
584 //==================================================================================
585 // Clear surface to color
586 //==================================================================================
sge_ClearSurface(SDL_Surface * Surface,Uint32 color)587 void sge_ClearSurface(SDL_Surface *Surface, Uint32 color)
588 {
589 
590 	SDL_FillRect(Surface,NULL, color);
591 
592 	if(_sge_update!=1){return;}
593 	SDL_UpdateRect(Surface, 0,0,0,0);
594 }
595 
596 
597 //==================================================================================
598 // Clear surface to color (RGB)
599 //==================================================================================
sge_ClearSurface(SDL_Surface * Surface,Uint8 R,Uint8 G,Uint8 B)600 void sge_ClearSurface(SDL_Surface *Surface, Uint8 R, Uint8 G, Uint8 B)
601 {
602 	sge_ClearSurface(Surface,SDL_MapRGB(Surface->format, R, G, B));
603 }
604 
605 
606 //==================================================================================
607 // Blit from one surface to another
608 // Warning! Alpha and color key is lost (=0) on Src surface
609 //==================================================================================
sge_BlitTransparent(SDL_Surface * Src,SDL_Surface * Dest,Sint16 SrcX,Sint16 SrcY,Sint16 DestX,Sint16 DestY,Sint16 W,Sint16 H,Uint32 Clear,Uint8 Alpha)610 int sge_BlitTransparent(SDL_Surface *Src, SDL_Surface *Dest, Sint16 SrcX, Sint16 SrcY, Sint16 DestX, Sint16 DestY, Sint16 W, Sint16 H, Uint32 Clear, Uint8 Alpha)
611 {
612  	SDL_Rect src, dest;
613 	int ret;
614 
615 	/* Dest clipping */
616 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
617     SDL_VERSIONNUM(1, 1, 5)
618 	int flag=0;
619 	if (DestX < Dest->clip_minx){
620 		SrcX += Dest->clip_minx-DestX;
621 		W -= Dest->clip_minx-DestX-1;
622 		DestX=Dest->clip_minx;
623  	}
624 	if (DestY < Dest->clip_miny){
625 		SrcY +=Dest->clip_miny-DestY;
626 		H -= Dest->clip_miny-DestY-1;
627  		DestY=Dest->clip_miny;
628  	}
629 	if ((DestX + W) > Dest->clip_maxx){
630 		W = W - ((DestX + W) - Dest->clip_maxx)+1;
631 		if(W<=0){SDL_SetError("SGE - Blit error");return -1;}
632  	}
633  	if ((DestY + H) > Dest->clip_maxy){
634 		H = H - ((DestY + H) - Dest->clip_maxy)+1;
635 		if(H<=0){SDL_SetError("SGE - Blit error");return -1;}
636  	}
637 	#endif
638 
639  	/* Initialize our rectangles */
640  	src.x = SrcX;
641  	src.y = SrcY;
642  	src.w = W;
643  	src.h = H;
644 
645  	dest.x = DestX;
646  	dest.y = DestY;
647  	dest.w = W;
648  	dest.h = H;
649 
650 	/* We don't care about src clipping, only dest! */
651 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
652     SDL_VERSIONNUM(1, 1, 5)
653 	if ( (Src->flags & SDL_SRCCLIPPING) == SDL_SRCCLIPPING){
654 		Src->flags &= ~SDL_SRCCLIPPING; flag=1;
655 	}
656 	#endif
657 
658  	/* Set the color to be transparent */
659  	SDL_SetColorKey(Src, SDL_SRCCOLORKEY, Clear);
660 
661  	/* Set the alpha value */
662  	SDL_SetAlpha(Src, SDL_SRCALPHA, Alpha);
663 
664 	/* Blit */
665  	ret=SDL_BlitSurface(Src, &src, Dest, &dest);
666 
667 	/* Set the correct flag */
668 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
669     SDL_VERSIONNUM(1, 1, 5)
670 	if (flag==1){
671 		Src->flags |= SDL_SRCCLIPPING;
672 	}
673 	#endif
674 
675 	/* Set normal levels */
676 	SDL_SetAlpha(Src,0,0);
677 	SDL_SetColorKey(Src,0,0);
678 
679 	return ret;
680 }
681 
682 
683 //==================================================================================
684 // Blit from one surface to another (not touching alpha or color key -
685 // use SDL_SetColorKey and SDL_SetAlpha)
686 //==================================================================================
sge_Blit(SDL_Surface * Src,SDL_Surface * Dest,Sint16 SrcX,Sint16 SrcY,Sint16 DestX,Sint16 DestY,Sint16 W,Sint16 H)687 int sge_Blit(SDL_Surface *Src, SDL_Surface *Dest, Sint16 SrcX, Sint16 SrcY, Sint16 DestX, Sint16 DestY, Sint16 W, Sint16 H)
688 {
689 	SDL_Rect src, dest;
690 	int ret;
691 
692 	/* Dest clipping */
693 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
694     SDL_VERSIONNUM(1, 1, 5)
695 	int flag=0;
696 	if (DestX < Dest->clip_minx){
697 		SrcX += Dest->clip_minx-DestX;
698 		W -= Dest->clip_minx-DestX -1;
699 		DestX=Dest->clip_minx;
700  	}
701 	if (DestY < Dest->clip_miny){
702 		SrcY +=Dest->clip_miny-DestY;
703 		H -= Dest->clip_miny-DestY -1;
704  		DestY=Dest->clip_miny;
705  	}
706 	if ((DestX + W) > Dest->clip_maxx){
707 		W = W - ((DestX + W) - Dest->clip_maxx)+1;
708 		if(W<=0){SDL_SetError("SGE - Blit error");return -1;}
709 	}
710  	if ((DestY + H) > Dest->clip_maxy){
711 		H = H - ((DestY + H) - Dest->clip_maxy)+1;
712 		if(H<=0){SDL_SetError("SGE - Blit error");return -1;}
713  	}
714 	#endif
715 
716  	/* Initialize our rectangles */
717  	src.x = SrcX;
718  	src.y = SrcY;
719  	src.w = W;
720  	src.h = H;
721 
722  	dest.x = DestX;
723  	dest.y = DestY;
724  	dest.w = W;
725  	dest.h = H;
726 
727 	/* We don't care about src clipping, only dest! */
728 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
729     SDL_VERSIONNUM(1, 1, 5)
730 	if ( (Src->flags & SDL_SRCCLIPPING) == SDL_SRCCLIPPING){
731 		Src->flags &= ~SDL_SRCCLIPPING; flag=1;
732 	}
733 	#endif
734 
735 	/* Blit */
736  	ret=SDL_BlitSurface(Src, &src, Dest, &dest);
737 
738 	/* Set the correct flag */
739 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
740     SDL_VERSIONNUM(1, 1, 5)
741 	if (flag==1){
742 		Src->flags |= SDL_SRCCLIPPING;
743 	}
744 	#endif
745 
746 	return ret;
747 }
748 
749 
750 //==================================================================================
751 // Copies a surface to a new...
752 //==================================================================================
sge_copy_surface(SDL_Surface * src)753 SDL_Surface *sge_copy_surface(SDL_Surface *src)
754 {
755 	return SDL_ConvertSurface(src, src->format,SDL_SWSURFACE);
756 }
757 
758 
759 
sge_copy_surface(SDL_Surface * a_poSource,Sint16 x,Sint16 y,Sint16 w,Sint16 h)760 SDL_Surface *sge_copy_surface(SDL_Surface *a_poSource, Sint16 x, Sint16 y, Sint16 w, Sint16 h)
761 {
762 	SDL_Surface* poDest;
763 	poDest = SDL_CreateRGBSurface( SDL_SWSURFACE, w, h, a_poSource->format->BitsPerPixel,
764 		a_poSource->format->Rmask, a_poSource->format->Gmask, a_poSource->format->Bmask, a_poSource->format->Amask );
765 	if ( a_poSource->format->BitsPerPixel <= 8 )
766 	{
767 		SDL_SetColors( poDest, a_poSource->format->palette->colors, 0, a_poSource->format->palette->ncolors );
768 	}
769 
770 	sge_Blit( a_poSource, poDest, x, y, 0, 0, w, h );
771 	return poDest;
772 }
773 
774 
775 
776 
777 
778 /**********************************************************************************/
779 /**                            Palette functions                                 **/
780 /**********************************************************************************/
781 //==================================================================================
782 // Fill in a palette entry with R, G, B componenets
783 //==================================================================================
sge_FillPaletteEntry(Uint8 R,Uint8 G,Uint8 B)784 SDL_Color sge_FillPaletteEntry(Uint8 R, Uint8 G, Uint8 B)
785 {
786    SDL_Color color;
787 
788    color.r = R;
789    color.g = G;
790    color.b = B;
791 
792    return color;
793 }
794 
795 
796 //==================================================================================
797 // Get the RGB of a color value
798 // Needed in those dark days before SDL 1.0
799 //==================================================================================
sge_GetRGB(SDL_Surface * Surface,Uint32 Color)800 SDL_Color sge_GetRGB(SDL_Surface *Surface, Uint32 Color)
801 {
802 	SDL_Color rgb;
803 	SDL_GetRGB(Color, Surface->format, &(rgb.r), &(rgb.g), &(rgb.b));
804 
805 	return(rgb);
806 }
807 
808 
809 //==================================================================================
810 // Fades from (sR,sG,sB) to (dR,dG,dB), puts result in ctab[start] to ctab[stop]
811 //==================================================================================
sge_Fader(SDL_Surface * Surface,Uint8 sR,Uint8 sG,Uint8 sB,Uint8 dR,Uint8 dG,Uint8 dB,Uint32 * ctab,int start,int stop)812 void sge_Fader(SDL_Surface *Surface, Uint8 sR,Uint8 sG,Uint8 sB, Uint8 dR,Uint8 dG,Uint8 dB,Uint32 *ctab,int start, int stop)
813 {
814 	// (sR,sG,sB) and (dR,dG,dB) are two points in space (the RGB cube).
815 
816 	/* The vector for the straight line */
817 	int v[3];
818 	v[0]=dR-sR; v[1]=dG-sG; v[2]=dB-sB;
819 
820 	/* Ref. point */
821 	int x0=sR, y0=sG, z0=sB;
822 
823 	// The line's equation is:
824 	// x= x0 + v[0] * t
825 	// y= y0 + v[1] * t
826 	// z= z0 + v[2] * t
827 	//
828 	// (x,y,z) will travel between the two points when t goes from 0 to 1.
829 
830 	int i=start;
831  	double step=1.0/((stop+1)-start);
832 
833 	for(double t=0.0; t<=1.0 && i<=stop ; t+=step){
834 		ctab[i++]=SDL_MapRGB(Surface->format, (Uint8)(x0+v[0]*t), (Uint8)(y0+v[1]*t), (Uint8)(z0+v[2]*t) );
835 	}
836 }
837 
838 
839 //==================================================================================
840 // Fades from (sR,sG,sB,sA) to (dR,dG,dB,dA), puts result in ctab[start] to ctab[stop]
841 //==================================================================================
sge_AlphaFader(Uint8 sR,Uint8 sG,Uint8 sB,Uint8 sA,Uint8 dR,Uint8 dG,Uint8 dB,Uint8 dA,Uint32 * ctab,int start,int stop)842 void sge_AlphaFader(Uint8 sR,Uint8 sG,Uint8 sB,Uint8 sA, Uint8 dR,Uint8 dG,Uint8 dB,Uint8 dA, Uint32 *ctab,int start, int stop)
843 {
844 	// (sR,sG,sB,sA) and (dR,dG,dB,dA) are two points in hyperspace (the RGBA hypercube).
845 
846 	/* The vector for the straight line */
847 	int v[4];
848 	v[0]=dR-sR; v[1]=dG-sG; v[2]=dB-sB; v[3]=dA-sA;
849 
850 	/* Ref. point */
851 	int x0=sR, y0=sG, z0=sB, w0=sA;
852 
853 	// The line's equation is:
854 	// x= x0 + v[0] * t
855 	// y= y0 + v[1] * t
856 	// z= z0 + v[2] * t
857 	// w= w0 + v[3] * t
858 	//
859 	// (x,y,z,w) will travel between the two points when t goes from 0 to 1.
860 
861 	int i=start;
862  	double step=1.0/((stop+1)-start);
863 
864 	for(double t=0.0; t<=1.0 && i<=stop ; t+=step)
865 		ctab[i++]=sge_MapAlpha((Uint8)(x0+v[0]*t), (Uint8)(y0+v[1]*t), (Uint8)(z0+v[2]*t), (Uint8)(w0+v[3]*t));
866 
867 }
868 
869 
870 //==================================================================================
871 // Copies a nice rainbow palette to the color table (ctab[start] to ctab[stop]).
872 // You must also set the intensity of the palette (0-bright 255-dark)
873 //==================================================================================
sge_SetupRainbowPalette(SDL_Surface * Surface,Uint32 * ctab,int intensity,int start,int stop)874 void sge_SetupRainbowPalette(SDL_Surface *Surface,Uint32 *ctab,int intensity, int start, int stop)
875 {
876 	int slice=(int)((stop-start)/6);
877 
878 	/* Red-Yellow */
879 	sge_Fader(Surface, 255,intensity,intensity, 255,255,intensity, ctab, start,slice);
880  	/* Yellow-Green */
881 	sge_Fader(Surface, 255,255,intensity, intensity,255,intensity, ctab, slice+1, 2*slice);
882  	/* Green-Turquoise blue */
883 	sge_Fader(Surface, intensity,255,intensity, intensity,255,255, ctab, 2*slice+1, 3*slice);
884  	/* Turquoise blue-Blue */
885 	sge_Fader(Surface, intensity,255,255, intensity,intensity,255, ctab, 3*slice+1, 4*slice);
886  	/* Blue-Purple */
887 	sge_Fader(Surface, intensity,intensity,255, 255,intensity,255, ctab, 4*slice+1, 5*slice);
888  	/* Purple-Red */
889 	sge_Fader(Surface, 255,intensity,255, 255,intensity,intensity, ctab, 5*slice+1, stop);
890 }
891 
892 
893 //==================================================================================
894 // Copies a B&W palette to the color table (ctab[start] to ctab[stop]).
895 //==================================================================================
sge_SetupBWPalette(SDL_Surface * Surface,Uint32 * ctab,int start,int stop)896 void sge_SetupBWPalette(SDL_Surface *Surface,Uint32 *ctab,int start, int stop)
897 {
898 	sge_Fader(Surface, 0,0,0, 255,255,255, ctab,start,stop);
899 }
900 
901