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