1 /*
2 *	SDL Graphics Extension
3 *	Drawing primitives
4 *
5 *	Started 990815 (split from sge_draw 010611)
6 *
7 *	License: LGPL v2+ (see the file LICENSE)
8 *	(c)1999-2003 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 <stdlib.h>
28 #include "sge_primitives.h"
29 #include "sge_surface.h"
30 
31 
32 /* Globals used for sge_Update/sge_Lock (defined in sge_surface) */
33 extern Uint8 _sge_update;
34 extern Uint8 _sge_lock;
35 
36 #define SWAP(x,y,temp) temp=x;x=y;y=temp
37 
38 /**********************************************************************************/
39 /**                             Line functions                                   **/
40 /**********************************************************************************/
41 
42 //==================================================================================
43 // Internal draw horizontal line
44 //==================================================================================
_HLine(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint32 Color)45 void _HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
46 {
47 	if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;}
48 
49 	//Do the clipping
50 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
51     SDL_VERSIONNUM(1, 1, 5)
52 	if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
53 		return;
54 	if(x1<Surface->clip_minx)
55 		x1=Surface->clip_minx;
56 	if(x2>Surface->clip_maxx)
57 		x2=Surface->clip_maxx;
58 	#endif
59 
60 	SDL_Rect l;
61 	l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
62 
63 	SDL_FillRect(Surface, &l, Color);
64 }
65 
66 //==================================================================================
67 // Draw horizontal line
68 //==================================================================================
sge_HLine(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint32 Color)69 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color)
70 {
71 	if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;}
72 
73 	//Do the clipping
74 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
75     SDL_VERSIONNUM(1, 1, 5)
76 	if(y<Surface->clip_miny || y>Surface->clip_maxy || x1>Surface->clip_maxx || x2<Surface->clip_minx)
77 		return;
78 	if(x1<Surface->clip_minx)
79 		x1=Surface->clip_minx;
80 	if(x2>Surface->clip_maxx)
81 		x2=Surface->clip_maxx;
82 	#endif
83 
84 	SDL_Rect l;
85 	l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
86 
87 	SDL_FillRect(Surface, &l, Color);
88 
89 	sge_UpdateRect(Surface, x1, y, x2-x1+1, 1);
90 }
91 
92 //==================================================================================
93 // Draw horizontal line (RGB)
94 //==================================================================================
sge_HLine(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint8 R,Uint8 G,Uint8 B)95 void sge_HLine(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B)
96 {
97 	sge_HLine(Surface,x1,x2,y, SDL_MapRGB(Surface->format, R, G, B));
98 }
99 
100 
101 //==================================================================================
102 // Internal draw horizontal line (alpha)
103 //==================================================================================
_HLineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint32 Color,Uint8 alpha)104 void _HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
105 {
106 	Uint8 update = _sge_update;
107 	Uint8 lock = _sge_lock;
108 	_sge_update = 0;
109 	_sge_lock = 0;
110 	sge_FilledRectAlpha(Surface, x1,y,x2,y, Color, alpha);
111 	_sge_update = update;
112 	_sge_lock = lock;
113 }
114 
115 //==================================================================================
116 // Draw horizontal line (alpha)
117 //==================================================================================
sge_HLineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint32 Color,Uint8 alpha)118 void sge_HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint32 Color, Uint8 alpha)
119 {
120 	sge_FilledRectAlpha(Surface, x1,y,x2,y, Color, alpha);
121 }
122 
123 //==================================================================================
124 // Draw horizontal line (alpha RGB)
125 //==================================================================================
sge_HLineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 x2,Sint16 y,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)126 void sge_HLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 x2, Sint16 y, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
127 {
128 	sge_HLineAlpha(Surface,x1,x2,y, SDL_MapRGB(Surface->format, R, G, B), alpha);
129 }
130 
131 
132 //==================================================================================
133 // Internal draw vertical line
134 //==================================================================================
_VLine(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint32 Color)135 void _VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
136 {
137 	if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
138 
139 	//Do the clipping
140 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
141     SDL_VERSIONNUM(1, 1, 5)
142 	if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
143 		return;
144 	if(y1<Surface->clip_miny)
145 		y1=Surface->clip_miny;
146 	if(y2>Surface->clip_maxy)
147 		y2=Surface->clip_maxy;
148 	#endif
149 
150 	SDL_Rect l;
151 	l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
152 
153 	SDL_FillRect(Surface, &l, Color);
154 }
155 
156 //==================================================================================
157 // Draw vertical line
158 //==================================================================================
sge_VLine(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint32 Color)159 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color)
160 {
161 	if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
162 
163 	//Do the clipping
164 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
165     SDL_VERSIONNUM(1, 1, 5)
166 	if(x<Surface->clip_minx || x>Surface->clip_maxx || y1>Surface->clip_maxy || y2<Surface->clip_miny)
167 		return;
168 	if(y1<Surface->clip_miny)
169 		y1=Surface->clip_miny;
170 	if(y2>Surface->clip_maxy)
171 		y2=Surface->clip_maxy;
172 	#endif
173 
174 	SDL_Rect l;
175 	l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
176 
177 	SDL_FillRect(Surface, &l, Color);
178 
179 	sge_UpdateRect(Surface, x, y1, 1, y2-y1+1);
180 }
181 
182 //==================================================================================
183 // Draw vertical line (RGB)
184 //==================================================================================
sge_VLine(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint8 R,Uint8 G,Uint8 B)185 void sge_VLine(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
186 {
187 	sge_VLine(Surface,x,y1,y2, SDL_MapRGB(Surface->format, R, G, B));
188 }
189 
190 
191 //==================================================================================
192 // Internal draw vertical line (alpha - no update)
193 //==================================================================================
_VLineAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint32 Color,Uint8 alpha)194 void _VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
195 {
196 	Uint8 update = _sge_update;
197 	Uint8 lock = _sge_lock;
198 	_sge_update = 0;
199 	_sge_lock = 0;
200 	sge_FilledRectAlpha(Surface, x,y1,x,y2, Color, alpha);
201 	_sge_update = update;
202 	_sge_lock = lock;
203 }
204 
205 //==================================================================================
206 // Draw vertical line (alpha)
207 //==================================================================================
sge_VLineAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint32 Color,Uint8 alpha)208 void sge_VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint32 Color, Uint8 alpha)
209 {
210 	sge_FilledRectAlpha(Surface, x,y1,x,y2, Color, alpha);
211 }
212 
213 //==================================================================================
214 // Draw vertical line (alpha RGB)
215 //==================================================================================
sge_VLineAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y1,Sint16 y2,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)216 void sge_VLineAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y1, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
217 {
218 	sge_VLineAlpha(Surface,x,y1,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
219 }
220 
221 
222 
223 //==================================================================================
224 // Performs Callback at each line point. (From PowerPak)
225 //==================================================================================
sge_DoLine(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 Color,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))226 void sge_DoLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
227 {
228 	Sint16 dx, dy, sdx, sdy, x, y, px, py;
229 
230 	dx = x2 - x1;
231 	dy = y2 - y1;
232 
233 	sdx = (dx < 0) ? -1 : 1;
234 	sdy = (dy < 0) ? -1 : 1;
235 
236 	dx = sdx * dx + 1;
237 	dy = sdy * dy + 1;
238 
239 	x = y = 0;
240 
241 	px = x1;
242 	py = y1;
243 
244 	if (dx >= dy){
245 		for (x = 0; x < dx; x++){
246 			Callback(Surface, px, py, Color);
247 
248 			y += dy;
249 			if (y >= dx){
250 				y -= dx;
251 				py += sdy;
252 			}
253 			px += sdx;
254 		}
255 	}
256 	else{
257 		for (y = 0; y < dy; y++){
258 			Callback(Surface, px, py, Color);
259 
260 			x += dx;
261 			if (x >= dy){
262 				x -= dy;
263 				px += sdx;
264 			}
265 			py += sdy;
266 		}
267 	}
268 }
269 
270 
271 //==================================================================================
272 // Performs Callback at each line point. (RGB)
273 //==================================================================================
sge_DoLine(SDL_Surface * Surface,Sint16 X1,Sint16 Y1,Sint16 X2,Sint16 Y2,Uint8 R,Uint8 G,Uint8 B,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))274 void sge_DoLine(SDL_Surface *Surface, Sint16 X1, Sint16 Y1, Sint16 X2, Sint16 Y2, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
275 {
276 	sge_DoLine(Surface,X1,Y1,X2,Y2, SDL_MapRGB(Surface->format, R, G, B),Callback);
277 }
278 
279 
280 //==================================================================================
281 // Line clipping
282 // Standard Cohen-Sutherland algorithm (from gfxPrimitives)
283 //==================================================================================
284 #define CLIP_LEFT_EDGE   0x1
285 #define CLIP_RIGHT_EDGE  0x2
286 #define CLIP_BOTTOM_EDGE 0x4
287 #define CLIP_TOP_EDGE    0x8
288 #define CLIP_INSIDE(a)   (!a)
289 #define CLIP_REJECT(a,b) (a&b)
290 #define CLIP_ACCEPT(a,b) (!(a|b))
291 
clipEncode(Sint16 x,Sint16 y,Sint16 left,Sint16 top,Sint16 right,Sint16 bottom)292 int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
293 {
294 	int code = 0;
295 
296 	if (x < left)
297 		code |= CLIP_LEFT_EDGE;
298 	else if (x > right)
299 		code |= CLIP_RIGHT_EDGE;
300 
301 	if (y < top)
302 		code |= CLIP_TOP_EDGE;
303 	else if (y > bottom)
304 		code |= CLIP_BOTTOM_EDGE;
305 
306 	return code;
307 }
308 
clipLine(SDL_Surface * dst,Sint16 * x1,Sint16 * y1,Sint16 * x2,Sint16 * y2)309 int clipLine(SDL_Surface *dst, Sint16 *x1, Sint16 *y1, Sint16 *x2, Sint16 *y2)
310 {
311 	int code1, code2;
312 	bool draw = false;
313 
314 	Sint16 tmp;
315 	float m;
316 
317 	/* Get clipping boundary */
318 	Sint16 left, right, top, bottom;
319 	left = sge_clip_xmin(dst);
320 	right = sge_clip_xmax(dst);
321 	top = sge_clip_ymin(dst);
322 	bottom = sge_clip_ymax(dst);
323 
324 	while (true){
325 		code1 = clipEncode(*x1, *y1, left, top, right, bottom);
326 		code2 = clipEncode(*x2, *y2, left, top, right, bottom);
327 
328 		if(CLIP_ACCEPT(code1, code2)){
329 			draw = true;
330 			break;
331 		}else if(CLIP_REJECT(code1, code2))
332 			break;
333 		else{
334 			if(CLIP_INSIDE(code1)){
335 				tmp = *x2;
336 				*x2 = *x1;
337 				*x1 = tmp;
338 				tmp = *y2;
339 				*y2 = *y1;
340 				*y1 = tmp;
341 				tmp = code2;
342 				code2 = code1;
343 				code1 = tmp;
344 			}
345 			if(*x2 != *x1)
346 				m = (*y2 - *y1) / float(*x2 - *x1);
347 			else
348 				m = 1.0;
349 
350 
351 			if(code1 & CLIP_LEFT_EDGE){
352 				*y1 += Sint16( (left - *x1) * m );
353 				*x1 = left;
354 			}else if(code1 & CLIP_RIGHT_EDGE){
355 				*y1 += Sint16( (right - *x1) * m );
356 				*x1 = right;
357 			}else if(code1 & CLIP_BOTTOM_EDGE){
358 				if (*x2 != *x1) {
359 					*x1 += Sint16( (bottom - *y1) / m );
360 				}
361 				*y1 = bottom;
362 			}else if(code1 & CLIP_TOP_EDGE){
363 				if (*x2 != *x1) {
364 					*x1 += Sint16( (top - *y1) / m );
365 				}
366 				*y1 = top;
367 			}
368 		}
369 	}
370 
371 	return draw;
372 }
373 
374 
375 //==================================================================================
376 // Draws a line
377 //==================================================================================
_Line(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)378 void _Line(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
379 {
380 	if( !clipLine(surface, &x1, &y1, &x2, &y2) )
381 		return;
382 
383 	Sint16 dx, dy, sdx, sdy, x, y;
384 
385 	dx = x2 - x1;
386 	dy = y2 - y1;
387 
388 	sdx = (dx < 0) ? -1 : 1;
389 	sdy = (dy < 0) ? -1 : 1;
390 
391 	dx = sdx * dx + 1;
392 	dy = sdy * dy + 1;
393 
394 	x = y = 0;
395 
396 	Sint16 pixx = surface->format->BytesPerPixel;
397   	Sint16 pixy = surface->pitch;
398 	Uint8 *pixel = (Uint8*)surface->pixels + y1*pixy + x1*pixx;
399 
400 	pixx *= sdx;
401   	pixy *= sdy;
402 
403 	if (dx < dy) {
404 		Sint32 tmp = dx; dx = dy; dy = Sint16(tmp);
405 		tmp = pixx; pixx = pixy; pixy = tmp;
406 	}
407 
408 	switch(surface->format->BytesPerPixel) {
409 		case 1: {
410 			for(x=0; x < dx; x++) {
411 				*pixel = color;
412 
413 				y += dy;
414 				if (y >= dx) {
415 					y -= dx;
416 					pixel += pixy;
417 				}
418 				pixel += pixx;
419 			}
420 		}
421 		break;
422 
423 		case 2: {
424 			for(x=0; x < dx; x++) {
425 				*(Uint16*)pixel = color;
426 
427 				y += dy;
428 				if (y >= dx) {
429 					y -= dx;
430 					pixel += pixy;
431 				}
432 				pixel += pixx;
433 			}
434 		}
435 		break;
436 
437 		case 3: {
438 			Uint8 rshift8 = surface->format->Rshift/8;
439 			Uint8 gshift8 = surface->format->Gshift/8;
440 			Uint8 bshift8 = surface->format->Bshift/8;
441 			Uint8 ashift8 = surface->format->Ashift/8;
442 
443 			Uint8 R = (color>>surface->format->Rshift)&0xff;
444 			Uint8 G = (color>>surface->format->Gshift)&0xff;
445 			Uint8 B = (color>>surface->format->Bshift)&0xff;
446 			Uint8 A = (color>>surface->format->Ashift)&0xff;
447 
448 			for(x=0; x < dx; x++) {
449 				*(pixel+rshift8) = R;
450   				*(pixel+gshift8) = G;
451   				*(pixel+bshift8) = B;
452 				*(pixel+ashift8) = A;
453 
454 				y += dy;
455 				if (y >= dx) {
456 					y -= dx;
457 					pixel += pixy;
458 				}
459 				pixel += pixx;
460 			}
461 		}
462 		break;
463 
464 		case 4: {
465 			for(x=0; x < dx; x++) {
466 				*(Uint32*)pixel = color;
467 
468 				y += dy;
469 				if (y >= dx) {
470 					y -= dx;
471 					pixel += pixy;
472 				}
473 				pixel += pixx;
474 			}
475 		}
476 		break;
477 	}
478 }
479 
sge_Line(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 Color)480 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color)
481 {
482 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
483 		if (SDL_LockSurface(Surface) < 0)
484 			return;
485 	}
486 
487 	/* Draw the line */
488 	_Line(Surface, x1,y1, x2,y2, Color);
489 
490 	/* unlock the display */
491 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
492 		SDL_UnlockSurface(Surface);
493 	}
494 
495 	sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
496 }
497 
498 
499 //==================================================================================
500 // Draws a line (RGB)
501 //==================================================================================
sge_Line(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B)502 void sge_Line(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
503 {
504 	sge_Line(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
505 }
506 
507 
508 //==================================================================================
509 // A quick hack to get alpha working with callbacks
510 //==================================================================================
511 Uint8 _sge_alpha_hack = 0;
callback_alpha_hack(SDL_Surface * surf,Sint16 x,Sint16 y,Uint32 color)512 void callback_alpha_hack(SDL_Surface *surf, Sint16 x, Sint16 y, Uint32 color)
513 {
514 	_PutPixelAlpha(surf,x,y,color,_sge_alpha_hack);
515 }
516 
517 //==================================================================================
518 // Draws a line (alpha)
519 //==================================================================================
_LineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 Color,Uint8 alpha)520 void _LineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, Uint8 alpha)
521 {
522 	_sge_alpha_hack = alpha;
523 
524 	/* Draw the line */
525 	sge_DoLine(Surface, x1, y1, x2, y2, Color, callback_alpha_hack);
526 }
527 
sge_LineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 Color,Uint8 alpha)528 void sge_LineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 Color, Uint8 alpha)
529 {
530 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
531 		if (SDL_LockSurface(Surface) < 0)
532 			return;
533 
534 	_LineAlpha(Surface, x1,  y1, x2, y2, Color, alpha);
535 
536 	/* unlock the display */
537 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
538 		SDL_UnlockSurface(Surface);
539 	}
540 
541 	sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
542 }
543 
544 //==================================================================================
545 // Draws a line (alpha - RGB)
546 //==================================================================================
sge_LineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)547 void sge_LineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
548 {
549 	sge_LineAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
550 }
551 
552 
553 //==================================================================================
554 // Anti-aliased line
555 // From SDL_gfxPrimitives written by A. Schiffler (aschiffler@home.com)
556 //==================================================================================
557 #define AAbits 8
558 #define AAlevels 256  /* 2^AAbits */
_AALineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)559 void _AALineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
560 {
561 	Uint32 erracc=0, erradj;
562 	Uint32 erracctmp, wgt;
563 	Sint16 tmp, y0p1, x0pxdir;
564 	Uint8 a;
565 
566 	/* Keep on working with 32bit numbers */
567 	Sint32 xx0=x1;
568 	Sint32 yy0=y1;
569 	Sint32 xx1=x2;
570 	Sint32 yy1=y2;
571 
572 	/* Reorder points if required */
573 	if (yy0 > yy1) {
574 		SWAP(yy0, yy1, tmp);
575 		SWAP(xx0, xx1, tmp);
576 	}
577 
578 	/* Calculate distance */
579 	Sint16 dx = xx1 - xx0;
580 	Sint16 dy = yy1 - yy0;
581 
582 	/* Adjust for negative dx and set xdir */
583 	Sint16 xdir = 1;
584 	if (dx < 0) {
585 		xdir=-1;
586 		dx=(-dx);
587 	}
588 
589 	/* Check for special cases */
590 	if (dx==0 || dy==0 || dx==dy) {
591 		if(alpha==SDL_ALPHA_OPAQUE)
592 			_Line(dst,x1,y1,x2,y2,color);
593 		else
594 			_LineAlpha(dst,x1,y1,x2,y2,color,alpha);
595 		return;
596 	}
597 
598 	float alpha_pp = float(alpha)/255;  /* Used to calculate alpha level if alpha != 255 */
599 
600 	Uint32 intshift    = 32 - AAbits;   /* # of bits by which to shift erracc to get intensity level */
601 
602 	/* Draw the initial pixel in the foreground color */
603 	if(alpha==SDL_ALPHA_OPAQUE)
604 		_PutPixel(dst,x1,y1, color);
605 	else
606 		_PutPixelAlpha(dst,x1,y1, color, alpha);
607 
608 	/* x-major or y-major? */
609 	if (dy > dx) {
610 
611 		/* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
612 		X advances every time Y advances 1 pixel, truncating the result so that
613 		we won't overrun the endpoint along the X axis */
614 		erradj = ((dx << 16) / dy)<<16;
615 
616 		/* draw all pixels other than the first and last */
617 		x0pxdir=xx0+xdir;
618 		while (--dy) {
619 			erracctmp = erracc;
620 			erracc += erradj;
621 			if (erracc <= erracctmp) {
622 				/* rollover in error accumulator, x coord advances */
623 				xx0=x0pxdir;
624 				x0pxdir += xdir;
625 			}
626 			yy0++;			/* y-major so always advance Y */
627 
628 			/* the AAbits most significant bits of erracc give us the intensity
629 			weighting for this pixel, and the complement of the weighting for
630 			the paired pixel. */
631 			wgt = (erracc >> intshift) & 255;
632 
633 			a = Uint8(255-wgt);
634 			if(alpha != SDL_ALPHA_OPAQUE)
635 				a = Uint8(a*alpha_pp);
636 
637 			_PutPixelAlpha(dst,xx0,yy0,color,a);
638 
639 			a = Uint8(wgt);
640 			if(alpha != SDL_ALPHA_OPAQUE)
641 				a = Uint8(a*alpha_pp);
642 
643 			_PutPixelAlpha(dst,x0pxdir,yy0,color,a);
644 		}
645 	} else {
646 
647 		/* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
648 		that Y advances each time X advances 1 pixel, truncating the result so
649 		that we won't overrun the endpoint along the X axis. */
650 		erradj = ((dy << 16) / dx)<<16;
651 
652 		/* draw all pixels other than the first and last */
653 		y0p1=yy0+1;
654 		while (--dx) {
655 
656 			erracctmp = erracc;
657 			erracc += erradj;
658 			if (erracc <= erracctmp) {
659 				/* Accumulator turned over, advance y */
660       			yy0=y0p1;
661       			y0p1++;
662     		}
663 			xx0 += xdir;  /* x-major so always advance X */
664 
665 			/* the AAbits most significant bits of erracc give us the intensity
666 			weighting for this pixel, and the complement of the weighting for
667 			the paired pixel. */
668 			wgt = (erracc >> intshift) & 255;
669 
670 			a = Uint8(255-wgt);
671 			if(alpha != SDL_ALPHA_OPAQUE)
672 				a = Uint8(a*alpha_pp);
673 
674 			_PutPixelAlpha(dst,xx0,yy0,color,a);
675 
676 			a = Uint8(wgt);
677 			if(alpha != SDL_ALPHA_OPAQUE)
678 				a = Uint8(a*alpha_pp);
679 
680 			_PutPixelAlpha(dst,xx0,y0p1,color,a);
681 		}
682 	}
683 
684 	/* Draw final pixel, always exactly intersected by the line and doesn't
685 	need to be weighted. */
686 	if(alpha==SDL_ALPHA_OPAQUE)
687 		_PutPixel(dst,x2,y2, color);
688 	else
689 		_PutPixelAlpha(dst,x2,y2, color, alpha);
690 
691 }
692 
sge_AALineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)693 void sge_AALineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
694 {
695 	/* Lock surface */
696 	if ( SDL_MUSTLOCK(dst) && _sge_lock )
697 		if ( SDL_LockSurface(dst) < 0 )
698 			return;
699 
700 	_AALineAlpha(dst,x1,y1,x2,y2,color,alpha);
701 
702 	/* unlock the display */
703 	if (SDL_MUSTLOCK(dst) && _sge_lock) {
704 		SDL_UnlockSurface(dst);
705 	}
706 
707 	sge_UpdateRect(dst, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
708 }
709 
sge_AALineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 alpha)710 void sge_AALineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 alpha)
711 {
712 	sge_AALineAlpha(dst,x1,y1,x2,y2,SDL_MapRGB(dst->format, r, g, b),alpha);
713 }
714 
sge_AALine(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)715 void sge_AALine(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
716 {
717 	sge_AALineAlpha(dst, x1,y1, x2,y2, color, SDL_ALPHA_OPAQUE);
718 }
719 
sge_AALine(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b)720 void sge_AALine(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b)
721 {
722 	sge_AALineAlpha(dst,x1,y1,x2,y2,SDL_MapRGB(dst->format, r, g, b),SDL_ALPHA_OPAQUE);
723 }
724 
725 
726 
727 //==================================================================================
728 // Draws a multicolored line
729 //==================================================================================
sge_DomcLine(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))730 void sge_DomcLine(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
731 {
732 	Sint16 dx, dy, sdx, sdy, x, y, px, py;
733 
734 	dx = x2 - x1;
735 	dy = y2 - y1;
736 
737 	sdx = (dx < 0) ? -1 : 1;
738 	sdy = (dy < 0) ? -1 : 1;
739 
740 	dx = sdx * dx + 1;
741 	dy = sdy * dy + 1;
742 
743 	x = y = 0;
744 
745 	px = x1;
746 	py = y1;
747 
748 	/* We use fixedpoint math for the color fading */
749 	Sint32 R = r1<<16;
750 	Sint32 G = g1<<16;
751 	Sint32 B = b1<<16;
752 	Sint32 rstep;
753 	Sint32 gstep;
754 	Sint32 bstep;
755 
756 	if (dx >= dy){
757 		rstep = Sint32((r2-r1)<<16) / Sint32(dx);
758 		gstep = Sint32((g2-g1)<<16) / Sint32(dx);
759 		bstep = Sint32((b2-b1)<<16) / Sint32(dx);
760 
761 		for (x = 0; x < dx; x++){
762 			Callback(surface, px, py, SDL_MapRGB(surface->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)) );
763 
764 			y += dy;
765 			if (y >= dx){
766 				y -= dx;
767 				py += sdy;
768 			}
769 			px += sdx;
770 
771 			R += rstep;
772 			G += gstep;
773 			B += bstep;
774 		}
775 	}
776 	else{
777 		rstep = Sint32((r2-r1)<<16) / Sint32(dy);
778 		gstep = Sint32((g2-g1)<<16) / Sint32(dy);
779 		bstep = Sint32((b2-b1)<<16) / Sint32(dy);
780 
781 		for (y = 0; y < dy; y++){
782 			Callback(surface, px, py, SDL_MapRGB(surface->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)) );
783 
784 			x += dx;
785 			if (x >= dy){
786 				x -= dy;
787 				px += sdx;
788 			}
789 			py += sdy;
790 
791 			R += rstep;
792 			G += gstep;
793 			B += bstep;
794 		}
795 	}
796 }
797 
sge_mcLine(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2)798 void sge_mcLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2)
799 {
800 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
801 		if (SDL_LockSurface(Surface) < 0)
802 			return;
803 	}
804 
805 	/* Draw the line */
806 	sge_DomcLine(Surface, x1,y1, x2,y2, r1,g1,b1, r2,g2,b2, _PutPixel);
807 
808 	/* unlock the display */
809 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
810 		SDL_UnlockSurface(Surface);
811 	}
812 
813 	sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
814 }
815 
sge_mcLineAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2,Uint8 alpha)816 void sge_mcLineAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
817 {
818 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
819 		if (SDL_LockSurface(Surface) < 0)
820 			return;
821 
822 	_sge_alpha_hack = alpha;
823 
824 	/* Draw the line */
825 	sge_DomcLine(Surface, x1,y1, x2,y2, r1,g1,b1, r2,g2,b2, callback_alpha_hack);
826 
827 	/* unlock the display */
828 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
829 		SDL_UnlockSurface(Surface);
830 	}
831 
832 	sge_UpdateRect(Surface, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
833 }
834 
835 
836 //==================================================================================
837 // Draws a anti-aliased multicolored line
838 //==================================================================================
_AAmcLineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2,Uint8 alpha)839 void _AAmcLineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
840 {
841 	Uint32 erracc=0, erradj;
842 	Uint32 erracctmp, wgt;
843 	Sint16 tmp, y0p1, x0pxdir;
844 	Uint8 a;
845 
846 	/* Keep on working with 32bit numbers */
847 	Sint32 xx0=x1;
848 	Sint32 yy0=y1;
849 	Sint32 xx1=x2;
850 	Sint32 yy1=y2;
851 
852 	/* Reorder points if required */
853 	if (yy0 > yy1) {
854 		SWAP(yy0, yy1, tmp);
855 		SWAP(xx0, xx1, tmp);
856 
857 		SWAP(r1, r2, a);
858 		SWAP(g1, g2, a);
859 		SWAP(b1, b2, a);
860 	}
861 
862 	/* Calculate distance */
863 	Sint16 dx = xx1 - xx0;
864 	Sint16 dy = yy1 - yy0;
865 
866 	/* Adjust for negative dx and set xdir */
867 	Sint16 xdir=1;
868 	if (dx < 0) {
869 		xdir=-1;
870 		dx=(-dx);
871 	}
872 
873 	/* Check for special cases */
874 	if (dx==0 || dy==0  || dx==dy) {
875 		sge_mcLineAlpha(dst, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, alpha);
876 		return;
877 	}
878 
879 	/* We use fixedpoint math for the color fading */
880 	Sint32 R = r1<<16;
881 	Sint32 G = g1<<16;
882 	Sint32 B = b1<<16;
883 	Sint32 rstep;
884 	Sint32 gstep;
885 	Sint32 bstep;
886 
887 	float alpha_pp = float(alpha)/255;  /* Used to calculate alpha level if alpha != 255 */
888 	Uint32 intshift    = 32 - AAbits;   /* # of bits by which to shift erracc to get intensity level */
889 
890 	if(alpha==255)
891 		_PutPixel(dst,x1,y1, SDL_MapRGB(dst->format, r1, g1, b1) );  /* Draw the initial pixel in the foreground color */
892 	else
893 		_PutPixelAlpha(dst,x1,y1, SDL_MapRGB(dst->format, r1, g1, b1), alpha);
894 
895 	/* x-major or y-major? */
896 	if (dy > dx) {
897 
898 		/* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
899 		X advances every time Y advances 1 pixel, truncating the result so that
900 		we won't overrun the endpoint along the X axis */
901 		erradj = ((dx << 16) / dy)<<16;
902 
903 		rstep = Sint32((r2-r1)<<16) / Sint32(dy);
904 		gstep = Sint32((g2-g1)<<16) / Sint32(dy);
905 		bstep = Sint32((b2-b1)<<16) / Sint32(dy);
906 
907 		/* draw all pixels other than the first and last */
908 		x0pxdir=xx0+xdir;
909 		while (--dy) {
910 			R += rstep;
911 			G += gstep;
912 			B += bstep;
913 
914 			erracctmp = erracc;
915 			erracc += erradj;
916 			if (erracc <= erracctmp) {
917 				/* rollover in error accumulator, x coord advances */
918 				xx0=x0pxdir;
919 				x0pxdir += xdir;
920 			}
921 			yy0++;			/* y-major so always advance Y */
922 
923 			/* the AAbits most significant bits of erracc give us the intensity
924 			weighting for this pixel, and the complement of the weighting for
925 			the paired pixel. */
926 			wgt = (erracc >> intshift) & 255;
927 
928 			a = Uint8(255-wgt);
929 			if(alpha != 255)
930 				a = Uint8(a*alpha_pp);
931 
932 			_PutPixelAlpha(dst,xx0,yy0,SDL_MapRGB(dst->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)),a);
933 
934 			a = Uint8(wgt);
935 			if(alpha != 255)
936 				a = Uint8(a*alpha_pp);
937 
938 			_PutPixelAlpha(dst,x0pxdir,yy0,SDL_MapRGB(dst->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)),a);
939 		}
940 	} else {
941 
942 		/* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
943 		that Y advances each time X advances 1 pixel, truncating the result so
944 		that we won't overrun the endpoint along the X axis. */
945 		erradj = ((dy << 16) / dx)<<16;
946 
947  		rstep = Sint32((r2-r1)<<16) / Sint32(dx);
948 		gstep = Sint32((g2-g1)<<16) / Sint32(dx);
949 		bstep = Sint32((b2-b1)<<16) / Sint32(dx);
950 
951 		/* draw all pixels other than the first and last */
952 		y0p1=yy0+1;
953 		while (--dx) {
954 			R += rstep;
955 			G += gstep;
956 			B += bstep;
957 
958 			erracctmp = erracc;
959 			erracc += erradj;
960 			if (erracc <= erracctmp) {
961 				/* Accumulator turned over, advance y */
962       			yy0=y0p1;
963       			y0p1++;
964     		}
965 			xx0 += xdir;  /* x-major so always advance X */
966 
967 			/* the AAbits most significant bits of erracc give us the intensity
968 			weighting for this pixel, and the complement of the weighting for
969 			the paired pixel. */
970 			wgt = (erracc >> intshift) & 255;
971 
972 			a = Uint8(255-wgt);
973 			if(alpha != 255)
974 				a = Uint8(a*alpha_pp);
975 
976 			_PutPixelAlpha(dst,xx0,yy0,SDL_MapRGB(dst->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)),a);
977 
978 			a = Uint8(wgt);
979 			if(alpha != 255)
980 				a = Uint8(a*alpha_pp);
981 
982 			_PutPixelAlpha(dst,xx0,y0p1,SDL_MapRGB(dst->format, Uint8(R>>16), Uint8(G>>16), Uint8(B>>16)),a);
983 		}
984 	}
985 
986 	/* Draw final pixel, always exactly intersected by the line and doesn't
987 	need to be weighted. */
988 	if(alpha==255)
989 		_PutPixel(dst,x2,y2, SDL_MapRGB(dst->format,r2, g2, b2));
990 	else
991 		_PutPixelAlpha(dst,x2,y2, SDL_MapRGB(dst->format,r2, g2, b2), alpha);
992 
993 }
994 
sge_AAmcLineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2,Uint8 alpha)995 void sge_AAmcLineAlpha(SDL_Surface *dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2, Uint8 alpha)
996 {
997 	if ( SDL_MUSTLOCK(dst) && _sge_lock )
998 		if ( SDL_LockSurface(dst) < 0 )
999 			return;
1000 
1001 	_AAmcLineAlpha(dst, x1, y1, x2, y2, r1, g1, b1, r2, g2, b2, alpha);
1002 
1003 	if (SDL_MUSTLOCK(dst) && _sge_lock)
1004 		SDL_UnlockSurface(dst);
1005 
1006 	sge_UpdateRect(dst, (x1 < x2)? x1 : x2, (y1 < y2)? y1 : y2, ((x2-x1)<0)? (x1-x2+1) : (x2-x1+1), ((y2-y1)<0)? (y1-y2+1) : (y2-y1+1));
1007 }
1008 
sge_AAmcLine(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r1,Uint8 g1,Uint8 b1,Uint8 r2,Uint8 g2,Uint8 b2)1009 void sge_AAmcLine(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r1, Uint8 g1, Uint8 b1, Uint8 r2, Uint8 g2, Uint8 b2)
1010 {
1011 	sge_AAmcLineAlpha(Surface, x1,y1, x2,y2, r1,g1,b1, r2,g2,b2, SDL_ALPHA_OPAQUE);
1012 }
1013 
1014 
1015 
1016 /**********************************************************************************/
1017 /**                           Figure functions                                   **/
1018 /**********************************************************************************/
1019 
1020 //==================================================================================
1021 // Draws a rectangle
1022 //==================================================================================
sge_Rect(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1023 void sge_Rect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1024 {
1025 	_HLine(Surface,x1,x2,y1,color);
1026 	_HLine(Surface,x1,x2,y2,color);
1027 	_VLine(Surface,x1,y1,y2,color);
1028 	_VLine(Surface,x2,y1,y2,color);
1029 
1030 	sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
1031 	sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
1032 	sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
1033 	sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
1034 }
1035 
1036 //==================================================================================
1037 // Draws a rectangle (RGB)
1038 //==================================================================================
sge_Rect(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B)1039 void sge_Rect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1040 {
1041 	sge_Rect(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
1042 }
1043 
1044 
1045 //==================================================================================
1046 // Draws a rectangle (alpha)
1047 //==================================================================================
sge_RectAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)1048 void sge_RectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
1049 {
1050 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
1051 		if (SDL_LockSurface(Surface) < 0)
1052 			return;
1053 
1054 	_HLineAlpha(Surface,x1,x2,y1,color,alpha);
1055 	_HLineAlpha(Surface,x1,x2,y2,color,alpha);
1056 	_VLineAlpha(Surface,x1,y1,y2,color,alpha);
1057 	_VLineAlpha(Surface,x2,y1,y2,color,alpha);
1058 
1059 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
1060 		SDL_UnlockSurface(Surface);
1061 	}
1062 
1063 	sge_UpdateRect(Surface, x1, y1, x2-x1, 1);
1064 	sge_UpdateRect(Surface, x1, y2, x2-x1+1, 1); /* Hmm? */
1065 	sge_UpdateRect(Surface, x1, y1, 1, y2-y1);
1066 	sge_UpdateRect(Surface, x2, y1, 1, y2-y1);
1067 }
1068 
1069 //==================================================================================
1070 // Draws a rectangle (RGB)
1071 //==================================================================================
sge_RectAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)1072 void sge_RectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
1073 {
1074 	sge_RectAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
1075 }
1076 
1077 
1078 //==================================================================================
1079 // Draws a filled rectangle
1080 //==================================================================================
sge_FilledRect(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1081 void sge_FilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1082 {
1083 	Sint16 tmp;
1084 	if(x1>x2){
1085 		tmp=x1; x1=x2; x2=tmp;
1086 	}
1087 	if(y1>y2){
1088 		tmp=y1; y1=y2; y2=tmp;
1089 	}
1090 
1091 	#if SDL_VERSIONNUM(SDL_MAJOR_VERSION, SDL_MINOR_VERSION, SDL_PATCHLEVEL) < \
1092     SDL_VERSIONNUM(1, 1, 5)
1093 	if(x2<Surface->clip_minx || x1>Surface->clip_maxx || y2<Surface->clip_miny || y1>Surface->clip_maxy)
1094 		return;
1095 	if (x1 < Surface->clip_minx)
1096   		x1=Surface->clip_minx;
1097 	if (x2 > Surface->clip_maxx)
1098   		x2=Surface->clip_maxx;
1099 	if (y1 < Surface->clip_miny)
1100   		y1=Surface->clip_miny;
1101 	if (y2 > Surface->clip_maxy)
1102   		y2=Surface->clip_maxy;
1103 	#endif
1104 
1105 	SDL_Rect area;
1106 	area.x=x1; area.y=y1;
1107 	area.w=x2-x1+1; area.h=y2-y1+1;
1108 
1109 	SDL_FillRect(Surface,&area,color);
1110 
1111 	sge_UpdateRect(Surface, x1, y1, x2-x1+1, y2-y1+1);
1112 }
1113 
1114 //==================================================================================
1115 // Draws a filled rectangle (RGB)
1116 //==================================================================================
sge_FilledRect(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B)1117 void sge_FilledRect(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B)
1118 {
1119 	sge_FilledRect(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B));
1120 }
1121 
1122 
1123 //==================================================================================
1124 // Draws a filled rectangle (alpha)
1125 //==================================================================================
sge_FilledRectAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)1126 void sge_FilledRectAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
1127 {
1128 	/*if( alpha == 255 ){
1129 		sge_FilledRect(surface,x1,y1,x2,y2,color);
1130 		return;
1131 	}*/
1132 
1133 	/* Fix coords */
1134 	Sint16 tmp;
1135 	if(x1>x2){
1136 		tmp=x1; x1=x2; x2=tmp;
1137 	}
1138 	if(y1>y2){
1139 		tmp=y1; y1=y2; y2=tmp;
1140 	}
1141 
1142 	/* Clipping */
1143 	if(x2<sge_clip_xmin(surface) || x1>sge_clip_xmax(surface) || y2<sge_clip_ymin(surface) || y1>sge_clip_ymax(surface))
1144 		return;
1145 	if (x1 < sge_clip_xmin(surface))
1146   		x1 = sge_clip_xmin(surface);
1147 	if (x2 > sge_clip_xmax(surface))
1148   		x2 = sge_clip_xmax(surface);
1149 	if (y1 < sge_clip_ymin(surface))
1150   		y1 = sge_clip_ymin(surface);
1151 	if (y2 > sge_clip_ymax(surface))
1152   		y2 = sge_clip_ymax(surface);
1153 
1154 	Uint32 Rmask = surface->format->Rmask, Gmask = surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
1155 	Uint32 R,G,B,A=0;
1156 	Sint16 x,y;
1157 
1158 	if (SDL_MUSTLOCK(surface) && _sge_lock)
1159 		if (SDL_LockSurface(surface) < 0)
1160 			return;
1161 
1162 	switch (surface->format->BytesPerPixel) {
1163 		case 1: { /* Assuming 8-bpp */
1164 			Uint8 *row, *pixel;
1165 			Uint8 dR, dG, dB;
1166 
1167 			Uint8 sR = surface->format->palette->colors[color].r;
1168 			Uint8 sG = surface->format->palette->colors[color].g;
1169 			Uint8 sB = surface->format->palette->colors[color].b;
1170 
1171 			for(y = y1; y<=y2; y++){
1172 				row = (Uint8 *)surface->pixels + y*surface->pitch;
1173 				for(x = x1; x <= x2; x++){
1174 					pixel = row + x;
1175 
1176 					dR = surface->format->palette->colors[*pixel].r;
1177 					dG = surface->format->palette->colors[*pixel].g;
1178 					dB = surface->format->palette->colors[*pixel].b;
1179 
1180 					dR = dR + ((sR-dR)*alpha >> 8);
1181 					dG = dG + ((sG-dG)*alpha >> 8);
1182 					dB = dB + ((sB-dB)*alpha >> 8);
1183 
1184 					*pixel = SDL_MapRGB(surface->format, dR, dG, dB);
1185 				}
1186 			}
1187 		}
1188 		break;
1189 
1190 		case 2: { /* Probably 15-bpp or 16-bpp */
1191 			Uint16 *row, *pixel;
1192 			Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
1193 
1194 			for(y = y1; y<=y2; y++){
1195 				row = (Uint16 *)surface->pixels + y*surface->pitch/2;
1196 				for(x = x1; x <= x2; x++){
1197 					pixel = row + x;
1198 
1199 					R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
1200 					G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
1201 					B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
1202 					if( Amask )
1203 						A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
1204 
1205 					*pixel= R | G | B | A;
1206 				}
1207 			}
1208 		}
1209 		break;
1210 
1211 		case 3: { /* Slow 24-bpp mode, usually not used */
1212 			Uint8 *row,*pix;
1213 			Uint8 dR, dG, dB, dA;
1214   			Uint8 rshift8=surface->format->Rshift/8;
1215 			Uint8 gshift8=surface->format->Gshift/8;
1216 			Uint8 bshift8=surface->format->Bshift/8;
1217 			Uint8 ashift8=surface->format->Ashift/8;
1218 
1219 			Uint8 sR = (color>>surface->format->Rshift)&0xff;
1220 			Uint8 sG = (color>>surface->format->Gshift)&0xff;
1221 			Uint8 sB = (color>>surface->format->Bshift)&0xff;
1222 			Uint8 sA = (color>>surface->format->Ashift)&0xff;
1223 
1224 			for(y = y1; y<=y2; y++){
1225 				row = (Uint8 *)surface->pixels + y * surface->pitch;
1226 				for(x = x1; x <= x2; x++){
1227 					pix = row + x*3;
1228 
1229 					dR = *((pix)+rshift8);
1230             		dG = *((pix)+gshift8);
1231             		dB = *((pix)+bshift8);
1232 					dA = *((pix)+ashift8);
1233 
1234 					dR = dR + ((sR-dR)*alpha >> 8);
1235 					dG = dG + ((sG-dG)*alpha >> 8);
1236 					dB = dB + ((sB-dB)*alpha >> 8);
1237 					dA = dA + ((sA-dA)*alpha >> 8);
1238 
1239 					*((pix)+rshift8) = dR;
1240             		*((pix)+gshift8) = dG;
1241             		*((pix)+bshift8) = dB;
1242 					*((pix)+ashift8) = dA;
1243 				}
1244 			}
1245 
1246 		}
1247 		break;
1248 
1249 		case 4: { /* Probably 32-bpp */
1250 			Uint32 *row, *pixel;
1251 			Uint32 dR=(color & Rmask),dG=(color & Gmask),dB=(color & Bmask),dA=(color & Amask);
1252 
1253 			for(y = y1; y<=y2; y++){
1254 				row = (Uint32 *)surface->pixels + y*surface->pitch/4;
1255 				for(x = x1; x <= x2; x++){
1256 					pixel = row + x;
1257 
1258 					R = ((*pixel & Rmask) + (( dR - (*pixel & Rmask) ) * alpha >> 8)) & Rmask;
1259 					G = ((*pixel & Gmask) + (( dG - (*pixel & Gmask) ) * alpha >> 8)) & Gmask;
1260 					B = ((*pixel & Bmask) + (( dB - (*pixel & Bmask) ) * alpha >> 8)) & Bmask;
1261 					if( Amask )
1262 						A = ((*pixel & Amask) + (( dA - (*pixel & Amask) ) * alpha >> 8)) & Amask;
1263 
1264 					*pixel= R | G | B | A;
1265 				}
1266 			}
1267 		}
1268 		break;
1269 	}
1270 
1271 	if (SDL_MUSTLOCK(surface) && _sge_lock) {
1272 		SDL_UnlockSurface(surface);
1273 	}
1274 
1275 	sge_UpdateRect(surface, x1, y1, x2-x1+1, y2-y1+1);
1276 }
1277 
sge_FilledRectAlpha(SDL_Surface * Surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)1278 void sge_FilledRectAlpha(SDL_Surface *Surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
1279 {
1280 	sge_FilledRectAlpha(Surface,x1,y1,x2,y2, SDL_MapRGB(Surface->format, R, G, B), alpha);
1281 }
1282 
1283 
1284 //==================================================================================
1285 // Performs Callback at each ellipse point.
1286 // (from Allegro)
1287 //==================================================================================
sge_DoEllipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))1288 void sge_DoEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color) )
1289 {
1290 	int ix, iy;
1291 	int h, i, j, k;
1292 	int oh, oi, oj, ok;
1293 
1294 	if (rx < 1)
1295 		rx = 1;
1296 
1297 	if (ry < 1)
1298 		ry = 1;
1299 
1300 	h = i = j = k = 0xFFFF;
1301 
1302 	if (rx > ry) {
1303 		ix = 0;
1304 		iy = rx * 64;
1305 
1306  		do {
1307 			oh = h;
1308 	 		oi = i;
1309 	 		oj = j;
1310 			ok = k;
1311 
1312 	 		h = (ix + 32) >> 6;
1313 	 		i = (iy + 32) >> 6;
1314 	 		j = (h * ry) / rx;
1315 	 		k = (i * ry) / rx;
1316 
1317 	 		if (((h != oh) || (k != ok)) && (h < oi)) {
1318 				Callback(Surface, x+h, y+k, color);
1319 	   			if (h)
1320 	    			Callback(Surface, x-h, y+k, color);
1321 	   			if (k) {
1322 	    			Callback(Surface, x+h, y-k, color);
1323 	     			if (h)
1324 		  				Callback(Surface, x-h, y-k, color);
1325 	  			}
1326 			}
1327 
1328 	 		if (((i != oi) || (j != oj)) && (h < i)) {
1329 				Callback(Surface, x+i, y+j, color);
1330 	  			if (i)
1331 	    			Callback(Surface, x-i, y+j, color);
1332 	  			if (j) {
1333 	   				Callback(Surface, x+i, y-j, color);
1334 	   				if (i)
1335 		  				Callback(Surface, x-i, y-j, color);
1336 	 			}
1337 	 		}
1338 
1339 			ix = ix + iy / rx;
1340 	 		iy = iy - ix / rx;
1341 
1342 		} while (i > h);
1343 	}
1344 	else {
1345 		ix = 0;
1346 		iy = ry * 64;
1347 
1348   		do {
1349 	 		oh = h;
1350 	 		oi = i;
1351 	 		oj = j;
1352 	 		ok = k;
1353 
1354 	 		h = (ix + 32) >> 6;
1355 	 		i = (iy + 32) >> 6;
1356 	 		j = (h * rx) / ry;
1357 	 		k = (i * rx) / ry;
1358 
1359 	 		if (((j != oj) || (i != oi)) && (h < i)) {
1360 	    		Callback(Surface, x+j, y+i, color);
1361 	    		if (j)
1362 	      			Callback(Surface, x-j, y+i, color);
1363 	    		if (i) {
1364 	       			Callback(Surface, x+j, y-i, color);
1365 	       			if (j)
1366 		  				Callback(Surface, x-j, y-i, color);
1367 	    		}
1368 	 		}
1369 
1370 	 		if (((k != ok) || (h != oh)) && (h < oi)) {
1371 	    		Callback(Surface, x+k, y+h, color);
1372 	   			if (k)
1373 	     			Callback(Surface, x-k, y+h, color);
1374 	    		if (h) {
1375 	      			Callback(Surface, x+k, y-h, color);
1376 	    			if (k)
1377 		  				Callback(Surface, x-k, y-h, color);
1378 	    		}
1379 	 		}
1380 
1381 	 		ix = ix + iy / ry;
1382 	 		iy = iy - ix / ry;
1383 
1384   		} while(i > h);
1385 	}
1386 }
1387 
1388 
1389 //==================================================================================
1390 // Performs Callback at each ellipse point. (RGB)
1391 //==================================================================================
sge_DoEllipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))1392 void sge_DoEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color) )
1393 {
1394 	sge_DoEllipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),Callback);
1395 }
1396 
1397 
1398 //==================================================================================
1399 // Draws an ellipse
1400 //==================================================================================
sge_Ellipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)1401 void sge_Ellipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1402 {
1403 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
1404       if (SDL_LockSurface(Surface) < 0)
1405          return;
1406    }
1407 
1408    sge_DoEllipse(Surface, x, y, rx, ry, color, _PutPixel);
1409 
1410    if (SDL_MUSTLOCK(Surface) && _sge_lock) {
1411       SDL_UnlockSurface(Surface);
1412    }
1413 
1414 	sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
1415 
1416 }
1417 
1418 
1419 //==================================================================================
1420 // Draws an ellipse (RGB)
1421 //==================================================================================
sge_Ellipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B)1422 void sge_Ellipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
1423 {
1424 	sge_Ellipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B));
1425 }
1426 
1427 
1428 //==================================================================================
1429 // Draws an ellipse (alpha)
1430 //==================================================================================
sge_EllipseAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color,Uint8 alpha)1431 void sge_EllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
1432 {
1433 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
1434 		if (SDL_LockSurface(Surface) < 0)
1435 			return;
1436 
1437 	_sge_alpha_hack = alpha;
1438 	sge_DoEllipse(Surface, x, y, rx, ry, color, callback_alpha_hack);
1439 
1440 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
1441 		SDL_UnlockSurface(Surface);
1442 	}
1443 
1444 	sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
1445 }
1446 
1447 
1448 //==================================================================================
1449 // Draws an ellipse (alpha - RGB)
1450 //==================================================================================
sge_EllipseAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)1451 void sge_EllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
1452 {
1453 	sge_EllipseAlpha(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),alpha);
1454 }
1455 
1456 
1457 //==================================================================================
1458 // Draws a filled ellipse
1459 //==================================================================================
sge_FilledEllipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)1460 void sge_FilledEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1461 {
1462 	int ix, iy;
1463 	int h, i, j, k;
1464 	int oh, oi, oj, ok;
1465 
1466 	if (rx < 1)
1467 		rx = 1;
1468 
1469 	if (ry < 1)
1470 		ry = 1;
1471 
1472 	oh = oi = oj = ok = 0xFFFF;
1473 
1474 	if (rx > ry) {
1475   		ix = 0;
1476    		iy = rx * 64;
1477 
1478  		do {
1479 	 		h = (ix + 32) >> 6;
1480 	 		i = (iy + 32) >> 6;
1481 	 		j = (h * ry) / rx;
1482 	 		k = (i * ry) / rx;
1483 
1484 	 		if ((k!=ok) && (k!=oj)) {
1485 	   			if (k){
1486 	   		  		_HLine(Surface,x-h,x+h,y-k,color);
1487 					_HLine(Surface,x-h,x+h,y+k,color);
1488 				}else
1489 					_HLine(Surface,x-h,x+h,y,color);
1490 				ok=k;
1491 			}
1492 
1493 	 		if ((j!=oj) && (j!=ok) && (k!=j))  {
1494 	  			if (j){
1495 	  		 		_HLine(Surface,x-i,x+i,y-j,color);
1496 					_HLine(Surface,x-i,x+i,y+j,color);
1497 				}else
1498 					_HLine(Surface,x-i,x+i,y,color);
1499 				oj=j;
1500 	 		}
1501 
1502 			ix = ix + iy / rx;
1503 	 		iy = iy - ix / rx;
1504 
1505 		} while (i > h);
1506 	}
1507 	else {
1508 		ix = 0;
1509 		iy = ry * 64;
1510 
1511 		do {
1512 	 		h = (ix + 32) >> 6;
1513 	 		i = (iy + 32) >> 6;
1514 	 		j = (h * rx) / ry;
1515 	 		k = (i * rx) / ry;
1516 
1517 	 		if ((i!=oi) && (i!=oh)) {
1518 	    		if (i){
1519 	    			_HLine(Surface,x-j,x+j,y-i,color);
1520 					_HLine(Surface,x-j,x+j,y+i,color);
1521 				}else
1522 					_HLine(Surface,x-j,x+j,y,color);
1523 				oi=i;
1524 	 		}
1525 
1526 	 		if ((h!=oh) && (h!=oi) && (i!=h)) {
1527 	    		if (h){
1528 	    			_HLine(Surface,x-k,x+k,y-h,color);
1529 					_HLine(Surface,x-k,x+k,y+h,color);
1530 				}else
1531 					_HLine(Surface,x-k,x+k,y,color);
1532 				oh=h;
1533 	 		}
1534 
1535 	 		ix = ix + iy / ry;
1536 	 		iy = iy - ix / ry;
1537 
1538   		} while(i > h);
1539 	}
1540 
1541 	sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
1542 }
1543 
1544 
1545 //==================================================================================
1546 // Draws a filled ellipse (RGB)
1547 //==================================================================================
sge_FilledEllipse(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B)1548 void sge_FilledEllipse(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
1549 {
1550 	sge_FilledEllipse(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B));
1551 }
1552 
1553 
1554 
1555 //==================================================================================
1556 // Draws a filled ellipse (alpha)
1557 //==================================================================================
sge_FilledEllipseAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color,Uint8 alpha)1558 void sge_FilledEllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
1559 {
1560 	int ix, iy;
1561 	int h, i, j, k;
1562 	int oh, oi, oj, ok;
1563 
1564 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
1565 		if (SDL_LockSurface(Surface) < 0)
1566 			return;
1567 
1568 	if (rx < 1)
1569 		rx = 1;
1570 
1571 	if (ry < 1)
1572 		ry = 1;
1573 
1574 	oh = oi = oj = ok = 0xFFFF;
1575 
1576 	if (rx > ry) {
1577   		ix = 0;
1578    		iy = rx * 64;
1579 
1580  		do {
1581 	 		h = (ix + 32) >> 6;
1582 	 		i = (iy + 32) >> 6;
1583 	 		j = (h * ry) / rx;
1584 	 		k = (i * ry) / rx;
1585 
1586 	 		if ((k!=ok) && (k!=oj)) {
1587 	   			if (k){
1588 	   		  		_HLineAlpha(Surface,x-h,x+h,y-k,color,alpha);
1589 					_HLineAlpha(Surface,x-h,x+h,y+k,color,alpha);
1590 				}else
1591 					_HLineAlpha(Surface,x-h,x+h,y,color,alpha);
1592 				ok=k;
1593 			}
1594 
1595 	 		if ((j!=oj) && (j!=ok) && (k!=j))  {
1596 	  			if (j){
1597 	  		 		_HLineAlpha(Surface,x-i,x+i,y-j,color,alpha);
1598 					_HLineAlpha(Surface,x-i,x+i,y+j,color,alpha);
1599 				}else
1600 					_HLineAlpha(Surface,x-i,x+i,y,color,alpha);
1601 				oj=j;
1602 	 		}
1603 
1604 			ix = ix + iy / rx;
1605 	 		iy = iy - ix / rx;
1606 
1607 		} while (i > h);
1608 	}
1609 	else {
1610 		ix = 0;
1611 		iy = ry * 64;
1612 
1613 		do {
1614 	 		h = (ix + 32) >> 6;
1615 	 		i = (iy + 32) >> 6;
1616 	 		j = (h * rx) / ry;
1617 	 		k = (i * rx) / ry;
1618 
1619 	 		if ((i!=oi) && (i!=oh)) {
1620 	    		if (i){
1621 	    			_HLineAlpha(Surface,x-j,x+j,y-i,color,alpha);
1622 					_HLineAlpha(Surface,x-j,x+j,y+i,color,alpha);
1623 				}else
1624 					_HLineAlpha(Surface,x-j,x+j,y,color,alpha);
1625 				oi=i;
1626 	 		}
1627 
1628 	 		if ((h!=oh) && (h!=oi) && (i!=h)) {
1629 	    		if (h){
1630 	    			_HLineAlpha(Surface,x-k,x+k,y-h,color,alpha);
1631 					_HLineAlpha(Surface,x-k,x+k,y+h,color,alpha);
1632 				}else
1633 					_HLineAlpha(Surface,x-k,x+k,y,color,alpha);
1634 				oh=h;
1635 	 		}
1636 
1637 	 		ix = ix + iy / ry;
1638 	 		iy = iy - ix / ry;
1639 
1640   		} while(i > h);
1641 	}
1642 
1643 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
1644 		SDL_UnlockSurface(Surface);
1645 	}
1646 
1647 	sge_UpdateRect(Surface, x-rx, y-ry, 2*rx+1, 2*ry+1);
1648 }
1649 
1650 
1651 //==================================================================================
1652 // Draws a filled ellipse (alpha - RGB)
1653 //==================================================================================
sge_FilledEllipseAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)1654 void sge_FilledEllipseAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
1655 {
1656 	sge_FilledEllipseAlpha(Surface,x,y,rx,ry,SDL_MapRGB(Surface->format, R, G, B),alpha);
1657 }
1658 
1659 
1660 //==================================================================================
1661 // Draws an anti-aliased ellipse (alpha)
1662 // Some of this code is taken from "TwinLib" (http://www.twinlib.org) written by
1663 // Nicolas Roard (nicolas@roard.com)
1664 //==================================================================================
sge_AAEllipseAlpha(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint32 color,Uint8 alpha)1665 void sge_AAEllipseAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color, Uint8 alpha)
1666 {
1667 	/* Sanity check */
1668 	if (rx < 1)
1669 		rx = 1;
1670 	if (ry < 1)
1671 		ry = 1;
1672 
1673 	int a2 = rx * rx;
1674 	int b2 = ry * ry;
1675 
1676 	int ds = 2 * a2;
1677 	int dt = 2 * b2;
1678 
1679 	int dxt = int (a2 / sqrt(a2 + b2));
1680 
1681 	int t = 0;
1682 	int s = -2 * a2 * ry;
1683 	int d = 0;
1684 
1685 	Sint16 x = xc;
1686 	Sint16 y = yc - ry;
1687 
1688 	Sint16 xs, ys, dyt;
1689 	float cp, is, ip, imax = 1.0;
1690 
1691 	Uint8 s_alpha, p_alpha;
1692 	float alpha_pp = float(alpha)/255;
1693 
1694 	/* Lock surface */
1695 	if ( SDL_MUSTLOCK(surface) && _sge_lock )
1696 		if ( SDL_LockSurface(surface) < 0 )
1697 			return;
1698 
1699 	/* "End points" */
1700 	_PutPixelAlpha(surface, x, y, color, alpha);
1701 	_PutPixelAlpha(surface, 2*xc-x, y, color, alpha);
1702 
1703 	_PutPixelAlpha(surface, x, 2*yc-y, color, alpha);
1704 	_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, alpha);
1705 
1706 	int i;
1707 
1708 	for (i = 1; i <= dxt; i++)
1709 	{
1710 		x--;
1711 		d += t - b2;
1712 
1713 		if (d >= 0)
1714 			ys = y - 1;
1715 		else if ((d - s - a2) > 0)
1716 		{
1717 			if ((2 * d - s - a2) >= 0)
1718 				ys = y + 1;
1719 			else
1720 			{
1721 				ys = y;
1722 				y++;
1723 				d -= s + a2;
1724 				s += ds;
1725 			}
1726 		}
1727 		else
1728 		{
1729 			y++;
1730 			ys = y + 1;
1731 			d -= s + a2;
1732 			s += ds;
1733 		}
1734 
1735 		t -= dt;
1736 
1737 		/* Calculate alpha */
1738 		cp = float(abs(d)) / abs(s);
1739 		is = float( cp * imax + 0.1 );
1740 		ip = float( imax - is + 0.2 );
1741 
1742 		/* Overflow check */
1743 		if( is > 1.0 )
1744 			is = 1.0;
1745 		if( ip > 1.0 )
1746 			ip = 1.0;
1747 
1748 		/* Calculate alpha level */
1749 		s_alpha = Uint8(is*255);
1750 		p_alpha = Uint8(ip*255);
1751 		if( alpha != 255 ){
1752 			s_alpha = Uint8(s_alpha*alpha_pp);
1753 			p_alpha = Uint8(p_alpha*alpha_pp);
1754 		}
1755 
1756 
1757 		/* Upper half */
1758 		_PutPixelAlpha(surface, x, y, color, p_alpha);
1759 		_PutPixelAlpha(surface, 2*xc-x, y, color, p_alpha);
1760 
1761 		_PutPixelAlpha(surface, x, ys, color, s_alpha);
1762 		_PutPixelAlpha(surface, 2*xc-x, ys, color, s_alpha);
1763 
1764 
1765 		/* Lower half */
1766 		_PutPixelAlpha(surface, x, 2*yc-y, color, p_alpha);
1767 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, p_alpha);
1768 
1769 		_PutPixelAlpha(surface, x, 2*yc-ys, color, s_alpha);
1770 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-ys, color, s_alpha);
1771 	}
1772 
1773 	dyt = abs(y - yc);
1774 
1775 	for (i = 1; i <= dyt; i++)
1776 	{
1777 		y++;
1778 		d -= s + a2;
1779 
1780 		if (d <= 0)
1781 			xs = x + 1;
1782 		else if ((d + t - b2) < 0)
1783 		{
1784 			if ((2 * d + t - b2) <= 0)
1785 				xs = x - 1;
1786 			else
1787 			{
1788 				xs = x;
1789 				x--;
1790 				d += t - b2;
1791 				t -= dt;
1792 			}
1793 		}
1794 		else
1795 		{
1796 			x--;
1797 			xs = x - 1;
1798 			d += t - b2;
1799 			t -= dt;
1800 		}
1801 
1802 		s += ds;
1803 
1804 		/* Calculate alpha */
1805 		cp = float(abs(d)) / abs(t);
1806 		is = float( cp * imax + 0.1 );
1807 		ip = float( imax - is + 0.2 );
1808 
1809 		/* Overflow check */
1810 		if( is > 1.0 )
1811 			is = 1.0;
1812 		if( ip > 1.0 )
1813 			ip = 1.0;
1814 
1815 		/* Calculate alpha level */
1816 		s_alpha = Uint8(is*255);
1817 		p_alpha = Uint8(ip*255);
1818 		if( alpha != 255 ){
1819 			s_alpha = Uint8(s_alpha*alpha_pp);
1820 			p_alpha = Uint8(p_alpha*alpha_pp);
1821 		}
1822 
1823 
1824 		/* Upper half */
1825 		_PutPixelAlpha(surface, x, y, color, p_alpha);
1826 		_PutPixelAlpha(surface, 2*xc-x, y, color, p_alpha);
1827 
1828 		_PutPixelAlpha(surface, xs, y, color, s_alpha);
1829 		_PutPixelAlpha(surface, 2*xc-xs, y, color, s_alpha);
1830 
1831 
1832 		/* Lower half*/
1833 		_PutPixelAlpha(surface, x, 2*yc-y, color, p_alpha);
1834 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, p_alpha);
1835 
1836 		_PutPixelAlpha(surface, xs, 2*yc-y, color, s_alpha);
1837 		_PutPixelAlpha(surface, 2*xc-xs, 2*yc-y, color, s_alpha);
1838 	}
1839 
1840 	/* unlock surface */
1841 	if (SDL_MUSTLOCK(surface) && _sge_lock) {
1842 		SDL_UnlockSurface(surface);
1843 	}
1844 
1845 	/* Update surface if needed */
1846 	sge_UpdateRect(surface, xc-rx, yc-ry, 2*rx+1, 2*ry+1);
1847 }
1848 
1849 
1850 //==================================================================================
1851 // Draws an anti-aliased ellipse (alpha - RGB)
1852 //==================================================================================
sge_AAEllipseAlpha(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)1853 void sge_AAEllipseAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
1854 {
1855 	sge_AAEllipseAlpha(surface,xc,yc,rx,ry,SDL_MapRGB(surface->format, R, G, B),alpha);
1856 }
1857 
1858 
1859 //==================================================================================
1860 // Draws an anti-aliased ellipse
1861 //==================================================================================
sge_AAEllipse(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint32 color)1862 void sge_AAEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
1863 {
1864 	sge_AAEllipseAlpha(surface,xc,yc,rx,ry,color,255);
1865 }
1866 
1867 //==================================================================================
1868 // Draws an anti-aliased ellipse (RGB)
1869 //==================================================================================
sge_AAEllipse(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B)1870 void sge_AAEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
1871 {
1872 	sge_AAEllipseAlpha(surface,xc,yc,rx,ry,SDL_MapRGB(surface->format, R, G, B),255);
1873 }
1874 
1875 
1876 //==================================================================================
1877 // Draws a filled anti-aliased ellipse
1878 // This is just a quick hack...
1879 //==================================================================================
sge_AAFilledEllipse(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint32 color)1880 void sge_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
1881 {
1882 	/* Sanity check */
1883 	if (rx < 1)
1884 		rx = 1;
1885 	if (ry < 1)
1886 		ry = 1;
1887 
1888 	int a2 = rx * rx;
1889 	int b2 = ry * ry;
1890 
1891 	int ds = 2 * a2;
1892 	int dt = 2 * b2;
1893 
1894 	int dxt = int (a2 / sqrt(a2 + b2));
1895 
1896 	int t = 0;
1897 	int s = -2 * a2 * ry;
1898 	int d = 0;
1899 
1900 	Sint16 x = xc;
1901 	Sint16 y = yc - ry;
1902 
1903 	Sint16 xs, ys, dyt;
1904 	float cp, is, ip, imax = 1.0;
1905 
1906 
1907 	/* Lock surface */
1908 	if ( SDL_MUSTLOCK(surface) && _sge_lock )
1909 		if ( SDL_LockSurface(surface) < 0 )
1910 			return;
1911 
1912 	/* "End points" */
1913 	_PutPixel(surface, x, y, color);
1914 	_PutPixel(surface, 2*xc-x, y, color);
1915 
1916 	_PutPixel(surface, x, 2*yc-y, color);
1917 	_PutPixel(surface, 2*xc-x, 2*yc-y, color);
1918 
1919 	/* unlock surface */
1920 	if (SDL_MUSTLOCK(surface) && _sge_lock)
1921 		SDL_UnlockSurface(surface);
1922 
1923 	_VLine(surface, x, y+1, 2*yc-y-1, color);
1924 
1925 	int i;
1926 
1927 	for (i = 1; i <= dxt; i++)
1928 	{
1929 		x--;
1930 		d += t - b2;
1931 
1932 		if (d >= 0)
1933 			ys = y - 1;
1934 		else if ((d - s - a2) > 0)
1935 		{
1936 			if ((2 * d - s - a2) >= 0)
1937 				ys = y + 1;
1938 			else
1939 			{
1940 				ys = y;
1941 				y++;
1942 				d -= s + a2;
1943 				s += ds;
1944 			}
1945 		}
1946 		else
1947 		{
1948 			y++;
1949 			ys = y + 1;
1950 			d -= s + a2;
1951 			s += ds;
1952 		}
1953 
1954 		t -= dt;
1955 
1956 		/* Calculate alpha */
1957 		cp = (float) abs(d) / abs(s);
1958 		is = cp * imax;
1959 		ip = imax - is;
1960 
1961 
1962 		/* Lock surface */
1963 		if ( SDL_MUSTLOCK(surface) && _sge_lock )
1964 			if ( SDL_LockSurface(surface) < 0 )
1965 				return;
1966 
1967 		/* Upper half */
1968 		_PutPixelAlpha(surface, x, y, color, Uint8(ip*255));
1969 		_PutPixelAlpha(surface, 2*xc-x, y, color, Uint8(ip*255));
1970 
1971 		_PutPixelAlpha(surface, x, ys, color, Uint8(is*255));
1972 		_PutPixelAlpha(surface, 2*xc-x, ys, color, Uint8(is*255));
1973 
1974 
1975 		/* Lower half */
1976 		_PutPixelAlpha(surface, x, 2*yc-y, color, Uint8(ip*255));
1977 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, Uint8(ip*255));
1978 
1979 		_PutPixelAlpha(surface, x, 2*yc-ys, color, Uint8(is*255));
1980 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-ys, color, Uint8(is*255));
1981 
1982 		/* unlock surface */
1983 		if (SDL_MUSTLOCK(surface) && _sge_lock)
1984 			SDL_UnlockSurface(surface);
1985 
1986 
1987 		/* Fill */
1988 		_VLine(surface, x, y+1, 2*yc-y-1, color);
1989 		_VLine(surface, 2*xc-x, y+1, 2*yc-y-1, color);
1990 		_VLine(surface, x, ys+1, 2*yc-ys-1, color);
1991 		_VLine(surface, 2*xc-x, ys+1, 2*yc-ys-1, color);
1992 	}
1993 
1994 	dyt = abs(y - yc);
1995 
1996 	for (i = 1; i <= dyt; i++)
1997 	{
1998 		y++;
1999 		d -= s + a2;
2000 
2001 		if (d <= 0)
2002 			xs = x + 1;
2003 		else if ((d + t - b2) < 0)
2004 		{
2005 			if ((2 * d + t - b2) <= 0)
2006 				xs = x - 1;
2007 			else
2008 			{
2009 				xs = x;
2010 				x--;
2011 				d += t - b2;
2012 				t -= dt;
2013 			}
2014 		}
2015 		else
2016 		{
2017 			x--;
2018 			xs = x - 1;
2019 			d += t - b2;
2020 			t -= dt;
2021 		}
2022 
2023 		s += ds;
2024 
2025 		/* Calculate alpha */
2026 		cp = (float) abs(d) / abs(t);
2027 		is = cp * imax;
2028 		ip = imax - is;
2029 
2030 
2031 		/* Lock surface */
2032 		if ( SDL_MUSTLOCK(surface) && _sge_lock )
2033 			if ( SDL_LockSurface(surface) < 0 )
2034 				return;
2035 
2036 		/* Upper half */
2037 		_PutPixelAlpha(surface, x, y, color, Uint8(ip*255));
2038 		_PutPixelAlpha(surface, 2*xc-x, y, color, Uint8(ip*255));
2039 
2040 		_PutPixelAlpha(surface, xs, y, color, Uint8(is*255));
2041 		_PutPixelAlpha(surface, 2*xc-xs, y, color, Uint8(is*255));
2042 
2043 
2044 		/* Lower half*/
2045 		_PutPixelAlpha(surface, x, 2*yc-y, color, Uint8(ip*255));
2046 		_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, Uint8(ip*255));
2047 
2048 		_PutPixelAlpha(surface, xs, 2*yc-y, color, Uint8(is*255));
2049 		_PutPixelAlpha(surface, 2*xc-xs, 2*yc-y, color, Uint8(is*255));
2050 
2051 		/* unlock surface */
2052 		if (SDL_MUSTLOCK(surface) && _sge_lock)
2053 			SDL_UnlockSurface(surface);
2054 
2055 		/* Fill */
2056 		_HLine(surface, x+1, 2*xc-x-1, y, color);
2057 		_HLine(surface, xs+1, 2*xc-xs-1, y, color);
2058 		_HLine(surface, x+1, 2*xc-x-1, 2*yc-y, color);
2059 		_HLine(surface, xs+1, 2*xc-xs-1, 2*yc-y, color);
2060 	}
2061 
2062 	/* Update surface if needed */
2063 	sge_UpdateRect(surface, xc-rx, yc-ry, 2*rx+1, 2*ry+1);
2064 }
2065 
2066 
2067 //==================================================================================
2068 // Draws a filled anti-aliased ellipse (RGB)
2069 //==================================================================================
sge_AAFilledEllipse(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint8 R,Uint8 G,Uint8 B)2070 void sge_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint8 R, Uint8 G, Uint8 B)
2071 {
2072 	sge_AAFilledEllipse(surface,xc,yc,rx,ry,SDL_MapRGB(surface->format, R, G, B));
2073 }
2074 
2075 
2076 
2077 
2078 
2079 //==================================================================================
2080 // Performs Callback at each circle point.
2081 //==================================================================================
sge_DoCircle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint32 color,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))2082 void sge_DoCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
2083 {
2084 	Sint16 cx = 0;
2085  	Sint16 cy = r;
2086  	Sint16 df = 1 - r;
2087  	Sint16 d_e = 3;
2088  	Sint16 d_se = -2 * r + 5;
2089 
2090 	do {
2091 		Callback(Surface, x+cx, y+cy, color);
2092 		Callback(Surface, x-cx, y+cy, color);
2093 		Callback(Surface, x+cx, y-cy, color);
2094 		Callback(Surface, x-cx, y-cy, color);
2095 		Callback(Surface, x+cy, y+cx, color);
2096 		Callback(Surface, x+cy, y-cx, color);
2097 		Callback(Surface, x-cy, y+cx, color);
2098 		Callback(Surface, x-cy, y-cx, color);
2099 
2100 		if (df < 0)  {
2101 			df += d_e;
2102 			d_e += 2;
2103 			d_se += 2;
2104 		}
2105 		else {
2106 			df += d_se;
2107 			d_e += 2;
2108 			d_se += 4;
2109 			cy--;
2110 		}
2111 
2112 		cx++;
2113 
2114 	}while(cx <= cy);
2115 
2116 }
2117 
2118 
2119 //==================================================================================
2120 // Performs Callback at each circle point. (RGB)
2121 //==================================================================================
sge_DoCircle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint8 R,Uint8 G,Uint8 B,void Callback (SDL_Surface * Surf,Sint16 X,Sint16 Y,Uint32 Color))2122 void sge_DoCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, void Callback(SDL_Surface *Surf, Sint16 X, Sint16 Y, Uint32 Color))
2123 {
2124 	sge_DoCircle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),Callback);
2125 }
2126 
2127 
2128 //==================================================================================
2129 // Draws a circle
2130 //==================================================================================
sge_Circle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2131 void sge_Circle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2132 {
2133 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
2134       if (SDL_LockSurface(Surface) < 0)
2135          return;
2136    }
2137 
2138    sge_DoCircle(Surface, x, y, r, color, _PutPixel);
2139 
2140    if (SDL_MUSTLOCK(Surface) && _sge_lock) {
2141       SDL_UnlockSurface(Surface);
2142    }
2143 
2144 	sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
2145 }
2146 
2147 //==================================================================================
2148 // Draws a circle (RGB)
2149 //==================================================================================
sge_Circle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint8 R,Uint8 G,Uint8 B)2150 void sge_Circle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
2151 {
2152 	sge_Circle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B));
2153 }
2154 
2155 
2156 //==================================================================================
2157 // Draws a circle (alpha)
2158 //==================================================================================
sge_CircleAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint32 color,Uint8 alpha)2159 void sge_CircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
2160 {
2161 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
2162 		if (SDL_LockSurface(Surface) < 0)
2163 			return;
2164 
2165 	_sge_alpha_hack = alpha;
2166 	sge_DoCircle(Surface, x, y, r, color, callback_alpha_hack);
2167 
2168 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
2169 		SDL_UnlockSurface(Surface);
2170 	}
2171 
2172 	sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
2173 }
2174 
2175 //==================================================================================
2176 // Draws a circle (alpha - RGB)
2177 //==================================================================================
sge_CircleAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)2178 void sge_CircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
2179 {
2180 	sge_CircleAlpha(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),alpha);
2181 }
2182 
2183 
2184 //==================================================================================
2185 // Draws a filled circle
2186 //==================================================================================
sge_FilledCircle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2187 void sge_FilledCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2188 {
2189 	Sint16 cx = 0;
2190  	Sint16 cy = r;
2191 	bool draw=true;
2192  	Sint16 df = 1 - r;
2193  	Sint16 d_e = 3;
2194  	Sint16 d_se = -2 * r + 5;
2195 
2196  	do {
2197 		if(draw){
2198  			_HLine(Surface,x-cx,x+cx,y+cy,color);
2199 			_HLine(Surface,x-cx,x+cx,y-cy,color);
2200 			draw=false;
2201 		}
2202 		if(cx!=cy){
2203 			if(cx){
2204 				_HLine(Surface,x-cy,x+cy,y-cx,color);
2205 	 			_HLine(Surface,x-cy,x+cy,y+cx,color);
2206 			}else
2207 				_HLine(Surface,x-cy,x+cy,y,color);
2208 		}
2209 
2210 		if (df < 0)  {
2211 	 		df += d_e;
2212 	 		d_e += 2;
2213 	 		d_se += 2;
2214  		}
2215    		else {
2216 	 		df += d_se;
2217 	 		d_e += 2;
2218 	 		d_se += 4;
2219 	 		cy--;
2220 			draw=true;
2221    		}
2222   		cx++;
2223 	}while(cx <= cy);
2224 
2225 	sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
2226 }
2227 
2228 //==================================================================================
2229 // Draws a filled circle (RGB)
2230 //==================================================================================
sge_FilledCircle(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint8 R,Uint8 G,Uint8 B)2231 void sge_FilledCircle(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
2232 {
2233 	sge_FilledCircle(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B));
2234 }
2235 
2236 
2237 //==================================================================================
2238 // Draws a filled circle (alpha)
2239 //==================================================================================
sge_FilledCircleAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint32 color,Uint8 alpha)2240 void sge_FilledCircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint32 color, Uint8 alpha)
2241 {
2242 	Sint16 cx = 0;
2243  	Sint16 cy = r;
2244 	bool draw=true;
2245  	Sint16 df = 1 - r;
2246  	Sint16 d_e = 3;
2247  	Sint16 d_se = -2 * r + 5;
2248 
2249 	if (SDL_MUSTLOCK(Surface) && _sge_lock)
2250 		if (SDL_LockSurface(Surface) < 0)
2251 			return;
2252 
2253  	do {
2254 		if(draw){
2255  			_HLineAlpha(Surface,x-cx,x+cx,y+cy,color,alpha);
2256 			_HLineAlpha(Surface,x-cx,x+cx,y-cy,color,alpha);
2257 			draw=false;
2258 		}
2259 		if(cx!=cy){
2260 			if(cx){
2261 				_HLineAlpha(Surface,x-cy,x+cy,y-cx,color,alpha);
2262 	 			_HLineAlpha(Surface,x-cy,x+cy,y+cx,color,alpha);
2263 			}else
2264 				_HLineAlpha(Surface,x-cy,x+cy,y,color,alpha);
2265 		}
2266 
2267 		if (df < 0)  {
2268 	 		df += d_e;
2269 	 		d_e += 2;
2270 	 		d_se += 2;
2271  		}
2272    		else {
2273 	 		df += d_se;
2274 	 		d_e += 2;
2275 	 		d_se += 4;
2276 	 		cy--;
2277 			draw=true;
2278    		}
2279   		cx++;
2280 	}while(cx <= cy);
2281 
2282 	if (SDL_MUSTLOCK(Surface) && _sge_lock) {
2283 		SDL_UnlockSurface(Surface);
2284 	}
2285 
2286 	sge_UpdateRect(Surface, x-r, y-r, 2*r+1, 2*r+1);
2287 }
2288 
2289 //==================================================================================
2290 // Draws a filled circle (alpha - RGB)
2291 //==================================================================================
sge_FilledCircleAlpha(SDL_Surface * Surface,Sint16 x,Sint16 y,Sint16 r,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)2292 void sge_FilledCircleAlpha(SDL_Surface *Surface, Sint16 x, Sint16 y, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
2293 {
2294 	sge_FilledCircleAlpha(Surface,x,y,r,SDL_MapRGB(Surface->format, R, G, B),alpha);
2295 }
2296 
2297 
2298 //==================================================================================
2299 // Draws an anti-aliased circle (alpha)
2300 //==================================================================================
sge_AACircleAlpha(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint32 color,Uint8 alpha)2301 void sge_AACircleAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint32 color, Uint8 alpha)
2302 {
2303 	sge_AAEllipseAlpha(surface, xc, yc, r, r, color, alpha);
2304 }
2305 
2306 
2307 //==================================================================================
2308 // Draws an anti-aliased circle (alpha - RGB)
2309 //==================================================================================
sge_AACircleAlpha(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)2310 void sge_AACircleAlpha(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
2311 {
2312 	sge_AAEllipseAlpha(surface,xc,yc,r,r,SDL_MapRGB(surface->format, R, G, B),alpha);
2313 }
2314 
2315 
2316 //==================================================================================
2317 // Draws an anti-aliased circle
2318 //==================================================================================
sge_AACircle(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint32 color)2319 void sge_AACircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint32 color)
2320 {
2321 	sge_AAEllipseAlpha(surface,xc,yc,r,r,color,255);
2322 }
2323 
2324 //==================================================================================
2325 // Draws an anti-aliased circle (RGB)
2326 //==================================================================================
sge_AACircle(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint8 R,Uint8 G,Uint8 B)2327 void sge_AACircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
2328 {
2329 	sge_AAEllipseAlpha(surface,xc,yc,r,r,SDL_MapRGB(surface->format, R, G, B),255);
2330 }
2331 
2332 
2333 //==================================================================================
2334 // Draws a filled anti-aliased circle
2335 //==================================================================================
sge_AAFilledCircle(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint32 color)2336 void sge_AAFilledCircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint32 color)
2337 {
2338 	sge_AAFilledEllipse(surface, xc, yc, r, r, color);
2339 }
2340 
2341 
2342 //==================================================================================
2343 // Draws a filled anti-aliased circle (RGB)
2344 //==================================================================================
sge_AAFilledCircle(SDL_Surface * surface,Sint16 xc,Sint16 yc,Sint16 r,Uint8 R,Uint8 G,Uint8 B)2345 void sge_AAFilledCircle(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 r, Uint8 R, Uint8 G, Uint8 B)
2346 {
2347 	sge_AAFilledEllipse(surface,xc,yc,r,r,SDL_MapRGB(surface->format, R, G, B));
2348 }
2349 
2350 
2351 
2352 
2353 
2354 //==================================================================================
2355 // Draws a bezier line
2356 //==================================================================================
2357 /* Macro to do the line... 'function' is the line drawing routine */
2358 #define DO_BEZIER(function)\
2359 	/*
2360 	*  Note: I don't think there is any great performance win in translating this to fixed-point integer math,
2361 	*  most of the time is spent in the line drawing routine.
2362 	*/\
2363 	float x = float(x1), y = float(y1);\
2364 	float xp = x, yp = y;\
2365 	float delta;\
2366 	float dx, d2x, d3x;\
2367 	float dy, d2y, d3y;\
2368 	float a, b, c;\
2369 	int i;\
2370 	int n = 1;\
2371 	Sint16 xmax=x1, ymax=y1, xmin=x1, ymin=y1;\
2372 	\
2373 	/* compute number of iterations */\
2374 	if(level < 1)\
2375 		level=1;\
2376 	if(level >= 15)\
2377 		level=15; \
2378 	while (level-- > 0)\
2379 		n*= 2;\
2380 	delta = float( 1.0 / float(n) );\
2381 	\
2382 	/* compute finite differences */\
2383 	/* a, b, c are the coefficient of the polynom in t defining the parametric curve */\
2384 	/* The computation is done independently for x and y */\
2385 	a = float(-x1 + 3*x2 - 3*x3 + x4);\
2386 	b = float(3*x1 - 6*x2 + 3*x3);\
2387 	c = float(-3*x1 + 3*x2);\
2388 	\
2389 	d3x = 6 * a * delta*delta*delta;\
2390 	d2x = d3x + 2 * b * delta*delta;\
2391 	dx = a * delta*delta*delta + b * delta*delta + c * delta;\
2392 	\
2393 	a = float(-y1 + 3*y2 - 3*y3 + y4);\
2394 	b = float(3*y1 - 6*y2 + 3*y3);\
2395 	c = float(-3*y1 + 3*y2);\
2396 	\
2397 	d3y = 6 * a * delta*delta*delta;\
2398 	d2y = d3y + 2 * b * delta*delta;\
2399 	dy = a * delta*delta*delta + b * delta*delta + c * delta;\
2400 	\
2401 	if (SDL_MUSTLOCK(surface) && _sge_lock) {\
2402 		if (SDL_LockSurface(surface) < 0)\
2403 			return;\
2404 	}\
2405 	\
2406 	/* iterate */\
2407 	for (i = 0; i < n; i++) {\
2408 		x += dx; dx += d2x; d2x += d3x;\
2409 		y += dy; dy += d2y; d2y += d3y;\
2410 		if(Sint16(xp) != Sint16(x) || Sint16(yp) != Sint16(y)){\
2411 			function;\
2412 			if(_sge_update==1){\
2413 				xmax= (xmax>Sint16(xp))? xmax : Sint16(xp);  ymax= (ymax>Sint16(yp))? ymax : Sint16(yp);\
2414 				xmin= (xmin<Sint16(xp))? xmin : Sint16(xp);  ymin= (ymin<Sint16(yp))? ymin : Sint16(yp);\
2415 				xmax= (xmax>Sint16(x))? xmax : Sint16(x);    ymax= (ymax>Sint16(y))? ymax : Sint16(y);\
2416 				xmin= (xmin<Sint16(x))? xmin : Sint16(x);    ymin= (ymin<Sint16(y))? ymin : Sint16(y);\
2417 			}\
2418 		}\
2419 		xp = x; yp = y;\
2420 	}\
2421 	\
2422 	/* unlock the display */\
2423 	if (SDL_MUSTLOCK(surface) && _sge_lock) {\
2424 		SDL_UnlockSurface(surface);\
2425 	}\
2426 	\
2427 	/* Update the area */\
2428 	sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
2429 
2430 //==================================================================================
2431 // Draws a bezier line
2432 //==================================================================================
sge_Bezier(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint32 color)2433 void sge_Bezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color)
2434 {
2435 	DO_BEZIER(_Line(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color));
2436 }
2437 
2438 //==================================================================================
2439 // Draws a bezier line (RGB)
2440 //==================================================================================
sge_Bezier(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint8 R,Uint8 G,Uint8 B)2441 void sge_Bezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
2442 {
2443 	sge_Bezier(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B));
2444 }
2445 
2446 
2447 //==================================================================================
2448 // Draws a bezier line (alpha)
2449 //==================================================================================
sge_BezierAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint32 color,Uint8 alpha)2450 void sge_BezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color, Uint8 alpha)
2451 {
2452 	_sge_alpha_hack = alpha;
2453 
2454 	DO_BEZIER(sge_DoLine(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color, callback_alpha_hack));
2455 }
2456 
2457 //==================================================================================
2458 // Draws a bezier line (alpha - RGB)
2459 //==================================================================================
sge_BezierAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)2460 void sge_BezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
2461 {
2462 	sge_BezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),alpha);
2463 }
2464 
2465 
2466 //==================================================================================
2467 // Draws an AA bezier line (alpha)
2468 //==================================================================================
sge_AABezierAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint32 color,Uint8 alpha)2469 void sge_AABezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color, Uint8 alpha)
2470 {
2471 	Uint8 update = _sge_update;
2472 	Uint8 lock = _sge_lock;
2473 	_sge_update = 0;
2474 	_sge_lock = 0;
2475 
2476 	if (SDL_MUSTLOCK(surface) && lock)
2477 		if (SDL_LockSurface(surface) < 0)
2478 			return;
2479 
2480 	DO_BEZIER(sge_AALineAlpha(surface, Sint16(xp),Sint16(yp), Sint16(x),Sint16(y), color, alpha));
2481 
2482 	if (SDL_MUSTLOCK(surface) && lock) {
2483 		SDL_UnlockSurface(surface);
2484 	}
2485 
2486 	_sge_update = update;
2487 	_sge_lock = lock;
2488 
2489 	sge_UpdateRect(surface, xmin, ymin, xmax-xmin+1, ymax-ymin+1);
2490 }
2491 
2492 //==================================================================================
2493 // Draws an AA bezier line (alpha - RGB)
2494 //==================================================================================
sge_AABezierAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint8 R,Uint8 G,Uint8 B,Uint8 alpha)2495 void sge_AABezierAlpha(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B, Uint8 alpha)
2496 {
2497 	sge_AABezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),alpha);
2498 }
2499 
2500 
2501 //==================================================================================
2502 // Draws an AA bezier line
2503 //==================================================================================
sge_AABezier(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint32 color)2504 void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint32 color)
2505 {
2506 	sge_AABezierAlpha(surface, x1,y1, x2,y2, x3,y3, x4,y4, level, color, 255);
2507 }
2508 
2509 //==================================================================================
2510 // Draws an AA bezier line (RGB)
2511 //==================================================================================
sge_AABezier(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Sint16 x4,Sint16 y4,int level,Uint8 R,Uint8 G,Uint8 B)2512 void sge_AABezier(SDL_Surface *surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2,Sint16 x3, Sint16 y3, Sint16 x4, Sint16 y4, int level, Uint8 R, Uint8 G, Uint8 B)
2513 {
2514 	sge_AABezierAlpha(surface,x1,y1,x2,y2,x3,y3,x4,y4,level, SDL_MapRGB(surface->format,R,G,B),255);
2515 }
2516 
2517