SDL2_gfx  1.0.0
GraphicsprimitivesandsurfacefunctionsforSDL2
/builddir/build/BUILD/SDL2_gfx-1.0.0/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 == 0) {
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 = 0;
524  Sint16 w, h, tmp;
525  Sint16 xx1, xx2, yy1, yy2;
526 
527  /*
528  * Check destination renderer
529  */
530  if (renderer == NULL)
531  {
532  return -1;
533  }
534 
535  /*
536  * Check radius vor valid range
537  */
538  if (rad < 0) {
539  return -1;
540  }
541 
542  /*
543  * Special case - no rounding
544  */
545  if (rad == 0) {
546  return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
547  }
548 
549  /*
550  * Test for special cases of straight lines or single point
551  */
552  if (x1 == x2) {
553  if (y1 == y2) {
554  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
555  } else {
556  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
557  }
558  } else {
559  if (y1 == y2) {
560  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
561  }
562  }
563 
564  /*
565  * Swap x1, x2 if required
566  */
567  if (x1 > x2) {
568  tmp = x1;
569  x1 = x2;
570  x2 = tmp;
571  }
572 
573  /*
574  * Swap y1, y2 if required
575  */
576  if (y1 > y2) {
577  tmp = y1;
578  y1 = y2;
579  y2 = tmp;
580  }
581 
582  /*
583  * Calculate width&height
584  */
585  w = x2 - x1;
586  h = y2 - y1;
587 
588  /*
589  * Maybe adjust radius
590  */
591  if ((rad * 2) > w)
592  {
593  rad = w / 2;
594  }
595  if ((rad * 2) > h)
596  {
597  rad = h / 2;
598  }
599 
600  /*
601  * Draw corners
602  */
603  xx1 = x1 + rad;
604  xx2 = x2 - rad;
605  yy1 = y1 + rad;
606  yy2 = y2 - rad;
607  result |= filledPieRGBA(renderer, xx1, yy1, rad, 180, 270, r, g, b, a);
608  result |= filledPieRGBA(renderer, xx2, yy1, rad, 270, 360, r, g, b, a);
609  result |= filledPieRGBA(renderer, xx1, yy2, rad, 90, 180, r, g, b, a);
610  result |= filledPieRGBA(renderer, xx2, yy2, rad, 0, 90, r, g, b, a);
611 
612  /*
613  * Draw body
614  */
615  xx1++;
616  xx2--;
617  yy1++;
618  yy2--;
619  if (xx1 <= xx2) {
620  result |= boxRGBA(renderer, xx1, y1, xx2, y2, r, g, b, a);
621  }
622  if (yy1 <= yy2) {
623  result |= boxRGBA(renderer, x1, yy1, xx1-1, yy2, r, g, b, a);
624  result |= boxRGBA(renderer, xx2+1, yy1, x2, yy2, r, g, b, a);
625  }
626 
627  return result;
628 }
629 
630 /* ---- Box */
631 
644 int boxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
645 {
646  Uint8 *c = (Uint8 *)&color;
647  return boxRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
648 }
649 
665 int boxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
666 {
667  int result;
668  Sint16 tmp;
669  SDL_Rect rect;
670 
671  /*
672  * Test for special cases of straight lines or single point
673  */
674  if (x1 == x2) {
675  if (y1 == y2) {
676  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
677  } else {
678  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
679  }
680  } else {
681  if (y1 == y2) {
682  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
683  }
684  }
685 
686  /*
687  * Swap x1, x2 if required
688  */
689  if (x1 > x2) {
690  tmp = x1;
691  x1 = x2;
692  x2 = tmp;
693  }
694 
695  /*
696  * Swap y1, y2 if required
697  */
698  if (y1 > y2) {
699  tmp = y1;
700  y1 = y2;
701  y2 = tmp;
702  }
703 
704  /*
705  * Create destination rect
706  */
707  rect.x = x1;
708  rect.y = y1;
709  rect.w = x2 - x1;
710  rect.h = y2 - y1;
711 
712  /*
713  * Draw
714  */
715  result = 0;
716  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
717  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
718  result |= SDL_RenderFillRect(renderer, &rect);
719  return result;
720 }
721 
722 /* ----- Line */
723 
735 int line(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
736 {
737  /*
738  * Draw
739  */
740  return SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
741 }
742 
755 int lineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
756 {
757  Uint8 *c = (Uint8 *)&color;
758  return lineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
759 }
760 
776 int lineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
777 {
778  /*
779  * Draw
780  */
781  int result = 0;
782  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
783  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
784  result |= SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
785  return result;
786 }
787 
788 /* ---- AA Line */
789 
790 #define AAlevels 256
791 #define AAbits 8
792 
816 int _aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
817 {
818  Sint32 xx0, yy0, xx1, yy1;
819  int result;
820  Uint32 intshift, erracc, erradj;
821  Uint32 erracctmp, wgt, wgtcompmask;
822  int dx, dy, tmp, xdir, y0p1, x0pxdir;
823 
824  /*
825  * Keep on working with 32bit numbers
826  */
827  xx0 = x1;
828  yy0 = y1;
829  xx1 = x2;
830  yy1 = y2;
831 
832  /*
833  * Reorder points to make dy positive
834  */
835  if (yy0 > yy1) {
836  tmp = yy0;
837  yy0 = yy1;
838  yy1 = tmp;
839  tmp = xx0;
840  xx0 = xx1;
841  xx1 = tmp;
842  }
843 
844  /*
845  * Calculate distance
846  */
847  dx = xx1 - xx0;
848  dy = yy1 - yy0;
849 
850  /*
851  * Adjust for negative dx and set xdir
852  */
853  if (dx >= 0) {
854  xdir = 1;
855  } else {
856  xdir = -1;
857  dx = (-dx);
858  }
859 
860  /*
861  * Check for special cases
862  */
863  if (dx == 0) {
864  /*
865  * Vertical line
866  */
867  if (draw_endpoint)
868  {
869  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
870  } else {
871  if (dy > 0) {
872  return (vlineRGBA(renderer, x1, yy0, yy0+dy, r, g, b, a));
873  } else {
874  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
875  }
876  }
877  } else if (dy == 0) {
878  /*
879  * Horizontal line
880  */
881  if (draw_endpoint)
882  {
883  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
884  } else {
885  if (dx > 0) {
886  return (hlineRGBA(renderer, xx0, xx0+dx, y1, r, g, b, a));
887  } else {
888  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
889  }
890  }
891  } else if ((dx == dy) && (draw_endpoint)) {
892  /*
893  * Diagonal line (with endpoint)
894  */
895  return (lineRGBA(renderer, x1, y1, x2, y2, r, g, b, a));
896  }
897 
898 
899  /*
900  * Line is not horizontal, vertical or diagonal (with endpoint)
901  */
902  result = 0;
903 
904  /*
905  * Zero accumulator
906  */
907  erracc = 0;
908 
909  /*
910  * # of bits by which to shift erracc to get intensity level
911  */
912  intshift = 32 - AAbits;
913 
914  /*
915  * Mask used to flip all bits in an intensity weighting
916  */
917  wgtcompmask = AAlevels - 1;
918 
919  /*
920  * Draw the initial pixel in the foreground color
921  */
922  result |= pixelRGBA(renderer, x1, y1, r, g, b, a);
923 
924  /*
925  * x-major or y-major?
926  */
927  if (dy > dx) {
928 
929  /*
930  * y-major. Calculate 16-bit fixed point fractional part of a pixel that
931  * X advances every time Y advances 1 pixel, truncating the result so that
932  * we won't overrun the endpoint along the X axis
933  */
934  /*
935  * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
936  */
937  erradj = ((dx << 16) / dy) << 16;
938 
939  /*
940  * draw all pixels other than the first and last
941  */
942  x0pxdir = xx0 + xdir;
943  while (--dy) {
944  erracctmp = erracc;
945  erracc += erradj;
946  if (erracc <= erracctmp) {
947  /*
948  * rollover in error accumulator, x coord advances
949  */
950  xx0 = x0pxdir;
951  x0pxdir += xdir;
952  }
953  yy0++; /* y-major so always advance Y */
954 
955  /*
956  * the AAbits most significant bits of erracc give us the intensity
957  * weighting for this pixel, and the complement of the weighting for
958  * the paired pixel.
959  */
960  wgt = (erracc >> intshift) & 255;
961  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
962  result |= pixelRGBAWeight (renderer, x0pxdir, yy0, r, g, b, a, wgt);
963  }
964 
965  } else {
966 
967  /*
968  * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
969  * that Y advances each time X advances 1 pixel, truncating the result so
970  * that we won't overrun the endpoint along the X axis.
971  */
972  /*
973  * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
974  */
975  erradj = ((dy << 16) / dx) << 16;
976 
977  /*
978  * draw all pixels other than the first and last
979  */
980  y0p1 = yy0 + 1;
981  while (--dx) {
982 
983  erracctmp = erracc;
984  erracc += erradj;
985  if (erracc <= erracctmp) {
986  /*
987  * Accumulator turned over, advance y
988  */
989  yy0 = y0p1;
990  y0p1++;
991  }
992  xx0 += xdir; /* x-major so always advance X */
993  /*
994  * the AAbits most significant bits of erracc give us the intensity
995  * weighting for this pixel, and the complement of the weighting for
996  * the paired pixel.
997  */
998  wgt = (erracc >> intshift) & 255;
999  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
1000  result |= pixelRGBAWeight (renderer, xx0, y0p1, r, g, b, a, wgt);
1001  }
1002  }
1003 
1004  /*
1005  * Do we have to draw the endpoint
1006  */
1007  if (draw_endpoint) {
1008  /*
1009  * Draw final pixel, always exactly intersected by the line and doesn't
1010  * need to be weighted.
1011  */
1012  result |= pixelRGBA (renderer, x2, y2, r, g, b, a);
1013  }
1014 
1015  return (result);
1016 }
1017 
1030 int aalineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1031 {
1032  Uint8 *c = (Uint8 *)&color;
1033  return _aalineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3], 1);
1034 }
1035 
1051 int aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1052 {
1053  return _aalineRGBA(renderer, x1, y1, x2, y2, r, g, b, a, 1);
1054 }
1055 
1056 /* ----- Circle */
1057 
1069 int circleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1070 {
1071  Uint8 *c = (Uint8 *)&color;
1072  return ellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1073 }
1074 
1089 int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1090 {
1091  return ellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1092 }
1093 
1094 /* ----- Arc */
1095 
1109 int arcColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
1110 {
1111  Uint8 *c = (Uint8 *)&color;
1112  return arcRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3]);
1113 }
1114 
1131 int arcRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1132 {
1133  int result;
1134  Sint16 cx = 0;
1135  Sint16 cy = rad;
1136  Sint16 df = 1 - rad;
1137  Sint16 d_e = 3;
1138  Sint16 d_se = -2 * rad + 5;
1139  Sint16 xpcx, xmcx, xpcy, xmcy;
1140  Sint16 ypcy, ymcy, ypcx, ymcx;
1141  Uint8 drawoct;
1142  int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
1143  double dstart, dend, temp = 0.;
1144 
1145  /*
1146  * Sanity check radius
1147  */
1148  if (rad < 0) {
1149  return (-1);
1150  }
1151 
1152  /*
1153  * Special case for rad=0 - draw a point
1154  */
1155  if (rad == 0) {
1156  return (pixelRGBA(renderer, x, y, r, g, b, a));
1157  }
1158 
1159  // Octant labelling
1160  //
1161  // \ 5 | 6 /
1162  // \ | /
1163  // 4 \ | / 7
1164  // \|/
1165  //------+------ +x
1166  // /|\
1167  // 3 / | \ 0
1168  // / | \
1169  // / 2 | 1 \
1170  // +y
1171 
1172  // Initially reset bitmask to 0x00000000
1173  // the set whether or not to keep drawing a given octant.
1174  // For example: 0x00111100 means we're drawing in octants 2-5
1175  drawoct = 0;
1176 
1177  /*
1178  * Fixup angles
1179  */
1180  start %= 360;
1181  end %= 360;
1182  // 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0.
1183  while (start < 0) start += 360;
1184  while (end < 0) end += 360;
1185  start %= 360;
1186  end %= 360;
1187 
1188  // now, we find which octants we're drawing in.
1189  startoct = start / 45;
1190  endoct = end / 45;
1191  oct = startoct - 1; // we increment as first step in loop
1192 
1193  // stopval_start, stopval_end;
1194  // what values of cx to stop at.
1195  do {
1196  oct = (oct + 1) % 8;
1197 
1198  if (oct == startoct) {
1199  // need to compute stopval_start for this octant. Look at picture above if this is unclear
1200  dstart = (double)start;
1201  switch (oct)
1202  {
1203  case 0:
1204  case 3:
1205  temp = sin(dstart * M_PI / 180.);
1206  break;
1207  case 1:
1208  case 6:
1209  temp = cos(dstart * M_PI / 180.);
1210  break;
1211  case 2:
1212  case 5:
1213  temp = -cos(dstart * M_PI / 180.);
1214  break;
1215  case 4:
1216  case 7:
1217  temp = -sin(dstart * M_PI / 180.);
1218  break;
1219  }
1220  temp *= rad;
1221  stopval_start = (int)temp; // always round down.
1222 
1223  // This isn't arbitrary, but requires graph paper to explain well.
1224  // The basic idea is that we're always changing drawoct after we draw, so we
1225  // stop immediately after we render the last sensible pixel at x = ((int)temp).
1226 
1227  // and whether to draw in this octant initially
1228  if (oct % 2) drawoct |= (1 << oct); // this is basically like saying drawoct[oct] = true, if drawoct were a bool array
1229  else drawoct &= 255 - (1 << oct); // this is basically like saying drawoct[oct] = false
1230  }
1231  if (oct == endoct) {
1232  // need to compute stopval_end for this octant
1233  dend = (double)end;
1234  switch (oct)
1235  {
1236  case 0:
1237  case 3:
1238  temp = sin(dend * M_PI / 180);
1239  break;
1240  case 1:
1241  case 6:
1242  temp = cos(dend * M_PI / 180);
1243  break;
1244  case 2:
1245  case 5:
1246  temp = -cos(dend * M_PI / 180);
1247  break;
1248  case 4:
1249  case 7:
1250  temp = -sin(dend * M_PI / 180);
1251  break;
1252  }
1253  temp *= rad;
1254  stopval_end = (int)temp;
1255 
1256  // and whether to draw in this octant initially
1257  if (startoct == endoct) {
1258  // note: we start drawing, stop, then start again in this case
1259  // otherwise: we only draw in this octant, so initialize it to false, it will get set back to true
1260  if (start > end) {
1261  // unfortunately, if we're in the same octant and need to draw over the whole circle,
1262  // we need to set the rest to true, because the while loop will end at the bottom.
1263  drawoct = 255;
1264  } else {
1265  drawoct &= 255 - (1 << oct);
1266  }
1267  }
1268  else if (oct % 2) drawoct &= 255 - (1 << oct);
1269  else drawoct |= (1 << oct);
1270  } else if (oct != startoct) { // already verified that it's != endoct
1271  drawoct |= (1 << oct); // draw this entire segment
1272  }
1273  } while (oct != endoct);
1274 
1275  // so now we have what octants to draw and when to draw them. all that's left is the actual raster code.
1276 
1277  /*
1278  * Set color
1279  */
1280  result = 0;
1281  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1282  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1283 
1284  /*
1285  * Draw arc
1286  */
1287  do {
1288  ypcy = y + cy;
1289  ymcy = y - cy;
1290  if (cx > 0) {
1291  xpcx = x + cx;
1292  xmcx = x - cx;
1293 
1294  // always check if we're drawing a certain octant before adding a pixel to that octant.
1295  if (drawoct & 4) result |= pixel(renderer, xmcx, ypcy);
1296  if (drawoct & 2) result |= pixel(renderer, xpcx, ypcy);
1297  if (drawoct & 32) result |= pixel(renderer, xmcx, ymcy);
1298  if (drawoct & 64) result |= pixel(renderer, xpcx, ymcy);
1299  } else {
1300  if (drawoct & 96) result |= pixel(renderer, x, ymcy);
1301  if (drawoct & 6) result |= pixel(renderer, x, ypcy);
1302  }
1303 
1304  xpcy = x + cy;
1305  xmcy = x - cy;
1306  if (cx > 0 && cx != cy) {
1307  ypcx = y + cx;
1308  ymcx = y - cx;
1309  if (drawoct & 8) result |= pixel(renderer, xmcy, ypcx);
1310  if (drawoct & 1) result |= pixel(renderer, xpcy, ypcx);
1311  if (drawoct & 16) result |= pixel(renderer, xmcy, ymcx);
1312  if (drawoct & 128) result |= pixel(renderer, xpcy, ymcx);
1313  } else if (cx == 0) {
1314  if (drawoct & 24) result |= pixel(renderer, xmcy, y);
1315  if (drawoct & 129) result |= pixel(renderer, xpcy, y);
1316  }
1317 
1318  /*
1319  * Update whether we're drawing an octant
1320  */
1321  if (stopval_start == cx) {
1322  // works like an on-off switch.
1323  // This is just in case start & end are in the same octant.
1324  if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
1325  else drawoct |= (1 << startoct);
1326  }
1327  if (stopval_end == cx) {
1328  if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
1329  else drawoct |= (1 << endoct);
1330  }
1331 
1332  /*
1333  * Update pixels
1334  */
1335  if (df < 0) {
1336  df += d_e;
1337  d_e += 2;
1338  d_se += 2;
1339  } else {
1340  df += d_se;
1341  d_e += 2;
1342  d_se += 4;
1343  cy--;
1344  }
1345  cx++;
1346  } while (cx <= cy);
1347 
1348  return (result);
1349 }
1350 
1351 /* ----- AA Circle */
1352 
1364 int aacircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1365 {
1366  Uint8 *c = (Uint8 *)&color;
1367  return aaellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1368 }
1369 
1384 int aacircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1385 {
1386  /*
1387  * Draw
1388  */
1389  return aaellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1390 }
1391 
1392 /* ----- Filled Circle */
1393 
1405 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1406 {
1407  Uint8 *c = (Uint8 *)&color;
1408  return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1409 }
1410 
1425 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1426 {
1427  int result;
1428  Sint16 cx = 0;
1429  Sint16 cy = rad;
1430  Sint16 ocx = (Sint16) 0xffff;
1431  Sint16 ocy = (Sint16) 0xffff;
1432  Sint16 df = 1 - rad;
1433  Sint16 d_e = 3;
1434  Sint16 d_se = -2 * rad + 5;
1435  Sint16 xpcx, xmcx, xpcy, xmcy;
1436  Sint16 ypcy, ymcy, ypcx, ymcx;
1437 
1438  /*
1439  * Sanity check radius
1440  */
1441  if (rad < 0) {
1442  return (-1);
1443  }
1444 
1445  /*
1446  * Special case for rad=0 - draw a point
1447  */
1448  if (rad == 0) {
1449  return (pixelRGBA(renderer, x, y, r, g, b, a));
1450  }
1451 
1452  /*
1453  * Set color
1454  */
1455  result = 0;
1456  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1457  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1458 
1459  /*
1460  * Draw
1461  */
1462  do {
1463  xpcx = x + cx;
1464  xmcx = x - cx;
1465  xpcy = x + cy;
1466  xmcy = x - cy;
1467  if (ocy != cy) {
1468  if (cy > 0) {
1469  ypcy = y + cy;
1470  ymcy = y - cy;
1471  result |= hline(renderer, xmcx, xpcx, ypcy);
1472  result |= hline(renderer, xmcx, xpcx, ymcy);
1473  } else {
1474  result |= hline(renderer, xmcx, xpcx, y);
1475  }
1476  ocy = cy;
1477  }
1478  if (ocx != cx) {
1479  if (cx != cy) {
1480  if (cx > 0) {
1481  ypcx = y + cx;
1482  ymcx = y - cx;
1483  result |= hline(renderer, xmcy, xpcy, ymcx);
1484  result |= hline(renderer, xmcy, xpcy, ypcx);
1485  } else {
1486  result |= hline(renderer, xmcy, xpcy, y);
1487  }
1488  }
1489  ocx = cx;
1490  }
1491 
1492  /*
1493  * Update
1494  */
1495  if (df < 0) {
1496  df += d_e;
1497  d_e += 2;
1498  d_se += 2;
1499  } else {
1500  df += d_se;
1501  d_e += 2;
1502  d_se += 4;
1503  cy--;
1504  }
1505  cx++;
1506  } while (cx <= cy);
1507 
1508  return (result);
1509 }
1510 
1511 /* ----- Ellipse */
1512 
1525 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1526 {
1527  Uint8 *c = (Uint8 *)&color;
1528  return ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1529 }
1530 
1546 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1547 {
1548  int result;
1549  int ix, iy;
1550  int h, i, j, k;
1551  int oh, oi, oj, ok;
1552  int xmh, xph, ypk, ymk;
1553  int xmi, xpi, ymj, ypj;
1554  int xmj, xpj, ymi, ypi;
1555  int xmk, xpk, ymh, yph;
1556 
1557  /*
1558  * Sanity check radii
1559  */
1560  if ((rx < 0) || (ry < 0)) {
1561  return (-1);
1562  }
1563 
1564  /*
1565  * Special case for rx=0 - draw a vline
1566  */
1567  if (rx == 0) {
1568  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1569  }
1570  /*
1571  * Special case for ry=0 - draw a hline
1572  */
1573  if (ry == 0) {
1574  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1575  }
1576 
1577  /*
1578  * Set color
1579  */
1580  result = 0;
1581  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1582  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1583 
1584  /*
1585  * Init vars
1586  */
1587  oh = oi = oj = ok = 0xFFFF;
1588 
1589  /*
1590  * Draw
1591  */
1592  if (rx > ry) {
1593  ix = 0;
1594  iy = rx * 64;
1595 
1596  do {
1597  h = (ix + 32) >> 6;
1598  i = (iy + 32) >> 6;
1599  j = (h * ry) / rx;
1600  k = (i * ry) / rx;
1601 
1602  if (((ok != k) && (oj != k)) || ((oj != j) && (ok != j)) || (k != j)) {
1603  xph = x + h;
1604  xmh = x - h;
1605  if (k > 0) {
1606  ypk = y + k;
1607  ymk = y - k;
1608  result |= pixel(renderer, xmh, ypk);
1609  result |= pixel(renderer, xph, ypk);
1610  result |= pixel(renderer, xmh, ymk);
1611  result |= pixel(renderer, xph, ymk);
1612  } else {
1613  result |= pixel(renderer, xmh, y);
1614  result |= pixel(renderer, xph, y);
1615  }
1616  ok = k;
1617  xpi = x + i;
1618  xmi = x - i;
1619  if (j > 0) {
1620  ypj = y + j;
1621  ymj = y - j;
1622  result |= pixel(renderer, xmi, ypj);
1623  result |= pixel(renderer, xpi, ypj);
1624  result |= pixel(renderer, xmi, ymj);
1625  result |= pixel(renderer, xpi, ymj);
1626  } else {
1627  result |= pixel(renderer, xmi, y);
1628  result |= pixel(renderer, xpi, y);
1629  }
1630  oj = j;
1631  }
1632 
1633  ix = ix + iy / rx;
1634  iy = iy - ix / rx;
1635 
1636  } while (i > h);
1637  } else {
1638  ix = 0;
1639  iy = ry * 64;
1640 
1641  do {
1642  h = (ix + 32) >> 6;
1643  i = (iy + 32) >> 6;
1644  j = (h * rx) / ry;
1645  k = (i * rx) / ry;
1646 
1647  if (((oi != i) && (oh != i)) || ((oh != h) && (oi != h) && (i != h))) {
1648  xmj = x - j;
1649  xpj = x + j;
1650  if (i > 0) {
1651  ypi = y + i;
1652  ymi = y - i;
1653  result |= pixel(renderer, xmj, ypi);
1654  result |= pixel(renderer, xpj, ypi);
1655  result |= pixel(renderer, xmj, ymi);
1656  result |= pixel(renderer, xpj, ymi);
1657  } else {
1658  result |= pixel(renderer, xmj, y);
1659  result |= pixel(renderer, xpj, y);
1660  }
1661  oi = i;
1662  xmk = x - k;
1663  xpk = x + k;
1664  if (h > 0) {
1665  yph = y + h;
1666  ymh = y - h;
1667  result |= pixel(renderer, xmk, yph);
1668  result |= pixel(renderer, xpk, yph);
1669  result |= pixel(renderer, xmk, ymh);
1670  result |= pixel(renderer, xpk, ymh);
1671  } else {
1672  result |= pixel(renderer, xmk, y);
1673  result |= pixel(renderer, xpk, y);
1674  }
1675  oh = h;
1676  }
1677 
1678  ix = ix + iy / ry;
1679  iy = iy - ix / ry;
1680 
1681  } while (i > h);
1682  }
1683 
1684  return (result);
1685 }
1686 
1687 /* ----- AA Ellipse */
1688 
1689 /* Windows targets do not have lrint, so provide a local inline version */
1690 #if defined(_MSC_VER)
1691 /* Detect 64bit and use intrinsic version */
1692 #ifdef _M_X64
1693 #include <emmintrin.h>
1694 static __inline long
1695  lrint(float f)
1696 {
1697  return _mm_cvtss_si32(_mm_load_ss(&f));
1698 }
1699 #elif defined(_M_IX86)
1700 __inline long int
1701  lrint (double flt)
1702 {
1703  int intgr;
1704  _asm
1705  {
1706  fld flt
1707  fistp intgr
1708  };
1709  return intgr;
1710 }
1711 #elif defined(_M_ARM)
1712 #include <armintr.h>
1713 #pragma warning(push)
1714 #pragma warning(disable: 4716)
1715 __declspec(naked) long int
1716  lrint (double flt)
1717 {
1718  __emit(0xEC410B10); // fmdrr d0, r0, r1
1719  __emit(0xEEBD0B40); // ftosid s0, d0
1720  __emit(0xEE100A10); // fmrs r0, s0
1721  __emit(0xE12FFF1E); // bx lr
1722 }
1723 #pragma warning(pop)
1724 #else
1725 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
1726 #endif
1727 #endif
1728 
1741 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1742 {
1743  Uint8 *c = (Uint8 *)&color;
1744  return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1745 }
1746 
1762 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1763 {
1764  int result;
1765  int i;
1766  int a2, b2, ds, dt, dxt, t, s, d;
1767  Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
1768  float cp;
1769  double sab;
1770  Uint8 weight, iweight;
1771 
1772  /*
1773  * Sanity check radii
1774  */
1775  if ((rx < 0) || (ry < 0)) {
1776  return (-1);
1777  }
1778 
1779  /*
1780  * Special case for rx=0 - draw a vline
1781  */
1782  if (rx == 0) {
1783  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1784  }
1785  /*
1786  * Special case for ry=0 - draw an hline
1787  */
1788  if (ry == 0) {
1789  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1790  }
1791 
1792  /* Variable setup */
1793  a2 = rx * rx;
1794  b2 = ry * ry;
1795 
1796  ds = 2 * a2;
1797  dt = 2 * b2;
1798 
1799  xc2 = 2 * x;
1800  yc2 = 2 * y;
1801 
1802  sab = sqrt((double)(a2 + b2));
1803  od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
1804  dxt = (Sint16)lrint((double)a2 / sab) + od;
1805 
1806  t = 0;
1807  s = -2 * a2 * ry;
1808  d = 0;
1809 
1810  xp = x;
1811  yp = y - ry;
1812 
1813  /* Draw */
1814  result = 0;
1815  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1816 
1817  /* "End points" */
1818  result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
1819  result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
1820  result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
1821  result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
1822 
1823  for (i = 1; i <= dxt; i++) {
1824  xp--;
1825  d += t - b2;
1826 
1827  if (d >= 0)
1828  ys = yp - 1;
1829  else if ((d - s - a2) > 0) {
1830  if ((2 * d - s - a2) >= 0)
1831  ys = yp + 1;
1832  else {
1833  ys = yp;
1834  yp++;
1835  d -= s + a2;
1836  s += ds;
1837  }
1838  } else {
1839  yp++;
1840  ys = yp + 1;
1841  d -= s + a2;
1842  s += ds;
1843  }
1844 
1845  t -= dt;
1846 
1847  /* Calculate alpha */
1848  if (s != 0) {
1849  cp = (float) abs(d) / (float) abs(s);
1850  if (cp > 1.0) {
1851  cp = 1.0;
1852  }
1853  } else {
1854  cp = 1.0;
1855  }
1856 
1857  /* Calculate weights */
1858  weight = (Uint8) (cp * 255);
1859  iweight = 255 - weight;
1860 
1861  /* Upper half */
1862  xx = xc2 - xp;
1863  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1864  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1865 
1866  result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
1867  result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
1868 
1869  /* Lower half */
1870  yy = yc2 - yp;
1871  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1872  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1873 
1874  yy = yc2 - ys;
1875  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
1876  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1877  }
1878 
1879  /* Replaces original approximation code dyt = abs(yp - yc); */
1880  dyt = (Sint16)lrint((double)b2 / sab ) + od;
1881 
1882  for (i = 1; i <= dyt; i++) {
1883  yp++;
1884  d -= s + a2;
1885 
1886  if (d <= 0)
1887  xs = xp + 1;
1888  else if ((d + t - b2) < 0) {
1889  if ((2 * d + t - b2) <= 0)
1890  xs = xp - 1;
1891  else {
1892  xs = xp;
1893  xp--;
1894  d += t - b2;
1895  t -= dt;
1896  }
1897  } else {
1898  xp--;
1899  xs = xp - 1;
1900  d += t - b2;
1901  t -= dt;
1902  }
1903 
1904  s += ds;
1905 
1906  /* Calculate alpha */
1907  if (t != 0) {
1908  cp = (float) abs(d) / (float) abs(t);
1909  if (cp > 1.0) {
1910  cp = 1.0;
1911  }
1912  } else {
1913  cp = 1.0;
1914  }
1915 
1916  /* Calculate weight */
1917  weight = (Uint8) (cp * 255);
1918  iweight = 255 - weight;
1919 
1920  /* Left half */
1921  xx = xc2 - xp;
1922  yy = yc2 - yp;
1923  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1924  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1925 
1926  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1927  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1928 
1929  /* Right half */
1930  xx = xc2 - xs;
1931  result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
1932  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
1933 
1934  result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
1935  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1936  }
1937 
1938  return (result);
1939 }
1940 
1941 /* ---- Filled Ellipse */
1942 
1955 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1956 {
1957  Uint8 *c = (Uint8 *)&color;
1958  return filledEllipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1959 }
1960 
1976 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1977 {
1978  int result;
1979  int ix, iy;
1980  int h, i, j, k;
1981  int oh, oi, oj, ok;
1982  int xmh, xph;
1983  int xmi, xpi;
1984  int xmj, xpj;
1985  int xmk, xpk;
1986 
1987  /*
1988  * Sanity check radii
1989  */
1990  if ((rx < 0) || (ry < 0)) {
1991  return (-1);
1992  }
1993 
1994  /*
1995  * Special case for rx=0 - draw a vline
1996  */
1997  if (rx == 0) {
1998  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1999  }
2000  /*
2001  * Special case for ry=0 - draw a hline
2002  */
2003  if (ry == 0) {
2004  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
2005  }
2006 
2007  /*
2008  * Set color
2009  */
2010  result = 0;
2011  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2012  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2013 
2014  /*
2015  * Init vars
2016  */
2017  oh = oi = oj = ok = 0xFFFF;
2018 
2019  /*
2020  * Draw
2021  */
2022  if (rx > ry) {
2023  ix = 0;
2024  iy = rx * 64;
2025 
2026  do {
2027  h = (ix + 32) >> 6;
2028  i = (iy + 32) >> 6;
2029  j = (h * ry) / rx;
2030  k = (i * ry) / rx;
2031 
2032  if ((ok != k) && (oj != k)) {
2033  xph = x + h;
2034  xmh = x - h;
2035  if (k > 0) {
2036  result |= hline(renderer, xmh, xph, y + k);
2037  result |= hline(renderer, xmh, xph, y - k);
2038  } else {
2039  result |= hline(renderer, xmh, xph, y);
2040  }
2041  ok = k;
2042  }
2043  if ((oj != j) && (ok != j) && (k != j)) {
2044  xmi = x - i;
2045  xpi = x + i;
2046  if (j > 0) {
2047  result |= hline(renderer, xmi, xpi, y + j);
2048  result |= hline(renderer, xmi, xpi, y - j);
2049  } else {
2050  result |= hline(renderer, xmi, xpi, y);
2051  }
2052  oj = j;
2053  }
2054 
2055  ix = ix + iy / rx;
2056  iy = iy - ix / rx;
2057 
2058  } while (i > h);
2059  } else {
2060  ix = 0;
2061  iy = ry * 64;
2062 
2063  do {
2064  h = (ix + 32) >> 6;
2065  i = (iy + 32) >> 6;
2066  j = (h * rx) / ry;
2067  k = (i * rx) / ry;
2068 
2069  if ((oi != i) && (oh != i)) {
2070  xmj = x - j;
2071  xpj = x + j;
2072  if (i > 0) {
2073  result |= hline(renderer, xmj, xpj, y + i);
2074  result |= hline(renderer, xmj, xpj, y - i);
2075  } else {
2076  result |= hline(renderer, xmj, xpj, y);
2077  }
2078  oi = i;
2079  }
2080  if ((oh != h) && (oi != h) && (i != h)) {
2081  xmk = x - k;
2082  xpk = x + k;
2083  if (h > 0) {
2084  result |= hline(renderer, xmk, xpk, y + h);
2085  result |= hline(renderer, xmk, xpk, y - h);
2086  } else {
2087  result |= hline(renderer, xmk, xpk, y);
2088  }
2089  oh = h;
2090  }
2091 
2092  ix = ix + iy / ry;
2093  iy = iy - ix / ry;
2094 
2095  } while (i > h);
2096  }
2097 
2098  return (result);
2099 }
2100 
2101 /* ----- Pie */
2102 
2122 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)
2123 {
2124  int result;
2125  double angle, start_angle, end_angle;
2126  double deltaAngle;
2127  double dr;
2128  int numpoints, i;
2129  Sint16 *vx, *vy;
2130 
2131  /*
2132  * Sanity check radii
2133  */
2134  if (rad < 0) {
2135  return (-1);
2136  }
2137 
2138  /*
2139  * Fixup angles
2140  */
2141  start = start % 360;
2142  end = end % 360;
2143 
2144  /*
2145  * Special case for rad=0 - draw a point
2146  */
2147  if (rad == 0) {
2148  return (pixelRGBA(renderer, x, y, r, g, b, a));
2149  }
2150 
2151  /*
2152  * Variable setup
2153  */
2154  dr = (double) rad;
2155  deltaAngle = 3.0 / dr;
2156  start_angle = (double) start *(2.0 * M_PI / 360.0);
2157  end_angle = (double) end *(2.0 * M_PI / 360.0);
2158  if (start > end) {
2159  end_angle += (2.0 * M_PI);
2160  }
2161 
2162  /* We will always have at least 2 points */
2163  numpoints = 2;
2164 
2165  /* Count points (rather than calculating it) */
2166  angle = start_angle;
2167  while (angle < end_angle) {
2168  angle += deltaAngle;
2169  numpoints++;
2170  }
2171 
2172  /* Allocate combined vertex array */
2173  vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
2174  if (vx == NULL) {
2175  return (-1);
2176  }
2177 
2178  /* Update point to start of vy */
2179  vy += numpoints;
2180 
2181  /* Center */
2182  vx[0] = x;
2183  vy[0] = y;
2184 
2185  /* First vertex */
2186  angle = start_angle;
2187  vx[1] = x + (int) (dr * cos(angle));
2188  vy[1] = y + (int) (dr * sin(angle));
2189 
2190  if (numpoints<3)
2191  {
2192  result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
2193  }
2194  else
2195  {
2196  /* Calculate other vertices */
2197  i = 2;
2198  angle = start_angle;
2199  while (angle < end_angle) {
2200  angle += deltaAngle;
2201  if (angle>end_angle)
2202  {
2203  angle = end_angle;
2204  }
2205  vx[i] = x + (int) (dr * cos(angle));
2206  vy[i] = y + (int) (dr * sin(angle));
2207  i++;
2208  }
2209 
2210  /* Draw */
2211  if (filled) {
2212  result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2213  } else {
2214  result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2215  }
2216  }
2217 
2218  /* Free combined vertex array */
2219  free(vx);
2220 
2221  return (result);
2222 }
2223 
2237 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2238  Sint16 start, Sint16 end, Uint32 color)
2239 {
2240  Uint8 *c = (Uint8 *)&color;
2241  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
2242 }
2243 
2260 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2261  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2262 {
2263  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
2264 }
2265 
2279 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
2280 {
2281  Uint8 *c = (Uint8 *)&color;
2282  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
2283 }
2284 
2301 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2302  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2303 {
2304  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
2305 }
2306 
2307 /* ------ Trigon */
2308 
2325 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2326 {
2327  Sint16 vx[3];
2328  Sint16 vy[3];
2329 
2330  vx[0]=x1;
2331  vx[1]=x2;
2332  vx[2]=x3;
2333  vy[0]=y1;
2334  vy[1]=y2;
2335  vy[2]=y3;
2336 
2337  return(polygonColor(renderer,vx,vy,3,color));
2338 }
2339 
2357 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2358  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2359 {
2360  Sint16 vx[3];
2361  Sint16 vy[3];
2362 
2363  vx[0]=x1;
2364  vx[1]=x2;
2365  vx[2]=x3;
2366  vy[0]=y1;
2367  vy[1]=y2;
2368  vy[2]=y3;
2369 
2370  return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
2371 }
2372 
2373 /* ------ AA-Trigon */
2374 
2391 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2392 {
2393  Sint16 vx[3];
2394  Sint16 vy[3];
2395 
2396  vx[0]=x1;
2397  vx[1]=x2;
2398  vx[2]=x3;
2399  vy[0]=y1;
2400  vy[1]=y2;
2401  vy[2]=y3;
2402 
2403  return(aapolygonColor(renderer,vx,vy,3,color));
2404 }
2405 
2423 int aatrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2424  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2425 {
2426  Sint16 vx[3];
2427  Sint16 vy[3];
2428 
2429  vx[0]=x1;
2430  vx[1]=x2;
2431  vx[2]=x3;
2432  vy[0]=y1;
2433  vy[1]=y2;
2434  vy[2]=y3;
2435 
2436  return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2437 }
2438 
2439 /* ------ Filled Trigon */
2440 
2457 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2458 {
2459  Sint16 vx[3];
2460  Sint16 vy[3];
2461 
2462  vx[0]=x1;
2463  vx[1]=x2;
2464  vx[2]=x3;
2465  vy[0]=y1;
2466  vy[1]=y2;
2467  vy[2]=y3;
2468 
2469  return(filledPolygonColor(renderer,vx,vy,3,color));
2470 }
2471 
2491 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2492  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2493 {
2494  Sint16 vx[3];
2495  Sint16 vy[3];
2496 
2497  vx[0]=x1;
2498  vx[1]=x2;
2499  vx[2]=x3;
2500  vy[0]=y1;
2501  vy[1]=y2;
2502  vy[2]=y3;
2503 
2504  return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2505 }
2506 
2507 /* ---- Polygon */
2508 
2520 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2521 {
2522  Uint8 *c = (Uint8 *)&color;
2523  return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2524 }
2525 
2536 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
2537 {
2538  /*
2539  * Draw
2540  */
2541  int result;
2542  int i, nn;
2543  SDL_Point* points;
2544 
2545  /*
2546  * Vertex array NULL check
2547  */
2548  if (vx == NULL) {
2549  return (-1);
2550  }
2551  if (vy == NULL) {
2552  return (-1);
2553  }
2554 
2555  /*
2556  * Sanity check
2557  */
2558  if (n < 3) {
2559  return (-1);
2560  }
2561 
2562  /*
2563  * Create array of points
2564  */
2565  nn = n + 1;
2566  points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
2567  if (points == NULL)
2568  {
2569  return -1;
2570  }
2571  for (i=0; i<n; i++)
2572  {
2573  points[i].x = vx[i];
2574  points[i].y = vy[i];
2575  }
2576  points[n].x = vx[0];
2577  points[n].y = vy[0];
2578 
2579  /*
2580  * Draw
2581  */
2582  result |= SDL_RenderDrawLines(renderer, points, nn);
2583  free(points);
2584 
2585  return (result);
2586 }
2587 
2602 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2603 {
2604  /*
2605  * Draw
2606  */
2607  int result;
2608  const Sint16 *x1, *y1, *x2, *y2;
2609 
2610  /*
2611  * Vertex array NULL check
2612  */
2613  if (vx == NULL) {
2614  return (-1);
2615  }
2616  if (vy == NULL) {
2617  return (-1);
2618  }
2619 
2620  /*
2621  * Sanity check
2622  */
2623  if (n < 3) {
2624  return (-1);
2625  }
2626 
2627  /*
2628  * Pointer setup
2629  */
2630  x1 = x2 = vx;
2631  y1 = y2 = vy;
2632  x2++;
2633  y2++;
2634 
2635  /*
2636  * Set color
2637  */
2638  result = 0;
2639  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2640  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2641 
2642  /*
2643  * Draw
2644  */
2645  result |= polygon(renderer, vx, vy, n);
2646 
2647  return (result);
2648 }
2649 
2650 /* ---- AA-Polygon */
2651 
2663 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2664 {
2665  Uint8 *c = (Uint8 *)&color;
2666  return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2667 }
2668 
2683 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2684 {
2685  int result;
2686  int i;
2687  const Sint16 *x1, *y1, *x2, *y2;
2688 
2689  /*
2690  * Vertex array NULL check
2691  */
2692  if (vx == NULL) {
2693  return (-1);
2694  }
2695  if (vy == NULL) {
2696  return (-1);
2697  }
2698 
2699  /*
2700  * Sanity check
2701  */
2702  if (n < 3) {
2703  return (-1);
2704  }
2705 
2706  /*
2707  * Pointer setup
2708  */
2709  x1 = x2 = vx;
2710  y1 = y2 = vy;
2711  x2++;
2712  y2++;
2713 
2714  /*
2715  * Draw
2716  */
2717  result = 0;
2718  for (i = 1; i < n; i++) {
2719  result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
2720  x1 = x2;
2721  y1 = y2;
2722  x2++;
2723  y2++;
2724  }
2725 
2726  result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
2727 
2728  return (result);
2729 }
2730 
2731 /* ---- Filled Polygon */
2732 
2741 int _gfxPrimitivesCompareInt(const void *a, const void *b)
2742 {
2743  return (*(const int *) a) - (*(const int *) b);
2744 }
2745 
2751 static int *gfxPrimitivesPolyIntsGlobal = NULL;
2752 
2758 static int gfxPrimitivesPolyAllocatedGlobal = 0;
2759 
2778 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)
2779 {
2780  int result;
2781  int i;
2782  int y, xa, xb;
2783  int miny, maxy;
2784  int x1, y1;
2785  int x2, y2;
2786  int ind1, ind2;
2787  int ints;
2788  int *gfxPrimitivesPolyInts = NULL;
2789  int *gfxPrimitivesPolyIntsNew = NULL;
2790  int gfxPrimitivesPolyAllocated = 0;
2791 
2792  /*
2793  * Vertex array NULL check
2794  */
2795  if (vx == NULL) {
2796  return (-1);
2797  }
2798  if (vy == NULL) {
2799  return (-1);
2800  }
2801 
2802  /*
2803  * Sanity check number of edges
2804  */
2805  if (n < 3) {
2806  return -1;
2807  }
2808 
2809  /*
2810  * Map polygon cache
2811  */
2812  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2813  /* Use global cache */
2814  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
2815  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
2816  } else {
2817  /* Use local cache */
2818  gfxPrimitivesPolyInts = *polyInts;
2819  gfxPrimitivesPolyAllocated = *polyAllocated;
2820  }
2821 
2822  /*
2823  * Allocate temp array, only grow array
2824  */
2825  if (!gfxPrimitivesPolyAllocated) {
2826  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
2827  gfxPrimitivesPolyAllocated = n;
2828  } else {
2829  if (gfxPrimitivesPolyAllocated < n) {
2830  gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
2831  if (!gfxPrimitivesPolyIntsNew) {
2832  if (!gfxPrimitivesPolyInts) {
2833  free(gfxPrimitivesPolyInts);
2834  gfxPrimitivesPolyInts = NULL;
2835  }
2836  gfxPrimitivesPolyAllocated = 0;
2837  } else {
2838  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
2839  gfxPrimitivesPolyAllocated = n;
2840  }
2841  }
2842  }
2843 
2844  /*
2845  * Check temp array
2846  */
2847  if (gfxPrimitivesPolyInts==NULL) {
2848  gfxPrimitivesPolyAllocated = 0;
2849  }
2850 
2851  /*
2852  * Update cache variables
2853  */
2854  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2855  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
2856  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
2857  } else {
2858  *polyInts = gfxPrimitivesPolyInts;
2859  *polyAllocated = gfxPrimitivesPolyAllocated;
2860  }
2861 
2862  /*
2863  * Check temp array again
2864  */
2865  if (gfxPrimitivesPolyInts==NULL) {
2866  return(-1);
2867  }
2868 
2869  /*
2870  * Determine Y maxima
2871  */
2872  miny = vy[0];
2873  maxy = vy[0];
2874  for (i = 1; (i < n); i++) {
2875  if (vy[i] < miny) {
2876  miny = vy[i];
2877  } else if (vy[i] > maxy) {
2878  maxy = vy[i];
2879  }
2880  }
2881 
2882  /*
2883  * Draw, scanning y
2884  */
2885  result = 0;
2886  for (y = miny; (y <= maxy); y++) {
2887  ints = 0;
2888  for (i = 0; (i < n); i++) {
2889  if (!i) {
2890  ind1 = n - 1;
2891  ind2 = 0;
2892  } else {
2893  ind1 = i - 1;
2894  ind2 = i;
2895  }
2896  y1 = vy[ind1];
2897  y2 = vy[ind2];
2898  if (y1 < y2) {
2899  x1 = vx[ind1];
2900  x2 = vx[ind2];
2901  } else if (y1 > y2) {
2902  y2 = vy[ind1];
2903  y1 = vy[ind2];
2904  x2 = vx[ind1];
2905  x1 = vx[ind2];
2906  } else {
2907  continue;
2908  }
2909  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
2910  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
2911  }
2912  }
2913 
2914  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
2915 
2916  /*
2917  * Set color
2918  */
2919  result = 0;
2920  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2921  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2922 
2923  for (i = 0; (i < ints); i += 2) {
2924  xa = gfxPrimitivesPolyInts[i] + 1;
2925  xa = (xa >> 16) + ((xa & 32768) >> 15);
2926  xb = gfxPrimitivesPolyInts[i+1] - 1;
2927  xb = (xb >> 16) + ((xb & 32768) >> 15);
2928  result |= hline(renderer, xa, xb, y);
2929  }
2930  }
2931 
2932  return (result);
2933 }
2934 
2946 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2947 {
2948  Uint8 *c = (Uint8 *)&color;
2949  return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
2950 }
2951 
2966 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2967 {
2968  return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
2969 }
2970 
2971 /* ---- Textured Polygon */
2972 
2988 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)
2989 {
2990  Sint16 w;
2991  Sint16 xtmp;
2992  int result = 0;
2993  int texture_x_walker;
2994  int texture_y_start;
2995  SDL_Rect source_rect,dst_rect;
2996  int pixels_written,write_width;
2997 
2998  /*
2999  * Swap x1, x2 if required to ensure x1<=x2
3000  */
3001  if (x1 > x2) {
3002  xtmp = x1;
3003  x1 = x2;
3004  x2 = xtmp;
3005  }
3006 
3007  /*
3008  * Calculate width to draw
3009  */
3010  w = x2 - x1 + 1;
3011 
3012  /*
3013  * Determine where in the texture we start drawing
3014  */
3015  texture_x_walker = (x1 - texture_dx) % texture_w;
3016  if (texture_x_walker < 0){
3017  texture_x_walker = texture_w + texture_x_walker ;
3018  }
3019 
3020  texture_y_start = (y + texture_dy) % texture_h;
3021  if (texture_y_start < 0){
3022  texture_y_start = texture_h + texture_y_start;
3023  }
3024 
3025  // setup the source rectangle; we are only drawing one horizontal line
3026  source_rect.y = texture_y_start;
3027  source_rect.x = texture_x_walker;
3028  source_rect.h = 1;
3029 
3030  // we will draw to the current y
3031  dst_rect.y = y;
3032 
3033  // if there are enough pixels left in the current row of the texture
3034  // draw it all at once
3035  if (w <= texture_w -texture_x_walker){
3036  source_rect.w = w;
3037  source_rect.x = texture_x_walker;
3038  dst_rect.x= x1;
3039  result = (SDL_RenderCopy(renderer, texture, &source_rect ,&dst_rect) == 0);
3040  } else { // we need to draw multiple times
3041  // draw the first segment
3042  pixels_written = texture_w - texture_x_walker;
3043  source_rect.w = pixels_written;
3044  source_rect.x = texture_x_walker;
3045  dst_rect.x= x1;
3046  result |= (SDL_RenderCopy(renderer, texture, &source_rect , &dst_rect) == 0);
3047  write_width = texture_w;
3048 
3049  // now draw the rest
3050  // set the source x to 0
3051  source_rect.x = 0;
3052  while (pixels_written < w){
3053  if (write_width >= w - pixels_written) {
3054  write_width = w - pixels_written;
3055  }
3056  source_rect.w = write_width;
3057  dst_rect.x = x1 + pixels_written;
3058  result |= (SDL_RenderCopy(renderer,texture,&source_rect , &dst_rect) == 0);
3059  pixels_written += write_width;
3060  }
3061  }
3062 
3063  return result;
3064 }
3065 
3082 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
3083  SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
3084 {
3085  int result;
3086  int i;
3087  int y, xa, xb;
3088  int minx,maxx,miny, maxy;
3089  int x1, y1;
3090  int x2, y2;
3091  int ind1, ind2;
3092  int ints;
3093  int *gfxPrimitivesPolyInts = NULL;
3094  int gfxPrimitivesPolyAllocated = 0;
3095  SDL_Texture *textureAsTexture;
3096 
3097  /*
3098  * Sanity check number of edges
3099  */
3100  if (n < 3) {
3101  return -1;
3102  }
3103 
3104  /*
3105  * Map polygon cache
3106  */
3107  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3108  /* Use global cache */
3109  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
3110  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
3111  } else {
3112  /* Use local cache */
3113  gfxPrimitivesPolyInts = *polyInts;
3114  gfxPrimitivesPolyAllocated = *polyAllocated;
3115  }
3116 
3117  /*
3118  * Allocate temp array, only grow array
3119  */
3120  if (!gfxPrimitivesPolyAllocated) {
3121  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3122  gfxPrimitivesPolyAllocated = n;
3123  } else {
3124  if (gfxPrimitivesPolyAllocated < n) {
3125  gfxPrimitivesPolyInts = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3126  gfxPrimitivesPolyAllocated = n;
3127  }
3128  }
3129 
3130  /*
3131  * Check temp array
3132  */
3133  if (gfxPrimitivesPolyInts==NULL) {
3134  gfxPrimitivesPolyAllocated = 0;
3135  }
3136 
3137  /*
3138  * Update cache variables
3139  */
3140  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3141  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
3142  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
3143  } else {
3144  *polyInts = gfxPrimitivesPolyInts;
3145  *polyAllocated = gfxPrimitivesPolyAllocated;
3146  }
3147 
3148  /*
3149  * Check temp array again
3150  */
3151  if (gfxPrimitivesPolyInts==NULL) {
3152  return(-1);
3153  }
3154 
3155  /*
3156  * Determine X,Y minima,maxima
3157  */
3158  miny = vy[0];
3159  maxy = vy[0];
3160  minx = vx[0];
3161  maxx = vx[0];
3162  for (i = 1; (i < n); i++) {
3163  if (vy[i] < miny) {
3164  miny = vy[i];
3165  } else if (vy[i] > maxy) {
3166  maxy = vy[i];
3167  }
3168  if (vx[i] < minx) {
3169  minx = vx[i];
3170  } else if (vx[i] > maxx) {
3171  maxx = vx[i];
3172  }
3173  }
3174 
3175  /*
3176  * Draw, scanning y
3177  */
3178  result = 0;
3179  for (y = miny; (y <= maxy); y++) {
3180  ints = 0;
3181  for (i = 0; (i < n); i++) {
3182  if (!i) {
3183  ind1 = n - 1;
3184  ind2 = 0;
3185  } else {
3186  ind1 = i - 1;
3187  ind2 = i;
3188  }
3189  y1 = vy[ind1];
3190  y2 = vy[ind2];
3191  if (y1 < y2) {
3192  x1 = vx[ind1];
3193  x2 = vx[ind2];
3194  } else if (y1 > y2) {
3195  y2 = vy[ind1];
3196  y1 = vy[ind2];
3197  x2 = vx[ind1];
3198  x1 = vx[ind2];
3199  } else {
3200  continue;
3201  }
3202  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
3203  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
3204  }
3205  }
3206 
3207  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
3208 
3209  textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
3210  if (textureAsTexture == NULL)
3211  {
3212  return (-1);
3213  }
3214 
3215  for (i = 0; (i < ints); i += 2) {
3216  xa = gfxPrimitivesPolyInts[i] + 1;
3217  xa = (xa >> 16) + ((xa & 32768) >> 15);
3218  xb = gfxPrimitivesPolyInts[i+1] - 1;
3219  xb = (xb >> 16) + ((xb & 32768) >> 15);
3220  result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
3221  }
3222  SDL_DestroyTexture(textureAsTexture);
3223  }
3224 
3225  return (result);
3226 }
3227 
3244 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
3245 {
3246  /*
3247  * Draw
3248  */
3249  return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
3250 }
3251 
3252 /* ---- Character */
3253 
3257 static SDL_Texture *gfxPrimitivesFont[256];
3258 
3262 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
3263 
3267 static Uint32 charWidth = 8;
3268 
3272 static Uint32 charHeight = 8;
3273 
3277 static Uint32 charWidthLocal = 8;
3278 
3282 static Uint32 charHeightLocal = 8;
3283 
3287 static Uint32 charPitch = 1;
3288 
3292 static Uint32 charRotation = 0;
3293 
3297 static Uint32 charSize = 8;
3298 
3312 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
3313 {
3314  int i;
3315 
3316  if ((fontdata) && (cw) && (ch)) {
3317  currentFontdata = (unsigned char *)fontdata;
3318  charWidth = cw;
3319  charHeight = ch;
3320  } else {
3321  currentFontdata = gfxPrimitivesFontdata;
3322  charWidth = 8;
3323  charHeight = 8;
3324  }
3325 
3326  charPitch = (charWidth+7)/8;
3327  charSize = charPitch * charHeight;
3328 
3329  /* Maybe flip width/height for rendering */
3330  if ((charRotation==1) || (charRotation==3))
3331  {
3332  charWidthLocal = charHeight;
3333  charHeightLocal = charWidth;
3334  }
3335  else
3336  {
3337  charWidthLocal = charWidth;
3338  charHeightLocal = charHeight;
3339  }
3340 
3341  /* Clear character cache */
3342  for (i = 0; i < 256; i++) {
3343  if (gfxPrimitivesFont[i]) {
3344  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3345  gfxPrimitivesFont[i] = NULL;
3346  }
3347  }
3348 }
3349 
3358 void gfxPrimitivesSetFontRotation(Uint32 rotation)
3359 {
3360  int i;
3361 
3362  rotation = rotation & 3;
3363  if (charRotation != rotation)
3364  {
3365  /* Store rotation */
3366  charRotation = rotation;
3367 
3368  /* Maybe flip width/height for rendering */
3369  if ((charRotation==1) || (charRotation==3))
3370  {
3371  charWidthLocal = charHeight;
3372  charHeightLocal = charWidth;
3373  }
3374  else
3375  {
3376  charWidthLocal = charWidth;
3377  charHeightLocal = charHeight;
3378  }
3379 
3380  /* Clear character cache */
3381  for (i = 0; i < 256; i++) {
3382  if (gfxPrimitivesFont[i]) {
3383  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3384  gfxPrimitivesFont[i] = NULL;
3385  }
3386  }
3387  }
3388 }
3389 
3404 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3405 {
3406  SDL_Rect srect;
3407  SDL_Rect drect;
3408  int result;
3409  Uint32 ix, iy;
3410  const unsigned char *charpos;
3411  Uint8 *curpos;
3412  Uint8 patt, mask;
3413  Uint8 *linepos;
3414  Uint32 pitch;
3415  SDL_Surface *character;
3416  SDL_Surface *rotatedCharacter;
3417  Uint32 ci;
3418 
3419  /*
3420  * Setup source rectangle
3421  */
3422  srect.x = 0;
3423  srect.y = 0;
3424  srect.w = charWidthLocal;
3425  srect.h = charHeightLocal;
3426 
3427  /*
3428  * Setup destination rectangle
3429  */
3430  drect.x = x;
3431  drect.y = y;
3432  drect.w = charWidthLocal;
3433  drect.h = charHeightLocal;
3434 
3435  /* Character index in cache */
3436  ci = (unsigned char) c;
3437 
3438  /*
3439  * Create new charWidth x charHeight bitmap surface if not already present.
3440  * Might get rotated later.
3441  */
3442  if (gfxPrimitivesFont[ci] == NULL) {
3443  /*
3444  * Redraw character into surface
3445  */
3446  character = SDL_CreateRGBSurface(SDL_SWSURFACE,
3447  charWidth, charHeight, 32,
3448  0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
3449  if (character == NULL) {
3450  return (-1);
3451  }
3452 
3453  charpos = currentFontdata + ci * charSize;
3454  linepos = (Uint8 *)character->pixels;
3455  pitch = character->pitch;
3456 
3457  /*
3458  * Drawing loop
3459  */
3460  patt = 0;
3461  for (iy = 0; iy < charHeight; iy++) {
3462  mask = 0x00;
3463  curpos = linepos;
3464  for (ix = 0; ix < charWidth; ix++) {
3465  if (!(mask >>= 1)) {
3466  patt = *charpos++;
3467  mask = 0x80;
3468  }
3469  if (patt & mask) {
3470  *(Uint32 *)curpos = 0xffffffff;
3471  } else {
3472  *(Uint32 *)curpos = 0;
3473  }
3474  curpos += 4;
3475  }
3476  linepos += pitch;
3477  }
3478 
3479  /* Maybe rotate and replace cached image */
3480  if (charRotation>0)
3481  {
3482  rotatedCharacter = rotateSurface90Degrees(character, charRotation);
3483  SDL_FreeSurface(character);
3484  character = rotatedCharacter;
3485  }
3486 
3487  /* Convert temp surface into texture */
3488  gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
3489  SDL_FreeSurface(character);
3490 
3491  /*
3492  * Check pointer
3493  */
3494  if (gfxPrimitivesFont[ci] == NULL) {
3495  return (-1);
3496  }
3497  }
3498 
3499  /*
3500  * Set color
3501  */
3502  result = 0;
3503  result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
3504  result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
3505 
3506  /*
3507  * Draw texture onto destination
3508  */
3509  result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
3510 
3511  return (result);
3512 }
3513 
3514 
3526 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
3527 {
3528  Uint8 *co = (Uint8 *)&color;
3529  return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
3530 }
3531 
3532 
3547 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
3548 {
3549  Uint8 *c = (Uint8 *)&color;
3550  return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
3551 }
3552 
3567 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3568 {
3569  int result = 0;
3570  Sint16 curx = x;
3571  Sint16 cury = y;
3572  const char *curchar = s;
3573 
3574  while (*curchar && !result) {
3575  result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
3576  switch (charRotation)
3577  {
3578  case 0:
3579  curx += charWidthLocal;
3580  break;
3581  case 2:
3582  curx -= charWidthLocal;
3583  break;
3584  case 1:
3585  cury += charHeightLocal;
3586  break;
3587  case 3:
3588  cury -= charHeightLocal;
3589  break;
3590  }
3591  curchar++;
3592  }
3593 
3594  return (result);
3595 }
3596 
3597 /* ---- Bezier curve */
3598 
3608 double _evaluateBezier (double *data, int ndata, double t)
3609 {
3610  double mu, result;
3611  int n,k,kn,nn,nkn;
3612  double blend,muk,munk;
3613 
3614  /* Sanity check bounds */
3615  if (t<0.0) {
3616  return(data[0]);
3617  }
3618  if (t>=(double)ndata) {
3619  return(data[ndata-1]);
3620  }
3621 
3622  /* Adjust t to the range 0.0 to 1.0 */
3623  mu=t/(double)ndata;
3624 
3625  /* Calculate interpolate */
3626  n=ndata-1;
3627  result=0.0;
3628  muk = 1;
3629  munk = pow(1-mu,(double)n);
3630  for (k=0;k<=n;k++) {
3631  nn = n;
3632  kn = k;
3633  nkn = n - k;
3634  blend = muk * munk;
3635  muk *= mu;
3636  munk /= (1-mu);
3637  while (nn >= 1) {
3638  blend *= nn;
3639  nn--;
3640  if (kn > 1) {
3641  blend /= (double)kn;
3642  kn--;
3643  }
3644  if (nkn > 1) {
3645  blend /= (double)nkn;
3646  nkn--;
3647  }
3648  }
3649  result += data[k] * blend;
3650  }
3651 
3652  return (result);
3653 }
3654 
3667 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
3668 {
3669  Uint8 *c = (Uint8 *)&color;
3670  return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
3671 }
3672 
3688 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3689 {
3690  int result;
3691  int i;
3692  double *x, *y, t, stepsize;
3693  Sint16 x1, y1, x2, y2;
3694 
3695  /*
3696  * Sanity check
3697  */
3698  if (n < 3) {
3699  return (-1);
3700  }
3701  if (s < 2) {
3702  return (-1);
3703  }
3704 
3705  /*
3706  * Variable setup
3707  */
3708  stepsize=(double)1.0/(double)s;
3709 
3710  /* Transfer vertices into float arrays */
3711  if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3712  return(-1);
3713  }
3714  if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3715  free(x);
3716  return(-1);
3717  }
3718  for (i=0; i<n; i++) {
3719  x[i]=(double)vx[i];
3720  y[i]=(double)vy[i];
3721  }
3722  x[n]=(double)vx[0];
3723  y[n]=(double)vy[0];
3724 
3725  /*
3726  * Set color
3727  */
3728  result = 0;
3729  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
3730  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
3731 
3732  /*
3733  * Draw
3734  */
3735  t=0.0;
3736  x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
3737  y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
3738  for (i = 0; i <= (n*s); i++) {
3739  t += stepsize;
3740  x2=(Sint16)_evaluateBezier(x,n,t);
3741  y2=(Sint16)_evaluateBezier(y,n,t);
3742  result |= line(renderer, x1, y1, x2, y2);
3743  x1 = x2;
3744  y1 = y2;
3745  }
3746 
3747  /* Clean up temporary array */
3748  free(x);
3749  free(y);
3750 
3751  return (result);
3752 }
3753 
3754 
3755 /* ---- Thick Line */
3756 
3775 int _bresenhamInitialize(SDL2_gfxBresenhamIterator *b, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
3776 {
3777  int temp;
3778 
3779  if (b==NULL) {
3780  return(-1);
3781  }
3782 
3783  b->x = x1;
3784  b->y = y1;
3785 
3786  /* dx = abs(x2-x1), s1 = sign(x2-x1) */
3787  if ((b->dx = x2 - x1) != 0) {
3788  if (b->dx < 0) {
3789  b->dx = -b->dx;
3790  b->s1 = -1;
3791  } else {
3792  b->s1 = 1;
3793  }
3794  } else {
3795  b->s1 = 0;
3796  }
3797 
3798  /* dy = abs(y2-y1), s2 = sign(y2-y1) */
3799  if ((b->dy = y2 - y1) != 0) {
3800  if (b->dy < 0) {
3801  b->dy = -b->dy;
3802  b->s2 = -1;
3803  } else {
3804  b->s2 = 1;
3805  }
3806  } else {
3807  b->s2 = 0;
3808  }
3809 
3810  if (b->dy > b->dx) {
3811  temp = b->dx;
3812  b->dx = b->dy;
3813  b->dy = temp;
3814  b->swapdir = 1;
3815  } else {
3816  b->swapdir = 0;
3817  }
3818 
3819  b->count = (b->dx<0) ? 0 : (unsigned int)b->dx;
3820  b->dy <<= 1;
3821  b->error = b->dy - b->dx;
3822  b->dx <<= 1;
3823 
3824  return(0);
3825 }
3826 
3827 
3838 {
3839  if (b==NULL) {
3840  return (-1);
3841  }
3842 
3843  /* last point check */
3844  if (b->count==0) {
3845  return (2);
3846  }
3847 
3848  while (b->error >= 0) {
3849  if (b->swapdir) {
3850  b->x += b->s1;
3851  } else {
3852  b->y += b->s2;
3853  }
3854 
3855  b->error -= b->dx;
3856  }
3857 
3858  if (b->swapdir) {
3859  b->y += b->s2;
3860  } else {
3861  b->x += b->s1;
3862  }
3863 
3864  b->error += b->dy;
3865  b->count--;
3866 
3867  /* count==0 indicates "end-of-line" */
3868  return ((b->count) ? 0 : 1);
3869 }
3870 
3871 
3880 void _murphyParaline(SDL2_gfxMurphyIterator *m, Sint16 x, Sint16 y, int d1)
3881 {
3882  int p;
3883  d1 = -d1;
3884 
3885  for (p = 0; p <= m->u; p++) {
3886 
3887  pixel(m->renderer, x, y);
3888 
3889  if (d1 <= m->kt) {
3890  if (m->oct2 == 0) {
3891  x++;
3892  } else {
3893  if (m->quad4 == 0) {
3894  y++;
3895  } else {
3896  y--;
3897  }
3898  }
3899  d1 += m->kv;
3900  } else {
3901  x++;
3902  if (m->quad4 == 0) {
3903  y++;
3904  } else {
3905  y--;
3906  }
3907  d1 += m->kd;
3908  }
3909  }
3910 
3911  m->tempx = x;
3912  m->tempy = y;
3913 }
3914 
3931  Uint16 ml1bx, Uint16 ml1by, Uint16 ml2bx, Uint16 ml2by,
3932  Uint16 ml1x, Uint16 ml1y, Uint16 ml2x, Uint16 ml2y)
3933 {
3934  int atemp1, atemp2;
3935  int ftmp1, ftmp2;
3936  Uint16 m1x, m1y, m2x, m2y;
3937  Uint16 fix, fiy, lax, lay, curx, cury;
3938  Sint16 px[4], py[4];
3940 
3941  if (miter > 1) {
3942  if (m->first1x != -32768) {
3943  fix = (m->first1x + m->first2x) / 2;
3944  fiy = (m->first1y + m->first2y) / 2;
3945  lax = (m->last1x + m->last2x) / 2;
3946  lay = (m->last1y + m->last2y) / 2;
3947  curx = (ml1x + ml2x) / 2;
3948  cury = (ml1y + ml2y) / 2;
3949 
3950  atemp1 = (fix - curx);
3951  atemp2 = (fiy - cury);
3952  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
3953  atemp1 = (lax - curx);
3954  atemp2 = (lay - cury);
3955  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
3956 
3957  if (ftmp1 <= ftmp2) {
3958  m1x = m->first1x;
3959  m1y = m->first1y;
3960  m2x = m->first2x;
3961  m2y = m->first2y;
3962  } else {
3963  m1x = m->last1x;
3964  m1y = m->last1y;
3965  m2x = m->last2x;
3966  m2y = m->last2y;
3967  }
3968 
3969  atemp1 = (m2x - ml2x);
3970  atemp2 = (m2y - ml2y);
3971  ftmp1 = atemp1 * atemp1 + atemp2 * atemp2;
3972  atemp1 = (m2x - ml2bx);
3973  atemp2 = (m2y - ml2by);
3974  ftmp2 = atemp1 * atemp1 + atemp2 * atemp2;
3975 
3976  if (ftmp2 >= ftmp1) {
3977  ftmp1 = ml2bx;
3978  ftmp2 = ml2by;
3979  ml2bx = ml2x;
3980  ml2by = ml2y;
3981  ml2x = ftmp1;
3982  ml2y = ftmp2;
3983  ftmp1 = ml1bx;
3984  ftmp2 = ml1by;
3985  ml1bx = ml1x;
3986  ml1by = ml1y;
3987  ml1x = ftmp1;
3988  ml1y = ftmp2;
3989  }
3990 
3991  /*
3992  * Lock the surface
3993  */
3994  _bresenhamInitialize(&b, m2x, m2y, m1x, m1y);
3995  do {
3996  pixel(m->renderer, b.x, b.y);
3997  } while (_bresenhamIterate(&b)==0);
3998 
3999  _bresenhamInitialize(&b, m1x, m1y, ml1bx, ml1by);
4000  do {
4001  pixel(m->renderer, b.x, b.y);
4002  } while (_bresenhamIterate(&b)==0);
4003 
4004  _bresenhamInitialize(&b, ml1bx, ml1by, ml2bx, ml2by);
4005  do {
4006  pixel(m->renderer, b.x, b.y);
4007  } while (_bresenhamIterate(&b)==0);
4008 
4009  _bresenhamInitialize(&b, ml2bx, ml2by, m2x, m2y);
4010  do {
4011  pixel(m->renderer, b.x, b.y);
4012  } while (_bresenhamIterate(&b)==0);
4013 
4014  px[0] = m1x;
4015  px[1] = m2x;
4016  px[2] = ml1bx;
4017  px[3] = ml2bx;
4018  py[0] = m1y;
4019  py[1] = m2y;
4020  py[2] = ml1by;
4021  py[3] = ml2by;
4022  polygon(m->renderer, px, py, 4);
4023  }
4024  }
4025 
4026  m->last1x = ml1x;
4027  m->last1y = ml1y;
4028  m->last2x = ml2x;
4029  m->last2y = ml2y;
4030  m->first1x = ml1bx;
4031  m->first1y = ml1by;
4032  m->first2x = ml2bx;
4033  m->first2y = ml2by;
4034 }
4035 
4036 
4037 #define HYPOT(x,y) sqrt((double)(x)*(double)(x)+(double)(y)*(double)(y))
4038 
4053 void _murphyWideline(SDL2_gfxMurphyIterator *m, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 miter)
4054 {
4055  float offset = (float)width / 2.f;
4056 
4057  Sint16 temp;
4058  Sint16 ptx, pty, ptxx, ptxy, ml1x, ml1y, ml2x, ml2y, ml1bx, ml1by, ml2bx, ml2by;
4059 
4060  int d0, d1; /* difference terms d0=perpendicular to line, d1=along line */
4061 
4062  int q; /* pel counter,q=perpendicular to line */
4063  int tmp;
4064 
4065  int dd; /* distance along line */
4066  int tk; /* thickness threshold */
4067  double ang; /* angle for initial point calculation */
4068  double sang, cang;
4069 
4070  /* Initialisation */
4071  m->u = x2 - x1; /* delta x */
4072  m->v = y2 - y1; /* delta y */
4073 
4074  if (m->u < 0) { /* swap to make sure we are in quadrants 1 or 4 */
4075  temp = x1;
4076  x1 = x2;
4077  x2 = temp;
4078  temp = y1;
4079  y1 = y2;
4080  y2 = temp;
4081  m->u *= -1;
4082  m->v *= -1;
4083  }
4084 
4085  if (m->v < 0) { /* swap to 1st quadrant and flag */
4086  m->v *= -1;
4087  m->quad4 = 1;
4088  } else {
4089  m->quad4 = 0;
4090  }
4091 
4092  if (m->v > m->u) { /* swap things if in 2 octant */
4093  tmp = m->u;
4094  m->u = m->v;
4095  m->v = tmp;
4096  m->oct2 = 1;
4097  } else {
4098  m->oct2 = 0;
4099  }
4100 
4101  m->ku = m->u + m->u; /* change in l for square shift */
4102  m->kv = m->v + m->v; /* change in d for square shift */
4103  m->kd = m->kv - m->ku; /* change in d for diagonal shift */
4104  m->kt = m->u - m->kv; /* diag/square decision threshold */
4105 
4106  d0 = 0;
4107  d1 = 0;
4108  dd = 0;
4109 
4110  ang = atan((double) m->v / (double) m->u); /* calc new initial point - offset both sides of ideal */
4111  sang = sin(ang);
4112  cang = cos(ang);
4113 
4114  if (m->oct2 == 0) {
4115  ptx = x1 + (Sint16)lrint(offset * sang);
4116  if (m->quad4 == 0) {
4117  pty = y1 - (Sint16)lrint(offset * cang);
4118  } else {
4119  pty = y1 + (Sint16)lrint(offset * cang);
4120  }
4121  } else {
4122  ptx = x1 - (Sint16)lrint(offset * cang);
4123  if (m->quad4 == 0) {
4124  pty = y1 + (Sint16)lrint(offset * sang);
4125  } else {
4126  pty = y1 - (Sint16)lrint(offset * sang);
4127  }
4128  }
4129 
4130  /* used here for constant thickness line */
4131  tk = (int) (4. * HYPOT(ptx - x1, pty - y1) * HYPOT(m->u, m->v));
4132 
4133  if (miter == 0) {
4134  m->first1x = -32768;
4135  m->first1y = -32768;
4136  m->first2x = -32768;
4137  m->first2y = -32768;
4138  m->last1x = -32768;
4139  m->last1y = -32768;
4140  m->last2x = -32768;
4141  m->last2y = -32768;
4142  }
4143  ptxx = ptx;
4144  ptxy = pty;
4145 
4146  for (q = 0; dd <= tk; q++) { /* outer loop, stepping perpendicular to line */
4147 
4148  _murphyParaline(m, ptx, pty, d1); /* call to inner loop - right edge */
4149  if (q == 0) {
4150  ml1x = ptx;
4151  ml1y = pty;
4152  ml1bx = m->tempx;
4153  ml1by = m->tempy;
4154  } else {
4155  ml2x = ptx;
4156  ml2y = pty;
4157  ml2bx = m->tempx;
4158  ml2by = m->tempy;
4159  }
4160  if (d0 < m->kt) { /* square move */
4161  if (m->oct2 == 0) {
4162  if (m->quad4 == 0) {
4163  pty++;
4164  } else {
4165  pty--;
4166  }
4167  } else {
4168  ptx++;
4169  }
4170  } else { /* diagonal move */
4171  dd += m->kv;
4172  d0 -= m->ku;
4173  if (d1 < m->kt) { /* normal diagonal */
4174  if (m->oct2 == 0) {
4175  ptx--;
4176  if (m->quad4 == 0) {
4177  pty++;
4178  } else {
4179  pty--;
4180  }
4181  } else {
4182  ptx++;
4183  if (m->quad4 == 0) {
4184  pty--;
4185  } else {
4186  pty++;
4187  }
4188  }
4189  d1 += m->kv;
4190  } else { /* double square move, extra parallel line */
4191  if (m->oct2 == 0) {
4192  ptx--;
4193  } else {
4194  if (m->quad4 == 0) {
4195  pty--;
4196  } else {
4197  pty++;
4198  }
4199  }
4200  d1 += m->kd;
4201  if (dd > tk) {
4202  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
4203  return; /* breakout on the extra line */
4204  }
4205  _murphyParaline(m, ptx, pty, d1);
4206  if (m->oct2 == 0) {
4207  if (m->quad4 == 0) {
4208  pty++;
4209  } else {
4210 
4211  pty--;
4212  }
4213  } else {
4214  ptx++;
4215  }
4216  }
4217  }
4218  dd += m->ku;
4219  d0 += m->kv;
4220  }
4221 
4222  _murphyIteration(m, miter, ml1bx, ml1by, ml2bx, ml2by, ml1x, ml1y, ml2x, ml2y);
4223 }
4224 
4225 
4239 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
4240 {
4241  Uint8 *c = (Uint8 *)&color;
4242  return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
4243 }
4244 
4261 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
4262 {
4263  int result;
4264  int wh;
4266 
4267  if (renderer == NULL) {
4268  return -1;
4269  }
4270  if (width < 1) {
4271  return -1;
4272  }
4273 
4274  /* Special case: thick "point" */
4275  if ((x1 == x2) && (y1 == y2)) {
4276  wh = width / 2;
4277  return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
4278  }
4279 
4280  /*
4281  * Set color
4282  */
4283  result = 0;
4284  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
4285  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
4286 
4287  /*
4288  * Draw
4289  */
4290  m.renderer = renderer;
4291  _murphyWideline(&m, x1, y1, x2, y2, width, 0);
4292  _murphyWideline(&m, x1, y1, x2, y2, width, 1);
4293 
4294  return(0);
4295 }
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 't'...
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.