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