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