1 /*
2 
3  SDL_gfxPrimitives - Graphics primitives for SDL surfaces
4 
5  LGPL (c) A. Schiffler
6 
7 */
8 
9 #include <stdio.h>
10 #include <stdlib.h>
11 #include <math.h>
12 #include <string.h>
13 
14 #include "SDL_gfxPrimitives.h"
15 #include "SDL_gfxPrimitives_font.h"
16 
17 /* -===================- */
18 
19 //#define MODIFIED_ALPHA_PIXEL_ROUTINE
20 #define ORIGINAL_ALPHA_PIXEL_ROUTINE
21 
22 /* ----- Defines for pixel clipping tests */
23 
24 #define clip_xmin(surface) surface->clip_rect.x
25 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
26 #define clip_ymin(surface) surface->clip_rect.y
27 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
28 
29 /* ----- Pixel - fast, no blending, no locking, clipping */
30 
fastPixelColorNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)31 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
32 {
33     int bpp;
34     Uint8 *p;
35 
36     /*
37      * Honor clipping setup at pixel level
38      */
39     if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
40 
41 	/*
42 	 * Get destination format
43 	 */
44 	bpp = dst->format->BytesPerPixel;
45 	p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
46 	switch (bpp) {
47 	case 1:
48 	    *p = color;
49 	    break;
50 	case 2:
51 	    *(Uint16 *) p = color;
52 	    break;
53 	case 3:
54 	    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
55 		p[0] = (color >> 16) & 0xff;
56 		p[1] = (color >> 8) & 0xff;
57 		p[2] = color & 0xff;
58 	    } else {
59 		p[0] = color & 0xff;
60 		p[1] = (color >> 8) & 0xff;
61 		p[2] = (color >> 16) & 0xff;
62 	    }
63 	    break;
64 	case 4:
65 	    *(Uint32 *) p = color;
66 	    break;
67 	}			/* switch */
68 
69 
70     }
71 
72     return (0);
73 }
74 
75 /* ----- Pixel - fast, no blending, no locking, no clipping */
76 
77 /* (faster but dangerous, make sure we stay in surface bounds) */
78 
fastPixelColorNolockNoclip(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)79 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
80 {
81     int bpp;
82     Uint8 *p;
83 
84     /*
85      * Get destination format
86      */
87     bpp = dst->format->BytesPerPixel;
88     p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
89     switch (bpp) {
90     case 1:
91 	*p = color;
92 	break;
93     case 2:
94 	*(Uint16 *) p = color;
95 	break;
96     case 3:
97 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
98 	    p[0] = (color >> 16) & 0xff;
99 	    p[1] = (color >> 8) & 0xff;
100 	    p[2] = color & 0xff;
101 	} else {
102 	    p[0] = color & 0xff;
103 	    p[1] = (color >> 8) & 0xff;
104 	    p[2] = (color >> 16) & 0xff;
105 	}
106 	break;
107     case 4:
108 	*(Uint32 *) p = color;
109 	break;
110     }				/* switch */
111 
112     return (0);
113 }
114 
115 /* ----- Pixel - fast, no blending, locking, clipping */
116 
fastPixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)117 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
118 {
119     int result;
120 
121     /*
122      * Lock the surface
123      */
124     if (SDL_MUSTLOCK(dst)) {
125 	if (SDL_LockSurface(dst) < 0) {
126 	    return (-1);
127 	}
128     }
129 
130     result = fastPixelColorNolock(dst, x, y, color);
131 
132     /*
133      * Unlock surface
134      */
135     if (SDL_MUSTLOCK(dst)) {
136 	SDL_UnlockSurface(dst);
137     }
138 
139     return (result);
140 }
141 
142 /* ----- Pixel - fast, no blending, locking, RGB input */
143 
fastPixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)144 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
145 {
146     Uint32 color;
147 
148     /*
149      * Setup color
150      */
151     color = SDL_MapRGBA(dst->format, r, g, b, a);
152 
153     /*
154      * Draw
155      */
156     return (fastPixelColor(dst, x, y, color));
157 
158 }
159 
160 /* ----- Pixel - fast, no blending, no locking RGB input */
161 
fastPixelRGBANolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)162 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
163 {
164     Uint32 color;
165 
166     /*
167      * Setup color
168      */
169     color = SDL_MapRGBA(dst->format, r, g, b, a);
170 
171     /*
172      * Draw
173      */
174     return (fastPixelColorNolock(dst, x, y, color));
175 }
176 
177 /* PutPixel routine with alpha blending, input color in destination format */
178 
179 /* New, faster routine - default blending pixel */
180 
_putPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)181 int _putPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
182 {
183     Uint32 Rmask = surface->format->Rmask, Gmask =
184 	surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
185     Uint32 R, G, B, A = 0;
186 
187     if (x >= clip_xmin(surface) && x <= clip_xmax(surface)
188 	&& y >= clip_ymin(surface) && y <= clip_ymax(surface)) {
189 
190 	switch (surface->format->BytesPerPixel) {
191 	case 1:{		/* Assuming 8-bpp */
192 		if (alpha == 255) {
193 		    *((Uint8 *) surface->pixels + y * surface->pitch + x) = color;
194 		} else {
195 		    Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x;
196 
197 		    Uint8 dR = surface->format->palette->colors[*pixel].r;
198 		    Uint8 dG = surface->format->palette->colors[*pixel].g;
199 		    Uint8 dB = surface->format->palette->colors[*pixel].b;
200 		    Uint8 sR = surface->format->palette->colors[color].r;
201 		    Uint8 sG = surface->format->palette->colors[color].g;
202 		    Uint8 sB = surface->format->palette->colors[color].b;
203 
204 		    dR = dR + ((sR - dR) * alpha >> 8);
205 		    dG = dG + ((sG - dG) * alpha >> 8);
206 		    dB = dB + ((sB - dB) * alpha >> 8);
207 
208 		    *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
209 		}
210 	    }
211 	    break;
212 
213 	case 2:{		/* Probably 15-bpp or 16-bpp */
214 		if (alpha == 255) {
215 		    *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color;
216 		} else {
217 		    Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x;
218 		    Uint32 dc = *pixel;
219 
220 		    R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
221 		    G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
222 		    B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
223 		    if (Amask)
224 			A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
225 
226 		    *pixel = R | G | B | A;
227 		}
228 	    }
229 	    break;
230 
231 	case 3:{		/* Slow 24-bpp mode, usually not used */
232 		Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
233 		Uint8 rshift8 = surface->format->Rshift / 8;
234 		Uint8 gshift8 = surface->format->Gshift / 8;
235 		Uint8 bshift8 = surface->format->Bshift / 8;
236 		Uint8 ashift8 = surface->format->Ashift / 8;
237 
238 
239 		if (alpha == 255) {
240 		    *(pix + rshift8) = color >> surface->format->Rshift;
241 		    *(pix + gshift8) = color >> surface->format->Gshift;
242 		    *(pix + bshift8) = color >> surface->format->Bshift;
243 		    *(pix + ashift8) = color >> surface->format->Ashift;
244 		} else {
245 		    Uint8 dR, dG, dB, dA = 0;
246 		    Uint8 sR, sG, sB, sA = 0;
247 
248 		    pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
249 
250 		    dR = *((pix) + rshift8);
251 		    dG = *((pix) + gshift8);
252 		    dB = *((pix) + bshift8);
253 		    dA = *((pix) + ashift8);
254 
255 		    sR = (color >> surface->format->Rshift) & 0xff;
256 		    sG = (color >> surface->format->Gshift) & 0xff;
257 		    sB = (color >> surface->format->Bshift) & 0xff;
258 		    sA = (color >> surface->format->Ashift) & 0xff;
259 
260 		    dR = dR + ((sR - dR) * alpha >> 8);
261 		    dG = dG + ((sG - dG) * alpha >> 8);
262 		    dB = dB + ((sB - dB) * alpha >> 8);
263 		    dA = dA + ((sA - dA) * alpha >> 8);
264 
265 		    *((pix) + rshift8) = dR;
266 		    *((pix) + gshift8) = dG;
267 		    *((pix) + bshift8) = dB;
268 		    *((pix) + ashift8) = dA;
269 		}
270 	    }
271 	    break;
272 
273 #ifdef ORIGINAL_ALPHA_PIXEL_ROUTINE
274 
275 	case 4:{		/* Probably :-) 32-bpp */
276 		if (alpha == 255) {
277 		    *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
278 		} else {
279 		    Uint32 Rshift, Gshift, Bshift, Ashift;
280 		    Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
281 		    Uint32 dc = *pixel;
282 
283 		    Rshift = surface->format->Rshift;
284 		    Gshift = surface->format->Gshift;
285 		    Bshift = surface->format->Bshift;
286 		    Ashift = surface->format->Ashift;
287 
288 		    R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
289 		    G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
290 		    B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
291 		    if (Amask)
292 			A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
293 
294 		    *pixel = R | G | B | A;
295 		}
296 	    }
297 	    break;
298 #endif
299 
300 #ifdef MODIFIED_ALPHA_PIXEL_ROUTINE
301 
302 	case 4:{		/* Probably :-) 32-bpp */
303 		if (alpha == 255) {
304 		    *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
305 		} else {
306 		    Uint32 Rshift, Gshift, Bshift, Ashift;
307 		    Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
308 		    Uint32 dc = *pixel;
309 		    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
310 		    Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
311 		    Uint32 aTmp;
312 
313 		    Rshift = surface->format->Rshift;
314 		    Gshift = surface->format->Gshift;
315 		    Bshift = surface->format->Bshift;
316 		    Ashift = surface->format->Ashift;
317 
318                     preMultR = (alpha * (dR>>Rshift));
319                     preMultG = (alpha * (dG>>Gshift));
320                     preMultB = (alpha * (dB>>Bshift));
321 
322                     surfaceAlpha = ((dc & Amask) >> Ashift);
323                     aTmp = (255 - alpha);
324                     if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
325                       aTmp *= surfaceAlpha;
326                       R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
327                       G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
328                       B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
329                     }
330 		    *pixel = R | G | B | (A << Ashift & Amask);
331 
332 		}
333 	    }
334 	    break;
335 #endif
336 	}
337     }
338 
339     return (0);
340 }
341 
342 /* ----- Pixel - pixel draw with blending enabled if a<255 */
343 
pixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)344 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
345 {
346     Uint8 alpha;
347     Uint32 mcolor;
348     int result = 0;
349 
350     /*
351      * Lock the surface
352      */
353     if (SDL_MUSTLOCK(dst)) {
354 	if (SDL_LockSurface(dst) < 0) {
355 	    return (-1);
356 	}
357     }
358 
359     /*
360      * Setup color
361      */
362     alpha = color & 0x000000ff;
363     mcolor =
364 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
365 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
366 
367     /*
368      * Draw
369      */
370     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
371 
372     /*
373      * Unlock the surface
374      */
375     if (SDL_MUSTLOCK(dst)) {
376 	SDL_UnlockSurface(dst);
377     }
378 
379     return (result);
380 }
381 
pixelColorNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)382 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
383 {
384     Uint8 alpha;
385     Uint32 mcolor;
386     int result = 0;
387 
388     /*
389      * Setup color
390      */
391     alpha = color & 0x000000ff;
392     mcolor =
393 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
394 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
395 
396     /*
397      * Draw
398      */
399     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
400 
401     return (result);
402 }
403 
404 
405 /* Filled rectangle with alpha blending, color in destination format */
406 
_filledRectAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)407 int _filledRectAlpha(SDL_Surface * surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
408 {
409     Uint32 Rmask = surface->format->Rmask, Gmask =
410 	surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
411     Uint32 R, G, B, A = 0;
412     Sint16 x, y;
413 
414     switch (surface->format->BytesPerPixel) {
415     case 1:{			/* Assuming 8-bpp */
416 	    Uint8 *row, *pixel;
417 	    Uint8 dR, dG, dB;
418 
419 	    Uint8 sR = surface->format->palette->colors[color].r;
420 	    Uint8 sG = surface->format->palette->colors[color].g;
421 	    Uint8 sB = surface->format->palette->colors[color].b;
422 
423 	    for (y = y1; y <= y2; y++) {
424 		row = (Uint8 *) surface->pixels + y * surface->pitch;
425 		for (x = x1; x <= x2; x++) {
426 		    pixel = row + x;
427 
428 		    dR = surface->format->palette->colors[*pixel].r;
429 		    dG = surface->format->palette->colors[*pixel].g;
430 		    dB = surface->format->palette->colors[*pixel].b;
431 
432 		    dR = dR + ((sR - dR) * alpha >> 8);
433 		    dG = dG + ((sG - dG) * alpha >> 8);
434 		    dB = dB + ((sB - dB) * alpha >> 8);
435 
436 		    *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
437 		}
438 	    }
439 	}
440 	break;
441 
442     case 2:{			/* Probably 15-bpp or 16-bpp */
443 	    Uint16 *row, *pixel;
444 	    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
445 
446 	    for (y = y1; y <= y2; y++) {
447 		row = (Uint16 *) surface->pixels + y * surface->pitch / 2;
448 		for (x = x1; x <= x2; x++) {
449 		    pixel = row + x;
450 
451 		    R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
452 		    G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
453 		    B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
454 		    if (Amask)
455 			A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
456 
457 		    *pixel = R | G | B | A;
458 		}
459 	    }
460 	}
461 	break;
462 
463     case 3:{			/* Slow 24-bpp mode, usually not used */
464 	    Uint8 *row, *pix;
465 	    Uint8 dR, dG, dB, dA;
466 	    Uint8 rshift8 = surface->format->Rshift / 8;
467 	    Uint8 gshift8 = surface->format->Gshift / 8;
468 	    Uint8 bshift8 = surface->format->Bshift / 8;
469 	    Uint8 ashift8 = surface->format->Ashift / 8;
470 
471 	    Uint8 sR = (color >> surface->format->Rshift) & 0xff;
472 	    Uint8 sG = (color >> surface->format->Gshift) & 0xff;
473 	    Uint8 sB = (color >> surface->format->Bshift) & 0xff;
474 	    Uint8 sA = (color >> surface->format->Ashift) & 0xff;
475 
476 	    for (y = y1; y <= y2; y++) {
477 		row = (Uint8 *) surface->pixels + y * surface->pitch;
478 		for (x = x1; x <= x2; x++) {
479 		    pix = row + x * 3;
480 
481 		    dR = *((pix) + rshift8);
482 		    dG = *((pix) + gshift8);
483 		    dB = *((pix) + bshift8);
484 		    dA = *((pix) + ashift8);
485 
486 		    dR = dR + ((sR - dR) * alpha >> 8);
487 		    dG = dG + ((sG - dG) * alpha >> 8);
488 		    dB = dB + ((sB - dB) * alpha >> 8);
489 		    dA = dA + ((sA - dA) * alpha >> 8);
490 
491 		    *((pix) + rshift8) = dR;
492 		    *((pix) + gshift8) = dG;
493 		    *((pix) + bshift8) = dB;
494 		    *((pix) + ashift8) = dA;
495 		}
496 	    }
497 
498 	}
499 	break;
500 
501 #ifdef ORIGINAL_ALPHA_PIXEL_ROUTINE
502     case 4:{			/* Probably :-) 32-bpp */
503 	    Uint32 Rshift, Gshift, Bshift, Ashift;
504 	    Uint32 *row, *pixel;
505 	    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
506 
507 	    Rshift = surface->format->Rshift;
508 	    Gshift = surface->format->Gshift;
509 	    Bshift = surface->format->Bshift;
510 	    Ashift = surface->format->Ashift;
511 
512 	    for (y = y1; y <= y2; y++) {
513 		row = (Uint32 *) surface->pixels + y * surface->pitch / 4;
514 		for (x = x1; x <= x2; x++) {
515 		    pixel = row + x;
516 
517 		    R = ((*pixel & Rmask) + ((((dR - (*pixel & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
518 		    G = ((*pixel & Gmask) + ((((dG - (*pixel & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
519 		    B = ((*pixel & Bmask) + ((((dB - (*pixel & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
520 		    if (Amask)
521 			A = ((*pixel & Amask) + ((((dA - (*pixel & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
522 
523 		    *pixel = R | G | B | A;
524 		}
525 	    }
526 	}
527 	break;
528 #endif
529 
530 #ifdef MODIFIED_ALPHA_PIXEL_ROUTINE
531     case 4:{			/* Probably :-) 32-bpp */
532 	    Uint32 Rshift, Gshift, Bshift, Ashift;
533 	    Uint32 *row, *pixel;
534 	    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
535             Uint32 dc;
536             Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
537             Uint32 aTmp;
538 
539 	    Rshift = surface->format->Rshift;
540 	    Gshift = surface->format->Gshift;
541 	    Bshift = surface->format->Bshift;
542 	    Ashift = surface->format->Ashift;
543 
544             preMultR = (alpha * (dR>>Rshift));
545             preMultG = (alpha * (dG>>Gshift));
546             preMultB = (alpha * (dB>>Bshift));
547 
548 	    for (y = y1; y <= y2; y++) {
549 		row = (Uint32 *) surface->pixels + y * surface->pitch / 4;
550 		for (x = x1; x <= x2; x++) {
551 		    pixel = row + x;
552 		    dc = *pixel;
553 
554                     surfaceAlpha = ((dc & Amask) >> Ashift);
555                     aTmp = (255 - alpha);
556                     if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
557                       aTmp *= surfaceAlpha;
558                       R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
559                       G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
560                       B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
561                     }
562 		    *pixel = R | G | B | (A << Ashift & Amask);
563 
564 		}
565 	    }
566 	}
567 	break;
568 #endif
569 
570     }
571 
572     return (0);
573 }
574 
575 /* Draw rectangle with alpha enabled from RGBA color. */
576 
filledRectAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)577 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
578 {
579     Uint8 alpha;
580     Uint32 mcolor;
581     int result = 0;
582 
583     /*
584      * Lock the surface
585      */
586     if (SDL_MUSTLOCK(dst)) {
587 	if (SDL_LockSurface(dst) < 0) {
588 	    return (-1);
589 	}
590     }
591 
592     /*
593      * Setup color
594      */
595     alpha = color & 0x000000ff;
596     mcolor =
597 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
598 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
599 
600     /*
601      * Draw
602      */
603     result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
604 
605     /*
606      * Unlock the surface
607      */
608     if (SDL_MUSTLOCK(dst)) {
609 	SDL_UnlockSurface(dst);
610     }
611 
612     return (result);
613 }
614 
615 /* Draw horizontal line with alpha enabled from RGBA color */
616 
HLineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)617 int HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
618 {
619     return (filledRectAlpha(dst, x1, y, x2, y, color));
620 }
621 
622 
623 /* Draw vertical line with alpha enabled from RGBA color */
624 
VLineAlpha(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)625 int VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
626 {
627     return (filledRectAlpha(dst, x, y1, x, y2, color));
628 }
629 
630 
631 /* Pixel - using alpha weight on color for AA-drawing */
632 
pixelColorWeight(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)633 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
634 {
635     Uint32 a;
636 
637     /*
638      * Get alpha
639      */
640     a = (color & (Uint32) 0x000000ff);
641 
642     /*
643      * Modify Alpha by weight
644      */
645     a = ((a * weight) >> 8);
646 
647     return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
648 }
649 
650 /* Pixel - using alpha weight on color for AA-drawing - no locking */
651 
pixelColorWeightNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)652 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
653 {
654     Uint32 a;
655 
656     /*
657      * Get alpha
658      */
659     a = (color & (Uint32) 0x000000ff);
660 
661     /*
662      * Modify Alpha by weight
663      */
664     a = ((a * weight) >> 8);
665 
666     return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
667 }
668 
pixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)669 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
670 {
671     Uint32 color;
672 
673     /*
674      * Check Alpha
675      */
676     if (a == 255) {
677 	/*
678 	 * No alpha blending required
679 	 */
680 	/*
681 	 * Setup color
682 	 */
683 	color = SDL_MapRGBA(dst->format, r, g, b, a);
684 	/*
685 	 * Draw
686 	 */
687 	return (fastPixelColor(dst, x, y, color));
688     } else {
689 	/*
690 	 * Alpha blending required
691 	 */
692 	/*
693 	 * Draw
694 	 */
695 	return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
696     }
697 }
698 
699 /* ----- Horizontal line */
700 
701 /* Just store color including alpha, no blending */
702 
hlineColorStore(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)703 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
704 {
705     Sint16 left, right, top, bottom;
706     Uint8 *pixel, *pixellast;
707     int dx;
708     int pixx, pixy;
709     Sint16 w;
710     Sint16 xtmp;
711     int result = -1;
712 
713     /*
714      * Check visibility of clipping rectangle
715      */
716     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
717      return(0);
718     }
719 
720     /*
721      * Swap x1, x2 if required to ensure x1<=x2
722      */
723     if (x1 > x2) {
724 	xtmp = x1;
725 	x1 = x2;
726 	x2 = xtmp;
727     }
728 
729     /*
730      * Get clipping boundary and
731      * check visibility of hline
732      */
733     left = dst->clip_rect.x;
734     if (x2<left) {
735      return(0);
736     }
737     right = dst->clip_rect.x + dst->clip_rect.w - 1;
738     if (x1>right) {
739      return(0);
740     }
741     top = dst->clip_rect.y;
742     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
743     if ((y<top) || (y>bottom)) {
744      return (0);
745     }
746 
747     /*
748      * Clip x
749      */
750     if (x1 < left) {
751 	x1 = left;
752     }
753     if (x2 > right) {
754 	x2 = right;
755     }
756 
757     /*
758      * Calculate width
759      */
760     w = x2 - x1;
761 
762     /*
763      * Lock surface
764      */
765     SDL_LockSurface(dst);
766 
767     /*
768      * More variable setup
769      */
770     dx = w;
771     pixx = dst->format->BytesPerPixel;
772 	pixy = dst->pitch;
773 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
774 
775 	/*
776 	 * Draw
777 	 */
778 	switch (dst->format->BytesPerPixel) {
779 	case 1:
780 	    memset(pixel, color, dx);
781 	    break;
782 	case 2:
783 	    pixellast = pixel + dx + dx;
784 	    for (; pixel <= pixellast; pixel += pixx) {
785 		*(Uint16 *) pixel = color;
786 	    }
787 	    break;
788 	case 3:
789 	    pixellast = pixel + dx + dx + dx;
790 	    for (; pixel <= pixellast; pixel += pixx) {
791 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
792 		    pixel[0] = (color >> 16) & 0xff;
793 		    pixel[1] = (color >> 8) & 0xff;
794 		    pixel[2] = color & 0xff;
795 		} else {
796 		    pixel[0] = color & 0xff;
797 		    pixel[1] = (color >> 8) & 0xff;
798 		    pixel[2] = (color >> 16) & 0xff;
799 		}
800 	    }
801 	    break;
802 	default:		/* case 4 */
803 	    dx = dx + dx;
804 	    pixellast = pixel + dx + dx;
805 	    for (; pixel <= pixellast; pixel += pixx) {
806 		*(Uint32 *) pixel = color;
807 	    }
808 	    break;
809 	}
810 
811 	/*
812 	 * Unlock surface
813 	 */
814 	SDL_UnlockSurface(dst);
815 
816 	/*
817 	 * Set result code
818 	 */
819 	result = 0;
820 
821     return (result);
822 }
823 
hlineRGBAStore(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)824 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
825 {
826     /*
827      * Draw
828      */
829     return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
830 }
831 
hlineColor(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)832 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
833 {
834     Sint16 left, right, top, bottom;
835     Uint8 *pixel, *pixellast;
836     int dx;
837     int pixx, pixy;
838     Sint16 w;
839     Sint16 xtmp;
840     int result = -1;
841     Uint8 *colorptr;
842 
843     /*
844      * Check visibility of clipping rectangle
845      */
846     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
847      return(0);
848     }
849 
850     /*
851      * Swap x1, x2 if required to ensure x1<=x2
852      */
853     if (x1 > x2) {
854 	xtmp = x1;
855 	x1 = x2;
856 	x2 = xtmp;
857     }
858 
859     /*
860      * Get clipping boundary and
861      * check visibility of hline
862      */
863     left = dst->clip_rect.x;
864     if (x2<left) {
865      return(0);
866     }
867     right = dst->clip_rect.x + dst->clip_rect.w - 1;
868     if (x1>right) {
869      return(0);
870     }
871     top = dst->clip_rect.y;
872     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
873     if ((y<top) || (y>bottom)) {
874      return (0);
875     }
876 
877     /*
878      * Clip x
879      */
880     if (x1 < left) {
881 	x1 = left;
882     }
883     if (x2 > right) {
884 	x2 = right;
885     }
886 
887     /*
888      * Calculate width
889      */
890     w = x2 - x1;
891 
892     /*
893      * Alpha check
894      */
895     if ((color & 255) == 255) {
896 
897 	/*
898 	 * No alpha-blending required
899 	 */
900 
901 	/*
902 	 * Setup color
903 	 */
904 	colorptr = (Uint8 *) & color;
905 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
906 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
907 	} else {
908 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
909 	}
910 
911 	/*
912 	 * Lock surface
913 	 */
914 	SDL_LockSurface(dst);
915 
916 	/*
917 	 * More variable setup
918 	 */
919 	dx = w;
920 	pixx = dst->format->BytesPerPixel;
921 	pixy = dst->pitch;
922 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
923 
924 	/*
925 	 * Draw
926 	 */
927 	switch (dst->format->BytesPerPixel) {
928 	case 1:
929 	    memset(pixel, color, dx);
930 	    break;
931 	case 2:
932 	    pixellast = pixel + dx + dx;
933 	    for (; pixel <= pixellast; pixel += pixx) {
934 		*(Uint16 *) pixel = color;
935 	    }
936 	    break;
937 	case 3:
938 	    pixellast = pixel + dx + dx + dx;
939 	    for (; pixel <= pixellast; pixel += pixx) {
940 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
941 		    pixel[0] = (color >> 16) & 0xff;
942 		    pixel[1] = (color >> 8) & 0xff;
943 		    pixel[2] = color & 0xff;
944 		} else {
945 		    pixel[0] = color & 0xff;
946 		    pixel[1] = (color >> 8) & 0xff;
947 		    pixel[2] = (color >> 16) & 0xff;
948 		}
949 	    }
950 	    break;
951 	default:		/* case 4 */
952 	    dx = dx + dx;
953 	    pixellast = pixel + dx + dx;
954 	    for (; pixel <= pixellast; pixel += pixx) {
955 		*(Uint32 *) pixel = color;
956 	    }
957 	    break;
958 	}
959 
960 	/*
961 	 * Unlock surface
962 	 */
963 	SDL_UnlockSurface(dst);
964 
965 	/*
966 	 * Set result code
967 	 */
968 	result = 0;
969 
970     } else {
971 
972 	/*
973 	 * Alpha blending blit
974 	 */
975 
976 	result = HLineAlpha(dst, x1, x1 + w, y, color);
977 
978     }
979 
980     return (result);
981 }
982 
hlineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)983 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
984 {
985     /*
986      * Draw
987      */
988     return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
989 }
990 
991 /* ----- Vertical line */
992 
vlineColor(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)993 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
994 {
995     Sint16 left, right, top, bottom;
996     Uint8 *pixel, *pixellast;
997     int dy;
998     int pixx, pixy;
999     Sint16 h;
1000     Sint16 ytmp;
1001     int result = -1;
1002     Uint8 *colorptr;
1003 
1004     /*
1005      * Check visibility of clipping rectangle
1006      */
1007     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1008      return(0);
1009     }
1010 
1011     /*
1012      * Swap y1, y2 if required to ensure y1<=y2
1013      */
1014     if (y1 > y2) {
1015 	ytmp = y1;
1016 	y1 = y2;
1017 	y2 = ytmp;
1018     }
1019 
1020     /*
1021      * Get clipping boundary and
1022      * check visibility of vline
1023      */
1024     left = dst->clip_rect.x;
1025     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1026     if ((x<left) || (x>right)) {
1027      return (0);
1028     }
1029     top = dst->clip_rect.y;
1030     if (y2<top) {
1031      return(0);
1032     }
1033     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1034     if (y1>bottom) {
1035      return(0);
1036     }
1037 
1038     /*
1039      * Clip x
1040      */
1041     if (y1 < top) {
1042 	y1 = top;
1043     }
1044     if (y2 > bottom) {
1045 	y2 = bottom;
1046     }
1047 
1048     /*
1049      * Calculate height
1050      */
1051     h = y2 - y1;
1052 
1053     /*
1054      * Alpha check
1055      */
1056     if ((color & 255) == 255) {
1057 
1058 	/*
1059 	 * No alpha-blending required
1060 	 */
1061 
1062 	/*
1063 	 * Setup color
1064 	 */
1065 	colorptr = (Uint8 *) & color;
1066 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1067 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1068 	} else {
1069 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1070 	}
1071 
1072 	/*
1073 	 * Lock surface
1074 	 */
1075 	SDL_LockSurface(dst);
1076 
1077 	/*
1078 	 * More variable setup
1079 	 */
1080 	dy = h;
1081 	pixx = dst->format->BytesPerPixel;
1082 	pixy = dst->pitch;
1083 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
1084 	pixellast = pixel + pixy * dy;
1085 
1086 	/*
1087 	 * Draw
1088 	 */
1089 	switch (dst->format->BytesPerPixel) {
1090 	case 1:
1091 	    for (; pixel <= pixellast; pixel += pixy) {
1092 		*(Uint8 *) pixel = color;
1093 	    }
1094 	    break;
1095 	case 2:
1096 	    for (; pixel <= pixellast; pixel += pixy) {
1097 		*(Uint16 *) pixel = color;
1098 	    }
1099 	    break;
1100 	case 3:
1101 	    for (; pixel <= pixellast; pixel += pixy) {
1102 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1103 		    pixel[0] = (color >> 16) & 0xff;
1104 		    pixel[1] = (color >> 8) & 0xff;
1105 		    pixel[2] = color & 0xff;
1106 		} else {
1107 		    pixel[0] = color & 0xff;
1108 		    pixel[1] = (color >> 8) & 0xff;
1109 		    pixel[2] = (color >> 16) & 0xff;
1110 		}
1111 	    }
1112 	    break;
1113 	default:		/* case 4 */
1114 	    for (; pixel <= pixellast; pixel += pixy) {
1115 		*(Uint32 *) pixel = color;
1116 	    }
1117 	    break;
1118 	}
1119 
1120 	/*
1121 	 * Unlock surface
1122 	 */
1123 	SDL_UnlockSurface(dst);
1124 
1125 	/*
1126 	 * Set result code
1127 	 */
1128 	result = 0;
1129 
1130     } else {
1131 
1132 	/*
1133 	 * Alpha blending blit
1134 	 */
1135 
1136 	result = VLineAlpha(dst, x, y1, y1 + h, color);
1137 
1138     }
1139 
1140     return (result);
1141 }
1142 
vlineRGBA(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1143 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1144 {
1145     /*
1146      * Draw
1147      */
1148     return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1149 }
1150 
1151 /* ----- Rectangle */
1152 
rectangleColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1153 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1154 {
1155     int result;
1156     Sint16 w, h, xtmp, ytmp;
1157 
1158     /*
1159      * Check visibility of clipping rectangle
1160      */
1161     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1162      return(0);
1163     }
1164 
1165     /*
1166      * Swap x1, x2 if required
1167      */
1168     if (x1 > x2) {
1169 	xtmp = x1;
1170 	x1 = x2;
1171 	x2 = xtmp;
1172     }
1173 
1174     /*
1175      * Swap y1, y2 if required
1176      */
1177     if (y1 > y2) {
1178 	ytmp = y1;
1179 	y1 = y2;
1180 	y2 = ytmp;
1181     }
1182 
1183     /*
1184      * Calculate width&height
1185      */
1186     w = x2 - x1;
1187     h = y2 - y1;
1188 
1189     /*
1190      * Sanity check
1191      */
1192     if ((w < 0) || (h < 0)) {
1193 	return (0);
1194     }
1195 
1196     /*
1197      * Test for special cases of straight lines or single point
1198      */
1199     if (x1 == x2) {
1200 	if (y1 == y2) {
1201 	    return (pixelColor(dst, x1, y1, color));
1202 	} else {
1203 	    return (vlineColor(dst, x1, y1, y2, color));
1204 	}
1205     } else {
1206 	if (y1 == y2) {
1207 	    return (hlineColor(dst, x1, x2, y1, color));
1208 	}
1209     }
1210 
1211     /*
1212      * Draw rectangle
1213      */
1214     result = 0;
1215     result |= hlineColor(dst, x1, x2, y1, color);
1216     result |= hlineColor(dst, x1, x2, y2, color);
1217     y1 += 1;
1218     y2 -= 1;
1219     if (y1<=y2) {
1220      result |= vlineColor(dst, x1, y1, y2, color);
1221      result |= vlineColor(dst, x2, y1, y2, color);
1222     }
1223     return (result);
1224 
1225 }
1226 
rectangleRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1227 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1228 {
1229     /*
1230      * Draw
1231      */
1232     return (rectangleColor
1233 	    (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1234 }
1235 
1236 /* --------- Clipping routines for line */
1237 
1238 /* Clipping based heavily on code from                       */
1239 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
1240 
1241 #define CLIP_LEFT_EDGE   0x1
1242 #define CLIP_RIGHT_EDGE  0x2
1243 #define CLIP_BOTTOM_EDGE 0x4
1244 #define CLIP_TOP_EDGE    0x8
1245 #define CLIP_INSIDE(a)   (!a)
1246 #define CLIP_REJECT(a,b) (a&b)
1247 #define CLIP_ACCEPT(a,b) (!(a|b))
1248 
clipEncode(Sint16 x,Sint16 y,Sint16 left,Sint16 top,Sint16 right,Sint16 bottom)1249 static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
1250 {
1251     int code = 0;
1252 
1253     if (x < left) {
1254 	code |= CLIP_LEFT_EDGE;
1255     } else if (x > right) {
1256 	code |= CLIP_RIGHT_EDGE;
1257     }
1258     if (y < top) {
1259 	code |= CLIP_TOP_EDGE;
1260     } else if (y > bottom) {
1261 	code |= CLIP_BOTTOM_EDGE;
1262     }
1263     return code;
1264 }
1265 
clipLine(SDL_Surface * dst,Sint16 * x1,Sint16 * y1,Sint16 * x2,Sint16 * y2)1266 static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
1267 {
1268     Sint16 left, right, top, bottom;
1269     int code1, code2;
1270     int draw = 0;
1271     Sint16 swaptmp;
1272     float m;
1273 
1274     /*
1275      * Get clipping boundary
1276      */
1277     left = dst->clip_rect.x;
1278     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1279     top = dst->clip_rect.y;
1280     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1281 
1282     while (1) {
1283 	code1 = clipEncode(*x1, *y1, left, top, right, bottom);
1284 	code2 = clipEncode(*x2, *y2, left, top, right, bottom);
1285 	if (CLIP_ACCEPT(code1, code2)) {
1286 	    draw = 1;
1287 	    break;
1288 	} else if (CLIP_REJECT(code1, code2))
1289 	    break;
1290 	else {
1291 	    if (CLIP_INSIDE(code1)) {
1292 		swaptmp = *x2;
1293 		*x2 = *x1;
1294 		*x1 = swaptmp;
1295 		swaptmp = *y2;
1296 		*y2 = *y1;
1297 		*y1 = swaptmp;
1298 		swaptmp = code2;
1299 		code2 = code1;
1300 		code1 = swaptmp;
1301 	    }
1302 	    if (*x2 != *x1) {
1303 		m = (*y2 - *y1) / (float) (*x2 - *x1);
1304 	    } else {
1305 		m = 1.0f;
1306 	    }
1307 	    if (code1 & CLIP_LEFT_EDGE) {
1308 		*y1 += (Sint16) ((left - *x1) * m);
1309 		*x1 = left;
1310 	    } else if (code1 & CLIP_RIGHT_EDGE) {
1311 		*y1 += (Sint16) ((right - *x1) * m);
1312 		*x1 = right;
1313 	    } else if (code1 & CLIP_BOTTOM_EDGE) {
1314 		if (*x2 != *x1) {
1315 		    *x1 += (Sint16) ((bottom - *y1) / m);
1316 		}
1317 		*y1 = bottom;
1318 	    } else if (code1 & CLIP_TOP_EDGE) {
1319 		if (*x2 != *x1) {
1320 		    *x1 += (Sint16) ((top - *y1) / m);
1321 		}
1322 		*y1 = top;
1323 	    }
1324 	}
1325     }
1326 
1327     return draw;
1328 }
1329 
1330 /* ----- Filled rectangle (Box) */
1331 
boxColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1332 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1333 {
1334     Sint16 left, right, top, bottom;
1335     Uint8 *pixel, *pixellast;
1336     int x, dx;
1337     int dy;
1338     int pixx, pixy;
1339     Sint16 w, h, tmp;
1340     int result;
1341     Uint8 *colorptr;
1342 
1343     /*
1344      * Check visibility of clipping rectangle
1345      */
1346     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1347      return(0);
1348     }
1349 
1350     /*
1351      * Order coordinates to ensure that
1352      * x1<=x2 and y1<=y2
1353      */
1354     if (x1 > x2) {
1355 	tmp = x1;
1356 	x1 = x2;
1357 	x2 = tmp;
1358     }
1359     if (y1 > y2) {
1360 	tmp = y1;
1361 	y1 = y2;
1362 	y2 = tmp;
1363     }
1364 
1365     /*
1366      * Get clipping boundary and
1367      * check visibility
1368      */
1369     left = dst->clip_rect.x;
1370     if (x2<left) {
1371      return(0);
1372     }
1373     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1374     if (x1>right) {
1375      return(0);
1376     }
1377     top = dst->clip_rect.y;
1378     if (y2<top) {
1379      return(0);
1380     }
1381     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1382     if (y1>bottom) {
1383      return(0);
1384     }
1385 
1386     /* Clip all points */
1387     if (x1<left) {
1388      x1=left;
1389     } else if (x1>right) {
1390      x1=right;
1391     }
1392     if (x2<left) {
1393      x2=left;
1394     } else if (x2>right) {
1395      x2=right;
1396     }
1397     if (y1<top) {
1398      y1=top;
1399     } else if (y1>bottom) {
1400      y1=bottom;
1401     }
1402     if (y2<top) {
1403      y2=top;
1404     } else if (y2>bottom) {
1405      y2=bottom;
1406     }
1407 
1408     /*
1409      * Test for special cases of straight line or single point
1410      */
1411     if (x1 == x2) {
1412 	if (y1 == y2) {
1413 	    return (pixelColor(dst, x1, y1, color));
1414 	} else {
1415 	    return (vlineColor(dst, x1, y1, y2, color));
1416 	}
1417     }
1418     if (y1 == y2) {
1419 	return (hlineColor(dst, x1, x2, y1, color));
1420     }
1421 
1422     /*
1423      * Calculate width&height
1424      */
1425     w = x2 - x1;
1426     h = y2 - y1;
1427 
1428     /*
1429      * Alpha check
1430      */
1431     if ((color & 255) == 255) {
1432 
1433 	/*
1434 	 * No alpha-blending required
1435 	 */
1436 
1437 	/*
1438 	 * Setup color
1439 	 */
1440 	colorptr = (Uint8 *) & color;
1441 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1442 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1443 	} else {
1444 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1445 	}
1446 
1447 	/*
1448 	 * Lock surface
1449 	 */
1450 	SDL_LockSurface(dst);
1451 
1452 	/*
1453 	 * More variable setup
1454 	 */
1455 	dx = w;
1456 	dy = h;
1457 	pixx = dst->format->BytesPerPixel;
1458 	pixy = dst->pitch;
1459 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
1460 	pixellast = pixel + pixx * dx + pixy * dy;
1461 	dx++;
1462 
1463 	/*
1464 	 * Draw
1465 	 */
1466 	switch (dst->format->BytesPerPixel) {
1467 	case 1:
1468 	    for (; pixel <= pixellast; pixel += pixy) {
1469 		memset(pixel, (Uint8) color, dx);
1470 	    }
1471 	    break;
1472 	case 2:
1473 	    pixy -= (pixx * dx);
1474 	    for (; pixel <= pixellast; pixel += pixy) {
1475 		for (x = 0; x < dx; x++) {
1476 		    *(Uint16*) pixel = color;
1477 		    pixel += pixx;
1478 		}
1479 	    }
1480 	    break;
1481 	case 3:
1482 	    pixy -= (pixx * dx);
1483 	    for (; pixel <= pixellast; pixel += pixy) {
1484 		for (x = 0; x < dx; x++) {
1485 		    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1486 			pixel[0] = (color >> 16) & 0xff;
1487 			pixel[1] = (color >> 8) & 0xff;
1488 			pixel[2] = color & 0xff;
1489 		    } else {
1490 			pixel[0] = color & 0xff;
1491 			pixel[1] = (color >> 8) & 0xff;
1492 			pixel[2] = (color >> 16) & 0xff;
1493 		    }
1494 		    pixel += pixx;
1495 		}
1496 	    }
1497 	    break;
1498 	default:		/* case 4 */
1499 	    pixy -= (pixx * dx);
1500 	    for (; pixel <= pixellast; pixel += pixy) {
1501 		for (x = 0; x < dx; x++) {
1502 		    *(Uint32 *) pixel = color;
1503 		    pixel += pixx;
1504 		}
1505 	    }
1506 	    break;
1507 	}
1508 
1509 	/*
1510 	 * Unlock surface
1511 	 */
1512 	SDL_UnlockSurface(dst);
1513 
1514 	result = 0;
1515 
1516     } else {
1517 
1518 	result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
1519 
1520     }
1521 
1522     return (result);
1523 }
1524 
boxRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1525 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1526 {
1527     /*
1528      * Draw
1529      */
1530     return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1531 }
1532 
1533 /* ----- Line */
1534 
1535 /* Non-alpha line drawing code adapted from routine          */
1536 /* by Pete Shinners, pete@shinners.org                       */
1537 /* Originally from pygame, http://pygame.seul.org            */
1538 
1539 #define ABS(a) (((a)<0) ? -(a) : (a))
1540 
lineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1541 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1542 {
1543     int pixx, pixy;
1544     int x, y;
1545     int dx, dy;
1546     int ax, ay;
1547     int sx, sy;
1548     int swaptmp;
1549     Uint8 *pixel;
1550     Uint8 *colorptr;
1551 
1552     /*
1553      * Clip line and test if we have to draw
1554      */
1555     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
1556 	return (0);
1557     }
1558 
1559     /*
1560      * Test for special cases of straight lines or single point
1561      */
1562     if (x1 == x2) {
1563 	if (y1 < y2) {
1564 	    return (vlineColor(dst, x1, y1, y2, color));
1565 	} else if (y1 > y2) {
1566 	    return (vlineColor(dst, x1, y2, y1, color));
1567 	} else {
1568 	    return (pixelColor(dst, x1, y1, color));
1569 	}
1570     }
1571     if (y1 == y2) {
1572 	if (x1 < x2) {
1573 	    return (hlineColor(dst, x1, x2, y1, color));
1574 	} else if (x1 > x2) {
1575 	    return (hlineColor(dst, x2, x1, y1, color));
1576 	}
1577     }
1578 
1579     /*
1580      * Variable setup
1581      */
1582     dx = x2 - x1;
1583     dy = y2 - y1;
1584     sx = (dx >= 0) ? 1 : -1;
1585     sy = (dy >= 0) ? 1 : -1;
1586 
1587     /* Lock surface */
1588     if (SDL_MUSTLOCK(dst)) {
1589 	if (SDL_LockSurface(dst) < 0) {
1590 	    return (-1);
1591 	}
1592     }
1593 
1594     /*
1595      * Check for alpha blending
1596      */
1597     if ((color & 255) == 255) {
1598 
1599 	/*
1600 	 * No alpha blending - use fast pixel routines
1601 	 */
1602 
1603 	/*
1604 	 * Setup color
1605 	 */
1606 	colorptr = (Uint8 *) & color;
1607 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1608 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1609 	} else {
1610 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1611 	}
1612 
1613 	/*
1614 	 * More variable setup
1615 	 */
1616 	dx = sx * dx + 1;
1617 	dy = sy * dy + 1;
1618 	pixx = dst->format->BytesPerPixel;
1619 	pixy = dst->pitch;
1620 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
1621 	pixx *= sx;
1622 	pixy *= sy;
1623 	if (dx < dy) {
1624 	    swaptmp = dx;
1625 	    dx = dy;
1626 	    dy = swaptmp;
1627 	    swaptmp = pixx;
1628 	    pixx = pixy;
1629 	    pixy = swaptmp;
1630 	}
1631 
1632 	/*
1633 	 * Draw
1634 	 */
1635 	x = 0;
1636 	y = 0;
1637 	switch (dst->format->BytesPerPixel) {
1638 	case 1:
1639 	    for (; x < dx; x++, pixel += pixx) {
1640 		*pixel = color;
1641 		y += dy;
1642 		if (y >= dx) {
1643 		    y -= dx;
1644 		    pixel += pixy;
1645 		}
1646 	    }
1647 	    break;
1648 	case 2:
1649 	    for (; x < dx; x++, pixel += pixx) {
1650 		*(Uint16 *) pixel = color;
1651 		y += dy;
1652 		if (y >= dx) {
1653 		    y -= dx;
1654 		    pixel += pixy;
1655 		}
1656 	    }
1657 	    break;
1658 	case 3:
1659 	    for (; x < dx; x++, pixel += pixx) {
1660 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1661 		    pixel[0] = (color >> 16) & 0xff;
1662 		    pixel[1] = (color >> 8) & 0xff;
1663 		    pixel[2] = color & 0xff;
1664 		} else {
1665 		    pixel[0] = color & 0xff;
1666 		    pixel[1] = (color >> 8) & 0xff;
1667 		    pixel[2] = (color >> 16) & 0xff;
1668 		}
1669 		y += dy;
1670 		if (y >= dx) {
1671 		    y -= dx;
1672 		    pixel += pixy;
1673 		}
1674 	    }
1675 	    break;
1676 	default:		/* case 4 */
1677 	    for (; x < dx; x++, pixel += pixx) {
1678 		*(Uint32 *) pixel = color;
1679 		y += dy;
1680 		if (y >= dx) {
1681 		    y -= dx;
1682 		    pixel += pixy;
1683 		}
1684 	    }
1685 	    break;
1686 	}
1687 
1688     } else {
1689 
1690 	/*
1691 	 * Alpha blending required - use single-pixel blits
1692 	 */
1693 
1694 	ax = ABS(dx) << 1;
1695 	ay = ABS(dy) << 1;
1696 	x = x1;
1697 	y = y1;
1698 	if (ax > ay) {
1699 	    int d = ay - (ax >> 1);
1700 
1701 	    while (x != x2) {
1702 		pixelColorNolock (dst, x, y, color);
1703 		if (d > 0 || (d == 0 && sx == 1)) {
1704 		    y += sy;
1705 		    d -= ax;
1706 		}
1707 		x += sx;
1708 		d += ay;
1709 	    }
1710 	} else {
1711 	    int d = ax - (ay >> 1);
1712 
1713 	    while (y != y2) {
1714 		pixelColorNolock (dst, x, y, color);
1715 		if (d > 0 || ((d == 0) && (sy == 1))) {
1716 		    x += sx;
1717 		    d -= ay;
1718 		}
1719 		y += sy;
1720 		d += ax;
1721 	    }
1722 	}
1723 	pixelColorNolock (dst, x, y, color);
1724 
1725     }
1726 
1727     /* Unlock surface */
1728     if (SDL_MUSTLOCK(dst)) {
1729 	SDL_UnlockSurface(dst);
1730     }
1731 
1732     return (0);
1733 }
1734 
lineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1735 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1736 {
1737     /*
1738      * Draw
1739      */
1740     return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1741 }
1742 
1743 /* AA Line */
1744 
1745 #define AAlevels 256
1746 #define AAbits 8
1747 
1748 /*
1749 
1750 This implementation of the Wu antialiasing code is based on Mike Abrash's
1751 DDJ article which was reprinted as Chapter 42 of his Graphics Programming
1752 Black Book, but has been optimized to work with SDL and utilizes 32-bit
1753 fixed-point arithmetic. (A. Schiffler).
1754 
1755 */
1756 
aalineColorInt(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,int draw_endpoint)1757 int aalineColorInt(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
1758 {
1759     Sint32 xx0, yy0, xx1, yy1;
1760     int result;
1761     Uint32 intshift, erracc, erradj;
1762     Uint32 erracctmp, wgt, wgtcompmask;
1763     int dx, dy, tmp, xdir, y0p1, x0pxdir;
1764 
1765     /*
1766      * Check visibility of clipping rectangle
1767      */
1768     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1769      return(0);
1770     }
1771 
1772     /*
1773      * Clip line and test if we have to draw
1774      */
1775     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
1776 	return (0);
1777     }
1778 
1779     /*
1780      * Keep on working with 32bit numbers
1781      */
1782     xx0 = x1;
1783     yy0 = y1;
1784     xx1 = x2;
1785     yy1 = y2;
1786 
1787     /*
1788      * Reorder points if required
1789      */
1790     if (yy0 > yy1) {
1791 	tmp = yy0;
1792 	yy0 = yy1;
1793 	yy1 = tmp;
1794 	tmp = xx0;
1795 	xx0 = xx1;
1796 	xx1 = tmp;
1797     }
1798 
1799     /*
1800      * Calculate distance
1801      */
1802     dx = xx1 - xx0;
1803     dy = yy1 - yy0;
1804 
1805     /*
1806      * Adjust for negative dx and set xdir
1807      */
1808     if (dx >= 0) {
1809 	xdir = 1;
1810     } else {
1811 	xdir = -1;
1812 	dx = (-dx);
1813     }
1814 
1815     /*
1816      * Check for special cases
1817      */
1818     if (dx == 0) {
1819 	/*
1820 	 * Vertical line
1821 	 */
1822 	return (vlineColor(dst, x1, y1, y2, color));
1823     } else if (dy == 0) {
1824 	/*
1825 	 * Horizontal line
1826 	 */
1827 	return (hlineColor(dst, x1, x2, y1, color));
1828     } else if (dx == dy) {
1829 	/*
1830 	 * Diagonal line
1831 	 */
1832 	return (lineColor(dst, x1, y1, x2, y2, color));
1833     }
1834 
1835     /*
1836      * Line is not horizontal, vertical or diagonal
1837      */
1838     result = 0;
1839 
1840     /*
1841      * Zero accumulator
1842      */
1843     erracc = 0;
1844 
1845     /*
1846      * # of bits by which to shift erracc to get intensity level
1847      */
1848     intshift = 32 - AAbits;
1849     /*
1850      * Mask used to flip all bits in an intensity weighting
1851      */
1852     wgtcompmask = AAlevels - 1;
1853 
1854     /* Lock surface */
1855     if (SDL_MUSTLOCK(dst)) {
1856 	if (SDL_LockSurface(dst) < 0) {
1857 	    return (-1);
1858 	}
1859     }
1860 
1861     /*
1862      * Draw the initial pixel in the foreground color
1863      */
1864     result |= pixelColorNolock(dst, x1, y1, color);
1865 
1866     /*
1867      * x-major or y-major?
1868      */
1869     if (dy > dx) {
1870 
1871 	/*
1872 	 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
1873 	 * X advances every time Y advances 1 pixel, truncating the result so that
1874 	 * we won't overrun the endpoint along the X axis
1875 	 */
1876 	/*
1877 	 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
1878 	 */
1879 	erradj = ((dx << 16) / dy) << 16;
1880 
1881 	/*
1882 	 * draw all pixels other than the first and last
1883 	 */
1884 	x0pxdir = xx0 + xdir;
1885 	while (--dy) {
1886 	    erracctmp = erracc;
1887 	    erracc += erradj;
1888 	    if (erracc <= erracctmp) {
1889 		/*
1890 		 * rollover in error accumulator, x coord advances
1891 		 */
1892 		xx0 = x0pxdir;
1893 		x0pxdir += xdir;
1894 	    }
1895 	    yy0++;		/* y-major so always advance Y */
1896 
1897 	    /*
1898 	     * the AAbits most significant bits of erracc give us the intensity
1899 	     * weighting for this pixel, and the complement of the weighting for
1900 	     * the paired pixel.
1901 	     */
1902 	    wgt = (erracc >> intshift) & 255;
1903 	    result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1904 	    result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
1905 	}
1906 
1907     } else {
1908 
1909 	/*
1910 	 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
1911 	 * that Y advances each time X advances 1 pixel, truncating the result so
1912 	 * that we won't overrun the endpoint along the X axis.
1913 	 */
1914 	/*
1915 	 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
1916 	 */
1917 	erradj = ((dy << 16) / dx) << 16;
1918 
1919 	/*
1920 	 * draw all pixels other than the first and last
1921 	 */
1922 	y0p1 = yy0 + 1;
1923 	while (--dx) {
1924 
1925 	    erracctmp = erracc;
1926 	    erracc += erradj;
1927 	    if (erracc <= erracctmp) {
1928 		/*
1929 		 * Accumulator turned over, advance y
1930 		 */
1931 		yy0 = y0p1;
1932 		y0p1++;
1933 	    }
1934 	    xx0 += xdir;	/* x-major so always advance X */
1935 	    /*
1936 	     * the AAbits most significant bits of erracc give us the intensity
1937 	     * weighting for this pixel, and the complement of the weighting for
1938 	     * the paired pixel.
1939 	     */
1940 	    wgt = (erracc >> intshift) & 255;
1941 	    result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1942 	    result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
1943 	}
1944     }
1945 
1946     /*
1947      * Do we have to draw the endpoint
1948      */
1949     if (draw_endpoint) {
1950 	/*
1951 	 * Draw final pixel, always exactly intersected by the line and doesn't
1952 	 * need to be weighted.
1953 	 */
1954 	result |= pixelColorNolock (dst, x2, y2, color);
1955     }
1956 
1957     /* Unlock surface */
1958     if (SDL_MUSTLOCK(dst)) {
1959 	SDL_UnlockSurface(dst);
1960     }
1961 
1962     return (result);
1963 }
1964 
aalineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1965 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1966 {
1967     return (aalineColorInt(dst, x1, y1, x2, y2, color, 1));
1968 }
1969 
aalineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1970 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1971 {
1972     return (aalineColorInt
1973 	    (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
1974 }
1975 
1976 
1977 /* ----- Circle */
1978 
1979 /* Note: Based on algorithm from sge library, modified by A. Schiffler */
1980 /* with multiple pixel-draw removal and other minor speedup changes.   */
1981 
circleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)1982 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
1983 {
1984     Sint16 left, right, top, bottom;
1985     int result;
1986     Sint16 x1, y1, x2, y2;
1987     Sint16 cx = 0;
1988     Sint16 cy = r;
1989     Sint16 ocx = (Sint16) 0xffff;
1990     Sint16 ocy = (Sint16) 0xffff;
1991     Sint16 df = 1 - r;
1992     Sint16 d_e = 3;
1993     Sint16 d_se = -2 * r + 5;
1994     Sint16 xpcx, xmcx, xpcy, xmcy;
1995     Sint16 ypcy, ymcy, ypcx, ymcx;
1996     Uint8 *colorptr;
1997 
1998     /*
1999      * Check visibility of clipping rectangle
2000      */
2001     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2002      return(0);
2003     }
2004 
2005     /*
2006      * Sanity check radius
2007      */
2008     if (r < 0) {
2009 	return (-1);
2010     }
2011 
2012     /*
2013      * Special case for r=0 - draw a point
2014      */
2015     if (r == 0) {
2016 	return (pixelColor(dst, x, y, color));
2017     }
2018 
2019     /*
2020      * Get circle and clipping boundary and
2021      * test if bounding box of circle is visible
2022      */
2023     x2 = x + r;
2024     left = dst->clip_rect.x;
2025     if (x2<left) {
2026      return(0);
2027     }
2028     x1 = x - r;
2029     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2030     if (x1>right) {
2031      return(0);
2032     }
2033     y2 = y + r;
2034     top = dst->clip_rect.y;
2035     if (y2<top) {
2036      return(0);
2037     }
2038     y1 = y - r;
2039     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2040     if (y1>bottom) {
2041      return(0);
2042     }
2043 
2044     /*
2045      * Draw circle
2046      */
2047     result = 0;
2048 
2049     /* Lock surface */
2050     if (SDL_MUSTLOCK(dst)) {
2051 	if (SDL_LockSurface(dst) < 0) {
2052 	    return (-1);
2053 	}
2054     }
2055 
2056     /*
2057      * Alpha Check
2058      */
2059     if ((color & 255) == 255) {
2060 
2061 	/*
2062 	 * No Alpha - direct memory writes
2063 	 */
2064 
2065 	/*
2066 	 * Setup color
2067 	 */
2068 	colorptr = (Uint8 *) & color;
2069 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2070 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2071 	} else {
2072 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2073 	}
2074 
2075 	/*
2076 	 * Draw
2077 	 */
2078 	do {
2079 		ypcy = y + cy;
2080 		ymcy = y - cy;
2081 		if (cx > 0) {
2082 		    xpcx = x + cx;
2083 		    xmcx = x - cx;
2084 		    result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
2085 		    result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
2086 		    result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
2087 		    result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
2088 		} else {
2089 		    result |= fastPixelColorNolock(dst, x, ymcy, color);
2090 		    result |= fastPixelColorNolock(dst, x, ypcy, color);
2091 		}
2092 		xpcy = x + cy;
2093 		xmcy = x - cy;
2094 		if ((cx > 0) && (cx != cy)) {
2095 		    ypcx = y + cx;
2096 		    ymcx = y - cx;
2097 		    result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
2098 		    result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
2099 		    result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
2100 		    result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
2101 		} else if (cx == 0) {
2102 		    result |= fastPixelColorNolock(dst, xmcy, y, color);
2103 		    result |= fastPixelColorNolock(dst, xpcy, y, color);
2104 		}
2105 	    /*
2106 	     * Update
2107 	     */
2108 	    if (df < 0) {
2109 		df += d_e;
2110 		d_e += 2;
2111 		d_se += 2;
2112 	    } else {
2113 		df += d_se;
2114 		d_e += 2;
2115 		d_se += 4;
2116 		cy--;
2117 	    }
2118 	    cx++;
2119 	} while (cx <= cy);
2120 
2121 	/*
2122 	 * Unlock surface
2123 	 */
2124 	SDL_UnlockSurface(dst);
2125 
2126     } else {
2127 
2128 	/*
2129 	 * Using Alpha - blended pixel blits
2130 	 */
2131 
2132 	do {
2133 	    /*
2134 	     * Draw
2135 	     */
2136 		ypcy = y + cy;
2137 		ymcy = y - cy;
2138 		if (cx > 0) {
2139 		    xpcx = x + cx;
2140 		    xmcx = x - cx;
2141 		    result |= pixelColorNolock (dst, xmcx, ypcy, color);
2142 		    result |= pixelColorNolock (dst, xpcx, ypcy, color);
2143 		    result |= pixelColorNolock (dst, xmcx, ymcy, color);
2144 		    result |= pixelColorNolock (dst, xpcx, ymcy, color);
2145 		} else {
2146 		    result |= pixelColorNolock (dst, x, ymcy, color);
2147 		    result |= pixelColorNolock (dst, x, ypcy, color);
2148 		}
2149 		xpcy = x + cy;
2150 		xmcy = x - cy;
2151 		if ((cx > 0) && (cx != cy)) {
2152 		    ypcx = y + cx;
2153 		    ymcx = y - cx;
2154 		    result |= pixelColorNolock (dst, xmcy, ypcx, color);
2155 		    result |= pixelColorNolock (dst, xpcy, ypcx, color);
2156 		    result |= pixelColorNolock (dst, xmcy, ymcx, color);
2157 		    result |= pixelColorNolock (dst, xpcy, ymcx, color);
2158 		} else if (cx == 0) {
2159 		    result |= pixelColorNolock (dst, xmcy, y, color);
2160 		    result |= pixelColorNolock (dst, xpcy, y, color);
2161 		}
2162 	    /*
2163 	     * Update
2164 	     */
2165 	    if (df < 0) {
2166 		df += d_e;
2167 		d_e += 2;
2168 		d_se += 2;
2169 	    } else {
2170 		df += d_se;
2171 		d_e += 2;
2172 		d_se += 4;
2173 		cy--;
2174 	    }
2175 	    cx++;
2176 	} while (cx <= cy);
2177 
2178     }				/* Alpha check */
2179 
2180     /* Unlock surface */
2181     if (SDL_MUSTLOCK(dst)) {
2182 	SDL_UnlockSurface(dst);
2183     }
2184 
2185     return (result);
2186 }
2187 
circleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2188 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2189 {
2190     /*
2191      * Draw
2192      */
2193     return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2194 }
2195 
2196 /* ----- Arc */
2197 
2198 /* Note: Based on above circle algorithm by A. Schiffler below.  Written by D. Raber */
2199 /* Calculates which octants arc goes through and renders accordingly */
2200 
arcColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Sint16 start,Sint16 end,Uint32 color)2201 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Sint16 start, Sint16 end, Uint32 color)
2202 {
2203     Sint16 left, right, top, bottom;
2204     int result;
2205     Sint16 x1, y1, x2, y2;
2206     Sint16 cx = 0;
2207     Sint16 cy = r;
2208     Sint16 ocx = (Sint16) 0xffff;
2209     Sint16 ocy = (Sint16) 0xffff;
2210     Sint16 df = 1 - r;
2211     Sint16 d_e = 3;
2212     Sint16 d_se = -2 * r + 5;
2213     Sint16 xpcx, xmcx, xpcy, xmcy;
2214     Sint16 ypcy, ymcy, ypcx, ymcx;
2215     Uint8 *colorptr;
2216 
2217     /*
2218      * Check visibility of clipping rectangle
2219      */
2220     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2221      return(0);
2222     }
2223 
2224     /*
2225      * Sanity check radius
2226      */
2227     if (r < 0) {
2228 	return (-1);
2229     }
2230 
2231     /*
2232      * Special case for r=0 - draw a point
2233      */
2234     if (r == 0) {
2235 	return (pixelColor(dst, x, y, color));
2236     }
2237 
2238     /*
2239      * Fixup angles
2240      */
2241     start = start % 360;
2242     end = end % 360;
2243 
2244     /*
2245      * Get arc's circle and clipping boundary and
2246      * test if bounding box of circle is visible
2247      */
2248     x2 = x + r;
2249     left = dst->clip_rect.x;
2250     if (x2<left) {
2251      return(0);
2252     }
2253     x1 = x - r;
2254     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2255     if (x1>right) {
2256      return(0);
2257     }
2258     y2 = y + r;
2259     top = dst->clip_rect.y;
2260     if (y2<top) {
2261      return(0);
2262     }
2263     y1 = y - r;
2264     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2265     if (y1>bottom) {
2266      return(0);
2267     }
2268 
2269     /*
2270      * Draw arc
2271      */
2272     result = 0;
2273 
2274     /* Lock surface */
2275     if (SDL_MUSTLOCK(dst)) {
2276 	if (SDL_LockSurface(dst) < 0) {
2277 	    return (-1);
2278 	}
2279     }
2280 
2281     // Octant labelling
2282     //
2283     //  \ 5 | 6 /
2284     //   \  |  /
2285     //  4 \ | / 7
2286     //     \|/
2287     //------+------ +x
2288     //     /|\
2289     //  3 / | \ 0
2290     //   /  |  \
2291     //  / 2 | 1 \
2292     //      +y
2293 
2294 	Uint8 drawoct = 0; // 0x00000000
2295 					   // whether or not to keep drawing a given octant.
2296 					   // For example: 0x00111100 means we're drawing in octants 2-5
2297 
2298 	// 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
2299 	while (start < 0) start += 360;
2300 	while (end < 0) end += 360;
2301 	start %= 360;
2302 	end %= 360;
2303 
2304 	// now, we find which octants we're drawing in.
2305 	int startoct = start / 45;
2306 	int endoct = end / 45;
2307 	int oct = startoct - 1; // we increment as first step in loop
2308 
2309 	int stopval_start, stopval_end; // what values of cx to stop at.
2310 	double temp;
2311 
2312 	do {
2313 		oct = (oct + 1) % 8;
2314 
2315 		if (oct == startoct) {
2316 			// need to compute stopval_start for this octant.  Look at picture above if this is unclear
2317 			switch (oct)
2318 			{
2319 			case 0:
2320 			case 3:
2321 				temp = sin(start * M_PI / 180);
2322 				break;
2323 			case 1:
2324 			case 6:
2325 				temp = cos(start * M_PI / 180);
2326 				break;
2327 			case 2:
2328 			case 5:
2329 				temp = -cos(start * M_PI / 180);
2330 				break;
2331 			case 4:
2332 			case 7:
2333 				temp = -sin(start * M_PI / 180);
2334 				break;
2335 			}
2336 			temp *= r;
2337 			stopval_start = (int)temp; // always round down.
2338 									   // This isn't arbitrary, but requires graph paper to explain well.
2339 									   // The basic idea is that we're always changing drawoct after we draw, so we
2340 									   // stop immediately after we render the last sensible pixel at x = ((int)temp).
2341 
2342 			// and whether to draw in this octant initially
2343 			if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
2344 			else		 drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
2345 		}
2346 		if (oct == endoct) {
2347 			// need to compute stopval_end for this octant
2348 			switch (oct)
2349 			{
2350 			case 0:
2351 			case 3:
2352 				temp = sin(end * M_PI / 180);
2353 				break;
2354 			case 1:
2355 			case 6:
2356 				temp = cos(end * M_PI / 180);
2357 				break;
2358 			case 2:
2359 			case 5:
2360 				temp = -cos(end * M_PI / 180);
2361 				break;
2362 			case 4:
2363 			case 7:
2364 				temp = -sin(end * M_PI / 180);
2365 				break;
2366 			}
2367 			temp *= r;
2368 			stopval_end = (int)temp;
2369 
2370 			// and whether to draw in this octant initially
2371 			if (startoct == endoct)	{
2372 				// note:      we start drawing, stop, then start again in this case
2373 				// otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
2374 				if (start > end) {
2375 					// unfortunately, if we're in the same octant and need to draw over the whole circle,
2376 					// we need to set the rest to true, because the while loop will end at the bottom.
2377 					drawoct = 255;
2378 				} else {
2379 					drawoct &= 255 - (1 << oct);
2380 				}
2381 			}
2382 			else if (oct % 2) drawoct &= 255 - (1 << oct);
2383 			else			  drawoct |= (1 << oct);
2384 		} else if (oct != startoct) { // already verified that it's != endoct
2385 			drawoct |= (1 << oct); // draw this entire segment
2386 		}
2387 	} while (oct != endoct);
2388 
2389 	// so now we have what octants to draw and when to draw them.  all that's left is the actual raster code.
2390 
2391 
2392     /*
2393      * Alpha Check
2394      */
2395     if ((color & 255) == 255) {
2396 
2397 	/*
2398 	 * No Alpha - direct memory writes
2399 	 */
2400 
2401 	/*
2402 	 * Setup color
2403 	 */
2404 	colorptr = (Uint8 *) & color;
2405 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2406 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2407 	} else {
2408 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2409 	}
2410 
2411 	/*
2412 	 * Draw
2413 	 */
2414 	do {
2415 		ypcy = y + cy;
2416 		ymcy = y - cy;
2417 		if (cx > 0) {
2418 			xpcx = x + cx;
2419 			xmcx = x - cx;
2420 			// always check if we're drawing a certain octant before adding a pixel to that octant.
2421 			if (drawoct & 4)  result |= fastPixelColorNolock(dst, xmcx, ypcy, color); // drawoct & 4 = 22; drawoct[2]
2422 			if (drawoct & 2)  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
2423 			if (drawoct & 32) result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
2424 			if (drawoct & 64) result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
2425 		} else {
2426 			if (drawoct & 6)  result |= fastPixelColorNolock(dst, x, ypcy, color); // 4 + 2; drawoct[2] || drawoct[1]
2427 			if (drawoct & 96) result |= fastPixelColorNolock(dst, x, ymcy, color); // 32 + 64
2428 		}
2429 
2430 		xpcy = x + cy;
2431 		xmcy = x - cy;
2432 		if (cx > 0 && cx != cy) {
2433 			ypcx = y + cx;
2434 			ymcx = y - cx;
2435 			if (drawoct & 8)   result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
2436 			if (drawoct & 1)   result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
2437 			if (drawoct & 16)  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
2438 			if (drawoct & 128) result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
2439 		} else if (cx == 0) {
2440 			if (drawoct & 24)  result |= fastPixelColorNolock(dst, xmcy, y, color); // 8 + 16
2441 			if (drawoct & 129) result |= fastPixelColorNolock(dst, xpcy, y, color); // 1 + 128
2442 		}
2443 
2444 
2445 	    /*
2446 	     * Update whether we're drawing an octant
2447 	     */
2448 		if (stopval_start == cx) {
2449 			// works like an on-off switch because start & end may be in the same octant.
2450 			if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
2451 			else drawoct |= (1 << startoct);
2452 		}
2453 		if (stopval_end == cx) {
2454 			if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
2455 			else drawoct |= (1 << endoct);
2456 		}
2457 
2458 		/*
2459 	     * Update pixels
2460 	     */
2461 	    if (df < 0) {
2462 			df += d_e;
2463 			d_e += 2;
2464 			d_se += 2;
2465 	    } else {
2466 			df += d_se;
2467 			d_e += 2;
2468 			d_se += 4;
2469 			cy--;
2470 	    }
2471 	    cx++;
2472 	} while (cx <= cy);
2473 
2474 	/*
2475 	 * Unlock surface
2476 	 */
2477 	SDL_UnlockSurface(dst);
2478 
2479     } else {
2480 
2481 	/*
2482 	 * Using Alpha - blended pixel blits
2483 	 */
2484 
2485 	do {
2486 		ypcy = y + cy;
2487 		ymcy = y - cy;
2488 		if (cx > 0) {
2489 			xpcx = x + cx;
2490 			xmcx = x - cx;
2491 
2492 			// always check if we're drawing a certain octant before adding a pixel to that octant.
2493 			if (drawoct & 4)  result |= pixelColorNolock(dst, xmcx, ypcy, color);
2494 			if (drawoct & 2)  result |= pixelColorNolock(dst, xpcx, ypcy, color);
2495 			if (drawoct & 32) result |= pixelColorNolock(dst, xmcx, ymcy, color);
2496 			if (drawoct & 64) result |= pixelColorNolock(dst, xpcx, ymcy, color);
2497 		} else {
2498 			if (drawoct & 96) result |= pixelColorNolock(dst, x, ymcy, color);
2499 			if (drawoct & 6)  result |= pixelColorNolock(dst, x, ypcy, color);
2500 		}
2501 
2502 		xpcy = x + cy;
2503 		xmcy = x - cy;
2504 		if (cx > 0 && cx != cy) {
2505 			ypcx = y + cx;
2506 			ymcx = y - cx;
2507 			if (drawoct & 8)   result |= pixelColorNolock(dst, xmcy, ypcx, color);
2508 			if (drawoct & 1)   result |= pixelColorNolock(dst, xpcy, ypcx, color);
2509 			if (drawoct & 16)  result |= pixelColorNolock(dst, xmcy, ymcx, color);
2510 			if (drawoct & 128) result |= pixelColorNolock(dst, xpcy, ymcx, color);
2511 		} else if (cx == 0) {
2512 			if (drawoct & 24)  result |= pixelColorNolock(dst, xmcy, y, color);
2513 			if (drawoct & 129) result |= pixelColorNolock(dst, xpcy, y, color);
2514 		}
2515 
2516 
2517 	    /*
2518 	     * Update whether we're drawing an octant
2519 	     */
2520 		if (stopval_start == cx) {
2521 			// works like an on-off switch.
2522 			// This is just in case start & end are in the same octant.
2523 			if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
2524 			else						   drawoct |= (1 << startoct);
2525 		}
2526 		if (stopval_end == cx) {
2527 			if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
2528 			else						 drawoct |= (1 << endoct);
2529 		}
2530 
2531 		/*
2532 	     * Update pixels
2533 	     */
2534 	    if (df < 0) {
2535 			df += d_e;
2536 			d_e += 2;
2537 			d_se += 2;
2538 	    } else {
2539 			df += d_se;
2540 			d_e += 2;
2541 			d_se += 4;
2542 			cy--;
2543 	    }
2544 	    cx++;
2545 	} while (cx <= cy);
2546 
2547     }				/* Alpha check */
2548 
2549     /* Unlock surface */
2550     if (SDL_MUSTLOCK(dst)) {
2551 	SDL_UnlockSurface(dst);
2552     }
2553 
2554     return (result);
2555 }
2556 
arcRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2557 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2558 {
2559     /*
2560      * Draw
2561      */
2562     return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2563 }
2564 
2565 /* ----- AA Circle */
2566 
2567 /* AA circle is based on AAellipse  */
2568 
aacircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2569 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2570 {
2571     return (aaellipseColor(dst, x, y, r, r, color));
2572 }
2573 
aacircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2574 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2575 {
2576     /*
2577      * Draw
2578      */
2579     return (aaellipseColor
2580 	    (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2581 }
2582 
2583 /* ----- Filled Circle */
2584 
2585 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
2586 
2587 /* and other speedup changes. */
2588 
filledCircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2589 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2590 {
2591     Sint16 left, right, top, bottom;
2592     int result;
2593     Sint16 x1, y1, x2, y2;
2594     Sint16 cx = 0;
2595     Sint16 cy = r;
2596     Sint16 ocx = (Sint16) 0xffff;
2597     Sint16 ocy = (Sint16) 0xffff;
2598     Sint16 df = 1 - r;
2599     Sint16 d_e = 3;
2600     Sint16 d_se = -2 * r + 5;
2601     Sint16 xpcx, xmcx, xpcy, xmcy;
2602     Sint16 ypcy, ymcy, ypcx, ymcx;
2603 
2604     /*
2605      * Check visibility of clipping rectangle
2606      */
2607     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2608      return(0);
2609     }
2610 
2611     /*
2612      * Sanity check radius
2613      */
2614     if (r < 0) {
2615 	return (-1);
2616     }
2617 
2618     /*
2619      * Special case for r=0 - draw a point
2620      */
2621     if (r == 0) {
2622 	return (pixelColor(dst, x, y, color));
2623     }
2624 
2625     /*
2626      * Get circle and clipping boundary and
2627      * test if bounding box of circle is visible
2628      */
2629     x2 = x + r;
2630     left = dst->clip_rect.x;
2631     if (x2<left) {
2632      return(0);
2633     }
2634     x1 = x - r;
2635     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2636     if (x1>right) {
2637      return(0);
2638     }
2639     y2 = y + r;
2640     top = dst->clip_rect.y;
2641     if (y2<top) {
2642      return(0);
2643     }
2644     y1 = y - r;
2645     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2646     if (y1>bottom) {
2647      return(0);
2648     }
2649 
2650     /*
2651      * Draw
2652      */
2653     result = 0;
2654     do {
2655 	xpcx = x + cx;
2656 	xmcx = x - cx;
2657 	xpcy = x + cy;
2658 	xmcy = x - cy;
2659 	if (ocy != cy) {
2660 	    if (cy > 0) {
2661 		ypcy = y + cy;
2662 		ymcy = y - cy;
2663 		result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
2664 		result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
2665 	    } else {
2666 		result |= hlineColor(dst, xmcx, xpcx, y, color);
2667 	    }
2668 	    ocy = cy;
2669 	}
2670 	if (ocx != cx) {
2671 	    if (cx != cy) {
2672 		if (cx > 0) {
2673 		    ypcx = y + cx;
2674 		    ymcx = y - cx;
2675 		    result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
2676 		    result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
2677 		} else {
2678 		    result |= hlineColor(dst, xmcy, xpcy, y, color);
2679 		}
2680 	    }
2681 	    ocx = cx;
2682 	}
2683 	/*
2684 	 * Update
2685 	 */
2686 	if (df < 0) {
2687 	    df += d_e;
2688 	    d_e += 2;
2689 	    d_se += 2;
2690 	} else {
2691 	    df += d_se;
2692 	    d_e += 2;
2693 	    d_se += 4;
2694 	    cy--;
2695 	}
2696 	cx++;
2697     } while (cx <= cy);
2698 
2699     return (result);
2700 }
2701 
filledCircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2702 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2703 {
2704     /*
2705      * Draw
2706      */
2707     return (filledCircleColor
2708 	    (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2709 }
2710 
2711 
2712 /* ----- Ellipse */
2713 
2714 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
2715 /* and other speedup changes. */
2716 
ellipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)2717 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2718 {
2719     Sint16 left, right, top, bottom;
2720     int result;
2721     Sint16 x1, y1, x2, y2;
2722     int ix, iy;
2723     int h, i, j, k;
2724     int oh, oi, oj, ok;
2725     int xmh, xph, ypk, ymk;
2726     int xmi, xpi, ymj, ypj;
2727     int xmj, xpj, ymi, ypi;
2728     int xmk, xpk, ymh, yph;
2729     Uint8 *colorptr;
2730 
2731     /*
2732      * Check visibility of clipping rectangle
2733      */
2734     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
2735      return(0);
2736     }
2737 
2738     /*
2739      * Sanity check radii
2740      */
2741     if ((rx < 0) || (ry < 0)) {
2742 	return (-1);
2743     }
2744 
2745     /*
2746      * Special case for rx=0 - draw a vline
2747      */
2748     if (rx == 0) {
2749 	return (vlineColor(dst, x, y - ry, y + ry, color));
2750     }
2751     /*
2752      * Special case for ry=0 - draw a hline
2753      */
2754     if (ry == 0) {
2755 	return (hlineColor(dst, x - rx, x + rx, y, color));
2756     }
2757 
2758     /*
2759      * Get circle and clipping boundary and
2760      * test if bounding box of circle is visible
2761      */
2762     x2 = x + rx;
2763     left = dst->clip_rect.x;
2764     if (x2<left) {
2765      return(0);
2766     }
2767     x1 = x - rx;
2768     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2769     if (x1>right) {
2770      return(0);
2771     }
2772     y2 = y + ry;
2773     top = dst->clip_rect.y;
2774     if (y2<top) {
2775      return(0);
2776     }
2777     y1 = y - ry;
2778     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2779     if (y1>bottom) {
2780      return(0);
2781     }
2782 
2783     /*
2784      * Init vars
2785      */
2786     oh = oi = oj = ok = 0xFFFF;
2787 
2788     /*
2789      * Draw
2790      */
2791     result = 0;
2792 
2793     /* Lock surface */
2794     if (SDL_MUSTLOCK(dst)) {
2795 	if (SDL_LockSurface(dst) < 0) {
2796 	    return (-1);
2797 	}
2798     }
2799 
2800     /*
2801      * Check alpha
2802      */
2803     if ((color & 255) == 255) {
2804 
2805 	/*
2806 	 * No Alpha - direct memory writes
2807 	 */
2808 
2809 	/*
2810 	 * Setup color
2811 	 */
2812 	colorptr = (Uint8 *) & color;
2813 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2814 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2815 	} else {
2816 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2817 	}
2818 
2819 
2820 	if (rx > ry) {
2821 	    ix = 0;
2822 	    iy = rx * 64;
2823 
2824 	    do {
2825 		h = (ix + 32) >> 6;
2826 		i = (iy + 32) >> 6;
2827 		j = (h * ry) / rx;
2828 		k = (i * ry) / rx;
2829 
2830 		if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
2831 		    xph = x + h;
2832 		    xmh = x - h;
2833 		    if (k > 0) {
2834 			ypk = y + k;
2835 			ymk = y - k;
2836 			result |= fastPixelColorNolock(dst, xmh, ypk, color);
2837 			result |= fastPixelColorNolock(dst, xph, ypk, color);
2838 			result |= fastPixelColorNolock(dst, xmh, ymk, color);
2839 			result |= fastPixelColorNolock(dst, xph, ymk, color);
2840 		    } else {
2841 			result |= fastPixelColorNolock(dst, xmh, y, color);
2842 			result |= fastPixelColorNolock(dst, xph, y, color);
2843 		    }
2844 		    ok = k;
2845 		    xpi = x + i;
2846 		    xmi = x - i;
2847 		    if (j > 0) {
2848 			ypj = y + j;
2849 			ymj = y - j;
2850 			result |= fastPixelColorNolock(dst, xmi, ypj, color);
2851 			result |= fastPixelColorNolock(dst, xpi, ypj, color);
2852 			result |= fastPixelColorNolock(dst, xmi, ymj, color);
2853 			result |= fastPixelColorNolock(dst, xpi, ymj, color);
2854 		    } else {
2855 			result |= fastPixelColorNolock(dst, xmi, y, color);
2856 			result |= fastPixelColorNolock(dst, xpi, y, color);
2857 		    }
2858 		    oj = j;
2859 		}
2860 
2861 		ix = ix + iy / rx;
2862 		iy = iy - ix / rx;
2863 
2864 	    } while (i > h);
2865 	} else {
2866 	    ix = 0;
2867 	    iy = ry * 64;
2868 
2869 	    do {
2870 		h = (ix + 32) >> 6;
2871 		i = (iy + 32) >> 6;
2872 		j = (h * rx) / ry;
2873 		k = (i * rx) / ry;
2874 
2875 		if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
2876 		    xmj = x - j;
2877 		    xpj = x + j;
2878 		    if (i > 0) {
2879 			ypi = y + i;
2880 			ymi = y - i;
2881 			result |= fastPixelColorNolock(dst, xmj, ypi, color);
2882 			result |= fastPixelColorNolock(dst, xpj, ypi, color);
2883 			result |= fastPixelColorNolock(dst, xmj, ymi, color);
2884 			result |= fastPixelColorNolock(dst, xpj, ymi, color);
2885 		    } else {
2886 			result |= fastPixelColorNolock(dst, xmj, y, color);
2887 			result |= fastPixelColorNolock(dst, xpj, y, color);
2888 		    }
2889 		    oi = i;
2890 		    xmk = x - k;
2891 		    xpk = x + k;
2892 		    if (h > 0) {
2893 			yph = y + h;
2894 			ymh = y - h;
2895 			result |= fastPixelColorNolock(dst, xmk, yph, color);
2896 			result |= fastPixelColorNolock(dst, xpk, yph, color);
2897 			result |= fastPixelColorNolock(dst, xmk, ymh, color);
2898 			result |= fastPixelColorNolock(dst, xpk, ymh, color);
2899 		    } else {
2900 			result |= fastPixelColorNolock(dst, xmk, y, color);
2901 			result |= fastPixelColorNolock(dst, xpk, y, color);
2902 		    }
2903 		    oh = h;
2904 		}
2905 
2906 		ix = ix + iy / ry;
2907 		iy = iy - ix / ry;
2908 
2909 	    } while (i > h);
2910 	}
2911 
2912     } else {
2913 
2914 	if (rx > ry) {
2915 	    ix = 0;
2916 	    iy = rx * 64;
2917 
2918 	    do {
2919 		h = (ix + 32) >> 6;
2920 		i = (iy + 32) >> 6;
2921 		j = (h * ry) / rx;
2922 		k = (i * ry) / rx;
2923 
2924 		if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
2925 		    xph = x + h;
2926 		    xmh = x - h;
2927 		    if (k > 0) {
2928 			ypk = y + k;
2929 			ymk = y - k;
2930 			result |= pixelColorNolock (dst, xmh, ypk, color);
2931 			result |= pixelColorNolock (dst, xph, ypk, color);
2932 			result |= pixelColorNolock (dst, xmh, ymk, color);
2933 			result |= pixelColorNolock (dst, xph, ymk, color);
2934 		    } else {
2935 			result |= pixelColorNolock (dst, xmh, y, color);
2936 			result |= pixelColorNolock (dst, xph, y, color);
2937 		    }
2938 		    ok = k;
2939 		    xpi = x + i;
2940 		    xmi = x - i;
2941 		    if (j > 0) {
2942 			ypj = y + j;
2943 			ymj = y - j;
2944 			result |= pixelColorNolock (dst, xmi, ypj, color);
2945 			result |= pixelColorNolock (dst, xpi, ypj, color);
2946 			result |= pixelColorNolock (dst, xmi, ymj, color);
2947 			result |= pixelColor(dst, xpi, ymj, color);
2948 		    } else {
2949 			result |= pixelColorNolock (dst, xmi, y, color);
2950 			result |= pixelColorNolock (dst, xpi, y, color);
2951 		    }
2952 		    oj = j;
2953 		}
2954 
2955 		ix = ix + iy / rx;
2956 		iy = iy - ix / rx;
2957 
2958 	    } while (i > h);
2959 	} else {
2960 	    ix = 0;
2961 	    iy = ry * 64;
2962 
2963 	    do {
2964 		h = (ix + 32) >> 6;
2965 		i = (iy + 32) >> 6;
2966 		j = (h * rx) / ry;
2967 		k = (i * rx) / ry;
2968 
2969 		if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
2970 		    xmj = x - j;
2971 		    xpj = x + j;
2972 		    if (i > 0) {
2973 			ypi = y + i;
2974 			ymi = y - i;
2975 			result |= pixelColorNolock (dst, xmj, ypi, color);
2976 			result |= pixelColorNolock (dst, xpj, ypi, color);
2977 			result |= pixelColorNolock (dst, xmj, ymi, color);
2978 			result |= pixelColorNolock (dst, xpj, ymi, color);
2979 		    } else {
2980 			result |= pixelColorNolock (dst, xmj, y, color);
2981 			result |= pixelColorNolock (dst, xpj, y, color);
2982 		    }
2983 		    oi = i;
2984 		    xmk = x - k;
2985 		    xpk = x + k;
2986 		    if (h > 0) {
2987 			yph = y + h;
2988 			ymh = y - h;
2989 			result |= pixelColorNolock (dst, xmk, yph, color);
2990 			result |= pixelColorNolock (dst, xpk, yph, color);
2991 			result |= pixelColorNolock (dst, xmk, ymh, color);
2992 			result |= pixelColorNolock (dst, xpk, ymh, color);
2993 		    } else {
2994 			result |= pixelColorNolock (dst, xmk, y, color);
2995 			result |= pixelColorNolock (dst, xpk, y, color);
2996 		    }
2997 		    oh = h;
2998 		}
2999 
3000 		ix = ix + iy / ry;
3001 		iy = iy - ix / ry;
3002 
3003 	    } while (i > h);
3004 	}
3005 
3006     }				/* Alpha check */
3007 
3008     /* Unlock surface */
3009     if (SDL_MUSTLOCK(dst)) {
3010 	SDL_UnlockSurface(dst);
3011     }
3012 
3013     return (result);
3014 }
3015 
ellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3016 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3017 {
3018     /*
3019      * Draw
3020      */
3021     return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3022 }
3023 
3024 /* ----- AA Ellipse */
3025 
3026 /* Win32 does not have lrint, so provide a local inline version */
3027 #ifdef WIN32
3028 
3029 __inline long int
lrint(double ftl)3030 lrint (double ftl)
3031 {
3032   int intgr;
3033   _asm
3034   {
3035     fld flt
3036     fistp intgr
3037   };
3038   return intgr;
3039 }
3040 
3041 #endif
3042 
3043 /* Based on code from Anders Lindstroem, based on code from SGE, based on code from TwinLib */
3044 
aaellipseColor(SDL_Surface * dst,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint32 color)3045 int aaellipseColor(SDL_Surface * dst, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
3046 {
3047     Sint16 left, right, top, bottom;
3048     Sint16 x1,y1,x2,y2;
3049     int i;
3050     int a2, b2, ds, dt, dxt, t, s, d;
3051     Sint16 x, y, xs, ys, dyt, od, xx, yy, xc2, yc2;
3052     float cp;
3053     double sab;
3054     Uint8 weight, iweight;
3055     int result;
3056 
3057     /*
3058      * Check visibility of clipping rectangle
3059      */
3060     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3061      return(0);
3062     }
3063 
3064     /*
3065      * Sanity check radii
3066      */
3067     if ((rx < 0) || (ry < 0)) {
3068 	return (-1);
3069     }
3070 
3071     /*
3072      * Special case for rx=0 - draw a vline
3073      */
3074     if (rx == 0) {
3075 	return (vlineColor(dst, xc, yc - ry, yc + ry, color));
3076     }
3077     /*
3078      * Special case for ry=0 - draw a hline
3079      */
3080     if (ry == 0) {
3081 	return (hlineColor(dst, xc - rx, xc + rx, yc, color));
3082     }
3083 
3084     /*
3085      * Get circle and clipping boundary and
3086      * test if bounding box of circle is visible
3087      */
3088     x2 = xc + rx;
3089     left = dst->clip_rect.x;
3090     if (x2<left) {
3091      return(0);
3092     }
3093     x1 = xc - rx;
3094     right = dst->clip_rect.x + dst->clip_rect.w - 1;
3095     if (x1>right) {
3096      return(0);
3097     }
3098     y2 = yc + ry;
3099     top = dst->clip_rect.y;
3100     if (y2<top) {
3101      return(0);
3102     }
3103     y1 = yc - ry;
3104     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3105     if (y1>bottom) {
3106      return(0);
3107     }
3108 
3109     /* Variable setup */
3110     a2 = rx * rx;
3111     b2 = ry * ry;
3112 
3113     ds = 2 * a2;
3114     dt = 2 * b2;
3115 
3116     xc2 = 2 * xc;
3117     yc2 = 2 * yc;
3118 
3119     sab = sqrt(a2 + b2);
3120     od = lrint(sab*0.01) + 1; /* introduce some overdraw */
3121     dxt = lrint((double)a2 / sab) + od;
3122 
3123     t = 0;
3124     s = -2 * a2 * ry;
3125     d = 0;
3126 
3127     x = xc;
3128     y = yc - ry;
3129 
3130     /* Draw */
3131     result = 0;
3132 
3133     /* Lock surface */
3134     if (SDL_MUSTLOCK(dst)) {
3135 	if (SDL_LockSurface(dst) < 0) {
3136 	    return (-1);
3137 	}
3138     }
3139 
3140     /* "End points" */
3141     result |= pixelColorNolock(dst, x, y, color);
3142     result |= pixelColorNolock(dst, xc2 - x, y, color);
3143     result |= pixelColorNolock(dst, x, yc2 - y, color);
3144     result |= pixelColorNolock(dst, xc2 - x, yc2 - y, color);
3145 
3146     for (i = 1; i <= dxt; i++) {
3147 	x--;
3148 	d += t - b2;
3149 
3150 	if (d >= 0)
3151 	    ys = y - 1;
3152 	else if ((d - s - a2) > 0) {
3153 	    if ((2 * d - s - a2) >= 0)
3154 		ys = y + 1;
3155 	    else {
3156 		ys = y;
3157 		y++;
3158 		d -= s + a2;
3159 		s += ds;
3160 	    }
3161 	} else {
3162 	    y++;
3163 	    ys = y + 1;
3164 	    d -= s + a2;
3165 	    s += ds;
3166 	}
3167 
3168 	t -= dt;
3169 
3170 	/* Calculate alpha */
3171 	if (s != 0.0) {
3172 	    cp = (float) abs(d) / (float) abs(s);
3173 	    if (cp > 1.0) {
3174 		cp = 1.0;
3175 	    }
3176 	} else {
3177 	    cp = 1.0;
3178 	}
3179 
3180 	/* Calculate weights */
3181 	weight = (Uint8) (cp * 255);
3182 	iweight = 255 - weight;
3183 
3184 	/* Upper half */
3185 	xx = xc2 - x;
3186 	result |= pixelColorWeightNolock(dst, x, y, color, iweight);
3187 	result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
3188 
3189 	result |= pixelColorWeightNolock(dst, x, ys, color, weight);
3190 	result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
3191 
3192 	/* Lower half */
3193 	yy = yc2 - y;
3194 	result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
3195 	result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
3196 
3197 	yy = yc2 - ys;
3198 	result |= pixelColorWeightNolock(dst, x, yy, color, weight);
3199 	result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
3200     }
3201 
3202     /* Replaces original approximation code dyt = abs(y - yc); */
3203     dyt = lrint((double)b2 / sab ) + od;
3204 
3205     for (i = 1; i <= dyt; i++) {
3206 	y++;
3207 	d -= s + a2;
3208 
3209 	if (d <= 0)
3210 	    xs = x + 1;
3211 	else if ((d + t - b2) < 0) {
3212 	    if ((2 * d + t - b2) <= 0)
3213 		xs = x - 1;
3214 	    else {
3215 		xs = x;
3216 		x--;
3217 		d += t - b2;
3218 		t -= dt;
3219 	    }
3220 	} else {
3221 	    x--;
3222 	    xs = x - 1;
3223 	    d += t - b2;
3224 	    t -= dt;
3225 	}
3226 
3227 	s += ds;
3228 
3229 	/* Calculate alpha */
3230 	if (t != 0.0) {
3231 	    cp = (float) abs(d) / (float) abs(t);
3232 	    if (cp > 1.0) {
3233 		cp = 1.0;
3234 	    }
3235 	} else {
3236 	    cp = 1.0;
3237 	}
3238 
3239 	/* Calculate weight */
3240 	weight = (Uint8) (cp * 255);
3241 	iweight = 255 - weight;
3242 
3243 	/* Left half */
3244 	xx = xc2 - x;
3245 	yy = yc2 - y;
3246 	result |= pixelColorWeightNolock(dst, x, y, color, iweight);
3247 	result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
3248 
3249 	result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
3250 	result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
3251 
3252 	/* Right half */
3253 	xx = 2 * xc - xs;
3254 	result |= pixelColorWeightNolock(dst, xs, y, color, weight);
3255 	result |= pixelColorWeightNolock(dst, xx, y, color, weight);
3256 
3257 	result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
3258 	result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
3259 
3260     }
3261 
3262     /* Unlock surface */
3263     if (SDL_MUSTLOCK(dst)) {
3264 	SDL_UnlockSurface(dst);
3265     }
3266 
3267     return (result);
3268 }
3269 
aaellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3270 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3271 {
3272     /*
3273      * Draw
3274      */
3275     return (aaellipseColor
3276 	    (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3277 }
3278 
3279 /* ---- Filled Ellipse */
3280 
3281 /* Note: */
3282 /* Based on algorithm from sge library with multiple-hline draw removal */
3283 /* and other speedup changes. */
3284 
filledEllipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)3285 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
3286 {
3287     Sint16 left, right, top, bottom;
3288     int result;
3289     Sint16 x1, y1, x2, y2;
3290     int ix, iy;
3291     int h, i, j, k;
3292     int oh, oi, oj, ok;
3293     int xmh, xph;
3294     int xmi, xpi;
3295     int xmj, xpj;
3296     int xmk, xpk;
3297 
3298     /*
3299      * Check visibility of clipping rectangle
3300      */
3301     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3302      return(0);
3303     }
3304 
3305     /*
3306      * Sanity check radii
3307      */
3308     if ((rx < 0) || (ry < 0)) {
3309 	return (-1);
3310     }
3311 
3312     /*
3313      * Special case for rx=0 - draw a vline
3314      */
3315     if (rx == 0) {
3316 	return (vlineColor(dst, x, y - ry, y + ry, color));
3317     }
3318     /*
3319      * Special case for ry=0 - draw a hline
3320      */
3321     if (ry == 0) {
3322 	return (hlineColor(dst, x - rx, x + rx, y, color));
3323     }
3324 
3325     /*
3326      * Get circle and clipping boundary and
3327      * test if bounding box of circle is visible
3328      */
3329     x2 = x + rx;
3330     left = dst->clip_rect.x;
3331     if (x2<left) {
3332      return(0);
3333     }
3334     x1 = x - rx;
3335     right = dst->clip_rect.x + dst->clip_rect.w - 1;
3336     if (x1>right) {
3337      return(0);
3338     }
3339     y2 = y + ry;
3340     top = dst->clip_rect.y;
3341     if (y2<top) {
3342      return(0);
3343     }
3344     y1 = y - ry;
3345     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3346     if (y1>bottom) {
3347      return(0);
3348     }
3349 
3350     /*
3351      * Init vars
3352      */
3353     oh = oi = oj = ok = 0xFFFF;
3354 
3355     /*
3356      * Draw
3357      */
3358     result = 0;
3359     if (rx > ry) {
3360 	ix = 0;
3361 	iy = rx * 64;
3362 
3363 	do {
3364 	    h = (ix + 32) >> 6;
3365 	    i = (iy + 32) >> 6;
3366 	    j = (h * ry) / rx;
3367 	    k = (i * ry) / rx;
3368 
3369 	    if ((ok != k) && (oj != k)) {
3370 		xph = x + h;
3371 		xmh = x - h;
3372 		if (k > 0) {
3373 		    result |= hlineColor(dst, xmh, xph, y + k, color);
3374 		    result |= hlineColor(dst, xmh, xph, y - k, color);
3375 		} else {
3376 		    result |= hlineColor(dst, xmh, xph, y, color);
3377 		}
3378 		ok = k;
3379 	    }
3380 	    if ((oj != j) && (ok != j) && (k != j)) {
3381 		xmi = x - i;
3382 		xpi = x + i;
3383 		if (j > 0) {
3384 		    result |= hlineColor(dst, xmi, xpi, y + j, color);
3385 		    result |= hlineColor(dst, xmi, xpi, y - j, color);
3386 		} else {
3387 		    result |= hlineColor(dst, xmi, xpi, y, color);
3388 		}
3389 		oj = j;
3390 	    }
3391 
3392 	    ix = ix + iy / rx;
3393 	    iy = iy - ix / rx;
3394 
3395 	} while (i > h);
3396     } else {
3397 	ix = 0;
3398 	iy = ry * 64;
3399 
3400 	do {
3401 	    h = (ix + 32) >> 6;
3402 	    i = (iy + 32) >> 6;
3403 	    j = (h * rx) / ry;
3404 	    k = (i * rx) / ry;
3405 
3406 	    if ((oi != i) && (oh != i)) {
3407 		xmj = x - j;
3408 		xpj = x + j;
3409 		if (i > 0) {
3410 		    result |= hlineColor(dst, xmj, xpj, y + i, color);
3411 		    result |= hlineColor(dst, xmj, xpj, y - i, color);
3412 		} else {
3413 		    result |= hlineColor(dst, xmj, xpj, y, color);
3414 		}
3415 		oi = i;
3416 	    }
3417 	    if ((oh != h) && (oi != h) && (i != h)) {
3418 		xmk = x - k;
3419 		xpk = x + k;
3420 		if (h > 0) {
3421 		    result |= hlineColor(dst, xmk, xpk, y + h, color);
3422 		    result |= hlineColor(dst, xmk, xpk, y - h, color);
3423 		} else {
3424 		    result |= hlineColor(dst, xmk, xpk, y, color);
3425 		}
3426 		oh = h;
3427 	    }
3428 
3429 	    ix = ix + iy / ry;
3430 	    iy = iy - ix / ry;
3431 
3432 	} while (i > h);
3433     }
3434 
3435     return (result);
3436 }
3437 
3438 
filledEllipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3439 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3440 {
3441     /*
3442      * Draw
3443      */
3444     return (filledEllipseColor
3445 	    (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3446 }
3447 
3448 /* ----- filled pie */
3449 
3450 /* Low-speed float pie-calc implementation by drawing polygons/lines. */
3451 
doPieColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color,Uint8 filled)3452 int doPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
3453 {
3454     Sint16 left, right, top, bottom;
3455     Sint16 x1, y1, x2, y2;
3456     int result;
3457     double angle, start_angle, end_angle;
3458     double deltaAngle;
3459     double dr;
3460     int posX, posY;
3461     int numpoints, i;
3462     Sint16 *vx, *vy;
3463 
3464     /*
3465      * Check visibility of clipping rectangle
3466      */
3467     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3468      return(0);
3469     }
3470 
3471     /*
3472      * Sanity check radii
3473      */
3474     if (rad < 0) {
3475 	return (-1);
3476     }
3477 
3478     /*
3479      * Fixup angles
3480      */
3481     start = start % 360;
3482     end = end % 360;
3483 
3484     /*
3485      * Special case for rad=0 - draw a point
3486      */
3487     if (rad == 0) {
3488 	return (pixelColor(dst, x, y, color));
3489     }
3490 
3491     /*
3492      * Clip against circle, not pie (not 100% optimal).
3493      * Get pie's circle and clipping boundary and
3494      * test if bounding box of circle is visible
3495      */
3496     x2 = x + rad;
3497     left = dst->clip_rect.x;
3498     if (x2<left) {
3499      return(0);
3500     }
3501     x1 = x - rad;
3502     right = dst->clip_rect.x + dst->clip_rect.w - 1;
3503     if (x1>right) {
3504      return(0);
3505     }
3506     y2 = y + rad;
3507     top = dst->clip_rect.y;
3508     if (y2<top) {
3509      return(0);
3510     }
3511     y1 = y - rad;
3512     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3513     if (y1>bottom) {
3514      return(0);
3515     }
3516 
3517     /*
3518      * Variable setup
3519      */
3520     dr = (double) rad;
3521     deltaAngle = 3.0 / dr;
3522     start_angle = (double) start *(2.0 * M_PI / 360.0);
3523     end_angle = (double) end *(2.0 * M_PI / 360.0);
3524     if (start > end) {
3525 	end_angle += (2.0 * M_PI);
3526     }
3527 
3528     /* Count points (rather than calculate it) */
3529     numpoints = 1;
3530     angle = start_angle;
3531     while (angle <= end_angle) {
3532 	angle += deltaAngle;
3533 	numpoints++;
3534     }
3535 
3536     /* Check size of array */
3537     if (numpoints == 1) {
3538 	return (pixelColor(dst, x, y, color));
3539     } else if (numpoints == 2) {
3540 	posX = x + (int) (dr * cos(start_angle));
3541 	posY = y + (int) (dr * sin(start_angle));
3542 	return (lineColor(dst, x, y, posX, posY, color));
3543     }
3544 
3545     /* Allocate vertex array */
3546     vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
3547     if (vx == NULL) {
3548 	return (-1);
3549     }
3550     vy += numpoints;
3551 
3552     /* Center */
3553     vx[0] = x;
3554     vy[0] = y;
3555 
3556     /* Calculate and store vertices */
3557     i = 1;
3558     angle = start_angle;
3559     while (angle <= end_angle) {
3560 	vx[i] = x + (int) (dr * cos(angle));
3561 	vy[i] = y + (int) (dr * sin(angle));
3562 	angle += deltaAngle;
3563 	i++;
3564     }
3565 
3566     /* Draw */
3567     if (filled) {
3568      result = filledPolygonColor(dst, vx, vy, numpoints, color);
3569     } else {
3570      result = polygonColor(dst, vx, vy, numpoints, color);
3571     }
3572 
3573     /* Free vertex array */
3574     free(vx);
3575 
3576     return (result);
3577 }
3578 
pieColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)3579 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
3580 		Sint16 start, Sint16 end, Uint32 color)
3581 {
3582     return (doPieColor(dst, x, y, rad, start, end, color, 0));
3583 
3584 }
3585 
pieRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3586 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
3587 	    Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3588 {
3589     return (doPieColor(dst, x, y, rad, start, end,
3590 			   ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
3591 
3592 }
3593 
filledPieColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)3594 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
3595 {
3596     return (doPieColor(dst, x, y, rad, start, end, color, 1));
3597 }
3598 
filledPieRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3599 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
3600 		  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3601 {
3602     return (doPieColor(dst, x, y, rad, start, end,
3603 			   ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
3604 }
3605 
3606 /* Trigon */
3607 
trigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)3608 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
3609 {
3610  Sint16 vx[3];
3611  Sint16 vy[3];
3612 
3613  vx[0]=x1;
3614  vx[1]=x2;
3615  vx[2]=x3;
3616  vy[0]=y1;
3617  vy[1]=y2;
3618  vy[2]=y3;
3619 
3620  return(polygonColor(dst,vx,vy,3,color));
3621 }
3622 
trigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3623 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3624 				 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3625 {
3626  Sint16 vx[3];
3627  Sint16 vy[3];
3628 
3629  vx[0]=x1;
3630  vx[1]=x2;
3631  vx[2]=x3;
3632  vy[0]=y1;
3633  vy[1]=y2;
3634  vy[2]=y3;
3635 
3636  return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
3637 }
3638 
3639 /* AA-Trigon */
3640 
aatrigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)3641 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
3642 {
3643  Sint16 vx[3];
3644  Sint16 vy[3];
3645 
3646  vx[0]=x1;
3647  vx[1]=x2;
3648  vx[2]=x3;
3649  vy[0]=y1;
3650  vy[1]=y2;
3651  vy[2]=y3;
3652 
3653  return(aapolygonColor(dst,vx,vy,3,color));
3654 }
3655 
aatrigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3656 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3657 				   Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3658 {
3659  Sint16 vx[3];
3660  Sint16 vy[3];
3661 
3662  vx[0]=x1;
3663  vx[1]=x2;
3664  vx[2]=x3;
3665  vy[0]=y1;
3666  vy[1]=y2;
3667  vy[2]=y3;
3668 
3669  return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
3670 }
3671 
3672 /* Filled Trigon */
3673 
filledTrigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)3674 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
3675 {
3676  Sint16 vx[3];
3677  Sint16 vy[3];
3678 
3679  vx[0]=x1;
3680  vx[1]=x2;
3681  vx[2]=x3;
3682  vy[0]=y1;
3683  vy[1]=y2;
3684  vy[2]=y3;
3685 
3686  return(filledPolygonColor(dst,vx,vy,3,color));
3687 }
3688 
filledTrigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3689 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3690 				       Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3691 {
3692  Sint16 vx[3];
3693  Sint16 vy[3];
3694 
3695  vx[0]=x1;
3696  vx[1]=x2;
3697  vx[2]=x3;
3698  vy[0]=y1;
3699  vy[1]=y2;
3700  vy[2]=y3;
3701 
3702  return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
3703 }
3704 
3705 /* ---- Polygon */
3706 
polygonColor(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)3707 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
3708 {
3709     int result;
3710     int i;
3711     const Sint16 *x1, *y1, *x2, *y2;
3712 
3713     /*
3714      * Check visibility of clipping rectangle
3715      */
3716     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3717      return(0);
3718     }
3719 
3720     /*
3721      * Sanity check
3722      */
3723     if (n < 3) {
3724 	return (-1);
3725     }
3726 
3727     /*
3728      * Pointer setup
3729      */
3730     x1 = x2 = vx;
3731     y1 = y2 = vy;
3732     x2++;
3733     y2++;
3734 
3735     /*
3736      * Draw
3737      */
3738     result = 0;
3739     for (i = 1; i < n; i++) {
3740 	result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
3741 	x1 = x2;
3742 	y1 = y2;
3743 	x2++;
3744 	y2++;
3745     }
3746     result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
3747 
3748     return (result);
3749 }
3750 
polygonRGBA(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3751 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3752 {
3753     /*
3754      * Draw
3755      */
3756     return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3757 }
3758 
3759 /* ---- AA-Polygon */
3760 
aapolygonColor(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)3761 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
3762 {
3763     int result;
3764     int i;
3765     const Sint16 *x1, *y1, *x2, *y2;
3766 
3767     /*
3768      * Check visibility of clipping rectangle
3769      */
3770     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3771      return(0);
3772     }
3773 
3774     /*
3775      * Sanity check
3776      */
3777     if (n < 3) {
3778 	return (-1);
3779     }
3780 
3781     /*
3782      * Pointer setup
3783      */
3784     x1 = x2 = vx;
3785     y1 = y2 = vy;
3786     x2++;
3787     y2++;
3788 
3789     /*
3790      * Draw
3791      */
3792     result = 0;
3793     for (i = 1; i < n; i++) {
3794 	result |= aalineColorInt(dst, *x1, *y1, *x2, *y2, color, 0);
3795 	x1 = x2;
3796 	y1 = y2;
3797 	x2++;
3798 	y2++;
3799     }
3800     result |= aalineColorInt(dst, *x1, *y1, *vx, *vy, color, 0);
3801 
3802     return (result);
3803 }
3804 
aapolygonRGBA(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3805 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3806 {
3807     /*
3808      * Draw
3809      */
3810     return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3811 }
3812 
3813 /* ---- Filled Polygon */
3814 
3815 int gfxPrimitivesCompareInt(const void *a, const void *b);
3816 
3817 /* Global vertex array to use if optional parameters are not given in polygon calls. */
3818 static int *gfxPrimitivesPolyIntsGlobal = NULL;
3819 static int gfxPrimitivesPolyAllocatedGlobal = 0;
3820 
3821 /* (Note: The last two parameters are optional; but required for multithreaded operation.) */
3822 
filledPolygonColorMT(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color,int ** polyInts,int * polyAllocated)3823 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
3824 {
3825     int result;
3826     int i;
3827     int y, xa, xb;
3828     int miny, maxy;
3829     int x1, y1;
3830     int x2, y2;
3831     int ind1, ind2;
3832     int ints;
3833     int *gfxPrimitivesPolyInts = NULL;
3834     int gfxPrimitivesPolyAllocated = 0;
3835 
3836     /*
3837      * Check visibility of clipping rectangle
3838      */
3839     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
3840      return(0);
3841     }
3842 
3843     /*
3844      * Sanity check number of edges
3845      */
3846     if (n < 3) {
3847 	return -1;
3848     }
3849 
3850     /*
3851      * Map polygon cache
3852      */
3853     if ((polyInts==NULL) || (polyAllocated==NULL)) {
3854        /* Use global cache */
3855        gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
3856        gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
3857     } else {
3858        /* Use local cache */
3859        gfxPrimitivesPolyInts = *polyInts;
3860        gfxPrimitivesPolyAllocated = *polyAllocated;
3861     }
3862 
3863     /*
3864      * Allocate temp array, only grow array
3865      */
3866     if (!gfxPrimitivesPolyAllocated) {
3867 	gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3868 	gfxPrimitivesPolyAllocated = n;
3869     } else {
3870 	if (gfxPrimitivesPolyAllocated < n) {
3871 	    gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3872 	    gfxPrimitivesPolyAllocated = n;
3873 	}
3874     }
3875 
3876     /*
3877      * Check temp array
3878      */
3879     if (gfxPrimitivesPolyInts==NULL) {
3880       gfxPrimitivesPolyAllocated = 0;
3881     }
3882 
3883     /*
3884      * Update cache variables
3885      */
3886     if ((polyInts==NULL) || (polyAllocated==NULL)) {
3887      gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
3888      gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
3889     } else {
3890      *polyInts = gfxPrimitivesPolyInts;
3891      *polyAllocated = gfxPrimitivesPolyAllocated;
3892     }
3893 
3894     /*
3895      * Check temp array again
3896      */
3897     if (gfxPrimitivesPolyInts==NULL) {
3898 	return(-1);
3899     }
3900 
3901     /*
3902      * Determine Y maxima
3903      */
3904     miny = vy[0];
3905     maxy = vy[0];
3906     for (i = 1; (i < n); i++) {
3907 	if (vy[i] < miny) {
3908 	    miny = vy[i];
3909 	} else if (vy[i] > maxy) {
3910 	    maxy = vy[i];
3911 	}
3912     }
3913 
3914     /*
3915      * Draw, scanning y
3916      */
3917     result = 0;
3918     for (y = miny; (y <= maxy); y++) {
3919 	ints = 0;
3920 	for (i = 0; (i < n); i++) {
3921 	    if (!i) {
3922 		ind1 = n - 1;
3923 		ind2 = 0;
3924 	    } else {
3925 		ind1 = i - 1;
3926 		ind2 = i;
3927 	    }
3928 	    y1 = vy[ind1];
3929 	    y2 = vy[ind2];
3930 	    if (y1 < y2) {
3931 		x1 = vx[ind1];
3932 		x2 = vx[ind2];
3933 	    } else if (y1 > y2) {
3934 		y2 = vy[ind1];
3935 		y1 = vy[ind2];
3936 		x2 = vx[ind1];
3937 		x1 = vx[ind2];
3938 	    } else {
3939 		continue;
3940 	    }
3941 	    if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
3942 		gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
3943 	    }
3944 	}
3945 
3946 	qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
3947 
3948 	for (i = 0; (i < ints); i += 2) {
3949 	    xa = gfxPrimitivesPolyInts[i] + 1;
3950 	    xa = (xa >> 16) + ((xa & 32768) >> 15);
3951 	    xb = gfxPrimitivesPolyInts[i+1] - 1;
3952 	    xb = (xb >> 16) + ((xb & 32768) >> 15);
3953 	    result |= hlineColor(dst, xa, xb, y, color);
3954 	}
3955     }
3956 
3957     return (result);
3958 }
3959 
filledPolygonRGBAMT(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a,int ** polyInts,int * polyAllocated)3960 int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
3961 {
3962     /*
3963      * Draw
3964      */
3965     return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
3966 }
3967 
3968 /* Standard versions are calling multithreaded versions with NULL cache parameters */
3969 
filledPolygonColor(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint32 color)3970 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
3971 {
3972     /*
3973      * Draw
3974      */
3975     return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
3976 }
3977 
filledPolygonRGBA(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3978 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3979 {
3980     /*
3981      * Draw
3982      */
3983     return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
3984 }
3985 
_texturedHLine(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,SDL_Surface * texture,int texture_dx,int texture_dy)3986 int _texturedHLine(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y,SDL_Surface *texture,int texture_dx,int texture_dy)
3987 {
3988     Sint16 left, right, top, bottom;
3989     Sint16 w;
3990     Sint16 xtmp;
3991     int result = 0;
3992     int texture_x_walker;
3993     int texture_y_start;
3994     SDL_Rect source_rect,dst_rect;
3995     int pixels_written,write_width;
3996 
3997     /*
3998      * Check visibility of clipping rectangle
3999      */
4000     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4001      return(0);
4002     }
4003 
4004     /*
4005      * Swap x1, x2 if required to ensure x1<=x2
4006      */
4007     if (x1 > x2) {
4008 	xtmp = x1;
4009 	x1 = x2;
4010 	x2 = xtmp;
4011     }
4012 
4013     /*
4014      * Get clipping boundary and
4015      * check visibility of hline
4016      */
4017     left = dst->clip_rect.x;
4018     if (x2<left) {
4019      return(0);
4020     }
4021     right = dst->clip_rect.x + dst->clip_rect.w - 1;
4022     if (x1>right) {
4023      return(0);
4024     }
4025     top = dst->clip_rect.y;
4026     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4027     if ((y<top) || (y>bottom)) {
4028      return (0);
4029     }
4030 
4031 
4032     /*
4033      * Clip x
4034      */
4035     if (x1 < left) {
4036 	x1 = left;
4037     }
4038     if (x2 > right) {
4039 	x2 = right;
4040     }
4041 
4042     /*
4043      * Calculate width
4044      */
4045     w = x2 - x1;
4046 
4047     /*
4048      * Determint where in the texture we start drawing
4049      **/
4050     texture_x_walker =   (x1 - texture_dx)  % texture->w;
4051     if (texture_x_walker < 0){
4052       texture_x_walker = texture->w +texture_x_walker ;
4053     }
4054 
4055     texture_y_start = (y + texture_dy) % texture->h;
4056     if (texture_y_start < 0){
4057        texture_y_start = texture->h + texture_y_start;
4058     }
4059 
4060     //setup the source rectangle  we are only drawing one horizontal line
4061     source_rect.y = texture_y_start;
4062     source_rect.x =texture_x_walker;
4063     source_rect.h =1;
4064     //we will draw to the current y
4065     dst_rect.y = y;
4066 
4067     //if there are enough pixels left in the current row of the texture
4068     //draw it all at once
4069     if (w <= texture->w -texture_x_walker){
4070       source_rect.w = w;
4071       source_rect.x = texture_x_walker;
4072       dst_rect.x= x1;
4073       result != SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) ;
4074     } else {//we need to draw multiple times
4075       //draw the first segment
4076       pixels_written = texture->w  -texture_x_walker;
4077       source_rect.w = pixels_written;
4078       source_rect.x = texture_x_walker;
4079       dst_rect.x= x1;
4080       result != SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect);
4081       write_width = texture->w;
4082 
4083       //now draw the rest
4084       //set the source x to 0
4085       source_rect.x = 0;
4086       while(pixels_written < w){
4087         if (write_width >= w - pixels_written){
4088           write_width=  w- pixels_written;
4089         }
4090         source_rect.w = write_width;
4091         dst_rect.x = x1 + pixels_written;
4092         result  != SDL_BlitSurface  (texture,&source_rect , dst, &dst_rect) ;
4093         pixels_written += write_width;
4094       }
4095   }
4096   return result;
4097 }
4098 
4099 /**
4100  * Draws a polygon filled with the given texture. this operation use SDL_BlitSurface. It supports
4101  * alpha drawing.
4102  * to get the best performance of this operation you need to make sure the texture and the dst surface have the same format
4103  * see  http://docs.mandragor.org/files/Common_libs_documentation/SDL/SDL_Documentation_project_en/sdlblitsurface.html
4104  *
4105  * dest the destination surface,
4106  * vx array of x vector components
4107  * vy array of x vector components
4108  * n the amount of vectors in the vx and vy array
4109  * texture the sdl surface to use to fill the polygon
4110  * texture_dx the offset of the texture relative to the screeen. if you move the polygon 10 pixels
4111  * to the left and want the texture to apear the same you need to increase the texture_dx value
4112  * texture_dy see texture_dx
4113  *
4114  * (Note: The last two parameters are optional, but required for multithreaded operation.)
4115  **/
texturedPolygonMT(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,SDL_Surface * texture,int texture_dx,int texture_dy,int ** polyInts,int * polyAllocated)4116 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface * texture,int texture_dx,int texture_dy, int **polyInts, int *polyAllocated)
4117 {
4118     int result;
4119     int i;
4120     int y, xa, xb;
4121     int minx,maxx,miny, maxy;
4122     int x1, y1;
4123     int x2, y2;
4124     int ind1, ind2;
4125     int ints;
4126     int *gfxPrimitivesPolyInts = NULL;
4127     int gfxPrimitivesPolyAllocated = 0;
4128 
4129     /*
4130      * Check visibility of clipping rectangle
4131      */
4132     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4133      return(0);
4134     }
4135 
4136     /*
4137      * Sanity check number of edges
4138      */
4139     if (n < 3) {
4140 	return -1;
4141     }
4142 
4143     /*
4144      * Map polygon cache
4145      */
4146     if ((polyInts==NULL) || (polyAllocated==NULL)) {
4147        /* Use global cache */
4148        gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
4149        gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
4150     } else {
4151        /* Use local cache */
4152        gfxPrimitivesPolyInts = *polyInts;
4153        gfxPrimitivesPolyAllocated = *polyAllocated;
4154     }
4155 
4156     /*
4157      * Allocate temp array, only grow array
4158      */
4159     if (!gfxPrimitivesPolyAllocated) {
4160 	gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
4161 	gfxPrimitivesPolyAllocated = n;
4162     } else {
4163 	if (gfxPrimitivesPolyAllocated < n) {
4164 	    gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
4165 	    gfxPrimitivesPolyAllocated = n;
4166 	}
4167     }
4168 
4169     /*
4170      * Check temp array
4171      */
4172     if (gfxPrimitivesPolyInts==NULL) {
4173       gfxPrimitivesPolyAllocated = 0;
4174     }
4175 
4176     /*
4177      * Update cache variables
4178      */
4179     if ((polyInts==NULL) || (polyAllocated==NULL)) {
4180      gfxPrimitivesPolyIntsGlobal =  gfxPrimitivesPolyInts;
4181      gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
4182     } else {
4183      *polyInts = gfxPrimitivesPolyInts;
4184      *polyAllocated = gfxPrimitivesPolyAllocated;
4185     }
4186 
4187     /*
4188      * Check temp array again
4189      */
4190     if (gfxPrimitivesPolyInts==NULL) {
4191 	return(-1);
4192     }
4193 
4194     /*
4195      * Determine X,Y minima,maxima
4196      */
4197     miny = vy[0];
4198     maxy = vy[0];
4199     minx = vx[0];
4200     maxx = vx[0];
4201     for (i = 1; (i < n); i++) {
4202         if (vy[i] < miny) {
4203             miny = vy[i];
4204         } else if (vy[i] > maxy) {
4205             maxy = vy[i];
4206         }
4207         if (vx[i] < minx) {
4208             minx = vx[i];
4209         } else if (vx[i] > maxx) {
4210             maxx = vx[i];
4211         }
4212     }
4213     if (maxx <0 || minx > dst->w){
4214       return -1;
4215     }
4216     if (maxy <0 || miny > dst->h){
4217       return -1;
4218     }
4219 
4220     /*
4221      * Draw, scanning y
4222      */
4223     result = 0;
4224     for (y = miny; (y <= maxy); y++) {
4225 	ints = 0;
4226 	for (i = 0; (i < n); i++) {
4227 	    if (!i) {
4228 		ind1 = n - 1;
4229 		ind2 = 0;
4230 	    } else {
4231 		ind1 = i - 1;
4232 		ind2 = i;
4233 	    }
4234 	    y1 = vy[ind1];
4235 	    y2 = vy[ind2];
4236 	    if (y1 < y2) {
4237 		x1 = vx[ind1];
4238 		x2 = vx[ind2];
4239 	    } else if (y1 > y2) {
4240 		y2 = vy[ind1];
4241 		y1 = vy[ind2];
4242 		x2 = vx[ind1];
4243 		x1 = vx[ind2];
4244 	    } else {
4245 		continue;
4246 	    }
4247 	    if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
4248 		gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
4249 	    }
4250 
4251 	}
4252 
4253 	qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
4254 
4255 	for (i = 0; (i < ints); i += 2) {
4256 	    xa = gfxPrimitivesPolyInts[i] + 1;
4257 	    xa = (xa >> 16) + ((xa & 32768) >> 15);
4258 	    xb = gfxPrimitivesPolyInts[i+1] - 1;
4259 	    xb = (xb >> 16) + ((xb & 32768) >> 15);
4260 	    result |= _texturedHLine(dst, xa, xb, y, texture,texture_dx,texture_dy);
4261 	}
4262     }
4263 
4264     return (result);
4265 }
4266 
4267 /* Standard version is calling multithreaded versions with NULL cache parameters. */
4268 
texturedPolygon(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,SDL_Surface * texture,int texture_dx,int texture_dy)4269 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
4270 {
4271  /*
4272   * Draw
4273   */
4274    return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
4275 }
4276 
4277 /* Helper qsort callback for polygon drawing */
4278 
gfxPrimitivesCompareInt(const void * a,const void * b)4279 int gfxPrimitivesCompareInt(const void *a, const void *b)
4280 {
4281     return (*(const int *) a) - (*(const int *) b);
4282 }
4283 
4284 
4285 
4286 /* ---- Character */
4287 
4288 static SDL_Surface *gfxPrimitivesFont[256];
4289 static Uint32 gfxPrimitivesFontColor[256];
4290 
4291 /* Default is to use 8x8 internal font */
4292 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
4293 
4294 static int charWidth = 8, charHeight = 8;
4295 static int charPitch = 1;
4296 static int charSize = 8;	/* character data size in bytes */
4297 
gfxPrimitivesSetFont(const void * fontdata,int cw,int ch)4298 void gfxPrimitivesSetFont(const void *fontdata, int cw, int ch)
4299 {
4300     int i;
4301 
4302     if (fontdata) {
4303         currentFontdata = fontdata;
4304         charWidth = cw;
4305         charHeight = ch;
4306     } else {
4307         currentFontdata = gfxPrimitivesFontdata;
4308         charWidth = 8;
4309         charHeight = 8;
4310     }
4311 
4312     charPitch = (charWidth+7)/8;
4313     charSize = charPitch * charHeight;
4314 
4315     for (i = 0; i < 256; i++) {
4316 	if (gfxPrimitivesFont[i]) {
4317 	    SDL_FreeSurface(gfxPrimitivesFont[i]);
4318 	    gfxPrimitivesFont[i] = NULL;
4319 	}
4320     }
4321 }
4322 
characterColor(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint32 color)4323 int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color)
4324 {
4325     Sint16 left, right, top, bottom;
4326     Sint16 x1, y1, x2, y2;
4327     SDL_Rect srect;
4328     SDL_Rect drect;
4329     int result;
4330     int ix, iy;
4331     const unsigned char *charpos;
4332     Uint8 *curpos;
4333     int forced_redraw;
4334     Uint8 patt, mask;
4335     Uint8 *linepos;
4336     int pitch;
4337 
4338     /*
4339      * Check visibility of clipping rectangle
4340      */
4341     if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
4342      return(0);
4343     }
4344 
4345     /*
4346      * Get text and clipping boundary and
4347      * test if bounding box of character is visible
4348      */
4349 
4350     left = dst->clip_rect.x;
4351     x2 = x + charWidth;
4352     if (x2<left) {
4353      return(0);
4354     }
4355     right = dst->clip_rect.x + dst->clip_rect.w - 1;
4356     x1 = x;
4357     if (x1>right) {
4358      return(0);
4359     }
4360     top = dst->clip_rect.y;
4361     y2 = y + charHeight;
4362     if (y2<top) {
4363      return(0);
4364     }
4365     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4366     y1 = y;
4367     if (y1>bottom) {
4368      return(0);
4369     }
4370 
4371     /*
4372      * Setup source rectangle
4373      */
4374     srect.x = 0;
4375     srect.y = 0;
4376     srect.w = charWidth;
4377     srect.h = charHeight;
4378 
4379     /*
4380      * Setup destination rectangle
4381      */
4382     drect.x = x;
4383     drect.y = y;
4384     drect.w = charWidth;
4385     drect.h = charHeight;
4386 
4387     /*
4388      * Create new charWidth x charHeight bitmap surface if not already present
4389      */
4390     if (gfxPrimitivesFont[(unsigned char) c] == NULL) {
4391 	gfxPrimitivesFont[(unsigned char) c] =
4392 	    SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA,
4393                                  charWidth, charHeight, 32,
4394 				 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
4395 	/*
4396 	 * Check pointer
4397 	 */
4398 	if (gfxPrimitivesFont[(unsigned char) c] == NULL) {
4399 	    return (-1);
4400 	}
4401 	/*
4402 	 * Definitely redraw
4403 	 */
4404 	forced_redraw = 1;
4405     } else {
4406 	forced_redraw = 0;
4407     }
4408 
4409     /*
4410      * Check if color has changed
4411      */
4412     if ((gfxPrimitivesFontColor[(unsigned char) c] != color) || (forced_redraw)) {
4413 	/*
4414 	 * Redraw character
4415 	 */
4416 	SDL_SetAlpha(gfxPrimitivesFont[(unsigned char) c], SDL_SRCALPHA, 255);
4417 	gfxPrimitivesFontColor[(unsigned char) c] = color;
4418 
4419 	/* Lock font-surface */
4420 	if (SDL_LockSurface(gfxPrimitivesFont[(unsigned char) c]) != 0)
4421 	    return (-1);
4422 
4423 	/*
4424 	 * Variable setup
4425 	 */
4426 	charpos = currentFontdata + (unsigned char) c * charSize;
4427 	linepos = (Uint8 *) gfxPrimitivesFont[(unsigned char) c]->pixels;
4428 	pitch = gfxPrimitivesFont[(unsigned char) c]->pitch;
4429 
4430 	/*
4431 	 * Drawing loop
4432 	 */
4433         patt = 0;
4434 	for (iy = 0; iy < charHeight; iy++) {
4435             mask = 0x00;
4436 	    curpos = linepos;
4437 	    for (ix = 0; ix < charWidth; ix++) {
4438 		if (!(mask >>= 1)) {
4439 		    patt = *charpos++;
4440 		    mask = 0x80;
4441 		}
4442 
4443 		if (patt & mask)
4444 		    *(Uint32 *)curpos = color;
4445 		else
4446 		    *(Uint32 *)curpos = 0;
4447 		curpos += 4;;
4448 	    }
4449 	    linepos += pitch;
4450 	}
4451 
4452 	/* Unlock font-surface */
4453 	SDL_UnlockSurface(gfxPrimitivesFont[(unsigned char) c]);
4454     }
4455 
4456     /*
4457      * Draw bitmap onto destination surface
4458      */
4459     result = SDL_BlitSurface(gfxPrimitivesFont[(unsigned char) c], &srect, dst, &drect);
4460 
4461     return (result);
4462 }
4463 
characterRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4464 int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4465 {
4466     /*
4467      * Draw
4468      */
4469     return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4470 }
4471 
stringColor(SDL_Surface * dst,Sint16 x,Sint16 y,const char * c,Uint32 color)4472 int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, const char *c, Uint32 color)
4473 {
4474     int result = 0;
4475     int curx = x;
4476     const char *curchar = c;
4477 
4478     while (*curchar) {
4479 	result |= characterColor(dst, curx, y, *curchar, color);
4480 	curx += charWidth;
4481 	curchar++;
4482     }
4483 
4484     return (result);
4485 }
4486 
stringRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,const char * c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4487 int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, const char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4488 {
4489     /*
4490      * Draw
4491      */
4492     return (stringColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4493 }
4494 
4495 /* ---- Bezier curve */
4496 
4497 /*
4498  Calculate bezier interpolator of data array with ndata values at position 't'
4499 */
4500 
evaluateBezier(double * data,int ndata,double t)4501 double evaluateBezier (double *data, int ndata, double t)
4502 {
4503  double mu, result;
4504  int n,k,kn,nn,nkn;
4505  double blend,muk,munk;
4506 
4507  /* Sanity check bounds */
4508  if (t<0.0) {
4509   return(data[0]);
4510  }
4511  if (t>=(double)ndata) {
4512   return(data[ndata-1]);
4513  }
4514 
4515  /* Adjust t to the range 0.0 to 1.0 */
4516  mu=t/(double)ndata;
4517 
4518  /* Calculate interpolate */
4519  n=ndata-1;
4520  result=0.0;
4521  muk = 1;
4522  munk = pow(1-mu,(double)n);
4523  for (k=0;k<=n;k++) {
4524   nn = n;
4525   kn = k;
4526   nkn = n - k;
4527   blend = muk * munk;
4528   muk *= mu;
4529   munk /= (1-mu);
4530   while (nn >= 1) {
4531    blend *= nn;
4532    nn--;
4533    if (kn > 1) {
4534     blend /= (double)kn;
4535     kn--;
4536    }
4537    if (nkn > 1) {
4538     blend /= (double)nkn;
4539     nkn--;
4540    }
4541   }
4542   result += data[k] * blend;
4543  }
4544 
4545  return(result);
4546 }
4547 
bezierColor(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,int s,Uint32 color)4548 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
4549 {
4550     int result;
4551     int i;
4552     double *x, *y, t, stepsize;
4553     Sint16 x1, y1, x2, y2;
4554 
4555     /*
4556      * Sanity check
4557      */
4558     if (n < 3) {
4559 	return (-1);
4560     }
4561     if (s < 2) {
4562         return (-1);
4563     }
4564 
4565     /*
4566      * Variable setup
4567      */
4568     stepsize=(double)1.0/(double)s;
4569 
4570     /* Transfer vertices into float arrays */
4571     if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
4572      return(-1);
4573     }
4574     if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
4575      free(x);
4576      return(-1);
4577     }
4578     for (i=0; i<n; i++) {
4579      x[i]=vx[i];
4580      y[i]=vy[i];
4581     }
4582     x[n]=vx[0];
4583     y[n]=vy[0];
4584 
4585     /*
4586      * Draw
4587      */
4588     result = 0;
4589     t=0.0;
4590     x1=evaluateBezier(x,n+1,t);
4591     y1=evaluateBezier(y,n+1,t);
4592     for (i = 0; i <= (n*s); i++) {
4593 	t += stepsize;
4594 	x2=(Sint16)evaluateBezier(x,n,t);
4595 	y2=(Sint16)evaluateBezier(y,n,t);
4596 	result |= lineColor(dst, x1, y1, x2, y2, color);
4597 	x1 = x2;
4598 	y1 = y2;
4599     }
4600 
4601     /* Clean up temporary array */
4602     free(x);
4603     free(y);
4604 
4605     return (result);
4606 }
4607 
bezierRGBA(SDL_Surface * dst,const Sint16 * vx,const Sint16 * vy,int n,int s,Uint8 r,Uint8 g,Uint8 b,Uint8 a)4608 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4609 {
4610     /*
4611      * Draw
4612      */
4613     return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4614 }
4615