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 /* ----- Defines for pixel clipping tests */
20 
21 #define clip_xmin(surface) surface->clip_rect.x
22 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
23 #define clip_ymin(surface) surface->clip_rect.y
24 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
25 
26 /* ----- Pixel - fast, no blending, no locking, clipping */
27 
fastPixelColorNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)28 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
29 {
30     int bpp;
31     Uint8 *p;
32 
33     /*
34      * Honor clipping setup at pixel level
35      */
36     if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
37 
38 	/*
39 	 * Get destination format
40 	 */
41 	bpp = dst->format->BytesPerPixel;
42 	p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
43 	switch (bpp) {
44 	case 1:
45 	    *p = color;
46 	    break;
47 	case 2:
48 	    *(Uint16 *) p = color;
49 	    break;
50 	case 3:
51 	    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
52 		p[0] = (color >> 16) & 0xff;
53 		p[1] = (color >> 8) & 0xff;
54 		p[2] = color & 0xff;
55 	    } else {
56 		p[0] = color & 0xff;
57 		p[1] = (color >> 8) & 0xff;
58 		p[2] = (color >> 16) & 0xff;
59 	    }
60 	    break;
61 	case 4:
62 	    *(Uint32 *) p = color;
63 	    break;
64 	}			/* switch */
65 
66 
67     }
68 
69     return (0);
70 }
71 
72 /* ----- Pixel - fast, no blending, no locking, no clipping */
73 
74 /* (faster but dangerous, make sure we stay in surface bounds) */
75 
fastPixelColorNolockNoclip(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)76 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
77 {
78     int bpp;
79     Uint8 *p;
80 
81     /*
82      * Get destination format
83      */
84     bpp = dst->format->BytesPerPixel;
85     p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
86     switch (bpp) {
87     case 1:
88 	*p = color;
89 	break;
90     case 2:
91 	*(Uint16 *) p = color;
92 	break;
93     case 3:
94 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
95 	    p[0] = (color >> 16) & 0xff;
96 	    p[1] = (color >> 8) & 0xff;
97 	    p[2] = color & 0xff;
98 	} else {
99 	    p[0] = color & 0xff;
100 	    p[1] = (color >> 8) & 0xff;
101 	    p[2] = (color >> 16) & 0xff;
102 	}
103 	break;
104     case 4:
105 	*(Uint32 *) p = color;
106 	break;
107     }				/* switch */
108 
109     return (0);
110 }
111 
112 /* ----- Pixel - fast, no blending, locking, clipping */
113 
fastPixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)114 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
115 {
116     int result;
117 
118     /*
119      * Lock the surface
120      */
121     if (SDL_MUSTLOCK(dst)) {
122 	if (SDL_LockSurface(dst) < 0) {
123 	    return (-1);
124 	}
125     }
126 
127     result = fastPixelColorNolock(dst, x, y, color);
128 
129     /*
130      * Unlock surface
131      */
132     if (SDL_MUSTLOCK(dst)) {
133 	SDL_UnlockSurface(dst);
134     }
135 
136     return (result);
137 }
138 
139 /* ----- Pixel - fast, no blending, locking, RGB input */
140 
fastPixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)141 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
142 {
143     Uint32 color;
144 
145     /*
146      * Setup color
147      */
148     color = SDL_MapRGBA(dst->format, r, g, b, a);
149 
150     /*
151      * Draw
152      */
153     return (fastPixelColor(dst, x, y, color));
154 
155 }
156 
157 /* ----- Pixel - fast, no blending, no locking RGB input */
158 
fastPixelRGBANolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)159 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
160 {
161     Uint32 color;
162 
163     /*
164      * Setup color
165      */
166     color = SDL_MapRGBA(dst->format, r, g, b, a);
167 
168     /*
169      * Draw
170      */
171     return (fastPixelColorNolock(dst, x, y, color));
172 }
173 
174 /* PutPixel routine with alpha blending, input color in destination format */
175 
176 /* New, faster routine - default blending pixel */
177 
_putPixelAlpha(SDL_Surface * surface,Sint16 x,Sint16 y,Uint32 color,Uint8 alpha)178 int _putPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
179 {
180     Uint32 Rmask = surface->format->Rmask, Gmask =
181 	surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
182     Uint32 R, G, B, A = 0;
183 
184     if (x >= clip_xmin(surface) && x <= clip_xmax(surface)
185 	&& y >= clip_ymin(surface) && y <= clip_ymax(surface)) {
186 
187 	switch (surface->format->BytesPerPixel) {
188 	case 1:{		/* Assuming 8-bpp */
189 		if (alpha == 255) {
190 		    *((Uint8 *) surface->pixels + y * surface->pitch + x) = color;
191 		} else {
192 		    Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x;
193 
194 		    Uint8 dR = surface->format->palette->colors[*pixel].r;
195 		    Uint8 dG = surface->format->palette->colors[*pixel].g;
196 		    Uint8 dB = surface->format->palette->colors[*pixel].b;
197 		    Uint8 sR = surface->format->palette->colors[color].r;
198 		    Uint8 sG = surface->format->palette->colors[color].g;
199 		    Uint8 sB = surface->format->palette->colors[color].b;
200 
201 		    dR = dR + ((sR - dR) * alpha >> 8);
202 		    dG = dG + ((sG - dG) * alpha >> 8);
203 		    dB = dB + ((sB - dB) * alpha >> 8);
204 
205 		    *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
206 		}
207 	    }
208 	    break;
209 
210 	case 2:{		/* Probably 15-bpp or 16-bpp */
211 		if (alpha == 255) {
212 		    *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color;
213 		} else {
214 		    Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x;
215 		    Uint32 dc = *pixel;
216 
217 		    R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
218 		    G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
219 		    B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
220 		    if (Amask)
221 			A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
222 
223 		    *pixel = R | G | B | A;
224 		}
225 	    }
226 	    break;
227 
228 	case 3:{		/* Slow 24-bpp mode, usually not used */
229 		Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
230 		Uint8 rshift8 = surface->format->Rshift / 8;
231 		Uint8 gshift8 = surface->format->Gshift / 8;
232 		Uint8 bshift8 = surface->format->Bshift / 8;
233 		Uint8 ashift8 = surface->format->Ashift / 8;
234 
235 
236 		if (alpha == 255) {
237 		    *(pix + rshift8) = color >> surface->format->Rshift;
238 		    *(pix + gshift8) = color >> surface->format->Gshift;
239 		    *(pix + bshift8) = color >> surface->format->Bshift;
240 		    *(pix + ashift8) = color >> surface->format->Ashift;
241 		} else {
242 		    Uint8 dR, dG, dB, dA = 0;
243 		    Uint8 sR, sG, sB, sA = 0;
244 
245 		    pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
246 
247 		    dR = *((pix) + rshift8);
248 		    dG = *((pix) + gshift8);
249 		    dB = *((pix) + bshift8);
250 		    dA = *((pix) + ashift8);
251 
252 		    sR = (color >> surface->format->Rshift) & 0xff;
253 		    sG = (color >> surface->format->Gshift) & 0xff;
254 		    sB = (color >> surface->format->Bshift) & 0xff;
255 		    sA = (color >> surface->format->Ashift) & 0xff;
256 
257 		    dR = dR + ((sR - dR) * alpha >> 8);
258 		    dG = dG + ((sG - dG) * alpha >> 8);
259 		    dB = dB + ((sB - dB) * alpha >> 8);
260 		    dA = dA + ((sA - dA) * alpha >> 8);
261 
262 		    *((pix) + rshift8) = dR;
263 		    *((pix) + gshift8) = dG;
264 		    *((pix) + bshift8) = dB;
265 		    *((pix) + ashift8) = dA;
266 		}
267 	    }
268 	    break;
269 
270 	case 4:{		/* Probably 32-bpp */
271 		if (alpha == 255) {
272 		    *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
273 		} else {
274 		    Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
275 		    Uint32 dc = *pixel;
276 
277 		    R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
278 		    G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
279 		    B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
280 		    if (Amask)
281 			A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
282 
283 		    *pixel = R | G | B | A;
284 		}
285 	    }
286 	    break;
287 	}
288     }
289 
290     return (0);
291 }
292 
293 /* ----- Pixel - pixel draw with blending enabled if a<255 */
294 
pixelColor(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)295 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
296 {
297     Uint8 alpha;
298     Uint32 mcolor;
299     int result = 0;
300 
301     /*
302      * Lock the surface
303      */
304     if (SDL_MUSTLOCK(dst)) {
305 	if (SDL_LockSurface(dst) < 0) {
306 	    return (-1);
307 	}
308     }
309 
310     /*
311      * Setup color
312      */
313     alpha = color & 0x000000ff;
314     mcolor =
315 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
316 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
317 
318     /*
319      * Draw
320      */
321     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
322 
323     /*
324      * Unlock the surface
325      */
326     if (SDL_MUSTLOCK(dst)) {
327 	SDL_UnlockSurface(dst);
328     }
329 
330     return (result);
331 }
332 
pixelColorNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color)333 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
334 {
335     Uint8 alpha;
336     Uint32 mcolor;
337     int result = 0;
338 
339     /*
340      * Setup color
341      */
342     alpha = color & 0x000000ff;
343     mcolor =
344 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
345 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
346 
347     /*
348      * Draw
349      */
350     result = _putPixelAlpha(dst, x, y, mcolor, alpha);
351 
352     return (result);
353 }
354 
355 
356 /* Filled rectangle with alpha blending, color in destination format */
357 
_filledRectAlpha(SDL_Surface * surface,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,Uint8 alpha)358 int _filledRectAlpha(SDL_Surface * surface, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
359 {
360     Uint32 Rmask = surface->format->Rmask, Gmask =
361 	surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
362     Uint32 R, G, B, A = 0;
363     Sint16 x, y;
364 
365     switch (surface->format->BytesPerPixel) {
366     case 1:{			/* Assuming 8-bpp */
367 	    Uint8 *row, *pixel;
368 	    Uint8 dR, dG, dB;
369 
370 	    Uint8 sR = surface->format->palette->colors[color].r;
371 	    Uint8 sG = surface->format->palette->colors[color].g;
372 	    Uint8 sB = surface->format->palette->colors[color].b;
373 
374 	    for (y = y1; y <= y2; y++) {
375 		row = (Uint8 *) surface->pixels + y * surface->pitch;
376 		for (x = x1; x <= x2; x++) {
377 		    pixel = row + x;
378 
379 		    dR = surface->format->palette->colors[*pixel].r;
380 		    dG = surface->format->palette->colors[*pixel].g;
381 		    dB = surface->format->palette->colors[*pixel].b;
382 
383 		    dR = dR + ((sR - dR) * alpha >> 8);
384 		    dG = dG + ((sG - dG) * alpha >> 8);
385 		    dB = dB + ((sB - dB) * alpha >> 8);
386 
387 		    *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
388 		}
389 	    }
390 	}
391 	break;
392 
393     case 2:{			/* Probably 15-bpp or 16-bpp */
394 	    Uint16 *row, *pixel;
395 	    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
396 
397 	    for (y = y1; y <= y2; y++) {
398 		row = (Uint16 *) surface->pixels + y * surface->pitch / 2;
399 		for (x = x1; x <= x2; x++) {
400 		    pixel = row + x;
401 
402 		    R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
403 		    G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
404 		    B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
405 		    if (Amask)
406 			A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
407 
408 		    *pixel = R | G | B | A;
409 		}
410 	    }
411 	}
412 	break;
413 
414     case 3:{			/* Slow 24-bpp mode, usually not used */
415 	    Uint8 *row, *pix;
416 	    Uint8 dR, dG, dB, dA;
417 	    Uint8 rshift8 = surface->format->Rshift / 8;
418 	    Uint8 gshift8 = surface->format->Gshift / 8;
419 	    Uint8 bshift8 = surface->format->Bshift / 8;
420 	    Uint8 ashift8 = surface->format->Ashift / 8;
421 
422 	    Uint8 sR = (color >> surface->format->Rshift) & 0xff;
423 	    Uint8 sG = (color >> surface->format->Gshift) & 0xff;
424 	    Uint8 sB = (color >> surface->format->Bshift) & 0xff;
425 	    Uint8 sA = (color >> surface->format->Ashift) & 0xff;
426 
427 	    for (y = y1; y <= y2; y++) {
428 		row = (Uint8 *) surface->pixels + y * surface->pitch;
429 		for (x = x1; x <= x2; x++) {
430 		    pix = row + x * 3;
431 
432 		    dR = *((pix) + rshift8);
433 		    dG = *((pix) + gshift8);
434 		    dB = *((pix) + bshift8);
435 		    dA = *((pix) + ashift8);
436 
437 		    dR = dR + ((sR - dR) * alpha >> 8);
438 		    dG = dG + ((sG - dG) * alpha >> 8);
439 		    dB = dB + ((sB - dB) * alpha >> 8);
440 		    dA = dA + ((sA - dA) * alpha >> 8);
441 
442 		    *((pix) + rshift8) = dR;
443 		    *((pix) + gshift8) = dG;
444 		    *((pix) + bshift8) = dB;
445 		    *((pix) + ashift8) = dA;
446 		}
447 	    }
448 
449 	}
450 	break;
451 
452     case 4:{			/* Probably 32-bpp */
453 	    Uint32 *row, *pixel;
454 	    Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask), dA = (color & Amask);
455 
456 	    for (y = y1; y <= y2; y++) {
457 		row = (Uint32 *) surface->pixels + y * surface->pitch / 4;
458 		for (x = x1; x <= x2; x++) {
459 		    pixel = row + x;
460 
461 		    R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
462 		    G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
463 		    B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
464 		    if (Amask)
465 			A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
466 
467 		    *pixel = R | G | B | A;
468 		}
469 	    }
470 	}
471 	break;
472     }
473 
474     return (0);
475 }
476 
477 /* Draw rectangle with alpha enabled from RGBA color. */
478 
filledRectAlpha(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)479 int filledRectAlpha(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
480 {
481     Uint8 alpha;
482     Uint32 mcolor;
483     int result = 0;
484 
485     /*
486      * Lock the surface
487      */
488     if (SDL_MUSTLOCK(dst)) {
489 	if (SDL_LockSurface(dst) < 0) {
490 	    return (-1);
491 	}
492     }
493 
494     /*
495      * Setup color
496      */
497     alpha = color & 0x000000ff;
498     mcolor =
499 	SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
500 		    (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
501 
502     /*
503      * Draw
504      */
505     result = _filledRectAlpha(dst, x1, y1, x2, y2, mcolor, alpha);
506 
507     /*
508      * Unlock the surface
509      */
510     if (SDL_MUSTLOCK(dst)) {
511 	SDL_UnlockSurface(dst);
512     }
513 
514     return (result);
515 }
516 
517 /* Draw horizontal line with alpha enabled from RGBA color */
518 
HLineAlpha(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)519 int HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
520 {
521     return (filledRectAlpha(dst, x1, y, x2, y, color));
522 }
523 
524 
525 /* Draw vertical line with alpha enabled from RGBA color */
526 
VLineAlpha(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)527 int VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
528 {
529     return (filledRectAlpha(dst, x, y1, x, y2, color));
530 }
531 
532 
533 /* Pixel - using alpha weight on color for AA-drawing */
534 
pixelColorWeight(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)535 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
536 {
537     Uint32 a;
538 
539     /*
540      * Get alpha
541      */
542     a = (color & (Uint32) 0x000000ff);
543 
544     /*
545      * Modify Alpha by weight
546      */
547     a = ((a * weight) >> 8);
548 
549     return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
550 }
551 
552 /* Pixel - using alpha weight on color for AA-drawing - no locking */
553 
pixelColorWeightNolock(SDL_Surface * dst,Sint16 x,Sint16 y,Uint32 color,Uint32 weight)554 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
555 {
556     Uint32 a;
557 
558     /*
559      * Get alpha
560      */
561     a = (color & (Uint32) 0x000000ff);
562 
563     /*
564      * Modify Alpha by weight
565      */
566     a = ((a * weight) >> 8);
567 
568     return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
569 }
570 
pixelRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)571 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
572 {
573     Uint32 color;
574 
575     /*
576      * Check Alpha
577      */
578     if (a == 255) {
579 	/*
580 	 * No alpha blending required
581 	 */
582 	/*
583 	 * Setup color
584 	 */
585 	color = SDL_MapRGBA(dst->format, r, g, b, a);
586 	/*
587 	 * Draw
588 	 */
589 	return (fastPixelColor(dst, x, y, color));
590     } else {
591 	/*
592 	 * Alpha blending required
593 	 */
594 	/*
595 	 * Draw
596 	 */
597 	return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
598     }
599 }
600 
601 /* ----- Horizontal line */
602 
603 /* Just store color including alpha, no blending */
604 
hlineColorStore(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)605 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
606 {
607     Sint16 left, right, top, bottom;
608     Uint8 *pixel, *pixellast;
609     int dx;
610     int pixx, pixy;
611     Sint16 w;
612     Sint16 xtmp;
613     int result = -1;
614 
615     /*
616      * Get clipping boundary
617      */
618     left = dst->clip_rect.x;
619     right = dst->clip_rect.x + dst->clip_rect.w - 1;
620     top = dst->clip_rect.y;
621     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
622 
623     /*
624      * Check visibility of hline
625      */
626     if ((x1<left) && (x2<left)) {
627      return(0);
628     }
629     if ((x1>right) && (x2>right)) {
630      return(0);
631     }
632     if ((y<top) || (y>bottom)) {
633      return (0);
634     }
635 
636     /*
637      * Clip x
638      */
639     if (x1 < left) {
640 	x1 = left;
641     }
642     if (x2 > right) {
643 	x2 = right;
644     }
645 
646     /*
647      * Swap x1, x2 if required
648      */
649     if (x1 > x2) {
650 	xtmp = x1;
651 	x1 = x2;
652 	x2 = xtmp;
653     }
654 
655     /*
656      * Calculate width
657      */
658     w = x2 - x1;
659 
660     /*
661      * Sanity check on width
662      */
663     if (w < 0) {
664 	return (0);
665     }
666 
667     /*
668      * Lock surface
669      */
670     SDL_LockSurface(dst);
671 
672     /*
673      * More variable setup
674      */
675     dx = w;
676     pixx = dst->format->BytesPerPixel;
677 	pixy = dst->pitch;
678 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
679 
680 	/*
681 	 * Draw
682 	 */
683 	switch (dst->format->BytesPerPixel) {
684 	case 1:
685 	    memset(pixel, color, dx);
686 	    break;
687 	case 2:
688 	    pixellast = pixel + dx + dx;
689 	    for (; pixel <= pixellast; pixel += pixx) {
690 		*(Uint16 *) pixel = color;
691 	    }
692 	    break;
693 	case 3:
694 	    pixellast = pixel + dx + dx + dx;
695 	    for (; pixel <= pixellast; pixel += pixx) {
696 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
697 		    pixel[0] = (color >> 16) & 0xff;
698 		    pixel[1] = (color >> 8) & 0xff;
699 		    pixel[2] = color & 0xff;
700 		} else {
701 		    pixel[0] = color & 0xff;
702 		    pixel[1] = (color >> 8) & 0xff;
703 		    pixel[2] = (color >> 16) & 0xff;
704 		}
705 	    }
706 	    break;
707 	default:		/* case 4 */
708 	    dx = dx + dx;
709 	    pixellast = pixel + dx + dx;
710 	    for (; pixel <= pixellast; pixel += pixx) {
711 		*(Uint32 *) pixel = color;
712 	    }
713 	    break;
714 	}
715 
716 	/*
717 	 * Unlock surface
718 	 */
719 	SDL_UnlockSurface(dst);
720 
721 	/*
722 	 * Set result code
723 	 */
724 	result = 0;
725 
726     return (result);
727 }
728 
hlineRGBAStore(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)729 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
730 {
731     /*
732      * Draw
733      */
734     return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
735 }
736 
hlineColor(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint32 color)737 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
738 {
739     Sint16 left, right, top, bottom;
740     Uint8 *pixel, *pixellast;
741     int dx;
742     int pixx, pixy;
743     Sint16 w;
744     Sint16 xtmp;
745     int result = -1;
746     Uint8 *colorptr;
747 
748     /*
749      * Get clipping boundary
750      */
751     left = dst->clip_rect.x;
752     right = dst->clip_rect.x + dst->clip_rect.w - 1;
753     top = dst->clip_rect.y;
754     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
755 
756     /*
757      * Check visibility of hline
758      */
759     if ((x1<left) && (x2<left)) {
760      return(0);
761     }
762     if ((x1>right) && (x2>right)) {
763      return(0);
764     }
765     if ((y<top) || (y>bottom)) {
766      return (0);
767     }
768 
769     /*
770      * Clip x
771      */
772     if (x1 < left) {
773 	x1 = left;
774     }
775     if (x2 > right) {
776 	x2 = right;
777     }
778 
779     /*
780      * Swap x1, x2 if required
781      */
782     if (x1 > x2) {
783 	xtmp = x1;
784 	x1 = x2;
785 	x2 = xtmp;
786     }
787 
788     /*
789      * Calculate width
790      */
791     w = x2 - x1;
792 
793     /*
794      * Sanity check on width
795      */
796     if (w < 0) {
797 	return (0);
798     }
799 
800     /*
801      * Alpha check
802      */
803     if ((color & 255) == 255) {
804 
805 	/*
806 	 * No alpha-blending required
807 	 */
808 
809 	/*
810 	 * Setup color
811 	 */
812 	colorptr = (Uint8 *) & color;
813 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
814 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
815 	} else {
816 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
817 	}
818 
819 	/*
820 	 * Lock surface
821 	 */
822 	SDL_LockSurface(dst);
823 
824 	/*
825 	 * More variable setup
826 	 */
827 	dx = w;
828 	pixx = dst->format->BytesPerPixel;
829 	pixy = dst->pitch;
830 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
831 
832 	/*
833 	 * Draw
834 	 */
835 	switch (dst->format->BytesPerPixel) {
836 	case 1:
837 	    memset(pixel, color, dx);
838 	    break;
839 	case 2:
840 	    pixellast = pixel + dx + dx;
841 	    for (; pixel <= pixellast; pixel += pixx) {
842 		*(Uint16 *) pixel = color;
843 	    }
844 	    break;
845 	case 3:
846 	    pixellast = pixel + dx + dx + dx;
847 	    for (; pixel <= pixellast; pixel += pixx) {
848 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
849 		    pixel[0] = (color >> 16) & 0xff;
850 		    pixel[1] = (color >> 8) & 0xff;
851 		    pixel[2] = color & 0xff;
852 		} else {
853 		    pixel[0] = color & 0xff;
854 		    pixel[1] = (color >> 8) & 0xff;
855 		    pixel[2] = (color >> 16) & 0xff;
856 		}
857 	    }
858 	    break;
859 	default:		/* case 4 */
860 	    dx = dx + dx;
861 	    pixellast = pixel + dx + dx;
862 	    for (; pixel <= pixellast; pixel += pixx) {
863 		*(Uint32 *) pixel = color;
864 	    }
865 	    break;
866 	}
867 
868 	/*
869 	 * Unlock surface
870 	 */
871 	SDL_UnlockSurface(dst);
872 
873 	/*
874 	 * Set result code
875 	 */
876 	result = 0;
877 
878     } else {
879 
880 	/*
881 	 * Alpha blending blit
882 	 */
883 
884 	result = HLineAlpha(dst, x1, x1 + w, y, color);
885 
886     }
887 
888     return (result);
889 }
890 
hlineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 x2,Sint16 y,Uint8 r,Uint8 g,Uint8 b,Uint8 a)891 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
892 {
893     /*
894      * Draw
895      */
896     return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
897 }
898 
899 /* ----- Vertical line */
900 
vlineColor(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint32 color)901 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
902 {
903     Sint16 left, right, top, bottom;
904     Uint8 *pixel, *pixellast;
905     int dy;
906     int pixx, pixy;
907     Sint16 h;
908     Sint16 ytmp;
909     int result = -1;
910     Uint8 *colorptr;
911 
912     /*
913      * Get clipping boundary
914      */
915     left = dst->clip_rect.x;
916     right = dst->clip_rect.x + dst->clip_rect.w - 1;
917     top = dst->clip_rect.y;
918     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
919 
920     /*
921      * Check visibility of vline
922      */
923     if ((x<left) || (x>right)) {
924      return (0);
925     }
926     if ((y1<top) && (y2<top)) {
927      return(0);
928     }
929     if ((y1>bottom) && (y2>bottom)) {
930      return(0);
931     }
932 
933     /*
934      * Clip y
935      */
936     if (y1 < top) {
937 	y1 = top;
938     }
939     if (y2 > bottom) {
940 	y2 = bottom;
941     }
942 
943     /*
944      * Swap y1, y2 if required
945      */
946     if (y1 > y2) {
947 	ytmp = y1;
948 	y1 = y2;
949 	y2 = ytmp;
950     }
951 
952     /*
953      * Calculate height
954      */
955     h = y2 - y1;
956 
957     /*
958      * Sanity check on height
959      */
960     if (h < 0) {
961 	return (0);
962     }
963 
964     /*
965      * Alpha check
966      */
967     if ((color & 255) == 255) {
968 
969 	/*
970 	 * No alpha-blending required
971 	 */
972 
973 	/*
974 	 * Setup color
975 	 */
976 	colorptr = (Uint8 *) & color;
977 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
978 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
979 	} else {
980 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
981 	}
982 
983 	/*
984 	 * Lock surface
985 	 */
986 	SDL_LockSurface(dst);
987 
988 	/*
989 	 * More variable setup
990 	 */
991 	dy = h;
992 	pixx = dst->format->BytesPerPixel;
993 	pixy = dst->pitch;
994 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y1;
995 	pixellast = pixel + pixy * dy;
996 
997 	/*
998 	 * Draw
999 	 */
1000 	switch (dst->format->BytesPerPixel) {
1001 	case 1:
1002 	    for (; pixel <= pixellast; pixel += pixy) {
1003 		*(Uint8 *) pixel = color;
1004 	    }
1005 	    break;
1006 	case 2:
1007 	    for (; pixel <= pixellast; pixel += pixy) {
1008 		*(Uint16 *) pixel = color;
1009 	    }
1010 	    break;
1011 	case 3:
1012 	    for (; pixel <= pixellast; pixel += pixy) {
1013 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1014 		    pixel[0] = (color >> 16) & 0xff;
1015 		    pixel[1] = (color >> 8) & 0xff;
1016 		    pixel[2] = color & 0xff;
1017 		} else {
1018 		    pixel[0] = color & 0xff;
1019 		    pixel[1] = (color >> 8) & 0xff;
1020 		    pixel[2] = (color >> 16) & 0xff;
1021 		}
1022 	    }
1023 	    break;
1024 	default:		/* case 4 */
1025 	    for (; pixel <= pixellast; pixel += pixy) {
1026 		*(Uint32 *) pixel = color;
1027 	    }
1028 	    break;
1029 	}
1030 
1031 	/*
1032 	 * Unlock surface
1033 	 */
1034 	SDL_UnlockSurface(dst);
1035 
1036 	/*
1037 	 * Set result code
1038 	 */
1039 	result = 0;
1040 
1041     } else {
1042 
1043 	/*
1044 	 * Alpha blending blit
1045 	 */
1046 
1047 	result = VLineAlpha(dst, x, y1, y1 + h, color);
1048 
1049     }
1050 
1051     return (result);
1052 }
1053 
vlineRGBA(SDL_Surface * dst,Sint16 x,Sint16 y1,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1054 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1055 {
1056     /*
1057      * Draw
1058      */
1059     return (vlineColor(dst, x, y1, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1060 }
1061 
1062 /* ----- Rectangle */
1063 
rectangleColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1064 int rectangleColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1065 {
1066     int result;
1067     Sint16 w, h, xtmp, ytmp;
1068 
1069     /*
1070      * Swap x1, x2 if required
1071      */
1072     if (x1 > x2) {
1073 	xtmp = x1;
1074 	x1 = x2;
1075 	x2 = xtmp;
1076     }
1077 
1078     /*
1079      * Swap y1, y2 if required
1080      */
1081     if (y1 > y2) {
1082 	ytmp = y1;
1083 	y1 = y2;
1084 	y2 = ytmp;
1085     }
1086 
1087     /*
1088      * Calculate width&height
1089      */
1090     w = x2 - x1;
1091     h = y2 - y1;
1092 
1093     /*
1094      * Sanity check
1095      */
1096     if ((w < 0) || (h < 0)) {
1097 	return (0);
1098     }
1099 
1100     /*
1101      * Test for special cases of straight lines or single point
1102      */
1103     if (x1 == x2) {
1104 	if (y1 == y2) {
1105 	    return (pixelColor(dst, x1, y1, color));
1106 	} else {
1107 	    return (vlineColor(dst, x1, y1, y2, color));
1108 	}
1109     } else {
1110 	if (y1 == y2) {
1111 	    return (hlineColor(dst, x1, x2, y1, color));
1112 	}
1113     }
1114 
1115     /*
1116      * Draw rectangle
1117      */
1118     result = 0;
1119     result |= hlineColor(dst, x1, x2, y1, color);
1120     result |= hlineColor(dst, x1, x2, y2, color);
1121     y1 += 1;
1122     y2 -= 1;
1123     if (y1<=y2) {
1124      result |= vlineColor(dst, x1, y1, y2, color);
1125      result |= vlineColor(dst, x2, y1, y2, color);
1126     }
1127     return (result);
1128 
1129 }
1130 
rectangleRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1131 int rectangleRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1132 {
1133     /*
1134      * Draw
1135      */
1136     return (rectangleColor
1137 	    (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1138 }
1139 
1140 /* --------- Clipping routines for line */
1141 
1142 /* Clipping based heavily on code from                       */
1143 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c   */
1144 
1145 #define CLIP_LEFT_EDGE   0x1
1146 #define CLIP_RIGHT_EDGE  0x2
1147 #define CLIP_BOTTOM_EDGE 0x4
1148 #define CLIP_TOP_EDGE    0x8
1149 #define CLIP_INSIDE(a)   (!a)
1150 #define CLIP_REJECT(a,b) (a&b)
1151 #define CLIP_ACCEPT(a,b) (!(a|b))
1152 
clipEncode(Sint16 x,Sint16 y,Sint16 left,Sint16 top,Sint16 right,Sint16 bottom)1153 static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
1154 {
1155     int code = 0;
1156 
1157     if (x < left) {
1158 	code |= CLIP_LEFT_EDGE;
1159     } else if (x > right) {
1160 	code |= CLIP_RIGHT_EDGE;
1161     }
1162     if (y < top) {
1163 	code |= CLIP_TOP_EDGE;
1164     } else if (y > bottom) {
1165 	code |= CLIP_BOTTOM_EDGE;
1166     }
1167     return code;
1168 }
1169 
clipLine(SDL_Surface * dst,Sint16 * x1,Sint16 * y1,Sint16 * x2,Sint16 * y2)1170 static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
1171 {
1172     Sint16 left, right, top, bottom;
1173     int code1, code2;
1174     int draw = 0;
1175     Sint16 swaptmp;
1176     float m;
1177 
1178     /*
1179      * Get clipping boundary
1180      */
1181     left = dst->clip_rect.x;
1182     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1183     top = dst->clip_rect.y;
1184     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1185 
1186     while (1) {
1187 	code1 = clipEncode(*x1, *y1, left, top, right, bottom);
1188 	code2 = clipEncode(*x2, *y2, left, top, right, bottom);
1189 	if (CLIP_ACCEPT(code1, code2)) {
1190 	    draw = 1;
1191 	    break;
1192 	} else if (CLIP_REJECT(code1, code2))
1193 	    break;
1194 	else {
1195 	    if (CLIP_INSIDE(code1)) {
1196 		swaptmp = *x2;
1197 		*x2 = *x1;
1198 		*x1 = swaptmp;
1199 		swaptmp = *y2;
1200 		*y2 = *y1;
1201 		*y1 = swaptmp;
1202 		swaptmp = code2;
1203 		code2 = code1;
1204 		code1 = swaptmp;
1205 	    }
1206 	    if (*x2 != *x1) {
1207 		m = (*y2 - *y1) / (float) (*x2 - *x1);
1208 	    } else {
1209 		m = 1.0f;
1210 	    }
1211 	    if (code1 & CLIP_LEFT_EDGE) {
1212 		*y1 += (Sint16) ((left - *x1) * m);
1213 		*x1 = left;
1214 	    } else if (code1 & CLIP_RIGHT_EDGE) {
1215 		*y1 += (Sint16) ((right - *x1) * m);
1216 		*x1 = right;
1217 	    } else if (code1 & CLIP_BOTTOM_EDGE) {
1218 		if (*x2 != *x1) {
1219 		    *x1 += (Sint16) ((bottom - *y1) / m);
1220 		}
1221 		*y1 = bottom;
1222 	    } else if (code1 & CLIP_TOP_EDGE) {
1223 		if (*x2 != *x1) {
1224 		    *x1 += (Sint16) ((top - *y1) / m);
1225 		}
1226 		*y1 = top;
1227 	    }
1228 	}
1229     }
1230 
1231     return draw;
1232 }
1233 
1234 /* ----- Filled rectangle (Box) */
1235 
boxColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1236 int boxColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1237 {
1238     Sint16 left, right, top, bottom;
1239     Uint8 *pixel, *pixellast;
1240     int x, dx;
1241     int dy;
1242     int pixx, pixy;
1243     Sint16 w, h, tmp;
1244     int result;
1245     Uint8 *colorptr;
1246 
1247     /*
1248      * Get clipping boundary
1249      */
1250     left = dst->clip_rect.x;
1251     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1252     top = dst->clip_rect.y;
1253     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1254 
1255     /* Check visibility */
1256     if ((x1<left) && (x2<left)) {
1257      return(0);
1258     }
1259     if ((x1>right) && (x2>right)) {
1260      return(0);
1261     }
1262     if ((y1<top) && (y2<top)) {
1263      return(0);
1264     }
1265     if ((y1>bottom) && (y2>bottom)) {
1266      return(0);
1267     }
1268 
1269     /* Clip all points */
1270     if (x1<left) {
1271      x1=left;
1272     } else if (x1>right) {
1273      x1=right;
1274     }
1275     if (x2<left) {
1276      x2=left;
1277     } else if (x2>right) {
1278      x2=right;
1279     }
1280     if (y1<top) {
1281      y1=top;
1282     } else if (y1>bottom) {
1283      y1=bottom;
1284     }
1285     if (y2<top) {
1286      y2=top;
1287     } else if (y2>bottom) {
1288      y2=bottom;
1289     }
1290 
1291     /*
1292      * Order coordinates
1293      */
1294     if (x1 > x2) {
1295 	tmp = x1;
1296 	x1 = x2;
1297 	x2 = tmp;
1298     }
1299     if (y1 > y2) {
1300 	tmp = y1;
1301 	y1 = y2;
1302 	y2 = tmp;
1303     }
1304 
1305     /*
1306      * Test for special cases of straight line or single point
1307      */
1308     if (x1 == x2) {
1309 	if (y1 == y2) {
1310 	    return (pixelColor(dst, x1, y1, color));
1311 	} else {
1312 	    return (vlineColor(dst, x1, y1, y2, color));
1313 	}
1314     }
1315     if (y1 == y2) {
1316 	return (hlineColor(dst, x1, x2, y1, color));
1317     }
1318 
1319 
1320     /*
1321      * Calculate width&height
1322      */
1323     w = x2 - x1;
1324     h = y2 - y1;
1325 
1326     /*
1327      * Alpha check
1328      */
1329     if ((color & 255) == 255) {
1330 
1331 	/*
1332 	 * No alpha-blending required
1333 	 */
1334 
1335 	/*
1336 	 * Setup color
1337 	 */
1338 	colorptr = (Uint8 *) & color;
1339 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1340 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1341 	} else {
1342 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1343 	}
1344 
1345 	/*
1346 	 * Lock surface
1347 	 */
1348 	SDL_LockSurface(dst);
1349 
1350 	/*
1351 	 * More variable setup
1352 	 */
1353 	dx = w;
1354 	dy = h;
1355 	pixx = dst->format->BytesPerPixel;
1356 	pixy = dst->pitch;
1357 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
1358 	pixellast = pixel + pixx * dx + pixy * dy;
1359 
1360 	/*
1361 	 * Draw
1362 	 */
1363 	switch (dst->format->BytesPerPixel) {
1364 	case 1:
1365 	    for (; pixel <= pixellast; pixel += pixy) {
1366 		memset(pixel, (Uint8) color, dx);
1367 	    }
1368 	    break;
1369 	case 2:
1370 	    pixy -= (pixx * dx);
1371 	    for (; pixel <= pixellast; pixel += pixy) {
1372 		for (x = 0; x < dx; x++) {
1373 		    *(Uint16 *) pixel = color;
1374 		    pixel += pixx;
1375 		}
1376 	    }
1377 	    break;
1378 	case 3:
1379 	    pixy -= (pixx * dx);
1380 	    for (; pixel <= pixellast; pixel += pixy) {
1381 		for (x = 0; x < dx; x++) {
1382 		    if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1383 			pixel[0] = (color >> 16) & 0xff;
1384 			pixel[1] = (color >> 8) & 0xff;
1385 			pixel[2] = color & 0xff;
1386 		    } else {
1387 			pixel[0] = color & 0xff;
1388 			pixel[1] = (color >> 8) & 0xff;
1389 			pixel[2] = (color >> 16) & 0xff;
1390 		    }
1391 		    pixel += pixx;
1392 		}
1393 	    }
1394 	    break;
1395 	default:		/* case 4 */
1396 	    pixy -= (pixx * dx);
1397 	    for (; pixel <= pixellast; pixel += pixy) {
1398 		for (x = 0; x < dx; x++) {
1399 		    *(Uint32 *) pixel = color;
1400 		    pixel += pixx;
1401 		}
1402 	    }
1403 	    break;
1404 	}
1405 
1406 	/*
1407 	 * Unlock surface
1408 	 */
1409 	SDL_UnlockSurface(dst);
1410 
1411 	result = 0;
1412 
1413     } else {
1414 
1415 	result = filledRectAlpha(dst, x1, y1, x1 + w, y1 + h, color);
1416 
1417     }
1418 
1419     return (result);
1420 }
1421 
boxRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1422 int boxRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1423 {
1424     /*
1425      * Draw
1426      */
1427     return (boxColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1428 }
1429 
1430 /* ----- Line */
1431 
1432 /* Non-alpha line drawing code adapted from routine          */
1433 /* by Pete Shinners, pete@shinners.org                       */
1434 /* Originally from pygame, http://pygame.seul.org            */
1435 
1436 #define ABS(a) (((a)<0) ? -(a) : (a))
1437 
lineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1438 int lineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1439 {
1440     int pixx, pixy;
1441     int x, y;
1442     int dx, dy;
1443     int ax, ay;
1444     int sx, sy;
1445     int swaptmp;
1446     Uint8 *pixel;
1447     Uint8 *colorptr;
1448 
1449     /*
1450      * Clip line and test if we have to draw
1451      */
1452     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
1453 	return (0);
1454     }
1455 
1456     /*
1457      * Test for special cases of straight lines or single point
1458      */
1459     if (x1 == x2) {
1460 	if (y1 < y2) {
1461 	    return (vlineColor(dst, x1, y1, y2, color));
1462 	} else if (y1 > y2) {
1463 	    return (vlineColor(dst, x1, y2, y1, color));
1464 	} else {
1465 	    return (pixelColor(dst, x1, y1, color));
1466 	}
1467     }
1468     if (y1 == y2) {
1469 	if (x1 < x2) {
1470 	    return (hlineColor(dst, x1, x2, y1, color));
1471 	} else if (x1 > x2) {
1472 	    return (hlineColor(dst, x2, x1, y1, color));
1473 	}
1474     }
1475 
1476     /*
1477      * Variable setup
1478      */
1479     dx = x2 - x1;
1480     dy = y2 - y1;
1481     sx = (dx >= 0) ? 1 : -1;
1482     sy = (dy >= 0) ? 1 : -1;
1483 
1484     /* Lock surface */
1485     if (SDL_MUSTLOCK(dst)) {
1486 	if (SDL_LockSurface(dst) < 0) {
1487 	    return (-1);
1488 	}
1489     }
1490 
1491     /*
1492      * Check for alpha blending
1493      */
1494     if ((color & 255) == 255) {
1495 
1496 	/*
1497 	 * No alpha blending - use fast pixel routines
1498 	 */
1499 
1500 	/*
1501 	 * Setup color
1502 	 */
1503 	colorptr = (Uint8 *) & color;
1504 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1505 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1506 	} else {
1507 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1508 	}
1509 
1510 	/*
1511 	 * More variable setup
1512 	 */
1513 	dx = sx * dx + 1;
1514 	dy = sy * dy + 1;
1515 	pixx = dst->format->BytesPerPixel;
1516 	pixy = dst->pitch;
1517 	pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
1518 	pixx *= sx;
1519 	pixy *= sy;
1520 	if (dx < dy) {
1521 	    swaptmp = dx;
1522 	    dx = dy;
1523 	    dy = swaptmp;
1524 	    swaptmp = pixx;
1525 	    pixx = pixy;
1526 	    pixy = swaptmp;
1527 	}
1528 
1529 	/*
1530 	 * Draw
1531 	 */
1532 	x = 0;
1533 	y = 0;
1534 	switch (dst->format->BytesPerPixel) {
1535 	case 1:
1536 	    for (; x < dx; x++, pixel += pixx) {
1537 		*pixel = color;
1538 		y += dy;
1539 		if (y >= dx) {
1540 		    y -= dx;
1541 		    pixel += pixy;
1542 		}
1543 	    }
1544 	    break;
1545 	case 2:
1546 	    for (; x < dx; x++, pixel += pixx) {
1547 		*(Uint16 *) pixel = color;
1548 		y += dy;
1549 		if (y >= dx) {
1550 		    y -= dx;
1551 		    pixel += pixy;
1552 		}
1553 	    }
1554 	    break;
1555 	case 3:
1556 	    for (; x < dx; x++, pixel += pixx) {
1557 		if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1558 		    pixel[0] = (color >> 16) & 0xff;
1559 		    pixel[1] = (color >> 8) & 0xff;
1560 		    pixel[2] = color & 0xff;
1561 		} else {
1562 		    pixel[0] = color & 0xff;
1563 		    pixel[1] = (color >> 8) & 0xff;
1564 		    pixel[2] = (color >> 16) & 0xff;
1565 		}
1566 		y += dy;
1567 		if (y >= dx) {
1568 		    y -= dx;
1569 		    pixel += pixy;
1570 		}
1571 	    }
1572 	    break;
1573 	default:		/* case 4 */
1574 	    for (; x < dx; x++, pixel += pixx) {
1575 		*(Uint32 *) pixel = color;
1576 		y += dy;
1577 		if (y >= dx) {
1578 		    y -= dx;
1579 		    pixel += pixy;
1580 		}
1581 	    }
1582 	    break;
1583 	}
1584 
1585     } else {
1586 
1587 	/*
1588 	 * Alpha blending required - use single-pixel blits
1589 	 */
1590 
1591 	ax = ABS(dx) << 1;
1592 	ay = ABS(dy) << 1;
1593 	x = x1;
1594 	y = y1;
1595 	if (ax > ay) {
1596 	    int d = ay - (ax >> 1);
1597 
1598 	    while (x != x2) {
1599 		pixelColorNolock (dst, x, y, color);
1600 		if (d > 0 || (d == 0 && sx == 1)) {
1601 		    y += sy;
1602 		    d -= ax;
1603 		}
1604 		x += sx;
1605 		d += ay;
1606 	    }
1607 	} else {
1608 	    int d = ax - (ay >> 1);
1609 
1610 	    while (y != y2) {
1611 		pixelColorNolock (dst, x, y, color);
1612 		if (d > 0 || ((d == 0) && (sy == 1))) {
1613 		    x += sx;
1614 		    d -= ay;
1615 		}
1616 		y += sy;
1617 		d += ax;
1618 	    }
1619 	}
1620 	pixelColorNolock (dst, x, y, color);
1621 
1622     }
1623 
1624     /* Unlock surface */
1625     if (SDL_MUSTLOCK(dst)) {
1626 	SDL_UnlockSurface(dst);
1627     }
1628 
1629     return (0);
1630 }
1631 
lineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1632 int lineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1633 {
1634     /*
1635      * Draw
1636      */
1637     return (lineColor(dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1638 }
1639 
1640 /* AA Line */
1641 
1642 #define AAlevels 256
1643 #define AAbits 8
1644 
1645 /*
1646 
1647 This implementation of the Wu antialiasing code is based on Mike Abrash's
1648 DDJ article which was reprinted as Chapter 42 of his Graphics Programming
1649 Black Book, but has been optimized to work with SDL and utilizes 32-bit
1650 fixed-point arithmetic. (A. Schiffler).
1651 
1652 */
1653 
aalineColorInt(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color,int draw_endpoint)1654 int aalineColorInt(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
1655 {
1656     Sint32 xx0, yy0, xx1, yy1;
1657     int result;
1658     Uint32 intshift, erracc, erradj;
1659     Uint32 erracctmp, wgt, wgtcompmask;
1660     int dx, dy, tmp, xdir, y0p1, x0pxdir;
1661 
1662     /*
1663      * Clip line and test if we have to draw
1664      */
1665     if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
1666 	return (0);
1667     }
1668 
1669     /*
1670      * Keep on working with 32bit numbers
1671      */
1672     xx0 = x1;
1673     yy0 = y1;
1674     xx1 = x2;
1675     yy1 = y2;
1676 
1677     /*
1678      * Reorder points if required
1679      */
1680     if (yy0 > yy1) {
1681 	tmp = yy0;
1682 	yy0 = yy1;
1683 	yy1 = tmp;
1684 	tmp = xx0;
1685 	xx0 = xx1;
1686 	xx1 = tmp;
1687     }
1688 
1689     /*
1690      * Calculate distance
1691      */
1692     dx = xx1 - xx0;
1693     dy = yy1 - yy0;
1694 
1695     /*
1696      * Adjust for negative dx and set xdir
1697      */
1698     if (dx >= 0) {
1699 	xdir = 1;
1700     } else {
1701 	xdir = -1;
1702 	dx = (-dx);
1703     }
1704 
1705     /*
1706      * Check for special cases
1707      */
1708     if (dx == 0) {
1709 	/*
1710 	 * Vertical line
1711 	 */
1712 	return (vlineColor(dst, x1, y1, y2, color));
1713     } else if (dy == 0) {
1714 	/*
1715 	 * Horizontal line
1716 	 */
1717 	return (hlineColor(dst, x1, x2, y1, color));
1718     } else if (dx == dy) {
1719 	/*
1720 	 * Diagonal line
1721 	 */
1722 	return (lineColor(dst, x1, y1, x2, y2, color));
1723     }
1724 
1725     /*
1726      * Line is not horizontal, vertical or diagonal
1727      */
1728     result = 0;
1729 
1730     /*
1731      * Zero accumulator
1732      */
1733     erracc = 0;
1734 
1735     /*
1736      * # of bits by which to shift erracc to get intensity level
1737      */
1738     intshift = 32 - AAbits;
1739     /*
1740      * Mask used to flip all bits in an intensity weighting
1741      */
1742     wgtcompmask = AAlevels - 1;
1743 
1744     /* Lock surface */
1745     if (SDL_MUSTLOCK(dst)) {
1746 	if (SDL_LockSurface(dst) < 0) {
1747 	    return (-1);
1748 	}
1749     }
1750 
1751     /*
1752      * Draw the initial pixel in the foreground color
1753      */
1754     result |= pixelColorNolock(dst, x1, y1, color);
1755 
1756     /*
1757      * x-major or y-major?
1758      */
1759     if (dy > dx) {
1760 
1761 	/*
1762 	 * y-major.  Calculate 16-bit fixed point fractional part of a pixel that
1763 	 * X advances every time Y advances 1 pixel, truncating the result so that
1764 	 * we won't overrun the endpoint along the X axis
1765 	 */
1766 	/*
1767 	 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
1768 	 */
1769 	erradj = ((dx << 16) / dy) << 16;
1770 
1771 	/*
1772 	 * draw all pixels other than the first and last
1773 	 */
1774 	x0pxdir = xx0 + xdir;
1775 	while (--dy) {
1776 	    erracctmp = erracc;
1777 	    erracc += erradj;
1778 	    if (erracc <= erracctmp) {
1779 		/*
1780 		 * rollover in error accumulator, x coord advances
1781 		 */
1782 		xx0 = x0pxdir;
1783 		x0pxdir += xdir;
1784 	    }
1785 	    yy0++;		/* y-major so always advance Y */
1786 
1787 	    /*
1788 	     * the AAbits most significant bits of erracc give us the intensity
1789 	     * weighting for this pixel, and the complement of the weighting for
1790 	     * the paired pixel.
1791 	     */
1792 	    wgt = (erracc >> intshift) & 255;
1793 	    result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1794 	    result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
1795 	}
1796 
1797     } else {
1798 
1799 	/*
1800 	 * x-major line.  Calculate 16-bit fixed-point fractional part of a pixel
1801 	 * that Y advances each time X advances 1 pixel, truncating the result so
1802 	 * that we won't overrun the endpoint along the X axis.
1803 	 */
1804 	/*
1805 	 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
1806 	 */
1807 	erradj = ((dy << 16) / dx) << 16;
1808 
1809 	/*
1810 	 * draw all pixels other than the first and last
1811 	 */
1812 	y0p1 = yy0 + 1;
1813 	while (--dx) {
1814 
1815 	    erracctmp = erracc;
1816 	    erracc += erradj;
1817 	    if (erracc <= erracctmp) {
1818 		/*
1819 		 * Accumulator turned over, advance y
1820 		 */
1821 		yy0 = y0p1;
1822 		y0p1++;
1823 	    }
1824 	    xx0 += xdir;	/* x-major so always advance X */
1825 	    /*
1826 	     * the AAbits most significant bits of erracc give us the intensity
1827 	     * weighting for this pixel, and the complement of the weighting for
1828 	     * the paired pixel.
1829 	     */
1830 	    wgt = (erracc >> intshift) & 255;
1831 	    result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1832 	    result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
1833 	}
1834     }
1835 
1836     /*
1837      * Do we have to draw the endpoint
1838      */
1839     if (draw_endpoint) {
1840 	/*
1841 	 * Draw final pixel, always exactly intersected by the line and doesn't
1842 	 * need to be weighted.
1843 	 */
1844 	result |= pixelColorNolock (dst, x2, y2, color);
1845     }
1846 
1847     /* Unlock surface */
1848     if (SDL_MUSTLOCK(dst)) {
1849 	SDL_UnlockSurface(dst);
1850     }
1851 
1852     return (result);
1853 }
1854 
aalineColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint32 color)1855 int aalineColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1856 {
1857     return (aalineColorInt(dst, x1, y1, x2, y2, color, 1));
1858 }
1859 
aalineRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Uint8 r,Uint8 g,Uint8 b,Uint8 a)1860 int aalineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1861 {
1862     return (aalineColorInt
1863 	    (dst, x1, y1, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
1864 }
1865 
1866 
1867 /* ----- Circle */
1868 
1869 /* Note: Based on algorithm from sge library, modified by A. Schiffler */
1870 /* with multiple pixel-draw removal and other minor speedup changes.   */
1871 
circleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)1872 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
1873 {
1874     Sint16 left, right, top, bottom;
1875     int result;
1876     Sint16 x1, y1, x2, y2;
1877     Sint16 cx = 0;
1878     Sint16 cy = r;
1879     Sint16 ocx = (Sint16) 0xffff;
1880     Sint16 ocy = (Sint16) 0xffff;
1881     Sint16 df = 1 - r;
1882     Sint16 d_e = 3;
1883     Sint16 d_se = -2 * r + 5;
1884     Sint16 xpcx, xmcx, xpcy, xmcy;
1885     Sint16 ypcy, ymcy, ypcx, ymcx;
1886     Uint8 *colorptr;
1887 
1888     /*
1889      * Sanity check radius
1890      */
1891     if (r < 0) {
1892 	return (-1);
1893     }
1894 
1895     /*
1896      * Special case for r=0 - draw a point
1897      */
1898     if (r == 0) {
1899 	return (pixelColor(dst, x, y, color));
1900     }
1901 
1902     /*
1903      * Get clipping boundary
1904      */
1905     left = dst->clip_rect.x;
1906     right = dst->clip_rect.x + dst->clip_rect.w - 1;
1907     top = dst->clip_rect.y;
1908     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1909 
1910     /*
1911      * Test if bounding box of circle is visible
1912      */
1913     x1 = x - r;
1914     x2 = x + r;
1915     y1 = y - r;
1916     y2 = y + r;
1917     if ((x1<left) && (x2<left)) {
1918      return(0);
1919     }
1920     if ((x1>right) && (x2>right)) {
1921      return(0);
1922     }
1923     if ((y1<top) && (y2<top)) {
1924      return(0);
1925     }
1926     if ((y1>bottom) && (y2>bottom)) {
1927      return(0);
1928     }
1929 
1930     /*
1931      * Draw circle
1932      */
1933     result = 0;
1934 
1935     /* Lock surface */
1936     if (SDL_MUSTLOCK(dst)) {
1937 	if (SDL_LockSurface(dst) < 0) {
1938 	    return (-1);
1939 	}
1940     }
1941 
1942     /*
1943      * Alpha Check
1944      */
1945     if ((color & 255) == 255) {
1946 
1947 	/*
1948 	 * No Alpha - direct memory writes
1949 	 */
1950 
1951 	/*
1952 	 * Setup color
1953 	 */
1954 	colorptr = (Uint8 *) & color;
1955 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1956 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1957 	} else {
1958 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1959 	}
1960 
1961 	/*
1962 	 * Draw
1963 	 */
1964 	do {
1965 	    if ((ocy != cy) || (ocx != cx)) {
1966 		xpcx = x + cx;
1967 		xmcx = x - cx;
1968 		if (cy > 0) {
1969 		    ypcy = y + cy;
1970 		    ymcy = y - cy;
1971 		    result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
1972 		    result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
1973 		    result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
1974 		    result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
1975 		} else {
1976 		    result |= fastPixelColorNolock(dst, xmcx, y, color);
1977 		    result |= fastPixelColorNolock(dst, xpcx, y, color);
1978 		}
1979 		ocy = cy;
1980 		xpcy = x + cy;
1981 		xmcy = x - cy;
1982 		if (cx > 0) {
1983 		    ypcx = y + cx;
1984 		    ymcx = y - cx;
1985 		    result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
1986 		    result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
1987 		    result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
1988 		    result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
1989 		} else {
1990 		    result |= fastPixelColorNolock(dst, xmcy, y, color);
1991 		    result |= fastPixelColorNolock(dst, xpcy, y, color);
1992 		}
1993 		ocx = cx;
1994 	    }
1995 	    /*
1996 	     * Update
1997 	     */
1998 	    if (df < 0) {
1999 		df += d_e;
2000 		d_e += 2;
2001 		d_se += 2;
2002 	    } else {
2003 		df += d_se;
2004 		d_e += 2;
2005 		d_se += 4;
2006 		cy--;
2007 	    }
2008 	    cx++;
2009 	} while (cx <= cy);
2010 
2011 	/*
2012 	 * Unlock surface
2013 	 */
2014 	SDL_UnlockSurface(dst);
2015 
2016     } else {
2017 
2018 	/*
2019 	 * Using Alpha - blended pixel blits
2020 	 */
2021 
2022 	do {
2023 	    /*
2024 	     * Draw
2025 	     */
2026 	    if ((ocy != cy) || (ocx != cx)) {
2027 		xpcx = x + cx;
2028 		xmcx = x - cx;
2029 		if (cy > 0) {
2030 		    ypcy = y + cy;
2031 		    ymcy = y - cy;
2032 		    result |= pixelColorNolock (dst, xmcx, ypcy, color);
2033 		    result |= pixelColorNolock (dst, xpcx, ypcy, color);
2034 		    result |= pixelColorNolock (dst, xmcx, ymcy, color);
2035 		    result |= pixelColorNolock (dst, xpcx, ymcy, color);
2036 		} else {
2037 		    result |= pixelColorNolock (dst, xmcx, y, color);
2038 		    result |= pixelColorNolock (dst, xpcx, y, color);
2039 		}
2040 		ocy = cy;
2041 		xpcy = x + cy;
2042 		xmcy = x - cy;
2043 		if (cx > 0) {
2044 		    ypcx = y + cx;
2045 		    ymcx = y - cx;
2046 		    result |= pixelColorNolock (dst, xmcy, ypcx, color);
2047 		    result |= pixelColorNolock (dst, xpcy, ypcx, color);
2048 		    result |= pixelColorNolock (dst, xmcy, ymcx, color);
2049 		    result |= pixelColorNolock (dst, xpcy, ymcx, color);
2050 		} else {
2051 		    result |= pixelColorNolock (dst, xmcy, y, color);
2052 		    result |= pixelColorNolock (dst, xpcy, y, color);
2053 		}
2054 		ocx = cx;
2055 	    }
2056 	    /*
2057 	     * Update
2058 	     */
2059 	    if (df < 0) {
2060 		df += d_e;
2061 		d_e += 2;
2062 		d_se += 2;
2063 	    } else {
2064 		df += d_se;
2065 		d_e += 2;
2066 		d_se += 4;
2067 		cy--;
2068 	    }
2069 	    cx++;
2070 	} while (cx <= cy);
2071 
2072     }				/* Alpha check */
2073 
2074     /* Unlock surface */
2075     if (SDL_MUSTLOCK(dst)) {
2076 	SDL_UnlockSurface(dst);
2077     }
2078 
2079     return (result);
2080 }
2081 
circleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2082 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2083 {
2084     /*
2085      * Draw
2086      */
2087     return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2088 }
2089 
2090 /* ----- AA Circle */
2091 
2092 /* AA circle is based on AAellipse  */
2093 
aacircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2094 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2095 {
2096     return (aaellipseColor(dst, x, y, r, r, color));
2097 }
2098 
aacircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2099 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2100 {
2101     /*
2102      * Draw
2103      */
2104     return (aaellipseColor
2105 	    (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2106 }
2107 
2108 /* ----- Filled Circle */
2109 
2110 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
2111 
2112 /* and other speedup changes. */
2113 
filledCircleColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 r,Uint32 color)2114 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 r, Uint32 color)
2115 {
2116     Sint16 left, right, top, bottom;
2117     int result;
2118     Sint16 x1, y1, x2, y2;
2119     Sint16 cx = 0;
2120     Sint16 cy = r;
2121     Sint16 ocx = (Sint16) 0xffff;
2122     Sint16 ocy = (Sint16) 0xffff;
2123     Sint16 df = 1 - r;
2124     Sint16 d_e = 3;
2125     Sint16 d_se = -2 * r + 5;
2126     Sint16 xpcx, xmcx, xpcy, xmcy;
2127     Sint16 ypcy, ymcy, ypcx, ymcx;
2128 
2129     /*
2130      * Sanity check radius
2131      */
2132     if (r < 0) {
2133 	return (-1);
2134     }
2135 
2136     /*
2137      * Special case for r=0 - draw a point
2138      */
2139     if (r == 0) {
2140 	return (pixelColor(dst, x, y, color));
2141     }
2142 
2143     /*
2144      * Get clipping boundary
2145      */
2146     left = dst->clip_rect.x;
2147     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2148     top = dst->clip_rect.y;
2149     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2150 
2151     /*
2152      * Test if bounding box of circle is visible
2153      */
2154     x1 = x - r;
2155     x2 = x + r;
2156     y1 = y - r;
2157     y2 = y + r;
2158     if ((x1<left) && (x2<left)) {
2159      return(0);
2160     }
2161     if ((x1>right) && (x2>right)) {
2162      return(0);
2163     }
2164     if ((y1<top) && (y2<top)) {
2165      return(0);
2166     }
2167     if ((y1>bottom) && (y2>bottom)) {
2168      return(0);
2169     }
2170 
2171     /*
2172      * Draw
2173      */
2174     result = 0;
2175     do {
2176 	xpcx = x + cx;
2177 	xmcx = x - cx;
2178 	xpcy = x + cy;
2179 	xmcy = x - cy;
2180 	if (ocy != cy) {
2181 	    if (cy > 0) {
2182 		ypcy = y + cy;
2183 		ymcy = y - cy;
2184 		result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
2185 		result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
2186 	    } else {
2187 		result |= hlineColor(dst, xmcx, xpcx, y, color);
2188 	    }
2189 	    ocy = cy;
2190 	}
2191 	if (ocx != cx) {
2192 	    if (cx != cy) {
2193 		if (cx > 0) {
2194 		    ypcx = y + cx;
2195 		    ymcx = y - cx;
2196 		    result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
2197 		    result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
2198 		} else {
2199 		    result |= hlineColor(dst, xmcy, xpcy, y, color);
2200 		}
2201 	    }
2202 	    ocx = cx;
2203 	}
2204 	/*
2205 	 * Update
2206 	 */
2207 	if (df < 0) {
2208 	    df += d_e;
2209 	    d_e += 2;
2210 	    d_se += 2;
2211 	} else {
2212 	    df += d_se;
2213 	    d_e += 2;
2214 	    d_se += 4;
2215 	    cy--;
2216 	}
2217 	cx++;
2218     } while (cx <= cy);
2219 
2220     return (result);
2221 }
2222 
filledCircleRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2223 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2224 {
2225     /*
2226      * Draw
2227      */
2228     return (filledCircleColor
2229 	    (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2230 }
2231 
2232 
2233 /* ----- Ellipse */
2234 
2235 /* Note: Based on algorithm from sge library with multiple-hline draw removal */
2236 /* and other speedup changes. */
2237 
ellipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)2238 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2239 {
2240     Sint16 left, right, top, bottom;
2241     int result;
2242     Sint16 x1, y1, x2, y2;
2243     int ix, iy;
2244     int h, i, j, k;
2245     int oh, oi, oj, ok;
2246     int xmh, xph, ypk, ymk;
2247     int xmi, xpi, ymj, ypj;
2248     int xmj, xpj, ymi, ypi;
2249     int xmk, xpk, ymh, yph;
2250     Uint8 *colorptr;
2251 
2252     /*
2253      * Sanity check radii
2254      */
2255     if ((rx < 0) || (ry < 0)) {
2256 	return (-1);
2257     }
2258 
2259     /*
2260      * Special case for rx=0 - draw a vline
2261      */
2262     if (rx == 0) {
2263 	return (vlineColor(dst, x, y - ry, y + ry, color));
2264     }
2265     /*
2266      * Special case for ry=0 - draw a hline
2267      */
2268     if (ry == 0) {
2269 	return (hlineColor(dst, x - rx, x + rx, y, color));
2270     }
2271 
2272     /*
2273      * Get clipping boundary
2274      */
2275     left = dst->clip_rect.x;
2276     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2277     top = dst->clip_rect.y;
2278     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2279 
2280     /*
2281      * Test if bounding box of ellipse is visible
2282      */
2283     x1 = x - rx;
2284     x2 = x + rx;
2285     y1 = y - ry;
2286     y2 = y + ry;
2287     if ((x1<left) && (x2<left)) {
2288      return(0);
2289     }
2290     if ((x1>right) && (x2>right)) {
2291      return(0);
2292     }
2293     if ((y1<top) && (y2<top)) {
2294      return(0);
2295     }
2296     if ((y1>bottom) && (y2>bottom)) {
2297      return(0);
2298     }
2299 
2300     /*
2301      * Init vars
2302      */
2303     oh = oi = oj = ok = 0xFFFF;
2304 
2305     /*
2306      * Draw
2307      */
2308     result = 0;
2309 
2310     /* Lock surface */
2311     if (SDL_MUSTLOCK(dst)) {
2312 	if (SDL_LockSurface(dst) < 0) {
2313 	    return (-1);
2314 	}
2315     }
2316 
2317     /*
2318      * Check alpha
2319      */
2320     if ((color & 255) == 255) {
2321 
2322 	/*
2323 	 * No Alpha - direct memory writes
2324 	 */
2325 
2326 	/*
2327 	 * Setup color
2328 	 */
2329 	colorptr = (Uint8 *) & color;
2330 	if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2331 	    color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2332 	} else {
2333 	    color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2334 	}
2335 
2336 
2337 	if (rx > ry) {
2338 	    ix = 0;
2339 	    iy = rx * 64;
2340 
2341 	    do {
2342 		h = (ix + 32) >> 6;
2343 		i = (iy + 32) >> 6;
2344 		j = (h * ry) / rx;
2345 		k = (i * ry) / rx;
2346 
2347 		if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
2348 		    xph = x + h;
2349 		    xmh = x - h;
2350 		    if (k > 0) {
2351 			ypk = y + k;
2352 			ymk = y - k;
2353 			result |= fastPixelColorNolock(dst, xmh, ypk, color);
2354 			result |= fastPixelColorNolock(dst, xph, ypk, color);
2355 			result |= fastPixelColorNolock(dst, xmh, ymk, color);
2356 			result |= fastPixelColorNolock(dst, xph, ymk, color);
2357 		    } else {
2358 			result |= fastPixelColorNolock(dst, xmh, y, color);
2359 			result |= fastPixelColorNolock(dst, xph, y, color);
2360 		    }
2361 		    ok = k;
2362 		    xpi = x + i;
2363 		    xmi = x - i;
2364 		    if (j > 0) {
2365 			ypj = y + j;
2366 			ymj = y - j;
2367 			result |= fastPixelColorNolock(dst, xmi, ypj, color);
2368 			result |= fastPixelColorNolock(dst, xpi, ypj, color);
2369 			result |= fastPixelColorNolock(dst, xmi, ymj, color);
2370 			result |= fastPixelColorNolock(dst, xpi, ymj, color);
2371 		    } else {
2372 			result |= fastPixelColorNolock(dst, xmi, y, color);
2373 			result |= fastPixelColorNolock(dst, xpi, y, color);
2374 		    }
2375 		    oj = j;
2376 		}
2377 
2378 		ix = ix + iy / rx;
2379 		iy = iy - ix / rx;
2380 
2381 	    } while (i > h);
2382 	} else {
2383 	    ix = 0;
2384 	    iy = ry * 64;
2385 
2386 	    do {
2387 		h = (ix + 32) >> 6;
2388 		i = (iy + 32) >> 6;
2389 		j = (h * rx) / ry;
2390 		k = (i * rx) / ry;
2391 
2392 		if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
2393 		    xmj = x - j;
2394 		    xpj = x + j;
2395 		    if (i > 0) {
2396 			ypi = y + i;
2397 			ymi = y - i;
2398 			result |= fastPixelColorNolock(dst, xmj, ypi, color);
2399 			result |= fastPixelColorNolock(dst, xpj, ypi, color);
2400 			result |= fastPixelColorNolock(dst, xmj, ymi, color);
2401 			result |= fastPixelColorNolock(dst, xpj, ymi, color);
2402 		    } else {
2403 			result |= fastPixelColorNolock(dst, xmj, y, color);
2404 			result |= fastPixelColorNolock(dst, xpj, y, color);
2405 		    }
2406 		    oi = i;
2407 		    xmk = x - k;
2408 		    xpk = x + k;
2409 		    if (h > 0) {
2410 			yph = y + h;
2411 			ymh = y - h;
2412 			result |= fastPixelColorNolock(dst, xmk, yph, color);
2413 			result |= fastPixelColorNolock(dst, xpk, yph, color);
2414 			result |= fastPixelColorNolock(dst, xmk, ymh, color);
2415 			result |= fastPixelColorNolock(dst, xpk, ymh, color);
2416 		    } else {
2417 			result |= fastPixelColorNolock(dst, xmk, y, color);
2418 			result |= fastPixelColorNolock(dst, xpk, y, color);
2419 		    }
2420 		    oh = h;
2421 		}
2422 
2423 		ix = ix + iy / ry;
2424 		iy = iy - ix / ry;
2425 
2426 	    } while (i > h);
2427 	}
2428 
2429     } else {
2430 
2431 	if (rx > ry) {
2432 	    ix = 0;
2433 	    iy = rx * 64;
2434 
2435 	    do {
2436 		h = (ix + 32) >> 6;
2437 		i = (iy + 32) >> 6;
2438 		j = (h * ry) / rx;
2439 		k = (i * ry) / rx;
2440 
2441 		if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
2442 		    xph = x + h;
2443 		    xmh = x - h;
2444 		    if (k > 0) {
2445 			ypk = y + k;
2446 			ymk = y - k;
2447 			result |= pixelColorNolock (dst, xmh, ypk, color);
2448 			result |= pixelColorNolock (dst, xph, ypk, color);
2449 			result |= pixelColorNolock (dst, xmh, ymk, color);
2450 			result |= pixelColorNolock (dst, xph, ymk, color);
2451 		    } else {
2452 			result |= pixelColorNolock (dst, xmh, y, color);
2453 			result |= pixelColorNolock (dst, xph, y, color);
2454 		    }
2455 		    ok = k;
2456 		    xpi = x + i;
2457 		    xmi = x - i;
2458 		    if (j > 0) {
2459 			ypj = y + j;
2460 			ymj = y - j;
2461 			result |= pixelColorNolock (dst, xmi, ypj, color);
2462 			result |= pixelColorNolock (dst, xpi, ypj, color);
2463 			result |= pixelColorNolock (dst, xmi, ymj, color);
2464 			result |= pixelColor(dst, xpi, ymj, color);
2465 		    } else {
2466 			result |= pixelColorNolock (dst, xmi, y, color);
2467 			result |= pixelColorNolock (dst, xpi, y, color);
2468 		    }
2469 		    oj = j;
2470 		}
2471 
2472 		ix = ix + iy / rx;
2473 		iy = iy - ix / rx;
2474 
2475 	    } while (i > h);
2476 	} else {
2477 	    ix = 0;
2478 	    iy = ry * 64;
2479 
2480 	    do {
2481 		h = (ix + 32) >> 6;
2482 		i = (iy + 32) >> 6;
2483 		j = (h * rx) / ry;
2484 		k = (i * rx) / ry;
2485 
2486 		if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
2487 		    xmj = x - j;
2488 		    xpj = x + j;
2489 		    if (i > 0) {
2490 			ypi = y + i;
2491 			ymi = y - i;
2492 			result |= pixelColorNolock (dst, xmj, ypi, color);
2493 			result |= pixelColorNolock (dst, xpj, ypi, color);
2494 			result |= pixelColorNolock (dst, xmj, ymi, color);
2495 			result |= pixelColorNolock (dst, xpj, ymi, color);
2496 		    } else {
2497 			result |= pixelColorNolock (dst, xmj, y, color);
2498 			result |= pixelColorNolock (dst, xpj, y, color);
2499 		    }
2500 		    oi = i;
2501 		    xmk = x - k;
2502 		    xpk = x + k;
2503 		    if (h > 0) {
2504 			yph = y + h;
2505 			ymh = y - h;
2506 			result |= pixelColorNolock (dst, xmk, yph, color);
2507 			result |= pixelColorNolock (dst, xpk, yph, color);
2508 			result |= pixelColorNolock (dst, xmk, ymh, color);
2509 			result |= pixelColorNolock (dst, xpk, ymh, color);
2510 		    } else {
2511 			result |= pixelColorNolock (dst, xmk, y, color);
2512 			result |= pixelColorNolock (dst, xpk, y, color);
2513 		    }
2514 		    oh = h;
2515 		}
2516 
2517 		ix = ix + iy / ry;
2518 		iy = iy - ix / ry;
2519 
2520 	    } while (i > h);
2521 	}
2522 
2523     }				/* Alpha check */
2524 
2525     /* Unlock surface */
2526     if (SDL_MUSTLOCK(dst)) {
2527 	SDL_UnlockSurface(dst);
2528     }
2529 
2530     return (result);
2531 }
2532 
ellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2533 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2534 {
2535     /*
2536      * Draw
2537      */
2538     return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2539 }
2540 
2541 /* ----- AA Ellipse */
2542 
2543 /* Based on code from Anders Lindstroem, based on code from SGE, based on code from TwinLib */
2544 
aaellipseColor(SDL_Surface * dst,Sint16 xc,Sint16 yc,Sint16 rx,Sint16 ry,Uint32 color)2545 int aaellipseColor(SDL_Surface * dst, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
2546 {
2547     Sint16 left, right, top, bottom;
2548     Sint16 x1,y1,x2,y2;
2549     int i;
2550     int a2, b2, ds, dt, dxt, t, s, d;
2551     Sint16 x, y, xs, ys, dyt, xx, yy, xc2, yc2;
2552     float cp;
2553     Uint8 weight, iweight;
2554     int result;
2555 
2556     /*
2557      * Sanity check radii
2558      */
2559     if ((rx < 0) || (ry < 0)) {
2560 	return (-1);
2561     }
2562 
2563     /*
2564      * Special case for rx=0 - draw a vline
2565      */
2566     if (rx == 0) {
2567 	return (vlineColor(dst, xc, yc - ry, yc + ry, color));
2568     }
2569     /*
2570      * Special case for ry=0 - draw a hline
2571      */
2572     if (ry == 0) {
2573 	return (hlineColor(dst, xc - rx, xc + rx, yc, color));
2574     }
2575 
2576     /*
2577      * Get clipping boundary
2578      */
2579     left = dst->clip_rect.x;
2580     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2581     top = dst->clip_rect.y;
2582     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2583 
2584     /*
2585      * Test if bounding box of ellipse is visible
2586      */
2587     x1 = xc - rx;
2588     x2 = xc + rx;
2589     y1 = yc - ry;
2590     y2 = yc + ry;
2591     if ((x1<left) && (x2<left)) {
2592      return(0);
2593     }
2594     if ((x1>right) && (x2>right)) {
2595      return(0);
2596     }
2597     if ((y1<top) && (y2<top)) {
2598      return(0);
2599     }
2600     if ((y1>bottom) && (y2>bottom)) {
2601      return(0);
2602     }
2603 
2604     /* Variable setup */
2605     a2 = rx * rx;
2606     b2 = ry * ry;
2607 
2608     ds = 2 * a2;
2609     dt = 2 * b2;
2610 
2611     xc2 = 2 * xc;
2612     yc2 = 2 * yc;
2613 
2614     dxt = (int) (a2 / sqrt(a2 + b2));
2615 
2616     t = 0;
2617     s = -2 * a2 * ry;
2618     d = 0;
2619 
2620     x = xc;
2621     y = yc - ry;
2622 
2623     /* Draw */
2624     result = 0;
2625 
2626     /* Lock surface */
2627     if (SDL_MUSTLOCK(dst)) {
2628 	if (SDL_LockSurface(dst) < 0) {
2629 	    return (-1);
2630 	}
2631     }
2632 
2633     /* "End points" */
2634     result |= pixelColorNolock(dst, x, y, color);
2635     result |= pixelColorNolock(dst, xc2 - x, y, color);
2636     result |= pixelColorNolock(dst, x, yc2 - y, color);
2637     result |= pixelColorNolock(dst, xc2 - x, yc2 - y, color);
2638 
2639     for (i = 1; i <= dxt; i++) {
2640 	x--;
2641 	d += t - b2;
2642 
2643 	if (d >= 0)
2644 	    ys = y - 1;
2645 	else if ((d - s - a2) > 0) {
2646 	    if ((2 * d - s - a2) >= 0)
2647 		ys = y + 1;
2648 	    else {
2649 		ys = y;
2650 		y++;
2651 		d -= s + a2;
2652 		s += ds;
2653 	    }
2654 	} else {
2655 	    y++;
2656 	    ys = y + 1;
2657 	    d -= s + a2;
2658 	    s += ds;
2659 	}
2660 
2661 	t -= dt;
2662 
2663 	/* Calculate alpha */
2664 	if (s != 0.0) {
2665 	    cp = (float) abs(d) / (float) abs(s);
2666 	    if (cp > 1.0) {
2667 		cp = 1.0;
2668 	    }
2669 	} else {
2670 	    cp = 1.0;
2671 	}
2672 
2673 	/* Calculate weights */
2674 	weight = (Uint8) (cp * 255);
2675 	iweight = 255 - weight;
2676 
2677 	/* Upper half */
2678 	xx = xc2 - x;
2679 	result |= pixelColorWeightNolock(dst, x, y, color, iweight);
2680 	result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
2681 
2682 	result |= pixelColorWeightNolock(dst, x, ys, color, weight);
2683 	result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
2684 
2685 	/* Lower half */
2686 	yy = yc2 - y;
2687 	result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
2688 	result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
2689 
2690 	yy = yc2 - ys;
2691 	result |= pixelColorWeightNolock(dst, x, yy, color, weight);
2692 	result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
2693     }
2694 
2695     dyt = abs(y - yc);
2696 
2697     for (i = 1; i <= dyt; i++) {
2698 	y++;
2699 	d -= s + a2;
2700 
2701 	if (d <= 0)
2702 	    xs = x + 1;
2703 	else if ((d + t - b2) < 0) {
2704 	    if ((2 * d + t - b2) <= 0)
2705 		xs = x - 1;
2706 	    else {
2707 		xs = x;
2708 		x--;
2709 		d += t - b2;
2710 		t -= dt;
2711 	    }
2712 	} else {
2713 	    x--;
2714 	    xs = x - 1;
2715 	    d += t - b2;
2716 	    t -= dt;
2717 	}
2718 
2719 	s += ds;
2720 
2721 	/* Calculate alpha */
2722 	if (t != 0.0) {
2723 	    cp = (float) abs(d) / (float) abs(t);
2724 	    if (cp > 1.0) {
2725 		cp = 1.0;
2726 	    }
2727 	} else {
2728 	    cp = 1.0;
2729 	}
2730 
2731 	/* Calculate weight */
2732 	weight = (Uint8) (cp * 255);
2733 	iweight = 255 - weight;
2734 
2735 	/* Left half */
2736 	xx = xc2 - x;
2737 	yy = yc2 - y;
2738 	result |= pixelColorWeightNolock(dst, x, y, color, iweight);
2739 	result |= pixelColorWeightNolock(dst, xx, y, color, iweight);
2740 
2741 	result |= pixelColorWeightNolock(dst, x, yy, color, iweight);
2742 	result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
2743 
2744 	/* Right half */
2745 	xx = 2 * xc - xs;
2746 	result |= pixelColorWeightNolock(dst, xs, y, color, weight);
2747 	result |= pixelColorWeightNolock(dst, xx, y, color, weight);
2748 
2749 	result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
2750 	result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
2751 
2752 
2753     }
2754 
2755     /* Unlock surface */
2756     if (SDL_MUSTLOCK(dst)) {
2757 	SDL_UnlockSurface(dst);
2758     }
2759 
2760     return (result);
2761 }
2762 
aaellipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2763 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2764 {
2765     /*
2766      * Draw
2767      */
2768     return (aaellipseColor
2769 	    (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2770 }
2771 
2772 /* ---- Filled Ellipse */
2773 
2774 /* Note: */
2775 /* Based on algorithm from sge library with multiple-hline draw removal */
2776 /* and other speedup changes. */
2777 
filledEllipseColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint32 color)2778 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2779 {
2780     Sint16 left, right, top, bottom;
2781     int result;
2782     Sint16 x1, y1, x2, y2;
2783     int ix, iy;
2784     int h, i, j, k;
2785     int oh, oi, oj, ok;
2786     int xmh, xph;
2787     int xmi, xpi;
2788     int xmj, xpj;
2789     int xmk, xpk;
2790 
2791     /*
2792      * Sanity check radii
2793      */
2794     if ((rx < 0) || (ry < 0)) {
2795 	return (-1);
2796     }
2797 
2798     /*
2799      * Special case for rx=0 - draw a vline
2800      */
2801     if (rx == 0) {
2802 	return (vlineColor(dst, x, y - ry, y + ry, color));
2803     }
2804     /*
2805      * Special case for ry=0 - draw a hline
2806      */
2807     if (ry == 0) {
2808 	return (hlineColor(dst, x - rx, x + rx, y, color));
2809     }
2810 
2811     /*
2812      * Get clipping boundary
2813      */
2814     left = dst->clip_rect.x;
2815     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2816     top = dst->clip_rect.y;
2817     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2818 
2819     /*
2820      * Test if bounding box of ellipse is visible
2821      */
2822     x1 = x - rx;
2823     x2 = x + rx;
2824     y1 = y - ry;
2825     y2 = y + ry;
2826     if ((x1<left) && (x2<left)) {
2827      return(0);
2828     }
2829     if ((x1>right) && (x2>right)) {
2830      return(0);
2831     }
2832     if ((y1<top) && (y2<top)) {
2833      return(0);
2834     }
2835     if ((y1>bottom) && (y2>bottom)) {
2836      return(0);
2837     }
2838 
2839     /*
2840      * Init vars
2841      */
2842     oh = oi = oj = ok = 0xFFFF;
2843 
2844     /*
2845      * Draw
2846      */
2847     result = 0;
2848     if (rx > ry) {
2849 	ix = 0;
2850 	iy = rx * 64;
2851 
2852 	do {
2853 	    h = (ix + 32) >> 6;
2854 	    i = (iy + 32) >> 6;
2855 	    j = (h * ry) / rx;
2856 	    k = (i * ry) / rx;
2857 
2858 	    if ((ok != k) && (oj != k)) {
2859 		xph = x + h;
2860 		xmh = x - h;
2861 		if (k > 0) {
2862 		    result |= hlineColor(dst, xmh, xph, y + k, color);
2863 		    result |= hlineColor(dst, xmh, xph, y - k, color);
2864 		} else {
2865 		    result |= hlineColor(dst, xmh, xph, y, color);
2866 		}
2867 		ok = k;
2868 	    }
2869 	    if ((oj != j) && (ok != j) && (k != j)) {
2870 		xmi = x - i;
2871 		xpi = x + i;
2872 		if (j > 0) {
2873 		    result |= hlineColor(dst, xmi, xpi, y + j, color);
2874 		    result |= hlineColor(dst, xmi, xpi, y - j, color);
2875 		} else {
2876 		    result |= hlineColor(dst, xmi, xpi, y, color);
2877 		}
2878 		oj = j;
2879 	    }
2880 
2881 	    ix = ix + iy / rx;
2882 	    iy = iy - ix / rx;
2883 
2884 	} while (i > h);
2885     } else {
2886 	ix = 0;
2887 	iy = ry * 64;
2888 
2889 	do {
2890 	    h = (ix + 32) >> 6;
2891 	    i = (iy + 32) >> 6;
2892 	    j = (h * rx) / ry;
2893 	    k = (i * rx) / ry;
2894 
2895 	    if ((oi != i) && (oh != i)) {
2896 		xmj = x - j;
2897 		xpj = x + j;
2898 		if (i > 0) {
2899 		    result |= hlineColor(dst, xmj, xpj, y + i, color);
2900 		    result |= hlineColor(dst, xmj, xpj, y - i, color);
2901 		} else {
2902 		    result |= hlineColor(dst, xmj, xpj, y, color);
2903 		}
2904 		oi = i;
2905 	    }
2906 	    if ((oh != h) && (oi != h) && (i != h)) {
2907 		xmk = x - k;
2908 		xpk = x + k;
2909 		if (h > 0) {
2910 		    result |= hlineColor(dst, xmk, xpk, y + h, color);
2911 		    result |= hlineColor(dst, xmk, xpk, y - h, color);
2912 		} else {
2913 		    result |= hlineColor(dst, xmk, xpk, y, color);
2914 		}
2915 		oh = h;
2916 	    }
2917 
2918 	    ix = ix + iy / ry;
2919 	    iy = iy - ix / ry;
2920 
2921 	} while (i > h);
2922     }
2923 
2924     return (result);
2925 }
2926 
2927 
filledEllipseRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rx,Sint16 ry,Uint8 r,Uint8 g,Uint8 b,Uint8 a)2928 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2929 {
2930     /*
2931      * Draw
2932      */
2933     return (filledEllipseColor
2934 	    (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2935 }
2936 
2937 /* ----- filled pie */
2938 
2939 /* Low-speed float pie-calc implementation by drawing polygons. */
2940 
filledpieColor(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint32 color)2941 int filledpieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
2942 {
2943     Sint16 left, right, top, bottom;
2944     Sint16 x1, y1, x2, y2;
2945     int result;
2946     double angle, start_angle, end_angle;
2947     double deltaAngle;
2948     double dr;
2949     int posX, posY;
2950     int numpoints, i;
2951     Sint16 *vx, *vy;
2952 
2953     /*
2954      * Sanity check radii
2955      */
2956     if (rad < 0) {
2957 	return (-1);
2958     }
2959 
2960     /*
2961      * Fixup angles
2962      */
2963     start = start % 360;
2964     end = end % 360;
2965 
2966     /*
2967      * Special case for rad=0 - draw a point
2968      */
2969     if (rad == 0) {
2970 	return (pixelColor(dst, x, y, color));
2971     }
2972 
2973     /*
2974      * Get clipping boundary
2975      */
2976     left = dst->clip_rect.x;
2977     right = dst->clip_rect.x + dst->clip_rect.w - 1;
2978     top = dst->clip_rect.y;
2979     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2980 
2981     /*
2982      * Test if bounding box of pie's circle is visible
2983      */
2984     x1 = x - rad;
2985     x2 = x + rad;
2986     y1 = y - rad;
2987     y2 = y + rad;
2988     if ((x1<left) && (x2<left)) {
2989      return(0);
2990     }
2991     if ((x1>right) && (x2>right)) {
2992      return(0);
2993     }
2994     if ((y1<top) && (y2<top)) {
2995      return(0);
2996     }
2997     if ((y1>bottom) && (y2>bottom)) {
2998      return(0);
2999     }
3000 
3001     /*
3002      * Variable setup
3003      */
3004     dr = (double) rad;
3005     deltaAngle = 3.0 / dr;
3006     start_angle = (double) start *(2.0 * M_PI / 360.0);
3007     end_angle = (double) end *(2.0 * M_PI / 360.0);
3008     if (start > end) {
3009 	end_angle += (2.0 * M_PI);
3010     }
3011 
3012     /* Count points (rather than calculate it) */
3013     numpoints = 1;
3014     angle = start_angle;
3015     while (angle <= end_angle) {
3016 	angle += deltaAngle;
3017 	numpoints++;
3018     }
3019 
3020     /* Check size of array */
3021     if (numpoints == 1) {
3022 	return (pixelColor(dst, x, y, color));
3023     } else if (numpoints == 2) {
3024 	posX = x + (int) (dr * cos(start_angle));
3025 	posY = y + (int) (dr * sin(start_angle));
3026 	return (lineColor(dst, x, y, posX, posY, color));
3027     }
3028 
3029     /* Allocate vertex array */
3030     vx = vy = (Uint16 *) malloc(2 * sizeof(Uint16) * numpoints);
3031     if (vx == NULL) {
3032 	return (-1);
3033     }
3034     vy += numpoints;
3035 
3036     /* Center */
3037     vx[0] = x;
3038     vy[0] = y;
3039 
3040     /* Calculate and store vertices */
3041     i = 1;
3042     angle = start_angle;
3043     while (angle <= end_angle) {
3044 	vx[i] = x + (int) (dr * cos(angle));
3045 	vy[i] = y + (int) (dr * sin(angle));
3046 	angle += deltaAngle;
3047 	i++;
3048     }
3049 
3050     /* Draw */
3051     result = filledPolygonColor(dst, vx, vy, numpoints, color);
3052 
3053     /* Free vertex array */
3054     free(vx);
3055 
3056     return (result);
3057 }
3058 
filledpieRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,Sint16 rad,Sint16 start,Sint16 end,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3059 int filledpieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
3060 		  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3061 {
3062     return (filledpieColor(dst, x, y, rad, start, end,
3063 			   ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3064 
3065 }
3066 
3067 
3068 /* Trigon */
3069 
trigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)3070 int trigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
3071 {
3072  Sint16 vx[3];
3073  Sint16 vy[3];
3074 
3075  vx[0]=x1;
3076  vx[1]=x2;
3077  vx[2]=x3;
3078  vy[0]=y1;
3079  vy[1]=y2;
3080  vy[2]=y3;
3081 
3082  return(polygonColor(dst,vx,vy,3,color));
3083 }
3084 
trigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3085 int trigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3086 				 Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3087 {
3088  Sint16 vx[3];
3089  Sint16 vy[3];
3090 
3091  vx[0]=x1;
3092  vx[1]=x2;
3093  vx[2]=x3;
3094  vy[0]=y1;
3095  vy[1]=y2;
3096  vy[2]=y3;
3097 
3098  return(polygonRGBA(dst,vx,vy,3,r,g,b,a));
3099 }
3100 
3101 /* AA-Trigon */
3102 
aatrigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint32 color)3103 int aatrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
3104 {
3105  Sint16 vx[3];
3106  Sint16 vy[3];
3107 
3108  vx[0]=x1;
3109  vx[1]=x2;
3110  vx[2]=x3;
3111  vy[0]=y1;
3112  vy[1]=y2;
3113  vy[2]=y3;
3114 
3115  return(aapolygonColor(dst,vx,vy,3,color));
3116 }
3117 
aatrigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3118 int aatrigonRGBA(SDL_Surface * dst,  Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3119 				   Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3120 {
3121  Sint16 vx[3];
3122  Sint16 vy[3];
3123 
3124  vx[0]=x1;
3125  vx[1]=x2;
3126  vx[2]=x3;
3127  vy[0]=y1;
3128  vy[1]=y2;
3129  vy[2]=y3;
3130 
3131  return(aapolygonRGBA(dst,vx,vy,3,r,g,b,a));
3132 }
3133 
3134 /* Filled Trigon */
3135 
filledTrigonColor(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,int color)3136 int filledTrigonColor(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, int color)
3137 {
3138  Sint16 vx[3];
3139  Sint16 vy[3];
3140 
3141  vx[0]=x1;
3142  vx[1]=x2;
3143  vx[2]=x3;
3144  vy[0]=y1;
3145  vy[1]=y2;
3146  vy[2]=y3;
3147 
3148  return(filledPolygonColor(dst,vx,vy,3,color));
3149 }
3150 
filledTrigonRGBA(SDL_Surface * dst,Sint16 x1,Sint16 y1,Sint16 x2,Sint16 y2,Sint16 x3,Sint16 y3,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3151 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
3152 				       Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3153 {
3154  Sint16 vx[3];
3155  Sint16 vy[3];
3156 
3157  vx[0]=x1;
3158  vx[1]=x2;
3159  vx[2]=x3;
3160  vy[0]=y1;
3161  vy[1]=y2;
3162  vy[2]=y3;
3163 
3164  return(filledPolygonRGBA(dst,vx,vy,3,r,g,b,a));
3165 }
3166 
3167 /* ---- Polygon */
3168 
polygonColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint32 color)3169 int polygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color)
3170 {
3171     int result;
3172     int i;
3173     Sint16 *x1, *y1, *x2, *y2;
3174 
3175     /*
3176      * Sanity check
3177      */
3178     if (n < 3) {
3179 	return (-1);
3180     }
3181 
3182     /*
3183      * Pointer setup
3184      */
3185     x1 = x2 = vx;
3186     y1 = y2 = vy;
3187     x2++;
3188     y2++;
3189 
3190     /*
3191      * Draw
3192      */
3193     result = 0;
3194     for (i = 1; i < n; i++) {
3195 	result |= lineColor(dst, *x1, *y1, *x2, *y2, color);
3196 	x1 = x2;
3197 	y1 = y2;
3198 	x2++;
3199 	y2++;
3200     }
3201     result |= lineColor(dst, *x1, *y1, *vx, *vy, color);
3202 
3203     return (result);
3204 }
3205 
polygonRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3206 int polygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3207 {
3208     /*
3209      * Draw
3210      */
3211     return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3212 }
3213 
3214 /* ---- AA-Polygon */
3215 
aapolygonColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint32 color)3216 int aapolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint32 color)
3217 {
3218     int result;
3219     int i;
3220     Sint16 *x1, *y1, *x2, *y2;
3221 
3222     /*
3223      * Sanity check
3224      */
3225     if (n < 3) {
3226 	return (-1);
3227     }
3228 
3229     /*
3230      * Pointer setup
3231      */
3232     x1 = x2 = vx;
3233     y1 = y2 = vy;
3234     x2++;
3235     y2++;
3236 
3237     /*
3238      * Draw
3239      */
3240     result = 0;
3241     for (i = 1; i < n; i++) {
3242 	result |= aalineColorInt(dst, *x1, *y1, *x2, *y2, color, 0);
3243 	x1 = x2;
3244 	y1 = y2;
3245 	x2++;
3246 	y2++;
3247     }
3248     result |= aalineColorInt(dst, *x1, *y1, *vx, *vy, color, 0);
3249 
3250     return (result);
3251 }
3252 
aapolygonRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3253 int aapolygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3254 {
3255     /*
3256      * Draw
3257      */
3258     return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3259 }
3260 
3261 /* ---- Filled Polygon */
3262 
3263 int gfxPrimitivesCompareInt(const void *a, const void *b);
3264 
3265 static int *gfxPrimitivesPolyInts = NULL;
3266 static int gfxPrimitivesPolyAllocated = 0;
3267 
filledPolygonColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,int color)3268 int filledPolygonColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int color)
3269 {
3270     int result;
3271     int i;
3272     int y;
3273     int miny, maxy;
3274     int x1, y1;
3275     int x2, y2;
3276     int ind1, ind2;
3277     int ints;
3278 
3279     /*
3280      * Sanity check
3281      */
3282     if (n < 3) {
3283 	return -1;
3284     }
3285 
3286     /*
3287      * Allocate temp array, only grow array
3288      */
3289     if (!gfxPrimitivesPolyAllocated) {
3290 	gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3291 	gfxPrimitivesPolyAllocated = n;
3292     } else {
3293 	if (gfxPrimitivesPolyAllocated < n) {
3294 	    gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3295 	    gfxPrimitivesPolyAllocated = n;
3296 	}
3297     }
3298 
3299     /*
3300      * Determine Y maxima
3301      */
3302     miny = vy[0];
3303     maxy = vy[0];
3304     for (i = 1; (i < n); i++) {
3305 	if (vy[i] < miny) {
3306 	    miny = vy[i];
3307 	} else if (vy[i] > maxy) {
3308 	    maxy = vy[i];
3309 	}
3310     }
3311 
3312     /*
3313      * Draw, scanning y
3314      */
3315     result = 0;
3316     for (y = miny; (y <= maxy); y++) {
3317 	ints = 0;
3318 	for (i = 0; (i < n); i++) {
3319 	    if (!i) {
3320 		ind1 = n - 1;
3321 		ind2 = 0;
3322 	    } else {
3323 		ind1 = i - 1;
3324 		ind2 = i;
3325 	    }
3326 	    y1 = vy[ind1];
3327 	    y2 = vy[ind2];
3328 	    if (y1 < y2) {
3329 		x1 = vx[ind1];
3330 		x2 = vx[ind2];
3331 	    } else if (y1 > y2) {
3332 		y2 = vy[ind1];
3333 		y1 = vy[ind2];
3334 		x2 = vx[ind1];
3335 		x1 = vx[ind2];
3336 	    } else {
3337 		continue;
3338 	    }
3339 	    if ((y >= y1) && (y < y2)) {
3340 		gfxPrimitivesPolyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
3341 	    } else if ((y == maxy) && (y > y1) && (y <= y2)) {
3342 		gfxPrimitivesPolyInts[ints++] = (y - y1) * (x2 - x1) / (y2 - y1) + x1;
3343 	    }
3344 	}
3345 	qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
3346 
3347 	for (i = 0; (i < ints); i += 2) {
3348 	    result |= hlineColor(dst, gfxPrimitivesPolyInts[i], gfxPrimitivesPolyInts[i + 1], y, color);
3349 	}
3350     }
3351 
3352     return (result);
3353 }
3354 
filledPolygonRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3355 int filledPolygonRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3356 {
3357     /*
3358      * Draw
3359      */
3360     return (filledPolygonColor
3361 	    (dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3362 }
3363 
gfxPrimitivesCompareInt(const void * a,const void * b)3364 int gfxPrimitivesCompareInt(const void *a, const void *b)
3365 {
3366     return (*(const int *) a) - (*(const int *) b);
3367 }
3368 
3369 /* ---- Character (8x8 internal font) */
3370 
3371 static SDL_Surface *gfxPrimitivesFont[256];
3372 static Uint32 gfxPrimitivesFontColor[256];
3373 
characterColor(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint32 color)3374 int characterColor(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint32 color)
3375 {
3376     Sint16 left, right, top, bottom;
3377     Sint16 x1, y1, x2, y2;
3378     SDL_Rect srect;
3379     SDL_Rect drect;
3380     int result;
3381     int ix, iy, k;
3382     unsigned char *charpos;
3383     unsigned char bits[8] = { 128, 64, 32, 16, 8, 4, 2, 1 };
3384     unsigned char *bitpos;
3385     Uint8 *curpos;
3386     int forced_redraw;
3387 
3388     /*
3389      * Get clipping boundary
3390      */
3391     left = dst->clip_rect.x;
3392     right = dst->clip_rect.x + dst->clip_rect.w - 1;
3393     top = dst->clip_rect.y;
3394     bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3395 
3396     /*
3397      * Test if bounding box of character is visible
3398      */
3399     x1 = x;
3400     x2 = x + 8;
3401     y1 = y;
3402     y2 = y + 8;
3403     if ((x1<left) && (x2<left)) {
3404      return(0);
3405     }
3406     if ((x1>right) && (x2>right)) {
3407      return(0);
3408     }
3409     if ((y1<top) && (y2<top)) {
3410      return(0);
3411     }
3412     if ((y1>bottom) && (y2>bottom)) {
3413      return(0);
3414     }
3415 
3416     /*
3417      * Setup source rectangle for 8x8 bitmap
3418      */
3419     srect.x = 0;
3420     srect.y = 0;
3421     srect.w = 8;
3422     srect.h = 8;
3423 
3424     /*
3425      * Setup destination rectangle for 8x8 bitmap
3426      */
3427     drect.x = x;
3428     drect.y = y;
3429     drect.w = 8;
3430     drect.h = 8;
3431 
3432     /*
3433      * Create new 8x8 bitmap surface if not already present
3434      */
3435     if (gfxPrimitivesFont[(unsigned char) c] == NULL) {
3436 	gfxPrimitivesFont[(unsigned char) c] =
3437 	    SDL_CreateRGBSurface(SDL_SWSURFACE | SDL_HWSURFACE | SDL_SRCALPHA, 8, 8,
3438 				 32, 0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
3439 	/*
3440 	 * Check pointer
3441 	 */
3442 	if (gfxPrimitivesFont[(unsigned char) c] == NULL) {
3443 	    return (-1);
3444 	}
3445 	/*
3446 	 * Definitely redraw
3447 	 */
3448 	forced_redraw = 1;
3449     } else {
3450 	forced_redraw = 0;
3451     }
3452 
3453     /*
3454      * Check if color has changed
3455      */
3456     if ((gfxPrimitivesFontColor[(unsigned char) c] != color) || (forced_redraw)) {
3457 	/*
3458 	 * Redraw character
3459 	 */
3460 	SDL_SetAlpha(gfxPrimitivesFont[(unsigned char) c], SDL_SRCALPHA, 255);
3461 	gfxPrimitivesFontColor[(unsigned char) c] = color;
3462 
3463 	/*
3464 	 * Variable setup
3465 	 */
3466 	k = (unsigned char) c;
3467 	k *= 8;
3468 	charpos = gfxPrimitivesFontdata;
3469 	charpos += k;
3470 
3471 	/*
3472 	 * Clear bitmap
3473 	 */
3474 	curpos = (Uint8 *) gfxPrimitivesFont[(unsigned char) c]->pixels;
3475 	memset(curpos, 0, 8 * 8 * 4);
3476 
3477 	/*
3478 	 * Drawing loop
3479 	 */
3480 	for (iy = 0; iy < 8; iy++) {
3481 	    bitpos = bits;
3482 	    for (ix = 0; ix < 8; ix++) {
3483 		if ((*charpos & *bitpos) == *bitpos) {
3484 		    memcpy(curpos, &color, 4);
3485 		}
3486 		bitpos++;
3487 		curpos += 4;;
3488 	    }
3489 	    charpos++;
3490 	}
3491     }
3492 
3493     /*
3494      * Draw bitmap onto destination surface
3495      */
3496     result = SDL_BlitSurface(gfxPrimitivesFont[(unsigned char) c], &srect, dst, &drect);
3497 
3498     return (result);
3499 }
3500 
characterRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,char c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3501 int characterRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3502 {
3503     /*
3504      * Draw
3505      */
3506     return (characterColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3507 }
3508 
stringColor(SDL_Surface * dst,Sint16 x,Sint16 y,char * c,Uint32 color)3509 int stringColor(SDL_Surface * dst, Sint16 x, Sint16 y, char *c, Uint32 color)
3510 {
3511     int result;
3512     int i, length;
3513     char *curchar;
3514     int curx;
3515 
3516     length = strlen(c);
3517     curchar = c;
3518     curx = x;
3519     result = 0;
3520     for (i = 0; i < length; i++) {
3521 	result |= characterColor(dst, curx, y, *curchar, color);
3522 	curchar++;
3523 	curx += 8;
3524     }
3525 
3526     return (result);
3527 }
3528 
stringRGBA(SDL_Surface * dst,Sint16 x,Sint16 y,char * c,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3529 int stringRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, char *c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3530 {
3531     /*
3532      * Draw
3533      */
3534     return (stringColor(dst, x, y, c, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3535 }
3536 
3537 /* ---- Bezier curve */
3538 
3539 /*
3540  Calculate bezier interpolator of data array with ndata values at position 't'
3541 */
3542 
evaluateBezier(double * data,int ndata,double t)3543 double evaluateBezier (double *data, int ndata, double t)
3544 {
3545  double mu, result;
3546  int n,k,kn,nn,nkn;
3547  double blend,muk,munk;
3548 
3549  /* Sanity check bounds */
3550  if (t<0.0) {
3551   return(data[0]);
3552  }
3553  if (t>=(double)ndata) {
3554   return(data[ndata-1]);
3555  }
3556 
3557  /* Adjust t to the range 0.0 to 1.0 */
3558  mu=t/(double)ndata;
3559 
3560  /* Calculate interpolate */
3561  n=ndata-1;
3562  result=0.0;
3563  muk = 1;
3564  munk = pow(1-mu,(double)n);
3565  for (k=0;k<=n;k++) {
3566   nn = n;
3567   kn = k;
3568   nkn = n - k;
3569   blend = muk * munk;
3570   muk *= mu;
3571   munk /= (1-mu);
3572   while (nn >= 1) {
3573    blend *= nn;
3574    nn--;
3575    if (kn > 1) {
3576     blend /= (double)kn;
3577     kn--;
3578    }
3579    if (nkn > 1) {
3580     blend /= (double)nkn;
3581     nkn--;
3582    }
3583   }
3584   result += data[k] * blend;
3585  }
3586 
3587  return(result);
3588 }
3589 
bezierColor(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,int s,Uint32 color)3590 int bezierColor(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int s, Uint32 color)
3591 {
3592     int result;
3593     int i;
3594     double *x, *y, t, stepsize;
3595     Sint16 x1, y1, x2, y2;
3596 
3597     /*
3598      * Sanity check
3599      */
3600     if (n < 3) {
3601 	return (-1);
3602     }
3603     if (s < 2) {
3604         return (-1);
3605     }
3606 
3607     /*
3608      * Variable setup
3609      */
3610     stepsize=(double)1.0/(double)s;
3611 
3612     /* Transfer vertices into float arrays */
3613     if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3614      return(-1);
3615     }
3616     if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3617      free(x);
3618      return(-1);
3619     }
3620     for (i=0; i<n; i++) {
3621      x[i]=vx[i];
3622      y[i]=vy[i];
3623     }
3624     x[n]=vx[0];
3625     y[n]=vy[0];
3626 
3627     /*
3628      * Draw
3629      */
3630     result = 0;
3631     t=0.0;
3632     x1=evaluateBezier(x,n+1,t);
3633     y1=evaluateBezier(y,n+1,t);
3634     for (i = 0; i <= (n*s); i++) {
3635 	t += stepsize;
3636 	x2=(Sint16)evaluateBezier(x,n,t);
3637 	y2=(Sint16)evaluateBezier(y,n,t);
3638 	result |= lineColor(dst, x1, y1, x2, y2, color);
3639 	x1 = x2;
3640 	y1 = y2;
3641     }
3642 
3643     /* Clean up temporary array */
3644     free(x);
3645     free(y);
3646 
3647     return (result);
3648 }
3649 
bezierRGBA(SDL_Surface * dst,Sint16 * vx,Sint16 * vy,int n,int s,Uint8 r,Uint8 g,Uint8 b,Uint8 a)3650 int bezierRGBA(SDL_Surface * dst, Sint16 * vx, Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3651 {
3652     /*
3653      * Draw
3654      */
3655     return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3656 }
3657