Atrinik Client  4.0
SDL_gfx.c
1 /*
2 
3 SDL_gfxPrimitives - Graphics primitives for SDL surfaces
4 
5 LGPL (c) A. Schiffler
6 
7  */
8 
9 #include <global.h>
10 
11 /* -===================- */
12 
13 #define DEFAULT_ALPHA_PIXEL_ROUTINE
14 #undef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
15 
16 /* ---- Structures */
17 
21 typedef struct {
22  Sint16 x, y;
23  int dx, dy, s1, s2, swapdir, error;
24  Uint32 count;
26 
30 typedef struct {
31  Uint32 color;
32  SDL_Surface *dst;
33  int u, v; /* delta x , delta y */
34  int ku, kt, kv, kd; /* loop constants */
35  int oct2;
36  int quad4;
37  Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
39 
40 /* ----- Defines for pixel clipping tests */
41 
60 static int _bresenhamInitialize(SDL_gfxBresenhamIterator *b, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2)
61 {
62  int temp;
63 
64  if (b == NULL) {
65  return (-1);
66  }
67 
68  b->x = x;
69  b->y = y;
70 
71  /* dx = abs(x2-x1), s1 = sign(x2-x1) */
72  if ((b->dx = x2 - x) != 0) {
73  if (b->dx < 0) {
74  b->dx = -b->dx;
75  b->s1 = -1;
76  } else {
77  b->s1 = 1;
78  }
79  } else {
80  b->s1 = 0;
81  }
82 
83  /* dy = abs(y2-y1), s2 = sign(y2-y1) */
84  if ((b->dy = y2 - y) != 0) {
85  if (b->dy < 0) {
86  b->dy = -b->dy;
87  b->s2 = -1;
88  } else {
89  b->s2 = 1;
90  }
91  } else {
92  b->s2 = 0;
93  }
94 
95  if (b->dy > b->dx) {
96  temp = b->dx;
97  b->dx = b->dy;
98  b->dy = temp;
99  b->swapdir = 1;
100  } else {
101  b->swapdir = 0;
102  }
103 
104  b->count = b->dx;
105  b->dy <<= 1;
106  b->error = b->dy - b->dx;
107  b->dx <<= 1;
108 
109  return (0);
110 }
111 
121 static int _bresenhamIterate(SDL_gfxBresenhamIterator *b)
122 {
123  if (b == NULL) {
124  return (-1);
125  }
126 
127  /* last point check */
128  if (b->count <= 0) {
129  return (2);
130  }
131 
132  while (b->error >= 0) {
133  if (b->swapdir) {
134  b->x += b->s1;
135  } else {
136  b->y += b->s2;
137  }
138 
139  b->error -= b->dx;
140  }
141 
142  if (b->swapdir) {
143  b->y += b->s2;
144  } else {
145  b->x += b->s1;
146  }
147 
148  b->error += b->dy;
149  b->count--;
150 
151  /* count==0 indicates "end-of-line" */
152  return ((b->count) ? 0 : 1);
153 }
154 
155 
165 #define clip_xmin(surface) surface->clip_rect.x
166 #define clip_xmax(surface) surface->clip_rect.x+surface->clip_rect.w-1
167 #define clip_ymin(surface) surface->clip_rect.y
168 #define clip_ymax(surface) surface->clip_rect.y+surface->clip_rect.h-1
169 
180 int fastPixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
181 {
182  int bpp;
183  Uint8 *p;
184 
185  /*
186  * Honor clipping setup at pixel level
187  */
188  if ((x >= clip_xmin(dst)) && (x <= clip_xmax(dst)) && (y >= clip_ymin(dst)) && (y <= clip_ymax(dst))) {
189 
190  /*
191  * Get destination format
192  */
193  bpp = dst->format->BytesPerPixel;
194  p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
195  switch (bpp) {
196  case 1:
197  *p = color;
198  break;
199  case 2:
200  *(Uint16 *) p = color;
201  break;
202  case 3:
203  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
204  p[0] = (color >> 16) & 0xff;
205  p[1] = (color >> 8) & 0xff;
206  p[2] = color & 0xff;
207  } else {
208  p[0] = color & 0xff;
209  p[1] = (color >> 8) & 0xff;
210  p[2] = (color >> 16) & 0xff;
211  }
212  break;
213  case 4:
214  *(Uint32 *) p = color;
215  break;
216  } /* switch */
217 
218 
219  }
220 
221  return (0);
222 }
223 
237 int fastPixelColorNolockNoclip(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
238 {
239  int bpp;
240  Uint8 *p;
241 
242  /*
243  * Get destination format
244  */
245  bpp = dst->format->BytesPerPixel;
246  p = (Uint8 *) dst->pixels + y * dst->pitch + x * bpp;
247  switch (bpp) {
248  case 1:
249  *p = color;
250  break;
251  case 2:
252  *(Uint16 *) p = color;
253  break;
254  case 3:
255  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
256  p[0] = (color >> 16) & 0xff;
257  p[1] = (color >> 8) & 0xff;
258  p[2] = color & 0xff;
259  } else {
260  p[0] = color & 0xff;
261  p[1] = (color >> 8) & 0xff;
262  p[2] = (color >> 16) & 0xff;
263  }
264  break;
265  case 4:
266  *(Uint32 *) p = color;
267  break;
268  } /* switch */
269 
270  return (0);
271 }
272 
283 int fastPixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
284 {
285  int result;
286 
287  /*
288  * Lock the surface
289  */
290  if (SDL_MUSTLOCK(dst)) {
291  if (SDL_LockSurface(dst) < 0) {
292  return (-1);
293  }
294  }
295 
296  result = fastPixelColorNolock(dst, x, y, color);
297 
298  /*
299  * Unlock surface
300  */
301  if (SDL_MUSTLOCK(dst)) {
302  SDL_UnlockSurface(dst);
303  }
304 
305  return (result);
306 }
307 
321 int fastPixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
322 {
323  Uint32 color;
324 
325  /*
326  * Setup color
327  */
328  color = SDL_MapRGBA(dst->format, r, g, b, a);
329 
330  /*
331  * Draw
332  */
333  return (fastPixelColor(dst, x, y, color));
334 }
335 
349 int fastPixelRGBANolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
350 {
351  Uint32 color;
352 
353  /*
354  * Setup color
355  */
356  color = SDL_MapRGBA(dst->format, r, g, b, a);
357 
358  /*
359  * Draw
360  */
361  return (fastPixelColorNolock(dst, x, y, color));
362 }
363 
379 int _putPixelAlpha(SDL_Surface *dst, Sint16 x, Sint16 y, Uint32 color, Uint8 alpha)
380 {
381  SDL_PixelFormat *format;
382  Uint32 Rmask, Gmask, Bmask, Amask;
383  Uint32 Rshift, Gshift, Bshift, Ashift;
384  Uint32 R, G, B, A;
385 
386  if (dst == NULL) {
387  return (-1);
388  }
389 
390  if (x >= clip_xmin(dst) && x <= clip_xmax(dst) &&
391  y >= clip_ymin(dst) && y <= clip_ymax(dst)) {
392 
393  format = dst->format;
394 
395  switch (format->BytesPerPixel) {
396  case 1:
397  { /* Assuming 8-bpp */
398  if (alpha == 255) {
399  *((Uint8 *) dst->pixels + y * dst->pitch + x) = color;
400  } else {
401  Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x;
402  SDL_Palette *palette = format->palette;
403  SDL_Color *colors = palette->colors;
404  SDL_Color dColor = colors[*pixel];
405  SDL_Color sColor = colors[color];
406  Uint8 dR = dColor.r;
407  Uint8 dG = dColor.g;
408  Uint8 dB = dColor.b;
409  Uint8 sR = sColor.r;
410  Uint8 sG = sColor.g;
411  Uint8 sB = sColor.b;
412 
413  dR = dR + ((sR - dR) * alpha >> 8);
414  dG = dG + ((sG - dG) * alpha >> 8);
415  dB = dB + ((sB - dB) * alpha >> 8);
416 
417  *pixel = SDL_MapRGB(format, dR, dG, dB);
418  }
419  }
420  break;
421 
422  case 2:
423  { /* Probably 15-bpp or 16-bpp */
424  if (alpha == 255) {
425  *((Uint16 *) dst->pixels + y * dst->pitch / 2 + x) = color;
426  } else {
427  Uint16 *pixel = (Uint16 *) dst->pixels + y * dst->pitch / 2 + x;
428  Uint32 dc = *pixel;
429 
430  Rmask = format->Rmask;
431  Gmask = format->Gmask;
432  Bmask = format->Bmask;
433  Amask = format->Amask;
434  R = ((dc & Rmask) + (((color & Rmask) - (dc & Rmask)) * alpha >> 8)) & Rmask;
435  G = ((dc & Gmask) + (((color & Gmask) - (dc & Gmask)) * alpha >> 8)) & Gmask;
436  B = ((dc & Bmask) + (((color & Bmask) - (dc & Bmask)) * alpha >> 8)) & Bmask;
437  A = 255;
438  if (Amask) {
439  A = ((dc & Amask) + (((color & Amask) - (dc & Amask)) * alpha >> 8)) & Amask;
440  }
441  *pixel = R | G | B | A;
442  }
443  }
444  break;
445 
446  case 3:
447  { /* Slow 24-bpp mode, usually not used */
448  Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
449  Uint8 *pixel = (Uint8 *) dst->pixels + y * dst->pitch + x * 3;
450 
451  Rshift = format->Rshift;
452  Gshift = format->Gshift;
453  Bshift = format->Bshift;
454  Ashift = format->Ashift;
455 
456  Rshift8 = Rshift / 8;
457  Gshift8 = Gshift / 8;
458  Bshift8 = Bshift / 8;
459  Ashift8 = Ashift / 8;
460 
461  if (alpha == 255) {
462  *(pixel + Rshift8) = color >> Rshift;
463  *(pixel + Gshift8) = color >> Gshift;
464  *(pixel + Bshift8) = color >> Bshift;
465  *(pixel + Ashift8) = color >> Ashift;
466  } else {
467  Uint8 dR, dG, dB, dA = 0;
468  Uint8 sR, sG, sB, sA = 0;
469 
470  dR = *((pixel) + Rshift8);
471  dG = *((pixel) + Gshift8);
472  dB = *((pixel) + Bshift8);
473  dA = *((pixel) + Ashift8);
474 
475  sR = (color >> Rshift) & 0xff;
476  sG = (color >> Gshift) & 0xff;
477  sB = (color >> Bshift) & 0xff;
478  sA = (color >> Ashift) & 0xff;
479 
480  dR = dR + ((sR - dR) * alpha >> 8);
481  dG = dG + ((sG - dG) * alpha >> 8);
482  dB = dB + ((sB - dB) * alpha >> 8);
483  dA = dA + ((sA - dA) * alpha >> 8);
484 
485  *((pixel) + Rshift8) = dR;
486  *((pixel) + Gshift8) = dG;
487  *((pixel) + Bshift8) = dB;
488  *((pixel) + Ashift8) = dA;
489  }
490  }
491  break;
492 
493 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
494 
495  case 4:
496  { /* Probably :-) 32-bpp */
497  if (alpha == 255) {
498  *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
499  } else {
500  Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
501  Uint32 dc = *pixel;
502 
503  Rmask = format->Rmask;
504  Gmask = format->Gmask;
505  Bmask = format->Bmask;
506  Amask = format->Amask;
507 
508  Rshift = format->Rshift;
509  Gshift = format->Gshift;
510  Bshift = format->Bshift;
511  Ashift = format->Ashift;
512 
513  A = 0;
514  R = ((dc & Rmask) + (((((color & Rmask) - (dc & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
515  G = ((dc & Gmask) + (((((color & Gmask) - (dc & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
516  B = ((dc & Bmask) + (((((color & Bmask) - (dc & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
517  if (Amask) {
518  A = ((dc & Amask) + (((((color & Amask) - (dc & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
519  }
520  *pixel = R | G | B | A;
521  }
522  }
523  break;
524 #endif
525 
526 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
527 
528  case 4:
529  { /* Probably :-) 32-bpp */
530  if (alpha == 255) {
531  *((Uint32 *) dst->pixels + y * dst->pitch / 4 + x) = color;
532  } else {
533  Uint32 *pixel = (Uint32 *) dst->pixels + y * dst->pitch / 4 + x;
534  Uint32 dR, dG, dB, dA;
535  Uint32 dc = *pixel;
536 
537  Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
538  Uint32 aTmp;
539 
540  Rmask = format->Rmask;
541  Gmask = format->Gmask;
542  Bmask = format->Bmask;
543  Amask = format->Amask;
544 
545  dR = (color & Rmask);
546  dG = (color & Gmask);
547  dB = (color & Bmask);
548  dA = (color & Amask);
549 
550  Rshift = format->Rshift;
551  Gshift = format->Gshift;
552  Bshift = format->Bshift;
553  Ashift = format->Ashift;
554 
555  preMultR = (alpha * (dR >> Rshift));
556  preMultG = (alpha * (dG >> Gshift));
557  preMultB = (alpha * (dB >> Bshift));
558 
559  surfaceAlpha = ((dc & Amask) >> Ashift);
560  aTmp = (255 - alpha);
561  if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
562  aTmp *= surfaceAlpha;
563  R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
564  G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
565  B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
566  }
567  *pixel = R | G | B | (A << Ashift & Amask);
568 
569  }
570  }
571  break;
572 #endif
573  }
574  }
575 
576  return (0);
577 }
578 
589 int pixelColor(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
590 {
591  Uint8 alpha;
592  Uint32 mcolor;
593  int result = 0;
594 
595  /*
596  * Lock the surface
597  */
598  if (SDL_MUSTLOCK(dst)) {
599  if (SDL_LockSurface(dst) < 0) {
600  return (-1);
601  }
602  }
603 
604  /*
605  * Setup color
606  */
607  alpha = color & 0x000000ff;
608  mcolor =
609  SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
610  (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
611 
612  /*
613  * Draw
614  */
615  result = _putPixelAlpha(dst, x, y, mcolor, alpha);
616 
617  /*
618  * Unlock the surface
619  */
620  if (SDL_MUSTLOCK(dst)) {
621  SDL_UnlockSurface(dst);
622  }
623 
624  return (result);
625 }
626 
637 int pixelColorNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color)
638 {
639  Uint8 alpha;
640  Uint32 mcolor;
641  int result = 0;
642 
643  /*
644  * Setup color
645  */
646  alpha = color & 0x000000ff;
647  mcolor =
648  SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
649  (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
650 
651  /*
652  * Draw
653  */
654  result = _putPixelAlpha(dst, x, y, mcolor, alpha);
655 
656  return (result);
657 }
658 
674 int _filledRectAlpha(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color, Uint8 alpha)
675 {
676  SDL_PixelFormat *format;
677  Uint32 Rmask, Bmask, Gmask, Amask;
678  Uint32 Rshift, Bshift, Gshift, Ashift;
679  Uint8 sR, sG, sB, sA;
680  Uint32 R, G, B, A;
681  Sint16 x, y;
682 
683  format = dst->format;
684  switch (format->BytesPerPixel) {
685  case 1:
686  { /* Assuming 8-bpp */
687  Uint8 *row, *pixel;
688  Uint8 dR, dG, dB;
689  SDL_Palette *palette = format->palette;
690  SDL_Color *colors = palette->colors;
691  sR = colors[color].r;
692  sG = colors[color].g;
693  sB = colors[color].b;
694 
695  for (y = yy; y <= y2; y++) {
696  if (y < 0 || y >= dst->h) {
697  continue;
698  }
699  row = (Uint8 *) dst->pixels + y * dst->pitch;
700  for (x = xx; x <= x2; x++) {
701  if (x < 0 || x >= dst->w) {
702  continue;
703  }
704  pixel = row + x;
705 
706  dR = colors[*pixel].r;
707  dG = colors[*pixel].g;
708  dB = colors[*pixel].b;
709 
710  dR = dR + ((sR - dR) * alpha >> 8);
711  dG = dG + ((sG - dG) * alpha >> 8);
712  dB = dB + ((sB - dB) * alpha >> 8);
713 
714  *pixel = SDL_MapRGB(format, dR, dG, dB);
715  }
716  }
717  }
718  break;
719 
720  case 2:
721  { /* Probably 15-bpp or 16-bpp */
722  Uint16 *row, *pixel;
723  Uint32 dR, dG, dB, dA;
724  Rmask = format->Rmask;
725  Gmask = format->Gmask;
726  Bmask = format->Bmask;
727  Amask = format->Amask;
728 
729  dR = (color & Rmask);
730  dG = (color & Gmask);
731  dB = (color & Bmask);
732  dA = (color & Amask);
733 
734  A = 0;
735 
736  for (y = yy; y <= y2; y++) {
737  if (y < 0 || y >= dst->h) {
738  continue;
739  }
740  row = (Uint16 *) dst->pixels + y * dst->pitch / 2;
741  for (x = xx; x <= x2; x++) {
742  if (x < 0 || x >= dst->w) {
743  continue;
744  }
745  pixel = row + x;
746 
747  R = ((*pixel & Rmask) + ((dR - (*pixel & Rmask)) * alpha >> 8)) & Rmask;
748  G = ((*pixel & Gmask) + ((dG - (*pixel & Gmask)) * alpha >> 8)) & Gmask;
749  B = ((*pixel & Bmask) + ((dB - (*pixel & Bmask)) * alpha >> 8)) & Bmask;
750  if (Amask) {
751  A = ((*pixel & Amask) + ((dA - (*pixel & Amask)) * alpha >> 8)) & Amask;
752  *pixel = R | G | B | A;
753  } else {
754  *pixel = R | G | B;
755  }
756  }
757  }
758  }
759  break;
760 
761  case 3:
762  { /* Slow 24-bpp mode, usually not used */
763  Uint8 *row, *pix;
764  Uint8 dR, dG, dB, dA;
765  Uint8 Rshift8, Gshift8, Bshift8, Ashift8;
766 
767  Rshift = format->Rshift;
768  Gshift = format->Gshift;
769  Bshift = format->Bshift;
770  Ashift = format->Ashift;
771 
772  Rshift8 = Rshift / 8;
773  Gshift8 = Gshift / 8;
774  Bshift8 = Bshift / 8;
775  Ashift8 = Ashift / 8;
776 
777  sR = (color >> Rshift) & 0xff;
778  sG = (color >> Gshift) & 0xff;
779  sB = (color >> Bshift) & 0xff;
780  sA = (color >> Ashift) & 0xff;
781 
782  for (y = yy; y <= y2; y++) {
783  if (y < 0 || y >= dst->h) {
784  continue;
785  }
786  row = (Uint8 *) dst->pixels + y * dst->pitch;
787  for (x = xx; x <= x2; x++) {
788  if (x < 0 || x >= dst->w) {
789  continue;
790  }
791  pix = row + x * 3;
792 
793  dR = *((pix) + Rshift8);
794  dG = *((pix) + Gshift8);
795  dB = *((pix) + Bshift8);
796  dA = *((pix) + Ashift8);
797 
798  dR = dR + ((sR - dR) * alpha >> 8);
799  dG = dG + ((sG - dG) * alpha >> 8);
800  dB = dB + ((sB - dB) * alpha >> 8);
801  dA = dA + ((sA - dA) * alpha >> 8);
802 
803  *((pix) + Rshift8) = dR;
804  *((pix) + Gshift8) = dG;
805  *((pix) + Bshift8) = dB;
806  *((pix) + Ashift8) = dA;
807  }
808  }
809  }
810  break;
811 
812 #ifdef DEFAULT_ALPHA_PIXEL_ROUTINE
813  case 4:
814  { /* Probably :-) 32-bpp */
815  Uint32 *row, *pixel;
816  Uint32 dR, dG, dB, dA;
817 
818  Rmask = format->Rmask;
819  Gmask = format->Gmask;
820  Bmask = format->Bmask;
821  Amask = format->Amask;
822 
823  Rshift = format->Rshift;
824  Gshift = format->Gshift;
825  Bshift = format->Bshift;
826  Ashift = format->Ashift;
827 
828  dR = (color & Rmask);
829  dG = (color & Gmask);
830  dB = (color & Bmask);
831  dA = (color & Amask);
832 
833  for (y = yy; y <= y2; y++) {
834  if (y < 0 || y >= dst->h) {
835  continue;
836  }
837  row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
838  for (x = xx; x <= x2; x++) {
839  if (x < 0 || x >= dst->w) {
840  continue;
841  }
842  pixel = row + x;
843 
844  R = ((*pixel & Rmask) + ((((dR - (*pixel & Rmask)) >> Rshift) * alpha >> 8) << Rshift)) & Rmask;
845  G = ((*pixel & Gmask) + ((((dG - (*pixel & Gmask)) >> Gshift) * alpha >> 8) << Gshift)) & Gmask;
846  B = ((*pixel & Bmask) + ((((dB - (*pixel & Bmask)) >> Bshift) * alpha >> 8) << Bshift)) & Bmask;
847  if (Amask) {
848  A = ((*pixel & Amask) + ((((dA - (*pixel & Amask)) >> Ashift) * alpha >> 8) << Ashift)) & Amask;
849  *pixel = R | G | B | A;
850  } else {
851  *pixel = R | G | B;
852  }
853  }
854  }
855  }
856  break;
857 #endif
858 
859 #ifdef EXPERIMENTAL_ALPHA_PIXEL_ROUTINE
860  case 4:
861  { /* Probably :-) 32-bpp */
862  Uint32 *row, *pixel;
863  Uint32 dR, dG, dB, dA;
864  Uint32 dc;
865  Uint32 surfaceAlpha, preMultR, preMultG, preMultB;
866  Uint32 aTmp;
867 
868  Rmask = format->Rmask;
869  Gmask = format->Gmask;
870  Bmask = format->Bmask;
871  Amask = format->Amask;
872 
873  dR = (color & Rmask);
874  dG = (color & Gmask);
875  dB = (color & Bmask);
876  dA = (color & Amask);
877 
878  Rshift = format->Rshift;
879  Gshift = format->Gshift;
880  Bshift = format->Bshift;
881  Ashift = format->Ashift;
882 
883  preMultR = (alpha * (dR >> Rshift));
884  preMultG = (alpha * (dG >> Gshift));
885  preMultB = (alpha * (dB >> Bshift));
886 
887  for (y = y1; y <= y2; y++) {
888  if (y < 0 || y >= dst->h) {
889  continue;
890  }
891  row = (Uint32 *) dst->pixels + y * dst->pitch / 4;
892  for (x = x1; x <= x2; x++) {
893  if (x < 0 || x >= dst->w) {
894  continue;
895  }
896  pixel = row + x;
897  dc = *pixel;
898 
899  surfaceAlpha = ((dc & Amask) >> Ashift);
900  aTmp = (255 - alpha);
901  if (A = 255 - ((aTmp * (255 - surfaceAlpha)) >> 8 )) {
902  aTmp *= surfaceAlpha;
903  R = (preMultR + ((aTmp * ((dc & Rmask) >> Rshift)) >> 8)) / A << Rshift & Rmask;
904  G = (preMultG + ((aTmp * ((dc & Gmask) >> Gshift)) >> 8)) / A << Gshift & Gmask;
905  B = (preMultB + ((aTmp * ((dc & Bmask) >> Bshift)) >> 8)) / A << Bshift & Bmask;
906  }
907  *pixel = R | G | B | (A << Ashift & Amask);
908 
909  }
910  }
911  }
912  break;
913 #endif
914 
915  }
916 
917  return (0);
918 }
919 
932 int filledRectAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
933 {
934  Uint8 alpha;
935  Uint32 mcolor;
936  int result = 0;
937 
938  /*
939  * Lock the surface
940  */
941  if (SDL_MUSTLOCK(dst)) {
942  if (SDL_LockSurface(dst) < 0) {
943  return (-1);
944  }
945  }
946 
947  /*
948  * Setup color
949  */
950  alpha = color & 0x000000ff;
951  mcolor =
952  SDL_MapRGBA(dst->format, (color & 0xff000000) >> 24,
953  (color & 0x00ff0000) >> 16, (color & 0x0000ff00) >> 8, alpha);
954 
955  /*
956  * Draw
957  */
958  result = _filledRectAlpha(dst, x, y, x2, y2, mcolor, alpha);
959 
960  /*
961  * Unlock the surface
962  */
963  if (SDL_MUSTLOCK(dst)) {
964  SDL_UnlockSurface(dst);
965  }
966 
967  return (result);
968 }
969 
981 int _HLineAlpha(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
982 {
983  return (filledRectAlpha(dst, x1, y, x2, y, color));
984 }
985 
997 int _VLineAlpha(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color)
998 {
999  return (filledRectAlpha(dst, x, y, x, y2, color));
1000 }
1001 
1013 int pixelColorWeight(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
1014 {
1015  Uint32 a;
1016 
1017  /*
1018  * Get alpha
1019  */
1020  a = (color & (Uint32) 0x000000ff);
1021 
1022  /*
1023  * Modify Alpha by weight
1024  */
1025  a = ((a * weight) >> 8);
1026 
1027  return (pixelColor(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
1028 }
1029 
1041 int pixelColorWeightNolock(SDL_Surface * dst, Sint16 x, Sint16 y, Uint32 color, Uint32 weight)
1042 {
1043  Uint32 a;
1044 
1045  /*
1046  * Get alpha
1047  */
1048  a = (color & (Uint32) 0x000000ff);
1049 
1050  /*
1051  * Modify Alpha by weight
1052  */
1053  a = ((a * weight) >> 8);
1054 
1055  return (pixelColorNolock(dst, x, y, (color & (Uint32) 0xffffff00) | (Uint32) a));
1056 }
1057 
1071 int pixelRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1072 {
1073  Uint32 color;
1074 
1075  /*
1076  * Check Alpha
1077  */
1078  if (a == 255) {
1079  /*
1080  * No alpha blending required
1081  */
1082  /*
1083  * Setup color
1084  */
1085  color = SDL_MapRGBA(dst->format, r, g, b, a);
1086  /*
1087  * Draw
1088  */
1089  return (fastPixelColor(dst, x, y, color));
1090  } else {
1091  /*
1092  * Alpha blending required
1093  */
1094  /*
1095  * Draw
1096  */
1097  return (pixelColor(dst, x, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1098  }
1099 }
1100 
1116 int hlineColorStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
1117 {
1118  Sint16 left, right, top, bottom;
1119  Uint8 *pixel, *pixellast;
1120  int dx;
1121  int pixx, pixy;
1122  Sint16 w;
1123  Sint16 xtmp;
1124  int result = -1;
1125 
1126  /*
1127  * Check visibility of clipping rectangle
1128  */
1129  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1130  return (0);
1131  }
1132 
1133  /*
1134  * Swap x1, x2 if required to ensure x1<=x2
1135  */
1136  if (x1 > x2) {
1137  xtmp = x1;
1138  x1 = x2;
1139  x2 = xtmp;
1140  }
1141 
1142  /*
1143  * Get clipping boundary and
1144  * check visibility of hline
1145  */
1146  left = dst->clip_rect.x;
1147  if (x2 < left) {
1148  return (0);
1149  }
1150  right = dst->clip_rect.x + dst->clip_rect.w - 1;
1151  if (x1 > right) {
1152  return (0);
1153  }
1154  top = dst->clip_rect.y;
1155  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1156  if ((y < top) || (y > bottom)) {
1157  return (0);
1158  }
1159 
1160  /*
1161  * Clip x
1162  */
1163  if (x1 < left) {
1164  x1 = left;
1165  }
1166  if (x2 > right) {
1167  x2 = right;
1168  }
1169 
1170  /*
1171  * Calculate width
1172  */
1173  w = x2 - x1;
1174 
1175  /*
1176  * Lock the surface
1177  */
1178  if (SDL_MUSTLOCK(dst)) {
1179  if (SDL_LockSurface(dst) < 0) {
1180  return (-1);
1181  }
1182  }
1183 
1184  /*
1185  * More variable setup
1186  */
1187  dx = w;
1188  pixx = dst->format->BytesPerPixel;
1189  pixy = dst->pitch;
1190  pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
1191 
1192  /*
1193  * Draw
1194  */
1195  switch (dst->format->BytesPerPixel) {
1196  case 1:
1197  memset(pixel, color, dx + 1);
1198  break;
1199  case 2:
1200  pixellast = pixel + dx + dx;
1201  for (; pixel <= pixellast; pixel += pixx) {
1202  *(Uint16 *) pixel = color;
1203  }
1204  break;
1205  case 3:
1206  pixellast = pixel + dx + dx + dx;
1207  for (; pixel <= pixellast; pixel += pixx) {
1208  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1209  pixel[0] = (color >> 16) & 0xff;
1210  pixel[1] = (color >> 8) & 0xff;
1211  pixel[2] = color & 0xff;
1212  } else {
1213  pixel[0] = color & 0xff;
1214  pixel[1] = (color >> 8) & 0xff;
1215  pixel[2] = (color >> 16) & 0xff;
1216  }
1217  }
1218  break;
1219  default: /* case 4 */
1220  dx = dx + dx;
1221  pixellast = pixel + dx + dx;
1222  for (; pixel <= pixellast; pixel += pixx) {
1223  *(Uint32 *) pixel = color;
1224  }
1225  break;
1226  }
1227 
1228  /*
1229  * Unlock surface
1230  */
1231  if (SDL_MUSTLOCK(dst)) {
1232  SDL_UnlockSurface(dst);
1233  }
1234 
1235  /*
1236  * Set result code
1237  */
1238  result = 0;
1239 
1240  return (result);
1241 }
1242 
1260 int hlineRGBAStore(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1261 {
1262  /*
1263  * Draw
1264  */
1265  return (hlineColorStore(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1266 }
1267 
1279 int hlineColor(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
1280 {
1281  Sint16 left, right, top, bottom;
1282  Uint8 *pixel, *pixellast;
1283  int dx;
1284  int pixx, pixy;
1285  Sint16 xtmp;
1286  int result = -1;
1287  Uint8 *colorptr;
1288  Uint8 color3[3];
1289 
1290  /*
1291  * Check visibility of clipping rectangle
1292  */
1293  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1294  return (0);
1295  }
1296 
1297  /*
1298  * Swap x1, x2 if required to ensure x1<=x2
1299  */
1300  if (x1 > x2) {
1301  xtmp = x1;
1302  x1 = x2;
1303  x2 = xtmp;
1304  }
1305 
1306  /*
1307  * Get clipping boundary and
1308  * check visibility of hline
1309  */
1310  left = dst->clip_rect.x;
1311  if (x2 < left) {
1312  return (0);
1313  }
1314  right = dst->clip_rect.x + dst->clip_rect.w - 1;
1315  if (x1 > right) {
1316  return (0);
1317  }
1318  top = dst->clip_rect.y;
1319  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1320  if ((y < top) || (y > bottom)) {
1321  return (0);
1322  }
1323 
1324  /*
1325  * Clip x
1326  */
1327  if (x1 < left) {
1328  x1 = left;
1329  }
1330  if (x2 > right) {
1331  x2 = right;
1332  }
1333 
1334  /*
1335  * Calculate width difference
1336  */
1337  dx = x2 - x1;
1338 
1339  /*
1340  * Alpha check
1341  */
1342  if ((color & 255) == 255) {
1343 
1344  /*
1345  * No alpha-blending required
1346  */
1347 
1348  /*
1349  * Setup color
1350  */
1351  colorptr = (Uint8 *) & color;
1352  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1353  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1354  } else {
1355  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1356  }
1357 
1358  /*
1359  * Lock the surface
1360  */
1361  if (SDL_MUSTLOCK(dst)) {
1362  if (SDL_LockSurface(dst) < 0) {
1363  return (-1);
1364  }
1365  }
1366 
1367  /*
1368  * More variable setup
1369  */
1370  pixx = dst->format->BytesPerPixel;
1371  pixy = dst->pitch;
1372  pixel = ((Uint8 *) dst->pixels) + pixx * (int) x1 + pixy * (int) y;
1373 
1374  /*
1375  * Draw
1376  */
1377  switch (dst->format->BytesPerPixel) {
1378  case 1:
1379  memset(pixel, color, dx + 1);
1380  break;
1381  case 2:
1382  pixellast = pixel + dx + dx;
1383  for (; pixel <= pixellast; pixel += pixx) {
1384  *(Uint16 *) pixel = color;
1385  }
1386  break;
1387  case 3:
1388  pixellast = pixel + dx + dx + dx;
1389  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1390  color3[0] = (color >> 16) & 0xff;
1391  color3[1] = (color >> 8) & 0xff;
1392  color3[2] = color & 0xff;
1393  } else {
1394  color3[0] = color & 0xff;
1395  color3[1] = (color >> 8) & 0xff;
1396  color3[2] = (color >> 16) & 0xff;
1397  }
1398  for (; pixel <= pixellast; pixel += pixx) {
1399  memcpy(pixel, color3, 3);
1400  }
1401  break;
1402  default: /* case 4 */
1403  dx = dx + dx;
1404  pixellast = pixel + dx + dx;
1405  for (; pixel <= pixellast; pixel += pixx) {
1406  *(Uint32 *) pixel = color;
1407  }
1408  break;
1409  }
1410 
1411  /*
1412  * Unlock surface
1413  */
1414  if (SDL_MUSTLOCK(dst)) {
1415  SDL_UnlockSurface(dst);
1416  }
1417 
1418  /*
1419  * Set result code
1420  */
1421  result = 0;
1422 
1423  } else {
1424 
1425  /*
1426  * Alpha blending blit
1427  */
1428  result = _HLineAlpha(dst, x1, x1 + dx, y, color);
1429  }
1430 
1431  return (result);
1432 }
1433 
1448 int hlineRGBA(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1449 {
1450  /*
1451  * Draw
1452  */
1453  return (hlineColor(dst, x1, x2, y, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1454 }
1455 
1467 int vlineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint32 color)
1468 {
1469  Sint16 left, right, top, bottom;
1470  Uint8 *pixel, *pixellast;
1471  int dy;
1472  int pixx, pixy;
1473  Sint16 h;
1474  Sint16 ytmp;
1475  int result = -1;
1476  Uint8 *colorptr;
1477 
1478  /*
1479  * Check visibility of clipping rectangle
1480  */
1481  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1482  return (0);
1483  }
1484 
1485  /*
1486  * Swap y1, y2 if required to ensure y1<=y2
1487  */
1488  if (y > y2) {
1489  ytmp = y;
1490  y = y2;
1491  y2 = ytmp;
1492  }
1493 
1494  /*
1495  * Get clipping boundary and
1496  * check visibility of vline
1497  */
1498  left = dst->clip_rect.x;
1499  right = dst->clip_rect.x + dst->clip_rect.w - 1;
1500  if ((x < left) || (x > right)) {
1501  return (0);
1502  }
1503  top = dst->clip_rect.y;
1504  if (y2 < top) {
1505  return (0);
1506  }
1507  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
1508  if (y > bottom) {
1509  return (0);
1510  }
1511 
1512  /*
1513  * Clip x
1514  */
1515  if (y < top) {
1516  y = top;
1517  }
1518  if (y2 > bottom) {
1519  y2 = bottom;
1520  }
1521 
1522  /*
1523  * Calculate height
1524  */
1525  h = y2 - y;
1526 
1527  /*
1528  * Alpha check
1529  */
1530  if ((color & 255) == 255) {
1531 
1532  /*
1533  * No alpha-blending required
1534  */
1535 
1536  /*
1537  * Setup color
1538  */
1539  colorptr = (Uint8 *) & color;
1540  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1541  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
1542  } else {
1543  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
1544  }
1545 
1546  /*
1547  * Lock the surface
1548  */
1549  if (SDL_MUSTLOCK(dst)) {
1550  if (SDL_LockSurface(dst) < 0) {
1551  return (-1);
1552  }
1553  }
1554 
1555  /*
1556  * More variable setup
1557  */
1558  dy = h;
1559  pixx = dst->format->BytesPerPixel;
1560  pixy = dst->pitch;
1561  pixel = ((Uint8 *) dst->pixels) + pixx * (int) x + pixy * (int) y;
1562  pixellast = pixel + pixy * dy;
1563 
1564  /*
1565  * Draw
1566  */
1567  switch (dst->format->BytesPerPixel) {
1568  case 1:
1569  for (; pixel <= pixellast; pixel += pixy) {
1570  *(Uint8 *) pixel = color;
1571  }
1572  break;
1573  case 2:
1574  for (; pixel <= pixellast; pixel += pixy) {
1575  *(Uint16 *) pixel = color;
1576  }
1577  break;
1578  case 3:
1579  for (; pixel <= pixellast; pixel += pixy) {
1580  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
1581  pixel[0] = (color >> 16) & 0xff;
1582  pixel[1] = (color >> 8) & 0xff;
1583  pixel[2] = color & 0xff;
1584  } else {
1585  pixel[0] = color & 0xff;
1586  pixel[1] = (color >> 8) & 0xff;
1587  pixel[2] = (color >> 16) & 0xff;
1588  }
1589  }
1590  break;
1591  default: /* case 4 */
1592  for (; pixel <= pixellast; pixel += pixy) {
1593  *(Uint32 *) pixel = color;
1594  }
1595  break;
1596  }
1597 
1598  /* Unlock surface */
1599  if (SDL_MUSTLOCK(dst)) {
1600  SDL_UnlockSurface(dst);
1601  }
1602 
1603  /*
1604  * Set result code
1605  */
1606  result = 0;
1607 
1608  } else {
1609 
1610  /*
1611  * Alpha blending blit
1612  */
1613 
1614  result = _VLineAlpha(dst, x, y, y + h, color);
1615 
1616  }
1617 
1618  return (result);
1619 }
1620 
1635 int vlineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1636 {
1637  /*
1638  * Draw
1639  */
1640  return (vlineColor(dst, x, y, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1641 }
1642 
1655 int rectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
1656 {
1657  int result;
1658  Sint16 tmp;
1659 
1660  /* Check destination surface */
1661  if (dst == NULL) {
1662  return -1;
1663  }
1664 
1665  /*
1666  * Check visibility of clipping rectangle
1667  */
1668  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1669  return 0;
1670  }
1671 
1672  /*
1673  * Test for special cases of straight lines or single point
1674  */
1675  if (x == x2) {
1676  if (y == y2) {
1677  return (pixelColor(dst, x, y, color));
1678  } else {
1679  return (vlineColor(dst, x, y, y2, color));
1680  }
1681  } else {
1682  if (y == y2) {
1683  return (hlineColor(dst, x, x2, y, color));
1684  }
1685  }
1686 
1687  /*
1688  * Swap x1, x2 if required
1689  */
1690  if (x > x2) {
1691  tmp = x;
1692  x = x2;
1693  x2 = tmp;
1694  }
1695 
1696  /*
1697  * Swap y1, y2 if required
1698  */
1699  if (y > y2) {
1700  tmp = y;
1701  y = y2;
1702  y2 = tmp;
1703  }
1704 
1705  /*
1706  * Draw rectangle
1707  */
1708  result = 0;
1709  result |= hlineColor(dst, x, x2, y, color);
1710  result |= hlineColor(dst, x, x2, y2, color);
1711  y += 1;
1712  y2 -= 1;
1713  if (y <= y2) {
1714  result |= vlineColor(dst, x, y, y2, color);
1715  result |= vlineColor(dst, x2, y, y2, color);
1716  }
1717 
1718  return (result);
1719 
1720 }
1721 
1737 int rectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1738 {
1739  /*
1740  * Draw
1741  */
1742  return (rectangleColor
1743  (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1744 }
1745 
1759 int roundedRectangleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
1760 {
1761  int result;
1762  Sint16 w, h, tmp;
1763  Sint16 xx1, xx2, yy1, yy2;
1764 
1765  /*
1766  * Check destination surface
1767  */
1768  if (dst == NULL) {
1769  return -1;
1770  }
1771 
1772  /*
1773  * Check radius vor valid range
1774  */
1775  if (rad < 0) {
1776  return -1;
1777  }
1778 
1779  /*
1780  * Special case - no rounding
1781  */
1782  if (rad == 0) {
1783  return rectangleColor(dst, x, y, x2, y2, color);
1784  }
1785 
1786  /*
1787  * Check visibility of clipping rectangle
1788  */
1789  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1790  return 0;
1791  }
1792 
1793  /*
1794  * Test for special cases of straight lines or single point
1795  */
1796  if (x == x2) {
1797  if (y == y2) {
1798  return (pixelColor(dst, x, y, color));
1799  } else {
1800  return (vlineColor(dst, x, y, y2, color));
1801  }
1802  } else {
1803  if (y == y2) {
1804  return (hlineColor(dst, x, x2, y, color));
1805  }
1806  }
1807 
1808  /*
1809  * Swap x1, x2 if required
1810  */
1811  if (x > x2) {
1812  tmp = x;
1813  x = x2;
1814  x2 = tmp;
1815  }
1816 
1817  /*
1818  * Swap y1, y2 if required
1819  */
1820  if (y > y2) {
1821  tmp = y;
1822  y = y2;
1823  y2 = tmp;
1824  }
1825 
1826  /*
1827  * Calculate width&height
1828  */
1829  w = x2 - x;
1830  h = y2 - y;
1831 
1832  /*
1833  * Maybe adjust radius
1834  */
1835  if ((rad * 2) > w) {
1836  rad = w / 2;
1837  }
1838  if ((rad * 2) > h) {
1839  rad = h / 2;
1840  }
1841 
1842  /*
1843  * Draw corners
1844  */
1845  result = 0;
1846  xx1 = x + rad;
1847  xx2 = x2 - rad;
1848  yy1 = y + rad;
1849  yy2 = y2 - rad;
1850  result |= arcColor(dst, xx1, yy1, rad, 180, 270, color);
1851  result |= arcColor(dst, xx2, yy1, rad, 270, 360, color);
1852  result |= arcColor(dst, xx1, yy2, rad, 90, 180, color);
1853  result |= arcColor(dst, xx2, yy2, rad, 0, 90, color);
1854 
1855  /*
1856  * Draw lines
1857  */
1858  if (xx1 <= xx2) {
1859  result |= hlineColor(dst, xx1, xx2, y, color);
1860  result |= hlineColor(dst, xx1, xx2, y2, color);
1861  }
1862  if (yy1 <= yy2) {
1863  result |= vlineColor(dst, x, yy1, yy2, color);
1864  result |= vlineColor(dst, x2, yy1, yy2, color);
1865  }
1866 
1867  return result;
1868 }
1869 
1886 int roundedRectangleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1887 {
1888  /*
1889  * Draw
1890  */
1891  return (roundedRectangleColor
1892  (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
1893 }
1894 
1908 int roundedBoxColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
1909 {
1910  int result;
1911  Sint16 w, h, tmp;
1912  Sint16 xx1, xx2, yy1, yy2;
1913 
1914  /*
1915  * Check destination surface
1916  */
1917  if (dst == NULL) {
1918  return -1;
1919  }
1920 
1921  /*
1922  * Check radius vor valid range
1923  */
1924  if (rad < 0) {
1925  return -1;
1926  }
1927 
1928  /*
1929  * Special case - no rounding
1930  */
1931  if (rad == 0) {
1932  return rectangleColor(dst, x, y, x2, y2, color);
1933  }
1934 
1935  /*
1936  * Check visibility of clipping rectangle
1937  */
1938  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
1939  return 0;
1940  }
1941 
1942  /*
1943  * Test for special cases of straight lines or single point
1944  */
1945  if (x == x2) {
1946  if (y == y2) {
1947  return (pixelColor(dst, x, y, color));
1948  } else {
1949  return (vlineColor(dst, x, y, y2, color));
1950  }
1951  } else {
1952  if (y == y2) {
1953  return (hlineColor(dst, x, x2, y, color));
1954  }
1955  }
1956 
1957  /*
1958  * Swap x1, x2 if required
1959  */
1960  if (x > x2) {
1961  tmp = x;
1962  x = x2;
1963  x2 = tmp;
1964  }
1965 
1966  /*
1967  * Swap y1, y2 if required
1968  */
1969  if (y > y2) {
1970  tmp = y;
1971  y = y2;
1972  y2 = tmp;
1973  }
1974 
1975  /*
1976  * Calculate width&height
1977  */
1978  w = x2 - x;
1979  h = y2 - y;
1980 
1981  /*
1982  * Maybe adjust radius
1983  */
1984  if ((rad * 2) > w) {
1985  rad = w / 2;
1986  }
1987  if ((rad * 2) > h) {
1988  rad = h / 2;
1989  }
1990 
1991  /*
1992  * Draw corners
1993  */
1994  result = 0;
1995  xx1 = x + rad;
1996  xx2 = x2 - rad;
1997  yy1 = y + rad;
1998  yy2 = y2 - rad;
1999  result |= filledPieColor(dst, xx1, yy1, rad, 180, 270, color);
2000  result |= filledPieColor(dst, xx2, yy1, rad, 270, 360, color);
2001  result |= filledPieColor(dst, xx1, yy2, rad, 90, 180, color);
2002  result |= filledPieColor(dst, xx2, yy2, rad, 0, 90, color);
2003 
2004  /*
2005  * Draw body
2006  */
2007  xx1++;
2008  xx2--;
2009  yy1++;
2010  yy2--;
2011  if (xx1 <= xx2) {
2012  result |= boxColor(dst, xx1, y, xx2, y2, color);
2013  }
2014  if (yy1 <= yy2) {
2015  result |= boxColor(dst, x, yy1, xx1 - 1, yy2, color);
2016  result |= boxColor(dst, xx2 + 1, yy1, x2, yy2, color);
2017  }
2018 
2019  return result;
2020 }
2021 
2038 int roundedBoxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2,
2039  Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2040 {
2041  /*
2042  * Draw
2043  */
2044  return (roundedBoxColor
2045  (dst, x, y, x2, y2, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2046 }
2047 
2048 /* --------- Clipping routines for line */
2049 
2050 /* Clipping based heavily on code from */
2051 /* http://www.ncsa.uiuc.edu/Vis/Graphics/src/clipCohSuth.c */
2052 
2053 #define CLIP_LEFT_EDGE 0x1
2054 #define CLIP_RIGHT_EDGE 0x2
2055 #define CLIP_BOTTOM_EDGE 0x4
2056 #define CLIP_TOP_EDGE 0x8
2057 #define CLIP_INSIDE(a) (!a)
2058 #define CLIP_REJECT(a,b) (a&b)
2059 #define CLIP_ACCEPT(a,b) (!(a|b))
2060 
2073 static int _clipEncode(Sint16 x, Sint16 y, Sint16 left, Sint16 top, Sint16 right, Sint16 bottom)
2074 {
2075  int code = 0;
2076 
2077  if (x < left) {
2078  code |= CLIP_LEFT_EDGE;
2079  } else if (x > right) {
2080  code |= CLIP_RIGHT_EDGE;
2081  }
2082  if (y < top) {
2083  code |= CLIP_TOP_EDGE;
2084  } else if (y > bottom) {
2085  code |= CLIP_BOTTOM_EDGE;
2086  }
2087  return code;
2088 }
2089 
2099 static int _clipLine(SDL_Surface * dst, Sint16 * x, Sint16 * y, Sint16 * x2, Sint16 * y2)
2100 {
2101  Sint16 left, right, top, bottom;
2102  int code1, code2;
2103  int draw = 0;
2104  Sint16 swaptmp;
2105  float m;
2106 
2107  /*
2108  * Get clipping boundary
2109  */
2110  left = dst->clip_rect.x;
2111  right = dst->clip_rect.x + dst->clip_rect.w - 1;
2112  top = dst->clip_rect.y;
2113  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2114 
2115  while (1) {
2116  code1 = _clipEncode(*x, *y, left, top, right, bottom);
2117  code2 = _clipEncode(*x2, *y2, left, top, right, bottom);
2118  if (CLIP_ACCEPT(code1, code2)) {
2119  draw = 1;
2120  break;
2121  } else if (CLIP_REJECT(code1, code2)) {
2122  break;
2123  } else {
2124  if (CLIP_INSIDE(code1)) {
2125  swaptmp = *x2;
2126  *x2 = *x;
2127  *x = swaptmp;
2128  swaptmp = *y2;
2129  *y2 = *y;
2130  *y = swaptmp;
2131  code1 = code2;
2132  }
2133  if (*x2 != *x) {
2134  m = (*y2 - *y) / (float) (*x2 - *x);
2135  } else {
2136  m = 1.0f;
2137  }
2138  if (code1 & CLIP_LEFT_EDGE) {
2139  *y += (Sint16) ((left - *x) * m);
2140  *x = left;
2141  } else if (code1 & CLIP_RIGHT_EDGE) {
2142  *y += (Sint16) ((right - *x) * m);
2143  *x = right;
2144  } else if (code1 & CLIP_BOTTOM_EDGE) {
2145  if (*x2 != *x) {
2146  *x += (Sint16) ((bottom - *y) / m);
2147  }
2148  *y = bottom;
2149  } else if (code1 & CLIP_TOP_EDGE) {
2150  if (*x2 != *x) {
2151  *x += (Sint16) ((top - *y) / m);
2152  }
2153  *y = top;
2154  }
2155  }
2156  }
2157 
2158  return draw;
2159 }
2160 
2173 int boxColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color)
2174 {
2175  Sint16 left, right, top, bottom;
2176  Uint8 *pixel, *pixellast;
2177  int x, dx;
2178  int dy;
2179  int pixx, pixy;
2180  Sint16 w, h, tmp;
2181  int result;
2182  Uint8 *colorptr;
2183 
2184  /*
2185  * Check visibility of clipping rectangle
2186  */
2187  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
2188  return (0);
2189  }
2190 
2191  /*
2192  * Order coordinates to ensure that
2193  * x1<=x2 and y1<=y2
2194  */
2195  if (xx > x2) {
2196  tmp = xx;
2197  xx = x2;
2198  x2 = tmp;
2199  }
2200  if (yy > y2) {
2201  tmp = yy;
2202  yy = y2;
2203  y2 = tmp;
2204  }
2205 
2206  /*
2207  * Get clipping boundary and
2208  * check visibility
2209  */
2210  left = dst->clip_rect.x;
2211  if (x2 < left) {
2212  return (0);
2213  }
2214  right = dst->clip_rect.x + dst->clip_rect.w - 1;
2215  if (xx > right) {
2216  return (0);
2217  }
2218  top = dst->clip_rect.y;
2219  if (y2 < top) {
2220  return (0);
2221  }
2222  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2223  if (yy > bottom) {
2224  return (0);
2225  }
2226 
2227  /* Clip all points */
2228  if (xx < left) {
2229  xx = left;
2230  } else if (xx > right) {
2231  xx = right;
2232  }
2233  if (x2 < left) {
2234  x2 = left;
2235  } else if (x2 > right) {
2236  x2 = right;
2237  }
2238  if (yy < top) {
2239  yy = top;
2240  } else if (yy > bottom) {
2241  yy = bottom;
2242  }
2243  if (y2 < top) {
2244  y2 = top;
2245  } else if (y2 > bottom) {
2246  y2 = bottom;
2247  }
2248 
2249  /*
2250  * Test for special cases of straight line or single point
2251  */
2252  if (xx == x2) {
2253  if (yy == y2) {
2254  return (pixelColor(dst, xx, yy, color));
2255  } else {
2256  return (vlineColor(dst, xx, yy, y2, color));
2257  }
2258  }
2259  if (yy == y2) {
2260  return (hlineColor(dst, xx, x2, yy, color));
2261  }
2262 
2263  /*
2264  * Calculate width&height
2265  */
2266  w = x2 - xx;
2267  h = y2 - yy;
2268 
2269  /*
2270  * Alpha check
2271  */
2272  if ((color & 255) == 255) {
2273 
2274  /*
2275  * No alpha-blending required
2276  */
2277 
2278  /*
2279  * Setup color
2280  */
2281  colorptr = (Uint8 *) & color;
2282  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2283  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2284  } else {
2285  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2286  }
2287 
2288  /*
2289  * Lock the surface
2290  */
2291  if (SDL_MUSTLOCK(dst)) {
2292  if (SDL_LockSurface(dst) < 0) {
2293  return (-1);
2294  }
2295  }
2296 
2297  /*
2298  * More variable setup
2299  */
2300  dx = w;
2301  dy = h;
2302  pixx = dst->format->BytesPerPixel;
2303  pixy = dst->pitch;
2304  pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy;
2305  pixellast = pixel + pixx * dx + pixy * dy;
2306  dx++;
2307 
2308  /*
2309  * Draw
2310  */
2311  switch (dst->format->BytesPerPixel) {
2312  case 1:
2313  for (; pixel <= pixellast; pixel += pixy) {
2314  memset(pixel, (Uint8) color, dx);
2315  }
2316  break;
2317  case 2:
2318  pixy -= (pixx * dx);
2319  for (; pixel <= pixellast; pixel += pixy) {
2320  for (x = 0; x < dx; x++) {
2321  *(Uint16*) pixel = color;
2322  pixel += pixx;
2323  }
2324  }
2325  break;
2326  case 3:
2327  pixy -= (pixx * dx);
2328  for (; pixel <= pixellast; pixel += pixy) {
2329  for (x = 0; x < dx; x++) {
2330  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2331  pixel[0] = (color >> 16) & 0xff;
2332  pixel[1] = (color >> 8) & 0xff;
2333  pixel[2] = color & 0xff;
2334  } else {
2335  pixel[0] = color & 0xff;
2336  pixel[1] = (color >> 8) & 0xff;
2337  pixel[2] = (color >> 16) & 0xff;
2338  }
2339  pixel += pixx;
2340  }
2341  }
2342  break;
2343  default: /* case 4 */
2344  pixy -= (pixx * dx);
2345  for (; pixel <= pixellast; pixel += pixy) {
2346  for (x = 0; x < dx; x++) {
2347  *(Uint32 *) pixel = color;
2348  pixel += pixx;
2349  }
2350  }
2351  break;
2352  }
2353 
2354  /* Unlock surface */
2355  if (SDL_MUSTLOCK(dst)) {
2356  SDL_UnlockSurface(dst);
2357  }
2358 
2359  result = 0;
2360 
2361  } else {
2362 
2363  result = filledRectAlpha(dst, xx, yy, xx + w, yy + h, color);
2364 
2365  }
2366 
2367  return (result);
2368 }
2369 
2385 int boxRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2386 {
2387  /*
2388  * Draw
2389  */
2390  return (boxColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2391 }
2392 
2393 /* ----- Line */
2394 
2395 /* Non-alpha line drawing code adapted from routine */
2396 /* by Pete Shinners, pete@shinners.org */
2397 /* Originally from pygame, http://pygame.seul.org */
2398 
2411 int lineColor(SDL_Surface * dst, Sint16 xx, Sint16 yy, Sint16 x2, Sint16 y2, Uint32 color)
2412 {
2413  int pixx, pixy;
2414  int x, y;
2415  int dx, dy;
2416  int ax, ay;
2417  int sx, sy;
2418  int swaptmp;
2419  Uint8 *pixel;
2420  Uint8 *colorptr;
2421 
2422  /*
2423  * Clip line and test if we have to draw
2424  */
2425  if (!(_clipLine(dst, &xx, &yy, &x2, &y2))) {
2426  return (0);
2427  }
2428 
2429  /*
2430  * Test for special cases of straight lines or single point
2431  */
2432  if (xx == x2) {
2433  if (yy < y2) {
2434  return (vlineColor(dst, xx, yy, y2, color));
2435  } else if (yy > y2) {
2436  return (vlineColor(dst, xx, y2, yy, color));
2437  } else {
2438  return (pixelColor(dst, xx, yy, color));
2439  }
2440  }
2441  if (yy == y2) {
2442  if (xx < x2) {
2443  return (hlineColor(dst, xx, x2, yy, color));
2444  } else if (xx > x2) {
2445  return (hlineColor(dst, x2, xx, yy, color));
2446  }
2447  }
2448 
2449  /*
2450  * Variable setup
2451  */
2452  dx = x2 - xx;
2453  dy = y2 - yy;
2454  sx = (dx >= 0) ? 1 : -1;
2455  sy = (dy >= 0) ? 1 : -1;
2456 
2457  /* Lock surface */
2458  if (SDL_MUSTLOCK(dst)) {
2459  if (SDL_LockSurface(dst) < 0) {
2460  return (-1);
2461  }
2462  }
2463 
2464  /*
2465  * Check for alpha blending
2466  */
2467  if ((color & 255) == 255) {
2468 
2469  /*
2470  * No alpha blending - use fast pixel routines
2471  */
2472 
2473  /*
2474  * Setup color
2475  */
2476  colorptr = (Uint8 *) & color;
2477  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2478  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
2479  } else {
2480  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
2481  }
2482 
2483  /*
2484  * More variable setup
2485  */
2486  dx = sx * dx + 1;
2487  dy = sy * dy + 1;
2488  pixx = dst->format->BytesPerPixel;
2489  pixy = dst->pitch;
2490  pixel = ((Uint8 *) dst->pixels) + pixx * (int) xx + pixy * (int) yy;
2491  pixx *= sx;
2492  pixy *= sy;
2493  if (dx < dy) {
2494  swaptmp = dx;
2495  dx = dy;
2496  dy = swaptmp;
2497  swaptmp = pixx;
2498  pixx = pixy;
2499  pixy = swaptmp;
2500  }
2501 
2502  /*
2503  * Draw
2504  */
2505  x = 0;
2506  y = 0;
2507  switch (dst->format->BytesPerPixel) {
2508  case 1:
2509  for (; x < dx; x++, pixel += pixx) {
2510  *pixel = color;
2511  y += dy;
2512  if (y >= dx) {
2513  y -= dx;
2514  pixel += pixy;
2515  }
2516  }
2517  break;
2518  case 2:
2519  for (; x < dx; x++, pixel += pixx) {
2520  *(Uint16 *) pixel = color;
2521  y += dy;
2522  if (y >= dx) {
2523  y -= dx;
2524  pixel += pixy;
2525  }
2526  }
2527  break;
2528  case 3:
2529  for (; x < dx; x++, pixel += pixx) {
2530  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
2531  pixel[0] = (color >> 16) & 0xff;
2532  pixel[1] = (color >> 8) & 0xff;
2533  pixel[2] = color & 0xff;
2534  } else {
2535  pixel[0] = color & 0xff;
2536  pixel[1] = (color >> 8) & 0xff;
2537  pixel[2] = (color >> 16) & 0xff;
2538  }
2539  y += dy;
2540  if (y >= dx) {
2541  y -= dx;
2542  pixel += pixy;
2543  }
2544  }
2545  break;
2546  default: /* case 4 */
2547  for (; x < dx; x++, pixel += pixx) {
2548  *(Uint32 *) pixel = color;
2549  y += dy;
2550  if (y >= dx) {
2551  y -= dx;
2552  pixel += pixy;
2553  }
2554  }
2555  break;
2556  }
2557 
2558  } else {
2559 
2560  /*
2561  * Alpha blending required - use single-pixel blits
2562  */
2563 
2564  ax = ABS(dx) << 1;
2565  ay = ABS(dy) << 1;
2566  x = xx;
2567  y = yy;
2568  if (ax > ay) {
2569  int d = ay - (ax >> 1);
2570 
2571  while (x != x2) {
2572  pixelColorNolock (dst, x, y, color);
2573  if (d > 0 || (d == 0 && sx == 1)) {
2574  y += sy;
2575  d -= ax;
2576  }
2577  x += sx;
2578  d += ay;
2579  }
2580  } else {
2581  int d = ax - (ay >> 1);
2582 
2583  while (y != y2) {
2584  pixelColorNolock (dst, x, y, color);
2585  if (d > 0 || ((d == 0) && (sy == 1))) {
2586  x += sx;
2587  d -= ay;
2588  }
2589  y += sy;
2590  d += ax;
2591  }
2592  }
2593  pixelColorNolock (dst, x, y, color);
2594 
2595  }
2596 
2597  /* Unlock surface */
2598  if (SDL_MUSTLOCK(dst)) {
2599  SDL_UnlockSurface(dst);
2600  }
2601 
2602  return (0);
2603 }
2604 
2620 int lineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2621 {
2622  /*
2623  * Draw
2624  */
2625  return (lineColor(dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
2626 }
2627 
2628 /* AA Line */
2629 
2630 #define AAlevels 256
2631 #define AAbits 8
2632 
2653 int _aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color, int draw_endpoint)
2654 {
2655  Sint32 xx0, yy0, xx1, yy1;
2656  int result;
2657  Uint32 intshift, erracc, erradj;
2658  Uint32 erracctmp, wgt;
2659  int dx, dy, tmp, xdir, y0p1, x0pxdir;
2660 
2661  /*
2662  * Check visibility of clipping rectangle
2663  */
2664  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
2665  return (0);
2666  }
2667 
2668  /*
2669  * Clip line and test if we have to draw
2670  */
2671  if (!(_clipLine(dst, &x, &y, &x2, &y2))) {
2672  return (0);
2673  }
2674 
2675  /*
2676  * Keep on working with 32bit numbers
2677  */
2678  xx0 = x;
2679  yy0 = y;
2680  xx1 = x2;
2681  yy1 = y2;
2682 
2683  /*
2684  * Reorder points if required
2685  */
2686  if (yy0 > yy1) {
2687  tmp = yy0;
2688  yy0 = yy1;
2689  yy1 = tmp;
2690  tmp = xx0;
2691  xx0 = xx1;
2692  xx1 = tmp;
2693  }
2694 
2695  /*
2696  * Calculate distance
2697  */
2698  dx = xx1 - xx0;
2699  dy = yy1 - yy0;
2700 
2701  /*
2702  * Check for special cases
2703  */
2704  if (dx == 0) {
2705  /*
2706  * Vertical line
2707  */
2708  if (draw_endpoint) {
2709  return (vlineColor(dst, x, y, y2, color));
2710  } else {
2711  if (dy > 0) {
2712  return (vlineColor(dst, x, yy0, yy0 + dy, color));
2713  } else {
2714  return (pixelColor(dst, x, y, color));
2715  }
2716  }
2717  } else if (dy == 0) {
2718  /*
2719  * Horizontal line
2720  */
2721  if (draw_endpoint) {
2722  return (hlineColor(dst, x, x2, y, color));
2723  } else {
2724  if (dx > 0) {
2725  return (hlineColor(dst, xx0, xx0 + dx, y, color));
2726  } else {
2727  return (pixelColor(dst, x, y, color));
2728  }
2729  }
2730  } else if ((dx == dy) && (draw_endpoint)) {
2731  /*
2732  * Diagonal line (with endpoint)
2733  */
2734  return (lineColor(dst, x, y, x2, y2, color));
2735  }
2736 
2737  /*
2738  * Adjust for negative dx and set xdir
2739  */
2740  if (dx >= 0) {
2741  xdir = 1;
2742  } else {
2743  xdir = -1;
2744  dx = (-dx);
2745  }
2746 
2747  /*
2748  * Line is not horizontal, vertical or diagonal (with endpoint)
2749  */
2750  result = 0;
2751 
2752  /*
2753  * Zero accumulator
2754  */
2755  erracc = 0;
2756 
2757  /*
2758  * # of bits by which to shift erracc to get intensity level
2759  */
2760  intshift = 32 - AAbits;
2761 
2762  /* Lock surface */
2763  if (SDL_MUSTLOCK(dst)) {
2764  if (SDL_LockSurface(dst) < 0) {
2765  return (-1);
2766  }
2767  }
2768 
2769  /*
2770  * Draw the initial pixel in the foreground color
2771  */
2772  result |= pixelColorNolock(dst, x, y, color);
2773 
2774  /*
2775  * x-major or y-major?
2776  */
2777  if (dy > dx) {
2778 
2779  /*
2780  * y-major. Calculate 16-bit fixed point fractional part of a pixel that
2781  * X advances every time Y advances 1 pixel, truncating the result so that
2782  * we won't overrun the endpoint along the X axis
2783  */
2784  /*
2785  * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
2786  */
2787  erradj = ((dx << 16) / dy) << 16;
2788 
2789  /*
2790  * draw all pixels other than the first and last
2791  */
2792  x0pxdir = xx0 + xdir;
2793  while (--dy) {
2794  erracctmp = erracc;
2795  erracc += erradj;
2796  if (erracc <= erracctmp) {
2797  /*
2798  * rollover in error accumulator, x coord advances
2799  */
2800  xx0 = x0pxdir;
2801  x0pxdir += xdir;
2802  }
2803  yy0++; /* y-major so always advance Y */
2804 
2805  /*
2806  * the AAbits most significant bits of erracc give us the intensity
2807  * weighting for this pixel, and the complement of the weighting for
2808  * the paired pixel.
2809  */
2810  wgt = (erracc >> intshift) & 255;
2811  result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
2812  result |= pixelColorWeightNolock (dst, x0pxdir, yy0, color, wgt);
2813  }
2814 
2815  } else {
2816 
2817  /*
2818  * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
2819  * that Y advances each time X advances 1 pixel, truncating the result so
2820  * that we won't overrun the endpoint along the X axis.
2821  */
2822  /*
2823  * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
2824  */
2825  erradj = ((dy << 16) / dx) << 16;
2826 
2827  /*
2828  * draw all pixels other than the first and last
2829  */
2830  y0p1 = yy0 + 1;
2831  while (--dx) {
2832 
2833  erracctmp = erracc;
2834  erracc += erradj;
2835  if (erracc <= erracctmp) {
2836  /*
2837  * Accumulator turned over, advance y
2838  */
2839  yy0 = y0p1;
2840  y0p1++;
2841  }
2842  xx0 += xdir; /* x-major so always advance X */
2843  /*
2844  * the AAbits most significant bits of erracc give us the intensity
2845  * weighting for this pixel, and the complement of the weighting for
2846  * the paired pixel.
2847  */
2848  wgt = (erracc >> intshift) & 255;
2849  result |= pixelColorWeightNolock (dst, xx0, yy0, color, 255 - wgt);
2850  result |= pixelColorWeightNolock (dst, xx0, y0p1, color, wgt);
2851  }
2852  }
2853 
2854  /*
2855  * Do we have to draw the endpoint
2856  */
2857  if (draw_endpoint) {
2858  /*
2859  * Draw final pixel, always exactly intersected by the line and doesn't
2860  * need to be weighted.
2861  */
2862  result |= pixelColorNolock (dst, x2, y2, color);
2863  }
2864 
2865  /* Unlock surface */
2866  if (SDL_MUSTLOCK(dst)) {
2867  SDL_UnlockSurface(dst);
2868  }
2869 
2870  return (result);
2871 }
2872 
2885 int aalineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint32 color)
2886 {
2887  return (_aalineColor(dst, x, y, x2, y2, color, 1));
2888 }
2889 
2905 int aalineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2906 {
2907  return (_aalineColor
2908  (dst, x, y, x2, y2, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
2909 }
2910 
2911 
2912 /* ----- Circle */
2913 
2929 int circleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
2930 {
2931  Sint16 left, right, top, bottom;
2932  int result;
2933  Sint16 xx, yy, x2, y2;
2934  Sint16 cx = 0;
2935  Sint16 cy = rad;
2936  Sint16 df = 1 - rad;
2937  Sint16 d_e = 3;
2938  Sint16 d_se = -2 * rad + 5;
2939  Sint16 xpcx, xmcx, xpcy, xmcy;
2940  Sint16 ypcy, ymcy, ypcx, ymcx;
2941  Uint8 *colorptr;
2942 
2943  /*
2944  * Check visibility of clipping rectangle
2945  */
2946  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
2947  return (0);
2948  }
2949 
2950  /*
2951  * Sanity check radius
2952  */
2953  if (rad < 0) {
2954  return (-1);
2955  }
2956 
2957  /*
2958  * Special case for rad=0 - draw a point
2959  */
2960  if (rad == 0) {
2961  return (pixelColor(dst, x, y, color));
2962  }
2963 
2964  /*
2965  * Get circle and clipping boundary and
2966  * test if bounding box of circle is visible
2967  */
2968  x2 = x + rad;
2969  left = dst->clip_rect.x;
2970  if (x2 < left) {
2971  return (0);
2972  }
2973  xx = x - rad;
2974  right = dst->clip_rect.x + dst->clip_rect.w - 1;
2975  if (xx > right) {
2976  return (0);
2977  }
2978  y2 = y + rad;
2979  top = dst->clip_rect.y;
2980  if (y2 < top) {
2981  return (0);
2982  }
2983  yy = y - rad;
2984  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
2985  if (yy > bottom) {
2986  return (0);
2987  }
2988 
2989  /*
2990  * Draw circle
2991  */
2992  result = 0;
2993 
2994  /* Lock surface */
2995  if (SDL_MUSTLOCK(dst)) {
2996  if (SDL_LockSurface(dst) < 0) {
2997  return (-1);
2998  }
2999  }
3000 
3001  /*
3002  * Alpha Check
3003  */
3004  if ((color & 255) == 255) {
3005 
3006  /*
3007  * No Alpha - direct memory writes
3008  */
3009 
3010  /*
3011  * Setup color
3012  */
3013  colorptr = (Uint8 *) & color;
3014  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
3015  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
3016  } else {
3017  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
3018  }
3019 
3020  /*
3021  * Draw
3022  */
3023  do {
3024  ypcy = y + cy;
3025  ymcy = y - cy;
3026  if (cx > 0) {
3027  xpcx = x + cx;
3028  xmcx = x - cx;
3029  result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
3030  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
3031  result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
3032  result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
3033  } else {
3034  result |= fastPixelColorNolock(dst, x, ymcy, color);
3035  result |= fastPixelColorNolock(dst, x, ypcy, color);
3036  }
3037  xpcy = x + cy;
3038  xmcy = x - cy;
3039  if ((cx > 0) && (cx != cy)) {
3040  ypcx = y + cx;
3041  ymcx = y - cx;
3042  result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
3043  result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
3044  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
3045  result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
3046  } else if (cx == 0) {
3047  result |= fastPixelColorNolock(dst, xmcy, y, color);
3048  result |= fastPixelColorNolock(dst, xpcy, y, color);
3049  }
3050  /*
3051  * Update
3052  */
3053  if (df < 0) {
3054  df += d_e;
3055  d_e += 2;
3056  d_se += 2;
3057  } else {
3058  df += d_se;
3059  d_e += 2;
3060  d_se += 4;
3061  cy--;
3062  }
3063  cx++;
3064  } while (cx <= cy);
3065 
3066  /*
3067  * Unlock surface
3068  */
3069  SDL_UnlockSurface(dst);
3070 
3071  } else {
3072 
3073  /*
3074  * Using Alpha - blended pixel blits
3075  */
3076 
3077  do {
3078  /*
3079  * Draw
3080  */
3081  ypcy = y + cy;
3082  ymcy = y - cy;
3083  if (cx > 0) {
3084  xpcx = x + cx;
3085  xmcx = x - cx;
3086  result |= pixelColorNolock (dst, xmcx, ypcy, color);
3087  result |= pixelColorNolock (dst, xpcx, ypcy, color);
3088  result |= pixelColorNolock (dst, xmcx, ymcy, color);
3089  result |= pixelColorNolock (dst, xpcx, ymcy, color);
3090  } else {
3091  result |= pixelColorNolock (dst, x, ymcy, color);
3092  result |= pixelColorNolock (dst, x, ypcy, color);
3093  }
3094  xpcy = x + cy;
3095  xmcy = x - cy;
3096  if ((cx > 0) && (cx != cy)) {
3097  ypcx = y + cx;
3098  ymcx = y - cx;
3099  result |= pixelColorNolock (dst, xmcy, ypcx, color);
3100  result |= pixelColorNolock (dst, xpcy, ypcx, color);
3101  result |= pixelColorNolock (dst, xmcy, ymcx, color);
3102  result |= pixelColorNolock (dst, xpcy, ymcx, color);
3103  } else if (cx == 0) {
3104  result |= pixelColorNolock (dst, xmcy, y, color);
3105  result |= pixelColorNolock (dst, xpcy, y, color);
3106  }
3107  /*
3108  * Update
3109  */
3110  if (df < 0) {
3111  df += d_e;
3112  d_e += 2;
3113  d_se += 2;
3114  } else {
3115  df += d_se;
3116  d_e += 2;
3117  d_se += 4;
3118  cy--;
3119  }
3120  cx++;
3121  } while (cx <= cy);
3122 
3123  } /* Alpha check */
3124 
3125  /* Unlock surface */
3126  if (SDL_MUSTLOCK(dst)) {
3127  SDL_UnlockSurface(dst);
3128  }
3129 
3130  return (result);
3131 }
3132 
3147 int circleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3148 {
3149  /*
3150  * Draw
3151  */
3152  return (circleColor(dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3153 }
3154 
3155 /* ----- Arc */
3156 
3174 int arcColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
3175 {
3176  Sint16 left, right, top, bottom;
3177  int result;
3178  Sint16 xx, yy, x2, y2;
3179  Sint16 cx = 0;
3180  Sint16 cy = rad;
3181  Sint16 df = 1 - rad;
3182  Sint16 d_e = 3;
3183  Sint16 d_se = -2 * rad + 5;
3184  Sint16 xpcx, xmcx, xpcy, xmcy;
3185  Sint16 ypcy, ymcy, ypcx, ymcx;
3186  Uint8 *colorptr;
3187  Uint8 drawoct;
3188  int startoct, endoct, oct, stopval_start = 0, stopval_end;
3189  double temp = 0;
3190 
3191  /*
3192  * Check visibility of clipping rectangle
3193  */
3194  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
3195  return (0);
3196  }
3197 
3198  /*
3199  * Sanity check radius
3200  */
3201  if (rad < 0) {
3202  return (-1);
3203  }
3204 
3205  /*
3206  * Special case for rad=0 - draw a point
3207  */
3208  if (rad == 0) {
3209  return (pixelColor(dst, x, y, color));
3210  }
3211 
3212  /*
3213  * Get arc's circle and clipping boundary and
3214  * test if bounding box of circle is visible
3215  */
3216  x2 = x + rad;
3217  left = dst->clip_rect.x;
3218  if (x2 < left) {
3219  return (0);
3220  }
3221  xx = x - rad;
3222  right = dst->clip_rect.x + dst->clip_rect.w - 1;
3223  if (xx > right) {
3224  return (0);
3225  }
3226  y2 = y + rad;
3227  top = dst->clip_rect.y;
3228  if (y2 < top) {
3229  return (0);
3230  }
3231  yy = y - rad;
3232  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3233  if (yy > bottom) {
3234  return (0);
3235  }
3236 
3237  /* Octant labelling
3238  // \ 5 | 6 /
3239  // \ | /
3240  // 4 \ | / 7
3241  // \|/
3242  //------+------ +x
3243  // /|\
3244  // 3 / | \ 0
3245  // / | \
3246  // / 2 | 1 \
3247  // +y */
3248 
3249  /* Initially reset bitmask to 0x00000000
3250  * the set whether or not to keep drawing a given octant.
3251  * For example: 0x00111100 means we're drawing in octants 2-5 */
3252  drawoct = 0;
3253 
3254  /*
3255  * Fixup angles
3256  */
3257  start %= 360;
3258  end %= 360;
3259  /* 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. */
3260  while (start < 0) {
3261  start += 360;
3262  }
3263  while (end < 0) {
3264  end += 360;
3265  }
3266  start %= 360;
3267  end %= 360;
3268 
3269  /* now, we find which octants we're drawing in. */
3270  startoct = start / 45;
3271  endoct = end / 45;
3272  oct = startoct - 1; /* we increment as first step in loop */
3273 
3274  /* stopval_start, stopval_end; */
3275  /* what values of cx to stop at. */
3276  do {
3277  oct = (oct + 1) % 8;
3278 
3279  if (oct == startoct) {
3280  /* need to compute stopval_start for this octant. Look at picture above if this is unclear */
3281  switch (oct) {
3282  case 0:
3283  case 3:
3284  temp = sin(start * M_PI / 180);
3285  break;
3286  case 1:
3287  case 6:
3288  temp = cos(start * M_PI / 180);
3289  break;
3290  case 2:
3291  case 5:
3292  temp = -cos(start * M_PI / 180);
3293  break;
3294  case 4:
3295  case 7:
3296  temp = -sin(start * M_PI / 180);
3297  break;
3298  }
3299  temp *= rad;
3300  stopval_start = (int) temp; /* always round down. */
3301  /* This isn't arbitrary, but requires graph paper to explain well. */
3302  /* The basic idea is that we're always changing drawoct after we draw, so we */
3303  /* stop immediately after we render the last sensible pixel at x = ((int)temp). */
3304 
3305  /* and whether to draw in this octant initially */
3306  if (oct % 2) {
3307  drawoct |= (1 << oct);
3308  }/* this is basically like saying drawoct[oct] = true, if drawoct were a bool array */
3309  else {
3310  drawoct &= 255 - (1 << oct);
3311  } /* this is basically like saying drawoct[oct] = false */
3312  }
3313  if (oct == endoct) {
3314  /* need to compute stopval_end for this octant */
3315  switch (oct) {
3316  case 0:
3317  case 3:
3318  temp = sin(end * M_PI / 180);
3319  break;
3320  case 1:
3321  case 6:
3322  temp = cos(end * M_PI / 180);
3323  break;
3324  case 2:
3325  case 5:
3326  temp = -cos(end * M_PI / 180);
3327  break;
3328  case 4:
3329  case 7:
3330  temp = -sin(end * M_PI / 180);
3331  break;
3332  }
3333  temp *= rad;
3334  stopval_end = (int) temp;
3335 
3336  /* and whether to draw in this octant initially */
3337  if (startoct == endoct) {
3338  /* note: we start drawing, stop, then start again in this case */
3339  /* otherwise: we only draw in this octant, so initialize it to false, it will get set back to true */
3340  if (start > end) {
3341  /* unfortunately, if we're in the same octant and need to draw over the whole circle, */
3342  /* we need to set the rest to true, because the while loop will end at the bottom. */
3343  drawoct = 255;
3344  } else {
3345  drawoct &= 255 - (1 << oct);
3346  }
3347  } else if (oct % 2) {
3348  drawoct &= 255 - (1 << oct);
3349  } else {
3350  drawoct |= (1 << oct);
3351  }
3352  } else if (oct != startoct) { /* already verified that it's != endoct */
3353  drawoct |= (1 << oct); /* draw this entire segment */
3354  }
3355  } while (oct != endoct);
3356 
3357  /* so now we have what octants to draw and when to draw them. all that's left is the actual raster code. */
3358 
3359  /* Lock surface */
3360  if (SDL_MUSTLOCK(dst)) {
3361  if (SDL_LockSurface(dst) < 0) {
3362  return (-1);
3363  }
3364  }
3365 
3366  /*
3367  * Draw arc
3368  */
3369  result = 0;
3370 
3371  /*
3372  * Alpha Check
3373  */
3374  if ((color & 255) == 255) {
3375 
3376  /*
3377  * No Alpha - direct memory writes
3378  */
3379 
3380  /*
3381  * Setup color
3382  */
3383  colorptr = (Uint8 *) & color;
3384  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
3385  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
3386  } else {
3387  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
3388  }
3389 
3390  /*
3391  * Draw
3392  */
3393  do {
3394  ypcy = y + cy;
3395  ymcy = y - cy;
3396  if (cx > 0) {
3397  xpcx = x + cx;
3398  xmcx = x - cx;
3399  if (drawoct & 4) {
3400  result |= fastPixelColorNolock(dst, xmcx, ypcy, color);
3401  }
3402  if (drawoct & 2) {
3403  result |= fastPixelColorNolock(dst, xpcx, ypcy, color);
3404  }
3405  if (drawoct & 32) {
3406  result |= fastPixelColorNolock(dst, xmcx, ymcy, color);
3407  }
3408  if (drawoct & 64) {
3409  result |= fastPixelColorNolock(dst, xpcx, ymcy, color);
3410  }
3411  } else {
3412  if (drawoct & 6) {
3413  result |= fastPixelColorNolock(dst, x, ypcy, color);
3414  }
3415  if (drawoct & 96) {
3416  result |= fastPixelColorNolock(dst, x, ymcy, color);
3417  }
3418  }
3419 
3420  xpcy = x + cy;
3421  xmcy = x - cy;
3422  if (cx > 0 && cx != cy) {
3423  ypcx = y + cx;
3424  ymcx = y - cx;
3425  if (drawoct & 8) {
3426  result |= fastPixelColorNolock(dst, xmcy, ypcx, color);
3427  }
3428  if (drawoct & 1) {
3429  result |= fastPixelColorNolock(dst, xpcy, ypcx, color);
3430  }
3431  if (drawoct & 16) {
3432  result |= fastPixelColorNolock(dst, xmcy, ymcx, color);
3433  }
3434  if (drawoct & 128) {
3435  result |= fastPixelColorNolock(dst, xpcy, ymcx, color);
3436  }
3437  } else if (cx == 0) {
3438  if (drawoct & 24) {
3439  result |= fastPixelColorNolock(dst, xmcy, y, color);
3440  }
3441  if (drawoct & 129) {
3442  result |= fastPixelColorNolock(dst, xpcy, y, color);
3443  }
3444  }
3445 
3446  /*
3447  * Update whether we're drawing an octant
3448  */
3449  if (stopval_start == cx) {
3450  if (drawoct & (1 << startoct)) {
3451  drawoct &= 255 - (1 << startoct);
3452  } else {
3453  drawoct |= (1 << startoct);
3454  }
3455  }
3456  if (stopval_end == cx) {
3457  if (drawoct & (1 << endoct)) {
3458  drawoct &= 255 - (1 << endoct);
3459  } else {
3460  drawoct |= (1 << endoct);
3461  }
3462  }
3463 
3464  /*
3465  * Update pixels
3466  */
3467  if (df < 0) {
3468  df += d_e;
3469  d_e += 2;
3470  d_se += 2;
3471  } else {
3472  df += d_se;
3473  d_e += 2;
3474  d_se += 4;
3475  cy--;
3476  }
3477  cx++;
3478  } while (cx <= cy);
3479 
3480  /*
3481  * Unlock surface
3482  */
3483  SDL_UnlockSurface(dst);
3484 
3485  } else {
3486 
3487  /*
3488  * Using Alpha - blended pixel blits
3489  */
3490 
3491  do {
3492  ypcy = y + cy;
3493  ymcy = y - cy;
3494  if (cx > 0) {
3495  xpcx = x + cx;
3496  xmcx = x - cx;
3497 
3498  if (drawoct & 4) {
3499  result |= pixelColorNolock(dst, xmcx, ypcy, color);
3500  }
3501  if (drawoct & 2) {
3502  result |= pixelColorNolock(dst, xpcx, ypcy, color);
3503  }
3504  if (drawoct & 32) {
3505  result |= pixelColorNolock(dst, xmcx, ymcy, color);
3506  }
3507  if (drawoct & 64) {
3508  result |= pixelColorNolock(dst, xpcx, ymcy, color);
3509  }
3510  } else {
3511  if (drawoct & 96) {
3512  result |= pixelColorNolock(dst, x, ymcy, color);
3513  }
3514  if (drawoct & 6) {
3515  result |= pixelColorNolock(dst, x, ypcy, color);
3516  }
3517  }
3518 
3519  xpcy = x + cy;
3520  xmcy = x - cy;
3521  if (cx > 0 && cx != cy) {
3522  ypcx = y + cx;
3523  ymcx = y - cx;
3524  if (drawoct & 8) {
3525  result |= pixelColorNolock(dst, xmcy, ypcx, color);
3526  }
3527  if (drawoct & 1) {
3528  result |= pixelColorNolock(dst, xpcy, ypcx, color);
3529  }
3530  if (drawoct & 16) {
3531  result |= pixelColorNolock(dst, xmcy, ymcx, color);
3532  }
3533  if (drawoct & 128) {
3534  result |= pixelColorNolock(dst, xpcy, ymcx, color);
3535  }
3536  } else if (cx == 0) {
3537  if (drawoct & 24) {
3538  result |= pixelColorNolock(dst, xmcy, y, color);
3539  }
3540  if (drawoct & 129) {
3541  result |= pixelColorNolock(dst, xpcy, y, color);
3542  }
3543  }
3544 
3545  /*
3546  * Update whether we're drawing an octant
3547  */
3548  if (stopval_start == cx) {
3549  if (drawoct & (1 << startoct)) {
3550  drawoct &= 255 - (1 << startoct);
3551  } else {
3552  drawoct |= (1 << startoct);
3553  }
3554  }
3555  if (stopval_end == cx) {
3556  if (drawoct & (1 << endoct)) {
3557  drawoct &= 255 - (1 << endoct);
3558  } else {
3559  drawoct |= (1 << endoct);
3560  }
3561  }
3562 
3563  /*
3564  * Update pixels
3565  */
3566  if (df < 0) {
3567  df += d_e;
3568  d_e += 2;
3569  d_se += 2;
3570  } else {
3571  df += d_se;
3572  d_e += 2;
3573  d_se += 4;
3574  cy--;
3575  }
3576  cx++;
3577  } while (cx <= cy);
3578 
3579  } /* Alpha check */
3580 
3581  /* Unlock surface */
3582  if (SDL_MUSTLOCK(dst)) {
3583  SDL_UnlockSurface(dst);
3584  }
3585 
3586  return (result);
3587 }
3588 
3605 int arcRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3606 {
3607  /*
3608  * Draw
3609  */
3610  return (arcColor(dst, x, y, rad, start, end, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3611 }
3612 
3613 /* ----- AA Circle */
3614 
3628 int aacircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
3629 {
3630  return (aaellipseColor(dst, x, y, rad, rad, color));
3631 }
3632 
3647 int aacircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3648 {
3649  /*
3650  * Draw
3651  */
3652  return (aaellipseColor
3653  (dst, x, y, rad, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3654 }
3655 
3656 /* ----- Filled Circle */
3657 
3672 int filledCircleColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
3673 {
3674  Sint16 left, right, top, bottom;
3675  int result;
3676  Sint16 xx, yy, x2, y2;
3677  Sint16 cx = 0;
3678  Sint16 cy = rad;
3679  Sint16 ocx = (Sint16) 0xffff;
3680  Sint16 ocy = (Sint16) 0xffff;
3681  Sint16 df = 1 - rad;
3682  Sint16 d_e = 3;
3683  Sint16 d_se = -2 * rad + 5;
3684  Sint16 xpcx, xmcx, xpcy, xmcy;
3685  Sint16 ypcy, ymcy, ypcx, ymcx;
3686 
3687  /*
3688  * Check visibility of clipping rectangle
3689  */
3690  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
3691  return (0);
3692  }
3693 
3694  /*
3695  * Sanity check radius
3696  */
3697  if (rad < 0) {
3698  return (-1);
3699  }
3700 
3701  /*
3702  * Special case for rad=0 - draw a point
3703  */
3704  if (rad == 0) {
3705  return (pixelColor(dst, x, y, color));
3706  }
3707 
3708  /*
3709  * Get circle and clipping boundary and
3710  * test if bounding box of circle is visible
3711  */
3712  x2 = x + rad;
3713  left = dst->clip_rect.x;
3714  if (x2 < left) {
3715  return (0);
3716  }
3717  xx = x - rad;
3718  right = dst->clip_rect.x + dst->clip_rect.w - 1;
3719  if (xx > right) {
3720  return (0);
3721  }
3722  y2 = y + rad;
3723  top = dst->clip_rect.y;
3724  if (y2 < top) {
3725  return (0);
3726  }
3727  yy = y - rad;
3728  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3729  if (yy > bottom) {
3730  return (0);
3731  }
3732 
3733  /*
3734  * Draw
3735  */
3736  result = 0;
3737  do {
3738  xpcx = x + cx;
3739  xmcx = x - cx;
3740  xpcy = x + cy;
3741  xmcy = x - cy;
3742  if (ocy != cy) {
3743  if (cy > 0) {
3744  ypcy = y + cy;
3745  ymcy = y - cy;
3746  result |= hlineColor(dst, xmcx, xpcx, ypcy, color);
3747  result |= hlineColor(dst, xmcx, xpcx, ymcy, color);
3748  } else {
3749  result |= hlineColor(dst, xmcx, xpcx, y, color);
3750  }
3751  ocy = cy;
3752  }
3753  if (ocx != cx) {
3754  if (cx != cy) {
3755  if (cx > 0) {
3756  ypcx = y + cx;
3757  ymcx = y - cx;
3758  result |= hlineColor(dst, xmcy, xpcy, ymcx, color);
3759  result |= hlineColor(dst, xmcy, xpcy, ypcx, color);
3760  } else {
3761  result |= hlineColor(dst, xmcy, xpcy, y, color);
3762  }
3763  }
3764  ocx = cx;
3765  }
3766  /*
3767  * Update
3768  */
3769  if (df < 0) {
3770  df += d_e;
3771  d_e += 2;
3772  d_se += 2;
3773  } else {
3774  df += d_se;
3775  d_e += 2;
3776  d_se += 4;
3777  cy--;
3778  }
3779  cx++;
3780  } while (cx <= cy);
3781 
3782  return (result);
3783 }
3784 
3799 int filledCircleRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3800 {
3801  /*
3802  * Draw
3803  */
3804  return (filledCircleColor
3805  (dst, x, y, rad, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
3806 }
3807 
3808 /* ----- Ellipse */
3809 
3825 int ellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
3826 {
3827  Sint16 left, right, top, bottom;
3828  int result;
3829  Sint16 xx, yy, x2, y2;
3830  int ix, iy;
3831  int h, i, j, k;
3832  int oh, oi, oj, ok;
3833  int xmh, xph, ypk, ymk;
3834  int xmi, xpi, ymj, ypj;
3835  int xmj, xpj, ymi, ypi;
3836  int xmk, xpk, ymh, yph;
3837  Uint8 *colorptr;
3838 
3839  /*
3840  * Check visibility of clipping rectangle
3841  */
3842  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
3843  return (0);
3844  }
3845 
3846  /*
3847  * Sanity check radii
3848  */
3849  if ((rx < 0) || (ry < 0)) {
3850  return (-1);
3851  }
3852 
3853  /*
3854  * Special case for rx=0 - draw a vline
3855  */
3856  if (rx == 0) {
3857  return (vlineColor(dst, x, y - ry, y + ry, color));
3858  }
3859  /*
3860  * Special case for ry=0 - draw a hline
3861  */
3862  if (ry == 0) {
3863  return (hlineColor(dst, x - rx, x + rx, y, color));
3864  }
3865 
3866  /*
3867  * Get circle and clipping boundary and
3868  * test if bounding box of circle is visible
3869  */
3870  x2 = x + rx;
3871  left = dst->clip_rect.x;
3872  if (x2 < left) {
3873  return (0);
3874  }
3875  xx = x - rx;
3876  right = dst->clip_rect.x + dst->clip_rect.w - 1;
3877  if (xx > right) {
3878  return (0);
3879  }
3880  y2 = y + ry;
3881  top = dst->clip_rect.y;
3882  if (y2 < top) {
3883  return (0);
3884  }
3885  yy = y - ry;
3886  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
3887  if (yy > bottom) {
3888  return (0);
3889  }
3890 
3891  /*
3892  * Init vars
3893  */
3894  oh = oi = oj = ok = 0xFFFF;
3895 
3896  /*
3897  * Draw
3898  */
3899  result = 0;
3900 
3901  /* Lock surface */
3902  if (SDL_MUSTLOCK(dst)) {
3903  if (SDL_LockSurface(dst) < 0) {
3904  return (-1);
3905  }
3906  }
3907 
3908  /*
3909  * Check alpha
3910  */
3911  if ((color & 255) == 255) {
3912 
3913  /*
3914  * No Alpha - direct memory writes
3915  */
3916 
3917  /*
3918  * Setup color
3919  */
3920  colorptr = (Uint8 *) & color;
3921  if (SDL_BYTEORDER == SDL_BIG_ENDIAN) {
3922  color = SDL_MapRGBA(dst->format, colorptr[0], colorptr[1], colorptr[2], colorptr[3]);
3923  } else {
3924  color = SDL_MapRGBA(dst->format, colorptr[3], colorptr[2], colorptr[1], colorptr[0]);
3925  }
3926 
3927 
3928  if (rx > ry) {
3929  ix = 0;
3930  iy = rx * 64;
3931 
3932  do {
3933  h = (ix + 32) >> 6;
3934  i = (iy + 32) >> 6;
3935  j = (h * ry) / rx;
3936  k = (i * ry) / rx;
3937 
3938  if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
3939  xph = x + h;
3940  xmh = x - h;
3941  if (k > 0) {
3942  ypk = y + k;
3943  ymk = y - k;
3944  result |= fastPixelColorNolock(dst, xmh, ypk, color);
3945  result |= fastPixelColorNolock(dst, xph, ypk, color);
3946  result |= fastPixelColorNolock(dst, xmh, ymk, color);
3947  result |= fastPixelColorNolock(dst, xph, ymk, color);
3948  } else {
3949  result |= fastPixelColorNolock(dst, xmh, y, color);
3950  result |= fastPixelColorNolock(dst, xph, y, color);
3951  }
3952  ok = k;
3953  xpi = x + i;
3954  xmi = x - i;
3955  if (j > 0) {
3956  ypj = y + j;
3957  ymj = y - j;
3958  result |= fastPixelColorNolock(dst, xmi, ypj, color);
3959  result |= fastPixelColorNolock(dst, xpi, ypj, color);
3960  result |= fastPixelColorNolock(dst, xmi, ymj, color);
3961  result |= fastPixelColorNolock(dst, xpi, ymj, color);
3962  } else {
3963  result |= fastPixelColorNolock(dst, xmi, y, color);
3964  result |= fastPixelColorNolock(dst, xpi, y, color);
3965  }
3966  oj = j;
3967  }
3968 
3969  ix = ix + iy / rx;
3970  iy = iy - ix / rx;
3971 
3972  } while (i > h);
3973  } else {
3974  ix = 0;
3975  iy = ry * 64;
3976 
3977  do {
3978  h = (ix + 32) >> 6;
3979  i = (iy + 32) >> 6;
3980  j = (h * rx) / ry;
3981  k = (i * rx) / ry;
3982 
3983  if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
3984  xmj = x - j;
3985  xpj = x + j;
3986  if (i > 0) {
3987  ypi = y + i;
3988  ymi = y - i;
3989  result |= fastPixelColorNolock(dst, xmj, ypi, color);
3990  result |= fastPixelColorNolock(dst, xpj, ypi, color);
3991  result |= fastPixelColorNolock(dst, xmj, ymi, color);
3992  result |= fastPixelColorNolock(dst, xpj, ymi, color);
3993  } else {
3994  result |= fastPixelColorNolock(dst, xmj, y, color);
3995  result |= fastPixelColorNolock(dst, xpj, y, color);
3996  }
3997  oi = i;
3998  xmk = x - k;
3999  xpk = x + k;
4000  if (h > 0) {
4001  yph = y + h;
4002  ymh = y - h;
4003  result |= fastPixelColorNolock(dst, xmk, yph, color);
4004  result |= fastPixelColorNolock(dst, xpk, yph, color);
4005  result |= fastPixelColorNolock(dst, xmk, ymh, color);
4006  result |= fastPixelColorNolock(dst, xpk, ymh, color);
4007  } else {
4008  result |= fastPixelColorNolock(dst, xmk, y, color);
4009  result |= fastPixelColorNolock(dst, xpk, y, color);
4010  }
4011  oh = h;
4012  }
4013 
4014  ix = ix + iy / ry;
4015  iy = iy - ix / ry;
4016 
4017  } while (i > h);
4018  }
4019 
4020  } else {
4021 
4022  if (rx > ry) {
4023  ix = 0;
4024  iy = rx * 64;
4025 
4026  do {
4027  h = (ix + 32) >> 6;
4028  i = (iy + 32) >> 6;
4029  j = (h * ry) / rx;
4030  k = (i * ry) / rx;
4031 
4032  if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
4033  xph = x + h;
4034  xmh = x - h;
4035  if (k > 0) {
4036  ypk = y + k;
4037  ymk = y - k;
4038  result |= pixelColorNolock (dst, xmh, ypk, color);
4039  result |= pixelColorNolock (dst, xph, ypk, color);
4040  result |= pixelColorNolock (dst, xmh, ymk, color);
4041  result |= pixelColorNolock (dst, xph, ymk, color);
4042  } else {
4043  result |= pixelColorNolock (dst, xmh, y, color);
4044  result |= pixelColorNolock (dst, xph, y, color);
4045  }
4046  ok = k;
4047  xpi = x + i;
4048  xmi = x - i;
4049  if (j > 0) {
4050  ypj = y + j;
4051  ymj = y - j;
4052  result |= pixelColorNolock (dst, xmi, ypj, color);
4053  result |= pixelColorNolock (dst, xpi, ypj, color);
4054  result |= pixelColorNolock (dst, xmi, ymj, color);
4055  result |= pixelColor(dst, xpi, ymj, color);
4056  } else {
4057  result |= pixelColorNolock (dst, xmi, y, color);
4058  result |= pixelColorNolock (dst, xpi, y, color);
4059  }
4060  oj = j;
4061  }
4062 
4063  ix = ix + iy / rx;
4064  iy = iy - ix / rx;
4065 
4066  } while (i > h);
4067  } else {
4068  ix = 0;
4069  iy = ry * 64;
4070 
4071  do {
4072  h = (ix + 32) >> 6;
4073  i = (iy + 32) >> 6;
4074  j = (h * rx) / ry;
4075  k = (i * rx) / ry;
4076 
4077  if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
4078  xmj = x - j;
4079  xpj = x + j;
4080  if (i > 0) {
4081  ypi = y + i;
4082  ymi = y - i;
4083  result |= pixelColorNolock (dst, xmj, ypi, color);
4084  result |= pixelColorNolock (dst, xpj, ypi, color);
4085  result |= pixelColorNolock (dst, xmj, ymi, color);
4086  result |= pixelColorNolock (dst, xpj, ymi, color);
4087  } else {
4088  result |= pixelColorNolock (dst, xmj, y, color);
4089  result |= pixelColorNolock (dst, xpj, y, color);
4090  }
4091  oi = i;
4092  xmk = x - k;
4093  xpk = x + k;
4094  if (h > 0) {
4095  yph = y + h;
4096  ymh = y - h;
4097  result |= pixelColorNolock (dst, xmk, yph, color);
4098  result |= pixelColorNolock (dst, xpk, yph, color);
4099  result |= pixelColorNolock (dst, xmk, ymh, color);
4100  result |= pixelColorNolock (dst, xpk, ymh, color);
4101  } else {
4102  result |= pixelColorNolock (dst, xmk, y, color);
4103  result |= pixelColorNolock (dst, xpk, y, color);
4104  }
4105  oh = h;
4106  }
4107 
4108  ix = ix + iy / ry;
4109  iy = iy - ix / ry;
4110 
4111  } while (i > h);
4112  }
4113 
4114  } /* Alpha check */
4115 
4116  /* Unlock surface */
4117  if (SDL_MUSTLOCK(dst)) {
4118  SDL_UnlockSurface(dst);
4119  }
4120 
4121  return (result);
4122 }
4123 
4139 int ellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4140 {
4141  /*
4142  * Draw
4143  */
4144  return (ellipseColor(dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4145 }
4146 
4147 /* ----- AA Ellipse */
4148 
4164 int aaellipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
4165 {
4166  Sint16 left, right, top, bottom;
4167  Sint16 xx1, yy1, x2, y2;
4168  int i;
4169  int a2, b2, ds, dt, dxt, t, s, d;
4170  Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
4171  float cp;
4172  double sab;
4173  Uint8 weight, iweight;
4174  int result;
4175 
4176  /*
4177  * Check visibility of clipping rectangle
4178  */
4179  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
4180  return (0);
4181  }
4182 
4183  /*
4184  * Sanity check radii
4185  */
4186  if ((rx < 0) || (ry < 0)) {
4187  return (-1);
4188  }
4189 
4190  /*
4191  * Special case for rx=0 - draw a vline
4192  */
4193  if (rx == 0) {
4194  return (vlineColor(dst, x, y - ry, y + ry, color));
4195  }
4196  /*
4197  * Special case for ry=0 - draw an hline
4198  */
4199  if (ry == 0) {
4200  return (hlineColor(dst, x - rx, x + rx, y, color));
4201  }
4202 
4203  /*
4204  * Get circle and clipping boundary and
4205  * test if bounding box of circle is visible
4206  */
4207  x2 = x + rx;
4208  left = dst->clip_rect.x;
4209  if (x2 < left) {
4210  return (0);
4211  }
4212  xx1 = x - rx;
4213  right = dst->clip_rect.x + dst->clip_rect.w - 1;
4214  if (xx1 > right) {
4215  return (0);
4216  }
4217  y2 = y + ry;
4218  top = dst->clip_rect.y;
4219  if (y2 < top) {
4220  return (0);
4221  }
4222  yy1 = y - ry;
4223  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4224  if (yy1 > bottom) {
4225  return (0);
4226  }
4227 
4228  /* Variable setup */
4229  a2 = rx * rx;
4230  b2 = ry * ry;
4231 
4232  ds = 2 * a2;
4233  dt = 2 * b2;
4234 
4235  xc2 = 2 * x;
4236  yc2 = 2 * y;
4237 
4238  sab = sqrt(a2 + b2);
4239  od = (Sint16) lrint(sab * 0.01) + 1; /* introduce some overdraw */
4240  dxt = (Sint16) lrint((double) a2 / sab) + od;
4241 
4242  t = 0;
4243  s = -2 * a2 * ry;
4244  d = 0;
4245 
4246  xp = x;
4247  yp = y - ry;
4248 
4249  /* Lock surface */
4250  if (SDL_MUSTLOCK(dst)) {
4251  if (SDL_LockSurface(dst) < 0) {
4252  return (-1);
4253  }
4254  }
4255 
4256  /* Draw */
4257  result = 0;
4258 
4259  /* "End points" */
4260  result |= pixelColorNolock(dst, xp, yp, color);
4261  result |= pixelColorNolock(dst, xc2 - xp, yp, color);
4262  result |= pixelColorNolock(dst, xp, yc2 - yp, color);
4263  result |= pixelColorNolock(dst, xc2 - xp, yc2 - yp, color);
4264 
4265  for (i = 1; i <= dxt; i++) {
4266  xp--;
4267  d += t - b2;
4268 
4269  if (d >= 0) {
4270  ys = yp - 1;
4271  } else if ((d - s - a2) > 0) {
4272  if ((2 * d - s - a2) >= 0) {
4273  ys = yp + 1;
4274  } else {
4275  ys = yp;
4276  yp++;
4277  d -= s + a2;
4278  s += ds;
4279  }
4280  } else {
4281  yp++;
4282  ys = yp + 1;
4283  d -= s + a2;
4284  s += ds;
4285  }
4286 
4287  t -= dt;
4288 
4289  /* Calculate alpha */
4290  if (s != 0) {
4291  cp = fabs((float) d) / fabs((float) s);
4292  if (cp > 1.0) {
4293  cp = 1.0;
4294  }
4295  } else {
4296  cp = 1.0;
4297  }
4298 
4299  /* Calculate weights */
4300  weight = (Uint8) (cp * 255);
4301  iweight = 255 - weight;
4302 
4303  /* Upper half */
4304  xx = xc2 - xp;
4305  result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
4306  result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
4307 
4308  result |= pixelColorWeightNolock(dst, xp, ys, color, weight);
4309  result |= pixelColorWeightNolock(dst, xx, ys, color, weight);
4310 
4311  /* Lower half */
4312  yy = yc2 - yp;
4313  result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
4314  result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
4315 
4316  yy = yc2 - ys;
4317  result |= pixelColorWeightNolock(dst, xp, yy, color, weight);
4318  result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
4319  }
4320 
4321  /* Replaces original approximation code dyt = abs(yp - yc); */
4322  dyt = (Sint16) lrint((double) b2 / sab ) + od;
4323 
4324  for (i = 1; i <= dyt; i++) {
4325  yp++;
4326  d -= s + a2;
4327 
4328  if (d <= 0) {
4329  xs = xp + 1;
4330  } else if ((d + t - b2) < 0) {
4331  if ((2 * d + t - b2) <= 0) {
4332  xs = xp - 1;
4333  } else {
4334  xs = xp;
4335  xp--;
4336  d += t - b2;
4337  t -= dt;
4338  }
4339  } else {
4340  xp--;
4341  xs = xp - 1;
4342  d += t - b2;
4343  t -= dt;
4344  }
4345 
4346  s += ds;
4347 
4348  /* Calculate alpha */
4349  if (t != 0) {
4350  cp = fabs((float) d) / fabs((float) t);
4351  if (cp > 1.0) {
4352  cp = 1.0;
4353  }
4354  } else {
4355  cp = 1.0;
4356  }
4357 
4358  /* Calculate weight */
4359  weight = (Uint8) (cp * 255);
4360  iweight = 255 - weight;
4361 
4362  /* Left half */
4363  xx = xc2 - xp;
4364  yy = yc2 - yp;
4365  result |= pixelColorWeightNolock(dst, xp, yp, color, iweight);
4366  result |= pixelColorWeightNolock(dst, xx, yp, color, iweight);
4367 
4368  result |= pixelColorWeightNolock(dst, xp, yy, color, iweight);
4369  result |= pixelColorWeightNolock(dst, xx, yy, color, iweight);
4370 
4371  /* Right half */
4372  xx = xc2 - xs;
4373  result |= pixelColorWeightNolock(dst, xs, yp, color, weight);
4374  result |= pixelColorWeightNolock(dst, xx, yp, color, weight);
4375 
4376  result |= pixelColorWeightNolock(dst, xs, yy, color, weight);
4377  result |= pixelColorWeightNolock(dst, xx, yy, color, weight);
4378 
4379  }
4380 
4381  /* Unlock surface */
4382  if (SDL_MUSTLOCK(dst)) {
4383  SDL_UnlockSurface(dst);
4384  }
4385 
4386  return (result);
4387 }
4388 
4404 int aaellipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4405 {
4406  /*
4407  * Draw
4408  */
4409  return (aaellipseColor
4410  (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4411 }
4412 
4413 /* ---- Filled Ellipse */
4414 
4415 /* Note: */
4416 /* Based on algorithm from sge library with multiple-hline draw removal */
4417 /* and other speedup changes. */
4418 
4434 int filledEllipseColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
4435 {
4436  Sint16 left, right, top, bottom;
4437  int result;
4438  Sint16 xx, yy, x2, y2;
4439  int ix, iy;
4440  int h, i, j, k;
4441  int oh, oi, oj, ok;
4442  int xmh, xph;
4443  int xmi, xpi;
4444  int xmj, xpj;
4445  int xmk, xpk;
4446 
4447  /*
4448  * Check visibility of clipping rectangle
4449  */
4450  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
4451  return (0);
4452  }
4453 
4454  /*
4455  * Sanity check radii
4456  */
4457  if ((rx < 0) || (ry < 0)) {
4458  return (-1);
4459  }
4460 
4461  /*
4462  * Special case for rx=0 - draw a vline
4463  */
4464  if (rx == 0) {
4465  return (vlineColor(dst, x, y - ry, y + ry, color));
4466  }
4467  /*
4468  * Special case for ry=0 - draw a hline
4469  */
4470  if (ry == 0) {
4471  return (hlineColor(dst, x - rx, x + rx, y, color));
4472  }
4473 
4474  /*
4475  * Get circle and clipping boundary and
4476  * test if bounding box of circle is visible
4477  */
4478  x2 = x + rx;
4479  left = dst->clip_rect.x;
4480  if (x2 < left) {
4481  return (0);
4482  }
4483  xx = x - rx;
4484  right = dst->clip_rect.x + dst->clip_rect.w - 1;
4485  if (xx > right) {
4486  return (0);
4487  }
4488  y2 = y + ry;
4489  top = dst->clip_rect.y;
4490  if (y2 < top) {
4491  return (0);
4492  }
4493  yy = y - ry;
4494  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4495  if (yy > bottom) {
4496  return (0);
4497  }
4498 
4499  /*
4500  * Init vars
4501  */
4502  oh = oi = oj = ok = 0xFFFF;
4503 
4504  /*
4505  * Draw
4506  */
4507  result = 0;
4508  if (rx > ry) {
4509  ix = 0;
4510  iy = rx * 64;
4511 
4512  do {
4513  h = (ix + 32) >> 6;
4514  i = (iy + 32) >> 6;
4515  j = (h * ry) / rx;
4516  k = (i * ry) / rx;
4517 
4518  if ((ok != k) && (oj != k)) {
4519  xph = x + h;
4520  xmh = x - h;
4521  if (k > 0) {
4522  result |= hlineColor(dst, xmh, xph, y + k, color);
4523  result |= hlineColor(dst, xmh, xph, y - k, color);
4524  } else {
4525  result |= hlineColor(dst, xmh, xph, y, color);
4526  }
4527  ok = k;
4528  }
4529  if ((oj != j) && (ok != j) && (k != j)) {
4530  xmi = x - i;
4531  xpi = x + i;
4532  if (j > 0) {
4533  result |= hlineColor(dst, xmi, xpi, y + j, color);
4534  result |= hlineColor(dst, xmi, xpi, y - j, color);
4535  } else {
4536  result |= hlineColor(dst, xmi, xpi, y, color);
4537  }
4538  oj = j;
4539  }
4540 
4541  ix = ix + iy / rx;
4542  iy = iy - ix / rx;
4543 
4544  } while (i > h);
4545  } else {
4546  ix = 0;
4547  iy = ry * 64;
4548 
4549  do {
4550  h = (ix + 32) >> 6;
4551  i = (iy + 32) >> 6;
4552  j = (h * rx) / ry;
4553  k = (i * rx) / ry;
4554 
4555  if ((oi != i) && (oh != i)) {
4556  xmj = x - j;
4557  xpj = x + j;
4558  if (i > 0) {
4559  result |= hlineColor(dst, xmj, xpj, y + i, color);
4560  result |= hlineColor(dst, xmj, xpj, y - i, color);
4561  } else {
4562  result |= hlineColor(dst, xmj, xpj, y, color);
4563  }
4564  oi = i;
4565  }
4566  if ((oh != h) && (oi != h) && (i != h)) {
4567  xmk = x - k;
4568  xpk = x + k;
4569  if (h > 0) {
4570  result |= hlineColor(dst, xmk, xpk, y + h, color);
4571  result |= hlineColor(dst, xmk, xpk, y - h, color);
4572  } else {
4573  result |= hlineColor(dst, xmk, xpk, y, color);
4574  }
4575  oh = h;
4576  }
4577 
4578  ix = ix + iy / ry;
4579  iy = iy - ix / ry;
4580 
4581  } while (i > h);
4582  }
4583 
4584  return (result);
4585 }
4586 
4602 int filledEllipseRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4603 {
4604  /*
4605  * Draw
4606  */
4607  return (filledEllipseColor
4608  (dst, x, y, rx, ry, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
4609 }
4610 
4611 /* ----- pie */
4612 
4629 int _pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color, Uint8 filled)
4630 {
4631  Sint16 left, right, top, bottom;
4632  Sint16 xx, yy, x2, y2;
4633  int result;
4634  double angle, start_angle, end_angle;
4635  double deltaAngle;
4636  double dr;
4637  int numpoints, i;
4638  Sint16 *vx, *vy;
4639 
4640  /*
4641  * Check visibility of clipping rectangle
4642  */
4643  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
4644  return (0);
4645  }
4646 
4647  /*
4648  * Sanity check radii
4649  */
4650  if (rad < 0) {
4651  return (-1);
4652  }
4653 
4654  /*
4655  * Fixup angles
4656  */
4657  start = start % 360;
4658  end = end % 360;
4659 
4660  /*
4661  * Special case for rad=0 - draw a point
4662  */
4663  if (rad == 0) {
4664  return (pixelColor(dst, x, y, color));
4665  }
4666 
4667  /*
4668  * Clip against circle, not pie (not 100% optimal).
4669  * Get pie's circle and clipping boundary and
4670  * test if bounding box of circle is visible
4671  */
4672  x2 = x + rad;
4673  left = dst->clip_rect.x;
4674  if (x2 < left) {
4675  return (0);
4676  }
4677  xx = x - rad;
4678  right = dst->clip_rect.x + dst->clip_rect.w - 1;
4679  if (xx > right) {
4680  return (0);
4681  }
4682  y2 = y + rad;
4683  top = dst->clip_rect.y;
4684  if (y2 < top) {
4685  return (0);
4686  }
4687  yy = y - rad;
4688  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
4689  if (yy > bottom) {
4690  return (0);
4691  }
4692 
4693  /*
4694  * Variable setup
4695  */
4696  dr = (double) rad;
4697  deltaAngle = 3.0 / dr;
4698  start_angle = (double) start * (2.0 * M_PI / 360.0);
4699  end_angle = (double) end * (2.0 * M_PI / 360.0);
4700  if (start > end) {
4701  end_angle += (2.0 * M_PI);
4702  }
4703 
4704  /* We will always have at least 2 points */
4705  numpoints = 2;
4706 
4707  /* Count points (rather than calculating it) */
4708  angle = start_angle;
4709  while (angle < end_angle) {
4710  angle += deltaAngle;
4711  numpoints++;
4712  }
4713 
4714  /* Allocate combined vertex array */
4715  vx = vy = malloc(2 * sizeof(Sint16) * numpoints);
4716  if (vx == NULL) {
4717  return (-1);
4718  }
4719 
4720  /* Update point to start of vy */
4721  vy += numpoints;
4722 
4723  /* Center */
4724  vx[0] = x;
4725  vy[0] = y;
4726 
4727  /* First vertex */
4728  angle = start_angle;
4729  vx[1] = x + (int) (dr * cos(angle));
4730  vy[1] = y + (int) (dr * sin(angle));
4731 
4732  if (numpoints < 3) {
4733  result = lineColor(dst, vx[0], vy[0], vx[1], vy[1], color);
4734  } else {
4735  /* Calculate other vertices */
4736  i = 2;
4737  angle = start_angle;
4738  while (angle < end_angle) {
4739  angle += deltaAngle;
4740  if (angle > end_angle) {
4741  angle = end_angle;
4742  }
4743  vx[i] = x + (int) (dr * cos(angle));
4744  vy[i] = y + (int) (dr * sin(angle));
4745  i++;
4746  }
4747 
4748  /* Draw */
4749  if (filled) {
4750  result = filledPolygonColor(dst, vx, vy, numpoints, color);
4751  } else {
4752  result = polygonColor(dst, vx, vy, numpoints, color);
4753  }
4754  }
4755 
4756  /* Free combined vertex array */
4757  free(vx);
4758 
4759  return (result);
4760 }
4761 
4775 int pieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
4776  Sint16 start, Sint16 end, Uint32 color)
4777 {
4778  return (_pieColor(dst, x, y, rad, start, end, color, 0));
4779 
4780 }
4781 
4798 int pieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
4799  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4800 {
4801  return (_pieColor(dst, x, y, rad, start, end,
4802  ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 0));
4803 
4804 }
4805 
4819 int filledPieColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
4820 {
4821  return (_pieColor(dst, x, y, rad, start, end, color, 1));
4822 }
4823 
4840 int filledPieRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 rad,
4841  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4842 {
4843  return (_pieColor(dst, x, y, rad, start, end,
4844  ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, 1));
4845 }
4846 
4847 /* ------ Trigon */
4848 
4865 int trigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
4866 {
4867  Sint16 vx[3];
4868  Sint16 vy[3];
4869 
4870  vx[0] = x;
4871  vx[1] = x2;
4872  vx[2] = x3;
4873  vy[0] = y;
4874  vy[1] = y2;
4875  vy[2] = y3;
4876 
4877  return (polygonColor(dst, vx, vy, 3, color));
4878 }
4879 
4897 int trigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
4898  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4899 {
4900  Sint16 vx[3];
4901  Sint16 vy[3];
4902 
4903  vx[0] = x;
4904  vx[1] = x2;
4905  vx[2] = x3;
4906  vy[0] = y;
4907  vy[1] = y2;
4908  vy[2] = y3;
4909 
4910  return (polygonRGBA(dst, vx, vy, 3, r, g, b, a));
4911 }
4912 
4913 /* ------ AA-Trigon */
4914 
4931 int aatrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
4932 {
4933  Sint16 vx[3];
4934  Sint16 vy[3];
4935 
4936  vx[0] = x;
4937  vx[1] = x2;
4938  vx[2] = x3;
4939  vy[0] = y;
4940  vy[1] = y2;
4941  vy[2] = y3;
4942 
4943  return (aapolygonColor(dst, vx, vy, 3, color));
4944 }
4945 
4963 int aatrigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
4964  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4965 {
4966  Sint16 vx[3];
4967  Sint16 vy[3];
4968 
4969  vx[0] = x;
4970  vx[1] = x2;
4971  vx[2] = x3;
4972  vy[0] = y;
4973  vy[1] = y2;
4974  vy[2] = y3;
4975 
4976  return (aapolygonRGBA(dst, vx, vy, 3, r, g, b, a));
4977 }
4978 
4979 /* ------ Filled Trigon */
4980 
4997 int filledTrigonColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
4998 {
4999  Sint16 vx[3];
5000  Sint16 vy[3];
5001 
5002  vx[0] = x;
5003  vx[1] = x2;
5004  vx[2] = x3;
5005  vy[0] = y;
5006  vy[1] = y2;
5007  vy[2] = y3;
5008 
5009  return (filledPolygonColor(dst, vx, vy, 3, color));
5010 }
5011 
5031 int filledTrigonRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
5032  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5033 {
5034  Sint16 vx[3];
5035  Sint16 vy[3];
5036 
5037  vx[0] = x;
5038  vx[1] = x2;
5039  vx[2] = x3;
5040  vy[0] = y;
5041  vy[1] = y2;
5042  vy[2] = y3;
5043 
5044  return (filledPolygonRGBA(dst, vx, vy, 3, r, g, b, a));
5045 }
5046 
5047 /* ---- Polygon */
5048 
5060 int polygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5061 {
5062  int result;
5063  int i;
5064  const Sint16 *x, *y, *x2, *y2;
5065 
5066  /*
5067  * Check visibility of clipping rectangle
5068  */
5069  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
5070  return (0);
5071  }
5072 
5073  /*
5074  * Vertex array NULL check
5075  */
5076  if (vx == NULL) {
5077  return (-1);
5078  }
5079  if (vy == NULL) {
5080  return (-1);
5081  }
5082 
5083  /*
5084  * Sanity check
5085  */
5086  if (n < 3) {
5087  return (-1);
5088  }
5089 
5090  /*
5091  * Pointer setup
5092  */
5093  x = x2 = vx;
5094  y = y2 = vy;
5095  x2++;
5096  y2++;
5097 
5098  /*
5099  * Draw
5100  */
5101  result = 0;
5102  for (i = 1; i < n; i++) {
5103  result |= lineColor(dst, *x, *y, *x2, *y2, color);
5104  x = x2;
5105  y = y2;
5106  x2++;
5107  y2++;
5108  }
5109  result |= lineColor(dst, *x, *y, *vx, *vy, color);
5110 
5111  return (result);
5112 }
5113 
5128 int polygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5129 {
5130  /*
5131  * Draw
5132  */
5133  return (polygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
5134 }
5135 
5136 /* ---- AA-Polygon */
5137 
5149 int aapolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5150 {
5151  int result;
5152  int i;
5153  const Sint16 *x, *y, *x2, *y2;
5154 
5155  /*
5156  * Check visibility of clipping rectangle
5157  */
5158  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
5159  return (0);
5160  }
5161 
5162  /*
5163  * Vertex array NULL check
5164  */
5165  if (vx == NULL) {
5166  return (-1);
5167  }
5168  if (vy == NULL) {
5169  return (-1);
5170  }
5171 
5172  /*
5173  * Sanity check
5174  */
5175  if (n < 3) {
5176  return (-1);
5177  }
5178 
5179  /*
5180  * Pointer setup
5181  */
5182  x = x2 = vx;
5183  y = y2 = vy;
5184  x2++;
5185  y2++;
5186 
5187  /*
5188  * Draw
5189  */
5190  result = 0;
5191  for (i = 1; i < n; i++) {
5192  result |= _aalineColor(dst, *x, *y, *x2, *y2, color, 0);
5193  x = x2;
5194  y = y2;
5195  x2++;
5196  y2++;
5197  }
5198  result |= _aalineColor(dst, *x, *y, *vx, *vy, color, 0);
5199 
5200  return (result);
5201 }
5202 
5217 int aapolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5218 {
5219  /*
5220  * Draw
5221  */
5222  return (aapolygonColor(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
5223 }
5224 
5225 /* ---- Filled Polygon */
5226 
5235 int _gfxPrimitivesCompareInt(const void *a, const void *b)
5236 {
5237  return (*(const int *) a) - (*(const int *) b);
5238 }
5239 
5245 static int *gfxPrimitivesPolyIntsGlobal = NULL;
5246 
5252 static int gfxPrimitivesPolyAllocatedGlobal = 0;
5253 
5269 int filledPolygonColorMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color, int **polyInts, int *polyAllocated)
5270 {
5271  int result;
5272  int i;
5273  int y, xa, xb;
5274  int miny, maxy;
5275  int xx, yy;
5276  int x2, y2;
5277  int ind1, ind2;
5278  int ints;
5279  int *gfxPrimitivesPolyInts = NULL;
5280  int gfxPrimitivesPolyAllocated = 0;
5281 
5282  /*
5283  * Check visibility of clipping rectangle
5284  */
5285  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
5286  return (0);
5287  }
5288 
5289  /*
5290  * Vertex array NULL check
5291  */
5292  if (vx == NULL) {
5293  return (-1);
5294  }
5295  if (vy == NULL) {
5296  return (-1);
5297  }
5298 
5299  /*
5300  * Sanity check number of edges
5301  */
5302  if (n < 3) {
5303  return -1;
5304  }
5305 
5306  /*
5307  * Map polygon cache
5308  */
5309  if ((polyInts == NULL) || (polyAllocated == NULL)) {
5310  /* Use global cache */
5311  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
5312  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
5313  } else {
5314  /* Use local cache */
5315  gfxPrimitivesPolyInts = *polyInts;
5316  gfxPrimitivesPolyAllocated = *polyAllocated;
5317  }
5318 
5319  /*
5320  * Allocate temp array, only grow array
5321  */
5322  if (!gfxPrimitivesPolyAllocated) {
5323  gfxPrimitivesPolyInts = malloc(sizeof(int) * n);
5324  gfxPrimitivesPolyAllocated = n;
5325  } else {
5326  if (gfxPrimitivesPolyAllocated < n) {
5327  gfxPrimitivesPolyInts = realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
5328  gfxPrimitivesPolyAllocated = n;
5329  }
5330  }
5331 
5332  /*
5333  * Check temp array
5334  */
5335  if (gfxPrimitivesPolyInts == NULL) {
5336  gfxPrimitivesPolyAllocated = 0;
5337  }
5338 
5339  /*
5340  * Update cache variables
5341  */
5342  if ((polyInts == NULL) || (polyAllocated == NULL)) {
5343  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
5344  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
5345  } else {
5346  *polyInts = gfxPrimitivesPolyInts;
5347  *polyAllocated = gfxPrimitivesPolyAllocated;
5348  }
5349 
5350  /*
5351  * Check temp array again
5352  */
5353  if (gfxPrimitivesPolyInts == NULL) {
5354  return (-1);
5355  }
5356 
5357  /*
5358  * Determine Y maxima
5359  */
5360  miny = vy[0];
5361  maxy = vy[0];
5362  for (i = 1; (i < n); i++) {
5363  if (vy[i] < miny) {
5364  miny = vy[i];
5365  } else if (vy[i] > maxy) {
5366  maxy = vy[i];
5367  }
5368  }
5369 
5370  /*
5371  * Draw, scanning y
5372  */
5373  result = 0;
5374  for (y = miny; (y <= maxy); y++) {
5375  ints = 0;
5376  for (i = 0; (i < n); i++) {
5377  if (!i) {
5378  ind1 = n - 1;
5379  ind2 = 0;
5380  } else {
5381  ind1 = i - 1;
5382  ind2 = i;
5383  }
5384  yy = vy[ind1];
5385  y2 = vy[ind2];
5386  if (yy < y2) {
5387  xx = vx[ind1];
5388  x2 = vx[ind2];
5389  } else if (yy > y2) {
5390  y2 = vy[ind1];
5391  yy = vy[ind2];
5392  x2 = vx[ind1];
5393  xx = vx[ind2];
5394  } else {
5395  continue;
5396  }
5397  if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) {
5398  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx);
5399  }
5400  }
5401 
5402  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
5403 
5404  for (i = 0; (i < ints); i += 2) {
5405  xa = gfxPrimitivesPolyInts[i] + 1;
5406  xa = (xa >> 16) + ((xa & 32768) >> 15);
5407  xb = gfxPrimitivesPolyInts[i + 1] - 1;
5408  xb = (xb >> 16) + ((xb & 32768) >> 15);
5409  result |= hlineColor(dst, xa, xb, y, color);
5410  }
5411  }
5412 
5413  return (result);
5414 }
5415 
5434 int filledPolygonRGBAMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
5435 {
5436  /*
5437  * Draw
5438  */
5439  return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, polyInts, polyAllocated));
5440 }
5441 
5456 int filledPolygonColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
5457 {
5458  /*
5459  * Draw
5460  */
5461  return (filledPolygonColorMT(dst, vx, vy, n, color, NULL, NULL));
5462 }
5463 
5478 int filledPolygonRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5479 {
5480  /*
5481  * Draw
5482  */
5483  return (filledPolygonColorMT(dst, vx, vy, n, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a, NULL, NULL));
5484 }
5485 
5499 int _HLineTextured(SDL_Surface * dst, Sint16 x1, Sint16 x2, Sint16 y, SDL_Surface *texture, int texture_dx, int texture_dy)
5500 {
5501  Sint16 left, right, top, bottom;
5502  Sint16 w;
5503  Sint16 xtmp;
5504  int result = 0;
5505  int texture_x_walker;
5506  int texture_y_start;
5507  SDL_Rect source_rect, dst_rect;
5508  int pixels_written, write_width;
5509 
5510  /*
5511  * Check visibility of clipping rectangle
5512  */
5513  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
5514  return (0);
5515  }
5516 
5517  /*
5518  * Swap x1, x2 if required to ensure x1<=x2
5519  */
5520  if (x1 > x2) {
5521  xtmp = x1;
5522  x1 = x2;
5523  x2 = xtmp;
5524  }
5525 
5526  /*
5527  * Get clipping boundary and
5528  * check visibility of hline
5529  */
5530  left = dst->clip_rect.x;
5531  if (x2 < left) {
5532  return (0);
5533  }
5534  right = dst->clip_rect.x + dst->clip_rect.w - 1;
5535  if (x1 > right) {
5536  return (0);
5537  }
5538  top = dst->clip_rect.y;
5539  bottom = dst->clip_rect.y + dst->clip_rect.h - 1;
5540  if ((y < top) || (y > bottom)) {
5541  return (0);
5542  }
5543 
5544  /*
5545  * Clip x
5546  */
5547  if (x1 < left) {
5548  x1 = left;
5549  }
5550  if (x2 > right) {
5551  x2 = right;
5552  }
5553 
5554  /*
5555  * Calculate width to draw
5556  */
5557  w = x2 - x1 + 1;
5558 
5559  /*
5560  * Determine where in the texture we start drawing
5561  */
5562  texture_x_walker = (x1 - texture_dx) % texture->w;
5563  if (texture_x_walker < 0) {
5564  texture_x_walker = texture->w + texture_x_walker ;
5565  }
5566 
5567  texture_y_start = (y + texture_dy) % texture->h;
5568  if (texture_y_start < 0) {
5569  texture_y_start = texture->h + texture_y_start;
5570  }
5571 
5572  source_rect.y = texture_y_start;
5573  source_rect.x = texture_x_walker;
5574  source_rect.h = 1;
5575 
5576  dst_rect.y = y;
5577 
5578  if (w <= texture->w - texture_x_walker) {
5579  source_rect.w = w;
5580  source_rect.x = texture_x_walker;
5581  dst_rect.x = x1;
5582  result = (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
5583  } else {
5584  pixels_written = texture->w - texture_x_walker;
5585  source_rect.w = pixels_written;
5586  source_rect.x = texture_x_walker;
5587  dst_rect.x = x1;
5588  result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
5589  write_width = texture->w;
5590 
5591  source_rect.x = 0;
5592  while (pixels_written < w) {
5593  if (write_width >= w - pixels_written) {
5594  write_width = w - pixels_written;
5595  }
5596  source_rect.w = write_width;
5597  dst_rect.x = x1 + pixels_written;
5598  result |= (SDL_BlitSurface (texture, &source_rect , dst, &dst_rect) == 0);
5599  pixels_written += write_width;
5600  }
5601  }
5602 
5603  return result;
5604 }
5605 
5629 int texturedPolygonMT(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n,
5630  SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
5631 {
5632  int result;
5633  int i;
5634  int y, xa, xb;
5635  int minx, maxx, miny, maxy;
5636  int xx, yy;
5637  int x2, y2;
5638  int ind1, ind2;
5639  int ints;
5640  int *gfxPrimitivesPolyInts = NULL;
5641  int gfxPrimitivesPolyAllocated = 0;
5642 
5643  /*
5644  * Check visibility of clipping rectangle
5645  */
5646  if ((dst->clip_rect.w == 0) || (dst->clip_rect.h == 0)) {
5647  return (0);
5648  }
5649 
5650  /*
5651  * Sanity check number of edges
5652  */
5653  if (n < 3) {
5654  return -1;
5655  }
5656 
5657  /*
5658  * Map polygon cache
5659  */
5660  if ((polyInts == NULL) || (polyAllocated == NULL)) {
5661  /* Use global cache */
5662  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
5663  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
5664  } else {
5665  /* Use local cache */
5666  gfxPrimitivesPolyInts = *polyInts;
5667  gfxPrimitivesPolyAllocated = *polyAllocated;
5668  }
5669 
5670  /*
5671  * Allocate temp array, only grow array
5672  */
5673  if (!gfxPrimitivesPolyAllocated) {
5674  gfxPrimitivesPolyInts = malloc(sizeof(int) * n);
5675  gfxPrimitivesPolyAllocated = n;
5676  } else {
5677  if (gfxPrimitivesPolyAllocated < n) {
5678  gfxPrimitivesPolyInts = realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
5679  gfxPrimitivesPolyAllocated = n;
5680  }
5681  }
5682 
5683  /*
5684  * Check temp array
5685  */
5686  if (gfxPrimitivesPolyInts == NULL) {
5687  gfxPrimitivesPolyAllocated = 0;
5688  }
5689 
5690  /*
5691  * Update cache variables
5692  */
5693  if ((polyInts == NULL) || (polyAllocated == NULL)) {
5694  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
5695  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
5696  } else {
5697  *polyInts = gfxPrimitivesPolyInts;
5698  *polyAllocated = gfxPrimitivesPolyAllocated;
5699  }
5700 
5701  /*
5702  * Check temp array again
5703  */
5704  if (gfxPrimitivesPolyInts == NULL) {
5705  return (-1);
5706  }
5707 
5708  /*
5709  * Determine X,Y minima,maxima
5710  */
5711  miny = vy[0];
5712  maxy = vy[0];
5713  minx = vx[0];
5714  maxx = vx[0];
5715  for (i = 1; (i < n); i++) {
5716  if (vy[i] < miny) {
5717  miny = vy[i];
5718  } else if (vy[i] > maxy) {
5719  maxy = vy[i];
5720  }
5721  if (vx[i] < minx) {
5722  minx = vx[i];
5723  } else if (vx[i] > maxx) {
5724  maxx = vx[i];
5725  }
5726  }
5727  if (maxx < 0 || minx > dst->w) {
5728  return -1;
5729  }
5730  if (maxy < 0 || miny > dst->h) {
5731  return -1;
5732  }
5733 
5734  /*
5735  * Draw, scanning y
5736  */
5737  result = 0;
5738  for (y = miny; (y <= maxy); y++) {
5739  ints = 0;
5740  for (i = 0; (i < n); i++) {
5741  if (!i) {
5742  ind1 = n - 1;
5743  ind2 = 0;
5744  } else {
5745  ind1 = i - 1;
5746  ind2 = i;
5747  }
5748  yy = vy[ind1];
5749  y2 = vy[ind2];
5750  if (yy < y2) {
5751  xx = vx[ind1];
5752  x2 = vx[ind2];
5753  } else if (yy > y2) {
5754  y2 = vy[ind1];
5755  yy = vy[ind2];
5756  x2 = vx[ind1];
5757  xx = vx[ind2];
5758  } else {
5759  continue;
5760  }
5761  if ( ((y >= yy) && (y < y2)) || ((y == maxy) && (y > yy) && (y <= y2)) ) {
5762  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - yy)) / (y2 - yy)) * (x2 - xx) + (65536 * xx);
5763  }
5764  }
5765 
5766  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
5767 
5768  for (i = 0; (i < ints); i += 2) {
5769  xa = gfxPrimitivesPolyInts[i] + 1;
5770  xa = (xa >> 16) + ((xa & 32768) >> 15);
5771  xb = gfxPrimitivesPolyInts[i + 1] - 1;
5772  xb = (xb >> 16) + ((xb & 32768) >> 15);
5773  result |= _HLineTextured(dst, xa, xb, y, texture, texture_dx, texture_dy);
5774  }
5775  }
5776 
5777  return (result);
5778 }
5779 
5796 int texturedPolygon(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
5797 {
5798  /*
5799  * Draw
5800  */
5801  return (texturedPolygonMT(dst, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
5802 }
5803 
5813 double _evaluateBezier (double *data, int ndata, double t)
5814 {
5815  double mu, result;
5816  int n, k, kn, nn, nkn;
5817  double blend, muk, munk;
5818 
5819  /* Sanity check bounds */
5820  if (t < 0.0) {
5821  return (data[0]);
5822  }
5823  if (t >= (double) ndata) {
5824  return (data[ndata - 1]);
5825  }
5826 
5827  /* Adjust t to the range 0.0 to 1.0 */
5828  mu = t / (double) ndata;
5829 
5830  /* Calculate interpolate */
5831  n = ndata - 1;
5832  result = 0.0;
5833  muk = 1;
5834  munk = pow(1 - mu, (double) n);
5835  for (k = 0; k <= n; k++) {
5836  nn = n;
5837  kn = k;
5838  nkn = n - k;
5839  blend = muk * munk;
5840  muk *= mu;
5841  munk /= (1 - mu);
5842  while (nn >= 1) {
5843  blend *= nn;
5844  nn--;
5845  if (kn > 1) {
5846  blend /= (double) kn;
5847  kn--;
5848  }
5849  if (nkn > 1) {
5850  blend /= (double) nkn;
5851  nkn--;
5852  }
5853  }
5854  result += data[k] * blend;
5855  }
5856 
5857  return (result);
5858 }
5859 
5872 int bezierColor(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
5873 {
5874  int result;
5875  int i;
5876  double *x, *y, t, stepsize;
5877  Sint16 xx, yy, x2, y2;
5878 
5879  /*
5880  * Sanity check
5881  */
5882  if (n < 3) {
5883  return (-1);
5884  }
5885  if (s < 2) {
5886  return (-1);
5887  }
5888 
5889  /*
5890  * Variable setup
5891  */
5892  stepsize = (double) 1.0 / (double) s;
5893 
5894  /* Transfer vertices into float arrays */
5895  if ((x = malloc(sizeof(double)*(n + 1))) == NULL) {
5896  return (-1);
5897  }
5898  if ((y = malloc(sizeof(double)*(n + 1))) == NULL) {
5899  free(x);
5900  return (-1);
5901  }
5902  for (i = 0; i < n; i++) {
5903  x[i] = vx[i];
5904  y[i] = vy[i];
5905  }
5906  x[n] = vx[0];
5907  y[n] = vy[0];
5908 
5909  /*
5910  * Draw
5911  */
5912  result = 0;
5913  t = 0.0;
5914  xx = (Sint16) lrint(_evaluateBezier(x, n + 1, t));
5915  yy = (Sint16) lrint(_evaluateBezier(y, n + 1, t));
5916  for (i = 0; i <= (n * s); i++) {
5917  t += stepsize;
5918  x2 = _evaluateBezier(x, n, t);
5919  y2 = _evaluateBezier(y, n, t);
5920  result |= lineColor(dst, xx, yy, x2, y2, color);
5921  xx = x2;
5922  yy = y2;
5923  }
5924 
5925  /* Clean up temporary array */
5926  free(x);
5927  free(y);
5928 
5929  return (result);
5930 }
5931 
5947 int bezierRGBA(SDL_Surface * dst, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
5948 {
5949  /*
5950  * Draw
5951  */
5952  return (bezierColor(dst, vx, vy, n, s, ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
5953 }
5954 
5955 static void _murphyParaline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
5956 {
5957  int p;
5958  d1 = -d1;
5959 
5960  /*
5961  * Lock the surface
5962  */
5963  if (SDL_MUSTLOCK(m->dst)) {
5964  SDL_LockSurface(m->dst);
5965  }
5966 
5967  for (p = 0; p <= m->u; p++) {
5968 
5969  pixelColorNolock(m->dst, x, y, m->color);
5970 
5971  if (d1 <= m->kt) {
5972  if (m->oct2 == 0) {
5973  x++;
5974  } else {
5975  if (m->quad4 == 0) {
5976  y++;
5977  } else {
5978  y--;
5979  }
5980  }
5981  d1 += m->kv;
5982  } else {
5983  x++;
5984  if (m->quad4 == 0) {
5985  y++;
5986  } else {
5987  y--;
5988  }
5989  d1 += m->kd;
5990  }
5991  }
5992 
5993  /* Unlock surface */
5994  if (SDL_MUSTLOCK(m->dst)) {
5995  SDL_UnlockSurface(m->dst);
5996  }
5997 
5998  m->tempx = x;
5999  m->tempy = y;
6000 }
6001 
6017 static void _murphyIteration(SDL_gfxMurphyIterator *m, Uint8 miter,
6018  Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
6019  Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
6020 {
6021  int atemp1, atemp2;
6022  int ftmp1, ftmp2;
6023  Uint16 m1x, m1y, m2x, m2y;
6024  Uint16 fix, fiy, lax, lay, curx, cury;
6025  Uint16 px[4], py[4];
6027 
6028  if (miter > 1) {
6029  if (m->first1x != -32768) {
6030  fix = (m->first1x + m->first2x) / 2;
6031  fiy = (m->first1y + m->first2y) / 2;
6032  lax = (m->last1x + m->last2x) / 2;
6033  lay = (m->last1y + m->last2y) / 2;
6034  curx = (ml1x + ml2x) / 2;
6035  cury = (ml1y + ml2y) / 2;
6036 
6037  atemp1 = (fix - curx);
6038  atemp2 = (fiy - cury);
6039  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
6040  atemp1 = (lax - curx);
6041  atemp2 = (lay - cury);
6042  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
6043 
6044  if (ftmp1 <= ftmp2) {
6045  m1x = m->first1x;
6046  m1y = m->first1y;
6047  m2x = m->first2x;
6048  m2y = m->first2y;
6049  } else {
6050  m1x = m->last1x;
6051  m1y = m->last1y;
6052  m2x = m->last2x;
6053  m2y = m->last2y;
6054  }
6055 
6056  atemp1 = (m2x - ml2x);
6057  atemp2 = (m2y - ml2y);
6058  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
6059  atemp1 = (m2x - ml2bx);
6060  atemp2 = (m2y - ml2by);
6061  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
6062 
6063  if (ftmp2 >= ftmp1) {
6064  ftmp1 = ml2bx;
6065  ftmp2 = ml2by;
6066  ml2bx = ml2x;
6067  ml2by = ml2y;
6068  ml2x = ftmp1;
6069  ml2y = ftmp2;
6070  ftmp1 = ml1bx;
6071  ftmp2 = ml1by;
6072  ml1bx = ml1x;
6073  ml1by = ml1y;
6074  ml1x = ftmp1;
6075  ml1y = ftmp2;
6076  }
6077 
6078  /*
6079  * Lock the surface
6080  */
6081  if (SDL_MUSTLOCK(m->dst)) {
6082  SDL_LockSurface(m->dst);
6083  }
6084 
6085  _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
6086  do {
6087  pixelColorNolock(m->dst, b.x, b.y, m->color);
6088  } while (_bresenhamIterate(&b) == 0);
6089 
6090  _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
6091  do {
6092  pixelColorNolock(m->dst, b.x, b.y, m->color);
6093  } while (_bresenhamIterate(&b) == 0);
6094 
6095  _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
6096  do {
6097  pixelColorNolock(m->dst, b.x, b.y, m->color);
6098  } while (_bresenhamIterate(&b) == 0);
6099 
6100  _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
6101  do {
6102  pixelColorNolock(m->dst, b.x, b.y, m->color);
6103  } while (_bresenhamIterate(&b) == 0);
6104 
6105  /* Unlock surface */
6106  if (SDL_MUSTLOCK(m->dst)) {
6107  SDL_UnlockSurface(m->dst);
6108  }
6109 
6110  px[0] = m1x;
6111  px[1] = m2x;
6112  px[2] = ml1bx;
6113  px[3] = ml2bx;
6114  py[0] = m1y;
6115  py[1] = m2y;
6116  py[2] = ml1by;
6117  py[3] = ml2by;
6118  polygonColor(m->dst, (const Sint16 *) px, (const Sint16 *) py, 4, m->color);
6119  }
6120  }
6121 
6122  m->last1x = ml1x;
6123  m->last1y = ml1y;
6124  m->last2x = ml2x;
6125  m->last2y = ml2y;
6126  m->first1x = ml1bx;
6127  m->first1y = ml1by;
6128  m->first2x = ml2bx;
6129  m->first2y = ml2by;
6130 }
6131 
6132 
6133 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
6134 
6149 static void _murphyWideline(SDL_gfxMurphyIterator *m, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
6150 {
6151  float offset = width / 2.f;
6152 
6153  Sint16 temp;
6154  Sint16 ptx, pty, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
6155 
6156  int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
6157 
6158  int q; /* pel counter,q=perpendicular to line */
6159  int tmp;
6160 
6161  int dd; /* distance along line */
6162  int tk; /* thickness threshold */
6163  double ang; /* angle for initial point calculation */
6164  double sang, cang;
6165 
6166  ml2by = ml2bx = ml1by = ml1bx = ml2y = ml2x = ml1y = ml1x = 0;
6167 
6168  /* Initialisation */
6169  m->u = x2 - x; /* delta x */
6170  m->v = y2 - y; /* delta y */
6171 
6172  if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
6173  temp = x;
6174  x = x2;
6175  x2 = temp;
6176  temp = y;
6177  y = y2;
6178  y2 = temp;
6179  m->u *= -1;
6180  m->v *= -1;
6181  }
6182 
6183  if (m->v < 0) { /* swap to 1st quadrant and flag */
6184  m->v *= -1;
6185  m->quad4 = 1;
6186  } else {
6187  m->quad4 = 0;
6188  }
6189 
6190  if (m->v > m->u) { /* swap things if in 2 octant */
6191  tmp = m->u;
6192  m->u = m->v;
6193  m->v = tmp;
6194  m->oct2 = 1;
6195  } else {
6196  m->oct2 = 0;
6197  }
6198 
6199  m->ku = m->u + m->u; /* change in l for square shift */
6200  m->kv = m->v + m->v; /* change in d for square shift */
6201  m->kd = m->kv - m->ku; /* change in d for diagonal shift */
6202  m->kt = m->u - m->kv; /* diag/square decision threshold */
6203 
6204  d0 = 0;
6205  d1 = 0;
6206  dd = 0;
6207 
6208  ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
6209  sang = sin(ang);
6210  cang = cos(ang);
6211 
6212  if (m->oct2 == 0) {
6213  ptx = x + (Sint16) lrint(offset * sang);
6214  if (m->quad4 == 0) {
6215  pty = y - (Sint16) lrint(offset * cang);
6216  } else {
6217  pty = y + (Sint16) lrint(offset * cang);
6218  }
6219  } else {
6220  ptx = x - (Sint16) lrint(offset * cang);
6221  if (m->quad4 == 0) {
6222  pty = y + (Sint16) lrint(offset * sang);
6223  } else {
6224  pty = y - (Sint16) lrint(offset * sang);
6225  }
6226  }
6227 
6228  /* used here for constant thickness line */
6229  tk = (int) (4. * HYPOT(ptx - x, pty - y) * HYPOT(m->u, m->v));
6230 
6231  if (miter == 0) {
6232  m->first1x = -32768;
6233  m->first1y = -32768;
6234  m->first2x = -32768;
6235  m->first2y = -32768;
6236  m->last1x = -32768;
6237  m->last1y = -32768;
6238  m->last2x = -32768;
6239  m->last2y = -32768;
6240  }
6241 
6242  for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */
6243 
6244  _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
6245  if (q == 0) {
6246  ml1x = ptx;
6247  ml1y = pty;
6248  ml1bx = m->tempx;
6249  ml1by = m->tempy;
6250  } else {
6251  ml2x = ptx;
6252  ml2y = pty;
6253  ml2bx = m->tempx;
6254  ml2by = m->tempy;
6255  }
6256  if (d0 < m->kt) { /* square move */
6257  if (m->oct2 == 0) {
6258  if (m->quad4 == 0) {
6259  pty++;
6260  } else {
6261  pty--;
6262  }
6263  } else {
6264  ptx++;
6265  }
6266  } else { /* diagonal move */
6267  dd += m->kv;
6268  d0 -= m->ku;
6269  if (d1 < m->kt) { /* normal diagonal */
6270  if (m->oct2 == 0) {
6271  ptx--;
6272  if (m->quad4 == 0) {
6273  pty++;
6274  } else {
6275  pty--;
6276  }
6277  } else {
6278  ptx++;
6279  if (m->quad4 == 0) {
6280  pty--;
6281  } else {
6282  pty++;
6283  }
6284  }
6285  d1 += m->kv;
6286  } else { /* double square move, extra parallel line */
6287  if (m->oct2 == 0) {
6288  ptx--;
6289  } else {
6290  if (m->quad4 == 0) {
6291  pty--;
6292  } else {
6293  pty++;
6294  }
6295  }
6296  d1 += m->kd;
6297  if (dd > tk) {
6298  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
6299  return; /* breakout on the extra line */
6300  }
6301  _murphyParaline(m, ptx, pty, d1);
6302  if (m->oct2 == 0) {
6303  if (m->quad4 == 0) {
6304  pty++;
6305  } else {
6306 
6307  pty--;
6308  }
6309  } else {
6310  ptx++;
6311  }
6312  }
6313  }
6314  dd += m->ku;
6315  d0 += m->kv;
6316  }
6317 
6318  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
6319 }
6320 
6334 int thickLineColor(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
6335 {
6337 
6338  if (dst == NULL) {
6339  return -1;
6340  }
6341  if (width < 1) {
6342  return -1;
6343  }
6344 
6345  m.dst = dst;
6346  m.color = color;
6347 
6348  _murphyWideline(&m, x, y, x2, y2, width, 0);
6349  _murphyWideline(&m, x, y, x2, y2, width, 1);
6350 
6351  return (0);
6352 }
6353 
6370 int thickLineRGBA(SDL_Surface * dst, Sint16 x, Sint16 y, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
6371 {
6372  return (thickLineColor(dst, x, y, x2, y2, width,
6373  ((Uint32) r << 24) | ((Uint32) g << 16) | ((Uint32) b << 8) | (Uint32) a));
6374 }
The structure passed to the internal Murphy iterator.
Definition: SDL_gfx.c:30
The structure passed to the internal Bresenham iterator.
Definition: SDL_gfx.c:21