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