1 //#warning Altered source only for use with RSDL_wrapper
2 //#warning RETRO HACK This is just an SDL wrapper for liretro core.
3 
4 /*
5 
6 RSDL_gfxPrimitives.c: graphics primitives for SDL surfaces
7 
8 Copyright (C) 2001-2012  Andreas Schiffler
9 
10 This software is provided 'as-is', without any express or implied
11 warranty. In no event will the authors be held liable for any damages
12 arising from the use of this software.
13 
14 Permission is granted to anyone to use this software for any purpose,
15 including commercial applications, and to alter it and redistribute it
16 freely, subject to the following restrictions:
17 
18 1. The origin of this software must not be misrepresented; you must not
19 claim that you wrote the original software. If you use this software
20 in a product, an acknowledgment in the product documentation would be
21 appreciated but is not required.
22 
23 2. Altered source versions must be plainly marked as such, and must not be
24 misrepresented as being the original software.
25 
26 3. This notice may not be removed or altered from any source
27 distribution.
28 
29 Andreas Schiffler -- aschiffler at ferzkopp dot net
30 
31 */
32 
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <math.h>
36 #include <string.h>
37 
38 #include "SDL_gfxPrimitives.h"
39 /*
40 #include "RSDL_rotozoom.h"
41 #include "RSDL_gfxPrimitives_font.h"
42 #include "RSDL_gfxBlitFunc.h"
43 */
44 
45 const unsigned int GFX_ALPHA_ADJUST_ARRAY[256] = {
46 	0,  /* 0 */
47 	15,  /* 1 */
48 	22,  /* 2 */
49 	27,  /* 3 */
50 	31,  /* 4 */
51 	35,  /* 5 */
52 	39,  /* 6 */
53 	42,  /* 7 */
54 	45,  /* 8 */
55 	47,  /* 9 */
56 	50,  /* 10 */
57 	52,  /* 11 */
58 	55,  /* 12 */
59 	57,  /* 13 */
60 	59,  /* 14 */
61 	61,  /* 15 */
62 	63,  /* 16 */
63 	65,  /* 17 */
64 	67,  /* 18 */
65 	69,  /* 19 */
66 	71,  /* 20 */
67 	73,  /* 21 */
68 	74,  /* 22 */
69 	76,  /* 23 */
70 	78,  /* 24 */
71 	79,  /* 25 */
72 	81,  /* 26 */
73 	82,  /* 27 */
74 	84,  /* 28 */
75 	85,  /* 29 */
76 	87,  /* 30 */
77 	88,  /* 31 */
78 	90,  /* 32 */
79 	91,  /* 33 */
80 	93,  /* 34 */
81 	94,  /* 35 */
82 	95,  /* 36 */
83 	97,  /* 37 */
84 	98,  /* 38 */
85 	99,  /* 39 */
86 	100,  /* 40 */
87 	102,  /* 41 */
88 	103,  /* 42 */
89 	104,  /* 43 */
90 	105,  /* 44 */
91 	107,  /* 45 */
92 	108,  /* 46 */
93 	109,  /* 47 */
94 	110,  /* 48 */
95 	111,  /* 49 */
96 	112,  /* 50 */
97 	114,  /* 51 */
98 	115,  /* 52 */
99 	116,  /* 53 */
100 	117,  /* 54 */
101 	118,  /* 55 */
102 	119,  /* 56 */
103 	120,  /* 57 */
104 	121,  /* 58 */
105 	122,  /* 59 */
106 	123,  /* 60 */
107 	124,  /* 61 */
108 	125,  /* 62 */
109 	126,  /* 63 */
110 	127,  /* 64 */
111 	128,  /* 65 */
112 	129,  /* 66 */
113 	130,  /* 67 */
114 	131,  /* 68 */
115 	132,  /* 69 */
116 	133,  /* 70 */
117 	134,  /* 71 */
118 	135,  /* 72 */
119 	136,  /* 73 */
120 	137,  /* 74 */
121 	138,  /* 75 */
122 	139,  /* 76 */
123 	140,  /* 77 */
124 	141,  /* 78 */
125 	141,  /* 79 */
126 	142,  /* 80 */
127 	143,  /* 81 */
128 	144,  /* 82 */
129 	145,  /* 83 */
130 	146,  /* 84 */
131 	147,  /* 85 */
132 	148,  /* 86 */
133 	148,  /* 87 */
134 	149,  /* 88 */
135 	150,  /* 89 */
136 	151,  /* 90 */
137 	152,  /* 91 */
138 	153,  /* 92 */
139 	153,  /* 93 */
140 	154,  /* 94 */
141 	155,  /* 95 */
142 	156,  /* 96 */
143 	157,  /* 97 */
144 	158,  /* 98 */
145 	158,  /* 99 */
146 	159,  /* 100 */
147 	160,  /* 101 */
148 	161,  /* 102 */
149 	162,  /* 103 */
150 	162,  /* 104 */
151 	163,  /* 105 */
152 	164,  /* 106 */
153 	165,  /* 107 */
154 	165,  /* 108 */
155 	166,  /* 109 */
156 	167,  /* 110 */
157 	168,  /* 111 */
158 	168,  /* 112 */
159 	169,  /* 113 */
160 	170,  /* 114 */
161 	171,  /* 115 */
162 	171,  /* 116 */
163 	172,  /* 117 */
164 	173,  /* 118 */
165 	174,  /* 119 */
166 	174,  /* 120 */
167 	175,  /* 121 */
168 	176,  /* 122 */
169 	177,  /* 123 */
170 	177,  /* 124 */
171 	178,  /* 125 */
172 	179,  /* 126 */
173 	179,  /* 127 */
174 	180,  /* 128 */
175 	181,  /* 129 */
176 	182,  /* 130 */
177 	182,  /* 131 */
178 	183,  /* 132 */
179 	184,  /* 133 */
180 	184,  /* 134 */
181 	185,  /* 135 */
182 	186,  /* 136 */
183 	186,  /* 137 */
184 	187,  /* 138 */
185 	188,  /* 139 */
186 	188,  /* 140 */
187 	189,  /* 141 */
188 	190,  /* 142 */
189 	190,  /* 143 */
190 	191,  /* 144 */
191 	192,  /* 145 */
192 	192,  /* 146 */
193 	193,  /* 147 */
194 	194,  /* 148 */
195 	194,  /* 149 */
196 	195,  /* 150 */
197 	196,  /* 151 */
198 	196,  /* 152 */
199 	197,  /* 153 */
200 	198,  /* 154 */
201 	198,  /* 155 */
202 	199,  /* 156 */
203 	200,  /* 157 */
204 	200,  /* 158 */
205 	201,  /* 159 */
206 	201,  /* 160 */
207 	202,  /* 161 */
208 	203,  /* 162 */
209 	203,  /* 163 */
210 	204,  /* 164 */
211 	205,  /* 165 */
212 	205,  /* 166 */
213 	206,  /* 167 */
214 	206,  /* 168 */
215 	207,  /* 169 */
216 	208,  /* 170 */
217 	208,  /* 171 */
218 	209,  /* 172 */
219 	210,  /* 173 */
220 	210,  /* 174 */
221 	211,  /* 175 */
222 	211,  /* 176 */
223 	212,  /* 177 */
224 	213,  /* 178 */
225 	213,  /* 179 */
226 	214,  /* 180 */
227 	214,  /* 181 */
228 	215,  /* 182 */
229 	216,  /* 183 */
230 	216,  /* 184 */
231 	217,  /* 185 */
232 	217,  /* 186 */
233 	218,  /* 187 */
234 	218,  /* 188 */
235 	219,  /* 189 */
236 	220,  /* 190 */
237 	220,  /* 191 */
238 	221,  /* 192 */
239 	221,  /* 193 */
240 	222,  /* 194 */
241 	222,  /* 195 */
242 	223,  /* 196 */
243 	224,  /* 197 */
244 	224,  /* 198 */
245 	225,  /* 199 */
246 	225,  /* 200 */
247 	226,  /* 201 */
248 	226,  /* 202 */
249 	227,  /* 203 */
250 	228,  /* 204 */
251 	228,  /* 205 */
252 	229,  /* 206 */
253 	229,  /* 207 */
254 	230,  /* 208 */
255 	230,  /* 209 */
256 	231,  /* 210 */
257 	231,  /* 211 */
258 	232,  /* 212 */
259 	233,  /* 213 */
260 	233,  /* 214 */
261 	234,  /* 215 */
262 	234,  /* 216 */
263 	235,  /* 217 */
264 	235,  /* 218 */
265 	236,  /* 219 */
266 	236,  /* 220 */
267 	237,  /* 221 */
268 	237,  /* 222 */
269 	238,  /* 223 */
270 	238,  /* 224 */
271 	239,  /* 225 */
272 	240,  /* 226 */
273 	240,  /* 227 */
274 	241,  /* 228 */
275 	241,  /* 229 */
276 	242,  /* 230 */
277 	242,  /* 231 */
278 	243,  /* 232 */
279 	243,  /* 233 */
280 	244,  /* 234 */
281 	244,  /* 235 */
282 	245,  /* 236 */
283 	245,  /* 237 */
284 	246,  /* 238 */
285 	246,  /* 239 */
286 	247,  /* 240 */
287 	247,  /* 241 */
288 	248,  /* 242 */
289 	248,  /* 243 */
290 	249,  /* 244 */
291 	249,  /* 245 */
292 	250,  /* 246 */
293 	250,  /* 247 */
294 	251,  /* 248 */
295 	251,  /* 249 */
296 	252,  /* 250 */
297 	252,  /* 251 */
298 	253,  /* 252 */
299 	253,  /* 253 */
300 	254,  /* 254 */
301 	255   /* 255 */
302 };
303 
304 /* -===================- */
305 
306 #define DEFAULT_ALPHA_PIXEL_ROUTINE
307 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
308 #define ALPHA_PIXEL_ADDITIVE_BLEND
309 
310 /* ---- Structures */
311 
312 /*!
313 \brief The structure passed to the internal Bresenham iterator.
314 */
315 typedef struct {
316 	Sint16 x, y;
317 	int dx, dy, s1, s2, swapdir, error;
318 	Uint32 count;
319 } RSDL_gfxBresenhamIterator;
320 
321 /*!
322 \brief The structure passed to the internal Murphy iterator.
323 */
324 typedef struct {
325 	Uint32 color;
326 	RSDL_Surface *dst;
327 	int u, v;		/* delta x , delta y */
328 	int ku, kt, kv, kd;	/* loop constants */
329 	int oct2;
330 	int quad4;
331 	Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
332 } RSDL_gfxMurphyIterator;
333 
334 /* ----- Defines for pixel clipping tests */
335 
336 #define clip_xmin(surface) surface->clip_rect.x
337 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
338 #define clip_ymin(surface) surface->clip_rect.y
339 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
340 
341 /*!
342 \brief Internal pixel drawing - fast, no blending, no locking, clipping.
343 
344 \param dst The surface to draw on.
345 \param x The horizontal coordinate of the pixel.
346 \param y The vertical position of the pixel.
347 \param color The color value of the pixel to draw.
348 
349 \returns Returns 0 on success, -1 on failure.
350 */
fastPixelColorNolock(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)351 int fastPixelColorNolock(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
352 {
353 	int bpp;
354 	Uint8 *p;
355 
356 	/*
357 	* Honor clipping setup at pixel level
358 	*/
359 	if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
360 
361 		/*
362 		* Get destination format
363 		*/
364 		bpp = dst->format->BytesPerPixel;
365 		p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
366 		switch (bpp) {
367 		case 1:
368 			*p = color;
369 			break;
370 		case 2:
371 			*(Uint16 *) p = color;
372 			break;
373 		case 3:
374 			if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
375 				p[0] = (color >> 16) & 0xff;
376 				p[1] = (color >> 8) & 0xff;
377 				p[2] = color & 0xff;
378 			} else {
379 				p[0] = color & 0xff;
380 				p[1] = (color >> 8) & 0xff;
381 				p[2] = (color >> 16) & 0xff;
382 			}
383 			break;
384 		case 4:
385 			*(Uint32 *) p = color;
386 			break;
387 		}			/* switch */
388 
389 
390 	}
391 
392 	return (0);
393 }
394 
395 /*!
396 \brief Internal pixel drawing - fast, no blending, no locking, no clipping.
397 
398 Function is faster but dangerous since no clipping check is done.
399 Code needs to make sure we stay in surface bounds before calling.
400 
401 \param dst The surface to draw on.
402 \param x The horizontal coordinate of the pixel.
403 \param y The vertical position of the pixel.
404 \param color The color value of the pixel to draw.
405 
406 \returns Returns 0 on success, -1 on failure.
407 */
fastPixelColorNolockNoclip(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)408 int fastPixelColorNolockNoclip(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
409 {
410 	int bpp;
411 	Uint8 *p;
412 
413 	/*
414 	* Get destination format
415 	*/
416 	bpp = dst->format->BytesPerPixel;
417 	p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
418 	switch (bpp) {
419 	case 1:
420 		*p = color;
421 		break;
422 	case 2:
423 		*(Uint16 *) p = color;
424 		break;
425 	case 3:
426 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
427 			p[0] = (color >> 16) & 0xff;
428 			p[1] = (color >> 8) & 0xff;
429 			p[2] = color & 0xff;
430 		} else {
431 			p[0] = color & 0xff;
432 			p[1] = (color >> 8) & 0xff;
433 			p[2] = (color >> 16) & 0xff;
434 		}
435 		break;
436 	case 4:
437 		*(Uint32 *) p = color;
438 		break;
439 	}				/* switch */
440 
441 	return (0);
442 }
443 
444 /*!
445 \brief Internal pixel drawing - fast, no blending, locking, clipping.
446 
447 \param dst The surface to draw on.
448 \param x The horizontal coordinate of the pixel.
449 \param y The vertical position of the pixel.
450 \param color The color value of the pixel to draw.
451 
452 \returns Returns 0 on success, -1 on failure.
453 */
fastPixelColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)454 int fastPixelColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
455 {
456 	int result;
457 
458 	/*
459 	* Lock the surface
460 	*/
461 	if (RSDL_MUSTLOCK(dst)) {
462 		if (RSDL_LockSurface(dst) < 0) {
463 			return (-1);
464 		}
465 	}
466 
467 	result = fastPixelColorNolock(dst, x, y, color);
468 
469 	/*
470 	* Unlock surface
471 	*/
472 	if (RSDL_MUSTLOCK(dst)) {
473 		RSDL_UnlockSurface(dst);
474 	}
475 
476 	return (result);
477 }
478 
479 /*!
480 \brief Internal pixel drawing - fast, no blending, locking, RGB input.
481 
482 \param dst The surface to draw on.
483 \param x The horizontal coordinate of the pixel.
484 \param y The vertical position of the pixel.
485 \param r The red value of the pixel to draw.
486 \param g The green value of the pixel to draw.
487 \param b The blue value of the pixel to draw.
488 \param a The alpha value of the pixel to draw.
489 
490 \returns Returns 0 on success, -1 on failure.
491 */
fastPixelRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)492 int fastPixelRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
493 {
494 	Uint32 color;
495 
496 	/*
497 	* Setup color
498 	*/
499 	color = RSDL_MapRGBA(dst->format, r, g, b, a);
500 
501 	/*
502 	* Draw
503 	*/
504 	return (fastPixelColor(dst, x, y, color));
505 }
506 
507 /*!
508 \brief Internal pixel drawing - fast, no blending, no locking RGB input.
509 
510 \param dst The surface to draw on.
511 \param x The horizontal coordinate of the pixel.
512 \param y The vertical position of the pixel.
513 \param r The red value of the pixel to draw.
514 \param g The green value of the pixel to draw.
515 \param b The blue value of the pixel to draw.
516 \param a The alpha value of the pixel to draw.
517 
518 \returns Returns 0 on success, -1 on failure.
519 */
fastPixelRGBANolock(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)520 int fastPixelRGBANolock(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
521 {
522 	Uint32 color;
523 
524 	/*
525 	* Setup color
526 	*/
527 	color = RSDL_MapRGBA(dst->format, r, g, b, a);
528 
529 	/*
530 	* Draw
531 	*/
532 	return (fastPixelColorNolock(dst, x, y, color));
533 }
534 
535 /*!
536 \brief Internal pixel drawing function with alpha blending where input color in in destination format.
537 
538 Contains two alternative 32 bit alpha blending routines which can be enabled at the source
539 level with the defines DEFAULT_ALPHA_PIXEL_ROUTINE or EXPERIMENTAL_ALPHA_PIXEL_ROUTINE.
540 Only the bits up to the surface depth are significant in the color value.
541 
542 \param dst The surface to draw on.
543 \param x The horizontal coordinate of the pixel.
544 \param y The vertical position of the pixel.
545 \param color The color value of the pixel to draw.
546 \param alpha The blend factor to apply while drawing.
547 
548 \returns Returns 0 on success, -1 on failure.
549 */
_putPixelAlpha(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)550 int _putPixelAlpha(RSDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
551 {
552 	RSDL_PixelFormat *format;
553 	Uint32 Rmask, Gmask, Bmask, Amask;
554 	Uint32 Rshift, Gshift, Bshift, Ashift;
555 	Uint32 sR, sG, sB;
556 	Uint32 dR, dG, dB, dA;
557 
558 	if (dst == NULL)
559 	{
560 		return (-1);
561 	}
562 
563 	if (x >= clip_xmin(dst) && x <= clip_xmax(dst) &&
564 		y >= clip_ymin(dst) && y <= clip_ymax(dst))
565 	{
566 
567 		format = dst->format;
568 
569 		switch (format->BytesPerPixel) {
570 		case 1:
571 			{		/* Assuming 8-bpp */
572 				Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
573 				if (alpha == 255) {
574 					*pixel = color;
575 				} else {
576 					Uint8 R, G, B;
577 					RSDL_Palette *palette = format->palette;
578 					RSDL_Color *colors = palette->colors;
579 					RSDL_Color dColor = colors[*pixel];
580 					RSDL_Color sColor = colors[color];
581 					dR = dColor.r;
582 					dG = dColor.g;
583 					dB = dColor.b;
584 					sR = sColor.r;
585 					sG = sColor.g;
586 					sB = sColor.b;
587 
588 					R = dR + ((sR - dR) * alpha >> 8);
589 					G = dG + ((sG - dG) * alpha >> 8);
590 					B = dB + ((sB - dB) * alpha >> 8);
591 
592 					*pixel = RSDL_MapRGB(format, R, G, B);
593 				}
594 			}
595 			break;
596 
597 		case 2:
598 			{		/* Probably 15-bpp or 16-bpp */
599 				Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
600 				if (alpha == 255) {
601 					*pixel = color;
602 				} else {
603 					Uint16 R, G, B, A;
604 					Uint16 dc = *pixel;
605 
606 					Rmask = format->Rmask;
607 					Gmask = format->Gmask;
608 					Bmask = format->Bmask;
609 					Amask = format->Amask;
610 
611 					dR = (dc & Rmask);
612 					dG = (dc & Gmask);
613 					dB = (dc & Bmask);
614 
615 					R = (dR + (((color & Rmask) - dR) * alpha >> 8)) & Rmask;
616 					G = (dG + (((color & Gmask) - dG) * alpha >> 8)) & Gmask;
617 					B = (dB + (((color & Bmask) - dB) * alpha >> 8)) & Bmask;
618 					*pixel = R | G | B;
619 					if (Amask!=0) {
620 						dA = (dc & Amask);
621 						A = (dA + (((color & Amask) - dA) * alpha >> 8)) & Amask;
622 						*pixel |= A;
623 					}
624 				}
625 			}
626 			break;
627 
628 		case 3:
629 			{		/* Slow 24-bpp mode, usually not used */
630 				Uint8 R, G, B;
631 				Uint8 Rshift8, Gshift8, Bshift8;
632 				Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
633 
634 				Rshift = format->Rshift;
635 				Gshift = format->Gshift;
636 				Bshift = format->Bshift;
637 
638 				Rshift8 = Rshift >> 3;
639 				Gshift8 = Gshift >> 3;
640 				Bshift8 = Bshift >> 3;
641 
642 				sR = (color >> Rshift) & 0xFF;
643 				sG = (color >> Gshift) & 0xFF;
644 				sB = (color >> Bshift) & 0xFF;
645 
646 				if (alpha == 255) {
647 					*(pixel + Rshift8) = sR;
648 					*(pixel + Gshift8) = sG;
649 					*(pixel + Bshift8) = sB;
650 				} else {
651 					dR = *((pixel) + Rshift8);
652 					dG = *((pixel) + Gshift8);
653 					dB = *((pixel) + Bshift8);
654 
655 					R = dR + ((sR - dR) * alpha >> 8);
656 					G = dG + ((sG - dG) * alpha >> 8);
657 					B = dB + ((sB - dB) * alpha >> 8);
658 
659 					*((pixel) + Rshift8) = R;
660 					*((pixel) + Gshift8) = G;
661 					*((pixel) + Bshift8) = B;
662 				}
663 			}
664 			break;
665 
666 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
667 
668 		case 4:
669 			{		/* Probably :-) 32-bpp */
670 				Uint32 R, G, B, A;
671 				Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
672 				if (alpha == 255) {
673 					*pixel = color;
674 				} else {
675 					Uint32 dc = *pixel;
676 
677 					Rmask = format->Rmask;
678 					Gmask = format->Gmask;
679 					Bmask = format->Bmask;
680 					Amask = format->Amask;
681 
682 					Rshift = format->Rshift;
683 					Gshift = format->Gshift;
684 					Bshift = format->Bshift;
685 					Ashift = format->Ashift;
686 
687 					dR = (dc & Rmask) >> Rshift;
688 					dG = (dc & Gmask) >> Gshift;
689 					dB = (dc & Bmask) >> Bshift;
690 
691 
692 					R = ((dR + ((((color & Rmask) >> Rshift) - dR) * alpha >> 8)) << Rshift) & Rmask;
693 					G = ((dG + ((((color & Gmask) >> Gshift) - dG) * alpha >> 8)) << Gshift) & Gmask;
694 					B = ((dB + ((((color & Bmask) >> Bshift) - dB) * alpha >> 8)) << Bshift) & Bmask;
695 					*pixel = R | G | B;
696 					if (Amask!=0) {
697 						dA = (dc & Amask) >> Ashift;
698 
699 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
700 						A = (dA | GFX_ALPHA_ADJUST_ARRAY[alpha & 255]) << Ashift; // make destination less transparent...
701 #else
702 						A = ((dA + ((((color & Amask) >> Ashift) - dA) * alpha >> 8)) << Ashift) & Amask;
703 #endif
704 						*pixel |= A;
705 					}
706 				}
707 			}
708 			break;
709 #endif
710 
711 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
712 
713 		case 4:{		/* Probably :-) 32-bpp */
714 			if (alpha == 255) {
715 				*((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
716 			} else {
717 				Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
718 				Uint32 dR, dG, dB, dA;
719 				Uint32 dc = *pixel;
720 
721 				Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
722 				Uint32 aTmp;
723 
724 				Rmask = format->Rmask;
725 				Gmask = format->Gmask;
726 				Bmask = format->Bmask;
727 				Amask = format->Amask;
728 
729 				dR = (color & Rmask);
730 				dG = (color & Gmask);
731 				dB = (color & Bmask);
732 				dA = (color & Amask);
733 
734 				Rshift = format->Rshift;
735 				Gshift = format->Gshift;
736 				Bshift = format->Bshift;
737 				Ashift = format->Ashift;
738 
739 				preMultR = (alpha * (dR >> Rshift));
740 				preMultG = (alpha * (dG >> Gshift));
741 				preMultB = (alpha * (dB >> Bshift));
742 
743 				surfaceAlpha = ((dc & Amask) >> Ashift);
744 				aTmp = (255 - alpha);
745 				if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
746 					aTmp *= surfaceAlpha;
747 					R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
748 					G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
749 					B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
750 				}
751 				*pixel = R | G | B | (A << Ashift & Amask);
752 
753 			}
754 			   }
755 			   break;
756 #endif
757 		}
758 	}
759 
760 	return (0);
761 }
762 
763 /*!
764 \brief Pixel draw with blending enabled if a<255.
765 
766 \param dst The surface to draw on.
767 \param x X (horizontal) coordinate of the pixel.
768 \param y Y (vertical) coordinate of the pixel.
769 \param color The color value of the pixel to draw (0xRRGGBBAA).
770 
771 \returns Returns 0 on success, -1 on failure.
772 */
pixelColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)773 int pixelColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
774 {
775 	Uint8 alpha;
776 	Uint32 mcolor;
777 	int result = 0;
778 
779 	/*
780 	* Lock the surface
781 	*/
782 	if (RSDL_MUSTLOCK(dst)) {
783 		if (RSDL_LockSurface(dst) < 0) {
784 			return (-1);
785 		}
786 	}
787 
788 	/*
789 	* Setup color
790 	*/
791 	alpha = color & 0x000000ff;
792 	mcolor =
793 		RSDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
794 		(color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
795 
796 	/*
797 	* Draw
798 	*/
799 	result = _putPixelAlpha(dst, x, y, mcolor, alpha);
800 
801 	/*
802 	* Unlock the surface
803 	*/
804 	if (RSDL_MUSTLOCK(dst)) {
805 		RSDL_UnlockSurface(dst);
806 	}
807 
808 	return (result);
809 }
810 
811 /*!
812 \brief Pixel draw with blending enabled if a<255 - no surface locking.
813 
814 \param dst The surface to draw on.
815 \param x X (horizontal) coordinate of the pixel.
816 \param y Y (vertical) coordinate of the pixel.
817 \param color The color value of the pixel to draw (0xRRGGBBAA).
818 
819 \returns Returns 0 on success, -1 on failure.
820 */
pixelColorNolock(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)821 int pixelColorNolock(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
822 {
823 	Uint8 alpha;
824 	Uint32 mcolor;
825 	int result = 0;
826 
827 	/*
828 	* Setup color
829 	*/
830 	alpha = color & 0x000000ff;
831 	mcolor =
832 		RSDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
833 		(color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
834 
835 	/*
836 	* Draw
837 	*/
838 	result = _putPixelAlpha(dst, x, y, mcolor, alpha);
839 
840 	return (result);
841 }
842 
843 
844 /*!
845 \brief Internal function to draw filled rectangle with alpha blending.
846 
847 Assumes color is in destination format.
848 
849 \param dst The surface to draw on.
850 \param x1 X coordinate of the first corner (upper left) of the rectangle.
851 \param y1 Y coordinate of the first corner (upper left) of the rectangle.
852 \param x2 X coordinate of the second corner (lower right) of the rectangle.
853 \param y2 Y coordinate of the second corner (lower right) of the rectangle.
854 \param color The color value of the rectangle to draw (0xRRGGBBAA).
855 \param alpha Alpha blending amount for pixels.
856 
857 \returns Returns 0 on success, -1 on failure.
858 */
_filledRectAlpha(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)859 int _filledRectAlpha(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
860 {
861 	RSDL_PixelFormat *format;
862 	Uint32 Rmask, Gmask, Bmask, Amask;
863 	Uint32 Rshift, Gshift, Bshift, Ashift;
864 	Uint32 sR, sG, sB, sA;
865 	Uint32 dR, dG, dB, dA;
866 	Sint16 x, y;
867 
868 	if (dst == NULL) {
869 		return (-1);
870 	}
871 
872 	format = dst->format;
873 	switch (format->BytesPerPixel) {
874 	case 1:
875 		{			/* Assuming 8-bpp */
876 			Uint8 *row, *pixel;
877 			Uint8 R, G, B;
878 			RSDL_Color *colors = format->palette->colors;
879 			RSDL_Color dColor;
880 			RSDL_Color sColor = colors[color];
881 			sR = sColor.r;
882 			sG = sColor.g;
883 			sB = sColor.b;
884 
885 			for (y = y1; y <= y2; y++) {
886 				row = (Uint8 *) dst->pixels + y * dst->pitch;
887 				for (x = x1; x <= x2; x++) {
888 					if (alpha == 255) {
889 						*(row + x) = color;
890 					} else {
891 						pixel = row + x;
892 
893 						dColor = colors[*pixel];
894 						dR = dColor.r;
895 						dG = dColor.g;
896 						dB = dColor.b;
897 
898 						R = dR + ((sR - dR) * alpha >> 8);
899 						G = dG + ((sG - dG) * alpha >> 8);
900 						B = dB + ((sB - dB) * alpha >> 8);
901 
902 						*pixel = RSDL_MapRGB(format, R, G, B);
903 					}
904 				}
905 			}
906 		}
907 		break;
908 
909 	case 2:
910 		{			/* Probably 15-bpp or 16-bpp */
911 			Uint16 *row, *pixel;
912 			Uint16 R, G, B, A;
913 			Uint16 dc;
914 			Rmask = format->Rmask;
915 			Gmask = format->Gmask;
916 			Bmask = format->Bmask;
917 			Amask = format->Amask;
918 
919 			sR = (color & Rmask);
920 			sG = (color & Gmask);
921 			sB = (color & Bmask);
922 			sA = (color & Amask);
923 
924 			for (y = y1; y <= y2; y++) {
925 				row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
926 				for (x = x1; x <= x2; x++) {
927 					if (alpha == 255) {
928 						*(row + x) = color;
929 					} else {
930 						pixel = row + x;
931 						dc = *pixel;
932 
933 						dR = (dc & Rmask);
934 						dG = (dc & Gmask);
935 						dB = (dc & Bmask);
936 
937 						R = (dR + ((sR - dR) * alpha >> 8)) & Rmask;
938 						G = (dG + ((sG - dG) * alpha >> 8)) & Gmask;
939 						B = (dB + ((sB - dB) * alpha >> 8)) & Bmask;
940 						*pixel = R | G | B;
941 						if (Amask!=0) {
942 							dA = (dc & Amask);
943 							A = (dA + ((sA - dA) * alpha >> 8)) & Amask;
944 							*pixel |= A;
945 						}
946 					}
947 				}
948 			}
949 		}
950 		break;
951 
952 	case 3:
953 		{			/* Slow 24-bpp mode, usually not used */
954 			Uint8 *row, *pixel;
955 			Uint8 R, G, B;
956 			Uint8 Rshift8, Gshift8, Bshift8;
957 
958 			Rshift = format->Rshift;
959 			Gshift = format->Gshift;
960 			Bshift = format->Bshift;
961 
962 			Rshift8 = Rshift >> 3;
963 			Gshift8 = Gshift >> 3;
964 			Bshift8 = Bshift >> 3;
965 
966 			sR = (color >> Rshift) & 0xff;
967 			sG = (color >> Gshift) & 0xff;
968 			sB = (color >> Bshift) & 0xff;
969 
970 			for (y = y1; y <= y2; y++) {
971 				row = (Uint8 *) dst->pixels + y * dst->pitch;
972 				for (x = x1; x <= x2; x++) {
973 					pixel = row + x * 3;
974 
975 					if (alpha == 255) {
976 						*(pixel + Rshift8) = sR;
977 						*(pixel + Gshift8) = sG;
978 						*(pixel + Bshift8) = sB;
979 					} else {
980 						dR = *((pixel) + Rshift8);
981 						dG = *((pixel) + Gshift8);
982 						dB = *((pixel) + Bshift8);
983 
984 						R = dR + ((sR - dR) * alpha >> 8);
985 						G = dG + ((sG - dG) * alpha >> 8);
986 						B = dB + ((sB - dB) * alpha >> 8);
987 
988 						*((pixel) + Rshift8) = R;
989 						*((pixel) + Gshift8) = G;
990 						*((pixel) + Bshift8) = B;
991 					}
992 				}
993 			}
994 		}
995 		break;
996 
997 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
998 	case 4:
999 		{			/* Probably :-) 32-bpp */
1000 			Uint32 *row, *pixel;
1001 			Uint32 R, G, B, A;
1002 			Uint32 dc;
1003 			Rmask = format->Rmask;
1004 			Gmask = format->Gmask;
1005 			Bmask = format->Bmask;
1006 			Amask = format->Amask;
1007 
1008 			Rshift = format->Rshift;
1009 			Gshift = format->Gshift;
1010 			Bshift = format->Bshift;
1011 			Ashift = format->Ashift;
1012 
1013 			sR = (color & Rmask) >> Rshift;
1014 			sG = (color & Gmask) >> Gshift;
1015 			sB = (color & Bmask) >> Bshift;
1016 			sA = (color & Amask) >> Ashift;
1017 
1018 			for (y = y1; y <= y2; y++) {
1019 				row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
1020 				for (x = x1; x <= x2; x++) {
1021 					if (alpha == 255) {
1022 						*(row + x) = color;
1023 					} else {
1024 						pixel = row + x;
1025 						dc = *pixel;
1026 
1027 						dR = (dc & Rmask) >> Rshift;
1028 						dG = (dc & Gmask) >> Gshift;
1029 						dB = (dc & Bmask) >> Bshift;
1030 
1031 						R = ((dR + ((sR - dR) * alpha >> 8)) << Rshift) & Rmask;
1032 						G = ((dG + ((sG - dG) * alpha >> 8)) << Gshift) & Gmask;
1033 						B = ((dB + ((sB - dB) * alpha >> 8)) << Bshift) & Bmask;
1034 						*pixel = R | G | B;
1035 						if (Amask!=0) {
1036 							dA = (dc & Amask) >> Ashift;
1037 #ifdef ALPHA_PIXEL_ADDITIVE_BLEND
1038 							A = (dA | GFX_ALPHA_ADJUST_ARRAY[sA & 255]) << Ashift; // make destination less transparent...
1039 #else
1040 							A = ((dA + ((sA - dA) * alpha >> 8)) << Ashift) & Amask;
1041 #endif
1042 							*pixel |= A;
1043 						}
1044 					}
1045 				}
1046 			}
1047 		}
1048 		break;
1049 #endif
1050 
1051 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
1052 	case 4:{			/* Probably :-) 32-bpp */
1053 		Uint32 *row, *pixel;
1054 		Uint32 dR, dG, dB, dA;
1055 		Uint32 dc;
1056 		Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
1057 		Uint32 aTmp;
1058 
1059 		Rmask = format->Rmask;
1060 		Gmask = format->Gmask;
1061 		Bmask = format->Bmask;
1062 		Amask = format->Amask;
1063 
1064 		dR = (color & Rmask);
1065 		dG = (color & Gmask);
1066 		dB = (color & Bmask);
1067 		dA = (color & Amask);
1068 
1069 		Rshift = format->Rshift;
1070 		Gshift = format->Gshift;
1071 		Bshift = format->Bshift;
1072 		Ashift = format->Ashift;
1073 
1074 		preMultR = (alpha * (dR >> Rshift));
1075 		preMultG = (alpha * (dG >> Gshift));
1076 		preMultB = (alpha * (dB >> Bshift));
1077 
1078 		for (y = y1; y <= y2; y++) {
1079 			row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
1080 			for (x = x1; x <= x2; x++) {
1081 				if (alpha == 255) {
1082 					*(row + x) = color;
1083 				} else {
1084 					pixel = row + x;
1085 					dc = *pixel;
1086 
1087 					surfaceAlpha = ((dc & Amask) >> Ashift);
1088 					aTmp = (255 - alpha);
1089 					if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
1090 						aTmp *= surfaceAlpha;
1091 						R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
1092 						G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
1093 						B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
1094 					}
1095 					*pixel = R | G | B | (A << Ashift & Amask);
1096 				}
1097 			}
1098 		}
1099 		   }
1100 		   break;
1101 #endif
1102 
1103 	}
1104 
1105 	return (0);
1106 }
1107 
1108 /*!
1109 \brief Draw filled rectangle of RGBA color with alpha blending.
1110 
1111 \param dst The surface to draw on.
1112 \param x1 X coordinate of the first corner (upper left) of the rectangle.
1113 \param y1 Y coordinate of the first corner (upper left) of the rectangle.
1114 \param x2 X coordinate of the second corner (lower right) of the rectangle.
1115 \param y2 Y coordinate of the second corner (lower right) of the rectangle.
1116 \param color The color value of the rectangle to draw (0xRRGGBBAA).
1117 
1118 \returns Returns 0 on success, -1 on failure.
1119 */
filledRectAlpha(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1120 int filledRectAlpha(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1121 {
1122 	Uint8 alpha;
1123 	Uint32 mcolor;
1124 	int result = 0;
1125 
1126 	/*
1127 	* Lock the surface
1128 	*/
1129 	if (RSDL_MUSTLOCK(dst)) {
1130 		if (RSDL_LockSurface(dst) < 0) {
1131 			return (-1);
1132 		}
1133 	}
1134 
1135 	/*
1136 	* Setup color
1137 	*/
1138 	alpha = color & 0x000000ff;
1139 	mcolor =
1140 		RSDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
1141 		(color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
1142 
1143 	/*
1144 	* Draw
1145 	*/
1146 	result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
1147 
1148 	/*
1149 	* Unlock the surface
1150 	*/
1151 	if (RSDL_MUSTLOCK(dst)) {
1152 		RSDL_UnlockSurface(dst);
1153 	}
1154 
1155 	return (result);
1156 }
1157 
1158 /*!
1159 \brief Internal function to draw horizontal line of RGBA color with alpha blending.
1160 
1161 \param dst The surface to draw on.
1162 \param x1 X coordinate of the first point (i.e. left) of the line.
1163 \param x2 X coordinate of the second point (i.e. right) of the line.
1164 \param y Y coordinate of the points of the line.
1165 \param color The color value of the line to draw (0xRRGGBBAA).
1166 
1167 \returns Returns 0 on success, -1 on failure.
1168 */
_HLineAlpha(RSDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)1169 int _HLineAlpha(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
1170 {
1171 	return (filledRectAlpha(dst, x1, y, x2, y, color));
1172 }
1173 
1174 /*!
1175 \brief Internal function to draw vertical line of RGBA color with alpha blending.
1176 
1177 \param dst The surface to draw on.
1178 \param x X coordinate of the points of the line.
1179 \param y1 Y coordinate of the first point (top) of the line.
1180 \param y2 Y coordinate of the second point (bottom) of the line.
1181 \param color The color value of the line to draw (0xRRGGBBAA).
1182 
1183 \returns Returns 0 on success, -1 on failure.
1184 */
_VLineAlpha(RSDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)1185 int _VLineAlpha(RSDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
1186 {
1187 	return (filledRectAlpha(dst, x, y1, x, y2, color));
1188 }
1189 
1190 /*!
1191 \brief Pixel draw with blending enabled and using alpha weight on color.
1192 
1193 \param dst The surface to draw on.
1194 \param x The horizontal coordinate of the pixel.
1195 \param y The vertical position of the pixel.
1196 \param color The color value of the pixel to draw (0xRRGGBBAA).
1197 \param weight The weight multiplied into the alpha value of the pixel.
1198 
1199 \returns Returns 0 on success, -1 on failure.
1200 */
pixelColorWeight(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)1201 int pixelColorWeight(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
1202 {
1203 	Uint32 a;
1204 
1205 	/*
1206 	* Get alpha
1207 	*/
1208 	a = (color & (Uint32) 0x000000ff);
1209 
1210 	/*
1211 	* Modify Alpha by weight
1212 	*/
1213 	a = ((a * weight) >> 8);
1214 
1215 	return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
1216 }
1217 
1218 /*!
1219 \brief Pixel draw with blending enabled and using alpha weight on color - no locking.
1220 
1221 \param dst The surface to draw on.
1222 \param x The horizontal coordinate of the pixel.
1223 \param y The vertical position of the pixel.
1224 \param color The color value of the pixel to draw (0xRRGGBBAA).
1225 \param weight The weight multiplied into the alpha value of the pixel.
1226 
1227 \returns Returns 0 on success, -1 on failure.
1228 */
pixelColorWeightNolock(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)1229 int pixelColorWeightNolock(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
1230 {
1231 	Uint32 a;
1232 
1233 	/*
1234 	* Get alpha
1235 	*/
1236 	a = (color & (Uint32) 0x000000ff);
1237 
1238 	/*
1239 	* Modify Alpha by weight
1240 	*/
1241 	a = ((a * weight) >> 8);
1242 
1243 	return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
1244 }
1245 
1246 /*!
1247 \brief Pixel draw with blending enabled if a<255.
1248 
1249 \param dst The surface to draw on.
1250 \param x X (horizontal) coordinate of the pixel.
1251 \param y Y (vertical) coordinate of the pixel.
1252 \param r The red color value of the pixel to draw.
1253 \param g The green color value of the pixel to draw.
1254 \param b The blue color value of the pixel to draw.
1255 \param a The alpha value of the pixel to draw.
1256 
1257 \returns Returns 0 on success, -1 on failure.
1258 */
pixelRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1259 int pixelRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1260 {
1261 	Uint32 color;
1262 
1263 	/*
1264 	* Check Alpha
1265 	*/
1266 	if (a == 255) {
1267 		/*
1268 		* No alpha blending required
1269 		*/
1270 		/*
1271 		* Setup color
1272 		*/
1273 		color = RSDL_MapRGBA(dst->format, r, g, b, a);
1274 		/*
1275 		* Draw
1276 		*/
1277 		return (fastPixelColor(dst, x, y, color));
1278 	} else {
1279 		/*
1280 		* Alpha blending required
1281 		*/
1282 		/*
1283 		* Draw
1284 		*/
1285 		return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1286 	}
1287 }
1288 
1289 
1290 /*!
1291 \brief Draw horizontal line without blending;
1292 
1293 Just stores the color value (including the alpha component) without blending.
1294 Only the same number of bits of the destination surface are transfered
1295 from the input color value.
1296 
1297 \param dst The surface to draw on.
1298 \param x1 X coordinate of the first point (i.e. left) of the line.
1299 \param x2 X coordinate of the second point (i.e. right) of the line.
1300 \param y Y coordinate of the points of the line.
1301 \param color The color value of the line to draw.
1302 
1303 \returns Returns 0 on success, -1 on failure.
1304 */
hlineColorStore(RSDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)1305 int hlineColorStore(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
1306 {
1307 	Sint16 left, right, top, bottom;
1308 	Uint8 *pixel, *pixellast;
1309 	int dx;
1310 	int pixx, pixy;
1311 	Sint16 w;
1312 	Sint16 xtmp;
1313 	int result = -1;
1314 
1315 	/*
1316 	* Check visibility of clipping rectangle
1317 	*/
1318 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1319 		return(0);
1320 	}
1321 
1322 	/*
1323 	* Swap x1, x2 if required to ensure x1<=x2
1324 	*/
1325 	if (x1 > x2) {
1326 		xtmp = x1;
1327 		x1 = x2;
1328 		x2 = xtmp;
1329 	}
1330 
1331 	/*
1332 	* Get clipping boundary and
1333 	* check visibility of hline
1334 	*/
1335 	left = dst->clip_rect.x;
1336 	if (x2<left) {
1337 		return(0);
1338 	}
1339 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
1340 	if (x1>right) {
1341 		return(0);
1342 	}
1343 	top = dst->clip_rect.y;
1344 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1345 	if ((y<top) || (y>bottom)) {
1346 		return (0);
1347 	}
1348 
1349 	/*
1350 	* Clip x
1351 	*/
1352 	if (x1 < left) {
1353 		x1 = left;
1354 	}
1355 	if (x2 > right) {
1356 		x2 = right;
1357 	}
1358 
1359 	/*
1360 	* Calculate width
1361 	*/
1362 	w = x2 - x1;
1363 
1364 	/*
1365 	* Lock the surface
1366 	*/
1367 	if (RSDL_MUSTLOCK(dst)) {
1368 		if (RSDL_LockSurface(dst) < 0) {
1369 			return (-1);
1370 		}
1371 	}
1372 
1373 	/*
1374 	* More variable setup
1375 	*/
1376 	dx = w;
1377 	pixx = dst->format->BytesPerPixel;
1378 	pixy = dst->pitch;
1379 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
1380 
1381 	/*
1382 	* Draw
1383 	*/
1384 	switch (dst->format->BytesPerPixel) {
1385 	case 1:
1386 		memset(pixel, color, dx+1);
1387 		break;
1388 	case 2:
1389 		pixellast = pixel + dx + dx;
1390 		for (; pixel <= pixellast; pixel += pixx) {
1391 			*(Uint16 *) pixel = color;
1392 		}
1393 		break;
1394 	case 3:
1395 		pixellast = pixel + dx + dx + dx;
1396 		for (; pixel <= pixellast; pixel += pixx) {
1397 			if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
1398 				pixel[0] = (color >> 16) & 0xff;
1399 				pixel[1] = (color >> 8) & 0xff;
1400 				pixel[2] = color & 0xff;
1401 			} else {
1402 				pixel[0] = color & 0xff;
1403 				pixel[1] = (color >> 8) & 0xff;
1404 				pixel[2] = (color >> 16) & 0xff;
1405 			}
1406 		}
1407 		break;
1408 	default:		/* case 4 */
1409 		dx = dx + dx;
1410 		pixellast = pixel + dx + dx;
1411 		for (; pixel <= pixellast; pixel += pixx) {
1412 			*(Uint32 *) pixel = color;
1413 		}
1414 		break;
1415 	}
1416 
1417 	/*
1418 	* Unlock surface
1419 	*/
1420 	if (RSDL_MUSTLOCK(dst)) {
1421 		RSDL_UnlockSurface(dst);
1422 	}
1423 
1424 	/*
1425 	* Set result code
1426 	*/
1427 	result = 0;
1428 
1429 	return (result);
1430 }
1431 
1432 /*!
1433 \brief Draw horizontal line without blending
1434 
1435 Just stores the color value (including the alpha component) without blending.
1436 Function should only be used for 32 bit target surfaces.
1437 
1438 \param dst The surface to draw on.
1439 \param x1 X coordinate of the first point (i.e. left) of the line.
1440 \param x2 X coordinate of the second point (i.e. right) of the line.
1441 \param y Y coordinate of the points of the line.
1442 \param r The red value of the line to draw.
1443 \param g The green value of the line to draw.
1444 \param b The blue value of the line to draw.
1445 \param a The alpha value of the line to draw.
1446 
1447 \returns Returns 0 on success, -1 on failure.
1448 */
hlineRGBAStore(RSDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1449 int hlineRGBAStore(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1450 {
1451 	/*
1452 	* Draw
1453 	*/
1454 	return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1455 }
1456 
1457 /*!
1458 \brief Draw horizontal line with blending.
1459 
1460 \param dst The surface to draw on.
1461 \param x1 X coordinate of the first point (i.e. left) of the line.
1462 \param x2 X coordinate of the second point (i.e. right) of the line.
1463 \param y Y coordinate of the points of the line.
1464 \param color The color value of the line to draw (0xRRGGBBAA).
1465 
1466 \returns Returns 0 on success, -1 on failure.
1467 */
hlineColor(RSDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)1468 int hlineColor(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
1469 {
1470 	Sint16 left, right, top, bottom;
1471 	Uint8 *pixel, *pixellast;
1472 	int dx;
1473 	int pixx, pixy;
1474 	Sint16 xtmp;
1475 	int result = -1;
1476 	Uint8 *colorptr;
1477 	Uint8 color3[3];
1478 
1479 	/*
1480 	* Check visibility of clipping rectangle
1481 	*/
1482 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1483 		return(0);
1484 	}
1485 
1486 	/*
1487 	* Swap x1, x2 if required to ensure x1<=x2
1488 	*/
1489 	if (x1 > x2) {
1490 		xtmp = x1;
1491 		x1 = x2;
1492 		x2 = xtmp;
1493 	}
1494 
1495 	/*
1496 	* Get clipping boundary and
1497 	* check visibility of hline
1498 	*/
1499 	left = dst->clip_rect.x;
1500 	if (x2<left) {
1501 		return(0);
1502 	}
1503 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
1504 	if (x1>right) {
1505 		return(0);
1506 	}
1507 	top = dst->clip_rect.y;
1508 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1509 	if ((y<top) || (y>bottom)) {
1510 		return (0);
1511 	}
1512 
1513 	/*
1514 	* Clip x
1515 	*/
1516 	if (x1 < left) {
1517 		x1 = left;
1518 	}
1519 	if (x2 > right) {
1520 		x2 = right;
1521 	}
1522 
1523 	/*
1524 	* Calculate width difference
1525 	*/
1526 	dx = x2 - x1;
1527 
1528 	/*
1529 	* Alpha check
1530 	*/
1531 	if ((color & 255) == 255) {
1532 
1533 		/*
1534 		* No alpha-blending required
1535 		*/
1536 
1537 		/*
1538 		* Setup color
1539 		*/
1540 		colorptr = (Uint8 *) & color;
1541 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
1542 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1543 		} else {
1544 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1545 		}
1546 
1547 		/*
1548 		* Lock the surface
1549 		*/
1550 		if (RSDL_MUSTLOCK(dst)) {
1551 			if (RSDL_LockSurface(dst) < 0) {
1552 				return (-1);
1553 			}
1554 		}
1555 
1556 		/*
1557 		* More variable setup
1558 		*/
1559 		pixx = dst->format->BytesPerPixel;
1560 		pixy = dst->pitch;
1561 		pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
1562 
1563 		/*
1564 		* Draw
1565 		*/
1566 		switch (dst->format->BytesPerPixel) {
1567 		case 1:
1568 			memset(pixel, color, dx + 1);
1569 			break;
1570 		case 2:
1571 			pixellast = pixel + dx + dx;
1572 			for (; pixel <= pixellast; pixel += pixx) {
1573 				*(Uint16 *) pixel = color;
1574 			}
1575 			break;
1576 		case 3:
1577 			pixellast = pixel + dx + dx + dx;
1578 			if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
1579 				color3[0] = (color >> 16) & 0xff;
1580 				color3[1] = (color >> 8) & 0xff;
1581 				color3[2] = color & 0xff;
1582 			} else {
1583 				color3[0] = color & 0xff;
1584 				color3[1] = (color >> 8) & 0xff;
1585 				color3[2] = (color >> 16) & 0xff;
1586 			}
1587 			for (; pixel <= pixellast; pixel += pixx) {
1588 				memcpy(pixel, color3, 3);
1589 			}
1590 			break;
1591 		default:		/* case 4 */
1592 			dx = dx + dx;
1593 			pixellast = pixel + dx + dx;
1594 			for (; pixel <= pixellast; pixel += pixx) {
1595 				*(Uint32 *) pixel = color;
1596 			}
1597 			break;
1598 		}
1599 
1600 		/*
1601 		* Unlock surface
1602 		*/
1603 		if (RSDL_MUSTLOCK(dst)) {
1604 			RSDL_UnlockSurface(dst);
1605 		}
1606 
1607 		/*
1608 		* Set result code
1609 		*/
1610 		result = 0;
1611 
1612 	} else {
1613 
1614 		/*
1615 		* Alpha blending blit
1616 		*/
1617 		result = _HLineAlpha(dst, x1, x1 + dx, y, color);
1618 	}
1619 
1620 	return (result);
1621 }
1622 
1623 /*!
1624 \brief Draw horizontal line with blending.
1625 
1626 \param dst The surface to draw on.
1627 \param x1 X coordinate of the first point (i.e. left) of the line.
1628 \param x2 X coordinate of the second point (i.e. right) of the line.
1629 \param y Y coordinate of the points of the line.
1630 \param r The red value of the line to draw.
1631 \param g The green value of the line to draw.
1632 \param b The blue value of the line to draw.
1633 \param a The alpha value of the line to draw.
1634 
1635 \returns Returns 0 on success, -1 on failure.
1636 */
hlineRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1637 int hlineRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1638 {
1639 	/*
1640 	* Draw
1641 	*/
1642 	return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1643 }
1644 
1645 /*!
1646 \brief Draw vertical line with blending.
1647 
1648 \param dst The surface to draw on.
1649 \param x X coordinate of the points of the line.
1650 \param y1 Y coordinate of the first point (i.e. top) of the line.
1651 \param y2 Y coordinate of the second point (i.e. bottom) of the line.
1652 \param color The color value of the line to draw (0xRRGGBBAA).
1653 
1654 \returns Returns 0 on success, -1 on failure.
1655 */
vlineColor(RSDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)1656 int vlineColor(RSDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
1657 {
1658 	Sint16 left, right, top, bottom;
1659 	Uint8 *pixel, *pixellast;
1660 	int dy;
1661 	int pixx, pixy;
1662 	Sint16 h;
1663 	Sint16 ytmp;
1664 	int result = -1;
1665 	Uint8 *colorptr;
1666 
1667 	/*
1668 	* Check visibility of clipping rectangle
1669 	*/
1670 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1671 		return(0);
1672 	}
1673 
1674 	/*
1675 	* Swap y1, y2 if required to ensure y1<=y2
1676 	*/
1677 	if (y1 > y2) {
1678 		ytmp = y1;
1679 		y1 = y2;
1680 		y2 = ytmp;
1681 	}
1682 
1683 	/*
1684 	* Get clipping boundary and
1685 	* check visibility of vline
1686 	*/
1687 	left = dst->clip_rect.x;
1688 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
1689 	if ((x<left) || (x>right)) {
1690 		return (0);
1691 	}
1692 	top = dst->clip_rect.y;
1693 	if (y2<top) {
1694 		return(0);
1695 	}
1696 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1697 	if (y1>bottom) {
1698 		return(0);
1699 	}
1700 
1701 	/*
1702 	* Clip x
1703 	*/
1704 	if (y1 < top) {
1705 		y1 = top;
1706 	}
1707 	if (y2 > bottom) {
1708 		y2 = bottom;
1709 	}
1710 
1711 	/*
1712 	* Calculate height
1713 	*/
1714 	h = y2 - y1;
1715 
1716 	/*
1717 	* Alpha check
1718 	*/
1719 	if ((color & 255) == 255) {
1720 
1721 		/*
1722 		* No alpha-blending required
1723 		*/
1724 
1725 		/*
1726 		* Setup color
1727 		*/
1728 		colorptr = (Uint8 *) & color;
1729 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
1730 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1731 		} else {
1732 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1733 		}
1734 
1735 		/*
1736 		* Lock the surface
1737 		*/
1738 		if (RSDL_MUSTLOCK(dst)) {
1739 			if (RSDL_LockSurface(dst) < 0) {
1740 				return (-1);
1741 			}
1742 		}
1743 
1744 		/*
1745 		* More variable setup
1746 		*/
1747 		dy = h;
1748 		pixx = dst->format->BytesPerPixel;
1749 		pixy = dst->pitch;
1750 		pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
1751 		pixellast = pixel + pixy * dy;
1752 
1753 		/*
1754 		* Draw
1755 		*/
1756 		switch (dst->format->BytesPerPixel) {
1757 		case 1:
1758 			for (; pixel <= pixellast; pixel += pixy) {
1759 				*(Uint8 *) pixel = color;
1760 			}
1761 			break;
1762 		case 2:
1763 			for (; pixel <= pixellast; pixel += pixy) {
1764 				*(Uint16 *) pixel = color;
1765 			}
1766 			break;
1767 		case 3:
1768 			for (; pixel <= pixellast; pixel += pixy) {
1769 				if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
1770 					pixel[0] = (color >> 16) & 0xff;
1771 					pixel[1] = (color >> 8) & 0xff;
1772 					pixel[2] = color & 0xff;
1773 				} else {
1774 					pixel[0] = color & 0xff;
1775 					pixel[1] = (color >> 8) & 0xff;
1776 					pixel[2] = (color >> 16) & 0xff;
1777 				}
1778 			}
1779 			break;
1780 		default:		/* case 4 */
1781 			for (; pixel <= pixellast; pixel += pixy) {
1782 				*(Uint32 *) pixel = color;
1783 			}
1784 			break;
1785 		}
1786 
1787 		/* Unlock surface */
1788 		if (RSDL_MUSTLOCK(dst)) {
1789 			RSDL_UnlockSurface(dst);
1790 		}
1791 
1792 		/*
1793 		* Set result code
1794 		*/
1795 		result = 0;
1796 
1797 	} else {
1798 
1799 		/*
1800 		* Alpha blending blit
1801 		*/
1802 
1803 		result = _VLineAlpha(dst, x, y1, y1 + h, color);
1804 
1805 	}
1806 
1807 	return (result);
1808 }
1809 
1810 /*!
1811 \brief Draw vertical line with blending.
1812 
1813 \param dst The surface to draw on.
1814 \param x X coordinate of the points of the line.
1815 \param y1 Y coordinate of the first point (i.e. top) of the line.
1816 \param y2 Y coordinate of the second point (i.e. bottom) of the line.
1817 \param r The red value of the line to draw.
1818 \param g The green value of the line to draw.
1819 \param b The blue value of the line to draw.
1820 \param a The alpha value of the line to draw.
1821 
1822 \returns Returns 0 on success, -1 on failure.
1823 */
vlineRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1824 int vlineRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1825 {
1826 	/*
1827 	* Draw
1828 	*/
1829 	return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1830 }
1831 
1832 /*!
1833 \brief Draw rectangle with blending.
1834 
1835 \param dst The surface to draw on.
1836 \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
1837 \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
1838 \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
1839 \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
1840 \param color The color value of the rectangle to draw (0xRRGGBBAA).
1841 
1842 \returns Returns 0 on success, -1 on failure.
1843 */
rectangleColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1844 int rectangleColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1845 {
1846 	int result;
1847 	Sint16 tmp;
1848 
1849 	/* Check destination surface */
1850 	if (dst == NULL)
1851 	{
1852 		return -1;
1853 	}
1854 
1855 	/*
1856 	* Check visibility of clipping rectangle
1857 	*/
1858 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1859 		return 0;
1860 	}
1861 
1862 	/*
1863 	* Test for special cases of straight lines or single point
1864 	*/
1865 	if (x1 == x2) {
1866 		if (y1 == y2) {
1867 			return (pixelColor(dst, x1, y1, color));
1868 		} else {
1869 			return (vlineColor(dst, x1, y1, y2, color));
1870 		}
1871 	} else {
1872 		if (y1 == y2) {
1873 			return (hlineColor(dst, x1, x2, y1, color));
1874 		}
1875 	}
1876 
1877 	/*
1878 	* Swap x1, x2 if required
1879 	*/
1880 	if (x1 > x2) {
1881 		tmp = x1;
1882 		x1 = x2;
1883 		x2 = tmp;
1884 	}
1885 
1886 	/*
1887 	* Swap y1, y2 if required
1888 	*/
1889 	if (y1 > y2) {
1890 		tmp = y1;
1891 		y1 = y2;
1892 		y2 = tmp;
1893 	}
1894 
1895 	/*
1896 	* Draw rectangle
1897 	*/
1898 	result = 0;
1899 	result |= hlineColor(dst, x1, x2, y1, color);
1900 	result |= hlineColor(dst, x1, x2, y2, color);
1901 	y1 += 1;
1902 	y2 -= 1;
1903 	if (y1 <= y2) {
1904 		result |= vlineColor(dst, x1, y1, y2, color);
1905 		result |= vlineColor(dst, x2, y1, y2, color);
1906 	}
1907 
1908 	return (result);
1909 
1910 }
1911 
1912 /*!
1913 \brief Draw rectangle with blending.
1914 
1915 \param dst The surface to draw on.
1916 \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
1917 \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
1918 \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
1919 \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
1920 \param r The red value of the rectangle to draw.
1921 \param g The green value of the rectangle to draw.
1922 \param b The blue value of the rectangle to draw.
1923 \param a The alpha value of the rectangle to draw.
1924 
1925 \returns Returns 0 on success, -1 on failure.
1926 */
rectangleRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1927 int rectangleRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1928 {
1929 	/*
1930 	* Draw
1931 	*/
1932 	return (rectangleColor
1933 		(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1934 }
1935 
1936 /*!
1937 \brief Draw rounded-corner rectangle with blending.
1938 
1939 \param dst The surface to draw on.
1940 \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
1941 \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
1942 \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
1943 \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
1944 \param rad The radius of the corner arc.
1945 \param color The color value of the rectangle to draw (0xRRGGBBAA).
1946 
1947 \returns Returns 0 on success, -1 on failure.
1948 */
roundedRectangleColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 rad,Uint32 color)1949 int roundedRectangleColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
1950 {
1951 	int result;
1952 	Sint16 w, h, tmp;
1953 	Sint16 xx1, xx2, yy1, yy2;
1954 
1955 	/*
1956 	* Check destination surface
1957 	*/
1958 	if (dst == NULL)
1959 	{
1960 		return -1;
1961 	}
1962 
1963 	/*
1964 	* Check radius vor valid range
1965 	*/
1966 	if (rad < 0) {
1967 		return -1;
1968 	}
1969 
1970 	/*
1971 	* Special case - no rounding
1972 	*/
1973 	if (rad == 0) {
1974 		return rectangleColor(dst, x1, y1, x2, y2, color);
1975 	}
1976 
1977 	/*
1978 	* Check visibility of clipping rectangle
1979 	*/
1980 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1981 		return 0;
1982 	}
1983 
1984 	/*
1985 	* Test for special cases of straight lines or single point
1986 	*/
1987 	if (x1 == x2) {
1988 		if (y1 == y2) {
1989 			return (pixelColor(dst, x1, y1, color));
1990 		} else {
1991 			return (vlineColor(dst, x1, y1, y2, color));
1992 		}
1993 	} else {
1994 		if (y1 == y2) {
1995 			return (hlineColor(dst, x1, x2, y1, color));
1996 		}
1997 	}
1998 
1999 	/*
2000 	* Swap x1, x2 if required
2001 	*/
2002 	if (x1 > x2) {
2003 		tmp = x1;
2004 		x1 = x2;
2005 		x2 = tmp;
2006 	}
2007 
2008 	/*
2009 	* Swap y1, y2 if required
2010 	*/
2011 	if (y1 > y2) {
2012 		tmp = y1;
2013 		y1 = y2;
2014 		y2 = tmp;
2015 	}
2016 
2017 	/*
2018 	* Calculate width&height
2019 	*/
2020 	w = x2 - x1;
2021 	h = y2 - y1;
2022 
2023 	/*
2024 	* Maybe adjust radius
2025 	*/
2026 	if ((rad * 2) > w)
2027 	{
2028 		rad = w / 2;
2029 	}
2030 	if ((rad * 2) > h)
2031 	{
2032 		rad = h / 2;
2033 	}
2034 
2035 	/*
2036 	* Draw corners
2037 	*/
2038 	result = 0;
2039 	xx1 = x1 + rad;
2040 	xx2 = x2 - rad;
2041 	yy1 = y1 + rad;
2042 	yy2 = y2 - rad;
2043 	result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
2044 	result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
2045 	result |= arcColor(dst, xx1, yy2, rad,  90, 180, color);
2046 	result |= arcColor(dst, xx2, yy2, rad,   0,  90, color);
2047 
2048 	/*
2049 	* Draw lines
2050 	*/
2051 	if (xx1 <= xx2) {
2052 		result |= hlineColor(dst, xx1, xx2, y1, color);
2053 		result |= hlineColor(dst, xx1, xx2, y2, color);
2054 	}
2055 	if (yy1 <= yy2) {
2056 		result |= vlineColor(dst, x1, yy1, yy2, color);
2057 		result |= vlineColor(dst, x2, yy1, yy2, color);
2058 	}
2059 
2060 	return result;
2061 }
2062 
2063 /*!
2064 \brief Draw rounded-corner rectangle with blending.
2065 
2066 \param dst The surface to draw on.
2067 \param x1 X coordinate of the first point (i.e. top right) of the rectangle.
2068 \param y1 Y coordinate of the first point (i.e. top right) of the rectangle.
2069 \param x2 X coordinate of the second point (i.e. bottom left) of the rectangle.
2070 \param y2 Y coordinate of the second point (i.e. bottom left) of the rectangle.
2071 \param rad The radius of the corner arc.
2072 \param r The red value of the rectangle to draw.
2073 \param g The green value of the rectangle to draw.
2074 \param b The blue value of the rectangle to draw.
2075 \param a The alpha value of the rectangle to draw.
2076 
2077 \returns Returns 0 on success, -1 on failure.
2078 */
roundedRectangleRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2079 int roundedRectangleRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2080 {
2081 	/*
2082 	* Draw
2083 	*/
2084 	return (roundedRectangleColor
2085 		(dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2086 }
2087 
2088 /*!
2089 \brief Draw rounded-corner box (filled rectangle) with blending.
2090 
2091 \param dst The surface to draw on.
2092 \param x1 X coordinate of the first point (i.e. top right) of the box.
2093 \param y1 Y coordinate of the first point (i.e. top right) of the box.
2094 \param x2 X coordinate of the second point (i.e. bottom left) of the box.
2095 \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
2096 \param rad The radius of the corner arcs of the box.
2097 \param color The color value of the box to draw (0xRRGGBBAA).
2098 
2099 \returns Returns 0 on success, -1 on failure.
2100 */
roundedBoxColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 rad,Uint32 color)2101 int roundedBoxColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
2102 {
2103 	int result;
2104 	Sint16 w, h, tmp;
2105 	Sint16 xx1, xx2, yy1, yy2;
2106 
2107 	/*
2108 	* Check destination surface
2109 	*/
2110 	if (dst == NULL)
2111 	{
2112 		return -1;
2113 	}
2114 
2115 	/*
2116 	* Check radius vor valid range
2117 	*/
2118 	if (rad < 0) {
2119 		return -1;
2120 	}
2121 
2122 	/*
2123 	* Special case - no rounding
2124 	*/
2125 	if (rad == 0) {
2126 		return rectangleColor(dst, x1, y1, x2, y2, color);
2127 	}
2128 
2129 	/*
2130 	* Check visibility of clipping rectangle
2131 	*/
2132 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2133 		return 0;
2134 	}
2135 
2136 	/*
2137 	* Test for special cases of straight lines or single point
2138 	*/
2139 	if (x1 == x2) {
2140 		if (y1 == y2) {
2141 			return (pixelColor(dst, x1, y1, color));
2142 		} else {
2143 			return (vlineColor(dst, x1, y1, y2, color));
2144 		}
2145 	} else {
2146 		if (y1 == y2) {
2147 			return (hlineColor(dst, x1, x2, y1, color));
2148 		}
2149 	}
2150 
2151 	/*
2152 	* Swap x1, x2 if required
2153 	*/
2154 	if (x1 > x2) {
2155 		tmp = x1;
2156 		x1 = x2;
2157 		x2 = tmp;
2158 	}
2159 
2160 	/*
2161 	* Swap y1, y2 if required
2162 	*/
2163 	if (y1 > y2) {
2164 		tmp = y1;
2165 		y1 = y2;
2166 		y2 = tmp;
2167 	}
2168 
2169 	/*
2170 	* Calculate width&height
2171 	*/
2172 	w = x2 - x1;
2173 	h = y2 - y1;
2174 
2175 	/*
2176 	* Maybe adjust radius
2177 	*/
2178 	if ((rad * 2) > w)
2179 	{
2180 		rad = w / 2;
2181 	}
2182 	if ((rad * 2) > h)
2183 	{
2184 		rad = h / 2;
2185 	}
2186 
2187 	/*
2188 	* Draw corners
2189 	*/
2190 	result = 0;
2191 	xx1 = x1 + rad;
2192 	xx2 = x2 - rad;
2193 	yy1 = y1 + rad;
2194 	yy2 = y2 - rad;
2195 	result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
2196 	result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
2197 	result |= filledPieColor(dst, xx1, yy2, rad,  90, 180, color);
2198 	result |= filledPieColor(dst, xx2, yy2, rad,   0,  90, color);
2199 
2200 	/*
2201 	* Draw body
2202 	*/
2203 	xx1++;
2204 	xx2--;
2205 	yy1++;
2206 	yy2--;
2207 	if (xx1 <= xx2) {
2208 		result |= boxColor(dst, xx1, y1, xx2, y2, color);
2209 	}
2210 	if (yy1 <= yy2) {
2211 		result |= boxColor(dst, x1, yy1, xx1-1, yy2, color);
2212 		result |= boxColor(dst, xx2+1, yy1, x2, yy2, color);
2213 	}
2214 
2215 	return result;
2216 }
2217 
2218 /*!
2219 \brief Draw rounded-corner box (filled rectangle) with blending.
2220 
2221 \param dst The surface to draw on.
2222 \param x1 X coordinate of the first point (i.e. top right) of the box.
2223 \param y1 Y coordinate of the first point (i.e. top right) of the box.
2224 \param x2 X coordinate of the second point (i.e. bottom left) of the box.
2225 \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
2226 \param rad The radius of the corner arcs of the box.
2227 \param r The red value of the box to draw.
2228 \param g The green value of the box to draw.
2229 \param b The blue value of the box to draw.
2230 \param a The alpha value of the box to draw.
2231 
2232 \returns Returns 0 on success, -1 on failure.
2233 */
roundedBoxRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2234 int roundedBoxRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2,
2235 	Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2236 {
2237 	/*
2238 	* Draw
2239 	*/
2240 	return (roundedBoxColor
2241 		(dst, x1, y1, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2242 }
2243 
2244 /* --------- Clipping routines for line */
2245 
2246 /* Clipping based heavily on code from                       */
2247 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
2248 
2249 #define CLIP_LEFT_EDGE   0x1
2250 #define CLIP_RIGHT_EDGE  0x2
2251 #define CLIP_BOTTOM_EDGE 0x4
2252 #define CLIP_TOP_EDGE    0x8
2253 #define CLIP_INSIDE(a)   (!a)
2254 #define CLIP_REJECT(a,b) (a&b)
2255 #define CLIP_ACCEPT(a,b) (!(a|b))
2256 
2257 /*!
2258 \brief Internal clip-encoding routine.
2259 
2260 Calculates a segement-based clipping encoding for a point against a rectangle.
2261 
2262 \param x X coordinate of point.
2263 \param y Y coordinate of point.
2264 \param left X coordinate of left edge of the rectangle.
2265 \param top Y coordinate of top edge of the rectangle.
2266 \param right X coordinate of right edge of the rectangle.
2267 \param bottom Y coordinate of bottom edge of the rectangle.
2268 */
_clipEncode(Sint16 x,Sint16 y,Sint16 left,Sint16 top,Sint16 right,Sint16 bottom)2269 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
2270 {
2271 	int code = 0;
2272 
2273 	if (x < left) {
2274 		code |= CLIP_LEFT_EDGE;
2275 	} else if (x > right) {
2276 		code |= CLIP_RIGHT_EDGE;
2277 	}
2278 	if (y < top) {
2279 		code |= CLIP_TOP_EDGE;
2280 	} else if (y > bottom) {
2281 		code |= CLIP_BOTTOM_EDGE;
2282 	}
2283 	return code;
2284 }
2285 
2286 /*!
2287 \brief Clip line to a the clipping rectangle of a surface.
2288 
2289 \param dst Target surface to draw on.
2290 \param x1 Pointer to X coordinate of first point of line.
2291 \param y1 Pointer to Y coordinate of first point of line.
2292 \param x2 Pointer to X coordinate of second point of line.
2293 \param y2 Pointer to Y coordinate of second point of line.
2294 */
_clipLine(RSDL_Surface * dst,Sint16 * x1,Sint16 * y1,Sint16 * x2,Sint16 * y2)2295 static int _clipLine(RSDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
2296 {
2297 	Sint16 left, right, top, bottom;
2298 	int code1, code2;
2299 	int draw = 0;
2300 	Sint16 swaptmp;
2301 	float m;
2302 
2303 	/*
2304 	* Get clipping boundary
2305 	*/
2306 	left = dst->clip_rect.x;
2307 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
2308 	top = dst->clip_rect.y;
2309 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2310 
2311 	while (1) {
2312 		code1 = _clipEncode(*x1, *y1, left, top, right, bottom);
2313 		code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
2314 		if (CLIP_ACCEPT(code1, code2)) {
2315 			draw = 1;
2316 			break;
2317 		} else if (CLIP_REJECT(code1, code2))
2318 			break;
2319 		else {
2320 			if (CLIP_INSIDE(code1)) {
2321 				swaptmp = *x2;
2322 				*x2 = *x1;
2323 				*x1 = swaptmp;
2324 				swaptmp = *y2;
2325 				*y2 = *y1;
2326 				*y1 = swaptmp;
2327 				swaptmp = code2;
2328 				code2 = code1;
2329 				code1 = swaptmp;
2330 			}
2331 			if (*x2 != *x1) {
2332 				m = (float)(*y2 - *y1) / (float)(*x2 - *x1);
2333 			} else {
2334 				m = 1.0f;
2335 			}
2336 			if (code1 & CLIP_LEFT_EDGE) {
2337 				*y1 += (Sint16) ((left - *x1) * m);
2338 				*x1 = left;
2339 			} else if (code1 & CLIP_RIGHT_EDGE) {
2340 				*y1 += (Sint16) ((right - *x1) * m);
2341 				*x1 = right;
2342 			} else if (code1 & CLIP_BOTTOM_EDGE) {
2343 				if (*x2 != *x1) {
2344 					*x1 += (Sint16) ((bottom - *y1) / m);
2345 				}
2346 				*y1 = bottom;
2347 			} else if (code1 & CLIP_TOP_EDGE) {
2348 				if (*x2 != *x1) {
2349 					*x1 += (Sint16) ((top - *y1) / m);
2350 				}
2351 				*y1 = top;
2352 			}
2353 		}
2354 	}
2355 
2356 	return draw;
2357 }
2358 
2359 /*!
2360 \brief Draw box (filled rectangle) with blending.
2361 
2362 \param dst The surface to draw on.
2363 \param x1 X coordinate of the first point (i.e. top right) of the box.
2364 \param y1 Y coordinate of the first point (i.e. top right) of the box.
2365 \param x2 X coordinate of the second point (i.e. bottom left) of the box.
2366 \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
2367 \param color The color value of the box to draw (0xRRGGBBAA).
2368 
2369 \returns Returns 0 on success, -1 on failure.
2370 */
boxColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)2371 int boxColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
2372 {
2373 	Sint16 left, right, top, bottom;
2374 	Uint8 *pixel, *pixellast;
2375 	int x, dx;
2376 	int dy;
2377 	int pixx, pixy;
2378 	Sint16 w, h, tmp;
2379 	int result;
2380 	Uint8 *colorptr;
2381 
2382 	/*
2383 	* Check visibility of clipping rectangle
2384 	*/
2385 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2386 		return(0);
2387 	}
2388 
2389 	/*
2390 	* Order coordinates to ensure that
2391 	* x1<=x2 and y1<=y2
2392 	*/
2393 	if (x1 > x2) {
2394 		tmp = x1;
2395 		x1 = x2;
2396 		x2 = tmp;
2397 	}
2398 	if (y1 > y2) {
2399 		tmp = y1;
2400 		y1 = y2;
2401 		y2 = tmp;
2402 	}
2403 
2404 	/*
2405 	* Get clipping boundary and
2406 	* check visibility
2407 	*/
2408 	left = dst->clip_rect.x;
2409 	if (x2<left) {
2410 		return(0);
2411 	}
2412 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
2413 	if (x1>right) {
2414 		return(0);
2415 	}
2416 	top = dst->clip_rect.y;
2417 	if (y2<top) {
2418 		return(0);
2419 	}
2420 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2421 	if (y1>bottom) {
2422 		return(0);
2423 	}
2424 
2425 	/* Clip all points */
2426 	if (x1<left) {
2427 		x1=left;
2428 	} else if (x1>right) {
2429 		x1=right;
2430 	}
2431 	if (x2<left) {
2432 		x2=left;
2433 	} else if (x2>right) {
2434 		x2=right;
2435 	}
2436 	if (y1<top) {
2437 		y1=top;
2438 	} else if (y1>bottom) {
2439 		y1=bottom;
2440 	}
2441 	if (y2<top) {
2442 		y2=top;
2443 	} else if (y2>bottom) {
2444 		y2=bottom;
2445 	}
2446 
2447 	/*
2448 	* Test for special cases of straight line or single point
2449 	*/
2450 	if (x1 == x2) {
2451 		if (y1 == y2) {
2452 			return (pixelColor(dst, x1, y1, color));
2453 		} else {
2454 			return (vlineColor(dst, x1, y1, y2, color));
2455 		}
2456 	}
2457 	if (y1 == y2) {
2458 		return (hlineColor(dst, x1, x2, y1, color));
2459 	}
2460 
2461 	/*
2462 	* Calculate width&height
2463 	*/
2464 	w = x2 - x1;
2465 	h = y2 - y1;
2466 
2467 	/*
2468 	* Alpha check
2469 	*/
2470 	if ((color & 255) == 255) {
2471 
2472 		/*
2473 		* No alpha-blending required
2474 		*/
2475 
2476 		/*
2477 		* Setup color
2478 		*/
2479 		colorptr = (Uint8 *) & color;
2480 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
2481 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2482 		} else {
2483 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2484 		}
2485 
2486 		/*
2487 		* Lock the surface
2488 		*/
2489 		if (RSDL_MUSTLOCK(dst)) {
2490 			if (RSDL_LockSurface(dst) < 0) {
2491 				return (-1);
2492 			}
2493 		}
2494 
2495 		/*
2496 		* More variable setup
2497 		*/
2498 		dx = w;
2499 		dy = h;
2500 		pixx = dst->format->BytesPerPixel;
2501 		pixy = dst->pitch;
2502 		pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
2503 		pixellast = pixel + pixx * dx + pixy * dy;
2504 		dx++;
2505 
2506 		/*
2507 		* Draw
2508 		*/
2509 		switch (dst->format->BytesPerPixel) {
2510 		case 1:
2511 			for (; pixel <= pixellast; pixel += pixy) {
2512 				memset(pixel, (Uint8) color, dx);
2513 			}
2514 			break;
2515 		case 2:
2516 			pixy -= (pixx * dx);
2517 			for (; pixel <= pixellast; pixel += pixy) {
2518 				for (x = 0; x < dx; x++) {
2519 					*(Uint16*) pixel = color;
2520 					pixel += pixx;
2521 				}
2522 			}
2523 			break;
2524 		case 3:
2525 			pixy -= (pixx * dx);
2526 			for (; pixel <= pixellast; pixel += pixy) {
2527 				for (x = 0; x < dx; x++) {
2528 					if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
2529 						pixel[0] = (color >> 16) & 0xff;
2530 						pixel[1] = (color >> 8) & 0xff;
2531 						pixel[2] = color & 0xff;
2532 					} else {
2533 						pixel[0] = color & 0xff;
2534 						pixel[1] = (color >> 8) & 0xff;
2535 						pixel[2] = (color >> 16) & 0xff;
2536 					}
2537 					pixel += pixx;
2538 				}
2539 			}
2540 			break;
2541 		default:		/* case 4 */
2542 			pixy -= (pixx * dx);
2543 			for (; pixel <= pixellast; pixel += pixy) {
2544 				for (x = 0; x < dx; x++) {
2545 					*(Uint32 *) pixel = color;
2546 					pixel += pixx;
2547 				}
2548 			}
2549 			break;
2550 		}
2551 
2552 		/* Unlock surface */
2553 		if (RSDL_MUSTLOCK(dst)) {
2554 			RSDL_UnlockSurface(dst);
2555 		}
2556 
2557 		result = 0;
2558 
2559 	} else {
2560 
2561 		result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
2562 
2563 	}
2564 
2565 	return (result);
2566 }
2567 
2568 /*!
2569 \brief Draw box (filled rectangle) with blending.
2570 
2571 \param dst The surface to draw on.
2572 \param x1 X coordinate of the first point (i.e. top right) of the box.
2573 \param y1 Y coordinate of the first point (i.e. top right) of the box.
2574 \param x2 X coordinate of the second point (i.e. bottom left) of the box.
2575 \param y2 Y coordinate of the second point (i.e. bottom left) of the box.
2576 \param r The red value of the box to draw.
2577 \param g The green value of the box to draw.
2578 \param b The blue value of the box to draw.
2579 \param a The alpha value of the box to draw.
2580 
2581 \returns Returns 0 on success, -1 on failure.
2582 */
boxRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2583 int boxRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2584 {
2585 	/*
2586 	* Draw
2587 	*/
2588 	return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2589 }
2590 
2591 /* ----- Line */
2592 
2593 /* Non-alpha line drawing code adapted from routine          */
2594 /* by Pete Shinners, pete@shinners.org                       */
2595 /* Originally from pygame, http://pygame.seul.org            */
2596 
2597 #define ABS(a) (((a)<0) ? -(a) : (a))
2598 
2599 /*!
2600 \brief Draw line with alpha blending.
2601 
2602 \param dst The surface to draw on.
2603 \param x1 X coordinate of the first point of the line.
2604 \param y1 Y coordinate of the first point of the line.
2605 \param x2 X coordinate of the second point of the line.
2606 \param y2 Y coordinate of the second point of the line.
2607 \param color The color value of the line to draw (0xRRGGBBAA).
2608 
2609 \returns Returns 0 on success, -1 on failure.
2610 */
lineColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)2611 int lineColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
2612 {
2613 	int pixx, pixy;
2614 	int x, y;
2615 	int dx, dy;
2616 	int ax, ay;
2617 	int sx, sy;
2618 	int swaptmp;
2619 	Uint8 *pixel;
2620 	Uint8 *colorptr;
2621 
2622 	/*
2623 	* Clip line and test if we have to draw
2624 	*/
2625 	if (!(_clipLine(dst, &x1, &y1, &x2, &y2))) {
2626 		return (0);
2627 	}
2628 
2629 	/*
2630 	* Test for special cases of straight lines or single point
2631 	*/
2632 	if (x1 == x2) {
2633 		if (y1 < y2) {
2634 			return (vlineColor(dst, x1, y1, y2, color));
2635 		} else if (y1 > y2) {
2636 			return (vlineColor(dst, x1, y2, y1, color));
2637 		} else {
2638 			return (pixelColor(dst, x1, y1, color));
2639 		}
2640 	}
2641 	if (y1 == y2) {
2642 		if (x1 < x2) {
2643 			return (hlineColor(dst, x1, x2, y1, color));
2644 		} else if (x1 > x2) {
2645 			return (hlineColor(dst, x2, x1, y1, color));
2646 		}
2647 	}
2648 
2649 	/*
2650 	* Variable setup
2651 	*/
2652 	dx = x2 - x1;
2653 	dy = y2 - y1;
2654 	sx = (dx >= 0) ? 1 : -1;
2655 	sy = (dy >= 0) ? 1 : -1;
2656 
2657 	/* Lock surface */
2658 	if (RSDL_MUSTLOCK(dst)) {
2659 		if (RSDL_LockSurface(dst) < 0) {
2660 			return (-1);
2661 		}
2662 	}
2663 
2664 	/*
2665 	* Check for alpha blending
2666 	*/
2667 	if ((color & 255) == 255) {
2668 
2669 		/*
2670 		* No alpha blending - use fast pixel routines
2671 		*/
2672 
2673 		/*
2674 		* Setup color
2675 		*/
2676 		colorptr = (Uint8 *) & color;
2677 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
2678 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2679 		} else {
2680 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2681 		}
2682 
2683 		/*
2684 		* More variable setup
2685 		*/
2686 		dx = sx * dx + 1;
2687 		dy = sy * dy + 1;
2688 		pixx = dst->format->BytesPerPixel;
2689 		pixy = dst->pitch;
2690 		pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
2691 		pixx *= sx;
2692 		pixy *= sy;
2693 		if (dx < dy) {
2694 			swaptmp = dx;
2695 			dx = dy;
2696 			dy = swaptmp;
2697 			swaptmp = pixx;
2698 			pixx = pixy;
2699 			pixy = swaptmp;
2700 		}
2701 
2702 		/*
2703 		* Draw
2704 		*/
2705 		x = 0;
2706 		y = 0;
2707 		switch (dst->format->BytesPerPixel) {
2708 		case 1:
2709 			for (; x < dx; x++, pixel += pixx) {
2710 				*pixel = color;
2711 				y += dy;
2712 				if (y >= dx) {
2713 					y -= dx;
2714 					pixel += pixy;
2715 				}
2716 			}
2717 			break;
2718 		case 2:
2719 			for (; x < dx; x++, pixel += pixx) {
2720 				*(Uint16 *) pixel = color;
2721 				y += dy;
2722 				if (y >= dx) {
2723 					y -= dx;
2724 					pixel += pixy;
2725 				}
2726 			}
2727 			break;
2728 		case 3:
2729 			for (; x < dx; x++, pixel += pixx) {
2730 				if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
2731 					pixel[0] = (color >> 16) & 0xff;
2732 					pixel[1] = (color >> 8) & 0xff;
2733 					pixel[2] = color & 0xff;
2734 				} else {
2735 					pixel[0] = color & 0xff;
2736 					pixel[1] = (color >> 8) & 0xff;
2737 					pixel[2] = (color >> 16) & 0xff;
2738 				}
2739 				y += dy;
2740 				if (y >= dx) {
2741 					y -= dx;
2742 					pixel += pixy;
2743 				}
2744 			}
2745 			break;
2746 		default:		/* case 4 */
2747 			for (; x < dx; x++, pixel += pixx) {
2748 				*(Uint32 *) pixel = color;
2749 				y += dy;
2750 				if (y >= dx) {
2751 					y -= dx;
2752 					pixel += pixy;
2753 				}
2754 			}
2755 			break;
2756 		}
2757 
2758 	} else {
2759 
2760 		/*
2761 		* Alpha blending required - use single-pixel blits
2762 		*/
2763 
2764 		ax = ABS(dx) << 1;
2765 		ay = ABS(dy) << 1;
2766 		x = x1;
2767 		y = y1;
2768 		if (ax > ay) {
2769 			int d = ay - (ax >> 1);
2770 
2771 			while (x != x2) {
2772 				pixelColorNolock (dst, x, y, color);
2773 				if (d > 0 || (d == 0 && sx == 1)) {
2774 					y += sy;
2775 					d -= ax;
2776 				}
2777 				x += sx;
2778 				d += ay;
2779 			}
2780 		} else {
2781 			int d = ax - (ay >> 1);
2782 
2783 			while (y != y2) {
2784 				pixelColorNolock (dst, x, y, color);
2785 				if (d > 0 || ((d == 0) && (sy == 1))) {
2786 					x += sx;
2787 					d -= ay;
2788 				}
2789 				y += sy;
2790 				d += ax;
2791 			}
2792 		}
2793 		pixelColorNolock (dst, x, y, color);
2794 
2795 	}
2796 
2797 	/* Unlock surface */
2798 	if (RSDL_MUSTLOCK(dst)) {
2799 		RSDL_UnlockSurface(dst);
2800 	}
2801 
2802 	return (0);
2803 }
2804 
2805 /*!
2806 \brief Draw line with alpha blending.
2807 
2808 \param dst The surface to draw on.
2809 \param x1 X coordinate of the first point of the line.
2810 \param y1 Y coordinate of the first point of the line.
2811 \param x2 X coordinate of the second point of the line.
2812 \param y2 Y coordinate of the second point of the line.
2813 \param r The red value of the line to draw.
2814 \param g The green value of the line to draw.
2815 \param b The blue value of the line to draw.
2816 \param a The alpha value of the line to draw.
2817 
2818 \returns Returns 0 on success, -1 on failure.
2819 */
lineRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2820 int lineRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2821 {
2822 	/*
2823 	* Draw
2824 	*/
2825 	return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2826 }
2827 
2828 /* AA Line */
2829 
2830 #define AAlevels 256
2831 #define AAbits 8
2832 
2833 /*!
2834 \brief Internal function to draw anti-aliased line with alpha blending and endpoint control.
2835 
2836 This implementation of the Wu antialiasing code is based on Mike Abrash's
2837 DDJ article which was reprinted as Chapter 42 of his Graphics Programming
2838 Black Book, but has been optimized to work with SDL and utilizes 32-bit
2839 fixed-point arithmetic by A. Schiffler. The endpoint control allows the
2840 supression to draw the last pixel useful for rendering continous aa-lines
2841 with alpha<255.
2842 
2843 \param dst The surface to draw on.
2844 \param x1 X coordinate of the first point of the aa-line.
2845 \param y1 Y coordinate of the first point of the aa-line.
2846 \param x2 X coordinate of the second point of the aa-line.
2847 \param y2 Y coordinate of the second point of the aa-line.
2848 \param color The color value of the aa-line to draw (0xRRGGBBAA).
2849 \param draw_endpoint Flag indicating if the endpoint should be drawn; draw if non-zero.
2850 
2851 \returns Returns 0 on success, -1 on failure.
2852 */
_aalineColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,int draw_endpoint)2853 int _aalineColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
2854 {
2855 	Sint32 xx0, yy0, xx1, yy1;
2856 	int result;
2857 	Uint32 intshift, erracc, erradj;
2858 	Uint32 erracctmp, wgt;
2859 	int dx, dy, tmp, xdir, y0p1, x0pxdir;
2860 
2861 	/*
2862 	* Check visibility of clipping rectangle
2863 	*/
2864 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0))
2865 		return(0);
2866 
2867 	/*
2868 	* Clip line and test if we have to draw
2869 	*/
2870 	if (!(_clipLine(dst, &x1, &y1, &x2, &y2)))
2871 		return (0);
2872 
2873 	/*
2874 	* Keep on working with 32bit numbers
2875 	*/
2876 	xx0 = x1;
2877 	yy0 = y1;
2878 	xx1 = x2;
2879 	yy1 = y2;
2880 
2881 	/*
2882 	* Reorder points if required
2883 	*/
2884 	if (yy0 > yy1)
2885    {
2886 		tmp = yy0;
2887 		yy0 = yy1;
2888 		yy1 = tmp;
2889 		tmp = xx0;
2890 		xx0 = xx1;
2891 		xx1 = tmp;
2892 	}
2893 
2894 	/*
2895 	* Calculate distance
2896 	*/
2897 	dx = xx1 - xx0;
2898 	dy = yy1 - yy0;
2899 
2900 	/*
2901 	* Check for special cases
2902 	*/
2903 	if (dx == 0)
2904    {
2905       /*
2906        * Vertical line
2907        */
2908       if (draw_endpoint)
2909          return (vlineColor(dst, x1, y1, y2, color));
2910 
2911       if (dy>0)
2912          return (vlineColor(dst, x1, yy0, yy0+dy, color));
2913       return (pixelColor(dst, x1, y1, color));
2914    }
2915    else if (dy == 0)
2916    {
2917       /*
2918        * Horizontal line
2919        */
2920       if (draw_endpoint)
2921          return (hlineColor(dst, x1, x2, y1, color));
2922       if (dx!=0)
2923          return (hlineColor(dst, xx0, xx0+dx, y1, color));
2924       return (pixelColor(dst, x1, y1, color));
2925    } else if ((dx == dy) && (draw_endpoint))
2926 		/*
2927 		* Diagonal line (with endpoint)
2928 		*/
2929 		return (lineColor(dst, x1, y1, x2, y2, color));
2930 
2931 	/*
2932 	* Adjust for negative dx and set xdir
2933 	*/
2934 	if (dx >= 0)
2935 		xdir = 1;
2936    else
2937    {
2938       xdir = -1;
2939       dx = (-dx);
2940    }
2941 
2942 	/*
2943 	* Line is not horizontal, vertical or diagonal (with endpoint)
2944 	*/
2945 	result = 0;
2946 
2947 	/*
2948 	* Zero accumulator
2949 	*/
2950 	erracc = 0;
2951 
2952 	/*
2953 	* # of bits by which to shift erracc to get intensity level
2954 	*/
2955 	intshift = 32 - AAbits;
2956 
2957 	/* Lock surface */
2958 	if (RSDL_MUSTLOCK(dst))
2959 		if (RSDL_LockSurface(dst) < 0)
2960 			return (-1);
2961 
2962 	/*
2963 	* Draw the initial pixel in the foreground color
2964 	*/
2965 	result |= pixelColorNolock(dst, x1, y1, color);
2966 
2967 	/*
2968 	* x-major or y-major?
2969 	*/
2970 	if (dy > dx)
2971    {
2972 		/*
2973 		* y-major.  Calculate 16-bit fixed point fractional part of a pixel that
2974 		* X advances every time Y advances 1 pixel, truncating the result so that
2975 		* we won't overrun the endpoint along the X axis
2976 		*/
2977 		/*
2978 		* Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
2979 		*/
2980 		erradj = ((dx << 16) / dy) << 16;
2981 
2982 		/*
2983 		* draw all pixels other than the first and last
2984 		*/
2985 		x0pxdir = xx0 + xdir;
2986 		while (--dy) {
2987 			erracctmp = erracc;
2988 			erracc += erradj;
2989 			if (erracc <= erracctmp) {
2990 				/*
2991 				* rollover in error accumulator, x coord advances
2992 				*/
2993 				xx0 = x0pxdir;
2994 				x0pxdir += xdir;
2995 			}
2996 			yy0++;		/* y-major so always advance Y */
2997 
2998 			/*
2999 			* the AAbits most significant bits of erracc give us the intensity
3000 			* weighting for this pixel, and the complement of the weighting for
3001 			* the paired pixel.
3002 			*/
3003 			wgt = (erracc >> intshift) & 255;
3004 			result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
3005 			result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
3006 		}
3007 
3008 	}
3009    else
3010    {
3011 		/*
3012 		* x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
3013 		* that Y advances each time X advances 1 pixel, truncating the result so
3014 		* that we won't overrun the endpoint along the X axis.
3015 		*/
3016 		/*
3017 		* Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
3018 		*/
3019 		erradj = ((dy << 16) / dx) << 16;
3020 
3021 		/*
3022 		* draw all pixels other than the first and last
3023 		*/
3024 		y0p1 = yy0 + 1;
3025 		while (--dx) {
3026 
3027 			erracctmp = erracc;
3028 			erracc += erradj;
3029 			if (erracc <= erracctmp) {
3030 				/*
3031 				* Accumulator turned over, advance y
3032 				*/
3033 				yy0 = y0p1;
3034 				y0p1++;
3035 			}
3036 			xx0 += xdir;	/* x-major so always advance X */
3037 			/*
3038 			* the AAbits most significant bits of erracc give us the intensity
3039 			* weighting for this pixel, and the complement of the weighting for
3040 			* the paired pixel.
3041 			*/
3042 			wgt = (erracc >> intshift) & 255;
3043 			result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
3044 			result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
3045 		}
3046 	}
3047 
3048 	/*
3049 	* Do we have to draw the endpoint
3050 	*/
3051 	if (draw_endpoint)
3052 		/*
3053 		* Draw final pixel, always exactly intersected by the line and doesn't
3054 		* need to be weighted.
3055 		*/
3056 		result |= pixelColorNolock (dst, x2, y2, color);
3057 
3058 	/* Unlock surface */
3059 	if (RSDL_MUSTLOCK(dst))
3060 		RSDL_UnlockSurface(dst);
3061 
3062 	return (result);
3063 }
3064 
3065 /*!
3066 \brief Ddraw anti-aliased line with alpha blending.
3067 
3068 \param dst The surface to draw on.
3069 \param x1 X coordinate of the first point of the aa-line.
3070 \param y1 Y coordinate of the first point of the aa-line.
3071 \param x2 X coordinate of the second point of the aa-line.
3072 \param y2 Y coordinate of the second point of the aa-line.
3073 \param color The color value of the aa-line to draw (0xRRGGBBAA).
3074 
3075 \returns Returns 0 on success, -1 on failure.
3076 */
aalineColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)3077 int aalineColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
3078 {
3079 	return (_aalineColor(dst, x1, y1, x2, y2, color, 1));
3080 }
3081 
3082 /*!
3083 \brief Draw anti-aliased line with alpha blending.
3084 
3085 \param dst The surface to draw on.
3086 \param x1 X coordinate of the first point of the aa-line.
3087 \param y1 Y coordinate of the first point of the aa-line.
3088 \param x2 X coordinate of the second point of the aa-line.
3089 \param y2 Y coordinate of the second point of the aa-line.
3090 \param r The red value of the aa-line to draw.
3091 \param g The green value of the aa-line to draw.
3092 \param b The blue value of the aa-line to draw.
3093 \param a The alpha value of the aa-line to draw.
3094 
3095 \returns Returns 0 on success, -1 on failure.
3096 */
aalineRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3097 int aalineRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3098 {
3099 	return (_aalineColor
3100 		(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
3101 }
3102 
3103 
3104 /* ----- Circle */
3105 
3106 /*!
3107 \brief Draw circle with blending.
3108 
3109 Note: Circle drawing routine is based on an algorithms from the sge library,
3110 but modified by A. Schiffler for multiple pixel-draw removal and other
3111 minor speedup changes.
3112 
3113 \param dst The surface to draw on.
3114 \param x X coordinate of the center of the circle.
3115 \param y Y coordinate of the center of the circle.
3116 \param rad Radius in pixels of the circle.
3117 \param color The color value of the circle to draw (0xRRGGBBAA).
3118 
3119 \returns Returns 0 on success, -1 on failure.
3120 */
circleColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint32 color)3121 int circleColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
3122 {
3123 	Sint16 left, right, top, bottom;
3124 	int result;
3125 	Sint16 x1, y1, x2, y2;
3126 	Sint16 cx = 0;
3127 	Sint16 cy = rad;
3128 	Sint16 df = 1 - rad;
3129 	Sint16 d_e = 3;
3130 	Sint16 d_se = -2 * rad + 5;
3131 	Sint16 xpcx, xmcx, xpcy, xmcy;
3132 	Sint16 ypcy, ymcy, ypcx, ymcx;
3133 	Uint8 *colorptr;
3134 
3135 	/*
3136 	* Check visibility of clipping rectangle
3137 	*/
3138 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3139 		return(0);
3140 	}
3141 
3142 	/*
3143 	* Sanity check radius
3144 	*/
3145 	if (rad < 0) {
3146 		return (-1);
3147 	}
3148 
3149 	/*
3150 	* Special case for rad=0 - draw a point
3151 	*/
3152 	if (rad == 0) {
3153 		return (pixelColor(dst, x, y, color));
3154 	}
3155 
3156 	/*
3157 	* Get circle and clipping boundary and
3158 	* test if bounding box of circle is visible
3159 	*/
3160 	x2 = x + rad;
3161 	left = dst->clip_rect.x;
3162 	if (x2<left) {
3163 		return(0);
3164 	}
3165 	x1 = x - rad;
3166 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
3167 	if (x1>right) {
3168 		return(0);
3169 	}
3170 	y2 = y + rad;
3171 	top = dst->clip_rect.y;
3172 	if (y2<top) {
3173 		return(0);
3174 	}
3175 	y1 = y - rad;
3176 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3177 	if (y1>bottom) {
3178 		return(0);
3179 	}
3180 
3181 	/*
3182 	* Draw circle
3183 	*/
3184 	result = 0;
3185 
3186 	/* Lock surface */
3187 	if (RSDL_MUSTLOCK(dst)) {
3188 		if (RSDL_LockSurface(dst) < 0) {
3189 			return (-1);
3190 		}
3191 	}
3192 
3193 	/*
3194 	* Alpha Check
3195 	*/
3196 	if ((color & 255) == 255) {
3197 
3198 		/*
3199 		* No Alpha - direct memory writes
3200 		*/
3201 
3202 		/*
3203 		* Setup color
3204 		*/
3205 		colorptr = (Uint8 *) & color;
3206 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
3207 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
3208 		} else {
3209 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
3210 		}
3211 
3212 		/*
3213 		* Draw
3214 		*/
3215 		do {
3216 			ypcy = y + cy;
3217 			ymcy = y - cy;
3218 			if (cx > 0) {
3219 				xpcx = x + cx;
3220 				xmcx = x - cx;
3221 				result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
3222 				result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
3223 				result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
3224 				result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
3225 			} else {
3226 				result |= fastPixelColorNolock(dst, x, ymcy, color);
3227 				result |= fastPixelColorNolock(dst, x, ypcy, color);
3228 			}
3229 			xpcy = x + cy;
3230 			xmcy = x - cy;
3231 			if ((cx > 0) && (cx != cy)) {
3232 				ypcx = y + cx;
3233 				ymcx = y - cx;
3234 				result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
3235 				result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
3236 				result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
3237 				result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
3238 			} else if (cx == 0) {
3239 				result |= fastPixelColorNolock(dst, xmcy, y, color);
3240 				result |= fastPixelColorNolock(dst, xpcy, y, color);
3241 			}
3242 			/*
3243 			* Update
3244 			*/
3245 			if (df < 0) {
3246 				df += d_e;
3247 				d_e += 2;
3248 				d_se += 2;
3249 			} else {
3250 				df += d_se;
3251 				d_e += 2;
3252 				d_se += 4;
3253 				cy--;
3254 			}
3255 			cx++;
3256 		} while (cx <= cy);
3257 
3258 		/*
3259 		* Unlock surface
3260 		*/
3261 		RSDL_UnlockSurface(dst);
3262 
3263 	} else {
3264 
3265 		/*
3266 		* Using Alpha - blended pixel blits
3267 		*/
3268 
3269 		do {
3270 			/*
3271 			* Draw
3272 			*/
3273 			ypcy = y + cy;
3274 			ymcy = y - cy;
3275 			if (cx > 0) {
3276 				xpcx = x + cx;
3277 				xmcx = x - cx;
3278 				result |= pixelColorNolock (dst, xmcx, ypcy, color);
3279 				result |= pixelColorNolock (dst, xpcx, ypcy, color);
3280 				result |= pixelColorNolock (dst, xmcx, ymcy, color);
3281 				result |= pixelColorNolock (dst, xpcx, ymcy, color);
3282 			} else {
3283 				result |= pixelColorNolock (dst, x, ymcy, color);
3284 				result |= pixelColorNolock (dst, x, ypcy, color);
3285 			}
3286 			xpcy = x + cy;
3287 			xmcy = x - cy;
3288 			if ((cx > 0) && (cx != cy)) {
3289 				ypcx = y + cx;
3290 				ymcx = y - cx;
3291 				result |= pixelColorNolock (dst, xmcy, ypcx, color);
3292 				result |= pixelColorNolock (dst, xpcy, ypcx, color);
3293 				result |= pixelColorNolock (dst, xmcy, ymcx, color);
3294 				result |= pixelColorNolock (dst, xpcy, ymcx, color);
3295 			} else if (cx == 0) {
3296 				result |= pixelColorNolock (dst, xmcy, y, color);
3297 				result |= pixelColorNolock (dst, xpcy, y, color);
3298 			}
3299 			/*
3300 			* Update
3301 			*/
3302 			if (df < 0) {
3303 				df += d_e;
3304 				d_e += 2;
3305 				d_se += 2;
3306 			} else {
3307 				df += d_se;
3308 				d_e += 2;
3309 				d_se += 4;
3310 				cy--;
3311 			}
3312 			cx++;
3313 		} while (cx <= cy);
3314 
3315 	}				/* Alpha check */
3316 
3317 	/* Unlock surface */
3318 	if (RSDL_MUSTLOCK(dst)) {
3319 		RSDL_UnlockSurface(dst);
3320 	}
3321 
3322 	return (result);
3323 }
3324 
3325 /*!
3326 \brief Draw circle with blending.
3327 
3328 \param dst The surface to draw on.
3329 \param x X coordinate of the center of the circle.
3330 \param y Y coordinate of the center of the circle.
3331 \param rad Radius in pixels of the circle.
3332 \param r The red value of the circle to draw.
3333 \param g The green value of the circle to draw.
3334 \param b The blue value of the circle to draw.
3335 \param a The alpha value of the circle to draw.
3336 
3337 \returns Returns 0 on success, -1 on failure.
3338 */
circleRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3339 int circleRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3340 {
3341 	/*
3342 	* Draw
3343 	*/
3344 	return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3345 }
3346 
3347 /* ----- Arc */
3348 
3349 /*!
3350 \brief Arc with blending.
3351 
3352 Note Arc drawing is based on circle algorithm by A. Schiffler and
3353 written by D. Raber. Calculates which octants arc goes through and
3354 renders pixels accordingly.
3355 
3356 \param dst The surface to draw on.
3357 \param x X coordinate of the center of the arc.
3358 \param y Y coordinate of the center of the arc.
3359 \param rad Radius in pixels of the arc.
3360 \param start Starting radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
3361 \param end Ending radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
3362 \param color The color value of the arc to draw (0xRRGGBBAA).
3363 
3364 \returns Returns 0 on success, -1 on failure.
3365 */
arcColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)3366 int arcColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
3367 {
3368 	Sint16 left, right, top, bottom;
3369 	int result;
3370 	Sint16 x1, y1, x2, y2;
3371 	Sint16 cx = 0;
3372 	Sint16 cy = rad;
3373 	Sint16 df = 1 - rad;
3374 	Sint16 d_e = 3;
3375 	Sint16 d_se = -2 * rad + 5;
3376 	Sint16 xpcx, xmcx, xpcy, xmcy;
3377 	Sint16 ypcy, ymcy, ypcx, ymcx;
3378 	Uint8 *colorptr;
3379 	Uint8 drawoct;
3380 	int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
3381 	double dstart, dend, temp = 0.;
3382 
3383 	/*
3384 	* Check visibility of clipping rectangle
3385 	*/
3386 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0))
3387 		return(0);
3388 
3389 	/*
3390 	* Sanity check radius
3391 	*/
3392 	if (rad < 0)
3393 		return (-1);
3394 
3395 	/*
3396 	* Special case for rad=0 - draw a point
3397 	*/
3398 	if (rad == 0)
3399 		return (pixelColor(dst, x, y, color));
3400 
3401 	/*
3402 	* Get arc's circle and clipping boundary and
3403 	* test if bounding box of circle is visible
3404 	*/
3405 	x2 = x + rad;
3406 	left = dst->clip_rect.x;
3407 	if (x2<left)
3408 		return(0);
3409 	x1 = x - rad;
3410 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
3411 	if (x1>right)
3412 		return(0);
3413 	y2 = y + rad;
3414 	top = dst->clip_rect.y;
3415 	if (y2<top)
3416 		return(0);
3417 	y1 = y - rad;
3418 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3419 	if (y1>bottom)
3420 		return(0);
3421 
3422 	/* Octant labelling
3423 	 *
3424 	 *  \ 5 | 6 /
3425 	 *   \  |  /
3426 	 *  4 \ | / 7
3427 	 *     \|/
3428 	 *------+------ +x
3429 	 *     /|\
3430 	 *  3 / | \ 0
3431 	 *   /  |  \
3432 	 *  / 2 | 1 \
3433 	 *      +y
3434 
3435 	 * Initially reset bitmask to 0x00000000
3436 	 * the set whether or not to keep drawing a given octant.
3437 	 * For example: 0x00111100 means we're drawing in octants 2-5
3438     */
3439 	drawoct = 0;
3440 
3441 	/*
3442 	* Fixup angles
3443 	*/
3444 	start %= 360;
3445 	end %= 360;
3446 	// 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
3447 	while (start < 0) start += 360;
3448 	while (end < 0) end += 360;
3449 	start %= 360;
3450 	end %= 360;
3451 
3452 	// now, we find which octants we're drawing in.
3453 	startoct = start / 45;
3454 	endoct = end / 45;
3455 	oct = startoct - 1; // we increment as first step in loop
3456 
3457 	// stopval_start, stopval_end;
3458 	// what values of cx to stop at.
3459 	do {
3460 		oct = (oct + 1) % 8;
3461 
3462 		if (oct == startoct) {
3463 			// need to compute stopval_start for this octant.  Look at picture above if this is unclear
3464 			dstart = (double)start;
3465 			switch (oct)
3466 			{
3467 			case 0:
3468 			case 3:
3469 				temp = sin(dstart * M_PI / 180.);
3470 				break;
3471 			case 1:
3472 			case 6:
3473 				temp = cos(dstart * M_PI / 180.);
3474 				break;
3475 			case 2:
3476 			case 5:
3477 				temp = -cos(dstart * M_PI / 180.);
3478 				break;
3479 			case 4:
3480 			case 7:
3481 				temp = -sin(dstart * M_PI / 180.);
3482 				break;
3483 			}
3484 			temp *= rad;
3485 			stopval_start = (int)temp; // always round down.
3486 			// This isn't arbitrary, but requires graph paper to explain well.
3487 			// The basic idea is that we're always changing drawoct after we draw, so we
3488 			// stop immediately after we render the last sensible pixel at x = ((int)temp).
3489 
3490 			// and whether to draw in this octant initially
3491 			if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
3492 			else		 drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
3493 		}
3494 		if (oct == endoct) {
3495 			// need to compute stopval_end for this octant
3496 			dend = (double)end;
3497 			switch (oct)
3498 			{
3499 			case 0:
3500 			case 3:
3501 				temp = sin(dend * M_PI / 180);
3502 				break;
3503 			case 1:
3504 			case 6:
3505 				temp = cos(dend * M_PI / 180);
3506 				break;
3507 			case 2:
3508 			case 5:
3509 				temp = -cos(dend * M_PI / 180);
3510 				break;
3511 			case 4:
3512 			case 7:
3513 				temp = -sin(dend * M_PI / 180);
3514 				break;
3515 			}
3516 			temp *= rad;
3517 			stopval_end = (int)temp;
3518 
3519 			// and whether to draw in this octant initially
3520 			if (startoct == endoct)	{
3521 				// note:      we start drawing, stop, then start again in this case
3522 				// otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
3523 				if (start > end) {
3524 					// unfortunately, if we're in the same octant and need to draw over the whole circle,
3525 					// we need to set the rest to true, because the while loop will end at the bottom.
3526 					drawoct = 255;
3527 				} else {
3528 					drawoct &= 255 - (1 << oct);
3529 				}
3530 			}
3531 			else if (oct % 2) drawoct &= 255 - (1 << oct);
3532 			else			  drawoct |= (1 << oct);
3533 		} else if (oct != startoct) { // already verified that it's != endoct
3534 			drawoct |= (1 << oct); // draw this entire segment
3535 		}
3536 	} while (oct != endoct);
3537 
3538 	// so now we have what octants to draw and when to draw them.  all that's left is the actual raster code.
3539 
3540 	/* Lock surface */
3541 	if (RSDL_MUSTLOCK(dst)) {
3542 		if (RSDL_LockSurface(dst) < 0) {
3543 			return (-1);
3544 		}
3545 	}
3546 
3547 	/*
3548 	* Draw arc
3549 	*/
3550 	result = 0;
3551 
3552 	/*
3553 	* Alpha Check
3554 	*/
3555 	if ((color & 255) == 255) {
3556 
3557 		/*
3558 		* No Alpha - direct memory writes
3559 		*/
3560 
3561 		/*
3562 		* Setup color
3563 		*/
3564 		colorptr = (Uint8 *) & color;
3565 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
3566 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
3567 		} else {
3568 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
3569 		}
3570 
3571 		/*
3572 		* Draw
3573 		*/
3574 		do {
3575 			ypcy = y + cy;
3576 			ymcy = y - cy;
3577 			if (cx > 0) {
3578 				xpcx = x + cx;
3579 				xmcx = x - cx;
3580 				// always check if we're drawing a certain octant before adding a pixel to that octant.
3581 				if (drawoct & 4)  result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2]
3582 				if (drawoct & 2)  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
3583 				if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
3584 				if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
3585 			} else {
3586 				if (drawoct & 6)  result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1]
3587 				if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64
3588 			}
3589 
3590 			xpcy = x + cy;
3591 			xmcy = x - cy;
3592 			if (cx > 0 && cx != cy) {
3593 				ypcx = y + cx;
3594 				ymcx = y - cx;
3595 				if (drawoct & 8)   result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
3596 				if (drawoct & 1)   result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
3597 				if (drawoct & 16)  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
3598 				if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
3599 			} else if (cx == 0) {
3600 				if (drawoct & 24)  result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16
3601 				if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128
3602 			}
3603 
3604 			/*
3605 			* Update whether we're drawing an octant
3606 			*/
3607 			if (stopval_start == cx) {
3608 				// works like an on-off switch because start & end may be in the same octant.
3609 				if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
3610 				else drawoct |= (1 << startoct);
3611 			}
3612 			if (stopval_end == cx) {
3613 				if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
3614 				else drawoct |= (1 << endoct);
3615 			}
3616 
3617 			/*
3618 			* Update pixels
3619 			*/
3620 			if (df < 0) {
3621 				df += d_e;
3622 				d_e += 2;
3623 				d_se += 2;
3624 			} else {
3625 				df += d_se;
3626 				d_e += 2;
3627 				d_se += 4;
3628 				cy--;
3629 			}
3630 			cx++;
3631 		} while (cx <= cy);
3632 
3633 		/*
3634 		* Unlock surface
3635 		*/
3636 		RSDL_UnlockSurface(dst);
3637 
3638 	} else {
3639 
3640 		/*
3641 		* Using Alpha - blended pixel blits
3642 		*/
3643 
3644 		do {
3645 			ypcy = y + cy;
3646 			ymcy = y - cy;
3647 			if (cx > 0) {
3648 				xpcx = x + cx;
3649 				xmcx = x - cx;
3650 
3651 				// always check if we're drawing a certain octant before adding a pixel to that octant.
3652 				if (drawoct & 4)  result |= pixelColorNolock(dst, xmcx, ypcy, color);
3653 				if (drawoct & 2)  result |= pixelColorNolock(dst, xpcx, ypcy, color);
3654 				if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
3655 				if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
3656 			} else {
3657 				if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
3658 				if (drawoct & 6)  result |= pixelColorNolock(dst, x, ypcy, color);
3659 			}
3660 
3661 			xpcy = x + cy;
3662 			xmcy = x - cy;
3663 			if (cx > 0 && cx != cy) {
3664 				ypcx = y + cx;
3665 				ymcx = y - cx;
3666 				if (drawoct & 8)   result |= pixelColorNolock(dst, xmcy, ypcx, color);
3667 				if (drawoct & 1)   result |= pixelColorNolock(dst, xpcy, ypcx, color);
3668 				if (drawoct & 16)  result |= pixelColorNolock(dst, xmcy, ymcx, color);
3669 				if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
3670 			} else if (cx == 0) {
3671 				if (drawoct & 24)  result |= pixelColorNolock(dst, xmcy, y, color);
3672 				if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
3673 			}
3674 
3675 			/*
3676 			* Update whether we're drawing an octant
3677 			*/
3678 			if (stopval_start == cx) {
3679 				// works like an on-off switch.
3680 				// This is just in case start & end are in the same octant.
3681 				if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
3682 				else						   drawoct |= (1 << startoct);
3683 			}
3684 			if (stopval_end == cx) {
3685 				if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
3686 				else						 drawoct |= (1 << endoct);
3687 			}
3688 
3689 			/*
3690 			* Update pixels
3691 			*/
3692 			if (df < 0) {
3693 				df += d_e;
3694 				d_e += 2;
3695 				d_se += 2;
3696 			} else {
3697 				df += d_se;
3698 				d_e += 2;
3699 				d_se += 4;
3700 				cy--;
3701 			}
3702 			cx++;
3703 		} while (cx <= cy);
3704 
3705 	}				/* Alpha check */
3706 
3707 	/* Unlock surface */
3708 	if (RSDL_MUSTLOCK(dst)) {
3709 		RSDL_UnlockSurface(dst);
3710 	}
3711 
3712 	return (result);
3713 }
3714 
3715 /*!
3716 \brief Arc with blending.
3717 
3718 \param dst The surface to draw on.
3719 \param x X coordinate of the center of the arc.
3720 \param y Y coordinate of the center of the arc.
3721 \param rad Radius in pixels of the arc.
3722 \param start Starting radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
3723 \param end Ending radius in degrees of the arc. 0 degrees is down, increasing counterclockwise.
3724 \param r The red value of the arc to draw.
3725 \param g The green value of the arc to draw.
3726 \param b The blue value of the arc to draw.
3727 \param a The alpha value of the arc to draw.
3728 
3729 \returns Returns 0 on success, -1 on failure.
3730 */
arcRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3731 int arcRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3732 {
3733 	/*
3734 	* Draw
3735 	*/
3736 	return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3737 }
3738 
3739 /* ----- AA Circle */
3740 
3741 
3742 /*!
3743 \brief Draw anti-aliased circle with blending.
3744 
3745 Note: The AA-circle routine is based on AA-ellipse with identical radii.
3746 
3747 \param dst The surface to draw on.
3748 \param x X coordinate of the center of the aa-circle.
3749 \param y Y coordinate of the center of the aa-circle.
3750 \param rad Radius in pixels of the aa-circle.
3751 \param color The color value of the aa-circle to draw (0xRRGGBBAA).
3752 
3753 \returns Returns 0 on success, -1 on failure.
3754 */
aacircleColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint32 color)3755 int aacircleColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
3756 {
3757 	return (aaellipseColor(dst, x, y, rad, rad, color));
3758 }
3759 
3760 /*!
3761 \brief Draw anti-aliased circle with blending.
3762 
3763 \param dst The surface to draw on.
3764 \param x X coordinate of the center of the aa-circle.
3765 \param y Y coordinate of the center of the aa-circle.
3766 \param rad Radius in pixels of the aa-circle.
3767 \param r The red value of the aa-circle to draw.
3768 \param g The green value of the aa-circle to draw.
3769 \param b The blue value of the aa-circle to draw.
3770 \param a The alpha value of the aa-circle to draw.
3771 
3772 \returns Returns 0 on success, -1 on failure.
3773 */
aacircleRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3774 int aacircleRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3775 {
3776 	/*
3777 	* Draw
3778 	*/
3779 	return (aaellipseColor
3780 		(dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3781 }
3782 
3783 /* ----- Filled Circle */
3784 
3785 /*!
3786 \brief Draw filled circle with blending.
3787 
3788 Note: Based on algorithms from sge library with modifications by A. Schiffler for
3789 multiple-hline draw removal and other minor speedup changes.
3790 
3791 \param dst The surface to draw on.
3792 \param x X coordinate of the center of the filled circle.
3793 \param y Y coordinate of the center of the filled circle.
3794 \param rad Radius in pixels of the filled circle.
3795 \param color The color value of the filled circle to draw (0xRRGGBBAA).
3796 
3797 \returns Returns 0 on success, -1 on failure.
3798 */
filledCircleColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint32 color)3799 int filledCircleColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
3800 {
3801 	Sint16 left, right, top, bottom;
3802 	int result;
3803 	Sint16 x1, y1, x2, y2;
3804 	Sint16 cx = 0;
3805 	Sint16 cy = rad;
3806 	Sint16 ocx = (Sint16) 0xffff;
3807 	Sint16 ocy = (Sint16) 0xffff;
3808 	Sint16 df = 1 - rad;
3809 	Sint16 d_e = 3;
3810 	Sint16 d_se = -2 * rad + 5;
3811 	Sint16 xpcx, xmcx, xpcy, xmcy;
3812 	Sint16 ypcy, ymcy, ypcx, ymcx;
3813 
3814 	/*
3815 	* Check visibility of clipping rectangle
3816 	*/
3817 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3818 		return(0);
3819 	}
3820 
3821 	/*
3822 	* Sanity check radius
3823 	*/
3824 	if (rad < 0) {
3825 		return (-1);
3826 	}
3827 
3828 	/*
3829 	* Special case for rad=0 - draw a point
3830 	*/
3831 	if (rad == 0) {
3832 		return (pixelColor(dst, x, y, color));
3833 	}
3834 
3835 	/*
3836 	* Get circle and clipping boundary and
3837 	* test if bounding box of circle is visible
3838 	*/
3839 	x2 = x + rad;
3840 	left = dst->clip_rect.x;
3841 	if (x2<left) {
3842 		return(0);
3843 	}
3844 	x1 = x - rad;
3845 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
3846 	if (x1>right) {
3847 		return(0);
3848 	}
3849 	y2 = y + rad;
3850 	top = dst->clip_rect.y;
3851 	if (y2<top) {
3852 		return(0);
3853 	}
3854 	y1 = y - rad;
3855 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3856 	if (y1>bottom) {
3857 		return(0);
3858 	}
3859 
3860 	/*
3861 	* Draw
3862 	*/
3863 	result = 0;
3864 	do {
3865 		xpcx = x + cx;
3866 		xmcx = x - cx;
3867 		xpcy = x + cy;
3868 		xmcy = x - cy;
3869 		if (ocy != cy) {
3870 			if (cy > 0) {
3871 				ypcy = y + cy;
3872 				ymcy = y - cy;
3873 				result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
3874 				result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
3875 			} else {
3876 				result |= hlineColor(dst, xmcx, xpcx, y, color);
3877 			}
3878 			ocy = cy;
3879 		}
3880 		if (ocx != cx) {
3881 			if (cx != cy) {
3882 				if (cx > 0) {
3883 					ypcx = y + cx;
3884 					ymcx = y - cx;
3885 					result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
3886 					result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
3887 				} else {
3888 					result |= hlineColor(dst, xmcy, xpcy, y, color);
3889 				}
3890 			}
3891 			ocx = cx;
3892 		}
3893 		/*
3894 		* Update
3895 		*/
3896 		if (df < 0) {
3897 			df += d_e;
3898 			d_e += 2;
3899 			d_se += 2;
3900 		} else {
3901 			df += d_se;
3902 			d_e += 2;
3903 			d_se += 4;
3904 			cy--;
3905 		}
3906 		cx++;
3907 	} while (cx <= cy);
3908 
3909 	return (result);
3910 }
3911 
3912 /*!
3913 \brief Draw filled circle with blending.
3914 
3915 \param dst The surface to draw on.
3916 \param x X coordinate of the center of the filled circle.
3917 \param y Y coordinate of the center of the filled circle.
3918 \param rad Radius in pixels of the filled circle.
3919 \param r The red value of the filled circle to draw.
3920 \param g The green value of the filled circle to draw.
3921 \param b The blue value of the filled circle to draw.
3922 \param a The alpha value of the filled circle to draw.
3923 
3924 \returns Returns 0 on success, -1 on failure.
3925 */
filledCircleRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3926 int filledCircleRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3927 {
3928 	/*
3929 	* Draw
3930 	*/
3931 	return (filledCircleColor
3932 		(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3933 }
3934 
3935 /* ----- Ellipse */
3936 
3937 /*!
3938 \brief Draw ellipse with blending.
3939 
3940 Note: Based on algorithms from sge library with modifications by A. Schiffler for
3941 multiple-pixel draw removal and other minor speedup changes.
3942 
3943 \param dst The surface to draw on.
3944 \param x X coordinate of the center of the ellipse.
3945 \param y Y coordinate of the center of the ellipse.
3946 \param rx Horizontal radius in pixels of the ellipse.
3947 \param ry Vertical radius in pixels of the ellipse.
3948 \param color The color value of the ellipse to draw (0xRRGGBBAA).
3949 
3950 \returns Returns 0 on success, -1 on failure.
3951 */
ellipseColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)3952 int ellipseColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
3953 {
3954 	Sint16 left, right, top, bottom;
3955 	int result;
3956 	Sint16 x1, y1, x2, y2;
3957 	int ix, iy;
3958 	int h, i, j, k;
3959 	int oh, oi, oj, ok;
3960 	int xmh, xph, ypk, ymk;
3961 	int xmi, xpi, ymj, ypj;
3962 	int xmj, xpj, ymi, ypi;
3963 	int xmk, xpk, ymh, yph;
3964 	Uint8 *colorptr;
3965 
3966 	/*
3967 	* Check visibility of clipping rectangle
3968 	*/
3969 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3970 		return(0);
3971 	}
3972 
3973 	/*
3974 	* Sanity check radii
3975 	*/
3976 	if ((rx < 0) || (ry < 0)) {
3977 		return (-1);
3978 	}
3979 
3980 	/*
3981 	* Special case for rx=0 - draw a vline
3982 	*/
3983 	if (rx == 0) {
3984 		return (vlineColor(dst, x, y - ry, y + ry, color));
3985 	}
3986 	/*
3987 	* Special case for ry=0 - draw a hline
3988 	*/
3989 	if (ry == 0) {
3990 		return (hlineColor(dst, x - rx, x + rx, y, color));
3991 	}
3992 
3993 	/*
3994 	* Get circle and clipping boundary and
3995 	* test if bounding box of circle is visible
3996 	*/
3997 	x2 = x + rx;
3998 	left = dst->clip_rect.x;
3999 	if (x2<left) {
4000 		return(0);
4001 	}
4002 	x1 = x - rx;
4003 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
4004 	if (x1>right) {
4005 		return(0);
4006 	}
4007 	y2 = y + ry;
4008 	top = dst->clip_rect.y;
4009 	if (y2<top) {
4010 		return(0);
4011 	}
4012 	y1 = y - ry;
4013 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4014 	if (y1>bottom) {
4015 		return(0);
4016 	}
4017 
4018 	/*
4019 	* Init vars
4020 	*/
4021 	oh = oi = oj = ok = 0xFFFF;
4022 
4023 	/*
4024 	* Draw
4025 	*/
4026 	result = 0;
4027 
4028 	/* Lock surface */
4029 	if (RSDL_MUSTLOCK(dst)) {
4030 		if (RSDL_LockSurface(dst) < 0) {
4031 			return (-1);
4032 		}
4033 	}
4034 
4035 	/*
4036 	* Check alpha
4037 	*/
4038 	if ((color & 255) == 255) {
4039 
4040 		/*
4041 		* No Alpha - direct memory writes
4042 		*/
4043 
4044 		/*
4045 		* Setup color
4046 		*/
4047 		colorptr = (Uint8 *) & color;
4048 		if (RSDL_BYTEORDER == RSDL_BIG_ENDIAN) {
4049 			color = RSDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
4050 		} else {
4051 			color = RSDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
4052 		}
4053 
4054 
4055 		if (rx > ry) {
4056 			ix = 0;
4057 			iy = rx * 64;
4058 
4059 			do {
4060 				h = (ix + 32) >> 6;
4061 				i = (iy + 32) >> 6;
4062 				j = (h * ry) / rx;
4063 				k = (i * ry) / rx;
4064 
4065 				if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
4066 					xph = x + h;
4067 					xmh = x - h;
4068 					if (k > 0) {
4069 						ypk = y + k;
4070 						ymk = y - k;
4071 						result |= fastPixelColorNolock(dst, xmh, ypk, color);
4072 						result |= fastPixelColorNolock(dst, xph, ypk, color);
4073 						result |= fastPixelColorNolock(dst, xmh, ymk, color);
4074 						result |= fastPixelColorNolock(dst, xph, ymk, color);
4075 					} else {
4076 						result |= fastPixelColorNolock(dst, xmh, y, color);
4077 						result |= fastPixelColorNolock(dst, xph, y, color);
4078 					}
4079 					ok = k;
4080 					xpi = x + i;
4081 					xmi = x - i;
4082 					if (j > 0) {
4083 						ypj = y + j;
4084 						ymj = y - j;
4085 						result |= fastPixelColorNolock(dst, xmi, ypj, color);
4086 						result |= fastPixelColorNolock(dst, xpi, ypj, color);
4087 						result |= fastPixelColorNolock(dst, xmi, ymj, color);
4088 						result |= fastPixelColorNolock(dst, xpi, ymj, color);
4089 					} else {
4090 						result |= fastPixelColorNolock(dst, xmi, y, color);
4091 						result |= fastPixelColorNolock(dst, xpi, y, color);
4092 					}
4093 					oj = j;
4094 				}
4095 
4096 				ix = ix + iy / rx;
4097 				iy = iy - ix / rx;
4098 
4099 			} while (i > h);
4100 		} else {
4101 			ix = 0;
4102 			iy = ry * 64;
4103 
4104 			do {
4105 				h = (ix + 32) >> 6;
4106 				i = (iy + 32) >> 6;
4107 				j = (h * rx) / ry;
4108 				k = (i * rx) / ry;
4109 
4110 				if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
4111 					xmj = x - j;
4112 					xpj = x + j;
4113 					if (i > 0) {
4114 						ypi = y + i;
4115 						ymi = y - i;
4116 						result |= fastPixelColorNolock(dst, xmj, ypi, color);
4117 						result |= fastPixelColorNolock(dst, xpj, ypi, color);
4118 						result |= fastPixelColorNolock(dst, xmj, ymi, color);
4119 						result |= fastPixelColorNolock(dst, xpj, ymi, color);
4120 					} else {
4121 						result |= fastPixelColorNolock(dst, xmj, y, color);
4122 						result |= fastPixelColorNolock(dst, xpj, y, color);
4123 					}
4124 					oi = i;
4125 					xmk = x - k;
4126 					xpk = x + k;
4127 					if (h > 0) {
4128 						yph = y + h;
4129 						ymh = y - h;
4130 						result |= fastPixelColorNolock(dst, xmk, yph, color);
4131 						result |= fastPixelColorNolock(dst, xpk, yph, color);
4132 						result |= fastPixelColorNolock(dst, xmk, ymh, color);
4133 						result |= fastPixelColorNolock(dst, xpk, ymh, color);
4134 					} else {
4135 						result |= fastPixelColorNolock(dst, xmk, y, color);
4136 						result |= fastPixelColorNolock(dst, xpk, y, color);
4137 					}
4138 					oh = h;
4139 				}
4140 
4141 				ix = ix + iy / ry;
4142 				iy = iy - ix / ry;
4143 
4144 			} while (i > h);
4145 		}
4146 
4147 	} else {
4148 
4149 		if (rx > ry) {
4150 			ix = 0;
4151 			iy = rx * 64;
4152 
4153 			do {
4154 				h = (ix + 32) >> 6;
4155 				i = (iy + 32) >> 6;
4156 				j = (h * ry) / rx;
4157 				k = (i * ry) / rx;
4158 
4159 				if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
4160 					xph = x + h;
4161 					xmh = x - h;
4162 					if (k > 0) {
4163 						ypk = y + k;
4164 						ymk = y - k;
4165 						result |= pixelColorNolock (dst, xmh, ypk, color);
4166 						result |= pixelColorNolock (dst, xph, ypk, color);
4167 						result |= pixelColorNolock (dst, xmh, ymk, color);
4168 						result |= pixelColorNolock (dst, xph, ymk, color);
4169 					} else {
4170 						result |= pixelColorNolock (dst, xmh, y, color);
4171 						result |= pixelColorNolock (dst, xph, y, color);
4172 					}
4173 					ok = k;
4174 					xpi = x + i;
4175 					xmi = x - i;
4176 					if (j > 0) {
4177 						ypj = y + j;
4178 						ymj = y - j;
4179 						result |= pixelColorNolock (dst, xmi, ypj, color);
4180 						result |= pixelColorNolock (dst, xpi, ypj, color);
4181 						result |= pixelColorNolock (dst, xmi, ymj, color);
4182 						result |= pixelColor(dst, xpi, ymj, color);
4183 					} else {
4184 						result |= pixelColorNolock (dst, xmi, y, color);
4185 						result |= pixelColorNolock (dst, xpi, y, color);
4186 					}
4187 					oj = j;
4188 				}
4189 
4190 				ix = ix + iy / rx;
4191 				iy = iy - ix / rx;
4192 
4193 			} while (i > h);
4194 		} else {
4195 			ix = 0;
4196 			iy = ry * 64;
4197 
4198 			do {
4199 				h = (ix + 32) >> 6;
4200 				i = (iy + 32) >> 6;
4201 				j = (h * rx) / ry;
4202 				k = (i * rx) / ry;
4203 
4204 				if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
4205 					xmj = x - j;
4206 					xpj = x + j;
4207 					if (i > 0) {
4208 						ypi = y + i;
4209 						ymi = y - i;
4210 						result |= pixelColorNolock (dst, xmj, ypi, color);
4211 						result |= pixelColorNolock (dst, xpj, ypi, color);
4212 						result |= pixelColorNolock (dst, xmj, ymi, color);
4213 						result |= pixelColorNolock (dst, xpj, ymi, color);
4214 					} else {
4215 						result |= pixelColorNolock (dst, xmj, y, color);
4216 						result |= pixelColorNolock (dst, xpj, y, color);
4217 					}
4218 					oi = i;
4219 					xmk = x - k;
4220 					xpk = x + k;
4221 					if (h > 0) {
4222 						yph = y + h;
4223 						ymh = y - h;
4224 						result |= pixelColorNolock (dst, xmk, yph, color);
4225 						result |= pixelColorNolock (dst, xpk, yph, color);
4226 						result |= pixelColorNolock (dst, xmk, ymh, color);
4227 						result |= pixelColorNolock (dst, xpk, ymh, color);
4228 					} else {
4229 						result |= pixelColorNolock (dst, xmk, y, color);
4230 						result |= pixelColorNolock (dst, xpk, y, color);
4231 					}
4232 					oh = h;
4233 				}
4234 
4235 				ix = ix + iy / ry;
4236 				iy = iy - ix / ry;
4237 
4238 			} while (i > h);
4239 		}
4240 
4241 	}				/* Alpha check */
4242 
4243 	/* Unlock surface */
4244 	if (RSDL_MUSTLOCK(dst)) {
4245 		RSDL_UnlockSurface(dst);
4246 	}
4247 
4248 	return (result);
4249 }
4250 
4251 /*!
4252 \brief Draw ellipse with blending.
4253 
4254 \param dst The surface to draw on.
4255 \param x X coordinate of the center of the ellipse.
4256 \param y Y coordinate of the center of the ellipse.
4257 \param rx Horizontal radius in pixels of the ellipse.
4258 \param ry Vertical radius in pixels of the ellipse.
4259 \param r The red value of the ellipse to draw.
4260 \param g The green value of the ellipse to draw.
4261 \param b The blue value of the ellipse to draw.
4262 \param a The alpha value of the ellipse to draw.
4263 
4264 \returns Returns 0 on success, -1 on failure.
4265 */
ellipseRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4266 int ellipseRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4267 {
4268 	/*
4269 	* Draw
4270 	*/
4271 	return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4272 }
4273 
4274 /* ----- AA Ellipse */
4275 
4276 /* Windows targets do not have lrint, so provide a local inline version */
4277 #if defined(_MSC_VER)
4278 /* Detect 64bit and use intrinsic version */
4279 #ifdef _M_X64
4280 #include <emmintrin.h>
4281 static __inline long
lrint(float f)4282 	lrint(float f)
4283 {
4284 	return _mm_cvtss_si32(_mm_load_ss(&f));
4285 }
4286 #elif defined(_M_IX86)
4287 __inline long int
lrint(double flt)4288 	lrint (double flt)
4289 {
4290 	int intgr;
4291 	_asm
4292 	{
4293 		fld flt
4294 			fistp intgr
4295 	};
4296 	return intgr;
4297 }
4298 #elif defined(_M_ARM)
4299 #include <armintr.h>
4300 #pragma warning(push)
4301 #pragma warning(disable: 4716)
4302 __declspec(naked) long int
lrint(double flt)4303 	lrint (double flt)
4304 {
4305 	__emit(0xEC410B10); // fmdrr  d0, r0, r1
4306 	__emit(0xEEBD0B40); // ftosid s0, d0
4307 	__emit(0xEE100A10); // fmrs   r0, s0
4308 	__emit(0xE12FFF1E); // bx     lr
4309 }
4310 #pragma warning(pop)
4311 #else
4312 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
4313 #endif
4314 #endif
4315 
4316 /*!
4317 \brief Draw anti-aliased ellipse with blending.
4318 
4319 Note: Based on code from Anders Lindstroem, which is based on code from sge library,
4320 which is based on code from TwinLib.
4321 
4322 \param dst The surface to draw on.
4323 \param x X coordinate of the center of the aa-ellipse.
4324 \param y Y coordinate of the center of the aa-ellipse.
4325 \param rx Horizontal radius in pixels of the aa-ellipse.
4326 \param ry Vertical radius in pixels of the aa-ellipse.
4327 \param color The color value of the aa-ellipse to draw (0xRRGGBBAA).
4328 
4329 \returns Returns 0 on success, -1 on failure.
4330 */
aaellipseColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)4331 int aaellipseColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
4332 {
4333 	Sint16 left, right, top, bottom;
4334 	Sint16 x1,y1,x2,y2;
4335 	int i;
4336 	int a2, b2, ds, dt, dxt, t, s, d;
4337 	Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
4338 	float cp;
4339 	double sab;
4340 	Uint8 weight, iweight;
4341 	int result;
4342 
4343 	/*
4344 	* Check visibility of clipping rectangle
4345 	*/
4346 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4347 		return(0);
4348 	}
4349 
4350 	/*
4351 	* Sanity check radii
4352 	*/
4353 	if ((rx < 0) || (ry < 0)) {
4354 		return (-1);
4355 	}
4356 
4357 	/*
4358 	* Special case for rx=0 - draw a vline
4359 	*/
4360 	if (rx == 0) {
4361 		return (vlineColor(dst, x, y - ry, y + ry, color));
4362 	}
4363 	/*
4364 	* Special case for ry=0 - draw an hline
4365 	*/
4366 	if (ry == 0) {
4367 		return (hlineColor(dst, x - rx, x + rx, y, color));
4368 	}
4369 
4370 	/*
4371 	* Get circle and clipping boundary and
4372 	* test if bounding box of circle is visible
4373 	*/
4374 	x2 = x + rx;
4375 	left = dst->clip_rect.x;
4376 	if (x2<left) {
4377 		return(0);
4378 	}
4379 	x1 = x - rx;
4380 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
4381 	if (x1>right) {
4382 		return(0);
4383 	}
4384 	y2 = y + ry;
4385 	top = dst->clip_rect.y;
4386 	if (y2<top) {
4387 		return(0);
4388 	}
4389 	y1 = y - ry;
4390 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4391 	if (y1>bottom) {
4392 		return(0);
4393 	}
4394 
4395 	/* Variable setup */
4396 	a2 = rx * rx;
4397 	b2 = ry * ry;
4398 
4399 	ds = 2 * a2;
4400 	dt = 2 * b2;
4401 
4402 	xc2 = 2 * x;
4403 	yc2 = 2 * y;
4404 
4405 	sab = sqrt((double)(a2 + b2));
4406 	od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
4407 	dxt = (Sint16)lrint((double)a2 / sab) + od;
4408 
4409 	t = 0;
4410 	s = -2 * a2 * ry;
4411 	d = 0;
4412 
4413 	xp = x;
4414 	yp = y - ry;
4415 
4416 	/* Lock surface */
4417 	if (RSDL_MUSTLOCK(dst)) {
4418 		if (RSDL_LockSurface(dst) < 0) {
4419 			return (-1);
4420 		}
4421 	}
4422 
4423 	/* Draw */
4424 	result = 0;
4425 
4426 	/* "End points" */
4427 	result |= pixelColorNolock(dst, xp, yp, color);
4428 	result |= pixelColorNolock(dst, xc2 - xp, yp, color);
4429 	result |= pixelColorNolock(dst, xp, yc2 - yp, color);
4430 	result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
4431 
4432 	for (i = 1; i <= dxt; i++) {
4433 		xp--;
4434 		d += t - b2;
4435 
4436 		if (d >= 0)
4437 			ys = yp - 1;
4438 		else if ((d - s - a2) > 0) {
4439 			if ((2 * d - s - a2) >= 0)
4440 				ys = yp + 1;
4441 			else {
4442 				ys = yp;
4443 				yp++;
4444 				d -= s + a2;
4445 				s += ds;
4446 			}
4447 		} else {
4448 			yp++;
4449 			ys = yp + 1;
4450 			d -= s + a2;
4451 			s += ds;
4452 		}
4453 
4454 		t -= dt;
4455 
4456 		/* Calculate alpha */
4457 		if (s != 0) {
4458 			cp = (float) abs(d) / (float) abs(s);
4459 			if (cp > 1.0) {
4460 				cp = 1.0;
4461 			}
4462 		} else {
4463 			cp = 1.0;
4464 		}
4465 
4466 		/* Calculate weights */
4467 		weight = (Uint8) (cp * 255);
4468 		iweight = 255 - weight;
4469 
4470 		/* Upper half */
4471 		xx = xc2 - xp;
4472 		result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
4473 		result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
4474 
4475 		result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
4476 		result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
4477 
4478 		/* Lower half */
4479 		yy = yc2 - yp;
4480 		result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
4481 		result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
4482 
4483 		yy = yc2 - ys;
4484 		result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
4485 		result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
4486 	}
4487 
4488 	/* Replaces original approximation code dyt = abs(yp - yc); */
4489 	dyt = (Sint16)lrint((double)b2 / sab ) + od;
4490 
4491 	for (i = 1; i <= dyt; i++) {
4492 		yp++;
4493 		d -= s + a2;
4494 
4495 		if (d <= 0)
4496 			xs = xp + 1;
4497 		else if ((d + t - b2) < 0) {
4498 			if ((2 * d + t - b2) <= 0)
4499 				xs = xp - 1;
4500 			else {
4501 				xs = xp;
4502 				xp--;
4503 				d += t - b2;
4504 				t -= dt;
4505 			}
4506 		} else {
4507 			xp--;
4508 			xs = xp - 1;
4509 			d += t - b2;
4510 			t -= dt;
4511 		}
4512 
4513 		s += ds;
4514 
4515 		/* Calculate alpha */
4516 		if (t != 0) {
4517 			cp = (float) abs(d) / (float) abs(t);
4518 			if (cp > 1.0) {
4519 				cp = 1.0;
4520 			}
4521 		} else {
4522 			cp = 1.0;
4523 		}
4524 
4525 		/* Calculate weight */
4526 		weight = (Uint8) (cp * 255);
4527 		iweight = 255 - weight;
4528 
4529 		/* Left half */
4530 		xx = xc2 - xp;
4531 		yy = yc2 - yp;
4532 		result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
4533 		result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
4534 
4535 		result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
4536 		result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
4537 
4538 		/* Right half */
4539 		xx = xc2 - xs;
4540 		result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
4541 		result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
4542 
4543 		result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
4544 		result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
4545 
4546 	}
4547 
4548 	/* Unlock surface */
4549 	if (RSDL_MUSTLOCK(dst)) {
4550 		RSDL_UnlockSurface(dst);
4551 	}
4552 
4553 	return (result);
4554 }
4555 
4556 /*!
4557 \brief Draw anti-aliased ellipse with blending.
4558 
4559 \param dst The surface to draw on.
4560 \param x X coordinate of the center of the aa-ellipse.
4561 \param y Y coordinate of the center of the aa-ellipse.
4562 \param rx Horizontal radius in pixels of the aa-ellipse.
4563 \param ry Vertical radius in pixels of the aa-ellipse.
4564 \param r The red value of the aa-ellipse to draw.
4565 \param g The green value of the aa-ellipse to draw.
4566 \param b The blue value of the aa-ellipse to draw.
4567 \param a The alpha value of the aa-ellipse to draw.
4568 
4569 \returns Returns 0 on success, -1 on failure.
4570 */
aaellipseRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4571 int aaellipseRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4572 {
4573 	/*
4574 	* Draw
4575 	*/
4576 	return (aaellipseColor
4577 		(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4578 }
4579 
4580 /* ---- Filled Ellipse */
4581 
4582 /* Note: */
4583 /* Based on algorithm from sge library with multiple-hline draw removal */
4584 /* and other speedup changes. */
4585 
4586 /*!
4587 \brief Draw filled ellipse with blending.
4588 
4589 Note: Based on algorithm from sge library with multiple-hline draw removal
4590 and other speedup changes.
4591 
4592 \param dst The surface to draw on.
4593 \param x X coordinate of the center of the filled ellipse.
4594 \param y Y coordinate of the center of the filled ellipse.
4595 \param rx Horizontal radius in pixels of the filled ellipse.
4596 \param ry Vertical radius in pixels of the filled ellipse.
4597 \param color The color value of the filled ellipse to draw (0xRRGGBBAA).
4598 
4599 \returns Returns 0 on success, -1 on failure.
4600 */
filledEllipseColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)4601 int filledEllipseColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
4602 {
4603 	Sint16 left, right, top, bottom;
4604 	int result;
4605 	Sint16 x1, y1, x2, y2;
4606 	int ix, iy;
4607 	int h, i, j, k;
4608 	int oh, oi, oj, ok;
4609 	int xmh, xph;
4610 	int xmi, xpi;
4611 	int xmj, xpj;
4612 	int xmk, xpk;
4613 
4614 	/*
4615 	* Check visibility of clipping rectangle
4616 	*/
4617 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4618 		return(0);
4619 	}
4620 
4621 	/*
4622 	* Sanity check radii
4623 	*/
4624 	if ((rx < 0) || (ry < 0)) {
4625 		return (-1);
4626 	}
4627 
4628 	/*
4629 	* Special case for rx=0 - draw a vline
4630 	*/
4631 	if (rx == 0) {
4632 		return (vlineColor(dst, x, y - ry, y + ry, color));
4633 	}
4634 	/*
4635 	* Special case for ry=0 - draw a hline
4636 	*/
4637 	if (ry == 0) {
4638 		return (hlineColor(dst, x - rx, x + rx, y, color));
4639 	}
4640 
4641 	/*
4642 	* Get circle and clipping boundary and
4643 	* test if bounding box of circle is visible
4644 	*/
4645 	x2 = x + rx;
4646 	left = dst->clip_rect.x;
4647 	if (x2<left) {
4648 		return(0);
4649 	}
4650 	x1 = x - rx;
4651 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
4652 	if (x1>right) {
4653 		return(0);
4654 	}
4655 	y2 = y + ry;
4656 	top = dst->clip_rect.y;
4657 	if (y2<top) {
4658 		return(0);
4659 	}
4660 	y1 = y - ry;
4661 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4662 	if (y1>bottom) {
4663 		return(0);
4664 	}
4665 
4666 	/*
4667 	* Init vars
4668 	*/
4669 	oh = oi = oj = ok = 0xFFFF;
4670 
4671 	/*
4672 	* Draw
4673 	*/
4674 	result = 0;
4675 	if (rx > ry) {
4676 		ix = 0;
4677 		iy = rx * 64;
4678 
4679 		do {
4680 			h = (ix + 32) >> 6;
4681 			i = (iy + 32) >> 6;
4682 			j = (h * ry) / rx;
4683 			k = (i * ry) / rx;
4684 
4685 			if ((ok != k) && (oj != k)) {
4686 				xph = x + h;
4687 				xmh = x - h;
4688 				if (k > 0) {
4689 					result |= hlineColor(dst, xmh, xph, y + k, color);
4690 					result |= hlineColor(dst, xmh, xph, y - k, color);
4691 				} else {
4692 					result |= hlineColor(dst, xmh, xph, y, color);
4693 				}
4694 				ok = k;
4695 			}
4696 			if ((oj != j) && (ok != j) && (k != j)) {
4697 				xmi = x - i;
4698 				xpi = x + i;
4699 				if (j > 0) {
4700 					result |= hlineColor(dst, xmi, xpi, y + j, color);
4701 					result |= hlineColor(dst, xmi, xpi, y - j, color);
4702 				} else {
4703 					result |= hlineColor(dst, xmi, xpi, y, color);
4704 				}
4705 				oj = j;
4706 			}
4707 
4708 			ix = ix + iy / rx;
4709 			iy = iy - ix / rx;
4710 
4711 		} while (i > h);
4712 	} else {
4713 		ix = 0;
4714 		iy = ry * 64;
4715 
4716 		do {
4717 			h = (ix + 32) >> 6;
4718 			i = (iy + 32) >> 6;
4719 			j = (h * rx) / ry;
4720 			k = (i * rx) / ry;
4721 
4722 			if ((oi != i) && (oh != i)) {
4723 				xmj = x - j;
4724 				xpj = x + j;
4725 				if (i > 0) {
4726 					result |= hlineColor(dst, xmj, xpj, y + i, color);
4727 					result |= hlineColor(dst, xmj, xpj, y - i, color);
4728 				} else {
4729 					result |= hlineColor(dst, xmj, xpj, y, color);
4730 				}
4731 				oi = i;
4732 			}
4733 			if ((oh != h) && (oi != h) && (i != h)) {
4734 				xmk = x - k;
4735 				xpk = x + k;
4736 				if (h > 0) {
4737 					result |= hlineColor(dst, xmk, xpk, y + h, color);
4738 					result |= hlineColor(dst, xmk, xpk, y - h, color);
4739 				} else {
4740 					result |= hlineColor(dst, xmk, xpk, y, color);
4741 				}
4742 				oh = h;
4743 			}
4744 
4745 			ix = ix + iy / ry;
4746 			iy = iy - ix / ry;
4747 
4748 		} while (i > h);
4749 	}
4750 
4751 	return (result);
4752 }
4753 
4754 /*!
4755 \brief Draw filled ellipse with blending.
4756 
4757 \param dst The surface to draw on.
4758 \param x X coordinate of the center of the filled ellipse.
4759 \param y Y coordinate of the center of the filled ellipse.
4760 \param rx Horizontal radius in pixels of the filled ellipse.
4761 \param ry Vertical radius in pixels of the filled ellipse.
4762 \param r The red value of the filled ellipse to draw.
4763 \param g The green value of the filled ellipse to draw.
4764 \param b The blue value of the filled ellipse to draw.
4765 \param a The alpha value of the filled ellipse to draw.
4766 
4767 \returns Returns 0 on success, -1 on failure.
4768 */
filledEllipseRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4769 int filledEllipseRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4770 {
4771 	/*
4772 	* Draw
4773 	*/
4774 	return (filledEllipseColor
4775 		(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4776 }
4777 
4778 /* ----- pie */
4779 
4780 /*!
4781 \brief Internal float (low-speed) pie-calc implementation by drawing polygons.
4782 
4783 Note: Determines vertex array and uses polygon or filledPolygon drawing routines to render.
4784 
4785 \param dst The surface to draw on.
4786 \param x X coordinate of the center of the pie.
4787 \param y Y coordinate of the center of the pie.
4788 \param rad Radius in pixels of the pie.
4789 \param start Starting radius in degrees of the pie.
4790 \param end Ending radius in degrees of the pie.
4791 \param color The color value of the pie to draw (0xRRGGBBAA).
4792 \param filled Flag indicating if the pie should be filled (=1) or not (=0).
4793 
4794 \returns Returns 0 on success, -1 on failure.
4795 */
_pieColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color,Uint8 filled)4796 int _pieColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
4797 {
4798 	Sint16 left, right, top, bottom;
4799 	Sint16 x1, y1, x2, y2;
4800 	int result;
4801 	double angle, start_angle, end_angle;
4802 	double deltaAngle;
4803 	double dr;
4804 	int numpoints, i;
4805 	Sint16 *vx, *vy;
4806 
4807 	/*
4808 	* Check visibility of clipping rectangle
4809 	*/
4810 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4811 		return(0);
4812 	}
4813 
4814 	/*
4815 	* Sanity check radii
4816 	*/
4817 	if (rad < 0) {
4818 		return (-1);
4819 	}
4820 
4821 	/*
4822 	* Fixup angles
4823 	*/
4824 	start = start % 360;
4825 	end = end % 360;
4826 
4827 	/*
4828 	* Special case for rad=0 - draw a point
4829 	*/
4830 	if (rad == 0) {
4831 		return (pixelColor(dst, x, y, color));
4832 	}
4833 
4834 	/*
4835 	* Clip against circle, not pie (not 100% optimal).
4836 	* Get pie's circle and clipping boundary and
4837 	* test if bounding box of circle is visible
4838 	*/
4839 	x2 = x + rad;
4840 	left = dst->clip_rect.x;
4841 	if (x2<left) {
4842 		return(0);
4843 	}
4844 	x1 = x - rad;
4845 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
4846 	if (x1>right) {
4847 		return(0);
4848 	}
4849 	y2 = y + rad;
4850 	top = dst->clip_rect.y;
4851 	if (y2<top) {
4852 		return(0);
4853 	}
4854 	y1 = y - rad;
4855 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4856 	if (y1>bottom) {
4857 		return(0);
4858 	}
4859 
4860 	/*
4861 	* Variable setup
4862 	*/
4863 	dr = (double) rad;
4864 	deltaAngle = 3.0 / dr;
4865 	start_angle = (double) start *(2.0 * M_PI / 360.0);
4866 	end_angle = (double) end *(2.0 * M_PI / 360.0);
4867 	if (start > end) {
4868 		end_angle += (2.0 * M_PI);
4869 	}
4870 
4871 	/* We will always have at least 2 points */
4872 	numpoints = 2;
4873 
4874 	/* Count points (rather than calculating it) */
4875 	angle = start_angle;
4876 	while (angle < end_angle) {
4877 		angle += deltaAngle;
4878 		numpoints++;
4879 	}
4880 
4881 	/* Allocate combined vertex array */
4882 	vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
4883 	if (vx == NULL) {
4884 		return (-1);
4885 	}
4886 
4887 	/* Update point to start of vy */
4888 	vy += numpoints;
4889 
4890 	/* Center */
4891 	vx[0] = x;
4892 	vy[0] = y;
4893 
4894 	/* First vertex */
4895 	angle = start_angle;
4896 	vx[1] = x + (int) (dr * cos(angle));
4897 	vy[1] = y + (int) (dr * sin(angle));
4898 
4899 	if (numpoints<3)
4900 	{
4901 		result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
4902 	}
4903 	else
4904 	{
4905 		/* Calculate other vertices */
4906 		i = 2;
4907 		angle = start_angle;
4908 		while (angle < end_angle) {
4909 			angle += deltaAngle;
4910 			if (angle>end_angle)
4911 			{
4912 				angle = end_angle;
4913 			}
4914 			vx[i] = x + (int) (dr * cos(angle));
4915 			vy[i] = y + (int) (dr * sin(angle));
4916 			i++;
4917 		}
4918 
4919 		/* Draw */
4920 		if (filled) {
4921 			result = filledPolygonColor(dst, vx, vy, numpoints, color);
4922 		} else {
4923 			result = polygonColor(dst, vx, vy, numpoints, color);
4924 		}
4925 	}
4926 
4927 	/* Free combined vertex array */
4928 	free(vx);
4929 
4930 	return (result);
4931 }
4932 
4933 /*!
4934 \brief Draw pie (outline) with alpha blending.
4935 
4936 \param dst The surface to draw on.
4937 \param x X coordinate of the center of the pie.
4938 \param y Y coordinate of the center of the pie.
4939 \param rad Radius in pixels of the pie.
4940 \param start Starting radius in degrees of the pie.
4941 \param end Ending radius in degrees of the pie.
4942 \param color The color value of the pie to draw (0xRRGGBBAA).
4943 
4944 \returns Returns 0 on success, -1 on failure.
4945 */
pieColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)4946 int pieColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
4947 	Sint16 start, Sint16 end, Uint32 color)
4948 {
4949 	return (_pieColor(dst, x, y, rad, start, end, color, 0));
4950 
4951 }
4952 
4953 /*!
4954 \brief Draw pie (outline) with alpha blending.
4955 
4956 \param dst The surface to draw on.
4957 \param x X coordinate of the center of the pie.
4958 \param y Y coordinate of the center of the pie.
4959 \param rad Radius in pixels of the pie.
4960 \param start Starting radius in degrees of the pie.
4961 \param end Ending radius in degrees of the pie.
4962 \param r The red value of the pie to draw.
4963 \param g The green value of the pie to draw.
4964 \param b The blue value of the pie to draw.
4965 \param a The alpha value of the pie to draw.
4966 
4967 \returns Returns 0 on success, -1 on failure.
4968 */
pieRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4969 int pieRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
4970 	Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4971 {
4972 	return (_pieColor(dst, x, y, rad, start, end,
4973 		((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
4974 
4975 }
4976 
4977 /*!
4978 \brief Draw filled pie with alpha blending.
4979 
4980 \param dst The surface to draw on.
4981 \param x X coordinate of the center of the filled pie.
4982 \param y Y coordinate of the center of the filled pie.
4983 \param rad Radius in pixels of the filled pie.
4984 \param start Starting radius in degrees of the filled pie.
4985 \param end Ending radius in degrees of the filled pie.
4986 \param color The color value of the filled pie to draw (0xRRGGBBAA).
4987 
4988 \returns Returns 0 on success, -1 on failure.
4989 */
filledPieColor(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)4990 int filledPieColor(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
4991 {
4992 	return (_pieColor(dst, x, y, rad, start, end, color, 1));
4993 }
4994 
4995 /*!
4996 \brief Draw filled pie with alpha blending.
4997 
4998 \param dst The surface to draw on.
4999 \param x X coordinate of the center of the filled pie.
5000 \param y Y coordinate of the center of the filled pie.
5001 \param rad Radius in pixels of the filled pie.
5002 \param start Starting radius in degrees of the filled pie.
5003 \param end Ending radius in degrees of the filled pie.
5004 \param r The red value of the filled pie to draw.
5005 \param g The green value of the filled pie to draw.
5006 \param b The blue value of the filled pie to draw.
5007 \param a The alpha value of the filled pie to draw.
5008 
5009 \returns Returns 0 on success, -1 on failure.
5010 */
filledPieRGBA(RSDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5011 int filledPieRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
5012 	Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5013 {
5014 	return (_pieColor(dst, x, y, rad, start, end,
5015 		((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
5016 }
5017 
5018 /* ------ Trigon */
5019 
5020 /*!
5021 \brief Draw trigon (triangle outline) with alpha blending.
5022 
5023 Note: Creates vertex array and uses polygon routine to render.
5024 
5025 \param dst The surface to draw on.
5026 \param x1 X coordinate of the first point of the trigon.
5027 \param y1 Y coordinate of the first point of the trigon.
5028 \param x2 X coordinate of the second point of the trigon.
5029 \param y2 Y coordinate of the second point of the trigon.
5030 \param x3 X coordinate of the third point of the trigon.
5031 \param y3 Y coordinate of the third point of the trigon.
5032 \param color The color value of the trigon to draw (0xRRGGBBAA).
5033 
5034 \returns Returns 0 on success, -1 on failure.
5035 */
trigonColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)5036 int trigonColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
5037 {
5038 	Sint16 vx[3];
5039 	Sint16 vy[3];
5040 
5041 	vx[0]=x1;
5042 	vx[1]=x2;
5043 	vx[2]=x3;
5044 	vy[0]=y1;
5045 	vy[1]=y2;
5046 	vy[2]=y3;
5047 
5048 	return(polygonColor(dst,vx,vy,3,color));
5049 }
5050 
5051 /*!
5052 \brief Draw trigon (triangle outline) with alpha blending.
5053 
5054 \param dst The surface to draw on.
5055 \param x1 X coordinate of the first point of the trigon.
5056 \param y1 Y coordinate of the first point of the trigon.
5057 \param x2 X coordinate of the second point of the trigon.
5058 \param y2 Y coordinate of the second point of the trigon.
5059 \param x3 X coordinate of the third point of the trigon.
5060 \param y3 Y coordinate of the third point of the trigon.
5061 \param r The red value of the trigon to draw.
5062 \param g The green value of the trigon to draw.
5063 \param b The blue value of the trigon to draw.
5064 \param a The alpha value of the trigon to draw.
5065 
5066 \returns Returns 0 on success, -1 on failure.
5067 */
trigonRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5068 int trigonRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
5069 	Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5070 {
5071 	Sint16 vx[3];
5072 	Sint16 vy[3];
5073 
5074 	vx[0]=x1;
5075 	vx[1]=x2;
5076 	vx[2]=x3;
5077 	vy[0]=y1;
5078 	vy[1]=y2;
5079 	vy[2]=y3;
5080 
5081 	return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
5082 }
5083 
5084 /* ------ AA-Trigon */
5085 
5086 /*!
5087 \brief Draw anti-aliased trigon (triangle outline) with alpha blending.
5088 
5089 Note: Creates vertex array and uses aapolygon routine to render.
5090 
5091 \param dst The surface to draw on.
5092 \param x1 X coordinate of the first point of the aa-trigon.
5093 \param y1 Y coordinate of the first point of the aa-trigon.
5094 \param x2 X coordinate of the second point of the aa-trigon.
5095 \param y2 Y coordinate of the second point of the aa-trigon.
5096 \param x3 X coordinate of the third point of the aa-trigon.
5097 \param y3 Y coordinate of the third point of the aa-trigon.
5098 \param color The color value of the aa-trigon to draw (0xRRGGBBAA).
5099 
5100 \returns Returns 0 on success, -1 on failure.
5101 */
aatrigonColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)5102 int aatrigonColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
5103 {
5104 	Sint16 vx[3];
5105 	Sint16 vy[3];
5106 
5107 	vx[0]=x1;
5108 	vx[1]=x2;
5109 	vx[2]=x3;
5110 	vy[0]=y1;
5111 	vy[1]=y2;
5112 	vy[2]=y3;
5113 
5114 	return(aapolygonColor(dst,vx,vy,3,color));
5115 }
5116 
5117 /*!
5118 \brief Draw anti-aliased trigon (triangle outline) with alpha blending.
5119 
5120 \param dst The surface to draw on.
5121 \param x1 X coordinate of the first point of the aa-trigon.
5122 \param y1 Y coordinate of the first point of the aa-trigon.
5123 \param x2 X coordinate of the second point of the aa-trigon.
5124 \param y2 Y coordinate of the second point of the aa-trigon.
5125 \param x3 X coordinate of the third point of the aa-trigon.
5126 \param y3 Y coordinate of the third point of the aa-trigon.
5127 \param r The red value of the aa-trigon to draw.
5128 \param g The green value of the aa-trigon to draw.
5129 \param b The blue value of the aa-trigon to draw.
5130 \param a The alpha value of the aa-trigon to draw.
5131 
5132 \returns Returns 0 on success, -1 on failure.
5133 */
aatrigonRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5134 int aatrigonRGBA(RSDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
5135 	Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5136 {
5137 	Sint16 vx[3];
5138 	Sint16 vy[3];
5139 
5140 	vx[0]=x1;
5141 	vx[1]=x2;
5142 	vx[2]=x3;
5143 	vy[0]=y1;
5144 	vy[1]=y2;
5145 	vy[2]=y3;
5146 
5147 	return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
5148 }
5149 
5150 /* ------ Filled Trigon */
5151 
5152 /*!
5153 \brief Draw filled trigon (triangle) with alpha blending.
5154 
5155 Note: Creates vertex array and uses aapolygon routine to render.
5156 
5157 \param dst The surface to draw on.
5158 \param x1 X coordinate of the first point of the filled trigon.
5159 \param y1 Y coordinate of the first point of the filled trigon.
5160 \param x2 X coordinate of the second point of the filled trigon.
5161 \param y2 Y coordinate of the second point of the filled trigon.
5162 \param x3 X coordinate of the third point of the filled trigon.
5163 \param y3 Y coordinate of the third point of the filled trigon.
5164 \param color The color value of the filled trigon to draw (0xRRGGBBAA).
5165 
5166 \returns Returns 0 on success, -1 on failure.
5167 */
filledTrigonColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)5168 int filledTrigonColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
5169 {
5170 	Sint16 vx[3];
5171 	Sint16 vy[3];
5172 
5173 	vx[0]=x1;
5174 	vx[1]=x2;
5175 	vx[2]=x3;
5176 	vy[0]=y1;
5177 	vy[1]=y2;
5178 	vy[2]=y3;
5179 
5180 	return(filledPolygonColor(dst,vx,vy,3,color));
5181 }
5182 
5183 /*!
5184 \brief Draw filled trigon (triangle) with alpha blending.
5185 
5186 Note: Creates vertex array and uses aapolygon routine to render.
5187 
5188 \param dst The surface to draw on.
5189 \param x1 X coordinate of the first point of the filled trigon.
5190 \param y1 Y coordinate of the first point of the filled trigon.
5191 \param x2 X coordinate of the second point of the filled trigon.
5192 \param y2 Y coordinate of the second point of the filled trigon.
5193 \param x3 X coordinate of the third point of the filled trigon.
5194 \param y3 Y coordinate of the third point of the filled trigon.
5195 \param r The red value of the filled trigon to draw.
5196 \param g The green value of the filled trigon to draw.
5197 \param b The blue value of the filled trigon to draw.
5198 \param a The alpha value of the filled trigon to draw.
5199 
5200 \returns Returns 0 on success, -1 on failure.
5201 */
filledTrigonRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5202 int filledTrigonRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
5203 	Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5204 {
5205 	Sint16 vx[3];
5206 	Sint16 vy[3];
5207 
5208 	vx[0]=x1;
5209 	vx[1]=x2;
5210 	vx[2]=x3;
5211 	vy[0]=y1;
5212 	vy[1]=y2;
5213 	vy[2]=y3;
5214 
5215 	return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
5216 }
5217 
5218 /* ---- Polygon */
5219 
5220 /*!
5221 \brief Draw polygon with alpha blending.
5222 
5223 \param dst The surface to draw on.
5224 \param vx Vertex array containing X coordinates of the points of the polygon.
5225 \param vy Vertex array containing Y coordinates of the points of the polygon.
5226 \param n Number of points in the vertex array. Minimum number is 3.
5227 \param color The color value of the polygon to draw (0xRRGGBBAA).
5228 
5229 \returns Returns 0 on success, -1 on failure.
5230 */
polygonColor(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)5231 int polygonColor(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5232 {
5233 	int result;
5234 	int i;
5235 	const Sint16 *x1, *y1, *x2, *y2;
5236 
5237 	/*
5238 	* Check visibility of clipping rectangle
5239 	*/
5240 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
5241 		return(0);
5242 	}
5243 
5244 	/*
5245 	* Vertex array NULL check
5246 	*/
5247 	if (vx == NULL) {
5248 		return (-1);
5249 	}
5250 	if (vy == NULL) {
5251 		return (-1);
5252 	}
5253 
5254 	/*
5255 	* Sanity check
5256 	*/
5257 	if (n < 3) {
5258 		return (-1);
5259 	}
5260 
5261 	/*
5262 	* Pointer setup
5263 	*/
5264 	x1 = x2 = vx;
5265 	y1 = y2 = vy;
5266 	x2++;
5267 	y2++;
5268 
5269 	/*
5270 	* Draw
5271 	*/
5272 	result = 0;
5273 	for (i = 1; i < n; i++) {
5274 		result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
5275 		x1 = x2;
5276 		y1 = y2;
5277 		x2++;
5278 		y2++;
5279 	}
5280 	result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
5281 
5282 	return (result);
5283 }
5284 
5285 /*!
5286 \brief Draw polygon with alpha blending.
5287 
5288 \param dst The surface to draw on.
5289 \param vx Vertex array containing X coordinates of the points of the polygon.
5290 \param vy Vertex array containing Y coordinates of the points of the polygon.
5291 \param n Number of points in the vertex array. Minimum number is 3.
5292 \param r The red value of the polygon to draw.
5293 \param g The green value of the polygon to draw.
5294 \param b The blue value of the polygon to draw.
5295 \param a The alpha value of the polygon to draw.
5296 
5297 \returns Returns 0 on success, -1 on failure.
5298 */
polygonRGBA(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5299 int polygonRGBA(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5300 {
5301 	/*
5302 	* Draw
5303 	*/
5304 	return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
5305 }
5306 
5307 /* ---- AA-Polygon */
5308 
5309 /*!
5310 \brief Draw anti-aliased polygon with alpha blending.
5311 
5312 \param dst The surface to draw on.
5313 \param vx Vertex array containing X coordinates of the points of the aa-polygon.
5314 \param vy Vertex array containing Y coordinates of the points of the aa-polygon.
5315 \param n Number of points in the vertex array. Minimum number is 3.
5316 \param color The color value of the aa-polygon to draw (0xRRGGBBAA).
5317 
5318 \returns Returns 0 on success, -1 on failure.
5319 */
aapolygonColor(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)5320 int aapolygonColor(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5321 {
5322 	int result;
5323 	int i;
5324 	const Sint16 *x1, *y1, *x2, *y2;
5325 
5326 	/*
5327 	* Check visibility of clipping rectangle
5328 	*/
5329 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
5330 		return(0);
5331 	}
5332 
5333 	/*
5334 	* Vertex array NULL check
5335 	*/
5336 	if (vx == NULL) {
5337 		return (-1);
5338 	}
5339 	if (vy == NULL) {
5340 		return (-1);
5341 	}
5342 
5343 	/*
5344 	* Sanity check
5345 	*/
5346 	if (n < 3) {
5347 		return (-1);
5348 	}
5349 
5350 	/*
5351 	* Pointer setup
5352 	*/
5353 	x1 = x2 = vx;
5354 	y1 = y2 = vy;
5355 	x2++;
5356 	y2++;
5357 
5358 	/*
5359 	* Draw
5360 	*/
5361 	result = 0;
5362 	for (i = 1; i < n; i++) {
5363 		result |= _aalineColor(dst, *x1, *y1, *x2, *y2, color, 0);
5364 		x1 = x2;
5365 		y1 = y2;
5366 		x2++;
5367 		y2++;
5368 	}
5369 	result |= _aalineColor(dst, *x1, *y1, *vx, *vy, color, 0);
5370 
5371 	return (result);
5372 }
5373 
5374 /*!
5375 \brief Draw anti-aliased polygon with alpha blending.
5376 
5377 \param dst The surface to draw on.
5378 \param vx Vertex array containing X coordinates of the points of the aa-polygon.
5379 \param vy Vertex array containing Y coordinates of the points of the aa-polygon.
5380 \param n Number of points in the vertex array. Minimum number is 3.
5381 \param r The red value of the aa-polygon to draw.
5382 \param g The green value of the aa-polygon to draw.
5383 \param b The blue value of the aa-polygon to draw.
5384 \param a The alpha value of the aa-polygon to draw.
5385 
5386 \returns Returns 0 on success, -1 on failure.
5387 */
aapolygonRGBA(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5388 int aapolygonRGBA(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5389 {
5390 	/*
5391 	* Draw
5392 	*/
5393 	return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
5394 }
5395 
5396 /* ---- Filled Polygon */
5397 
5398 /*!
5399 \brief Internal helper qsort callback functions used in filled polygon drawing.
5400 
5401 \param a The surface to draw on.
5402 \param b Vertex array containing X coordinates of the points of the polygon.
5403 
5404 \returns Returns 0 if a==b, a negative number if a<b or a positive number if a>b.
5405 */
_gfxPrimitivesCompareInt(const void * a,const void * b)5406 int _gfxPrimitivesCompareInt(const void *a, const void *b)
5407 {
5408 	return (*(const int *) a) - (*(const int *) b);
5409 }
5410 
5411 /*!
5412 \brief Global vertex array to use if optional parameters are not given in filledPolygonMT calls.
5413 
5414 Note: Used for non-multithreaded (default) operation of filledPolygonMT.
5415 */
5416 static int *gfxPrimitivesPolyIntsGlobal = NULL;
5417 
5418 /*!
5419 \brief Flag indicating if global vertex array was already allocated.
5420 
5421 Note: Used for non-multithreaded (default) operation of filledPolygonMT.
5422 */
5423 static int gfxPrimitivesPolyAllocatedGlobal = 0;
5424 
5425 /*!
5426 \brief Draw filled polygon with alpha blending (multi-threaded capable).
5427 
5428 Note: The last two parameters are optional; but are required for multithreaded operation.
5429 
5430 \param dst The surface to draw on.
5431 \param vx Vertex array containing X coordinates of the points of the filled polygon.
5432 \param vy Vertex array containing Y coordinates of the points of the filled polygon.
5433 \param n Number of points in the vertex array. Minimum number is 3.
5434 \param color The color value of the filled polygon to draw (0xRRGGBBAA).
5435 \param polyInts Preallocated, temporary vertex array used for sorting vertices. Required for multithreaded operation; set to NULL otherwise.
5436 \param polyAllocated Flag indicating if temporary vertex array was allocated. Required for multithreaded operation; set to NULL otherwise.
5437 
5438 \returns Returns 0 on success, -1 on failure.
5439 */
filledPolygonColorMT(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color,int ** polyInts,int * polyAllocated)5440 int filledPolygonColorMT(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
5441 {
5442 	int result;
5443 	int i;
5444 	int y, xa, xb;
5445 	int miny, maxy;
5446 	int x1, y1;
5447 	int x2, y2;
5448 	int ind1, ind2;
5449 	int ints;
5450 	int *gfxPrimitivesPolyInts = NULL;
5451 	int *gfxPrimitivesPolyIntsNew = NULL;
5452 	int gfxPrimitivesPolyAllocated = 0;
5453 
5454 	/*
5455 	* Check visibility of clipping rectangle
5456 	*/
5457 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
5458 		return(0);
5459 	}
5460 
5461 	/*
5462 	* Vertex array NULL check
5463 	*/
5464 	if (vx == NULL) {
5465 		return (-1);
5466 	}
5467 	if (vy == NULL) {
5468 		return (-1);
5469 	}
5470 
5471 	/*
5472 	* Sanity check number of edges
5473 	*/
5474 	if (n < 3) {
5475 		return -1;
5476 	}
5477 
5478 	/*
5479 	* Map polygon cache
5480 	*/
5481 	if ((polyInts==NULL) || (polyAllocated==NULL)) {
5482 		/* Use global cache */
5483 		gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
5484 		gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
5485 	} else {
5486 		/* Use local cache */
5487 		gfxPrimitivesPolyInts = *polyInts;
5488 		gfxPrimitivesPolyAllocated = *polyAllocated;
5489 	}
5490 
5491 	/*
5492 	* Allocate temp array, only grow array
5493 	*/
5494 	if (!gfxPrimitivesPolyAllocated) {
5495 		gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
5496 		gfxPrimitivesPolyAllocated = n;
5497 	} else {
5498 		if (gfxPrimitivesPolyAllocated < n) {
5499 			gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
5500 			if (!gfxPrimitivesPolyIntsNew) {
5501 				if (!gfxPrimitivesPolyInts) {
5502 					free(gfxPrimitivesPolyInts);
5503 					gfxPrimitivesPolyInts = NULL;
5504 				}
5505 				gfxPrimitivesPolyAllocated = 0;
5506 			} else {
5507 				gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
5508 				gfxPrimitivesPolyAllocated = n;
5509 			}
5510 		}
5511 	}
5512 
5513 	/*
5514 	* Check temp array
5515 	*/
5516 	if (gfxPrimitivesPolyInts==NULL) {
5517 		gfxPrimitivesPolyAllocated = 0;
5518 	}
5519 
5520 	/*
5521 	* Update cache variables
5522 	*/
5523 	if ((polyInts==NULL) || (polyAllocated==NULL)) {
5524 		gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
5525 		gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
5526 	} else {
5527 		*polyInts = gfxPrimitivesPolyInts;
5528 		*polyAllocated = gfxPrimitivesPolyAllocated;
5529 	}
5530 
5531 	/*
5532 	* Check temp array again
5533 	*/
5534 	if (gfxPrimitivesPolyInts==NULL) {
5535 		return(-1);
5536 	}
5537 
5538 	/*
5539 	* Determine Y maxima
5540 	*/
5541 	miny = vy[0];
5542 	maxy = vy[0];
5543 	for (i = 1; (i < n); i++) {
5544 		if (vy[i] < miny) {
5545 			miny = vy[i];
5546 		} else if (vy[i] > maxy) {
5547 			maxy = vy[i];
5548 		}
5549 	}
5550 
5551 	/*
5552 	* Draw, scanning y
5553 	*/
5554 	result = 0;
5555 	for (y = miny; (y <= maxy); y++) {
5556 		ints = 0;
5557 		for (i = 0; (i < n); i++) {
5558 			if (!i) {
5559 				ind1 = n - 1;
5560 				ind2 = 0;
5561 			} else {
5562 				ind1 = i - 1;
5563 				ind2 = i;
5564 			}
5565 			y1 = vy[ind1];
5566 			y2 = vy[ind2];
5567 			if (y1 < y2) {
5568 				x1 = vx[ind1];
5569 				x2 = vx[ind2];
5570 			} else if (y1 > y2) {
5571 				y2 = vy[ind1];
5572 				y1 = vy[ind2];
5573 				x2 = vx[ind1];
5574 				x1 = vx[ind2];
5575 			} else {
5576 				continue;
5577 			}
5578 			if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
5579 				gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
5580 			}
5581 		}
5582 
5583 		qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
5584 
5585 		for (i = 0; (i < ints); i += 2) {
5586 			xa = gfxPrimitivesPolyInts[i] + 1;
5587 			xa = (xa >> 16) + ((xa & 32768) >> 15);
5588 			xb = gfxPrimitivesPolyInts[i+1] - 1;
5589 			xb = (xb >> 16) + ((xb & 32768) >> 15);
5590 			result |= hlineColor(dst, xa, xb, y, color);
5591 		}
5592 	}
5593 
5594 	return (result);
5595 }
5596 
5597 /*!
5598 \brief Draw filled polygon with alpha blending (multi-threaded capable).
5599 
5600 Note: The last two parameters are optional; but are required for multithreaded operation.
5601 
5602 \param dst The surface to draw on.
5603 \param vx Vertex array containing X coordinates of the points of the filled polygon.
5604 \param vy Vertex array containing Y coordinates of the points of the filled polygon.
5605 \param n Number of points in the vertex array. Minimum number is 3.
5606 \param r The red value of the filled polygon to draw.
5607 \param g The green value of the filled polygon to draw.
5608 \param b The blue value of the filed polygon to draw.
5609 \param a The alpha value of the filled polygon to draw.
5610 \param polyInts Preallocated, temporary vertex array used for sorting vertices. Required for multithreaded operation; set to NULL otherwise.
5611 \param polyAllocated Flag indicating if temporary vertex array was allocated. Required for multithreaded operation; set to NULL otherwise.
5612 
5613 \returns Returns 0 on success, -1 on failure.
5614 */
filledPolygonRGBAMT(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a,int ** polyInts,int * polyAllocated)5615 int filledPolygonRGBAMT(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
5616 {
5617 	/*
5618 	* Draw
5619 	*/
5620 	return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
5621 }
5622 
5623 /*!
5624 \brief Draw filled polygon with alpha blending.
5625 
5626 Note: Standard filledPolygon function is calling multithreaded version with NULL parameters
5627 to use the global vertex cache.
5628 
5629 \param dst The surface to draw on.
5630 \param vx Vertex array containing X coordinates of the points of the filled polygon.
5631 \param vy Vertex array containing Y coordinates of the points of the filled polygon.
5632 \param n Number of points in the vertex array. Minimum number is 3.
5633 \param color The color value of the filled polygon to draw (0xRRGGBBAA).
5634 
5635 \returns Returns 0 on success, -1 on failure.
5636 */
filledPolygonColor(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)5637 int filledPolygonColor(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5638 {
5639 	/*
5640 	* Draw
5641 	*/
5642 	return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
5643 }
5644 
5645 /*!
5646 \brief Draw filled polygon with alpha blending.
5647 
5648 \param dst The surface to draw on.
5649 \param vx Vertex array containing X coordinates of the points of the filled polygon.
5650 \param vy Vertex array containing Y coordinates of the points of the filled polygon.
5651 \param n Number of points in the vertex array. Minimum number is 3.
5652 \param r The red value of the filled polygon to draw.
5653 \param g The green value of the filled polygon to draw.
5654 \param b The blue value of the filed polygon to draw.
5655 \param a The alpha value of the filled polygon to draw.
5656 
5657 \returns Returns 0 on success, -1 on failure.
5658 */
filledPolygonRGBA(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)5659 int filledPolygonRGBA(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5660 {
5661 	/*
5662 	* Draw
5663 	*/
5664 	return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
5665 }
5666 
5667 #if 0
5668 /*!
5669 \brief Internal function to draw a textured horizontal line.
5670 
5671 \param dst The surface to draw on.
5672 \param x1 X coordinate of the first point (i.e. left) of the line.
5673 \param x2 X coordinate of the second point (i.e. right) of the line.
5674 \param y Y coordinate of the points of the line.
5675 \param texture The texture surface to retrieve color information from.
5676 \param texture_dx The X offset for the texture lookup.
5677 \param texture_dy The Y offset for the textured lookup.
5678 
5679 \returns Returns 0 on success, -1 on failure.
5680 */
5681 int _HLineTextured(RSDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, RSDL_Surface *texture, int texture_dx, int texture_dy)
5682 {
5683 	Sint16 left, right, top, bottom;
5684 	Sint16 w;
5685 	Sint16 xtmp;
5686 	int result = 0;
5687 	int texture_x_walker;
5688 	int texture_y_start;
5689 	RSDL_Rect source_rect,dst_rect;
5690 	int pixels_written,write_width;
5691 
5692 	/*
5693 	* Check visibility of clipping rectangle
5694 	*/
5695 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
5696 		return(0);
5697 	}
5698 
5699 	/*
5700 	* Swap x1, x2 if required to ensure x1<=x2
5701 	*/
5702 	if (x1 > x2) {
5703 		xtmp = x1;
5704 		x1 = x2;
5705 		x2 = xtmp;
5706 	}
5707 
5708 	/*
5709 	* Get clipping boundary and
5710 	* check visibility of hline
5711 	*/
5712 	left = dst->clip_rect.x;
5713 	if (x2<left) {
5714 		return(0);
5715 	}
5716 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
5717 	if (x1>right) {
5718 		return(0);
5719 	}
5720 	top = dst->clip_rect.y;
5721 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
5722 	if ((y<top) || (y>bottom)) {
5723 		return (0);
5724 	}
5725 
5726 	/*
5727 	* Clip x
5728 	*/
5729 	if (x1 < left) {
5730 		x1 = left;
5731 	}
5732 	if (x2 > right) {
5733 		x2 = right;
5734 	}
5735 
5736 	/*
5737 	* Calculate width to draw
5738 	*/
5739 	w = x2 - x1 + 1;
5740 
5741 	/*
5742 	* Determine where in the texture we start drawing
5743 	*/
5744 	texture_x_walker =   (x1 - texture_dx)  % texture->w;
5745 	if (texture_x_walker < 0){
5746 		texture_x_walker = texture->w + texture_x_walker ;
5747 	}
5748 
5749 	texture_y_start = (y + texture_dy) % texture->h;
5750 	if (texture_y_start < 0){
5751 		texture_y_start = texture->h + texture_y_start;
5752 	}
5753 
5754 	// setup the source rectangle; we are only drawing one horizontal line
5755 	source_rect.y = texture_y_start;
5756 	source_rect.x = texture_x_walker;
5757 	source_rect.h = 1;
5758 
5759 	// we will draw to the current y
5760 	dst_rect.y = y;
5761 
5762 	// if there are enough pixels left in the current row of the texture
5763 	// draw it all at once
5764 	if (w <= texture->w -texture_x_walker){
5765 		source_rect.w = w;
5766 		source_rect.x = texture_x_walker;
5767 		dst_rect.x= x1;
5768 		result = (RSDL_BlitSurface  (texture, &source_rect , dst, &dst_rect) == 0);
5769 	} else { // we need to draw multiple times
5770 		// draw the first segment
5771 		pixels_written = texture->w  - texture_x_walker;
5772 		source_rect.w = pixels_written;
5773 		source_rect.x = texture_x_walker;
5774 		dst_rect.x= x1;
5775 		result |= (RSDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
5776 		write_width = texture->w;
5777 
5778 		// now draw the rest
5779 		// set the source x to 0
5780 		source_rect.x = 0;
5781 		while (pixels_written < w){
5782 			if (write_width >= w - pixels_written) {
5783 				write_width =  w - pixels_written;
5784 			}
5785 			source_rect.w = write_width;
5786 			dst_rect.x = x1 + pixels_written;
5787 			result  |= (RSDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) == 0);
5788 			pixels_written += write_width;
5789 		}
5790 	}
5791 
5792 	return result;
5793 }
5794 
5795 /*!
5796 \brief Draws a polygon filled with the given texture (Multi-Threading Capable).
5797 
5798 This operation use internally RSDL_BlitSurface for lines of the source texture. It supports
5799 alpha drawing.
5800 
5801 To get the best performance of this operation you need to make sure the texture and the dst surface have the same format
5802 (see  http://docs.mandragor.org/files/Common_libs_documentation/SDL/RSDL_Documentation_project_en/sdlblitsurface.html).
5803 The last two parameters are optional, but required for multithreaded operation. When set to NULL, uses global static temp array.
5804 
5805 \param dst the destination surface,
5806 \param vx array of x vector components
5807 \param vy array of x vector components
5808 \param n the amount of vectors in the vx and vy array
5809 \param texture the sdl surface to use to fill the polygon
5810 \param texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels
5811 to the left and want the texture to apear the same you need to increase the texture_dx value
5812 \param texture_dy see texture_dx
5813 \param polyInts preallocated temp array storage for vertex sorting (used for multi-threaded operation)
5814 \param polyAllocated flag indicating oif the temp array was allocated (used for multi-threaded operation)
5815 
5816 \returns Returns 0 on success, -1 on failure.
5817 */
5818 int texturedPolygonMT(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n,
5819 	RSDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
5820 {
5821 	int result;
5822 	int i;
5823 	int y, xa, xb;
5824 	int minx,maxx,miny, maxy;
5825 	int x1, y1;
5826 	int x2, y2;
5827 	int ind1, ind2;
5828 	int ints;
5829 	int *gfxPrimitivesPolyInts = NULL;
5830 	int gfxPrimitivesPolyAllocated = 0;
5831 
5832 	/*
5833 	* Check visibility of clipping rectangle
5834 	*/
5835 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
5836 		return(0);
5837 	}
5838 
5839 	/*
5840 	* Sanity check number of edges
5841 	*/
5842 	if (n < 3) {
5843 		return -1;
5844 	}
5845 
5846 	/*
5847 	* Map polygon cache
5848 	*/
5849 	if ((polyInts==NULL) || (polyAllocated==NULL)) {
5850 		/* Use global cache */
5851 		gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
5852 		gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
5853 	} else {
5854 		/* Use local cache */
5855 		gfxPrimitivesPolyInts = *polyInts;
5856 		gfxPrimitivesPolyAllocated = *polyAllocated;
5857 	}
5858 
5859 	/*
5860 	* Allocate temp array, only grow array
5861 	*/
5862 	if (!gfxPrimitivesPolyAllocated) {
5863 		gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
5864 		gfxPrimitivesPolyAllocated = n;
5865 	} else {
5866 		if (gfxPrimitivesPolyAllocated < n) {
5867 			gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
5868 			gfxPrimitivesPolyAllocated = n;
5869 		}
5870 	}
5871 
5872 	/*
5873 	* Check temp array
5874 	*/
5875 	if (gfxPrimitivesPolyInts==NULL) {
5876 		gfxPrimitivesPolyAllocated = 0;
5877 	}
5878 
5879 	/*
5880 	* Update cache variables
5881 	*/
5882 	if ((polyInts==NULL) || (polyAllocated==NULL)) {
5883 		gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
5884 		gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
5885 	} else {
5886 		*polyInts = gfxPrimitivesPolyInts;
5887 		*polyAllocated = gfxPrimitivesPolyAllocated;
5888 	}
5889 
5890 	/*
5891 	* Check temp array again
5892 	*/
5893 	if (gfxPrimitivesPolyInts==NULL) {
5894 		return(-1);
5895 	}
5896 
5897 	/*
5898 	* Determine X,Y minima,maxima
5899 	*/
5900 	miny = vy[0];
5901 	maxy = vy[0];
5902 	minx = vx[0];
5903 	maxx = vx[0];
5904 	for (i = 1; (i < n); i++) {
5905 		if (vy[i] < miny) {
5906 			miny = vy[i];
5907 		} else if (vy[i] > maxy) {
5908 			maxy = vy[i];
5909 		}
5910 		if (vx[i] < minx) {
5911 			minx = vx[i];
5912 		} else if (vx[i] > maxx) {
5913 			maxx = vx[i];
5914 		}
5915 	}
5916 	if (maxx <0 || minx > dst->w){
5917 		return -1;
5918 	}
5919 	if (maxy <0 || miny > dst->h){
5920 		return -1;
5921 	}
5922 
5923 	/*
5924 	* Draw, scanning y
5925 	*/
5926 	result = 0;
5927 	for (y = miny; (y <= maxy); y++) {
5928 		ints = 0;
5929 		for (i = 0; (i < n); i++) {
5930 			if (!i) {
5931 				ind1 = n - 1;
5932 				ind2 = 0;
5933 			} else {
5934 				ind1 = i - 1;
5935 				ind2 = i;
5936 			}
5937 			y1 = vy[ind1];
5938 			y2 = vy[ind2];
5939 			if (y1 < y2) {
5940 				x1 = vx[ind1];
5941 				x2 = vx[ind2];
5942 			} else if (y1 > y2) {
5943 				y2 = vy[ind1];
5944 				y1 = vy[ind2];
5945 				x2 = vx[ind1];
5946 				x1 = vx[ind2];
5947 			} else {
5948 				continue;
5949 			}
5950 			if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
5951 				gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
5952 			}
5953 		}
5954 
5955 		qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
5956 
5957 		for (i = 0; (i < ints); i += 2) {
5958 			xa = gfxPrimitivesPolyInts[i] + 1;
5959 			xa = (xa >> 16) + ((xa & 32768) >> 15);
5960 			xb = gfxPrimitivesPolyInts[i+1] - 1;
5961 			xb = (xb >> 16) + ((xb & 32768) >> 15);
5962 			result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
5963 		}
5964 	}
5965 
5966 	return (result);
5967 }
5968 
5969 /*!
5970 \brief Draws a polygon filled with the given texture.
5971 
5972 This standard version is calling multithreaded versions with NULL cache parameters.
5973 
5974 \param dst the destination surface,
5975 \param vx array of x vector components
5976 \param vy array of x vector components
5977 \param n the amount of vectors in the vx and vy array
5978 \param texture the sdl surface to use to fill the polygon
5979 \param texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels
5980 to the left and want the texture to apear the same you need to increase the texture_dx value
5981 \param texture_dy see texture_dx
5982 
5983 \returns Returns 0 on success, -1 on failure.
5984 */
5985 int texturedPolygon(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, RSDL_Surface *texture, int texture_dx, int texture_dy)
5986 {
5987 	/*
5988 	* Draw
5989 	*/
5990 	return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
5991 }
5992 #endif //IF 0
5993 #if 0
5994 /* ---- Character */
5995 
5996 /*!
5997 \brief Global cache for NxM pixel font surfaces created at runtime.
5998 */
5999 static RSDL_Surface *gfxPrimitivesFont[256];
6000 
6001 /*!
6002 \brief Global cache of the color used for the font surfaces created at runtime.
6003 */
6004 static Uint32 gfxPrimitivesFontColor[256];
6005 
6006 /*!
6007 \brief Pointer to the current font data. Default is a 8x8 pixel internal font.
6008 */
6009 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
6010 
6011 /*!
6012 \brief Width of the current font. Default is 8.
6013 */
6014 static Uint32 charWidth = 8;
6015 
6016 /*!
6017 \brief Height of the current font. Default is 8.
6018 */
6019 static Uint32 charHeight = 8;
6020 
6021 /*!
6022 \brief Width for rendering. Autocalculated.
6023 */
6024 static Uint32 charWidthLocal = 8;
6025 
6026 /*!
6027 \brief Height for rendering. Autocalculated.
6028 */
6029 static Uint32 charHeightLocal = 8;
6030 
6031 /*!
6032 \brief Pitch of the current font in bytes. Default is 1.
6033 */
6034 static Uint32 charPitch = 1;
6035 
6036 /*!
6037 \brief Characters 90deg clockwise rotations. Default is 0. Max is 3.
6038 */
6039 static Uint32 charRotation = 0;
6040 
6041 /*!
6042 \brief Character data size in bytes of the current font. Default is 8.
6043 */
6044 static Uint32 charSize = 8;
6045 
6046 /*!
6047 \brief Sets or resets the current global font data.
6048 
6049 The font data array is organized in follows:
6050 [fontdata] = [character 0][character 1]...[character 255] where
6051 [character n] = [byte 1 row 1][byte 2 row 1]...[byte {pitch} row 1][byte 1 row 2] ...[byte {pitch} row height] where
6052 [byte n] = [bit 0]...[bit 7] where
6053 [bit n] = [0 for transparent pixel|1 for colored pixel]
6054 
6055 \param fontdata Pointer to array of font data. Set to NULL, to reset global font to the default 8x8 font.
6056 \param cw Width of character in bytes. Ignored if fontdata==NULL.
6057 \param ch Height of character in bytes. Ignored if fontdata==NULL.
6058 */
6059 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
6060 {
6061 	int i;
6062 
6063 	if ((fontdata) && (cw) && (ch)) {
6064 		currentFontdata = fontdata;
6065 		charWidth = cw;
6066 		charHeight = ch;
6067 	} else {
6068 		currentFontdata = gfxPrimitivesFontdata;
6069 		charWidth = 8;
6070 		charHeight = 8;
6071 	}
6072 
6073 	charPitch = (charWidth+7)/8;
6074 	charSize = charPitch * charHeight;
6075 
6076 	/* Maybe flip width/height for rendering */
6077 	if ((charRotation==1) || (charRotation==3))
6078 	{
6079 		charWidthLocal = charHeight;
6080 		charHeightLocal = charWidth;
6081 	}
6082 	else
6083 	{
6084 		charWidthLocal = charWidth;
6085 		charHeightLocal = charHeight;
6086 	}
6087 
6088 	/* Clear character cache */
6089 	for (i = 0; i < 256; i++) {
6090 		if (gfxPrimitivesFont[i]) {
6091 			RSDL_FreeSurface(gfxPrimitivesFont[i]);
6092 			gfxPrimitivesFont[i] = NULL;
6093 		}
6094 	}
6095 }
6096 
6097 /*!
6098 \brief Sets current global font character rotation steps.
6099 
6100 Default is 0 (no rotation). 1 = 90deg clockwise. 2 = 180deg clockwise. 3 = 270deg clockwise.
6101 Changing the rotation, will reset the character cache.
6102 
6103 \param rotation Number of 90deg clockwise steps to rotate
6104 */
6105 void gfxPrimitivesSetFontRotation(Uint32 rotation)
6106 {
6107 	int i;
6108 
6109 	rotation = rotation & 3;
6110 	if (charRotation != rotation)
6111 	{
6112 		/* Store rotation */
6113 		charRotation = rotation;
6114 
6115 		/* Maybe flip width/height for rendering */
6116 		if ((charRotation==1) || (charRotation==3))
6117 		{
6118 			charWidthLocal = charHeight;
6119 			charHeightLocal = charWidth;
6120 		}
6121 		else
6122 		{
6123 			charWidthLocal = charWidth;
6124 			charHeightLocal = charHeight;
6125 		}
6126 
6127 		/* Clear character cache */
6128 		for (i = 0; i < 256; i++) {
6129 			if (gfxPrimitivesFont[i]) {
6130 				RSDL_FreeSurface(gfxPrimitivesFont[i]);
6131 				gfxPrimitivesFont[i] = NULL;
6132 			}
6133 		}
6134 	}
6135 }
6136 
6137 /*!
6138 \brief Draw a character of the currently set font.
6139 
6140 On first call for a particular character and color combination, the function needs to
6141 generate the character surface (slower. Subsequent calls blit a cached surface (fast).
6142 Uses alpha blending if A<255 in color.
6143 
6144 \param dst The surface to draw on.
6145 \param x X (horizontal) coordinate of the upper left corner of the character.
6146 \param y Y (vertical) coordinate of the upper left corner of the character.
6147 \param c The character to draw.
6148 \param color The color value of the character to draw (0xRRGGBBAA).
6149 
6150 \returns Returns 0 on success, -1 on failure.
6151 */
6152 int characterColor(RSDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color)
6153 {
6154 	Sint16 left, right, top, bottom;
6155 	Sint16 x1, y1, x2, y2;
6156 	RSDL_Rect srect;
6157 	RSDL_Rect drect;
6158 	int result;
6159 	Uint32 ix, iy;
6160 	const unsigned char *charpos;
6161 	Uint8 *curpos;
6162 	int forced_redraw;
6163 	Uint8 patt, mask;
6164 	Uint8 *linepos;
6165 	Uint32 pitch;
6166 	RSDL_Surface *rotatedCharacter;
6167 	Uint32 ci;
6168 
6169 	/*
6170 	* Check visibility of clipping rectangle
6171 	*/
6172 	if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
6173 		return(0);
6174 	}
6175 
6176 	/*
6177 	* Get text and clipping boundary and
6178 	* test if bounding box of character is visible
6179 	*/
6180 
6181 	left = dst->clip_rect.x;
6182 	x2 = x + charWidthLocal;
6183 	if (x2<left) {
6184 		return(0);
6185 	}
6186 	right = dst->clip_rect.x + dst->clip_rect.w - 1;
6187 	x1 = x;
6188 	if (x1>right) {
6189 		return(0);
6190 	}
6191 	top = dst->clip_rect.y;
6192 	y2 = y + charHeightLocal;
6193 	if (y2<top) {
6194 		return(0);
6195 	}
6196 	bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
6197 	y1 = y;
6198 	if (y1>bottom) {
6199 		return(0);
6200 	}
6201 
6202 	/*
6203 	* Setup source rectangle
6204 	*/
6205 	srect.x = 0;
6206 	srect.y = 0;
6207 	srect.w = charWidthLocal;
6208 	srect.h = charHeightLocal;
6209 
6210 	/*
6211 	* Setup destination rectangle
6212 	*/
6213 	drect.x = x;
6214 	drect.y = y;
6215 	drect.w = charWidthLocal;
6216 	drect.h = charHeightLocal;
6217 
6218 	/* Character index in cache */
6219 	ci = (unsigned char) c;
6220 
6221 	/*
6222 	* Create new charWidth x charHeight bitmap surface if not already present.
6223 	* Might get rotated later.
6224 	*/
6225 	if (gfxPrimitivesFont[ci] == NULL) {
6226 		gfxPrimitivesFont[ci] =
6227 			RSDL_CreateRGBSurface(RSDL_SWSURFACE | RSDL_HWSURFACE | RSDL_SRCALPHA,
6228 			charWidth, charHeight, 32,
6229 			0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
6230 		/*
6231 		* Check pointer
6232 		*/
6233 		if (gfxPrimitivesFont[ci] == NULL) {
6234 			return (-1);
6235 		}
6236 		/*
6237 		* Definitely redraw
6238 		*/
6239 		forced_redraw = 1;
6240 	} else {
6241 		forced_redraw = 0;
6242 	}
6243 
6244 	/*
6245 	* Check if color has changed
6246 	*/
6247 	if ((gfxPrimitivesFontColor[ci] != color) || (forced_redraw)) {
6248 		/*
6249 		* Redraw character
6250 		*/
6251 		RSDL_SetAlpha(gfxPrimitivesFont[ci], RSDL_SRCALPHA, 255);
6252 		gfxPrimitivesFontColor[ci] = color;
6253 
6254 		/* Lock font-surface */
6255 		if (RSDL_LockSurface(gfxPrimitivesFont[ci]) != 0)
6256 			return (-1);
6257 
6258 		/*
6259 		* Variable setup
6260 		*/
6261 		charpos = currentFontdata + ci * charSize;
6262 		linepos = (Uint8 *) gfxPrimitivesFont[ci]->pixels;
6263 		pitch = gfxPrimitivesFont[ci]->pitch;
6264 
6265 		/*
6266 		* Drawing loop
6267 		*/
6268 		patt = 0;
6269 		for (iy = 0; iy < charHeight; iy++) {
6270 			mask = 0x00;
6271 			curpos = linepos;
6272 			for (ix = 0; ix < charWidth; ix++) {
6273 				if (!(mask >>= 1)) {
6274 					patt = *charpos++;
6275 					mask = 0x80;
6276 				}
6277 
6278 				if (patt & mask)
6279 					*(Uint32 *)curpos = color;
6280 				else
6281 					*(Uint32 *)curpos = 0;
6282 				curpos += 4;
6283 			}
6284 			linepos += pitch;
6285 		}
6286 
6287 		/* Unlock font-surface */
6288 		RSDL_UnlockSurface(gfxPrimitivesFont[ci]);
6289 
6290 		/* Maybe rotate and replace cached image */
6291 		if (charRotation>0)
6292 		{
6293 			rotatedCharacter = rotateSurface90Degrees(gfxPrimitivesFont[ci], charRotation);
6294 			RSDL_FreeSurface(gfxPrimitivesFont[ci]);
6295 			gfxPrimitivesFont[ci] = rotatedCharacter;
6296 		}
6297 	}
6298 
6299 	/*
6300 	* Draw bitmap onto destination surface
6301 	*/
6302 	result = RSDL_BlitSurface(gfxPrimitivesFont[ci], &srect, dst, &drect);
6303 
6304 	return (result);
6305 }
6306 
6307 /*!
6308 \brief Draw a character of the currently set font.
6309 
6310 \param dst The surface to draw on.
6311 \param x X (horizontal) coordinate of the upper left corner of the character.
6312 \param y Y (vertical) coordinate of the upper left corner of the character.
6313 \param c The character to draw.
6314 \param r The red value of the character to draw.
6315 \param g The green value of the character to draw.
6316 \param b The blue value of the character to draw.
6317 \param a The alpha value of the character to draw.
6318 
6319 \returns Returns 0 on success, -1 on failure.
6320 */
6321 int characterRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
6322 {
6323 	/*
6324 	* Draw
6325 	*/
6326 	return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
6327 }
6328 
6329 /*!
6330 \brief Draw a string in the currently set font.
6331 
6332 The spacing between consequtive characters in the string is the fixed number of pixels
6333 of the character width of the current global font.
6334 
6335 \param dst The surface to draw on.
6336 \param x X (horizontal) coordinate of the upper left corner of the string.
6337 \param y Y (vertical) coordinate of the upper left corner of the string.
6338 \param s The string to draw.
6339 \param color The color value of the string to draw (0xRRGGBBAA).
6340 
6341 \returns Returns 0 on success, -1 on failure.
6342 */
6343 int stringColor(RSDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint32 color)
6344 {
6345 	int result = 0;
6346 	Sint16 curx = x;
6347 	Sint16 cury = y;
6348 	const char *curchar = s;
6349 
6350 	while (*curchar && !result) {
6351 		result |= characterColor(dst, curx, cury, *curchar, color);
6352 		switch (charRotation)
6353 		{
6354 		case 0:
6355 			curx += charWidthLocal;
6356 			break;
6357 		case 2:
6358 			curx -= charWidthLocal;
6359 			break;
6360 		case 1:
6361 			cury += charHeightLocal;
6362 			break;
6363 		case 3:
6364 			cury -= charHeightLocal;
6365 			break;
6366 		}
6367 		curchar++;
6368 	}
6369 
6370 	return (result);
6371 }
6372 
6373 /*!
6374 \brief Draw a string in the currently set font.
6375 
6376 \param dst The surface to draw on.
6377 \param x X (horizontal) coordinate of the upper left corner of the string.
6378 \param y Y (vertical) coordinate of the upper left corner of the string.
6379 \param s The string to draw.
6380 \param r The red value of the string to draw.
6381 \param g The green value of the string to draw.
6382 \param b The blue value of the string to draw.
6383 \param a The alpha value of the string to draw.
6384 
6385 \returns Returns 0 on success, -1 on failure.
6386 */
6387 int stringRGBA(RSDL_Surface * dst, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
6388 {
6389 	/*
6390 	* Draw
6391 	*/
6392 	return (stringColor(dst, x, y, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
6393 }
6394 
6395 #endif //IF 0
6396 
6397 /* ---- Bezier curve */
6398 
6399 /*!
6400 \brief Internal function to calculate bezier interpolator of data array with ndata values at position 't'.
6401 
6402 \param data Array of values.
6403 \param ndata Size of array.
6404 \param t Position for which to calculate interpolated value. t should be between [0, ndata].
6405 
6406 \returns Interpolated value at position t, value[0] when t<0, value[n-1] when t>n.
6407 */
_evaluateBezier(double * data,int ndata,double t)6408 double _evaluateBezier (double *data, int ndata, double t)
6409 {
6410 	double mu, result;
6411 	int n,k,kn,nn,nkn;
6412 	double blend,muk,munk;
6413 
6414 	/* Sanity check bounds */
6415 	if (t<0.0) {
6416 		return(data[0]);
6417 	}
6418 	if (t>=(double)ndata) {
6419 		return(data[ndata-1]);
6420 	}
6421 
6422 	/* Adjust t to the range 0.0 to 1.0 */
6423 	mu=t/(double)ndata;
6424 
6425 	/* Calculate interpolate */
6426 	n=ndata-1;
6427 	result=0.0;
6428 	muk = 1;
6429 	munk = pow(1-mu,(double)n);
6430 	for (k=0;k<=n;k++) {
6431 		nn = n;
6432 		kn = k;
6433 		nkn = n - k;
6434 		blend = muk * munk;
6435 		muk *= mu;
6436 		munk /= (1-mu);
6437 		while (nn >= 1) {
6438 			blend *= nn;
6439 			nn--;
6440 			if (kn > 1) {
6441 				blend /= (double)kn;
6442 				kn--;
6443 			}
6444 			if (nkn > 1) {
6445 				blend /= (double)nkn;
6446 				nkn--;
6447 			}
6448 		}
6449 		result += data[k] * blend;
6450 	}
6451 
6452 	return (result);
6453 }
6454 
6455 /*!
6456 \brief Draw a bezier curve with alpha blending.
6457 
6458 \param dst The surface to draw on.
6459 \param vx Vertex array containing X coordinates of the points of the bezier curve.
6460 \param vy Vertex array containing Y coordinates of the points of the bezier curve.
6461 \param n Number of points in the vertex array. Minimum number is 3.
6462 \param s Number of steps for the interpolation. Minimum number is 2.
6463 \param color The color value of the bezier curve to draw (0xRRGGBBAA).
6464 
6465 \returns Returns 0 on success, -1 on failure.
6466 */
bezierColor(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,int s,Uint32 color)6467 int bezierColor(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
6468 {
6469 	int result;
6470 	int i;
6471 	double *x, *y, t, stepsize;
6472 	Sint16 x1, y1, x2, y2;
6473 
6474 	/*
6475 	* Sanity check
6476 	*/
6477 	if (n < 3) {
6478 		return (-1);
6479 	}
6480 	if (s < 2) {
6481 		return (-1);
6482 	}
6483 
6484 	/*
6485 	* Variable setup
6486 	*/
6487 	stepsize=(double)1.0/(double)s;
6488 
6489 	/* Transfer vertices into float arrays */
6490 	if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
6491 		return(-1);
6492 	}
6493 	if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
6494 		free(x);
6495 		return(-1);
6496 	}
6497 	for (i=0; i<n; i++) {
6498 		x[i]=(double)vx[i];
6499 		y[i]=(double)vy[i];
6500 	}
6501 	x[n]=(double)vx[0];
6502 	y[n]=(double)vy[0];
6503 
6504 	/*
6505 	* Draw
6506 	*/
6507 	result = 0;
6508 	t=0.0;
6509 	x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
6510 	y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
6511 	for (i = 0; i <= (n*s); i++) {
6512 		t += stepsize;
6513 		x2=(Sint16)_evaluateBezier(x,n,t);
6514 		y2=(Sint16)_evaluateBezier(y,n,t);
6515 		result |= lineColor(dst, x1, y1, x2, y2, color);
6516 		x1 = x2;
6517 		y1 = y2;
6518 	}
6519 
6520 	/* Clean up temporary array */
6521 	free(x);
6522 	free(y);
6523 
6524 	return (result);
6525 }
6526 
6527 /*!
6528 \brief Draw a bezier curve with alpha blending.
6529 
6530 \param dst The surface to draw on.
6531 \param vx Vertex array containing X coordinates of the points of the bezier curve.
6532 \param vy Vertex array containing Y coordinates of the points of the bezier curve.
6533 \param n Number of points in the vertex array. Minimum number is 3.
6534 \param s Number of steps for the interpolation. Minimum number is 2.
6535 \param r The red value of the bezier curve to draw.
6536 \param g The green value of the bezier curve to draw.
6537 \param b The blue value of the bezier curve to draw.
6538 \param a The alpha value of the bezier curve to draw.
6539 
6540 \returns Returns 0 on success, -1 on failure.
6541 */
bezierRGBA(RSDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,int s,Uint8 r,Uint8 g,Uint8 b,Uint8 a)6542 int bezierRGBA(RSDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
6543 {
6544 	/*
6545 	* Draw
6546 	*/
6547 	return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
6548 }
6549 
6550 
6551 /*!
6552 \brief Internal function to initialize the Bresenham line iterator.
6553 
6554 Example of use:
6555 RSDL_gfxBresenhamIterator b;
6556 _bresenhamInitialize (&b, x1, y1, x2, y2);
6557 do {
6558 plot(b.x, b.y);
6559 } while (_bresenhamIterate(&b)==0);
6560 
6561 \param b Pointer to struct for bresenham line drawing state.
6562 \param x1 X coordinate of the first point of the line.
6563 \param y1 Y coordinate of the first point of the line.
6564 \param x2 X coordinate of the second point of the line.
6565 \param y2 Y coordinate of the second point of the line.
6566 
6567 \returns Returns 0 on success, -1 on failure.
6568 */
_bresenhamInitialize(RSDL_gfxBresenhamIterator * b,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2)6569 int _bresenhamInitialize(RSDL_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
6570 {
6571 	int temp;
6572 
6573 	if (b==NULL) {
6574 		return(-1);
6575 	}
6576 
6577 	b->x = x1;
6578 	b->y = y1;
6579 
6580 	/* dx = abs(x2-x1), s1 = sign(x2-x1) */
6581 	if ((b->dx = x2 - x1) != 0) {
6582 		if (b->dx < 0) {
6583 			b->dx = -b->dx;
6584 			b->s1 = -1;
6585 		} else {
6586 			b->s1 = 1;
6587 		}
6588 	} else {
6589 		b->s1 = 0;
6590 	}
6591 
6592 	/* dy = abs(y2-y1), s2 = sign(y2-y1)    */
6593 	if ((b->dy = y2 - y1) != 0) {
6594 		if (b->dy < 0) {
6595 			b->dy = -b->dy;
6596 			b->s2 = -1;
6597 		} else {
6598 			b->s2 = 1;
6599 		}
6600 	} else {
6601 		b->s2 = 0;
6602 	}
6603 
6604 	if (b->dy > b->dx) {
6605 		temp = b->dx;
6606 		b->dx = b->dy;
6607 		b->dy = temp;
6608 		b->swapdir = 1;
6609 	} else {
6610 		b->swapdir = 0;
6611 	}
6612 
6613 	b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
6614 	b->dy <<= 1;
6615 	b->error = b->dy - b->dx;
6616 	b->dx <<= 1;
6617 
6618 	return(0);
6619 }
6620 
6621 
6622 /*!
6623 \brief Internal function to move Bresenham line iterator to the next position.
6624 
6625 Maybe updates the x and y coordinates of the iterator struct.
6626 
6627 \param b Pointer to struct for bresenham line drawing state.
6628 
6629 \returns Returns 0 on success, 1 if last point was reached, 2 if moving past end-of-line, -1 on failure.
6630 */
_bresenhamIterate(RSDL_gfxBresenhamIterator * b)6631 int _bresenhamIterate(RSDL_gfxBresenhamIterator *b)
6632 {
6633 	if (b==NULL) {
6634 		return (-1);
6635 	}
6636 
6637 	/* last point check */
6638 	if (b->count==0) {
6639 		return (2);
6640 	}
6641 
6642 	while (b->error >= 0) {
6643 		if (b->swapdir) {
6644 			b->x += b->s1;
6645 		} else  {
6646 			b->y += b->s2;
6647 		}
6648 
6649 		b->error -= b->dx;
6650 	}
6651 
6652 	if (b->swapdir) {
6653 		b->y += b->s2;
6654 	} else {
6655 		b->x += b->s1;
6656 	}
6657 
6658 	b->error += b->dy;
6659 	b->count--;
6660 
6661 	/* count==0 indicates "end-of-line" */
6662 	return ((b->count) ? 0 : 1);
6663 }
6664 
6665 
6666 /*!
6667 \brief Internal function to to draw parallel lines with Murphy algorithm.
6668 
6669 \param m Pointer to struct for murphy iterator.
6670 \param x X coordinate of point.
6671 \param y Y coordinate of point.
6672 \param d1 Direction square/diagonal.
6673 */
_murphyParaline(RSDL_gfxMurphyIterator * m,Sint16 x,Sint16 y,int d1)6674 void _murphyParaline(RSDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
6675 {
6676 	int p;
6677 	d1 = -d1;
6678 
6679 	/*
6680 	* Lock the surface
6681 	*/
6682 	if (RSDL_MUSTLOCK(m->dst)) {
6683 		RSDL_LockSurface(m->dst);
6684 	}
6685 
6686 	for (p = 0; p <= m->u; p++) {
6687 
6688 		pixelColorNolock(m->dst, x, y, m->color);
6689 
6690 		if (d1 <= m->kt) {
6691 			if (m->oct2 == 0) {
6692 				x++;
6693 			} else {
6694 				if (m->quad4 == 0) {
6695 					y++;
6696 				} else {
6697 					y--;
6698 				}
6699 			}
6700 			d1 += m->kv;
6701 		} else {
6702 			x++;
6703 			if (m->quad4 == 0) {
6704 				y++;
6705 			} else {
6706 				y--;
6707 			}
6708 			d1 += m->kd;
6709 		}
6710 	}
6711 
6712 	/* Unlock surface */
6713 	if (RSDL_MUSTLOCK(m->dst)) {
6714 		RSDL_UnlockSurface(m->dst);
6715 	}
6716 
6717 	m->tempx = x;
6718 	m->tempy = y;
6719 }
6720 
6721 /*!
6722 \brief Internal function to to draw one iteration of the Murphy algorithm.
6723 
6724 \param m Pointer to struct for murphy iterator.
6725 \param miter Iteration count.
6726 \param ml1bx X coordinate of a point.
6727 \param ml1by Y coordinate of a point.
6728 \param ml2bx X coordinate of a point.
6729 \param ml2by Y coordinate of a point.
6730 \param ml1x X coordinate of a point.
6731 \param ml1y Y coordinate of a point.
6732 \param ml2x X coordinate of a point.
6733 \param ml2y Y coordinate of a point.
6734 
6735 */
_murphyIteration(RSDL_gfxMurphyIterator * m,Uint8 miter,Uint16 ml1bx,Uint16 ml1by,Uint16 ml2bx,Uint16 ml2by,Uint16 ml1x,Uint16 ml1y,Uint16 ml2x,Uint16 ml2y)6736 void _murphyIteration(RSDL_gfxMurphyIterator *m, Uint8 miter,
6737 	Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
6738 	Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
6739 {
6740 	int atemp1, atemp2;
6741 	int ftmp1, ftmp2;
6742 	Uint16 m1x, m1y, m2x, m2y;
6743 	Uint16 fix, fiy, lax, lay, curx, cury;
6744 	Uint16 px[4], py[4];
6745 	RSDL_gfxBresenhamIterator b;
6746 
6747 	if (miter > 1) {
6748 		if (m->first1x != -32768) {
6749 			fix = (m->first1x + m->first2x) / 2;
6750 			fiy = (m->first1y + m->first2y) / 2;
6751 			lax = (m->last1x + m->last2x) / 2;
6752 			lay = (m->last1y + m->last2y) / 2;
6753 			curx = (ml1x + ml2x) / 2;
6754 			cury = (ml1y + ml2y) / 2;
6755 
6756 			atemp1 = (fix - curx);
6757 			atemp2 = (fiy - cury);
6758 			ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
6759 			atemp1 = (lax - curx);
6760 			atemp2 = (lay - cury);
6761 			ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
6762 
6763 			if (ftmp1 <= ftmp2) {
6764 				m1x = m->first1x;
6765 				m1y = m->first1y;
6766 				m2x = m->first2x;
6767 				m2y = m->first2y;
6768 			} else {
6769 				m1x = m->last1x;
6770 				m1y = m->last1y;
6771 				m2x = m->last2x;
6772 				m2y = m->last2y;
6773 			}
6774 
6775 			atemp1 = (m2x - ml2x);
6776 			atemp2 = (m2y - ml2y);
6777 			ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
6778 			atemp1 = (m2x - ml2bx);
6779 			atemp2 = (m2y - ml2by);
6780 			ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
6781 
6782 			if (ftmp2 >= ftmp1) {
6783 				ftmp1 = ml2bx;
6784 				ftmp2 = ml2by;
6785 				ml2bx = ml2x;
6786 				ml2by = ml2y;
6787 				ml2x = ftmp1;
6788 				ml2y = ftmp2;
6789 				ftmp1 = ml1bx;
6790 				ftmp2 = ml1by;
6791 				ml1bx = ml1x;
6792 				ml1by = ml1y;
6793 				ml1x = ftmp1;
6794 				ml1y = ftmp2;
6795 			}
6796 
6797 			/*
6798 			* Lock the surface
6799 			*/
6800 			if (RSDL_MUSTLOCK(m->dst)) {
6801 				RSDL_LockSurface(m->dst);
6802 			}
6803 
6804 			_bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
6805 			do {
6806 				pixelColorNolock(m->dst, b.x, b.y, m->color);
6807 			} while (_bresenhamIterate(&b)==0);
6808 
6809 			_bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
6810 			do {
6811 				pixelColorNolock(m->dst, b.x, b.y, m->color);
6812 			} while (_bresenhamIterate(&b)==0);
6813 
6814 			_bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
6815 			do {
6816 				pixelColorNolock(m->dst, b.x, b.y, m->color);
6817 			} while (_bresenhamIterate(&b)==0);
6818 
6819 			_bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
6820 			do {
6821 				pixelColorNolock(m->dst, b.x, b.y, m->color);
6822 			} while (_bresenhamIterate(&b)==0);
6823 
6824 			/* Unlock surface */
6825 			if (RSDL_MUSTLOCK(m->dst)) {
6826 				RSDL_UnlockSurface(m->dst);
6827 			}
6828 
6829 			px[0] = m1x;
6830 			px[1] = m2x;
6831 			px[2] = ml1bx;
6832 			px[3] = ml2bx;
6833 			py[0] = m1y;
6834 			py[1] = m2y;
6835 			py[2] = ml1by;
6836 			py[3] = ml2by;
6837 			polygonColor(m->dst, (Sint16 *)px,(Sint16 *)py, 4, m->color);
6838 		}
6839 	}
6840 
6841 	m->last1x = ml1x;
6842 	m->last1y = ml1y;
6843 	m->last2x = ml2x;
6844 	m->last2y = ml2y;
6845 	m->first1x = ml1bx;
6846 	m->first1y = ml1by;
6847 	m->first2x = ml2bx;
6848 	m->first2y = ml2by;
6849 }
6850 
6851 
6852 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
6853 
6854 /*!
6855 \brief Internal function to to draw wide lines with Murphy algorithm.
6856 
6857 Draws lines parallel to ideal line.
6858 
6859 \param m Pointer to struct for murphy iterator.
6860 \param x1 X coordinate of first point.
6861 \param y1 Y coordinate of first point.
6862 \param x2 X coordinate of second point.
6863 \param y2 Y coordinate of second point.
6864 \param width Width of line.
6865 \param miter Iteration count.
6866 
6867 */
_murphyWideline(RSDL_gfxMurphyIterator * m,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 width,Uint8 miter)6868 void _murphyWideline(RSDL_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
6869 {
6870 	float offset = (float)width / 2.f;
6871 
6872 	Sint16 temp;
6873 	Sint16 ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
6874 
6875 	int d0, d1;		/* difference terms d0=perpendicular to line, d1=along line */
6876 
6877 	int q;			/* pel counter,q=perpendicular to line */
6878 	int tmp;
6879 
6880 	int dd;			/* distance along line */
6881 	int tk;			/* thickness threshold */
6882 	double ang;		/* angle for initial point calculation */
6883 	double sang, cang;
6884 
6885 	/* Initialisation */
6886 	m->u = x2 - x1;	/* delta x */
6887 	m->v = y2 - y1;	/* delta y */
6888 
6889 	if (m->u < 0) {	/* swap to make sure we are in quadrants 1 or 4 */
6890 		temp = x1;
6891 		x1 = x2;
6892 		x2 = temp;
6893 		temp = y1;
6894 		y1 = y2;
6895 		y2 = temp;
6896 		m->u *= -1;
6897 		m->v *= -1;
6898 	}
6899 
6900 	if (m->v < 0) {	/* swap to 1st quadrant and flag */
6901 		m->v *= -1;
6902 		m->quad4 = 1;
6903 	} else {
6904 		m->quad4 = 0;
6905 	}
6906 
6907 	if (m->v > m->u) {	/* swap things if in 2 octant */
6908 		tmp = m->u;
6909 		m->u = m->v;
6910 		m->v = tmp;
6911 		m->oct2 = 1;
6912 	} else {
6913 		m->oct2 = 0;
6914 	}
6915 
6916 	m->ku = m->u + m->u;	/* change in l for square shift */
6917 	m->kv = m->v + m->v;	/* change in d for square shift */
6918 	m->kd = m->kv - m->ku;	/* change in d for diagonal shift */
6919 	m->kt = m->u - m->kv;	/* diag/square decision threshold */
6920 
6921 	d0 = 0;
6922 	d1 = 0;
6923 	dd = 0;
6924 
6925 	ang = atan((double) m->v / (double) m->u);	/* calc new initial point - offset both sides of ideal */
6926 	sang = sin(ang);
6927 	cang = cos(ang);
6928 
6929 	if (m->oct2 == 0) {
6930 		ptx = x1 + (Sint16)lrint(offset * sang);
6931 		if (m->quad4 == 0) {
6932 			pty = y1 - (Sint16)lrint(offset * cang);
6933 		} else {
6934 			pty = y1 + (Sint16)lrint(offset * cang);
6935 		}
6936 	} else {
6937 		ptx = x1 - (Sint16)lrint(offset * cang);
6938 		if (m->quad4 == 0) {
6939 			pty = y1 + (Sint16)lrint(offset * sang);
6940 		} else {
6941 			pty = y1 - (Sint16)lrint(offset * sang);
6942 		}
6943 	}
6944 
6945 	/* used here for constant thickness line */
6946 	tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
6947 
6948 	if (miter == 0) {
6949 		m->first1x = -32768;
6950 		m->first1y = -32768;
6951 		m->first2x = -32768;
6952 		m->first2y = -32768;
6953 		m->last1x = -32768;
6954 		m->last1y = -32768;
6955 		m->last2x = -32768;
6956 		m->last2y = -32768;
6957 	}
6958 
6959 	for (q = 0; dd <= tk; q++) {	/* outer loop, stepping perpendicular to line */
6960 
6961 		_murphyParaline(m, ptx, pty, d1);	/* call to inner loop - right edge */
6962 		if (q == 0) {
6963 			ml1x = ptx;
6964 			ml1y = pty;
6965 			ml1bx = m->tempx;
6966 			ml1by = m->tempy;
6967 		} else {
6968 			ml2x = ptx;
6969 			ml2y = pty;
6970 			ml2bx = m->tempx;
6971 			ml2by = m->tempy;
6972 		}
6973 		if (d0 < m->kt) {	/* square move */
6974 			if (m->oct2 == 0) {
6975 				if (m->quad4 == 0) {
6976 					pty++;
6977 				} else {
6978 					pty--;
6979 				}
6980 			} else {
6981 				ptx++;
6982 			}
6983 		} else {	/* diagonal move */
6984 			dd += m->kv;
6985 			d0 -= m->ku;
6986 			if (d1 < m->kt) {	/* normal diagonal */
6987 				if (m->oct2 == 0) {
6988 					ptx--;
6989 					if (m->quad4 == 0) {
6990 						pty++;
6991 					} else {
6992 						pty--;
6993 					}
6994 				} else {
6995 					ptx++;
6996 					if (m->quad4 == 0) {
6997 						pty--;
6998 					} else {
6999 						pty++;
7000 					}
7001 				}
7002 				d1 += m->kv;
7003 			} else {	/* double square move, extra parallel line */
7004 				if (m->oct2 == 0) {
7005 					ptx--;
7006 				} else {
7007 					if (m->quad4 == 0) {
7008 						pty--;
7009 					} else {
7010 						pty++;
7011 					}
7012 				}
7013 				d1 += m->kd;
7014 				if (dd > tk) {
7015 					_murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
7016 					return;	/* breakout on the extra line */
7017 				}
7018 				_murphyParaline(m, ptx, pty, d1);
7019 				if (m->oct2 == 0) {
7020 					if (m->quad4 == 0) {
7021 						pty++;
7022 					} else {
7023 
7024 						pty--;
7025 					}
7026 				} else {
7027 					ptx++;
7028 				}
7029 			}
7030 		}
7031 		dd += m->ku;
7032 		d0 += m->kv;
7033 	}
7034 
7035 	_murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
7036 }
7037 
7038 
7039 /*!
7040 \brief Draw a thick line with alpha blending.
7041 
7042 \param dst The surface to draw on.
7043 \param x1 X coordinate of the first point of the line.
7044 \param y1 Y coordinate of the first point of the line.
7045 \param x2 X coordinate of the second point of the line.
7046 \param y2 Y coordinate of the second point of the line.
7047 \param width Width of the line in pixels. Must be >0.
7048 \param color The color value of the line to draw (0xRRGGBBAA).
7049 
7050 \returns Returns 0 on success, -1 on failure.
7051 */
thickLineColor(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 width,Uint32 color)7052 int thickLineColor(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
7053 {
7054 	int wh;
7055 	RSDL_gfxMurphyIterator m;
7056 
7057 	if (dst == NULL) return -1;
7058 	if (width < 1) return -1;
7059 
7060 	/* Special case: thick "point" */
7061 	if ((x1 == x2) && (y1 == y2)) {
7062 		wh = width / 2;
7063 		return boxColor(dst, x1 - wh, y1 - wh, x2 + width, y2 + width, color);
7064 	}
7065 
7066 	m.dst = dst;
7067 	m.color = color;
7068 
7069 	_murphyWideline(&m, x1, y1, x2, y2, width, 0);
7070 	_murphyWideline(&m, x1, y1, x2, y2, width, 1);
7071 
7072 	return(0);
7073 }
7074 
7075 /*!
7076 \brief Draw a thick line with alpha blending.
7077 
7078 \param dst The surface to draw on.
7079 \param x1 X coordinate of the first point of the line.
7080 \param y1 Y coordinate of the first point of the line.
7081 \param x2 X coordinate of the second point of the line.
7082 \param y2 Y coordinate of the second point of the line.
7083 \param width Width of the line in pixels. Must be >0.
7084 \param r The red value of the character to draw.
7085 \param g The green value of the character to draw.
7086 \param b The blue value of the character to draw.
7087 \param a The alpha value of the character to draw.
7088 
7089 \returns Returns 0 on success, -1 on failure.
7090 */
thickLineRGBA(RSDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 width,Uint8 r,Uint8 g,Uint8 b,Uint8 a)7091 int thickLineRGBA(RSDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
7092 {
7093 	return (thickLineColor(dst, x1, y1, x2, y2, width,
7094 		((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
7095 }
7096 
7097