/[zanavi_public1]/navit/navit/graphics/sdl/raster.c
ZANavi

Contents of /navit/navit/graphics/sdl/raster.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2 - (show annotations) (download)
Fri Oct 28 21:19:04 2011 UTC (12 years, 5 months ago) by zoff99
File MIME type: text/plain
File size: 43711 byte(s)
import files
1 /* raster.c -- line/rect/circle/poly rasterization
2
3 copyright (c) 2008 bryan rittmeyer <bryanr@bryanr.org>
4 license: LGPLv2
5
6 based on SDL_gfx (c) A. Schiffler
7 and SGE (c)1999-2003 Anders Lindström
8
9 + added filled anti-aliased polygons
10 + fixed some bugs and improved performance
11
12 revision history
13 2008-07-05 initial
14 2008-07-06 aacircle
15 */
16
17
18 #include <math.h>
19
20 #include "raster.h"
21
22 #undef DEBUG
23 #undef PARANOID
24
25
26 /* raster_rect */
27
28 static inline void raster_rect_inline(SDL_Surface *dst, int16_t x1, int16_t y1, int16_t w, int16_t h, uint32_t color)
29 {
30 /* sge */
31 SDL_Rect rect;
32
33 #if 1
34 if((w <= 0) || (h <= 0))
35 {
36 return;
37 }
38
39 #if 0
40 if(x1 < 0)
41 {
42 if((x1 + w) < 0)
43 {
44 return;
45 }
46 else
47 {
48 w = w + x1;
49 x1 = 0;
50 }
51 }
52 if(y1 < 0)
53 {
54 if((y1 + h) < 0)
55 {
56 return;
57 }
58 else
59 {
60 h = h + y1;
61 y1 = 0;
62 }
63 }
64
65 if(x1 + w >= dst->w)
66 {
67 w = dst->w - x1;
68 }
69 if(y1 + h >= dst->h)
70 {
71 h = dst->h - y1;
72 }
73 #endif
74
75 rect.x = x1;
76 rect.y = y1;
77 rect.w = w;
78 rect.h = h;
79
80 /* will clip internally */
81 SDL_FillRect(dst, &rect, color);
82
83 #else
84
85 x2 = x1 + w;
86 y2 = y1 + h;
87
88 /*
89 * Order coordinates to ensure that
90 * x1<=x2 and y1<=y2
91 */
92 if (x1 > x2) {
93 tmp = x1;
94 x1 = x2;
95 x2 = tmp;
96 }
97 if (y1 > y2) {
98 tmp = y1;
99 y1 = y2;
100 y2 = tmp;
101 }
102
103 /*
104 * Get clipping boundary and
105 * check visibility
106 */
107 left = dst->clip_rect.x;
108 if (x2<left) {
109 return(0);
110 }
111 right = dst->clip_rect.x + dst->clip_rect.w - 1;
112 if (x1>right) {
113 return(0);
114 }
115 top = dst->clip_rect.y;
116 if (y2<top) {
117 return(0);
118 }
119 bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
120 if (y1>bottom) {
121 return(0);
122 }
123
124 /* Clip all points */
125 if (x1<left) {
126 x1=left;
127 } else if (x1>right) {
128 x1=right;
129 }
130 if (x2<left) {
131 x2=left;
132 } else if (x2>right) {
133 x2=right;
134 }
135 if (y1<top) {
136 y1=top;
137 } else if (y1>bottom) {
138 y1=bottom;
139 }
140 if (y2<top) {
141 y2=top;
142 } else if (y2>bottom) {
143 y2=bottom;
144 }
145
146 #if 0
147 /*
148 * Test for special cases of straight line or single point
149 */
150 if (x1 == x2) {
151 if (y1 == y2) {
152 return (pixelColor(dst, x1, y1, color));
153 } else {
154 return (vlineColor(dst, x1, y1, y2, color));
155 }
156 }
157 if (y1 == y2) {
158 return (hlineColor(dst, x1, x2, y1, color));
159 }
160 #endif
161
162 /*
163 * Calculate width&height
164 */
165 w = x2 - x1;
166 h = y2 - y1;
167
168 /*
169 * No alpha-blending required
170 */
171
172 #if 0
173 /*
174 * Setup color
175 */
176 colorptr = (Uint8 *) & color;
177 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
178 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
179 } else {
180 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
181 }
182 #endif
183
184 /*
185 * Lock surface
186 */
187 SDL_LockSurface(dst);
188
189 /*
190 * More variable setup
191 */
192 dx = w;
193 dy = h;
194 pixx = dst->format->BytesPerPixel;
195 pixy = dst->pitch;
196 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
197 pixellast = pixel + pixx * dx + pixy * dy;
198 dx++;
199
200 /*
201 * Draw
202 */
203 switch (dst->format->BytesPerPixel) {
204 case 1:
205 for (; pixel <= pixellast; pixel += pixy) {
206 memset(pixel, (Uint8) color, dx);
207 }
208 break;
209 case 2:
210 pixy -= (pixx * dx);
211 for (; pixel <= pixellast; pixel += pixy) {
212 for (x = 0; x < dx; x++) {
213 *(Uint16*) pixel = color;
214 pixel += pixx;
215 }
216 }
217 break;
218 case 3:
219 pixy -= (pixx * dx);
220 for (; pixel <= pixellast; pixel += pixy) {
221 for (x = 0; x < dx; x++) {
222 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
223 pixel[0] = (color >> 16) & 0xff;
224 pixel[1] = (color >> 8) & 0xff;
225 pixel[2] = color & 0xff;
226 } else {
227 pixel[0] = color & 0xff;
228 pixel[1] = (color >> 8) & 0xff;
229 pixel[2] = (color >> 16) & 0xff;
230 }
231 pixel += pixx;
232 }
233 }
234 break;
235 default: /* case 4 */
236 pixy -= (pixx * dx);
237 for (; pixel <= pixellast; pixel += pixy) {
238 for (x = 0; x < dx; x++) {
239 *(Uint32 *) pixel = color;
240 pixel += pixx;
241 }
242 }
243 break;
244 }
245
246 /*
247 * Unlock surface
248 */
249 SDL_UnlockSurface(dst);
250
251 #endif
252 }
253
254 void raster_rect(SDL_Surface *s, int16_t x, int16_t y, int16_t w, int16_t h, uint32_t col)
255 {
256 raster_rect_inline(s, x, y, w, h, col);
257 }
258
259 #define raster_rect_inline raster_rect
260
261
262 /* raster :: pixel */
263
264 #define MODIFIED_ALPHA_PIXEL_ROUTINE
265
266
267 #define clip_xmin(surface) surface->clip_rect.x
268 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
269 #define clip_ymin(surface) surface->clip_rect.y
270 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
271
272
273 static void raster_PutPixel(SDL_Surface *surface, Sint16 x, Sint16 y, Uint32 color)
274 {
275 if(x>=clip_xmin(surface) && x<=clip_xmax(surface) && y>=clip_ymin(surface) && y<=clip_ymax(surface)){
276 switch (surface->format->BytesPerPixel) {
277 case 1: { /* Assuming 8-bpp */
278 *((Uint8 *)surface->pixels + y*surface->pitch + x) = color;
279 }
280 break;
281
282 case 2: { /* Probably 15-bpp or 16-bpp */
283 *((Uint16 *)surface->pixels + y*surface->pitch/2 + x) = color;
284 }
285 break;
286
287 case 3: { /* Slow 24-bpp mode, usually not used */
288 Uint8 *pix = (Uint8 *)surface->pixels + y * surface->pitch + x*3;
289
290 /* Gack - slow, but endian correct */
291 *(pix+surface->format->Rshift/8) = color>>surface->format->Rshift;
292 *(pix+surface->format->Gshift/8) = color>>surface->format->Gshift;
293 *(pix+surface->format->Bshift/8) = color>>surface->format->Bshift;
294 *(pix+surface->format->Ashift/8) = color>>surface->format->Ashift;
295 }
296 break;
297
298 case 4: { /* Probably 32-bpp */
299 *((Uint32 *)surface->pixels + y*surface->pitch/4 + x) = color;
300 }
301 break;
302 }
303 }
304 }
305
306 /* PutPixel routine with alpha blending, input color in destination format */
307
308 /* New, faster routine - default blending pixel */
309
310 static void raster_PutPixelAlpha(SDL_Surface * surface, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
311 {
312 /* sdl-gfx */
313 Uint32 Rmask = surface->format->Rmask, Gmask =
314 surface->format->Gmask, Bmask = surface->format->Bmask, Amask = surface->format->Amask;
315 Uint32 R = 0, G = 0, B = 0, A = 0;
316
317 if (x >= clip_xmin(surface) && x <= clip_xmax(surface)
318 && y >= clip_ymin(surface) && y <= clip_ymax(surface)) {
319
320 switch (surface->format->BytesPerPixel) {
321 case 1:{ /* Assuming 8-bpp */
322 if (alpha == 255) {
323 *((Uint8 *) surface->pixels + y * surface->pitch + x) = color;
324 } else {
325 Uint8 *pixel = (Uint8 *) surface->pixels + y * surface->pitch + x;
326
327 Uint8 dR = surface->format->palette->colors[*pixel].r;
328 Uint8 dG = surface->format->palette->colors[*pixel].g;
329 Uint8 dB = surface->format->palette->colors[*pixel].b;
330 Uint8 sR = surface->format->palette->colors[color].r;
331 Uint8 sG = surface->format->palette->colors[color].g;
332 Uint8 sB = surface->format->palette->colors[color].b;
333
334 dR = dR + ((sR - dR) * alpha >> 8);
335 dG = dG + ((sG - dG) * alpha >> 8);
336 dB = dB + ((sB - dB) * alpha >> 8);
337
338 *pixel = SDL_MapRGB(surface->format, dR, dG, dB);
339 }
340 }
341 break;
342
343 case 2:{ /* Probably 15-bpp or 16-bpp */
344 if (alpha == 255) {
345 *((Uint16 *) surface->pixels + y * surface->pitch / 2 + x) = color;
346 } else {
347 Uint16 *pixel = (Uint16 *) surface->pixels + y * surface->pitch / 2 + x;
348 Uint32 dc = *pixel;
349
350 R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
351 G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
352 B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
353 if (Amask)
354 A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
355
356 *pixel = R | G | B | A;
357 }
358 }
359 break;
360
361 case 3:{ /* Slow 24-bpp mode, usually not used */
362 Uint8 *pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
363 Uint8 rshift8 = surface->format->Rshift / 8;
364 Uint8 gshift8 = surface->format->Gshift / 8;
365 Uint8 bshift8 = surface->format->Bshift / 8;
366 Uint8 ashift8 = surface->format->Ashift / 8;
367
368
369 if (alpha == 255) {
370 *(pix + rshift8) = color >> surface->format->Rshift;
371 *(pix + gshift8) = color >> surface->format->Gshift;
372 *(pix + bshift8) = color >> surface->format->Bshift;
373 *(pix + ashift8) = color >> surface->format->Ashift;
374 } else {
375 Uint8 dR, dG, dB, dA = 0;
376 Uint8 sR, sG, sB, sA = 0;
377
378 pix = (Uint8 *) surface->pixels + y * surface->pitch + x * 3;
379
380 dR = *((pix) + rshift8);
381 dG = *((pix) + gshift8);
382 dB = *((pix) + bshift8);
383 dA = *((pix) + ashift8);
384
385 sR = (color >> surface->format->Rshift) & 0xff;
386 sG = (color >> surface->format->Gshift) & 0xff;
387 sB = (color >> surface->format->Bshift) & 0xff;
388 sA = (color >> surface->format->Ashift) & 0xff;
389
390 dR = dR + ((sR - dR) * alpha >> 8);
391 dG = dG + ((sG - dG) * alpha >> 8);
392 dB = dB + ((sB - dB) * alpha >> 8);
393 dA = dA + ((sA - dA) * alpha >> 8);
394
395 *((pix) + rshift8) = dR;
396 *((pix) + gshift8) = dG;
397 *((pix) + bshift8) = dB;
398 *((pix) + ashift8) = dA;
399 }
400 }
401 break;
402
403 #ifdef ORIGINAL_ALPHA_PIXEL_ROUTINE
404
405 case 4:{ /* Probably :-) 32-bpp */
406 if (alpha == 255) {
407 *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
408 } else {
409 Uint32 Rshift, Gshift, Bshift, Ashift;
410 Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
411 Uint32 dc = *pixel;
412
413 Rshift = surface->format->Rshift;
414 Gshift = surface->format->Gshift;
415 Bshift = surface->format->Bshift;
416 Ashift = surface->format->Ashift;
417
418 R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
419 G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
420 B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
421 if (Amask)
422 A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
423
424 *pixel = R | G | B | A;
425 }
426 }
427 break;
428 #endif
429
430 #ifdef MODIFIED_ALPHA_PIXEL_ROUTINE
431
432 case 4:{ /* Probably :-) 32-bpp */
433 if (alpha == 255) {
434 *((Uint32 *) surface->pixels + y * surface->pitch / 4 + x) = color;
435 } else {
436 Uint32 Rshift, Gshift, Bshift, Ashift;
437 Uint32 *pixel = (Uint32 *) surface->pixels + y * surface->pitch / 4 + x;
438 Uint32 dc = *pixel;
439 Uint32 dR = (color & Rmask), dG = (color & Gmask), dB = (color & Bmask);
440 Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
441 Uint32 aTmp;
442
443 Rshift = surface->format->Rshift;
444 Gshift = surface->format->Gshift;
445 Bshift = surface->format->Bshift;
446 Ashift = surface->format->Ashift;
447
448 preMultR = (alpha * (dR>>Rshift));
449 preMultG = (alpha * (dG>>Gshift));
450 preMultB = (alpha * (dB>>Bshift));
451
452 surfaceAlpha = ((dc & Amask) >> Ashift);
453 aTmp = (255 - alpha);
454 if ((A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 ))) {
455 aTmp *= surfaceAlpha;
456 R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
457 G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
458 B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
459 }
460 *pixel = R | G | B | (A << Ashift & Amask);
461
462 }
463 }
464 break;
465 #endif
466 }
467 }
468 }
469
470
471 /* FIXME: eliminate these 2 functions */
472
473 static int raster_pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
474 {
475 int result = 0;
476
477 #if 0
478 /*
479 * Setup color
480 */
481 alpha = color & 0x000000ff;
482 mcolor =
483 SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
484 (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
485 #endif
486
487 /*
488 * Draw
489 */
490 raster_PutPixel(dst, x, y, color);
491
492 return (result);
493 }
494
495
496 /* Pixel - using alpha weight on color for AA-drawing - no locking */
497
498 static int raster_pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
499 {
500 #if 0
501 Uint32 a;
502
503 /*
504 * Get alpha
505 */
506 a = (color & (Uint32) 0x000000ff);
507
508 /*
509 * Modify Alpha by weight
510 */
511 a = ((a * weight) >> 8);
512 #endif
513
514 raster_PutPixelAlpha(dst, x, y, color, weight);
515
516 return 0;
517 }
518
519
520 /* raster :: line */
521
522
523
524 static inline void raster_hline(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
525 {
526 #if 1
527 SDL_Rect l;
528
529 /* sge */
530 if(x1>x2){Sint16 tmp=x1; x1=x2; x2=tmp;}
531
532 l.x=x1; l.y=y; l.w=x2-x1+1; l.h=1;
533
534 SDL_FillRect(dst, &l, color);
535
536 #else
537 /* sdl_gfx */
538 Sint16 left, right, top, bottom;
539 Uint8 *pixel, *pixellast;
540 int dx;
541 int pixx, pixy;
542 Sint16 w;
543 Sint16 xtmp;
544 int result = -1;
545 #if 0
546 int i;
547 union
548 {
549 double d;
550 uint16_t col[4];
551 } doub;
552
553 for(i = 0; i < 4; i++)
554 {
555 doub.col[i] = color;
556 }
557 #endif
558
559 /*
560 * Check visibility of clipping rectangle
561 */
562 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
563 return(0);
564 }
565
566 /*
567 * Swap x1, x2 if required to ensure x1<=x2
568 */
569 if (x1 > x2) {
570 xtmp = x1;
571 x1 = x2;
572 x2 = xtmp;
573 }
574
575 /*
576 * Get clipping boundary and
577 * check visibility of hline
578 */
579 left = dst->clip_rect.x;
580 if (x2<left) {
581 return(0);
582 }
583 right = dst->clip_rect.x + dst->clip_rect.w - 1;
584 if (x1>right) {
585 return(0);
586 }
587 top = dst->clip_rect.y;
588 bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
589 if ((y<top) || (y>bottom)) {
590 return (0);
591 }
592
593 /*
594 * Clip x
595 */
596 if (x1 < left) {
597 x1 = left;
598 }
599 if (x2 > right) {
600 x2 = right;
601 }
602
603 /*
604 * Calculate width
605 */
606 w = x2 - x1;
607
608 #if 0
609 printf("raster_hline %d %d %d %d\n", x1, x2, y, w);
610 #endif
611
612 /*
613 * Lock surface
614 */
615 if (SDL_MUSTLOCK(dst)) {
616 SDL_LockSurface(dst);
617 }
618
619 /*
620 * More variable setup
621 */
622 dx = w;
623 pixx = dst->format->BytesPerPixel;
624 pixy = dst->pitch;
625 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
626
627 /*
628 * Draw
629 */
630 switch (dst->format->BytesPerPixel) {
631 case 1:
632 memset(pixel, color, dx);
633 break;
634 case 2:
635 pixellast = pixel + dx + dx;
636 #if 0
637 for (; (pixel+3) <= pixellast; pixel += 4*pixx)
638 {
639 *(double *)pixel = doub.d;
640 }
641 #endif
642 for (; pixel <= pixellast; pixel += pixx) {
643 *(Uint16 *) pixel = color;
644 }
645 break;
646 case 3:
647 pixellast = pixel + dx + dx + dx;
648 for (; pixel <= pixellast; pixel += pixx) {
649 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
650 pixel[0] = (color >> 16) & 0xff;
651 pixel[1] = (color >> 8) & 0xff;
652 pixel[2] = color & 0xff;
653 } else {
654 pixel[0] = color & 0xff;
655 pixel[1] = (color >> 8) & 0xff;
656 pixel[2] = (color >> 16) & 0xff;
657 }
658 }
659 break;
660 default: /* case 4 */
661 dx = dx + dx;
662 pixellast = pixel + dx + dx;
663 for (; pixel <= pixellast; pixel += pixx) {
664 *(Uint32 *) pixel = color;
665 }
666 break;
667 }
668
669 /*
670 * Unlock surface
671 */
672 if (SDL_MUSTLOCK(dst)) {
673 SDL_UnlockSurface(dst);
674 }
675
676 /*
677 * Set result code
678 */
679 result = 0;
680
681 return (result);
682 #endif
683 }
684
685 static void raster_vline(SDL_Surface *dst, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
686 {
687 SDL_Rect l;
688
689 if(y1>y2){Sint16 tmp=y1; y1=y2; y2=tmp;}
690
691 l.x=x; l.y=y1; l.w=1; l.h=y2-y1+1;
692
693 SDL_FillRect(dst, &l, color);
694 }
695
696
697
698 /* raster_line */
699 #define CLIP_LEFT_EDGE 0x1
700 #define CLIP_RIGHT_EDGE 0x2
701 #define CLIP_BOTTOM_EDGE 0x4
702 #define CLIP_TOP_EDGE 0x8
703 #define CLIP_INSIDE(a) (!a)
704 #define CLIP_REJECT(a,b) (a&b)
705 #define CLIP_ACCEPT(a,b) (!(a|b))
706
707 static int clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
708 {
709 int code = 0;
710
711 if (x < left) {
712 code |= CLIP_LEFT_EDGE;
713 } else if (x > right) {
714 code |= CLIP_RIGHT_EDGE;
715 }
716 if (y < top) {
717 code |= CLIP_TOP_EDGE;
718 } else if (y > bottom) {
719 code |= CLIP_BOTTOM_EDGE;
720 }
721 return code;
722 }
723
724 static int clipLine(SDL_Surface * dst, Sint16 * x1, Sint16 * y1, Sint16 * x2, Sint16 * y2)
725 {
726 Sint16 left, right, top, bottom;
727 int code1, code2;
728 int draw = 0;
729 Sint16 swaptmp;
730 float m;
731
732 /*
733 * Get clipping boundary
734 */
735 left = dst->clip_rect.x;
736 right = dst->clip_rect.x + dst->clip_rect.w - 1;
737 top = dst->clip_rect.y;
738 bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
739
740 while (1) {
741 code1 = clipEncode(*x1, *y1, left, top, right, bottom);
742 code2 = clipEncode(*x2, *y2, left, top, right, bottom);
743 if (CLIP_ACCEPT(code1, code2)) {
744 draw = 1;
745 break;
746 } else if (CLIP_REJECT(code1, code2))
747 break;
748 else {
749 if (CLIP_INSIDE(code1)) {
750 swaptmp = *x2;
751 *x2 = *x1;
752 *x1 = swaptmp;
753 swaptmp = *y2;
754 *y2 = *y1;
755 *y1 = swaptmp;
756 swaptmp = code2;
757 code2 = code1;
758 code1 = swaptmp;
759 }
760 if (*x2 != *x1) {
761 m = (*y2 - *y1) / (float) (*x2 - *x1);
762 } else {
763 m = 1.0f;
764 }
765 if (code1 & CLIP_LEFT_EDGE) {
766 *y1 += (Sint16) ((left - *x1) * m);
767 *x1 = left;
768 } else if (code1 & CLIP_RIGHT_EDGE) {
769 *y1 += (Sint16) ((right - *x1) * m);
770 *x1 = right;
771 } else if (code1 & CLIP_BOTTOM_EDGE) {
772 if (*x2 != *x1) {
773 *x1 += (Sint16) ((bottom - *y1) / m);
774 }
775 *y1 = bottom;
776 } else if (code1 & CLIP_TOP_EDGE) {
777 if (*x2 != *x1) {
778 *x1 += (Sint16) ((top - *y1) / m);
779 }
780 *y1 = top;
781 }
782 }
783 }
784
785 return draw;
786 }
787
788
789 void raster_line(SDL_Surface *dst, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t color)
790 {
791 /* sdl-gfx */
792 int pixx, pixy;
793 int x, y;
794 int dx, dy;
795 int sx, sy;
796 int swaptmp;
797 void *pixel;
798
799 /*
800 * Clip line and test if we have to draw
801 */
802 if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
803 return;
804 }
805
806 /*
807 * Test for special cases of straight lines or single point
808 */
809 if (x1 == x2) {
810 if (y1 < y2) {
811 raster_vline(dst, x1, y1, y2, color);
812 return;
813 } else if (y1 > y2) {
814 raster_vline(dst, x1, y2, y1, color);
815 return;
816 } else {
817 raster_PutPixel(dst, x1, y1, color);
818 return;
819 }
820 }
821 if (y1 == y2) {
822 if (x1 < x2) {
823 raster_hline(dst, x1, x2, y1, color);
824 return;
825 } else if (x1 > x2) {
826 raster_hline(dst, x2, x1, y1, color);
827 return;
828 }
829 }
830
831
832 /*
833 * Variable setup
834 */
835 dx = x2 - x1;
836 dy = y2 - y1;
837 sx = (dx >= 0) ? 1 : -1;
838 sy = (dy >= 0) ? 1 : -1;
839
840 /* Lock surface */
841 if (SDL_MUSTLOCK(dst)) {
842 if (SDL_LockSurface(dst) < 0) {
843 return;
844 }
845 }
846
847 /*
848 * No alpha blending - use fast pixel routines
849 */
850
851 #if 0
852 /*
853 * Setup color
854 */
855 colorptr = (Uint8 *) & color;
856 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
857 color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
858 } else {
859 color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
860 }
861 #endif
862
863 /*
864 * More variable setup
865 */
866 dx = sx * dx + 1;
867 dy = sy * dy + 1;
868 pixx = dst->format->BytesPerPixel;
869 pixy = dst->pitch;
870 pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y1;
871 pixx *= sx;
872 pixy *= sy;
873 if (dx < dy) {
874 swaptmp = dx;
875 dx = dy;
876 dy = swaptmp;
877 swaptmp = pixx;
878 pixx = pixy;
879 pixy = swaptmp;
880 }
881
882 /*
883 * Draw
884 */
885 x = 0;
886 y = 0;
887 switch (dst->format->BytesPerPixel) {
888 case 1:
889 for (; x < dx; x++, pixel=(Uint8 *)+pixx) {
890 *(Uint8 *)pixel = color;
891 y += dy;
892 if (y >= dx) {
893 y -= dx;
894 pixel = (Uint8 *)pixel + pixy;
895 }
896 }
897 break;
898 case 2:
899 for (; x < dx; x++, pixel=(Uint8 *)pixel+pixx) {
900 *(Uint16 *) pixel = color;
901 y += dy;
902 if (y >= dx) {
903 y -= dx;
904 pixel = (Uint8 *)pixel + pixy;
905 }
906 }
907 break;
908 case 3:
909 for (; x < dx; x++, pixel=(Uint8 *)pixel+pixx) {
910 if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
911 *(Uint8 *)pixel = (color >> 16) & 0xff;
912 *((Uint8 *)pixel+1) = (color >> 8) & 0xff;
913 *((Uint8 *)pixel+2) = color & 0xff;
914 } else {
915 *(Uint8 *)pixel = color & 0xff;
916 *((Uint8 *)pixel+1) = (color >> 8) & 0xff;
917 *((Uint8 *)pixel+2) = (color >> 16) & 0xff;
918 }
919 y += dy;
920 if (y >= dx) {
921 y -= dx;
922 pixel = (Uint8 *)pixel + pixy;
923 }
924 }
925 break;
926 default: /* case 4 */
927 for (; x < dx; x++, pixel=(Uint8 *)pixel+pixx) {
928 *(Uint32 *) pixel = color;
929 y += dy;
930 if (y >= dx) {
931 y -= dx;
932 pixel = (Uint8 *)pixel + pixy;
933 }
934 }
935 break;
936 }
937
938 /* Unlock surface */
939 if (SDL_MUSTLOCK(dst)) {
940 SDL_UnlockSurface(dst);
941 }
942
943 return;
944 }
945
946
947 #define AAlevels 256
948 #define AAbits 8
949
950 static void raster_aalineColorInt(SDL_Surface * dst, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
951 {
952 Sint32 xx0, yy0, xx1, yy1;
953 int result;
954 Uint32 intshift, erracc, erradj;
955 Uint32 erracctmp, wgt, wgtcompmask;
956 int dx, dy, tmp, xdir, y0p1, x0pxdir;
957
958 /*
959 * Check visibility of clipping rectangle
960 */
961 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
962 return;
963 }
964
965 /*
966 * Clip line and test if we have to draw
967 */
968 if (!(clipLine(dst, &x1, &y1, &x2, &y2))) {
969 return;
970 }
971
972 /*
973 * Keep on working with 32bit numbers
974 */
975 xx0 = x1;
976 yy0 = y1;
977 xx1 = x2;
978 yy1 = y2;
979
980 /*
981 * Reorder points if required
982 */
983 if (yy0 > yy1) {
984 tmp = yy0;
985 yy0 = yy1;
986 yy1 = tmp;
987 tmp = xx0;
988 xx0 = xx1;
989 xx1 = tmp;
990 }
991
992 /*
993 * Calculate distance
994 */
995 dx = xx1 - xx0;
996 dy = yy1 - yy0;
997
998 /*
999 * Adjust for negative dx and set xdir
1000 */
1001 if (dx >= 0) {
1002 xdir = 1;
1003 } else {
1004 xdir = -1;
1005 dx = (-dx);
1006 }
1007
1008 /*
1009 * Check for special cases
1010 */
1011 if (dx == 0) {
1012 /*
1013 * Vertical line
1014 */
1015 raster_vline(dst, x1, y1, y2, color);
1016 return;
1017 } else if (dy == 0) {
1018 /*
1019 * Horizontal line
1020 */
1021 raster_hline(dst, x1, x2, y1, color);
1022 return;
1023 } else if (dx == dy) {
1024 /*
1025 * Diagonal line
1026 */
1027 raster_line(dst, x1, y1, x2, y2, color);
1028 return;
1029 }
1030
1031 /*
1032 * Line is not horizontal, vertical or diagonal
1033 */
1034 result = 0;
1035
1036 /*
1037 * Zero accumulator
1038 */
1039 erracc = 0;
1040
1041 /*
1042 * # of bits by which to shift erracc to get intensity level
1043 */
1044 intshift = 32 - AAbits;
1045 /*
1046 * Mask used to flip all bits in an intensity weighting
1047 */
1048 wgtcompmask = AAlevels - 1;
1049
1050 /* Lock surface */
1051 if (SDL_MUSTLOCK(dst)) {
1052 if (SDL_LockSurface(dst) < 0) {
1053 return;
1054 }
1055 }
1056
1057 /*
1058 * Draw the initial pixel in the foreground color
1059 */
1060 raster_pixelColorNolock(dst, x1, y1, color);
1061
1062 /*
1063 * x-major or y-major?
1064 */
1065 if (dy > dx) {
1066
1067 /*
1068 * y-major. Calculate 16-bit fixed point fractional part of a pixel that
1069 * X advances every time Y advances 1 pixel, truncating the result so that
1070 * we won't overrun the endpoint along the X axis
1071 */
1072 /*
1073 * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
1074 */
1075 erradj = ((dx << 16) / dy) << 16;
1076
1077 /*
1078 * draw all pixels other than the first and last
1079 */
1080 x0pxdir = xx0 + xdir;
1081 while (--dy) {
1082 erracctmp = erracc;
1083 erracc += erradj;
1084 if (erracc <= erracctmp) {
1085 /*
1086 * rollover in error accumulator, x coord advances
1087 */
1088 xx0 = x0pxdir;
1089 x0pxdir += xdir;
1090 }
1091 yy0++; /* y-major so always advance Y */
1092
1093 /*
1094 * the AAbits most significant bits of erracc give us the intensity
1095 * weighting for this pixel, and the complement of the weighting for
1096 * the paired pixel.
1097 */
1098 wgt = (erracc >> intshift) & 255;
1099 raster_pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1100 raster_pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
1101 }
1102
1103 } else {
1104
1105 /*
1106 * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
1107 * that Y advances each time X advances 1 pixel, truncating the result so
1108 * that we won't overrun the endpoint along the X axis.
1109 */
1110 /*
1111 * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
1112 */
1113 erradj = ((dy << 16) / dx) << 16;
1114
1115 /*
1116 * draw all pixels other than the first and last
1117 */
1118 y0p1 = yy0 + 1;
1119 while (--dx) {
1120
1121 erracctmp = erracc;
1122 erracc += erradj;
1123 if (erracc <= erracctmp) {
1124 /*
1125 * Accumulator turned over, advance y
1126 */
1127 yy0 = y0p1;
1128 y0p1++;
1129 }
1130 xx0 += xdir; /* x-major so always advance X */
1131 /*
1132 * the AAbits most significant bits of erracc give us the intensity
1133 * weighting for this pixel, and the complement of the weighting for
1134 * the paired pixel.
1135 */
1136 wgt = (erracc >> intshift) & 255;
1137 raster_pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
1138 raster_pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
1139 }
1140 }
1141
1142 /*
1143 * Do we have to draw the endpoint
1144 */
1145 if (draw_endpoint) {
1146 /*
1147 * Draw final pixel, always exactly intersected by the line and doesn't
1148 * need to be weighted.
1149 */
1150 raster_pixelColorNolock (dst, x2, y2, color);
1151 }
1152
1153 /* Unlock surface */
1154 if (SDL_MUSTLOCK(dst)) {
1155 SDL_UnlockSurface(dst);
1156 }
1157 }
1158
1159 void raster_aaline(SDL_Surface *s, int16_t x1, int16_t y1, int16_t x2, int16_t y2, uint32_t col)
1160 {
1161 raster_aalineColorInt(s, x1, y1, x2, y2, col, 1);
1162 }
1163
1164
1165
1166 /* raster :: circle */
1167
1168 void raster_circle(SDL_Surface *dst, int16_t x, int16_t y, int16_t r, uint32_t color)
1169 {
1170 /* sdl-gfx */
1171 Sint16 left, right, top, bottom;
1172 int result;
1173 Sint16 x1, y1, x2, y2;
1174 Sint16 cx = 0;
1175 Sint16 cy = r;
1176 Sint16 ocx = (Sint16) 0xffff;
1177 Sint16 ocy = (Sint16) 0xffff;
1178 Sint16 df = 1 - r;
1179 Sint16 d_e = 3;
1180 Sint16 d_se = -2 * r + 5;
1181 Sint16 xpcx, xmcx, xpcy, xmcy;
1182 Sint16 ypcy, ymcy, ypcx, ymcx;
1183
1184 /*
1185 * Check visibility of clipping rectangle
1186 */
1187 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1188 return;
1189 }
1190
1191 /*
1192 * Sanity check radius
1193 */
1194 if (r < 0) {
1195 return;
1196 }
1197
1198 /*
1199 * Special case for r=0 - draw a point
1200 */
1201 if (r == 0) {
1202 return (raster_PutPixel(dst, x, y, color));
1203 }
1204
1205 /*
1206 * Get circle and clipping boundary and
1207 * test if bounding box of circle is visible
1208 */
1209 x2 = x + r;
1210 left = dst->clip_rect.x;
1211 if (x2<left) {
1212 return;
1213 }
1214 x1 = x - r;
1215 right = dst->clip_rect.x + dst->clip_rect.w - 1;
1216 if (x1>right) {
1217 return;
1218 }
1219 y2 = y + r;
1220 top = dst->clip_rect.y;
1221 if (y2<top) {
1222 return;
1223 }
1224 y1 = y - r;
1225 bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1226 if (y1>bottom) {
1227 return;
1228 }
1229
1230 /*
1231 * Draw
1232 */
1233 result = 0;
1234 do {
1235 xpcx = x + cx;
1236 xmcx = x - cx;
1237 xpcy = x + cy;
1238 xmcy = x - cy;
1239 if (ocy != cy) {
1240 if (cy > 0) {
1241 ypcy = y + cy;
1242 ymcy = y - cy;
1243 raster_hline(dst, xmcx, xpcx, ypcy, color);
1244 raster_hline(dst, xmcx, xpcx, ymcy, color);
1245 // raster_rect_inline(dst, xmcx, ypcy, 2*cx, 1, color);
1246 // raster_rect_inline(dst, xmcx, ymcy, 2*cx, 1, color);
1247
1248 } else {
1249 raster_hline(dst, xmcx, xpcx, y, color);
1250 // raster_rect_inline(dst, xmcx, y, 2*cx, 1, color);
1251 }
1252 ocy = cy;
1253 }
1254 if (ocx != cx) {
1255 if (cx != cy) {
1256 if (cx > 0) {
1257 ypcx = y + cx;
1258 ymcx = y - cx;
1259 raster_hline(dst, xmcy, xpcy, ymcx, color);
1260 raster_hline(dst, xmcy, xpcy, ypcx, color);
1261 //raster_rect_inline(dst, xmcy, ymcx, 2*cy, 1, color);
1262 //raster_rect_inline(dst, xmcy, ypcx, 2*cy, 1, color);
1263 } else {
1264 raster_hline(dst, xmcy, xpcy, y, color);
1265 //raster_rect_inline(dst, xmcy, y, 2*cy, 1, color);
1266 }
1267 }
1268 ocx = cx;
1269 }
1270 /*
1271 * Update
1272 */
1273 if (df < 0) {
1274 df += d_e;
1275 d_e += 2;
1276 d_se += 2;
1277 } else {
1278 df += d_se;
1279 d_e += 2;
1280 d_se += 4;
1281 cy--;
1282 }
1283 cx++;
1284 } while (cx <= cy);
1285 }
1286
1287
1288 /* FIXME: convert to fixed pt */
1289 static void raster_AAFilledEllipse(SDL_Surface *surface, Sint16 xc, Sint16 yc, Sint16 rx, Sint16 ry, Uint32 color)
1290 {
1291 /* sge */
1292 /* Sanity check */
1293 if (rx < 1)
1294 rx = 1;
1295 if (ry < 1)
1296 ry = 1;
1297
1298 int a2 = rx * rx;
1299 int b2 = ry * ry;
1300
1301 int ds = 2 * a2;
1302 int dt = 2 * b2;
1303
1304 int dxt = (int)(a2 / sqrt(a2 + b2));
1305
1306 int t = 0;
1307 int s = -2 * a2 * ry;
1308 int d = 0;
1309
1310 Sint16 x = xc;
1311 Sint16 y = yc - ry;
1312
1313 Sint16 xs, ys, dyt;
1314 float cp, is, ip, imax = 1.0;
1315
1316 /* Lock surface */
1317 if ( SDL_MUSTLOCK(surface) )
1318 if ( SDL_LockSurface(surface) < 0 )
1319 return;
1320
1321 /* "End points" */
1322 raster_PutPixel(surface, x, y, color);
1323 raster_PutPixel(surface, 2*xc-x, y, color);
1324
1325 raster_PutPixel(surface, x, 2*yc-y, color);
1326 raster_PutPixel(surface, 2*xc-x, 2*yc-y, color);
1327
1328 /* unlock surface */
1329 if (SDL_MUSTLOCK(surface) )
1330 SDL_UnlockSurface(surface);
1331
1332 raster_vline(surface, x, y+1, 2*yc-y-1, color);
1333
1334 int i;
1335
1336 for (i = 1; i <= dxt; i++)
1337 {
1338 x--;
1339 d += t - b2;
1340
1341 if (d >= 0)
1342 ys = y - 1;
1343 else if ((d - s - a2) > 0)
1344 {
1345 if ((2 * d - s - a2) >= 0)
1346 ys = y + 1;
1347 else
1348 {
1349 ys = y;
1350 y++;
1351 d -= s + a2;
1352 s += ds;
1353 }
1354 }
1355 else
1356 {
1357 y++;
1358 ys = y + 1;
1359 d -= s + a2;
1360 s += ds;
1361 }
1362
1363 t -= dt;
1364
1365 /* Calculate alpha */
1366 cp = (float) abs(d) / abs(s);
1367 is = cp * imax;
1368 ip = imax - is;
1369
1370
1371 /* Lock surface */
1372 if ( SDL_MUSTLOCK(surface) )
1373 if ( SDL_LockSurface(surface) < 0 )
1374 return;
1375
1376 /* Upper half */
1377 raster_PutPixelAlpha(surface, x, y, color, (Uint8)(ip*255));
1378 raster_PutPixelAlpha(surface, 2*xc-x, y, color, (Uint8)(ip*255));
1379
1380 raster_PutPixelAlpha(surface, x, ys, color, (Uint8)(is*255));
1381 raster_PutPixelAlpha(surface, 2*xc-x, ys, color, (Uint8)(is*255));
1382
1383
1384 /* Lower half */
1385 raster_PutPixelAlpha(surface, x, 2*yc-y, color, (Uint8)(ip*255));
1386 raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, (Uint8)(ip*255));
1387
1388 raster_PutPixelAlpha(surface, x, 2*yc-ys, color, (Uint8)(is*255));
1389 raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-ys, color, (Uint8)(is*255));
1390
1391 /* unlock surface */
1392 if (SDL_MUSTLOCK(surface) )
1393 SDL_UnlockSurface(surface);
1394
1395
1396 /* Fill */
1397 raster_vline(surface, x, y+1, 2*yc-y-1, color);
1398 raster_vline(surface, 2*xc-x, y+1, 2*yc-y-1, color);
1399 raster_vline(surface, x, ys+1, 2*yc-ys-1, color);
1400 raster_vline(surface, 2*xc-x, ys+1, 2*yc-ys-1, color);
1401 }
1402
1403 dyt = abs(y - yc);
1404
1405 for (i = 1; i <= dyt; i++)
1406 {
1407 y++;
1408 d -= s + a2;
1409
1410 if (d <= 0)
1411 xs = x + 1;
1412 else if ((d + t - b2) < 0)
1413 {
1414 if ((2 * d + t - b2) <= 0)
1415 xs = x - 1;
1416 else
1417 {
1418 xs = x;
1419 x--;
1420 d += t - b2;
1421 t -= dt;
1422 }
1423 }
1424 else
1425 {
1426 x--;
1427 xs = x - 1;
1428 d += t - b2;
1429 t -= dt;
1430 }
1431
1432 s += ds;
1433
1434 /* Calculate alpha */
1435 cp = (float) abs(d) / abs(t);
1436 is = cp * imax;
1437 ip = imax - is;
1438
1439
1440 /* Lock surface */
1441 if ( SDL_MUSTLOCK(surface) )
1442 if ( SDL_LockSurface(surface) < 0 )
1443 return;
1444
1445 /* Upper half */
1446 raster_PutPixelAlpha(surface, x, y, color, (Uint8)(ip*255));
1447 raster_PutPixelAlpha(surface, 2*xc-x, y, color, (Uint8)(ip*255));
1448
1449 raster_PutPixelAlpha(surface, xs, y, color, (Uint8)(is*255));
1450 raster_PutPixelAlpha(surface, 2*xc-xs, y, color, (Uint8)(is*255));
1451
1452
1453 /* Lower half*/
1454 raster_PutPixelAlpha(surface, x, 2*yc-y, color, (Uint8)(ip*255));
1455 raster_PutPixelAlpha(surface, 2*xc-x, 2*yc-y, color, (Uint8)(ip*255));
1456
1457 raster_PutPixelAlpha(surface, xs, 2*yc-y, color, (Uint8)(is*255));
1458 raster_PutPixelAlpha(surface, 2*xc-xs, 2*yc-y, color, (Uint8)(is*255));
1459
1460 /* unlock surface */
1461 if (SDL_MUSTLOCK(surface) )
1462 SDL_UnlockSurface(surface);
1463
1464 /* Fill */
1465 raster_hline(surface, x+1, 2*xc-x-1, y, color);
1466 raster_hline(surface, xs+1, 2*xc-xs-1, y, color);
1467 raster_hline(surface, x+1, 2*xc-x-1, 2*yc-y, color);
1468 raster_hline(surface, xs+1, 2*xc-xs-1, 2*yc-y, color);
1469 }
1470 }
1471
1472 void raster_aacircle(SDL_Surface *s, int16_t x, int16_t y, int16_t r, uint32_t col)
1473 {
1474 raster_AAFilledEllipse(s, x, y, r, r, col);
1475 }
1476
1477 #if 0
1478 void raster_aacircle(SDL_Surface *s, int16_t x, int16_t y, int16_t r, uint32_t col)
1479 {
1480 /* sdl-gfx */
1481 Sint16 left, right, top, bottom;
1482 int result;
1483 Sint16 x1, y1, x2, y2;
1484 Sint16 cx = 0;
1485 Sint16 cy = r;
1486 Sint16 ocx = (Sint16) 0xffff;
1487 Sint16 ocy = (Sint16) 0xffff;
1488 Sint16 df = 1 - r;
1489 Sint16 d_e = 3;
1490 Sint16 d_se = -2 * r + 5;
1491 Sint16 xpcx, xmcx, xpcy, xmcy;
1492 Sint16 ypcy, ymcy, ypcx, ymcx;
1493
1494 /*
1495 * Check visibility of clipping rectangle
1496 */
1497 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1498 return;
1499 }
1500
1501 /*
1502 * Sanity check radius
1503 */
1504 if (r < 0) {
1505 return;
1506 }
1507
1508 #if 0
1509 /*
1510 * Special case for r=0 - draw a point
1511 */
1512 if (r == 0) {
1513 return (pixelColor(dst, x, y, color));
1514 }
1515 #endif
1516
1517 /*
1518 * Get circle and clipping boundary and
1519 * test if bounding box of circle is visible
1520 */
1521 x2 = x + r;
1522 left = dst->clip_rect.x;
1523 if (x2<left) {
1524 return;
1525 }
1526 x1 = x - r;
1527 right = dst->clip_rect.x + dst->clip_rect.w - 1;
1528 if (x1>right) {
1529 return;
1530 }
1531 y2 = y + r;
1532 top = dst->clip_rect.y;
1533 if (y2<top) {
1534 return;
1535 }
1536 y1 = y - r;
1537 bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1538 if (y1>bottom) {
1539 return;
1540 }
1541
1542 /*
1543 * Draw
1544 */
1545 result = 0;
1546 do {
1547 xpcx = x + cx;
1548 xmcx = x - cx;
1549 xpcy = x + cy;
1550 xmcy = x - cy;
1551 if (ocy != cy) {
1552 if (cy > 0) {
1553 ypcy = y + cy;
1554 ymcy = y - cy;
1555 raster_hlineColor(dst, xmcx, xpcx, ypcy, color);
1556 raster_hlineColor(dst, xmcx, xpcx, ymcy, color);
1557 // raster_rect_inline(dst, xmcx, ypcy, 2*cx, 1, color);
1558 // raster_rect_inline(dst, xmcx, ymcy, 2*cx, 1, color);
1559
1560 } else {
1561 raster_hlineColor(dst, xmcx, xpcx, y, color);
1562 // raster_rect_inline(dst, xmcx, y, 2*cx, 1, color);
1563 }
1564 ocy = cy;
1565 }
1566 if (ocx != cx) {
1567 if (cx != cy) {
1568 if (cx > 0) {
1569 ypcx = y + cx;
1570 ymcx = y - cx;
1571 raster_hlineColor(dst, xmcy, xpcy, ymcx, color);
1572 raster_hlineColor(dst, xmcy, xpcy, ypcx, color);
1573 //raster_rect_inline(dst, xmcy, ymcx, 2*cy, 1, color);
1574 //raster_rect_inline(dst, xmcy, ypcx, 2*cy, 1, color);
1575 } else {
1576 raster_hlineColor(dst, xmcy, xpcy, y, color);
1577 //raster_rect_inline(dst, xmcy, y, 2*cy, 1, color);
1578 }
1579 }
1580 ocx = cx;
1581 }
1582 /*
1583 * Update
1584 */
1585 if (df < 0) {
1586 df += d_e;
1587 d_e += 2;
1588 d_se += 2;
1589 } else {
1590 df += d_se;
1591 d_e += 2;
1592 d_se += 4;
1593 cy--;
1594 }
1595 cx++;
1596 } while (cx <= cy);
1597 #if 0
1598 /* sge */
1599 Sint16 cx = 0;
1600 Sint16 cy = r;
1601 int draw=1;
1602 Sint16 df = 1 - r;
1603 Sint16 d_e = 3;
1604 Sint16 d_se = -2 * r + 5;
1605
1606 #ifdef DEBUG
1607 printf("raster_circle %d %d %d\n", x, y, r);
1608 #endif
1609
1610 if(r < 0)
1611 {
1612 return;
1613 }
1614
1615 do {
1616 if(draw)
1617 {
1618 raster_rect_inline(s, x-cx, y+cy, 2*cx, 1, col);
1619 raster_rect_inline(s, x-cx, y-cy, 2*cx, 1, col);
1620 draw=0;
1621 }
1622 if(cx!=cy)
1623 {
1624 if(cx)
1625 {
1626 raster_rect_inline(s, x-cy, y-cx, 2*cy, 1, col);
1627 raster_rect_inline(s, x-cy, y+cx, 2*cy, 1, col);
1628 }
1629 else
1630 {
1631 raster_rect_inline(s, x-cy, y, 2*cy, 1, col);
1632 }
1633 }
1634
1635 if (df < 0)
1636 {
1637 df += d_e;
1638 d_e += 2;
1639 d_se += 2;
1640 }
1641 else
1642 {
1643 df += d_se;
1644 d_e += 2;
1645 d_se += 4;
1646 cy--;
1647 draw=1;
1648 }
1649 cx++;
1650 } while(cx <= cy);
1651 #endif
1652 }
1653 #endif
1654
1655
1656
1657 /* raster :: poly */
1658
1659
1660 /* ---- Filled Polygon */
1661
1662 /* Helper qsort callback for polygon drawing */
1663
1664 static int gfxPrimitivesCompareInt(const void *a, const void *b)
1665 {
1666 return (*(const int *) a) - (*(const int *) b);
1667 }
1668
1669
1670 /* Global vertex array to use if optional parameters are not given in polygon calls. */
1671 static int *gfxPrimitivesPolyIntsGlobal = NULL;
1672 static int gfxPrimitivesPolyAllocatedGlobal = 0;
1673
1674 /* (Note: The last two parameters are optional; but required for multithreaded operation.) */
1675
1676 static inline int raster_filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
1677 {
1678 /* sdl-gfx */
1679 int result;
1680 int i;
1681 int y, xa, xb;
1682 int miny, maxy;
1683 int x1, y1;
1684 int x2, y2;
1685 int ind1, ind2;
1686 int ints;
1687 int *gfxPrimitivesPolyInts = NULL;
1688 int gfxPrimitivesPolyAllocated = 0;
1689
1690 /*
1691 * Check visibility of clipping rectangle
1692 */
1693 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1694 return(0);
1695 }
1696
1697 /*
1698 * Sanity check number of edges
1699 */
1700 if (n < 3) {
1701 return -1;
1702 }
1703
1704 /*
1705 * Map polygon cache
1706 */
1707 if ((polyInts==NULL) || (polyAllocated==NULL)) {
1708 /* Use global cache */
1709 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
1710 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
1711 } else {
1712 /* Use local cache */
1713 gfxPrimitivesPolyInts = *polyInts;
1714 gfxPrimitivesPolyAllocated = *polyAllocated;
1715 }
1716
1717 /*
1718 * Allocate temp array, only grow array
1719 */
1720 if (!gfxPrimitivesPolyAllocated) {
1721 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
1722 gfxPrimitivesPolyAllocated = n;
1723 } else {
1724 if (gfxPrimitivesPolyAllocated < n) {
1725 gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
1726 gfxPrimitivesPolyAllocated = n;
1727 }
1728 }
1729
1730 /*
1731 * Check temp array
1732 */
1733 if (gfxPrimitivesPolyInts==NULL) {
1734 gfxPrimitivesPolyAllocated = 0;
1735 }
1736
1737 /*
1738 * Update cache variables
1739 */
1740 if ((polyInts==NULL) || (polyAllocated==NULL)) {
1741 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
1742 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
1743 } else {
1744 *polyInts = gfxPrimitivesPolyInts;
1745 *polyAllocated = gfxPrimitivesPolyAllocated;
1746 }
1747
1748 /*
1749 * Check temp array again
1750 */
1751 if (gfxPrimitivesPolyInts==NULL) {
1752 return(-1);
1753 }
1754
1755 /*
1756 * Determine Y maxima
1757 */
1758 miny = vy[0];
1759 maxy = vy[0];
1760 for (i = 1; (i < n); i++) {
1761 if (vy[i] < miny) {
1762 miny = vy[i];
1763 } else if (vy[i] > maxy) {
1764 maxy = vy[i];
1765 }
1766 }
1767
1768 /*
1769 * Draw, scanning y
1770 */
1771 result = 0;
1772 for (y = miny; (y <= maxy); y++) {
1773 ints = 0;
1774 for (i = 0; (i < n); i++) {
1775 if (!i) {
1776 ind1 = n - 1;
1777 ind2 = 0;
1778 } else {
1779 ind1 = i - 1;
1780 ind2 = i;
1781 }
1782 y1 = vy[ind1];
1783 y2 = vy[ind2];
1784 if (y1 < y2) {
1785 x1 = vx[ind1];
1786 x2 = vx[ind2];
1787 } else if (y1 > y2) {
1788 y2 = vy[ind1];
1789 y1 = vy[ind2];
1790 x2 = vx[ind1];
1791 x1 = vx[ind2];
1792 } else {
1793 continue;
1794 }
1795 if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
1796 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
1797 }
1798 }
1799
1800 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
1801
1802 for (i = 0; (i < ints); i += 2) {
1803 xa = gfxPrimitivesPolyInts[i] + 1;
1804 xa = (xa >> 16) + ((xa & 32768) >> 15);
1805 xb = gfxPrimitivesPolyInts[i+1] - 1;
1806 xb = (xb >> 16) + ((xb & 32768) >> 15);
1807 raster_hline(dst, xa, xb, y, color);
1808 // raster_rect_inline(dst, xa, y, xb - xa, 1, color);
1809 }
1810 }
1811
1812 return (result);
1813 }
1814
1815 void raster_polygon(SDL_Surface *s, int16_t n, int16_t *vx, int16_t *vy, uint32_t col)
1816 {
1817 raster_filledPolygonColorMT(s, vx, vy, n, col, NULL, NULL);
1818 }
1819
1820
1821 void raster_aapolygon(SDL_Surface *dst, int16_t n, int16_t *vx, int16_t *vy, uint32_t color)
1822 {
1823 /* sdl-gfx + sge w/ rphlx changes: basically, draw aaline border,
1824 then fill.
1825
1826 the output is not perfect yet but usually looks better than aliasing
1827 */
1828 int result;
1829 int i;
1830 int y, xa, xb;
1831 int miny, maxy;
1832 int x1, y1;
1833 int x2, y2;
1834 int ind1, ind2;
1835 int ints;
1836 int *gfxPrimitivesPolyInts = NULL;
1837 int gfxPrimitivesPolyAllocated = 0;
1838 const Sint16 *px1, *py1, *px2, *py2;
1839 int **polyInts;
1840 int *polyAllocated;
1841
1842 polyInts = NULL;
1843 polyAllocated = NULL;
1844
1845 /*
1846 * Check visibility of clipping rectangle
1847 */
1848 if ((dst->clip_rect.w==0) || (dst->clip_rect.h==0)) {
1849 return;
1850 }
1851
1852 /*
1853 * Sanity check number of edges
1854 */
1855 if (n < 3) {
1856 return;
1857 }
1858
1859
1860 /*
1861 * Pointer setup
1862 */
1863 px1 = px2 = vx;
1864 py1 = py2 = vy;
1865 px2++;
1866 py2++;
1867
1868 /*
1869 * Draw
1870 */
1871 result = 0;
1872 for (i = 1; i < n; i++) {
1873 raster_aalineColorInt(dst, *px1, *py1, *px2, *py2, color, 0);
1874 px1 = px2;
1875 py1 = py2;
1876 px2++;
1877 py2++;
1878 }
1879 raster_aalineColorInt(dst, *px1, *py1, *vx, *vy, color, 0);
1880
1881 /*
1882 * Map polygon cache
1883 */
1884 if ((polyInts==NULL) || (polyAllocated==NULL)) {
1885 /* Use global cache */
1886 gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
1887 gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
1888 } else {
1889 /* Use local cache */
1890 gfxPrimitivesPolyInts = *polyInts;
1891 gfxPrimitivesPolyAllocated = *polyAllocated;
1892 }
1893
1894 /*
1895 * Allocate temp array, only grow array
1896 */
1897 if (!gfxPrimitivesPolyAllocated) {
1898 gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
1899 gfxPrimitivesPolyAllocated = n;
1900 } else {
1901 if (gfxPrimitivesPolyAllocated < n) {
1902 gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
1903 gfxPrimitivesPolyAllocated = n;
1904 }
1905 }
1906
1907 /*
1908 * Check temp array
1909 */
1910 if (gfxPrimitivesPolyInts==NULL) {
1911 gfxPrimitivesPolyAllocated = 0;
1912 }
1913
1914 /*
1915 * Update cache variables
1916 */
1917 if ((polyInts==NULL) || (polyAllocated==NULL)) {
1918 gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
1919 gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
1920 } else {
1921 *polyInts = gfxPrimitivesPolyInts;
1922 *polyAllocated = gfxPrimitivesPolyAllocated;
1923 }
1924
1925 /*
1926 * Check temp array again
1927 */
1928 if (gfxPrimitivesPolyInts==NULL) {
1929 return;
1930 }
1931
1932 /*
1933 * Determine Y maxima
1934 */
1935 miny = vy[0];
1936 maxy = vy[0];
1937 for (i = 1; (i < n); i++) {
1938 if (vy[i] < miny) {
1939 miny = vy[i];
1940 } else if (vy[i] > maxy) {
1941 maxy = vy[i];
1942 }
1943 }
1944
1945 /*
1946 * Draw, scanning y
1947 */
1948 result = 0;
1949 for (y = miny; (y <= maxy); y++) {
1950 ints = 0;
1951 for (i = 0; (i < n); i++) {
1952 if (!i) {
1953 ind1 = n - 1;
1954 ind2 = 0;
1955 } else {
1956 ind1 = i - 1;
1957 ind2 = i;
1958 }
1959 y1 = vy[ind1];
1960 y2 = vy[ind2];
1961 if (y1 < y2) {
1962 x1 = vx[ind1];
1963 x2 = vx[ind2];
1964 } else if (y1 > y2) {
1965 y2 = vy[ind1];
1966 y1 = vy[ind2];
1967 x2 = vx[ind1];
1968 x1 = vx[ind2];
1969 } else {
1970 continue;
1971 }
1972 if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
1973 gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
1974 }
1975 }
1976
1977 qsort(gfxPrimitivesPolyInts, ints, sizeof(int), gfxPrimitivesCompareInt);
1978
1979 // o = p = -1;
1980 for (i = 0; (i < ints); i +=2) {
1981 #if 0
1982 xa = gfxPrimitivesPolyInts[i] + 1;
1983 xa = (xa >> 16) + ((xa & 32768) >> 15);
1984 xb = gfxPrimitivesPolyInts[i+1] - 1;
1985 xb = (xb >> 16) + ((xb & 32768) >> 15);
1986 #else
1987 xa = (gfxPrimitivesPolyInts[i] >> 16);
1988 xb = (gfxPrimitivesPolyInts[i+1] >> 16);
1989 #endif
1990
1991 #if 0
1992 if(o < 0)
1993 {
1994 o = xa+1;
1995 }
1996 else if(p < 0)
1997 {
1998 p = xa;
1999 }
2000
2001 if( (o >= 0) && (p >= 0))
2002 {
2003 if(p-o < 0)
2004 {
2005 o = p = -1;
2006 continue;
2007 }
2008
2009 raster_hlineColor(dst, o, p, y, color);
2010
2011 o = p = -1;
2012 }
2013 #else
2014
2015 raster_hline(dst, xa+1, xb, y, color);
2016 #endif
2017
2018 // raster_rect_inline(dst, xa, y, xb - xa, 1, color);
2019 }
2020 }
2021 }
2022

   
Visit the ZANavi Wiki