SDL2_gfx  1.0.1
GraphicsprimitivesandsurfacefunctionsforSDL2
/builddir/build/BUILD/SDL2_gfx-1.0.1/SDL2_gfxPrimitives.c
Go to the documentation of this file.
1 /*
2 
3 SDL2_gfxPrimitives.c: graphics primitives for SDL2 renderers
4 
5 Copyright (C) 2012 Andreas Schiffler
6 
7 This software is provided 'as-is', without any express or implied
8 warranty. In no event will the authors be held liable for any damages
9 arising from the use of this software.
10 
11 Permission is granted to anyone to use this software for any purpose,
12 including commercial applications, and to alter it and redistribute it
13 freely, subject to the following restrictions:
14 
15 1. The origin of this software must not be misrepresented; you must not
16 claim that you wrote the original software. If you use this software
17 in a product, an acknowledgment in the product documentation would be
18 appreciated but is not required.
19 
20 2. Altered source versions must be plainly marked as such, and must not be
21 misrepresented as being the original software.
22 
23 3. This notice may not be removed or altered from any source
24 distribution.
25 
26 Andreas Schiffler -- aschiffler at ferzkopp dot net
27 
28 */
29 
30 #include <stdio.h>
31 #include <stdlib.h>
32 #include <math.h>
33 #include <string.h>
34 
35 #include "SDL2_gfxPrimitives.h"
36 #include "SDL2_rotozoom.h"
38 
39 /* ---- Structures */
40 
44 typedef struct {
45  Sint16 x, y;
46  int dx, dy, s1, s2, swapdir, error;
47  Uint32 count;
49 
53 typedef struct {
54  SDL_Renderer *renderer;
55  int u, v; /* delta x , delta y */
56  int ku, kt, kv, kd; /* loop constants */
57  int oct2;
58  int quad4;
59  Sint16 last1x, last1y, last2x, last2y, first1x, first1y, first2x, first2y, tempx, tempy;
61 
62 /* ---- Pixel */
63 
73 int pixel(SDL_Renderer *renderer, Sint16 x, Sint16 y)
74 {
75  return SDL_RenderDrawPoint(renderer, x, y);
76 }
77 
88 int pixelColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint32 color)
89 {
90  Uint8 *c = (Uint8 *)&color;
91  return pixelRGBA(renderer, x, y, c[0], c[1], c[2], c[3]);
92 }
93 
107 int pixelRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
108 {
109  int result = 0;
110  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
111  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
112  result |= SDL_RenderDrawPoint(renderer, x, y);
113  return result;
114 }
115 
130 int pixelRGBAWeight(SDL_Renderer * renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint32 weight)
131 {
132  /*
133  * Modify Alpha by weight
134  */
135  Uint32 ax = a;
136  ax = ((ax * weight) >> 8);
137  if (ax > 255) {
138  a = 255;
139  } else {
140  a = (Uint8)(ax & 0x000000ff);
141  }
142 
143  return pixelRGBA(renderer, x, y, r, g, b, a);
144 }
145 
146 /* ---- Hline */
147 
158 int hline(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y)
159 {
160  return SDL_RenderDrawLine(renderer, x1, y, x2, y);;
161 }
162 
163 
175 int hlineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
176 {
177  Uint8 *c = (Uint8 *)&color;
178  return hlineRGBA(renderer, x1, x2, y, c[0], c[1], c[2], c[3]);
179 }
180 
195 int hlineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
196 {
197  int result = 0;
198  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
199  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
200  result |= SDL_RenderDrawLine(renderer, x1, y, x2, y);
201  return result;
202 }
203 
204 /* ---- Vline */
205 
217 int vlineColor(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
218 {
219  Uint8 *c = (Uint8 *)&color;
220  return vlineRGBA(renderer, x, y1, y2, c[0], c[1], c[2], c[3]);
221 }
222 
237 int vlineRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
238 {
239  int result = 0;
240  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
241  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
242  result |= SDL_RenderDrawLine(renderer, x, y1, x, y2);
243  return result;
244 }
245 
246 /* ---- Rectangle */
247 
260 int rectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
261 {
262  Uint8 *c = (Uint8 *)&color;
263  return rectangleRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
264 }
265 
281 int rectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
282 {
283  int result;
284  Sint16 tmp;
285  SDL_Rect rect;
286 
287  /*
288  * Test for special cases of straight lines or single point
289  */
290  if (x1 == x2) {
291  if (y1 == y2) {
292  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
293  } else {
294  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
295  }
296  } else {
297  if (y1 == y2) {
298  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
299  }
300  }
301 
302  /*
303  * Swap x1, x2 if required
304  */
305  if (x1 > x2) {
306  tmp = x1;
307  x1 = x2;
308  x2 = tmp;
309  }
310 
311  /*
312  * Swap y1, y2 if required
313  */
314  if (y1 > y2) {
315  tmp = y1;
316  y1 = y2;
317  y2 = tmp;
318  }
319 
320  /*
321  * Create destination rect
322  */
323  rect.x = x1;
324  rect.y = y1;
325  rect.w = x2 - x1;
326  rect.h = y2 - y1;
327 
328  /*
329  * Draw
330  */
331  result = 0;
332  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
333  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
334  result |= SDL_RenderDrawRect(renderer, &rect);
335  return result;
336 }
337 
338 /* ---- Rounded Rectangle */
339 
353 int roundedRectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
354 {
355  Uint8 *c = (Uint8 *)&color;
356  return roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
357 }
358 
375 int roundedRectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
376 {
377  int result = 0;
378  Sint16 tmp;
379  Sint16 w, h;
380  Sint16 xx1, xx2;
381  Sint16 yy1, yy2;
382 
383  /*
384  * Check renderer
385  */
386  if (renderer == NULL)
387  {
388  return -1;
389  }
390 
391  /*
392  * Check radius vor valid range
393  */
394  if (rad < 0) {
395  return -1;
396  }
397 
398  /*
399  * Special case - no rounding
400  */
401  if (rad <= 1) {
402  return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
403  }
404 
405  /*
406  * Test for special cases of straight lines or single point
407  */
408  if (x1 == x2) {
409  if (y1 == y2) {
410  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
411  } else {
412  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
413  }
414  } else {
415  if (y1 == y2) {
416  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
417  }
418  }
419 
420  /*
421  * Swap x1, x2 if required
422  */
423  if (x1 > x2) {
424  tmp = x1;
425  x1 = x2;
426  x2 = tmp;
427  }
428 
429  /*
430  * Swap y1, y2 if required
431  */
432  if (y1 > y2) {
433  tmp = y1;
434  y1 = y2;
435  y2 = tmp;
436  }
437 
438  /*
439  * Calculate width&height
440  */
441  w = x2 - x1;
442  h = y2 - y1;
443 
444  /*
445  * Maybe adjust radius
446  */
447  if ((rad * 2) > w)
448  {
449  rad = w / 2;
450  }
451  if ((rad * 2) > h)
452  {
453  rad = h / 2;
454  }
455 
456  /*
457  * Draw corners
458  */
459  xx1 = x1 + rad;
460  xx2 = x2 - rad;
461  yy1 = y1 + rad;
462  yy2 = y2 - rad;
463  result |= arcRGBA(renderer, xx1, yy1, rad, 180, 270, r, g, b, a);
464  result |= arcRGBA(renderer, xx2, yy1, rad, 270, 360, r, g, b, a);
465  result |= arcRGBA(renderer, xx1, yy2, rad, 90, 180, r, g, b, a);
466  result |= arcRGBA(renderer, xx2, yy2, rad, 0, 90, r, g, b, a);
467 
468  /*
469  * Draw lines
470  */
471  if (xx1 <= xx2) {
472  result |= hlineRGBA(renderer, xx1, xx2, y1, r, g, b, a);
473  result |= hlineRGBA(renderer, xx1, xx2, y2, r, g, b, a);
474  }
475  if (yy1 <= yy2) {
476  result |= vlineRGBA(renderer, x1, yy1, yy2, r, g, b, a);
477  result |= vlineRGBA(renderer, x2, yy1, yy2, r, g, b, a);
478  }
479 
480  return result;
481 }
482 
483 /* ---- Rounded Box */
484 
498 int roundedBoxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
499 {
500  Uint8 *c = (Uint8 *)&color;
501  return roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
502 }
503 
520 int roundedBoxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2,
521  Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
522 {
523  int result;
524  Sint16 w, h, r2, tmp;
525  Sint16 cx = 0;
526  Sint16 cy = rad;
527  Sint16 ocx = (Sint16) 0xffff;
528  Sint16 ocy = (Sint16) 0xffff;
529  Sint16 df = 1 - rad;
530  Sint16 d_e = 3;
531  Sint16 d_se = -2 * rad + 5;
532  Sint16 xpcx, xmcx, xpcy, xmcy;
533  Sint16 ypcy, ymcy, ypcx, ymcx;
534  Sint16 x, y, dx, dy;
535 
536  /*
537  * Check destination renderer
538  */
539  if (renderer == NULL)
540  {
541  return -1;
542  }
543 
544  /*
545  * Check radius vor valid range
546  */
547  if (rad < 0) {
548  return -1;
549  }
550 
551  /*
552  * Special case - no rounding
553  */
554  if (rad <= 1) {
555  return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
556  }
557 
558  /*
559  * Test for special cases of straight lines or single point
560  */
561  if (x1 == x2) {
562  if (y1 == y2) {
563  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
564  } else {
565  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
566  }
567  } else {
568  if (y1 == y2) {
569  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
570  }
571  }
572 
573  /*
574  * Swap x1, x2 if required
575  */
576  if (x1 > x2) {
577  tmp = x1;
578  x1 = x2;
579  x2 = tmp;
580  }
581 
582  /*
583  * Swap y1, y2 if required
584  */
585  if (y1 > y2) {
586  tmp = y1;
587  y1 = y2;
588  y2 = tmp;
589  }
590 
591  /*
592  * Calculate width&height
593  */
594  w = x2 - x1 + 1;
595  h = y2 - y1 + 1;
596 
597  /*
598  * Maybe adjust radius
599  */
600  r2 = rad + rad;
601  if (r2 > w)
602  {
603  rad = w / 2;
604  r2 = rad + rad;
605  }
606  if (r2 > h)
607  {
608  rad = h / 2;
609  }
610 
611  /* Setup filled circle drawing for corners */
612  x = x1 + rad;
613  y = y1 + rad;
614  dx = x2 - x1 - rad - rad;
615  dy = y2 - y1 - rad - rad;
616 
617  /*
618  * Set color
619  */
620  result = 0;
621  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
622  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
623 
624  /*
625  * Draw corners
626  */
627  do {
628  xpcx = x + cx;
629  xmcx = x - cx;
630  xpcy = x + cy;
631  xmcy = x - cy;
632  if (ocy != cy) {
633  if (cy > 0) {
634  ypcy = y + cy;
635  ymcy = y - cy;
636  result |= hline(renderer, xmcx, xpcx + dx, ypcy + dy);
637  result |= hline(renderer, xmcx, xpcx + dx, ymcy);
638  } else {
639  result |= hline(renderer, xmcx, xpcx + dx, y);
640  }
641  ocy = cy;
642  }
643  if (ocx != cx) {
644  if (cx != cy) {
645  if (cx > 0) {
646  ypcx = y + cx;
647  ymcx = y - cx;
648  result |= hline(renderer, xmcy, xpcy + dx, ymcx);
649  result |= hline(renderer, xmcy, xpcy + dx, ypcx + dy);
650  } else {
651  result |= hline(renderer, xmcy, xpcy + dx, y);
652  }
653  }
654  ocx = cx;
655  }
656 
657  /*
658  * Update
659  */
660  if (df < 0) {
661  df += d_e;
662  d_e += 2;
663  d_se += 2;
664  } else {
665  df += d_se;
666  d_e += 2;
667  d_se += 4;
668  cy--;
669  }
670  cx++;
671  } while (cx <= cy);
672 
673  /* Inside */
674  if (dx > 0 && dy > 0) {
675  result |= boxRGBA(renderer, x1, y1 + rad + 1, x2, y2 - rad, r, g, b, a);
676  }
677 
678  return (result);
679 }
680 
681 /* ---- Box */
682 
695 int boxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
696 {
697  Uint8 *c = (Uint8 *)&color;
698  return boxRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
699 }
700 
716 int boxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
717 {
718  int result;
719  Sint16 tmp;
720  SDL_Rect rect;
721 
722  /*
723  * Test for special cases of straight lines or single point
724  */
725  if (x1 == x2) {
726  if (y1 == y2) {
727  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
728  } else {
729  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
730  }
731  } else {
732  if (y1 == y2) {
733  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
734  }
735  }
736 
737  /*
738  * Swap x1, x2 if required
739  */
740  if (x1 > x2) {
741  tmp = x1;
742  x1 = x2;
743  x2 = tmp;
744  }
745 
746  /*
747  * Swap y1, y2 if required
748  */
749  if (y1 > y2) {
750  tmp = y1;
751  y1 = y2;
752  y2 = tmp;
753  }
754 
755  /*
756  * Create destination rect
757  */
758  rect.x = x1;
759  rect.y = y1;
760  rect.w = x2 - x1 + 1;
761  rect.h = y2 - y1 + 1;
762 
763  /*
764  * Draw
765  */
766  result = 0;
767  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
768  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
769  result |= SDL_RenderFillRect(renderer, &rect);
770  return result;
771 }
772 
773 /* ----- Line */
774 
786 int line(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
787 {
788  /*
789  * Draw
790  */
791  return SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
792 }
793 
806 int lineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
807 {
808  Uint8 *c = (Uint8 *)&color;
809  return lineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
810 }
811 
827 int lineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
828 {
829  /*
830  * Draw
831  */
832  int result = 0;
833  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
834  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
835  result |= SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
836  return result;
837 }
838 
839 /* ---- AA Line */
840 
841 #define AAlevels 256
842 #define AAbits 8
843 
867 int _aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
868 {
869  Sint32 xx0, yy0, xx1, yy1;
870  int result;
871  Uint32 intshift, erracc, erradj;
872  Uint32 erracctmp, wgt, wgtcompmask;
873  int dx, dy, tmp, xdir, y0p1, x0pxdir;
874 
875  /*
876  * Keep on working with 32bit numbers
877  */
878  xx0 = x1;
879  yy0 = y1;
880  xx1 = x2;
881  yy1 = y2;
882 
883  /*
884  * Reorder points to make dy positive
885  */
886  if (yy0 > yy1) {
887  tmp = yy0;
888  yy0 = yy1;
889  yy1 = tmp;
890  tmp = xx0;
891  xx0 = xx1;
892  xx1 = tmp;
893  }
894 
895  /*
896  * Calculate distance
897  */
898  dx = xx1 - xx0;
899  dy = yy1 - yy0;
900 
901  /*
902  * Adjust for negative dx and set xdir
903  */
904  if (dx >= 0) {
905  xdir = 1;
906  } else {
907  xdir = -1;
908  dx = (-dx);
909  }
910 
911  /*
912  * Check for special cases
913  */
914  if (dx == 0) {
915  /*
916  * Vertical line
917  */
918  if (draw_endpoint)
919  {
920  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
921  } else {
922  if (dy > 0) {
923  return (vlineRGBA(renderer, x1, yy0, yy0+dy, r, g, b, a));
924  } else {
925  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
926  }
927  }
928  } else if (dy == 0) {
929  /*
930  * Horizontal line
931  */
932  if (draw_endpoint)
933  {
934  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
935  } else {
936  if (dx > 0) {
937  return (hlineRGBA(renderer, xx0, xx0+dx, y1, r, g, b, a));
938  } else {
939  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
940  }
941  }
942  } else if ((dx == dy) && (draw_endpoint)) {
943  /*
944  * Diagonal line (with endpoint)
945  */
946  return (lineRGBA(renderer, x1, y1, x2, y2, r, g, b, a));
947  }
948 
949 
950  /*
951  * Line is not horizontal, vertical or diagonal (with endpoint)
952  */
953  result = 0;
954 
955  /*
956  * Zero accumulator
957  */
958  erracc = 0;
959 
960  /*
961  * # of bits by which to shift erracc to get intensity level
962  */
963  intshift = 32 - AAbits;
964 
965  /*
966  * Mask used to flip all bits in an intensity weighting
967  */
968  wgtcompmask = AAlevels - 1;
969 
970  /*
971  * Draw the initial pixel in the foreground color
972  */
973  result |= pixelRGBA(renderer, x1, y1, r, g, b, a);
974 
975  /*
976  * x-major or y-major?
977  */
978  if (dy > dx) {
979 
980  /*
981  * y-major. Calculate 16-bit fixed point fractional part of a pixel that
982  * X advances every time Y advances 1 pixel, truncating the result so that
983  * we won't overrun the endpoint along the X axis
984  */
985  /*
986  * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
987  */
988  erradj = ((dx << 16) / dy) << 16;
989 
990  /*
991  * draw all pixels other than the first and last
992  */
993  x0pxdir = xx0 + xdir;
994  while (--dy) {
995  erracctmp = erracc;
996  erracc += erradj;
997  if (erracc <= erracctmp) {
998  /*
999  * rollover in error accumulator, x coord advances
1000  */
1001  xx0 = x0pxdir;
1002  x0pxdir += xdir;
1003  }
1004  yy0++; /* y-major so always advance Y */
1005 
1006  /*
1007  * the AAbits most significant bits of erracc give us the intensity
1008  * weighting for this pixel, and the complement of the weighting for
1009  * the paired pixel.
1010  */
1011  wgt = (erracc >> intshift) & 255;
1012  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
1013  result |= pixelRGBAWeight (renderer, x0pxdir, yy0, r, g, b, a, wgt);
1014  }
1015 
1016  } else {
1017 
1018  /*
1019  * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
1020  * that Y advances each time X advances 1 pixel, truncating the result so
1021  * that we won't overrun the endpoint along the X axis.
1022  */
1023  /*
1024  * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
1025  */
1026  erradj = ((dy << 16) / dx) << 16;
1027 
1028  /*
1029  * draw all pixels other than the first and last
1030  */
1031  y0p1 = yy0 + 1;
1032  while (--dx) {
1033 
1034  erracctmp = erracc;
1035  erracc += erradj;
1036  if (erracc <= erracctmp) {
1037  /*
1038  * Accumulator turned over, advance y
1039  */
1040  yy0 = y0p1;
1041  y0p1++;
1042  }
1043  xx0 += xdir; /* x-major so always advance X */
1044  /*
1045  * the AAbits most significant bits of erracc give us the intensity
1046  * weighting for this pixel, and the complement of the weighting for
1047  * the paired pixel.
1048  */
1049  wgt = (erracc >> intshift) & 255;
1050  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
1051  result |= pixelRGBAWeight (renderer, xx0, y0p1, r, g, b, a, wgt);
1052  }
1053  }
1054 
1055  /*
1056  * Do we have to draw the endpoint
1057  */
1058  if (draw_endpoint) {
1059  /*
1060  * Draw final pixel, always exactly intersected by the line and doesn't
1061  * need to be weighted.
1062  */
1063  result |= pixelRGBA (renderer, x2, y2, r, g, b, a);
1064  }
1065 
1066  return (result);
1067 }
1068 
1081 int aalineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1082 {
1083  Uint8 *c = (Uint8 *)&color;
1084  return _aalineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3], 1);
1085 }
1086 
1102 int aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1103 {
1104  return _aalineRGBA(renderer, x1, y1, x2, y2, r, g, b, a, 1);
1105 }
1106 
1107 /* ----- Circle */
1108 
1120 int circleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1121 {
1122  Uint8 *c = (Uint8 *)&color;
1123  return ellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1124 }
1125 
1140 int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1141 {
1142  return ellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1143 }
1144 
1145 /* ----- Arc */
1146 
1160 int arcColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
1161 {
1162  Uint8 *c = (Uint8 *)&color;
1163  return arcRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3]);
1164 }
1165 
1182 /* TODO: rewrite algorithm; arc endpoints are not always drawn */
1183 int arcRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1184 {
1185  int result;
1186  Sint16 cx = 0;
1187  Sint16 cy = rad;
1188  Sint16 df = 1 - rad;
1189  Sint16 d_e = 3;
1190  Sint16 d_se = -2 * rad + 5;
1191  Sint16 xpcx, xmcx, xpcy, xmcy;
1192  Sint16 ypcy, ymcy, ypcx, ymcx;
1193  Uint8 drawoct;
1194  int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
1195  double dstart, dend, temp = 0.;
1196 
1197  /*
1198  * Sanity check radius
1199  */
1200  if (rad < 0) {
1201  return (-1);
1202  }
1203 
1204  /*
1205  * Special case for rad=0 - draw a point
1206  */
1207  if (rad == 0) {
1208  return (pixelRGBA(renderer, x, y, r, g, b, a));
1209  }
1210 
1211  // Octant labelling
1212  //
1213  // \ 5 | 6 /
1214  // \ | /
1215  // 4 \ | / 7
1216  // \|/
1217  //------+------ +x
1218  // /|\
1219  // 3 / | \ 0
1220  // / | \
1221  // / 2 | 1 \
1222  // +y
1223 
1224  // Initially reset bitmask to 0x00000000
1225  // the set whether or not to keep drawing a given octant.
1226  // For example: 0x00111100 means we're drawing in octants 2-5
1227  drawoct = 0;
1228 
1229  /*
1230  * Fixup angles
1231  */
1232  start %= 360;
1233  end %= 360;
1234  // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
1235  while (start < 0) start += 360;
1236  while (end < 0) end += 360;
1237  start %= 360;
1238  end %= 360;
1239 
1240  // now, we find which octants we're drawing in.
1241  startoct = start / 45;
1242  endoct = end / 45;
1243  oct = startoct - 1; // we increment as first step in loop
1244 
1245  // stopval_start, stopval_end;
1246  // what values of cx to stop at.
1247  do {
1248  oct = (oct + 1) % 8;
1249 
1250  if (oct == startoct) {
1251  // need to compute stopval_start for this octant. Look at picture above if this is unclear
1252  dstart = (double)start;
1253  switch (oct)
1254  {
1255  case 0:
1256  case 3:
1257  temp = sin(dstart * M_PI / 180.);
1258  break;
1259  case 1:
1260  case 6:
1261  temp = cos(dstart * M_PI / 180.);
1262  break;
1263  case 2:
1264  case 5:
1265  temp = -cos(dstart * M_PI / 180.);
1266  break;
1267  case 4:
1268  case 7:
1269  temp = -sin(dstart * M_PI / 180.);
1270  break;
1271  }
1272  temp *= rad;
1273  stopval_start = (int)temp; // always round down
1274 
1275  // This isn't arbitrary, but requires graph paper to explain well.
1276  // The basic idea is that we're always changing drawoct after we draw, so we
1277  // stop immediately after we render the last sensible pixel at x = ((int)temp).
1278 
1279  // and whether to draw in this octant initially
1280  if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
1281  else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
1282  }
1283  if (oct == endoct) {
1284  // need to compute stopval_end for this octant
1285  dend = (double)end;
1286  switch (oct)
1287  {
1288  case 0:
1289  case 3:
1290  temp = sin(dend * M_PI / 180);
1291  break;
1292  case 1:
1293  case 6:
1294  temp = cos(dend * M_PI / 180);
1295  break;
1296  case 2:
1297  case 5:
1298  temp = -cos(dend * M_PI / 180);
1299  break;
1300  case 4:
1301  case 7:
1302  temp = -sin(dend * M_PI / 180);
1303  break;
1304  }
1305  temp *= rad;
1306  stopval_end = (int)temp;
1307 
1308  // and whether to draw in this octant initially
1309  if (startoct == endoct) {
1310  // note: we start drawing, stop, then start again in this case
1311  // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
1312  if (start > end) {
1313  // unfortunately, if we're in the same octant and need to draw over the whole circle,
1314  // we need to set the rest to true, because the while loop will end at the bottom.
1315  drawoct = 255;
1316  } else {
1317  drawoct &= 255 - (1 << oct);
1318  }
1319  }
1320  else if (oct % 2) drawoct &= 255 - (1 << oct);
1321  else drawoct |= (1 << oct);
1322  } else if (oct != startoct) { // already verified that it's != endoct
1323  drawoct |= (1 << oct); // draw this entire segment
1324  }
1325  } while (oct != endoct);
1326 
1327  // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
1328 
1329  /*
1330  * Set color
1331  */
1332  result = 0;
1333  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1334  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1335 
1336  /*
1337  * Draw arc
1338  */
1339  do {
1340  ypcy = y + cy;
1341  ymcy = y - cy;
1342  if (cx > 0) {
1343  xpcx = x + cx;
1344  xmcx = x - cx;
1345 
1346  // always check if we're drawing a certain octant before adding a pixel to that octant.
1347  if (drawoct & 4) result |= pixel(renderer, xmcx, ypcy);
1348  if (drawoct & 2) result |= pixel(renderer, xpcx, ypcy);
1349  if (drawoct & 32) result |= pixel(renderer, xmcx, ymcy);
1350  if (drawoct & 64) result |= pixel(renderer, xpcx, ymcy);
1351  } else {
1352  if (drawoct & 96) result |= pixel(renderer, x, ymcy);
1353  if (drawoct & 6) result |= pixel(renderer, x, ypcy);
1354  }
1355 
1356  xpcy = x + cy;
1357  xmcy = x - cy;
1358  if (cx > 0 && cx != cy) {
1359  ypcx = y + cx;
1360  ymcx = y - cx;
1361  if (drawoct & 8) result |= pixel(renderer, xmcy, ypcx);
1362  if (drawoct & 1) result |= pixel(renderer, xpcy, ypcx);
1363  if (drawoct & 16) result |= pixel(renderer, xmcy, ymcx);
1364  if (drawoct & 128) result |= pixel(renderer, xpcy, ymcx);
1365  } else if (cx == 0) {
1366  if (drawoct & 24) result |= pixel(renderer, xmcy, y);
1367  if (drawoct & 129) result |= pixel(renderer, xpcy, y);
1368  }
1369 
1370  /*
1371  * Update whether we're drawing an octant
1372  */
1373  if (stopval_start == cx) {
1374  // works like an on-off switch.
1375  // This is just in case start & end are in the same octant.
1376  if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
1377  else drawoct |= (1 << startoct);
1378  }
1379  if (stopval_end == cx) {
1380  if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
1381  else drawoct |= (1 << endoct);
1382  }
1383 
1384  /*
1385  * Update pixels
1386  */
1387  if (df < 0) {
1388  df += d_e;
1389  d_e += 2;
1390  d_se += 2;
1391  } else {
1392  df += d_se;
1393  d_e += 2;
1394  d_se += 4;
1395  cy--;
1396  }
1397  cx++;
1398  } while (cx <= cy);
1399 
1400  return (result);
1401 }
1402 
1403 /* ----- AA Circle */
1404 
1416 int aacircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1417 {
1418  Uint8 *c = (Uint8 *)&color;
1419  return aaellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1420 }
1421 
1436 int aacircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1437 {
1438  /*
1439  * Draw
1440  */
1441  return aaellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1442 }
1443 
1444 /* ----- Filled Circle */
1445 
1457 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1458 {
1459  Uint8 *c = (Uint8 *)&color;
1460  return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1461 }
1462 
1477 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1478 {
1479  int result;
1480  Sint16 cx = 0;
1481  Sint16 cy = rad;
1482  Sint16 ocx = (Sint16) 0xffff;
1483  Sint16 ocy = (Sint16) 0xffff;
1484  Sint16 df = 1 - rad;
1485  Sint16 d_e = 3;
1486  Sint16 d_se = -2 * rad + 5;
1487  Sint16 xpcx, xmcx, xpcy, xmcy;
1488  Sint16 ypcy, ymcy, ypcx, ymcx;
1489 
1490  /*
1491  * Sanity check radius
1492  */
1493  if (rad < 0) {
1494  return (-1);
1495  }
1496 
1497  /*
1498  * Special case for rad=0 - draw a point
1499  */
1500  if (rad == 0) {
1501  return (pixelRGBA(renderer, x, y, r, g, b, a));
1502  }
1503 
1504  /*
1505  * Set color
1506  */
1507  result = 0;
1508  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1509  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1510 
1511  /*
1512  * Draw
1513  */
1514  do {
1515  xpcx = x + cx;
1516  xmcx = x - cx;
1517  xpcy = x + cy;
1518  xmcy = x - cy;
1519  if (ocy != cy) {
1520  if (cy > 0) {
1521  ypcy = y + cy;
1522  ymcy = y - cy;
1523  result |= hline(renderer, xmcx, xpcx, ypcy);
1524  result |= hline(renderer, xmcx, xpcx, ymcy);
1525  } else {
1526  result |= hline(renderer, xmcx, xpcx, y);
1527  }
1528  ocy = cy;
1529  }
1530  if (ocx != cx) {
1531  if (cx != cy) {
1532  if (cx > 0) {
1533  ypcx = y + cx;
1534  ymcx = y - cx;
1535  result |= hline(renderer, xmcy, xpcy, ymcx);
1536  result |= hline(renderer, xmcy, xpcy, ypcx);
1537  } else {
1538  result |= hline(renderer, xmcy, xpcy, y);
1539  }
1540  }
1541  ocx = cx;
1542  }
1543 
1544  /*
1545  * Update
1546  */
1547  if (df < 0) {
1548  df += d_e;
1549  d_e += 2;
1550  d_se += 2;
1551  } else {
1552  df += d_se;
1553  d_e += 2;
1554  d_se += 4;
1555  cy--;
1556  }
1557  cx++;
1558  } while (cx <= cy);
1559 
1560  return (result);
1561 }
1562 
1563 /* ----- Ellipse */
1564 
1577 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1578 {
1579  Uint8 *c = (Uint8 *)&color;
1580  return ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1581 }
1582 
1598 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1599 {
1600  int result;
1601  int ix, iy;
1602  int h, i, j, k;
1603  int oh, oi, oj, ok;
1604  int xmh, xph, ypk, ymk;
1605  int xmi, xpi, ymj, ypj;
1606  int xmj, xpj, ymi, ypi;
1607  int xmk, xpk, ymh, yph;
1608 
1609  /*
1610  * Sanity check radii
1611  */
1612  if ((rx < 0) || (ry < 0)) {
1613  return (-1);
1614  }
1615 
1616  /*
1617  * Special case for rx=0 - draw a vline
1618  */
1619  if (rx == 0) {
1620  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1621  }
1622  /*
1623  * Special case for ry=0 - draw a hline
1624  */
1625  if (ry == 0) {
1626  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1627  }
1628 
1629  /*
1630  * Set color
1631  */
1632  result = 0;
1633  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1634  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1635 
1636  /*
1637  * Init vars
1638  */
1639  oh = oi = oj = ok = 0xFFFF;
1640 
1641  /*
1642  * Draw
1643  */
1644  if (rx > ry) {
1645  ix = 0;
1646  iy = rx * 64;
1647 
1648  do {
1649  h = (ix + 32) >> 6;
1650  i = (iy + 32) >> 6;
1651  j = (h * ry) / rx;
1652  k = (i * ry) / rx;
1653 
1654  if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
1655  xph = x + h;
1656  xmh = x - h;
1657  if (k > 0) {
1658  ypk = y + k;
1659  ymk = y - k;
1660  result |= pixel(renderer, xmh, ypk);
1661  result |= pixel(renderer, xph, ypk);
1662  result |= pixel(renderer, xmh, ymk);
1663  result |= pixel(renderer, xph, ymk);
1664  } else {
1665  result |= pixel(renderer, xmh, y);
1666  result |= pixel(renderer, xph, y);
1667  }
1668  ok = k;
1669  xpi = x + i;
1670  xmi = x - i;
1671  if (j > 0) {
1672  ypj = y + j;
1673  ymj = y - j;
1674  result |= pixel(renderer, xmi, ypj);
1675  result |= pixel(renderer, xpi, ypj);
1676  result |= pixel(renderer, xmi, ymj);
1677  result |= pixel(renderer, xpi, ymj);
1678  } else {
1679  result |= pixel(renderer, xmi, y);
1680  result |= pixel(renderer, xpi, y);
1681  }
1682  oj = j;
1683  }
1684 
1685  ix = ix + iy / rx;
1686  iy = iy - ix / rx;
1687 
1688  } while (i > h);
1689  } else {
1690  ix = 0;
1691  iy = ry * 64;
1692 
1693  do {
1694  h = (ix + 32) >> 6;
1695  i = (iy + 32) >> 6;
1696  j = (h * rx) / ry;
1697  k = (i * rx) / ry;
1698 
1699  if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
1700  xmj = x - j;
1701  xpj = x + j;
1702  if (i > 0) {
1703  ypi = y + i;
1704  ymi = y - i;
1705  result |= pixel(renderer, xmj, ypi);
1706  result |= pixel(renderer, xpj, ypi);
1707  result |= pixel(renderer, xmj, ymi);
1708  result |= pixel(renderer, xpj, ymi);
1709  } else {
1710  result |= pixel(renderer, xmj, y);
1711  result |= pixel(renderer, xpj, y);
1712  }
1713  oi = i;
1714  xmk = x - k;
1715  xpk = x + k;
1716  if (h > 0) {
1717  yph = y + h;
1718  ymh = y - h;
1719  result |= pixel(renderer, xmk, yph);
1720  result |= pixel(renderer, xpk, yph);
1721  result |= pixel(renderer, xmk, ymh);
1722  result |= pixel(renderer, xpk, ymh);
1723  } else {
1724  result |= pixel(renderer, xmk, y);
1725  result |= pixel(renderer, xpk, y);
1726  }
1727  oh = h;
1728  }
1729 
1730  ix = ix + iy / ry;
1731  iy = iy - ix / ry;
1732 
1733  } while (i > h);
1734  }
1735 
1736  return (result);
1737 }
1738 
1739 /* ----- AA Ellipse */
1740 
1741 /* Windows targets do not have lrint, so provide a local inline version */
1742 #if defined(_MSC_VER)
1743 /* Detect 64bit and use intrinsic version */
1744 #ifdef _M_X64
1745 #include <emmintrin.h>
1746 static __inline long
1747  lrint(float f)
1748 {
1749  return _mm_cvtss_si32(_mm_load_ss(&f));
1750 }
1751 #elif defined(_M_IX86)
1752 __inline long int
1753  lrint (double flt)
1754 {
1755  int intgr;
1756  _asm
1757  {
1758  fld flt
1759  fistp intgr
1760  };
1761  return intgr;
1762 }
1763 #elif defined(_M_ARM)
1764 #include <armintr.h>
1765 #pragma warning(push)
1766 #pragma warning(disable: 4716)
1767 __declspec(naked) long int
1768  lrint (double flt)
1769 {
1770  __emit(0xEC410B10); // fmdrr d0, r0, r1
1771  __emit(0xEEBD0B40); // ftosid s0, d0
1772  __emit(0xEE100A10); // fmrs r0, s0
1773  __emit(0xE12FFF1E); // bx lr
1774 }
1775 #pragma warning(pop)
1776 #else
1777 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
1778 #endif
1779 #endif
1780 
1793 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1794 {
1795  Uint8 *c = (Uint8 *)&color;
1796  return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1797 }
1798 
1814 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1815 {
1816  int result;
1817  int i;
1818  int a2, b2, ds, dt, dxt, t, s, d;
1819  Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
1820  float cp;
1821  double sab;
1822  Uint8 weight, iweight;
1823 
1824  /*
1825  * Sanity check radii
1826  */
1827  if ((rx < 0) || (ry < 0)) {
1828  return (-1);
1829  }
1830 
1831  /*
1832  * Special case for rx=0 - draw a vline
1833  */
1834  if (rx == 0) {
1835  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1836  }
1837  /*
1838  * Special case for ry=0 - draw an hline
1839  */
1840  if (ry == 0) {
1841  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1842  }
1843 
1844  /* Variable setup */
1845  a2 = rx * rx;
1846  b2 = ry * ry;
1847 
1848  ds = 2 * a2;
1849  dt = 2 * b2;
1850 
1851  xc2 = 2 * x;
1852  yc2 = 2 * y;
1853 
1854  sab = sqrt((double)(a2 + b2));
1855  od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
1856  dxt = (Sint16)lrint((double)a2 / sab) + od;
1857 
1858  t = 0;
1859  s = -2 * a2 * ry;
1860  d = 0;
1861 
1862  xp = x;
1863  yp = y - ry;
1864 
1865  /* Draw */
1866  result = 0;
1867  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1868 
1869  /* "End points" */
1870  result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
1871  result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
1872  result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
1873  result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
1874 
1875  for (i = 1; i <= dxt; i++) {
1876  xp--;
1877  d += t - b2;
1878 
1879  if (d >= 0)
1880  ys = yp - 1;
1881  else if ((d - s - a2) > 0) {
1882  if ((2 * d - s - a2) >= 0)
1883  ys = yp + 1;
1884  else {
1885  ys = yp;
1886  yp++;
1887  d -= s + a2;
1888  s += ds;
1889  }
1890  } else {
1891  yp++;
1892  ys = yp + 1;
1893  d -= s + a2;
1894  s += ds;
1895  }
1896 
1897  t -= dt;
1898 
1899  /* Calculate alpha */
1900  if (s != 0) {
1901  cp = (float) abs(d) / (float) abs(s);
1902  if (cp > 1.0) {
1903  cp = 1.0;
1904  }
1905  } else {
1906  cp = 1.0;
1907  }
1908 
1909  /* Calculate weights */
1910  weight = (Uint8) (cp * 255);
1911  iweight = 255 - weight;
1912 
1913  /* Upper half */
1914  xx = xc2 - xp;
1915  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1916  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1917 
1918  result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
1919  result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
1920 
1921  /* Lower half */
1922  yy = yc2 - yp;
1923  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1924  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1925 
1926  yy = yc2 - ys;
1927  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
1928  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1929  }
1930 
1931  /* Replaces original approximation code dyt = abs(yp - yc); */
1932  dyt = (Sint16)lrint((double)b2 / sab ) + od;
1933 
1934  for (i = 1; i <= dyt; i++) {
1935  yp++;
1936  d -= s + a2;
1937 
1938  if (d <= 0)
1939  xs = xp + 1;
1940  else if ((d + t - b2) < 0) {
1941  if ((2 * d + t - b2) <= 0)
1942  xs = xp - 1;
1943  else {
1944  xs = xp;
1945  xp--;
1946  d += t - b2;
1947  t -= dt;
1948  }
1949  } else {
1950  xp--;
1951  xs = xp - 1;
1952  d += t - b2;
1953  t -= dt;
1954  }
1955 
1956  s += ds;
1957 
1958  /* Calculate alpha */
1959  if (t != 0) {
1960  cp = (float) abs(d) / (float) abs(t);
1961  if (cp > 1.0) {
1962  cp = 1.0;
1963  }
1964  } else {
1965  cp = 1.0;
1966  }
1967 
1968  /* Calculate weight */
1969  weight = (Uint8) (cp * 255);
1970  iweight = 255 - weight;
1971 
1972  /* Left half */
1973  xx = xc2 - xp;
1974  yy = yc2 - yp;
1975  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1976  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1977 
1978  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1979  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1980 
1981  /* Right half */
1982  xx = xc2 - xs;
1983  result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
1984  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
1985 
1986  result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
1987  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1988  }
1989 
1990  return (result);
1991 }
1992 
1993 /* ---- Filled Ellipse */
1994 
2007 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2008 {
2009  Uint8 *c = (Uint8 *)&color;
2010  return filledEllipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
2011 }
2012 
2028 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2029 {
2030  int result;
2031  int ix, iy;
2032  int h, i, j, k;
2033  int oh, oi, oj, ok;
2034  int xmh, xph;
2035  int xmi, xpi;
2036  int xmj, xpj;
2037  int xmk, xpk;
2038 
2039  /*
2040  * Sanity check radii
2041  */
2042  if ((rx < 0) || (ry < 0)) {
2043  return (-1);
2044  }
2045 
2046  /*
2047  * Special case for rx=0 - draw a vline
2048  */
2049  if (rx == 0) {
2050  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
2051  }
2052  /*
2053  * Special case for ry=0 - draw a hline
2054  */
2055  if (ry == 0) {
2056  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
2057  }
2058 
2059  /*
2060  * Set color
2061  */
2062  result = 0;
2063  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2064  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2065 
2066  /*
2067  * Init vars
2068  */
2069  oh = oi = oj = ok = 0xFFFF;
2070 
2071  /*
2072  * Draw
2073  */
2074  if (rx > ry) {
2075  ix = 0;
2076  iy = rx * 64;
2077 
2078  do {
2079  h = (ix + 32) >> 6;
2080  i = (iy + 32) >> 6;
2081  j = (h * ry) / rx;
2082  k = (i * ry) / rx;
2083 
2084  if ((ok != k) && (oj != k)) {
2085  xph = x + h;
2086  xmh = x - h;
2087  if (k > 0) {
2088  result |= hline(renderer, xmh, xph, y + k);
2089  result |= hline(renderer, xmh, xph, y - k);
2090  } else {
2091  result |= hline(renderer, xmh, xph, y);
2092  }
2093  ok = k;
2094  }
2095  if ((oj != j) && (ok != j) && (k != j)) {
2096  xmi = x - i;
2097  xpi = x + i;
2098  if (j > 0) {
2099  result |= hline(renderer, xmi, xpi, y + j);
2100  result |= hline(renderer, xmi, xpi, y - j);
2101  } else {
2102  result |= hline(renderer, xmi, xpi, y);
2103  }
2104  oj = j;
2105  }
2106 
2107  ix = ix + iy / rx;
2108  iy = iy - ix / rx;
2109 
2110  } while (i > h);
2111  } else {
2112  ix = 0;
2113  iy = ry * 64;
2114 
2115  do {
2116  h = (ix + 32) >> 6;
2117  i = (iy + 32) >> 6;
2118  j = (h * rx) / ry;
2119  k = (i * rx) / ry;
2120 
2121  if ((oi != i) && (oh != i)) {
2122  xmj = x - j;
2123  xpj = x + j;
2124  if (i > 0) {
2125  result |= hline(renderer, xmj, xpj, y + i);
2126  result |= hline(renderer, xmj, xpj, y - i);
2127  } else {
2128  result |= hline(renderer, xmj, xpj, y);
2129  }
2130  oi = i;
2131  }
2132  if ((oh != h) && (oi != h) && (i != h)) {
2133  xmk = x - k;
2134  xpk = x + k;
2135  if (h > 0) {
2136  result |= hline(renderer, xmk, xpk, y + h);
2137  result |= hline(renderer, xmk, xpk, y - h);
2138  } else {
2139  result |= hline(renderer, xmk, xpk, y);
2140  }
2141  oh = h;
2142  }
2143 
2144  ix = ix + iy / ry;
2145  iy = iy - ix / ry;
2146 
2147  } while (i > h);
2148  }
2149 
2150  return (result);
2151 }
2152 
2153 /* ----- Pie */
2154 
2174 /* TODO: rewrite algorithm; pie is not always accurate */
2175 int _pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint8 filled)
2176 {
2177  int result;
2178  double angle, start_angle, end_angle;
2179  double deltaAngle;
2180  double dr;
2181  int numpoints, i;
2182  Sint16 *vx, *vy;
2183 
2184  /*
2185  * Sanity check radii
2186  */
2187  if (rad < 0) {
2188  return (-1);
2189  }
2190 
2191  /*
2192  * Fixup angles
2193  */
2194  start = start % 360;
2195  end = end % 360;
2196 
2197  /*
2198  * Special case for rad=0 - draw a point
2199  */
2200  if (rad == 0) {
2201  return (pixelRGBA(renderer, x, y, r, g, b, a));
2202  }
2203 
2204  /*
2205  * Variable setup
2206  */
2207  dr = (double) rad;
2208  deltaAngle = 3.0 / dr;
2209  start_angle = (double) start *(2.0 * M_PI / 360.0);
2210  end_angle = (double) end *(2.0 * M_PI / 360.0);
2211  if (start > end) {
2212  end_angle += (2.0 * M_PI);
2213  }
2214 
2215  /* We will always have at least 2 points */
2216  numpoints = 2;
2217 
2218  /* Count points (rather than calculating it) */
2219  angle = start_angle;
2220  while (angle < end_angle) {
2221  angle += deltaAngle;
2222  numpoints++;
2223  }
2224 
2225  /* Allocate combined vertex array */
2226  vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
2227  if (vx == NULL) {
2228  return (-1);
2229  }
2230 
2231  /* Update point to start of vy */
2232  vy += numpoints;
2233 
2234  /* Center */
2235  vx[0] = x;
2236  vy[0] = y;
2237 
2238  /* First vertex */
2239  angle = start_angle;
2240  vx[1] = x + (int) (dr * cos(angle));
2241  vy[1] = y + (int) (dr * sin(angle));
2242 
2243  if (numpoints<3)
2244  {
2245  result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
2246  }
2247  else
2248  {
2249  /* Calculate other vertices */
2250  i = 2;
2251  angle = start_angle;
2252  while (angle < end_angle) {
2253  angle += deltaAngle;
2254  if (angle>end_angle)
2255  {
2256  angle = end_angle;
2257  }
2258  vx[i] = x + (int) (dr * cos(angle));
2259  vy[i] = y + (int) (dr * sin(angle));
2260  i++;
2261  }
2262 
2263  /* Draw */
2264  if (filled) {
2265  result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2266  } else {
2267  result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2268  }
2269  }
2270 
2271  /* Free combined vertex array */
2272  free(vx);
2273 
2274  return (result);
2275 }
2276 
2290 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2291  Sint16 start, Sint16 end, Uint32 color)
2292 {
2293  Uint8 *c = (Uint8 *)&color;
2294  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
2295 }
2296 
2313 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2314  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2315 {
2316  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
2317 }
2318 
2332 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
2333 {
2334  Uint8 *c = (Uint8 *)&color;
2335  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
2336 }
2337 
2354 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2355  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2356 {
2357  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
2358 }
2359 
2360 /* ------ Trigon */
2361 
2378 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2379 {
2380  Sint16 vx[3];
2381  Sint16 vy[3];
2382 
2383  vx[0]=x1;
2384  vx[1]=x2;
2385  vx[2]=x3;
2386  vy[0]=y1;
2387  vy[1]=y2;
2388  vy[2]=y3;
2389 
2390  return(polygonColor(renderer,vx,vy,3,color));
2391 }
2392 
2410 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2411  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2412 {
2413  Sint16 vx[3];
2414  Sint16 vy[3];
2415 
2416  vx[0]=x1;
2417  vx[1]=x2;
2418  vx[2]=x3;
2419  vy[0]=y1;
2420  vy[1]=y2;
2421  vy[2]=y3;
2422 
2423  return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
2424 }
2425 
2426 /* ------ AA-Trigon */
2427 
2444 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2445 {
2446  Sint16 vx[3];
2447  Sint16 vy[3];
2448 
2449  vx[0]=x1;
2450  vx[1]=x2;
2451  vx[2]=x3;
2452  vy[0]=y1;
2453  vy[1]=y2;
2454  vy[2]=y3;
2455 
2456  return(aapolygonColor(renderer,vx,vy,3,color));
2457 }
2458 
2476 int aatrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2477  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2478 {
2479  Sint16 vx[3];
2480  Sint16 vy[3];
2481 
2482  vx[0]=x1;
2483  vx[1]=x2;
2484  vx[2]=x3;
2485  vy[0]=y1;
2486  vy[1]=y2;
2487  vy[2]=y3;
2488 
2489  return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2490 }
2491 
2492 /* ------ Filled Trigon */
2493 
2510 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2511 {
2512  Sint16 vx[3];
2513  Sint16 vy[3];
2514 
2515  vx[0]=x1;
2516  vx[1]=x2;
2517  vx[2]=x3;
2518  vy[0]=y1;
2519  vy[1]=y2;
2520  vy[2]=y3;
2521 
2522  return(filledPolygonColor(renderer,vx,vy,3,color));
2523 }
2524 
2544 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2545  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2546 {
2547  Sint16 vx[3];
2548  Sint16 vy[3];
2549 
2550  vx[0]=x1;
2551  vx[1]=x2;
2552  vx[2]=x3;
2553  vy[0]=y1;
2554  vy[1]=y2;
2555  vy[2]=y3;
2556 
2557  return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2558 }
2559 
2560 /* ---- Polygon */
2561 
2573 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2574 {
2575  Uint8 *c = (Uint8 *)&color;
2576  return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2577 }
2578 
2589 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
2590 {
2591  /*
2592  * Draw
2593  */
2594  int result;
2595  int i, nn;
2596  SDL_Point* points;
2597 
2598  /*
2599  * Vertex array NULL check
2600  */
2601  if (vx == NULL) {
2602  return (-1);
2603  }
2604  if (vy == NULL) {
2605  return (-1);
2606  }
2607 
2608  /*
2609  * Sanity check
2610  */
2611  if (n < 3) {
2612  return (-1);
2613  }
2614 
2615  /*
2616  * Create array of points
2617  */
2618  nn = n + 1;
2619  points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
2620  if (points == NULL)
2621  {
2622  return -1;
2623  }
2624  for (i=0; i<n; i++)
2625  {
2626  points[i].x = vx[i];
2627  points[i].y = vy[i];
2628  }
2629  points[n].x = vx[0];
2630  points[n].y = vy[0];
2631 
2632  /*
2633  * Draw
2634  */
2635  result |= SDL_RenderDrawLines(renderer, points, nn);
2636  free(points);
2637 
2638  return (result);
2639 }
2640 
2655 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2656 {
2657  /*
2658  * Draw
2659  */
2660  int result;
2661  const Sint16 *x1, *y1, *x2, *y2;
2662 
2663  /*
2664  * Vertex array NULL check
2665  */
2666  if (vx == NULL) {
2667  return (-1);
2668  }
2669  if (vy == NULL) {
2670  return (-1);
2671  }
2672 
2673  /*
2674  * Sanity check
2675  */
2676  if (n < 3) {
2677  return (-1);
2678  }
2679 
2680  /*
2681  * Pointer setup
2682  */
2683  x1 = x2 = vx;
2684  y1 = y2 = vy;
2685  x2++;
2686  y2++;
2687 
2688  /*
2689  * Set color
2690  */
2691  result = 0;
2692  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2693  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2694 
2695  /*
2696  * Draw
2697  */
2698  result |= polygon(renderer, vx, vy, n);
2699 
2700  return (result);
2701 }
2702 
2703 /* ---- AA-Polygon */
2704 
2716 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2717 {
2718  Uint8 *c = (Uint8 *)&color;
2719  return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2720 }
2721 
2736 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2737 {
2738  int result;
2739  int i;
2740  const Sint16 *x1, *y1, *x2, *y2;
2741 
2742  /*
2743  * Vertex array NULL check
2744  */
2745  if (vx == NULL) {
2746  return (-1);
2747  }
2748  if (vy == NULL) {
2749  return (-1);
2750  }
2751 
2752  /*
2753  * Sanity check
2754  */
2755  if (n < 3) {
2756  return (-1);
2757  }
2758 
2759  /*
2760  * Pointer setup
2761  */
2762  x1 = x2 = vx;
2763  y1 = y2 = vy;
2764  x2++;
2765  y2++;
2766 
2767  /*
2768  * Draw
2769  */
2770  result = 0;
2771  for (i = 1; i < n; i++) {
2772  result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
2773  x1 = x2;
2774  y1 = y2;
2775  x2++;
2776  y2++;
2777  }
2778 
2779  result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
2780 
2781  return (result);
2782 }
2783 
2784 /* ---- Filled Polygon */
2785 
2794 int _gfxPrimitivesCompareInt(const void *a, const void *b)
2795 {
2796  return (*(const int *) a) - (*(const int *) b);
2797 }
2798 
2804 static int *gfxPrimitivesPolyIntsGlobal = NULL;
2805 
2811 static int gfxPrimitivesPolyAllocatedGlobal = 0;
2812 
2831 int filledPolygonRGBAMT(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
2832 {
2833  int result;
2834  int i;
2835  int y, xa, xb;
2836  int miny, maxy;
2837  int x1, y1;
2838  int x2, y2;
2839  int ind1, ind2;
2840  int ints;
2841  int *gfxPrimitivesPolyInts = NULL;
2842  int *gfxPrimitivesPolyIntsNew = NULL;
2843  int gfxPrimitivesPolyAllocated = 0;
2844 
2845  /*
2846  * Vertex array NULL check
2847  */
2848  if (vx == NULL) {
2849  return (-1);
2850  }
2851  if (vy == NULL) {
2852  return (-1);
2853  }
2854 
2855  /*
2856  * Sanity check number of edges
2857  */
2858  if (n < 3) {
2859  return -1;
2860  }
2861 
2862  /*
2863  * Map polygon cache
2864  */
2865  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2866  /* Use global cache */
2867  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
2868  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
2869  } else {
2870  /* Use local cache */
2871  gfxPrimitivesPolyInts = *polyInts;
2872  gfxPrimitivesPolyAllocated = *polyAllocated;
2873  }
2874 
2875  /*
2876  * Allocate temp array, only grow array
2877  */
2878  if (!gfxPrimitivesPolyAllocated) {
2879  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
2880  gfxPrimitivesPolyAllocated = n;
2881  } else {
2882  if (gfxPrimitivesPolyAllocated < n) {
2883  gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
2884  if (!gfxPrimitivesPolyIntsNew) {
2885  if (!gfxPrimitivesPolyInts) {
2886  free(gfxPrimitivesPolyInts);
2887  gfxPrimitivesPolyInts = NULL;
2888  }
2889  gfxPrimitivesPolyAllocated = 0;
2890  } else {
2891  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
2892  gfxPrimitivesPolyAllocated = n;
2893  }
2894  }
2895  }
2896 
2897  /*
2898  * Check temp array
2899  */
2900  if (gfxPrimitivesPolyInts==NULL) {
2901  gfxPrimitivesPolyAllocated = 0;
2902  }
2903 
2904  /*
2905  * Update cache variables
2906  */
2907  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2908  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
2909  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
2910  } else {
2911  *polyInts = gfxPrimitivesPolyInts;
2912  *polyAllocated = gfxPrimitivesPolyAllocated;
2913  }
2914 
2915  /*
2916  * Check temp array again
2917  */
2918  if (gfxPrimitivesPolyInts==NULL) {
2919  return(-1);
2920  }
2921 
2922  /*
2923  * Determine Y maxima
2924  */
2925  miny = vy[0];
2926  maxy = vy[0];
2927  for (i = 1; (i < n); i++) {
2928  if (vy[i] < miny) {
2929  miny = vy[i];
2930  } else if (vy[i] > maxy) {
2931  maxy = vy[i];
2932  }
2933  }
2934 
2935  /*
2936  * Draw, scanning y
2937  */
2938  result = 0;
2939  for (y = miny; (y <= maxy); y++) {
2940  ints = 0;
2941  for (i = 0; (i < n); i++) {
2942  if (!i) {
2943  ind1 = n - 1;
2944  ind2 = 0;
2945  } else {
2946  ind1 = i - 1;
2947  ind2 = i;
2948  }
2949  y1 = vy[ind1];
2950  y2 = vy[ind2];
2951  if (y1 < y2) {
2952  x1 = vx[ind1];
2953  x2 = vx[ind2];
2954  } else if (y1 > y2) {
2955  y2 = vy[ind1];
2956  y1 = vy[ind2];
2957  x2 = vx[ind1];
2958  x1 = vx[ind2];
2959  } else {
2960  continue;
2961  }
2962  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
2963  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
2964  }
2965  }
2966 
2967  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
2968 
2969  /*
2970  * Set color
2971  */
2972  result = 0;
2973  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2974  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2975 
2976  for (i = 0; (i < ints); i += 2) {
2977  xa = gfxPrimitivesPolyInts[i] + 1;
2978  xa = (xa >> 16) + ((xa & 32768) >> 15);
2979  xb = gfxPrimitivesPolyInts[i+1] - 1;
2980  xb = (xb >> 16) + ((xb & 32768) >> 15);
2981  result |= hline(renderer, xa, xb, y);
2982  }
2983  }
2984 
2985  return (result);
2986 }
2987 
2999 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
3000 {
3001  Uint8 *c = (Uint8 *)&color;
3002  return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
3003 }
3004 
3019 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3020 {
3021  return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
3022 }
3023 
3024 /* ---- Textured Polygon */
3025 
3041 int _HLineTextured(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, SDL_Texture *texture, int texture_w, int texture_h, int texture_dx, int texture_dy)
3042 {
3043  Sint16 w;
3044  Sint16 xtmp;
3045  int result = 0;
3046  int texture_x_walker;
3047  int texture_y_start;
3048  SDL_Rect source_rect,dst_rect;
3049  int pixels_written,write_width;
3050 
3051  /*
3052  * Swap x1, x2 if required to ensure x1<=x2
3053  */
3054  if (x1 > x2) {
3055  xtmp = x1;
3056  x1 = x2;
3057  x2 = xtmp;
3058  }
3059 
3060  /*
3061  * Calculate width to draw
3062  */
3063  w = x2 - x1 + 1;
3064 
3065  /*
3066  * Determine where in the texture we start drawing
3067  */
3068  texture_x_walker = (x1 - texture_dx) % texture_w;
3069  if (texture_x_walker < 0){
3070  texture_x_walker = texture_w + texture_x_walker ;
3071  }
3072 
3073  texture_y_start = (y + texture_dy) % texture_h;
3074  if (texture_y_start < 0){
3075  texture_y_start = texture_h + texture_y_start;
3076  }
3077 
3078  // setup the source rectangle; we are only drawing one horizontal line
3079  source_rect.y = texture_y_start;
3080  source_rect.x = texture_x_walker;
3081  source_rect.h = 1;
3082 
3083  // we will draw to the current y
3084  dst_rect.y = y;
3085  dst_rect.h = 1;
3086 
3087  // if there are enough pixels left in the current row of the texture
3088  // draw it all at once
3089  if (w <= texture_w -texture_x_walker){
3090  source_rect.w = w;
3091  source_rect.x = texture_x_walker;
3092  dst_rect.x= x1;
3093  dst_rect.w = source_rect.w;
3094  result = (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
3095  } else {
3096  // we need to draw multiple times
3097  // draw the first segment
3098  pixels_written = texture_w - texture_x_walker;
3099  source_rect.w = pixels_written;
3100  source_rect.x = texture_x_walker;
3101  dst_rect.x= x1;
3102  dst_rect.w = source_rect.w;
3103  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
3104  write_width = texture_w;
3105 
3106  // now draw the rest
3107  // set the source x to 0
3108  source_rect.x = 0;
3109  while (pixels_written < w){
3110  if (write_width >= w - pixels_written) {
3111  write_width = w - pixels_written;
3112  }
3113  source_rect.w = write_width;
3114  dst_rect.x = x1 + pixels_written;
3115  dst_rect.w = source_rect.w;
3116  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
3117  pixels_written += write_width;
3118  }
3119  }
3120 
3121  return result;
3122 }
3123 
3140 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
3141  SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
3142 {
3143  int result;
3144  int i;
3145  int y, xa, xb;
3146  int minx,maxx,miny, maxy;
3147  int x1, y1;
3148  int x2, y2;
3149  int ind1, ind2;
3150  int ints;
3151  int *gfxPrimitivesPolyInts = NULL;
3152  int gfxPrimitivesPolyAllocated = 0;
3153  SDL_Texture *textureAsTexture = NULL;
3154 
3155  /*
3156  * Sanity check number of edges
3157  */
3158  if (n < 3) {
3159  return -1;
3160  }
3161 
3162  /*
3163  * Map polygon cache
3164  */
3165  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3166  /* Use global cache */
3167  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
3168  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
3169  } else {
3170  /* Use local cache */
3171  gfxPrimitivesPolyInts = *polyInts;
3172  gfxPrimitivesPolyAllocated = *polyAllocated;
3173  }
3174 
3175  /*
3176  * Allocate temp array, only grow array
3177  */
3178  if (!gfxPrimitivesPolyAllocated) {
3179  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3180  gfxPrimitivesPolyAllocated = n;
3181  } else {
3182  if (gfxPrimitivesPolyAllocated < n) {
3183  gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3184  gfxPrimitivesPolyAllocated = n;
3185  }
3186  }
3187 
3188  /*
3189  * Check temp array
3190  */
3191  if (gfxPrimitivesPolyInts==NULL) {
3192  gfxPrimitivesPolyAllocated = 0;
3193  }
3194 
3195  /*
3196  * Update cache variables
3197  */
3198  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3199  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
3200  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
3201  } else {
3202  *polyInts = gfxPrimitivesPolyInts;
3203  *polyAllocated = gfxPrimitivesPolyAllocated;
3204  }
3205 
3206  /*
3207  * Check temp array again
3208  */
3209  if (gfxPrimitivesPolyInts==NULL) {
3210  return(-1);
3211  }
3212 
3213  /*
3214  * Determine X,Y minima,maxima
3215  */
3216  miny = vy[0];
3217  maxy = vy[0];
3218  minx = vx[0];
3219  maxx = vx[0];
3220  for (i = 1; (i < n); i++) {
3221  if (vy[i] < miny) {
3222  miny = vy[i];
3223  } else if (vy[i] > maxy) {
3224  maxy = vy[i];
3225  }
3226  if (vx[i] < minx) {
3227  minx = vx[i];
3228  } else if (vx[i] > maxx) {
3229  maxx = vx[i];
3230  }
3231  }
3232 
3233  /* Create texture for drawing */
3234  textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
3235  if (textureAsTexture == NULL)
3236  {
3237  return -1;
3238  }
3239  SDL_SetTextureBlendMode(textureAsTexture, SDL_BLENDMODE_BLEND);
3240 
3241  /*
3242  * Draw, scanning y
3243  */
3244  result = 0;
3245  for (y = miny; (y <= maxy); y++) {
3246  ints = 0;
3247  for (i = 0; (i < n); i++) {
3248  if (!i) {
3249  ind1 = n - 1;
3250  ind2 = 0;
3251  } else {
3252  ind1 = i - 1;
3253  ind2 = i;
3254  }
3255  y1 = vy[ind1];
3256  y2 = vy[ind2];
3257  if (y1 < y2) {
3258  x1 = vx[ind1];
3259  x2 = vx[ind2];
3260  } else if (y1 > y2) {
3261  y2 = vy[ind1];
3262  y1 = vy[ind2];
3263  x2 = vx[ind1];
3264  x1 = vx[ind2];
3265  } else {
3266  continue;
3267  }
3268  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
3269  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
3270  }
3271  }
3272 
3273  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
3274 
3275  for (i = 0; (i < ints); i += 2) {
3276  xa = gfxPrimitivesPolyInts[i] + 1;
3277  xa = (xa >> 16) + ((xa & 32768) >> 15);
3278  xb = gfxPrimitivesPolyInts[i+1] - 1;
3279  xb = (xb >> 16) + ((xb & 32768) >> 15);
3280  result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
3281  }
3282  }
3283 
3284  SDL_RenderPresent(renderer);
3285  SDL_DestroyTexture(textureAsTexture);
3286 
3287  return (result);
3288 }
3289 
3306 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
3307 {
3308  /*
3309  * Draw
3310  */
3311  return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
3312 }
3313 
3314 /* ---- Character */
3315 
3319 static SDL_Texture *gfxPrimitivesFont[256];
3320 
3324 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
3325 
3329 static Uint32 charWidth = 8;
3330 
3334 static Uint32 charHeight = 8;
3335 
3339 static Uint32 charWidthLocal = 8;
3340 
3344 static Uint32 charHeightLocal = 8;
3345 
3349 static Uint32 charPitch = 1;
3350 
3354 static Uint32 charRotation = 0;
3355 
3359 static Uint32 charSize = 8;
3360 
3374 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
3375 {
3376  int i;
3377 
3378  if ((fontdata) && (cw) && (ch)) {
3379  currentFontdata = (unsigned char *)fontdata;
3380  charWidth = cw;
3381  charHeight = ch;
3382  } else {
3383  currentFontdata = gfxPrimitivesFontdata;
3384  charWidth = 8;
3385  charHeight = 8;
3386  }
3387 
3388  charPitch = (charWidth+7)/8;
3389  charSize = charPitch * charHeight;
3390 
3391  /* Maybe flip width/height for rendering */
3392  if ((charRotation==1) || (charRotation==3))
3393  {
3394  charWidthLocal = charHeight;
3395  charHeightLocal = charWidth;
3396  }
3397  else
3398  {
3399  charWidthLocal = charWidth;
3400  charHeightLocal = charHeight;
3401  }
3402 
3403  /* Clear character cache */
3404  for (i = 0; i < 256; i++) {
3405  if (gfxPrimitivesFont[i]) {
3406  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3407  gfxPrimitivesFont[i] = NULL;
3408  }
3409  }
3410 }
3411 
3420 void gfxPrimitivesSetFontRotation(Uint32 rotation)
3421 {
3422  int i;
3423 
3424  rotation = rotation & 3;
3425  if (charRotation != rotation)
3426  {
3427  /* Store rotation */
3428  charRotation = rotation;
3429 
3430  /* Maybe flip width/height for rendering */
3431  if ((charRotation==1) || (charRotation==3))
3432  {
3433  charWidthLocal = charHeight;
3434  charHeightLocal = charWidth;
3435  }
3436  else
3437  {
3438  charWidthLocal = charWidth;
3439  charHeightLocal = charHeight;
3440  }
3441 
3442  /* Clear character cache */
3443  for (i = 0; i < 256; i++) {
3444  if (gfxPrimitivesFont[i]) {
3445  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3446  gfxPrimitivesFont[i] = NULL;
3447  }
3448  }
3449  }
3450 }
3451 
3466 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3467 {
3468  SDL_Rect srect;
3469  SDL_Rect drect;
3470  int result;
3471  Uint32 ix, iy;
3472  const unsigned char *charpos;
3473  Uint8 *curpos;
3474  Uint8 patt, mask;
3475  Uint8 *linepos;
3476  Uint32 pitch;
3477  SDL_Surface *character;
3478  SDL_Surface *rotatedCharacter;
3479  Uint32 ci;
3480 
3481  /*
3482  * Setup source rectangle
3483  */
3484  srect.x = 0;
3485  srect.y = 0;
3486  srect.w = charWidthLocal;
3487  srect.h = charHeightLocal;
3488 
3489  /*
3490  * Setup destination rectangle
3491  */
3492  drect.x = x;
3493  drect.y = y;
3494  drect.w = charWidthLocal;
3495  drect.h = charHeightLocal;
3496 
3497  /* Character index in cache */
3498  ci = (unsigned char) c;
3499 
3500  /*
3501  * Create new charWidth x charHeight bitmap surface if not already present.
3502  * Might get rotated later.
3503  */
3504  if (gfxPrimitivesFont[ci] == NULL) {
3505  /*
3506  * Redraw character into surface
3507  */
3508  character = SDL_CreateRGBSurface(SDL_SWSURFACE,
3509  charWidth, charHeight, 32,
3510  0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
3511  if (character == NULL) {
3512  return (-1);
3513  }
3514 
3515  charpos = currentFontdata + ci * charSize;
3516  linepos = (Uint8 *)character->pixels;
3517  pitch = character->pitch;
3518 
3519  /*
3520  * Drawing loop
3521  */
3522  patt = 0;
3523  for (iy = 0; iy < charHeight; iy++) {
3524  mask = 0x00;
3525  curpos = linepos;
3526  for (ix = 0; ix < charWidth; ix++) {
3527  if (!(mask >>= 1)) {
3528  patt = *charpos++;
3529  mask = 0x80;
3530  }
3531  if (patt & mask) {
3532  *(Uint32 *)curpos = 0xffffffff;
3533  } else {
3534  *(Uint32 *)curpos = 0;
3535  }
3536  curpos += 4;
3537  }
3538  linepos += pitch;
3539  }
3540 
3541  /* Maybe rotate and replace cached image */
3542  if (charRotation>0)
3543  {
3544  rotatedCharacter = rotateSurface90Degrees(character, charRotation);
3545  SDL_FreeSurface(character);
3546  character = rotatedCharacter;
3547  }
3548 
3549  /* Convert temp surface into texture */
3550  gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
3551  SDL_FreeSurface(character);
3552 
3553  /*
3554  * Check pointer
3555  */
3556  if (gfxPrimitivesFont[ci] == NULL) {
3557  return (-1);
3558  }
3559  }
3560 
3561  /*
3562  * Set color
3563  */
3564  result = 0;
3565  result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
3566  result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
3567 
3568  /*
3569  * Draw texture onto destination
3570  */
3571  result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
3572 
3573  return (result);
3574 }
3575 
3576 
3588 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
3589 {
3590  Uint8 *co = (Uint8 *)&color;
3591  return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
3592 }
3593 
3594 
3609 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
3610 {
3611  Uint8 *c = (Uint8 *)&color;
3612  return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
3613 }
3614 
3629 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3630 {
3631  int result = 0;
3632  Sint16 curx = x;
3633  Sint16 cury = y;
3634  const char *curchar = s;
3635 
3636  while (*curchar && !result) {
3637  result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
3638  switch (charRotation)
3639  {
3640  case 0:
3641  curx += charWidthLocal;
3642  break;
3643  case 2:
3644  curx -= charWidthLocal;
3645  break;
3646  case 1:
3647  cury += charHeightLocal;
3648  break;
3649  case 3:
3650  cury -= charHeightLocal;
3651  break;
3652  }
3653  curchar++;
3654  }
3655 
3656  return (result);
3657 }
3658 
3659 /* ---- Bezier curve */
3660 
3670 double _evaluateBezier (double *data, int ndata, double t)
3671 {
3672  double mu, result;
3673  int n,k,kn,nn,nkn;
3674  double blend,muk,munk;
3675 
3676  /* Sanity check bounds */
3677  if (t<0.0) {
3678  return(data[0]);
3679  }
3680  if (t>=(double)ndata) {
3681  return(data[ndata-1]);
3682  }
3683 
3684  /* Adjust t to the range 0.0 to 1.0 */
3685  mu=t/(double)ndata;
3686 
3687  /* Calculate interpolate */
3688  n=ndata-1;
3689  result=0.0;
3690  muk = 1;
3691  munk = pow(1-mu,(double)n);
3692  for (k=0;k<=n;k++) {
3693  nn = n;
3694  kn = k;
3695  nkn = n - k;
3696  blend = muk * munk;
3697  muk *= mu;
3698  munk /= (1-mu);
3699  while (nn >= 1) {
3700  blend *= nn;
3701  nn--;
3702  if (kn > 1) {
3703  blend /= (double)kn;
3704  kn--;
3705  }
3706  if (nkn > 1) {
3707  blend /= (double)nkn;
3708  nkn--;
3709  }
3710  }
3711  result += data[k] * blend;
3712  }
3713 
3714  return (result);
3715 }
3716 
3729 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
3730 {
3731  Uint8 *c = (Uint8 *)&color;
3732  return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
3733 }
3734 
3750 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3751 {
3752  int result;
3753  int i;
3754  double *x, *y, t, stepsize;
3755  Sint16 x1, y1, x2, y2;
3756 
3757  /*
3758  * Sanity check
3759  */
3760  if (n < 3) {
3761  return (-1);
3762  }
3763  if (s < 2) {
3764  return (-1);
3765  }
3766 
3767  /*
3768  * Variable setup
3769  */
3770  stepsize=(double)1.0/(double)s;
3771 
3772  /* Transfer vertices into float arrays */
3773  if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3774  return(-1);
3775  }
3776  if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3777  free(x);
3778  return(-1);
3779  }
3780  for (i=0; i<n; i++) {
3781  x[i]=(double)vx[i];
3782  y[i]=(double)vy[i];
3783  }
3784  x[n]=(double)vx[0];
3785  y[n]=(double)vy[0];
3786 
3787  /*
3788  * Set color
3789  */
3790  result = 0;
3791  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
3792  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
3793 
3794  /*
3795  * Draw
3796  */
3797  t=0.0;
3798  x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
3799  y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
3800  for (i = 0; i <= (n*s); i++) {
3801  t += stepsize;
3802  x2=(Sint16)_evaluateBezier(x,n,t);
3803  y2=(Sint16)_evaluateBezier(y,n,t);
3804  result |= line(renderer, x1, y1, x2, y2);
3805  x1 = x2;
3806  y1 = y2;
3807  }
3808 
3809  /* Clean up temporary array */
3810  free(x);
3811  free(y);
3812 
3813  return (result);
3814 }
3815 
3816 
3817 /* ---- Thick Line */
3818 
3837 int _bresenhamInitialize(SDL2_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
3838 {
3839  int temp;
3840 
3841  if (b==NULL) {
3842  return(-1);
3843  }
3844 
3845  b->x = x1;
3846  b->y = y1;
3847 
3848  /* dx = abs(x2-x1), s1 = sign(x2-x1) */
3849  if ((b->dx = x2 - x1) != 0) {
3850  if (b->dx < 0) {
3851  b->dx = -b->dx;
3852  b->s1 = -1;
3853  } else {
3854  b->s1 = 1;
3855  }
3856  } else {
3857  b->s1 = 0;
3858  }
3859 
3860  /* dy = abs(y2-y1), s2 = sign(y2-y1) */
3861  if ((b->dy = y2 - y1) != 0) {
3862  if (b->dy < 0) {
3863  b->dy = -b->dy;
3864  b->s2 = -1;
3865  } else {
3866  b->s2 = 1;
3867  }
3868  } else {
3869  b->s2 = 0;
3870  }
3871 
3872  if (b->dy > b->dx) {
3873  temp = b->dx;
3874  b->dx = b->dy;
3875  b->dy = temp;
3876  b->swapdir = 1;
3877  } else {
3878  b->swapdir = 0;
3879  }
3880 
3881  b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
3882  b->dy <<= 1;
3883  b->error = b->dy - b->dx;
3884  b->dx <<= 1;
3885 
3886  return(0);
3887 }
3888 
3889 
3900 {
3901  if (b==NULL) {
3902  return (-1);
3903  }
3904 
3905  /* last point check */
3906  if (b->count==0) {
3907  return (2);
3908  }
3909 
3910  while (b->error >= 0) {
3911  if (b->swapdir) {
3912  b->x += b->s1;
3913  } else {
3914  b->y += b->s2;
3915  }
3916 
3917  b->error -= b->dx;
3918  }
3919 
3920  if (b->swapdir) {
3921  b->y += b->s2;
3922  } else {
3923  b->x += b->s1;
3924  }
3925 
3926  b->error += b->dy;
3927  b->count--;
3928 
3929  /* count==0 indicates "end-of-line" */
3930  return ((b->count) ? 0 : 1);
3931 }
3932 
3933 
3942 void _murphyParaline(SDL2_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
3943 {
3944  int p;
3945  d1 = -d1;
3946 
3947  for (p = 0; p <= m->u; p++) {
3948 
3949  pixel(m->renderer, x, y);
3950 
3951  if (d1 <= m->kt) {
3952  if (m->oct2 == 0) {
3953  x++;
3954  } else {
3955  if (m->quad4 == 0) {
3956  y++;
3957  } else {
3958  y--;
3959  }
3960  }
3961  d1 += m->kv;
3962  } else {
3963  x++;
3964  if (m->quad4 == 0) {
3965  y++;
3966  } else {
3967  y--;
3968  }
3969  d1 += m->kd;
3970  }
3971  }
3972 
3973  m->tempx = x;
3974  m->tempy = y;
3975 }
3976 
3993  Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
3994  Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
3995 {
3996  int atemp1, atemp2;
3997  int ftmp1, ftmp2;
3998  Uint16 m1x, m1y, m2x, m2y;
3999  Uint16 fix, fiy, lax, lay, curx, cury;
4000  Sint16 px[4], py[4];
4002 
4003  if (miter > 1) {
4004  if (m->first1x != -32768) {
4005  fix = (m->first1x + m->first2x) / 2;
4006  fiy = (m->first1y + m->first2y) / 2;
4007  lax = (m->last1x + m->last2x) / 2;
4008  lay = (m->last1y + m->last2y) / 2;
4009  curx = (ml1x + ml2x) / 2;
4010  cury = (ml1y + ml2y) / 2;
4011 
4012  atemp1 = (fix - curx);
4013  atemp2 = (fiy - cury);
4014  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
4015  atemp1 = (lax - curx);
4016  atemp2 = (lay - cury);
4017  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
4018 
4019  if (ftmp1 <= ftmp2) {
4020  m1x = m->first1x;
4021  m1y = m->first1y;
4022  m2x = m->first2x;
4023  m2y = m->first2y;
4024  } else {
4025  m1x = m->last1x;
4026  m1y = m->last1y;
4027  m2x = m->last2x;
4028  m2y = m->last2y;
4029  }
4030 
4031  atemp1 = (m2x - ml2x);
4032  atemp2 = (m2y - ml2y);
4033  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
4034  atemp1 = (m2x - ml2bx);
4035  atemp2 = (m2y - ml2by);
4036  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
4037 
4038  if (ftmp2 >= ftmp1) {
4039  ftmp1 = ml2bx;
4040  ftmp2 = ml2by;
4041  ml2bx = ml2x;
4042  ml2by = ml2y;
4043  ml2x = ftmp1;
4044  ml2y = ftmp2;
4045  ftmp1 = ml1bx;
4046  ftmp2 = ml1by;
4047  ml1bx = ml1x;
4048  ml1by = ml1y;
4049  ml1x = ftmp1;
4050  ml1y = ftmp2;
4051  }
4052 
4053  /*
4054  * Lock the surface
4055  */
4056  _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
4057  do {
4058  pixel(m->renderer, b.x, b.y);
4059  } while (_bresenhamIterate(&b)==0);
4060 
4061  _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
4062  do {
4063  pixel(m->renderer, b.x, b.y);
4064  } while (_bresenhamIterate(&b)==0);
4065 
4066  _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
4067  do {
4068  pixel(m->renderer, b.x, b.y);
4069  } while (_bresenhamIterate(&b)==0);
4070 
4071  _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
4072  do {
4073  pixel(m->renderer, b.x, b.y);
4074  } while (_bresenhamIterate(&b)==0);
4075 
4076  px[0] = m1x;
4077  px[1] = m2x;
4078  px[2] = ml1bx;
4079  px[3] = ml2bx;
4080  py[0] = m1y;
4081  py[1] = m2y;
4082  py[2] = ml1by;
4083  py[3] = ml2by;
4084  polygon(m->renderer, px, py, 4);
4085  }
4086  }
4087 
4088  m->last1x = ml1x;
4089  m->last1y = ml1y;
4090  m->last2x = ml2x;
4091  m->last2y = ml2y;
4092  m->first1x = ml1bx;
4093  m->first1y = ml1by;
4094  m->first2x = ml2bx;
4095  m->first2y = ml2by;
4096 }
4097 
4098 
4099 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
4100 
4115 void _murphyWideline(SDL2_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
4116 {
4117  float offset = (float)width / 2.f;
4118 
4119  Sint16 temp;
4120  Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
4121 
4122  int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
4123 
4124  int q; /* pel counter,q=perpendicular to line */
4125  int tmp;
4126 
4127  int dd; /* distance along line */
4128  int tk; /* thickness threshold */
4129  double ang; /* angle for initial point calculation */
4130  double sang, cang;
4131 
4132  /* Initialisation */
4133  m->u = x2 - x1; /* delta x */
4134  m->v = y2 - y1; /* delta y */
4135 
4136  if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
4137  temp = x1;
4138  x1 = x2;
4139  x2 = temp;
4140  temp = y1;
4141  y1 = y2;
4142  y2 = temp;
4143  m->u *= -1;
4144  m->v *= -1;
4145  }
4146 
4147  if (m->v < 0) { /* swap to 1st quadrant and flag */
4148  m->v *= -1;
4149  m->quad4 = 1;
4150  } else {
4151  m->quad4 = 0;
4152  }
4153 
4154  if (m->v > m->u) { /* swap things if in 2 octant */
4155  tmp = m->u;
4156  m->u = m->v;
4157  m->v = tmp;
4158  m->oct2 = 1;
4159  } else {
4160  m->oct2 = 0;
4161  }
4162 
4163  m->ku = m->u + m->u; /* change in l for square shift */
4164  m->kv = m->v + m->v; /* change in d for square shift */
4165  m->kd = m->kv - m->ku; /* change in d for diagonal shift */
4166  m->kt = m->u - m->kv; /* diag/square decision threshold */
4167 
4168  d0 = 0;
4169  d1 = 0;
4170  dd = 0;
4171 
4172  ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
4173  sang = sin(ang);
4174  cang = cos(ang);
4175 
4176  if (m->oct2 == 0) {
4177  ptx = x1 + (Sint16)lrint(offset * sang);
4178  if (m->quad4 == 0) {
4179  pty = y1 - (Sint16)lrint(offset * cang);
4180  } else {
4181  pty = y1 + (Sint16)lrint(offset * cang);
4182  }
4183  } else {
4184  ptx = x1 - (Sint16)lrint(offset * cang);
4185  if (m->quad4 == 0) {
4186  pty = y1 + (Sint16)lrint(offset * sang);
4187  } else {
4188  pty = y1 - (Sint16)lrint(offset * sang);
4189  }
4190  }
4191 
4192  /* used here for constant thickness line */
4193  tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
4194 
4195  if (miter == 0) {
4196  m->first1x = -32768;
4197  m->first1y = -32768;
4198  m->first2x = -32768;
4199  m->first2y = -32768;
4200  m->last1x = -32768;
4201  m->last1y = -32768;
4202  m->last2x = -32768;
4203  m->last2y = -32768;
4204  }
4205  ptxx = ptx;
4206  ptxy = pty;
4207 
4208  for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */
4209 
4210  _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
4211  if (q == 0) {
4212  ml1x = ptx;
4213  ml1y = pty;
4214  ml1bx = m->tempx;
4215  ml1by = m->tempy;
4216  } else {
4217  ml2x = ptx;
4218  ml2y = pty;
4219  ml2bx = m->tempx;
4220  ml2by = m->tempy;
4221  }
4222  if (d0 < m->kt) { /* square move */
4223  if (m->oct2 == 0) {
4224  if (m->quad4 == 0) {
4225  pty++;
4226  } else {
4227  pty--;
4228  }
4229  } else {
4230  ptx++;
4231  }
4232  } else { /* diagonal move */
4233  dd += m->kv;
4234  d0 -= m->ku;
4235  if (d1 < m->kt) { /* normal diagonal */
4236  if (m->oct2 == 0) {
4237  ptx--;
4238  if (m->quad4 == 0) {
4239  pty++;
4240  } else {
4241  pty--;
4242  }
4243  } else {
4244  ptx++;
4245  if (m->quad4 == 0) {
4246  pty--;
4247  } else {
4248  pty++;
4249  }
4250  }
4251  d1 += m->kv;
4252  } else { /* double square move, extra parallel line */
4253  if (m->oct2 == 0) {
4254  ptx--;
4255  } else {
4256  if (m->quad4 == 0) {
4257  pty--;
4258  } else {
4259  pty++;
4260  }
4261  }
4262  d1 += m->kd;
4263  if (dd > tk) {
4264  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
4265  return; /* breakout on the extra line */
4266  }
4267  _murphyParaline(m, ptx, pty, d1);
4268  if (m->oct2 == 0) {
4269  if (m->quad4 == 0) {
4270  pty++;
4271  } else {
4272 
4273  pty--;
4274  }
4275  } else {
4276  ptx++;
4277  }
4278  }
4279  }
4280  dd += m->ku;
4281  d0 += m->kv;
4282  }
4283 
4284  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
4285 }
4286 
4287 
4301 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
4302 {
4303  Uint8 *c = (Uint8 *)&color;
4304  return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
4305 }
4306 
4323 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4324 {
4325  int result;
4326  int wh;
4328 
4329  if (renderer == NULL) {
4330  return -1;
4331  }
4332  if (width < 1) {
4333  return -1;
4334  }
4335 
4336  /* Special case: thick "point" */
4337  if ((x1 == x2) && (y1 == y2)) {
4338  wh = width / 2;
4339  return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
4340  }
4341 
4342  /*
4343  * Set color
4344  */
4345  result = 0;
4346  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
4347  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
4348 
4349  /*
4350  * Draw
4351  */
4352  m.renderer = renderer;
4353  _murphyWideline(&m, x1, y1, x2, y2, width, 0);
4354  _murphyWideline(&m, x1, y1, x2, y2, width, 1);
4355 
4356  return(0);
4357 }
int polygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw polygon with alpha blending.
int filledPieColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Draw filled pie with alpha blending.
#define HYPOT(x, y)
int line(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
Draw line with alpha blending using the currently set color.
void _murphyWideline(SDL2_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
Internal function to to draw wide lines with Murphy algorithm.
int filledPolygonRGBAMT(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int **polyInts, int *polyAllocated)
Draw filled polygon with alpha blending (multi-threaded capable).
int roundedBoxRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw rounded-corner box (filled rectangle) with blending.
int boxColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw box (filled rectangle) with blending.
int pixelColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint32 color)
Draw pixel with blending enabled if a<255.
The structure passed to the internal Murphy iterator.
int ellipseRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw ellipse with blending.
int filledEllipseRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled ellipse with blending.
int trigonRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw trigon (triangle outline) with alpha blending.
The structure passed to the internal Bresenham iterator.
int arcColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Arc with blending.
int aatrigonColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
Draw anti-aliased trigon (triangle outline) with alpha blending.
int filledPolygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw filled polygon with alpha blending.
void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
Sets or resets the current global font data.
int pixelRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw pixel with blending enabled if a<255.
int ellipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw ellipse with blending.
int roundedRectangleColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
Draw rounded-corner rectangle with blending.
int boxRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw box (filled rectangle) with blending.
int roundedRectangleRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw rounded-corner rectangle with blending.
int polygon(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n)
Draw polygon with the currently set color and blend mode.
int circleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw circle with blending.
int hlineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw horizontal line with blending.
int rectangleColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw rectangle with blending.
int _bresenhamInitialize(SDL2_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
Internal function to initialize the Bresenham line iterator.
int texturedPolygon(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
Draws a polygon filled with the given texture.
int stringRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw a string in the currently set font.
int aapolygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw anti-aliased polygon with alpha blending.
#define AAbits
int pixelRGBAWeight(SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint32 weight)
Draw pixel with blending enabled and using alpha weight on color.
int pixel(SDL_Renderer *renderer, Sint16 x, Sint16 y)
Draw pixel in currently set color.
int aacircleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw anti-aliased circle with blending.
int filledCircleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw filled circle with blending.
int lineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw line with alpha blending.
int aaellipseRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw anti-aliased ellipse with blending.
int filledTrigonRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled trigon (triangle) with alpha blending.
int _HLineTextured(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, SDL_Texture *texture, int texture_w, int texture_h, int texture_dx, int texture_dy)
Internal function to draw a textured horizontal line.
double _evaluateBezier(double *data, int ndata, double t)
Internal function to calculate bezier interpolator of data array with ndata values at position &#39;t&#39;...
int aalineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw anti-aliased line with alpha blending.
void gfxPrimitivesSetFontRotation(Uint32 rotation)
Sets current global font character rotation steps.
void _murphyParaline(SDL2_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
Internal function to to draw parallel lines with Murphy algorithm.
int bezierRGBA(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw a bezier curve with alpha blending.
int lineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw line with alpha blending.
void _murphyIteration(SDL2_gfxMurphyIterator *m, Uint8 miter, Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by, Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
Internal function to to draw one iteration of the Murphy algorithm.
int _bresenhamIterate(SDL2_gfxBresenhamIterator *b)
Internal function to move Bresenham line iterator to the next position.
int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw a thick line with alpha blending.
#define AAlevels
int circleRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw circle with blending.
int _gfxPrimitivesCompareInt(const void *a, const void *b)
Internal helper qsort callback functions used in filled polygon drawing.
int hlineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
Draw horizontal line with blending.
int stringColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
Draw a string in the currently set font.
int rectangleRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw rectangle with blending.
int polygonRGBA(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw polygon with alpha blending.
int aacircleRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw anti-aliased circle with blending.
int filledCircleRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled circle with blending.
int filledTrigonColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
Draw filled trigon (triangle) with alpha blending.
int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw a character of the currently set font.
int aapolygonRGBA(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw anti-aliased polygon with alpha blending.
int _aalineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
Internal function to draw anti-aliased line with alpha blending and endpoint control.
int trigonColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
Draw trigon (triangle outline) with alpha blending.
int aatrigonRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw anti-aliased trigon (triangle outline) with alpha blending.
int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
Draw a thick line with alpha blending.
#define M_PI
int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
Draws a polygon filled with the given texture (Multi-Threading Capable).
int characterColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint32 color)
Draw a character of the currently set font.
int bezierColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, int s, Uint32 color)
Draw a bezier curve with alpha blending.
int _pieRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Uint8 filled)
Internal float (low-speed) pie-calc implementation by drawing polygons.
int filledEllipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw filled ellipse with blending.
int hline(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y)
Draw horizontal line in currently set color.
int filledPolygonRGBA(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled polygon with alpha blending.
int pieColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Draw pie (outline) with alpha blending.
int filledPieRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled pie with alpha blending.
int vlineRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw vertical line with blending.
int aalineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw anti-aliased line with alpha blending.
int roundedBoxColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
Draw rounded-corner box (filled rectangle) with blending.
int pieRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw pie (outline) with alpha blending.
int aaellipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw anti-aliased ellipse with blending.
int vlineColor(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
Draw vertical line with blending.
int arcRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Arc with blending.
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.