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