SDL2_gfx  1.0.2
GraphicsprimitivesandsurfacefunctionsforSDL2
/cygdrive/i/Sources/sdl2gfx/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-2014 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 
216 int vline(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2)
217 {
218  return SDL_RenderDrawLine(renderer, x, y1, x, y2);;
219 }
220 
232 int vlineColor(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
233 {
234  Uint8 *c = (Uint8 *)&color;
235  return vlineRGBA(renderer, x, y1, y2, c[0], c[1], c[2], c[3]);
236 }
237 
252 int vlineRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
253 {
254  int result = 0;
255  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
256  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
257  result |= SDL_RenderDrawLine(renderer, x, y1, x, y2);
258  return result;
259 }
260 
261 /* ---- Rectangle */
262 
275 int rectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
276 {
277  Uint8 *c = (Uint8 *)&color;
278  return rectangleRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
279 }
280 
296 int rectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
297 {
298  int result;
299  Sint16 tmp;
300  SDL_Rect rect;
301 
302  /*
303  * Test for special cases of straight lines or single point
304  */
305  if (x1 == x2) {
306  if (y1 == y2) {
307  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
308  } else {
309  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
310  }
311  } else {
312  if (y1 == y2) {
313  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
314  }
315  }
316 
317  /*
318  * Swap x1, x2 if required
319  */
320  if (x1 > x2) {
321  tmp = x1;
322  x1 = x2;
323  x2 = tmp;
324  }
325 
326  /*
327  * Swap y1, y2 if required
328  */
329  if (y1 > y2) {
330  tmp = y1;
331  y1 = y2;
332  y2 = tmp;
333  }
334 
335  /*
336  * Create destination rect
337  */
338  rect.x = x1;
339  rect.y = y1;
340  rect.w = x2 - x1;
341  rect.h = y2 - y1;
342 
343  /*
344  * Draw
345  */
346  result = 0;
347  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
348  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
349  result |= SDL_RenderDrawRect(renderer, &rect);
350  return result;
351 }
352 
353 /* ---- Rounded Rectangle */
354 
368 int roundedRectangleColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
369 {
370  Uint8 *c = (Uint8 *)&color;
371  return roundedRectangleRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
372 }
373 
390 int roundedRectangleRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
391 {
392  int result = 0;
393  Sint16 tmp;
394  Sint16 w, h;
395  Sint16 xx1, xx2;
396  Sint16 yy1, yy2;
397 
398  /*
399  * Check renderer
400  */
401  if (renderer == NULL)
402  {
403  return -1;
404  }
405 
406  /*
407  * Check radius vor valid range
408  */
409  if (rad < 0) {
410  return -1;
411  }
412 
413  /*
414  * Special case - no rounding
415  */
416  if (rad <= 1) {
417  return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
418  }
419 
420  /*
421  * Test for special cases of straight lines or single point
422  */
423  if (x1 == x2) {
424  if (y1 == y2) {
425  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
426  } else {
427  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
428  }
429  } else {
430  if (y1 == y2) {
431  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
432  }
433  }
434 
435  /*
436  * Swap x1, x2 if required
437  */
438  if (x1 > x2) {
439  tmp = x1;
440  x1 = x2;
441  x2 = tmp;
442  }
443 
444  /*
445  * Swap y1, y2 if required
446  */
447  if (y1 > y2) {
448  tmp = y1;
449  y1 = y2;
450  y2 = tmp;
451  }
452 
453  /*
454  * Calculate width&height
455  */
456  w = x2 - x1;
457  h = y2 - y1;
458 
459  /*
460  * Maybe adjust radius
461  */
462  if ((rad * 2) > w)
463  {
464  rad = w / 2;
465  }
466  if ((rad * 2) > h)
467  {
468  rad = h / 2;
469  }
470 
471  /*
472  * Draw corners
473  */
474  xx1 = x1 + rad;
475  xx2 = x2 - rad;
476  yy1 = y1 + rad;
477  yy2 = y2 - rad;
478  result |= arcRGBA(renderer, xx1, yy1, rad, 180, 270, r, g, b, a);
479  result |= arcRGBA(renderer, xx2, yy1, rad, 270, 360, r, g, b, a);
480  result |= arcRGBA(renderer, xx1, yy2, rad, 90, 180, r, g, b, a);
481  result |= arcRGBA(renderer, xx2, yy2, rad, 0, 90, r, g, b, a);
482 
483  /*
484  * Draw lines
485  */
486  if (xx1 <= xx2) {
487  result |= hlineRGBA(renderer, xx1, xx2, y1, r, g, b, a);
488  result |= hlineRGBA(renderer, xx1, xx2, y2, r, g, b, a);
489  }
490  if (yy1 <= yy2) {
491  result |= vlineRGBA(renderer, x1, yy1, yy2, r, g, b, a);
492  result |= vlineRGBA(renderer, x2, yy1, yy2, r, g, b, a);
493  }
494 
495  return result;
496 }
497 
498 /* ---- Rounded Box */
499 
513 int roundedBoxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 rad, Uint32 color)
514 {
515  Uint8 *c = (Uint8 *)&color;
516  return roundedBoxRGBA(renderer, x1, y1, x2, y2, rad, c[0], c[1], c[2], c[3]);
517 }
518 
535 int roundedBoxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2,
536  Sint16 y2, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
537 {
538  int result;
539  Sint16 w, h, r2, tmp;
540  Sint16 cx = 0;
541  Sint16 cy = rad;
542  Sint16 ocx = (Sint16) 0xffff;
543  Sint16 ocy = (Sint16) 0xffff;
544  Sint16 df = 1 - rad;
545  Sint16 d_e = 3;
546  Sint16 d_se = -2 * rad + 5;
547  Sint16 xpcx, xmcx, xpcy, xmcy;
548  Sint16 ypcy, ymcy, ypcx, ymcx;
549  Sint16 x, y, dx, dy;
550 
551  /*
552  * Check destination renderer
553  */
554  if (renderer == NULL)
555  {
556  return -1;
557  }
558 
559  /*
560  * Check radius vor valid range
561  */
562  if (rad < 0) {
563  return -1;
564  }
565 
566  /*
567  * Special case - no rounding
568  */
569  if (rad <= 1) {
570  return rectangleRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
571  }
572 
573  /*
574  * Test for special cases of straight lines or single point
575  */
576  if (x1 == x2) {
577  if (y1 == y2) {
578  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
579  } else {
580  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
581  }
582  } else {
583  if (y1 == y2) {
584  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
585  }
586  }
587 
588  /*
589  * Swap x1, x2 if required
590  */
591  if (x1 > x2) {
592  tmp = x1;
593  x1 = x2;
594  x2 = tmp;
595  }
596 
597  /*
598  * Swap y1, y2 if required
599  */
600  if (y1 > y2) {
601  tmp = y1;
602  y1 = y2;
603  y2 = tmp;
604  }
605 
606  /*
607  * Calculate width&height
608  */
609  w = x2 - x1 + 1;
610  h = y2 - y1 + 1;
611 
612  /*
613  * Maybe adjust radius
614  */
615  r2 = rad + rad;
616  if (r2 > w)
617  {
618  rad = w / 2;
619  r2 = rad + rad;
620  }
621  if (r2 > h)
622  {
623  rad = h / 2;
624  }
625 
626  /* Setup filled circle drawing for corners */
627  x = x1 + rad;
628  y = y1 + rad;
629  dx = x2 - x1 - rad - rad;
630  dy = y2 - y1 - rad - rad;
631 
632  /*
633  * Set color
634  */
635  result = 0;
636  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
637  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
638 
639  /*
640  * Draw corners
641  */
642  do {
643  xpcx = x + cx;
644  xmcx = x - cx;
645  xpcy = x + cy;
646  xmcy = x - cy;
647  if (ocy != cy) {
648  if (cy > 0) {
649  ypcy = y + cy;
650  ymcy = y - cy;
651  result |= hline(renderer, xmcx, xpcx + dx, ypcy + dy);
652  result |= hline(renderer, xmcx, xpcx + dx, ymcy);
653  } else {
654  result |= hline(renderer, xmcx, xpcx + dx, y);
655  }
656  ocy = cy;
657  }
658  if (ocx != cx) {
659  if (cx != cy) {
660  if (cx > 0) {
661  ypcx = y + cx;
662  ymcx = y - cx;
663  result |= hline(renderer, xmcy, xpcy + dx, ymcx);
664  result |= hline(renderer, xmcy, xpcy + dx, ypcx + dy);
665  } else {
666  result |= hline(renderer, xmcy, xpcy + dx, y);
667  }
668  }
669  ocx = cx;
670  }
671 
672  /*
673  * Update
674  */
675  if (df < 0) {
676  df += d_e;
677  d_e += 2;
678  d_se += 2;
679  } else {
680  df += d_se;
681  d_e += 2;
682  d_se += 4;
683  cy--;
684  }
685  cx++;
686  } while (cx <= cy);
687 
688  /* Inside */
689  if (dx > 0 && dy > 0) {
690  result |= boxRGBA(renderer, x1, y1 + rad + 1, x2, y2 - rad, r, g, b, a);
691  }
692 
693  return (result);
694 }
695 
696 /* ---- Box */
697 
710 int boxColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
711 {
712  Uint8 *c = (Uint8 *)&color;
713  return boxRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
714 }
715 
731 int boxRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
732 {
733  int result;
734  Sint16 tmp;
735  SDL_Rect rect;
736 
737  /*
738  * Test for special cases of straight lines or single point
739  */
740  if (x1 == x2) {
741  if (y1 == y2) {
742  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
743  } else {
744  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
745  }
746  } else {
747  if (y1 == y2) {
748  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
749  }
750  }
751 
752  /*
753  * Swap x1, x2 if required
754  */
755  if (x1 > x2) {
756  tmp = x1;
757  x1 = x2;
758  x2 = tmp;
759  }
760 
761  /*
762  * Swap y1, y2 if required
763  */
764  if (y1 > y2) {
765  tmp = y1;
766  y1 = y2;
767  y2 = tmp;
768  }
769 
770  /*
771  * Create destination rect
772  */
773  rect.x = x1;
774  rect.y = y1;
775  rect.w = x2 - x1 + 1;
776  rect.h = y2 - y1 + 1;
777 
778  /*
779  * Draw
780  */
781  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_RenderFillRect(renderer, &rect);
785  return result;
786 }
787 
788 /* ----- Line */
789 
801 int line(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
802 {
803  /*
804  * Draw
805  */
806  return SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
807 }
808 
821 int lineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
822 {
823  Uint8 *c = (Uint8 *)&color;
824  return lineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3]);
825 }
826 
842 int lineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
843 {
844  /*
845  * Draw
846  */
847  int result = 0;
848  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
849  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
850  result |= SDL_RenderDrawLine(renderer, x1, y1, x2, y2);
851  return result;
852 }
853 
854 /* ---- AA Line */
855 
856 #define AAlevels 256
857 #define AAbits 8
858 
882 int _aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a, int draw_endpoint)
883 {
884  Sint32 xx0, yy0, xx1, yy1;
885  int result;
886  Uint32 intshift, erracc, erradj;
887  Uint32 erracctmp, wgt, wgtcompmask;
888  int dx, dy, tmp, xdir, y0p1, x0pxdir;
889 
890  /*
891  * Keep on working with 32bit numbers
892  */
893  xx0 = x1;
894  yy0 = y1;
895  xx1 = x2;
896  yy1 = y2;
897 
898  /*
899  * Reorder points to make dy positive
900  */
901  if (yy0 > yy1) {
902  tmp = yy0;
903  yy0 = yy1;
904  yy1 = tmp;
905  tmp = xx0;
906  xx0 = xx1;
907  xx1 = tmp;
908  }
909 
910  /*
911  * Calculate distance
912  */
913  dx = xx1 - xx0;
914  dy = yy1 - yy0;
915 
916  /*
917  * Adjust for negative dx and set xdir
918  */
919  if (dx >= 0) {
920  xdir = 1;
921  } else {
922  xdir = -1;
923  dx = (-dx);
924  }
925 
926  /*
927  * Check for special cases
928  */
929  if (dx == 0) {
930  /*
931  * Vertical line
932  */
933  if (draw_endpoint)
934  {
935  return (vlineRGBA(renderer, x1, y1, y2, r, g, b, a));
936  } else {
937  if (dy > 0) {
938  return (vlineRGBA(renderer, x1, yy0, yy0+dy, r, g, b, a));
939  } else {
940  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
941  }
942  }
943  } else if (dy == 0) {
944  /*
945  * Horizontal line
946  */
947  if (draw_endpoint)
948  {
949  return (hlineRGBA(renderer, x1, x2, y1, r, g, b, a));
950  } else {
951  if (dx > 0) {
952  return (hlineRGBA(renderer, xx0, xx0+dx, y1, r, g, b, a));
953  } else {
954  return (pixelRGBA(renderer, x1, y1, r, g, b, a));
955  }
956  }
957  } else if ((dx == dy) && (draw_endpoint)) {
958  /*
959  * Diagonal line (with endpoint)
960  */
961  return (lineRGBA(renderer, x1, y1, x2, y2, r, g, b, a));
962  }
963 
964 
965  /*
966  * Line is not horizontal, vertical or diagonal (with endpoint)
967  */
968  result = 0;
969 
970  /*
971  * Zero accumulator
972  */
973  erracc = 0;
974 
975  /*
976  * # of bits by which to shift erracc to get intensity level
977  */
978  intshift = 32 - AAbits;
979 
980  /*
981  * Mask used to flip all bits in an intensity weighting
982  */
983  wgtcompmask = AAlevels - 1;
984 
985  /*
986  * Draw the initial pixel in the foreground color
987  */
988  result |= pixelRGBA(renderer, x1, y1, r, g, b, a);
989 
990  /*
991  * x-major or y-major?
992  */
993  if (dy > dx) {
994 
995  /*
996  * y-major. Calculate 16-bit fixed point fractional part of a pixel that
997  * X advances every time Y advances 1 pixel, truncating the result so that
998  * we won't overrun the endpoint along the X axis
999  */
1000  /*
1001  * Not-so-portable version: erradj = ((Uint64)dx << 32) / (Uint64)dy;
1002  */
1003  erradj = ((dx << 16) / dy) << 16;
1004 
1005  /*
1006  * draw all pixels other than the first and last
1007  */
1008  x0pxdir = xx0 + xdir;
1009  while (--dy) {
1010  erracctmp = erracc;
1011  erracc += erradj;
1012  if (erracc <= erracctmp) {
1013  /*
1014  * rollover in error accumulator, x coord advances
1015  */
1016  xx0 = x0pxdir;
1017  x0pxdir += xdir;
1018  }
1019  yy0++; /* y-major so always advance Y */
1020 
1021  /*
1022  * the AAbits most significant bits of erracc give us the intensity
1023  * weighting for this pixel, and the complement of the weighting for
1024  * the paired pixel.
1025  */
1026  wgt = (erracc >> intshift) & 255;
1027  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
1028  result |= pixelRGBAWeight (renderer, x0pxdir, yy0, r, g, b, a, wgt);
1029  }
1030 
1031  } else {
1032 
1033  /*
1034  * x-major line. Calculate 16-bit fixed-point fractional part of a pixel
1035  * that Y advances each time X advances 1 pixel, truncating the result so
1036  * that we won't overrun the endpoint along the X axis.
1037  */
1038  /*
1039  * Not-so-portable version: erradj = ((Uint64)dy << 32) / (Uint64)dx;
1040  */
1041  erradj = ((dy << 16) / dx) << 16;
1042 
1043  /*
1044  * draw all pixels other than the first and last
1045  */
1046  y0p1 = yy0 + 1;
1047  while (--dx) {
1048 
1049  erracctmp = erracc;
1050  erracc += erradj;
1051  if (erracc <= erracctmp) {
1052  /*
1053  * Accumulator turned over, advance y
1054  */
1055  yy0 = y0p1;
1056  y0p1++;
1057  }
1058  xx0 += xdir; /* x-major so always advance X */
1059  /*
1060  * the AAbits most significant bits of erracc give us the intensity
1061  * weighting for this pixel, and the complement of the weighting for
1062  * the paired pixel.
1063  */
1064  wgt = (erracc >> intshift) & 255;
1065  result |= pixelRGBAWeight (renderer, xx0, yy0, r, g, b, a, 255 - wgt);
1066  result |= pixelRGBAWeight (renderer, xx0, y0p1, r, g, b, a, wgt);
1067  }
1068  }
1069 
1070  /*
1071  * Do we have to draw the endpoint
1072  */
1073  if (draw_endpoint) {
1074  /*
1075  * Draw final pixel, always exactly intersected by the line and doesn't
1076  * need to be weighted.
1077  */
1078  result |= pixelRGBA (renderer, x2, y2, r, g, b, a);
1079  }
1080 
1081  return (result);
1082 }
1083 
1096 int aalineColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
1097 {
1098  Uint8 *c = (Uint8 *)&color;
1099  return _aalineRGBA(renderer, x1, y1, x2, y2, c[0], c[1], c[2], c[3], 1);
1100 }
1101 
1117 int aalineRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1118 {
1119  return _aalineRGBA(renderer, x1, y1, x2, y2, r, g, b, a, 1);
1120 }
1121 
1122 /* ----- Circle */
1123 
1135 int circleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1136 {
1137  Uint8 *c = (Uint8 *)&color;
1138  return ellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1139 }
1140 
1155 int circleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1156 {
1157  return ellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1158 }
1159 
1160 /* ----- Arc */
1161 
1175 int arcColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
1176 {
1177  Uint8 *c = (Uint8 *)&color;
1178  return arcRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3]);
1179 }
1180 
1197 /* TODO: rewrite algorithm; arc endpoints are not always drawn */
1198 int arcRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1199 {
1200  int result;
1201  Sint16 cx = 0;
1202  Sint16 cy = rad;
1203  Sint16 df = 1 - rad;
1204  Sint16 d_e = 3;
1205  Sint16 d_se = -2 * rad + 5;
1206  Sint16 xpcx, xmcx, xpcy, xmcy;
1207  Sint16 ypcy, ymcy, ypcx, ymcx;
1208  Uint8 drawoct;
1209  int startoct, endoct, oct, stopval_start = 0, stopval_end = 0;
1210  double dstart, dend, temp = 0.;
1211 
1212  /*
1213  * Sanity check radius
1214  */
1215  if (rad < 0) {
1216  return (-1);
1217  }
1218 
1219  /*
1220  * Special case for rad=0 - draw a point
1221  */
1222  if (rad == 0) {
1223  return (pixelRGBA(renderer, x, y, r, g, b, a));
1224  }
1225 
1226  /*
1227  Octant labeling
1228 
1229  \ 5 | 6 /
1230  \ | /
1231  4 \ | / 7
1232  \|/
1233  ------+------ +x
1234  /|\
1235  3 / | \ 0
1236  / | \
1237  / 2 | 1 \
1238  +y
1239 
1240  Initially reset bitmask to 0x00000000
1241  the set whether or not to keep drawing a given octant.
1242  For example: 0x00111100 means we're drawing in octants 2-5
1243  */
1244  drawoct = 0;
1245 
1246  /*
1247  * Fixup angles
1248  */
1249  start %= 360;
1250  end %= 360;
1251  /* 0 <= start & end < 360; note that sometimes start > end - if so, arc goes back through 0. */
1252  while (start < 0) start += 360;
1253  while (end < 0) end += 360;
1254  start %= 360;
1255  end %= 360;
1256 
1257  /* now, we find which octants we're drawing in. */
1258  startoct = start / 45;
1259  endoct = end / 45;
1260  oct = startoct - 1;
1261 
1262  /* stopval_start, stopval_end; what values of cx to stop at. */
1263  do {
1264  oct = (oct + 1) % 8;
1265 
1266  if (oct == startoct) {
1267  /* need to compute stopval_start for this octant. Look at picture above if this is unclear */
1268  dstart = (double)start;
1269  switch (oct)
1270  {
1271  case 0:
1272  case 3:
1273  temp = sin(dstart * M_PI / 180.);
1274  break;
1275  case 1:
1276  case 6:
1277  temp = cos(dstart * M_PI / 180.);
1278  break;
1279  case 2:
1280  case 5:
1281  temp = -cos(dstart * M_PI / 180.);
1282  break;
1283  case 4:
1284  case 7:
1285  temp = -sin(dstart * M_PI / 180.);
1286  break;
1287  }
1288  temp *= rad;
1289  stopval_start = (int)temp;
1290 
1291  /*
1292  This isn't arbitrary, but requires graph paper to explain well.
1293  The basic idea is that we're always changing drawoct after we draw, so we
1294  stop immediately after we render the last sensible pixel at x = ((int)temp).
1295  and whether to draw in this octant initially
1296  */
1297  if (oct % 2) drawoct |= (1 << oct); /* this is basically like saying drawoct[oct] = true, if drawoct were a bool array */
1298  else drawoct &= 255 - (1 << oct); /* this is basically like saying drawoct[oct] = false */
1299  }
1300  if (oct == endoct) {
1301  /* need to compute stopval_end for this octant */
1302  dend = (double)end;
1303  switch (oct)
1304  {
1305  case 0:
1306  case 3:
1307  temp = sin(dend * M_PI / 180);
1308  break;
1309  case 1:
1310  case 6:
1311  temp = cos(dend * M_PI / 180);
1312  break;
1313  case 2:
1314  case 5:
1315  temp = -cos(dend * M_PI / 180);
1316  break;
1317  case 4:
1318  case 7:
1319  temp = -sin(dend * M_PI / 180);
1320  break;
1321  }
1322  temp *= rad;
1323  stopval_end = (int)temp;
1324 
1325  /* and whether to draw in this octant initially */
1326  if (startoct == endoct) {
1327  /* note: we start drawing, stop, then start again in this case */
1328  /* otherwise: we only draw in this octant, so initialize it to false, it will get set back to true */
1329  if (start > end) {
1330  /* unfortunately, if we're in the same octant and need to draw over the whole circle, */
1331  /* we need to set the rest to true, because the while loop will end at the bottom. */
1332  drawoct = 255;
1333  } else {
1334  drawoct &= 255 - (1 << oct);
1335  }
1336  }
1337  else if (oct % 2) drawoct &= 255 - (1 << oct);
1338  else drawoct |= (1 << oct);
1339  } else if (oct != startoct) { /* already verified that it's != endoct */
1340  drawoct |= (1 << oct); /* draw this entire segment */
1341  }
1342  } while (oct != endoct);
1343 
1344  /* so now we have what octants to draw and when to draw them. all that's left is the actual raster code. */
1345 
1346  /*
1347  * Set color
1348  */
1349  result = 0;
1350  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1351  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1352 
1353  /*
1354  * Draw arc
1355  */
1356  do {
1357  ypcy = y + cy;
1358  ymcy = y - cy;
1359  if (cx > 0) {
1360  xpcx = x + cx;
1361  xmcx = x - cx;
1362 
1363  /* always check if we're drawing a certain octant before adding a pixel to that octant. */
1364  if (drawoct & 4) result |= pixel(renderer, xmcx, ypcy);
1365  if (drawoct & 2) result |= pixel(renderer, xpcx, ypcy);
1366  if (drawoct & 32) result |= pixel(renderer, xmcx, ymcy);
1367  if (drawoct & 64) result |= pixel(renderer, xpcx, ymcy);
1368  } else {
1369  if (drawoct & 96) result |= pixel(renderer, x, ymcy);
1370  if (drawoct & 6) result |= pixel(renderer, x, ypcy);
1371  }
1372 
1373  xpcy = x + cy;
1374  xmcy = x - cy;
1375  if (cx > 0 && cx != cy) {
1376  ypcx = y + cx;
1377  ymcx = y - cx;
1378  if (drawoct & 8) result |= pixel(renderer, xmcy, ypcx);
1379  if (drawoct & 1) result |= pixel(renderer, xpcy, ypcx);
1380  if (drawoct & 16) result |= pixel(renderer, xmcy, ymcx);
1381  if (drawoct & 128) result |= pixel(renderer, xpcy, ymcx);
1382  } else if (cx == 0) {
1383  if (drawoct & 24) result |= pixel(renderer, xmcy, y);
1384  if (drawoct & 129) result |= pixel(renderer, xpcy, y);
1385  }
1386 
1387  /*
1388  * Update whether we're drawing an octant
1389  */
1390  if (stopval_start == cx) {
1391  /* works like an on-off switch. */
1392  /* This is just in case start & end are in the same octant. */
1393  if (drawoct & (1 << startoct)) drawoct &= 255 - (1 << startoct);
1394  else drawoct |= (1 << startoct);
1395  }
1396  if (stopval_end == cx) {
1397  if (drawoct & (1 << endoct)) drawoct &= 255 - (1 << endoct);
1398  else drawoct |= (1 << endoct);
1399  }
1400 
1401  /*
1402  * Update pixels
1403  */
1404  if (df < 0) {
1405  df += d_e;
1406  d_e += 2;
1407  d_se += 2;
1408  } else {
1409  df += d_se;
1410  d_e += 2;
1411  d_se += 4;
1412  cy--;
1413  }
1414  cx++;
1415  } while (cx <= cy);
1416 
1417  return (result);
1418 }
1419 
1420 /* ----- AA Circle */
1421 
1433 int aacircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1434 {
1435  Uint8 *c = (Uint8 *)&color;
1436  return aaellipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1437 }
1438 
1453 int aacircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1454 {
1455  /*
1456  * Draw
1457  */
1458  return aaellipseRGBA(renderer, x, y, rad, rad, r, g, b, a);
1459 }
1460 
1461 /* ----- Ellipse */
1462 
1475 int _drawQuadrants(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 dx, Sint16 dy, Sint32 f)
1476 {
1477  int result = 0;
1478  Sint16 xpdx, xmdx;
1479  Sint16 ypdy, ymdy;
1480 
1481  if (dx == 0) {
1482  if (dy == 0) {
1483  result |= pixel(renderer, x, y);
1484  } else {
1485  ypdy = y + dy;
1486  ymdy = y - dy;
1487  if (f) {
1488  result |= vline(renderer, x, ymdy, ypdy);
1489  } else {
1490  result |= pixel(renderer, x, ypdy);
1491  result |= pixel(renderer, x, ymdy);
1492  }
1493  }
1494  } else {
1495  xpdx = x + dx;
1496  xmdx = x - dx;
1497  ypdy = y + dy;
1498  ymdy = y - dy;
1499  if (f) {
1500  result |= vline(renderer, xpdx, ymdy, ypdy);
1501  result |= vline(renderer, xmdx, ymdy, ypdy);
1502  } else {
1503  result |= pixel(renderer, xpdx, ypdy);
1504  result |= pixel(renderer, xmdx, ypdy);
1505  result |= pixel(renderer, xpdx, ymdy);
1506  result |= pixel(renderer, xmdx, ymdy);
1507  }
1508  }
1509 
1510  return result;
1511 }
1512 
1529 #define ELLIPSE_OVERSCAN 4
1530 int _ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Sint32 f)
1531 {
1532  int result;
1533  Sint32 rx2, ry2, rx22, ry22;
1534  Sint32 error;
1535  Sint32 curX, curY, curXp1, curYm1;
1536  Sint32 scrX, scrY, oldX, oldY;
1537  Sint32 deltaX, deltaY;
1538 
1539  /*
1540  * Sanity check radii
1541  */
1542  if ((rx < 0) || (ry < 0)) {
1543  return (-1);
1544  }
1545 
1546  /*
1547  * Set color
1548  */
1549  result = 0;
1550  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1551  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1552 
1553  /*
1554  * Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
1555  */
1556  if (rx == 0) {
1557  if (ry == 0) {
1558  return (pixel(renderer, x, y));
1559  } else {
1560  return (vline(renderer, x, y - ry, y + ry));
1561  }
1562  } else {
1563  if (ry == 0) {
1564  return (hline(renderer, x - rx, x + rx, y));
1565  }
1566  }
1567 
1568  /*
1569  * Top/bottom center points.
1570  */
1571  oldX = scrX = 0;
1572  oldY = scrY = ry;
1573  result |= _drawQuadrants(renderer, x, y, 0, ry, f);
1574 
1575  /* Midpoint ellipse algorithm with overdraw */
1576  rx *= ELLIPSE_OVERSCAN;
1577  ry *= ELLIPSE_OVERSCAN;
1578  rx2 = rx * rx;
1579  rx22 = rx2 + rx2;
1580  ry2 = ry * ry;
1581  ry22 = ry2 + ry2;
1582  curX = 0;
1583  curY = ry;
1584  deltaX = 0;
1585  deltaY = rx22 * curY;
1586 
1587  /* Points in segment 1 */
1588  error = ry2 - rx2 * ry + rx2 / 4;
1589  while (deltaX <= deltaY)
1590  {
1591  curX++;
1592  deltaX += ry22;
1593 
1594  error += deltaX + ry2;
1595  if (error >= 0)
1596  {
1597  curY--;
1598  deltaY -= rx22;
1599  error -= deltaY;
1600  }
1601 
1602  scrX = curX/ELLIPSE_OVERSCAN;
1603  scrY = curY/ELLIPSE_OVERSCAN;
1604  if ((scrX != oldX && scrY == oldY) || (scrX != oldX && scrY != oldY)) {
1605  result |= _drawQuadrants(renderer, x, y, scrX, scrY, f);
1606  oldX = scrX;
1607  oldY = scrY;
1608  }
1609  }
1610 
1611  /* Points in segment 2 */
1612  if (curY > 0)
1613  {
1614  curXp1 = curX + 1;
1615  curYm1 = curY - 1;
1616  error = ry2 * curX * curXp1 + ((ry2 + 3) / 4) + rx2 * curYm1 * curYm1 - rx2 * ry2;
1617  while (curY > 0)
1618  {
1619  curY--;
1620  deltaY -= rx22;
1621 
1622  error += rx2;
1623  error -= deltaY;
1624 
1625  if (error <= 0)
1626  {
1627  curX++;
1628  deltaX += ry22;
1629  error += deltaX;
1630  }
1631 
1632  scrX = curX/ELLIPSE_OVERSCAN;
1633  scrY = curY/ELLIPSE_OVERSCAN;
1634  if ((scrX != oldX && scrY == oldY) || (scrX != oldX && scrY != oldY)) {
1635  oldY--;
1636  for (;oldY >= scrY; oldY--) {
1637  result |= _drawQuadrants(renderer, x, y, scrX, oldY, f);
1638  /* prevent overdraw */
1639  if (f) {
1640  oldY = scrY - 1;
1641  }
1642  }
1643  oldX = scrX;
1644  oldY = scrY;
1645  }
1646  }
1647 
1648  /* Remaining points in vertical */
1649  if (!f) {
1650  oldY--;
1651  for (;oldY >= 0; oldY--) {
1652  result |= _drawQuadrants(renderer, x, y, scrX, oldY, f);
1653  }
1654  }
1655  }
1656 
1657  return (result);
1658 }
1659 
1672 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1673 {
1674  Uint8 *c = (Uint8 *)&color;
1675  return _ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3], 0);
1676 }
1677 
1693 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1694 {
1695  return _ellipseRGBA(renderer, x, y, rx, ry, r, g, b, a, 0);
1696 }
1697 
1698 /* ----- Filled Circle */
1699 
1711 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1712 {
1713  Uint8 *c = (Uint8 *)&color;
1714  return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1715 }
1716 
1731 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1732 {
1733  return _ellipseRGBA(renderer, x, y, rad, rad, r, g ,b, a, 1);
1734 }
1735 
1736 
1737 /* ----- AA Ellipse */
1738 
1739 /* Windows targets do not have lrint, so provide a local inline version */
1740 #if defined(_MSC_VER)
1741 /* Detect 64bit and use intrinsic version */
1742 #ifdef _M_X64
1743 #include <emmintrin.h>
1744 static __inline long
1745  lrint(float f)
1746 {
1747  return _mm_cvtss_si32(_mm_load_ss(&f));
1748 }
1749 #elif defined(_M_IX86)
1750 __inline long int
1751  lrint (double flt)
1752 {
1753  int intgr;
1754  _asm
1755  {
1756  fld flt
1757  fistp intgr
1758  };
1759  return intgr;
1760 }
1761 #elif defined(_M_ARM)
1762 #include <armintr.h>
1763 #pragma warning(push)
1764 #pragma warning(disable: 4716)
1765 __declspec(naked) long int
1766  lrint (double flt)
1767 {
1768  __emit(0xEC410B10); // fmdrr d0, r0, r1
1769  __emit(0xEEBD0B40); // ftosid s0, d0
1770  __emit(0xEE100A10); // fmrs r0, s0
1771  __emit(0xE12FFF1E); // bx lr
1772 }
1773 #pragma warning(pop)
1774 #else
1775 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
1776 #endif
1777 #endif
1778 
1791 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1792 {
1793  Uint8 *c = (Uint8 *)&color;
1794  return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1795 }
1796 
1812 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1813 {
1814  int result;
1815  int i;
1816  int a2, b2, ds, dt, dxt, t, s, d;
1817  Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
1818  float cp;
1819  double sab;
1820  Uint8 weight, iweight;
1821 
1822  /*
1823  * Sanity check radii
1824  */
1825  if ((rx < 0) || (ry < 0)) {
1826  return (-1);
1827  }
1828 
1829  /*
1830  * Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
1831  */
1832  if (rx == 0) {
1833  if (ry == 0) {
1834  return (pixelRGBA(renderer, x, y, r, g, b, a));
1835  } else {
1836  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1837  }
1838  } else {
1839  if (ry == 0) {
1840  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1841  }
1842  }
1843 
1844  /* Variable setup */
1845  a2 = rx * rx;
1846  b2 = ry * ry;
1847 
1848  ds = 2 * a2;
1849  dt = 2 * b2;
1850 
1851  xc2 = 2 * x;
1852  yc2 = 2 * y;
1853 
1854  sab = sqrt((double)(a2 + b2));
1855  od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
1856  dxt = (Sint16)lrint((double)a2 / sab) + od;
1857 
1858  t = 0;
1859  s = -2 * a2 * ry;
1860  d = 0;
1861 
1862  xp = x;
1863  yp = y - ry;
1864 
1865  /* Draw */
1866  result = 0;
1867  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1868 
1869  /* "End points" */
1870  result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
1871  result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
1872  result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
1873  result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
1874 
1875  for (i = 1; i <= dxt; i++) {
1876  xp--;
1877  d += t - b2;
1878 
1879  if (d >= 0)
1880  ys = yp - 1;
1881  else if ((d - s - a2) > 0) {
1882  if ((2 * d - s - a2) >= 0)
1883  ys = yp + 1;
1884  else {
1885  ys = yp;
1886  yp++;
1887  d -= s + a2;
1888  s += ds;
1889  }
1890  } else {
1891  yp++;
1892  ys = yp + 1;
1893  d -= s + a2;
1894  s += ds;
1895  }
1896 
1897  t -= dt;
1898 
1899  /* Calculate alpha */
1900  if (s != 0) {
1901  cp = (float) abs(d) / (float) abs(s);
1902  if (cp > 1.0) {
1903  cp = 1.0;
1904  }
1905  } else {
1906  cp = 1.0;
1907  }
1908 
1909  /* Calculate weights */
1910  weight = (Uint8) (cp * 255);
1911  iweight = 255 - weight;
1912 
1913  /* Upper half */
1914  xx = xc2 - xp;
1915  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1916  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1917 
1918  result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
1919  result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
1920 
1921  /* Lower half */
1922  yy = yc2 - yp;
1923  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1924  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1925 
1926  yy = yc2 - ys;
1927  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
1928  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1929  }
1930 
1931  /* Replaces original approximation code dyt = abs(yp - yc); */
1932  dyt = (Sint16)lrint((double)b2 / sab ) + od;
1933 
1934  for (i = 1; i <= dyt; i++) {
1935  yp++;
1936  d -= s + a2;
1937 
1938  if (d <= 0)
1939  xs = xp + 1;
1940  else if ((d + t - b2) < 0) {
1941  if ((2 * d + t - b2) <= 0)
1942  xs = xp - 1;
1943  else {
1944  xs = xp;
1945  xp--;
1946  d += t - b2;
1947  t -= dt;
1948  }
1949  } else {
1950  xp--;
1951  xs = xp - 1;
1952  d += t - b2;
1953  t -= dt;
1954  }
1955 
1956  s += ds;
1957 
1958  /* Calculate alpha */
1959  if (t != 0) {
1960  cp = (float) abs(d) / (float) abs(t);
1961  if (cp > 1.0) {
1962  cp = 1.0;
1963  }
1964  } else {
1965  cp = 1.0;
1966  }
1967 
1968  /* Calculate weight */
1969  weight = (Uint8) (cp * 255);
1970  iweight = 255 - weight;
1971 
1972  /* Left half */
1973  xx = xc2 - xp;
1974  yy = yc2 - yp;
1975  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1976  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1977 
1978  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1979  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1980 
1981  /* Right half */
1982  xx = xc2 - xs;
1983  result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
1984  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
1985 
1986  result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
1987  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1988  }
1989 
1990  return (result);
1991 }
1992 
1993 /* ---- Filled Ellipse */
1994 
2007 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2008 {
2009  Uint8 *c = (Uint8 *)&color;
2010  return _ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3], 1);
2011 }
2012 
2028 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2029 {
2030  return _ellipseRGBA(renderer, x, y, rx, ry, r, g, b, a, 1);
2031 }
2032 
2033 /* ----- Pie */
2034 
2054 /* TODO: rewrite algorithm; pie is not always accurate */
2055 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)
2056 {
2057  int result;
2058  double angle, start_angle, end_angle;
2059  double deltaAngle;
2060  double dr;
2061  int numpoints, i;
2062  Sint16 *vx, *vy;
2063 
2064  /*
2065  * Sanity check radii
2066  */
2067  if (rad < 0) {
2068  return (-1);
2069  }
2070 
2071  /*
2072  * Fixup angles
2073  */
2074  start = start % 360;
2075  end = end % 360;
2076 
2077  /*
2078  * Special case for rad=0 - draw a point
2079  */
2080  if (rad == 0) {
2081  return (pixelRGBA(renderer, x, y, r, g, b, a));
2082  }
2083 
2084  /*
2085  * Variable setup
2086  */
2087  dr = (double) rad;
2088  deltaAngle = 3.0 / dr;
2089  start_angle = (double) start *(2.0 * M_PI / 360.0);
2090  end_angle = (double) end *(2.0 * M_PI / 360.0);
2091  if (start > end) {
2092  end_angle += (2.0 * M_PI);
2093  }
2094 
2095  /* We will always have at least 2 points */
2096  numpoints = 2;
2097 
2098  /* Count points (rather than calculating it) */
2099  angle = start_angle;
2100  while (angle < end_angle) {
2101  angle += deltaAngle;
2102  numpoints++;
2103  }
2104 
2105  /* Allocate combined vertex array */
2106  vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
2107  if (vx == NULL) {
2108  return (-1);
2109  }
2110 
2111  /* Update point to start of vy */
2112  vy += numpoints;
2113 
2114  /* Center */
2115  vx[0] = x;
2116  vy[0] = y;
2117 
2118  /* First vertex */
2119  angle = start_angle;
2120  vx[1] = x + (int) (dr * cos(angle));
2121  vy[1] = y + (int) (dr * sin(angle));
2122 
2123  if (numpoints<3)
2124  {
2125  result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
2126  }
2127  else
2128  {
2129  /* Calculate other vertices */
2130  i = 2;
2131  angle = start_angle;
2132  while (angle < end_angle) {
2133  angle += deltaAngle;
2134  if (angle>end_angle)
2135  {
2136  angle = end_angle;
2137  }
2138  vx[i] = x + (int) (dr * cos(angle));
2139  vy[i] = y + (int) (dr * sin(angle));
2140  i++;
2141  }
2142 
2143  /* Draw */
2144  if (filled) {
2145  result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2146  } else {
2147  result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2148  }
2149  }
2150 
2151  /* Free combined vertex array */
2152  free(vx);
2153 
2154  return (result);
2155 }
2156 
2170 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2171  Sint16 start, Sint16 end, Uint32 color)
2172 {
2173  Uint8 *c = (Uint8 *)&color;
2174  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
2175 }
2176 
2193 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2194  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2195 {
2196  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
2197 }
2198 
2212 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
2213 {
2214  Uint8 *c = (Uint8 *)&color;
2215  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
2216 }
2217 
2234 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2235  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2236 {
2237  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
2238 }
2239 
2240 /* ------ Trigon */
2241 
2258 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2259 {
2260  Sint16 vx[3];
2261  Sint16 vy[3];
2262 
2263  vx[0]=x1;
2264  vx[1]=x2;
2265  vx[2]=x3;
2266  vy[0]=y1;
2267  vy[1]=y2;
2268  vy[2]=y3;
2269 
2270  return(polygonColor(renderer,vx,vy,3,color));
2271 }
2272 
2290 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2291  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2292 {
2293  Sint16 vx[3];
2294  Sint16 vy[3];
2295 
2296  vx[0]=x1;
2297  vx[1]=x2;
2298  vx[2]=x3;
2299  vy[0]=y1;
2300  vy[1]=y2;
2301  vy[2]=y3;
2302 
2303  return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
2304 }
2305 
2306 /* ------ AA-Trigon */
2307 
2324 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2325 {
2326  Sint16 vx[3];
2327  Sint16 vy[3];
2328 
2329  vx[0]=x1;
2330  vx[1]=x2;
2331  vx[2]=x3;
2332  vy[0]=y1;
2333  vy[1]=y2;
2334  vy[2]=y3;
2335 
2336  return(aapolygonColor(renderer,vx,vy,3,color));
2337 }
2338 
2356 int aatrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2357  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2358 {
2359  Sint16 vx[3];
2360  Sint16 vy[3];
2361 
2362  vx[0]=x1;
2363  vx[1]=x2;
2364  vx[2]=x3;
2365  vy[0]=y1;
2366  vy[1]=y2;
2367  vy[2]=y3;
2368 
2369  return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2370 }
2371 
2372 /* ------ Filled Trigon */
2373 
2390 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2391 {
2392  Sint16 vx[3];
2393  Sint16 vy[3];
2394 
2395  vx[0]=x1;
2396  vx[1]=x2;
2397  vx[2]=x3;
2398  vy[0]=y1;
2399  vy[1]=y2;
2400  vy[2]=y3;
2401 
2402  return(filledPolygonColor(renderer,vx,vy,3,color));
2403 }
2404 
2424 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2425  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2426 {
2427  Sint16 vx[3];
2428  Sint16 vy[3];
2429 
2430  vx[0]=x1;
2431  vx[1]=x2;
2432  vx[2]=x3;
2433  vy[0]=y1;
2434  vy[1]=y2;
2435  vy[2]=y3;
2436 
2437  return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2438 }
2439 
2440 /* ---- Polygon */
2441 
2453 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2454 {
2455  Uint8 *c = (Uint8 *)&color;
2456  return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2457 }
2458 
2469 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
2470 {
2471  /*
2472  * Draw
2473  */
2474  int result = 0;
2475  int i, nn;
2476  SDL_Point* points;
2477 
2478  /*
2479  * Vertex array NULL check
2480  */
2481  if (vx == NULL) {
2482  return (-1);
2483  }
2484  if (vy == NULL) {
2485  return (-1);
2486  }
2487 
2488  /*
2489  * Sanity check
2490  */
2491  if (n < 3) {
2492  return (-1);
2493  }
2494 
2495  /*
2496  * Create array of points
2497  */
2498  nn = n + 1;
2499  points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
2500  if (points == NULL)
2501  {
2502  return -1;
2503  }
2504  for (i=0; i<n; i++)
2505  {
2506  points[i].x = vx[i];
2507  points[i].y = vy[i];
2508  }
2509  points[n].x = vx[0];
2510  points[n].y = vy[0];
2511 
2512  /*
2513  * Draw
2514  */
2515  result |= SDL_RenderDrawLines(renderer, points, nn);
2516  free(points);
2517 
2518  return (result);
2519 }
2520 
2535 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2536 {
2537  /*
2538  * Draw
2539  */
2540  int result;
2541  const Sint16 *x1, *y1, *x2, *y2;
2542 
2543  /*
2544  * Vertex array NULL check
2545  */
2546  if (vx == NULL) {
2547  return (-1);
2548  }
2549  if (vy == NULL) {
2550  return (-1);
2551  }
2552 
2553  /*
2554  * Sanity check
2555  */
2556  if (n < 3) {
2557  return (-1);
2558  }
2559 
2560  /*
2561  * Pointer setup
2562  */
2563  x1 = x2 = vx;
2564  y1 = y2 = vy;
2565  x2++;
2566  y2++;
2567 
2568  /*
2569  * Set color
2570  */
2571  result = 0;
2572  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2573  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2574 
2575  /*
2576  * Draw
2577  */
2578  result |= polygon(renderer, vx, vy, n);
2579 
2580  return (result);
2581 }
2582 
2583 /* ---- AA-Polygon */
2584 
2596 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2597 {
2598  Uint8 *c = (Uint8 *)&color;
2599  return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2600 }
2601 
2616 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2617 {
2618  int result;
2619  int i;
2620  const Sint16 *x1, *y1, *x2, *y2;
2621 
2622  /*
2623  * Vertex array NULL check
2624  */
2625  if (vx == NULL) {
2626  return (-1);
2627  }
2628  if (vy == NULL) {
2629  return (-1);
2630  }
2631 
2632  /*
2633  * Sanity check
2634  */
2635  if (n < 3) {
2636  return (-1);
2637  }
2638 
2639  /*
2640  * Pointer setup
2641  */
2642  x1 = x2 = vx;
2643  y1 = y2 = vy;
2644  x2++;
2645  y2++;
2646 
2647  /*
2648  * Draw
2649  */
2650  result = 0;
2651  for (i = 1; i < n; i++) {
2652  result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
2653  x1 = x2;
2654  y1 = y2;
2655  x2++;
2656  y2++;
2657  }
2658 
2659  result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
2660 
2661  return (result);
2662 }
2663 
2664 /* ---- Filled Polygon */
2665 
2674 int _gfxPrimitivesCompareInt(const void *a, const void *b)
2675 {
2676  return (*(const int *) a) - (*(const int *) b);
2677 }
2678 
2684 static int *gfxPrimitivesPolyIntsGlobal = NULL;
2685 
2691 static int gfxPrimitivesPolyAllocatedGlobal = 0;
2692 
2711 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)
2712 {
2713  int result;
2714  int i;
2715  int y, xa, xb;
2716  int miny, maxy;
2717  int x1, y1;
2718  int x2, y2;
2719  int ind1, ind2;
2720  int ints;
2721  int *gfxPrimitivesPolyInts = NULL;
2722  int *gfxPrimitivesPolyIntsNew = NULL;
2723  int gfxPrimitivesPolyAllocated = 0;
2724 
2725  /*
2726  * Vertex array NULL check
2727  */
2728  if (vx == NULL) {
2729  return (-1);
2730  }
2731  if (vy == NULL) {
2732  return (-1);
2733  }
2734 
2735  /*
2736  * Sanity check number of edges
2737  */
2738  if (n < 3) {
2739  return -1;
2740  }
2741 
2742  /*
2743  * Map polygon cache
2744  */
2745  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2746  /* Use global cache */
2747  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
2748  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
2749  } else {
2750  /* Use local cache */
2751  gfxPrimitivesPolyInts = *polyInts;
2752  gfxPrimitivesPolyAllocated = *polyAllocated;
2753  }
2754 
2755  /*
2756  * Allocate temp array, only grow array
2757  */
2758  if (!gfxPrimitivesPolyAllocated) {
2759  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
2760  gfxPrimitivesPolyAllocated = n;
2761  } else {
2762  if (gfxPrimitivesPolyAllocated < n) {
2763  gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
2764  if (!gfxPrimitivesPolyIntsNew) {
2765  if (!gfxPrimitivesPolyInts) {
2766  free(gfxPrimitivesPolyInts);
2767  gfxPrimitivesPolyInts = NULL;
2768  }
2769  gfxPrimitivesPolyAllocated = 0;
2770  } else {
2771  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
2772  gfxPrimitivesPolyAllocated = n;
2773  }
2774  }
2775  }
2776 
2777  /*
2778  * Check temp array
2779  */
2780  if (gfxPrimitivesPolyInts==NULL) {
2781  gfxPrimitivesPolyAllocated = 0;
2782  }
2783 
2784  /*
2785  * Update cache variables
2786  */
2787  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2788  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
2789  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
2790  } else {
2791  *polyInts = gfxPrimitivesPolyInts;
2792  *polyAllocated = gfxPrimitivesPolyAllocated;
2793  }
2794 
2795  /*
2796  * Check temp array again
2797  */
2798  if (gfxPrimitivesPolyInts==NULL) {
2799  return(-1);
2800  }
2801 
2802  /*
2803  * Determine Y maxima
2804  */
2805  miny = vy[0];
2806  maxy = vy[0];
2807  for (i = 1; (i < n); i++) {
2808  if (vy[i] < miny) {
2809  miny = vy[i];
2810  } else if (vy[i] > maxy) {
2811  maxy = vy[i];
2812  }
2813  }
2814 
2815  /*
2816  * Draw, scanning y
2817  */
2818  result = 0;
2819  for (y = miny; (y <= maxy); y++) {
2820  ints = 0;
2821  for (i = 0; (i < n); i++) {
2822  if (!i) {
2823  ind1 = n - 1;
2824  ind2 = 0;
2825  } else {
2826  ind1 = i - 1;
2827  ind2 = i;
2828  }
2829  y1 = vy[ind1];
2830  y2 = vy[ind2];
2831  if (y1 < y2) {
2832  x1 = vx[ind1];
2833  x2 = vx[ind2];
2834  } else if (y1 > y2) {
2835  y2 = vy[ind1];
2836  y1 = vy[ind2];
2837  x2 = vx[ind1];
2838  x1 = vx[ind2];
2839  } else {
2840  continue;
2841  }
2842  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
2843  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
2844  }
2845  }
2846 
2847  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
2848 
2849  /*
2850  * Set color
2851  */
2852  result = 0;
2853  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2854  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2855 
2856  for (i = 0; (i < ints); i += 2) {
2857  xa = gfxPrimitivesPolyInts[i] + 1;
2858  xa = (xa >> 16) + ((xa & 32768) >> 15);
2859  xb = gfxPrimitivesPolyInts[i+1] - 1;
2860  xb = (xb >> 16) + ((xb & 32768) >> 15);
2861  result |= hline(renderer, xa, xb, y);
2862  }
2863  }
2864 
2865  return (result);
2866 }
2867 
2879 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2880 {
2881  Uint8 *c = (Uint8 *)&color;
2882  return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
2883 }
2884 
2899 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2900 {
2901  return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
2902 }
2903 
2904 /* ---- Textured Polygon */
2905 
2921 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)
2922 {
2923  Sint16 w;
2924  Sint16 xtmp;
2925  int result = 0;
2926  int texture_x_walker;
2927  int texture_y_start;
2928  SDL_Rect source_rect,dst_rect;
2929  int pixels_written,write_width;
2930 
2931  /*
2932  * Swap x1, x2 if required to ensure x1<=x2
2933  */
2934  if (x1 > x2) {
2935  xtmp = x1;
2936  x1 = x2;
2937  x2 = xtmp;
2938  }
2939 
2940  /*
2941  * Calculate width to draw
2942  */
2943  w = x2 - x1 + 1;
2944 
2945  /*
2946  * Determine where in the texture we start drawing
2947  */
2948  texture_x_walker = (x1 - texture_dx) % texture_w;
2949  if (texture_x_walker < 0){
2950  texture_x_walker = texture_w + texture_x_walker ;
2951  }
2952 
2953  texture_y_start = (y + texture_dy) % texture_h;
2954  if (texture_y_start < 0){
2955  texture_y_start = texture_h + texture_y_start;
2956  }
2957 
2958  /* setup the source rectangle; we are only drawing one horizontal line */
2959  source_rect.y = texture_y_start;
2960  source_rect.x = texture_x_walker;
2961  source_rect.h = 1;
2962 
2963  /* we will draw to the current y */
2964  dst_rect.y = y;
2965  dst_rect.h = 1;
2966 
2967  /* if there are enough pixels left in the current row of the texture */
2968  /* draw it all at once */
2969  if (w <= texture_w -texture_x_walker){
2970  source_rect.w = w;
2971  source_rect.x = texture_x_walker;
2972  dst_rect.x= x1;
2973  dst_rect.w = source_rect.w;
2974  result = (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
2975  } else {
2976  /* we need to draw multiple times */
2977  /* draw the first segment */
2978  pixels_written = texture_w - texture_x_walker;
2979  source_rect.w = pixels_written;
2980  source_rect.x = texture_x_walker;
2981  dst_rect.x= x1;
2982  dst_rect.w = source_rect.w;
2983  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
2984  write_width = texture_w;
2985 
2986  /* now draw the rest */
2987  /* set the source x to 0 */
2988  source_rect.x = 0;
2989  while (pixels_written < w){
2990  if (write_width >= w - pixels_written) {
2991  write_width = w - pixels_written;
2992  }
2993  source_rect.w = write_width;
2994  dst_rect.x = x1 + pixels_written;
2995  dst_rect.w = source_rect.w;
2996  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
2997  pixels_written += write_width;
2998  }
2999  }
3000 
3001  return result;
3002 }
3003 
3020 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
3021  SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
3022 {
3023  int result;
3024  int i;
3025  int y, xa, xb;
3026  int minx,maxx,miny, maxy;
3027  int x1, y1;
3028  int x2, y2;
3029  int ind1, ind2;
3030  int ints;
3031  int *gfxPrimitivesPolyInts = NULL;
3032  int *gfxPrimitivesPolyIntsTemp = NULL;
3033  int gfxPrimitivesPolyAllocated = 0;
3034  SDL_Texture *textureAsTexture = NULL;
3035 
3036  /*
3037  * Sanity check number of edges
3038  */
3039  if (n < 3) {
3040  return -1;
3041  }
3042 
3043  /*
3044  * Map polygon cache
3045  */
3046  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3047  /* Use global cache */
3048  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
3049  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
3050  } else {
3051  /* Use local cache */
3052  gfxPrimitivesPolyInts = *polyInts;
3053  gfxPrimitivesPolyAllocated = *polyAllocated;
3054  }
3055 
3056  /*
3057  * Allocate temp array, only grow array
3058  */
3059  if (!gfxPrimitivesPolyAllocated) {
3060  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3061  gfxPrimitivesPolyAllocated = n;
3062  } else {
3063  if (gfxPrimitivesPolyAllocated < n) {
3064  gfxPrimitivesPolyIntsTemp = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3065  if (gfxPrimitivesPolyIntsTemp == NULL) {
3066  /* Realloc failed - keeps original memory block, but fails this operation */
3067  return(-1);
3068  }
3069  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsTemp;
3070  gfxPrimitivesPolyAllocated = n;
3071  }
3072  }
3073 
3074  /*
3075  * Check temp array
3076  */
3077  if (gfxPrimitivesPolyInts==NULL) {
3078  gfxPrimitivesPolyAllocated = 0;
3079  }
3080 
3081  /*
3082  * Update cache variables
3083  */
3084  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3085  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
3086  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
3087  } else {
3088  *polyInts = gfxPrimitivesPolyInts;
3089  *polyAllocated = gfxPrimitivesPolyAllocated;
3090  }
3091 
3092  /*
3093  * Check temp array again
3094  */
3095  if (gfxPrimitivesPolyInts==NULL) {
3096  return(-1);
3097  }
3098 
3099  /*
3100  * Determine X,Y minima,maxima
3101  */
3102  miny = vy[0];
3103  maxy = vy[0];
3104  minx = vx[0];
3105  maxx = vx[0];
3106  for (i = 1; (i < n); i++) {
3107  if (vy[i] < miny) {
3108  miny = vy[i];
3109  } else if (vy[i] > maxy) {
3110  maxy = vy[i];
3111  }
3112  if (vx[i] < minx) {
3113  minx = vx[i];
3114  } else if (vx[i] > maxx) {
3115  maxx = vx[i];
3116  }
3117  }
3118 
3119  /* Create texture for drawing */
3120  textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
3121  if (textureAsTexture == NULL)
3122  {
3123  return -1;
3124  }
3125  SDL_SetTextureBlendMode(textureAsTexture, SDL_BLENDMODE_BLEND);
3126 
3127  /*
3128  * Draw, scanning y
3129  */
3130  result = 0;
3131  for (y = miny; (y <= maxy); y++) {
3132  ints = 0;
3133  for (i = 0; (i < n); i++) {
3134  if (!i) {
3135  ind1 = n - 1;
3136  ind2 = 0;
3137  } else {
3138  ind1 = i - 1;
3139  ind2 = i;
3140  }
3141  y1 = vy[ind1];
3142  y2 = vy[ind2];
3143  if (y1 < y2) {
3144  x1 = vx[ind1];
3145  x2 = vx[ind2];
3146  } else if (y1 > y2) {
3147  y2 = vy[ind1];
3148  y1 = vy[ind2];
3149  x2 = vx[ind1];
3150  x1 = vx[ind2];
3151  } else {
3152  continue;
3153  }
3154  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
3155  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
3156  }
3157  }
3158 
3159  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
3160 
3161  for (i = 0; (i < ints); i += 2) {
3162  xa = gfxPrimitivesPolyInts[i] + 1;
3163  xa = (xa >> 16) + ((xa & 32768) >> 15);
3164  xb = gfxPrimitivesPolyInts[i+1] - 1;
3165  xb = (xb >> 16) + ((xb & 32768) >> 15);
3166  result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
3167  }
3168  }
3169 
3170  SDL_RenderPresent(renderer);
3171  SDL_DestroyTexture(textureAsTexture);
3172 
3173  return (result);
3174 }
3175 
3192 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
3193 {
3194  /*
3195  * Draw
3196  */
3197  return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
3198 }
3199 
3200 /* ---- Character */
3201 
3205 static SDL_Texture *gfxPrimitivesFont[256];
3206 
3210 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
3211 
3215 static Uint32 charWidth = 8;
3216 
3220 static Uint32 charHeight = 8;
3221 
3225 static Uint32 charWidthLocal = 8;
3226 
3230 static Uint32 charHeightLocal = 8;
3231 
3235 static Uint32 charPitch = 1;
3236 
3240 static Uint32 charRotation = 0;
3241 
3245 static Uint32 charSize = 8;
3246 
3260 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
3261 {
3262  int i;
3263 
3264  if ((fontdata) && (cw) && (ch)) {
3265  currentFontdata = (unsigned char *)fontdata;
3266  charWidth = cw;
3267  charHeight = ch;
3268  } else {
3269  currentFontdata = gfxPrimitivesFontdata;
3270  charWidth = 8;
3271  charHeight = 8;
3272  }
3273 
3274  charPitch = (charWidth+7)/8;
3275  charSize = charPitch * charHeight;
3276 
3277  /* Maybe flip width/height for rendering */
3278  if ((charRotation==1) || (charRotation==3))
3279  {
3280  charWidthLocal = charHeight;
3281  charHeightLocal = charWidth;
3282  }
3283  else
3284  {
3285  charWidthLocal = charWidth;
3286  charHeightLocal = charHeight;
3287  }
3288 
3289  /* Clear character cache */
3290  for (i = 0; i < 256; i++) {
3291  if (gfxPrimitivesFont[i]) {
3292  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3293  gfxPrimitivesFont[i] = NULL;
3294  }
3295  }
3296 }
3297 
3306 void gfxPrimitivesSetFontRotation(Uint32 rotation)
3307 {
3308  int i;
3309 
3310  rotation = rotation & 3;
3311  if (charRotation != rotation)
3312  {
3313  /* Store rotation */
3314  charRotation = rotation;
3315 
3316  /* Maybe flip width/height for rendering */
3317  if ((charRotation==1) || (charRotation==3))
3318  {
3319  charWidthLocal = charHeight;
3320  charHeightLocal = charWidth;
3321  }
3322  else
3323  {
3324  charWidthLocal = charWidth;
3325  charHeightLocal = charHeight;
3326  }
3327 
3328  /* Clear character cache */
3329  for (i = 0; i < 256; i++) {
3330  if (gfxPrimitivesFont[i]) {
3331  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3332  gfxPrimitivesFont[i] = NULL;
3333  }
3334  }
3335  }
3336 }
3337 
3352 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3353 {
3354  SDL_Rect srect;
3355  SDL_Rect drect;
3356  int result;
3357  Uint32 ix, iy;
3358  const unsigned char *charpos;
3359  Uint8 *curpos;
3360  Uint8 patt, mask;
3361  Uint8 *linepos;
3362  Uint32 pitch;
3363  SDL_Surface *character;
3364  SDL_Surface *rotatedCharacter;
3365  Uint32 ci;
3366 
3367  /*
3368  * Setup source rectangle
3369  */
3370  srect.x = 0;
3371  srect.y = 0;
3372  srect.w = charWidthLocal;
3373  srect.h = charHeightLocal;
3374 
3375  /*
3376  * Setup destination rectangle
3377  */
3378  drect.x = x;
3379  drect.y = y;
3380  drect.w = charWidthLocal;
3381  drect.h = charHeightLocal;
3382 
3383  /* Character index in cache */
3384  ci = (unsigned char) c;
3385 
3386  /*
3387  * Create new charWidth x charHeight bitmap surface if not already present.
3388  * Might get rotated later.
3389  */
3390  if (gfxPrimitivesFont[ci] == NULL) {
3391  /*
3392  * Redraw character into surface
3393  */
3394  character = SDL_CreateRGBSurface(SDL_SWSURFACE,
3395  charWidth, charHeight, 32,
3396  0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
3397  if (character == NULL) {
3398  return (-1);
3399  }
3400 
3401  charpos = currentFontdata + ci * charSize;
3402  linepos = (Uint8 *)character->pixels;
3403  pitch = character->pitch;
3404 
3405  /*
3406  * Drawing loop
3407  */
3408  patt = 0;
3409  for (iy = 0; iy < charHeight; iy++) {
3410  mask = 0x00;
3411  curpos = linepos;
3412  for (ix = 0; ix < charWidth; ix++) {
3413  if (!(mask >>= 1)) {
3414  patt = *charpos++;
3415  mask = 0x80;
3416  }
3417  if (patt & mask) {
3418  *(Uint32 *)curpos = 0xffffffff;
3419  } else {
3420  *(Uint32 *)curpos = 0;
3421  }
3422  curpos += 4;
3423  }
3424  linepos += pitch;
3425  }
3426 
3427  /* Maybe rotate and replace cached image */
3428  if (charRotation>0)
3429  {
3430  rotatedCharacter = rotateSurface90Degrees(character, charRotation);
3431  SDL_FreeSurface(character);
3432  character = rotatedCharacter;
3433  }
3434 
3435  /* Convert temp surface into texture */
3436  gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
3437  SDL_FreeSurface(character);
3438 
3439  /*
3440  * Check pointer
3441  */
3442  if (gfxPrimitivesFont[ci] == NULL) {
3443  return (-1);
3444  }
3445  }
3446 
3447  /*
3448  * Set color
3449  */
3450  result = 0;
3451  result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
3452  result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
3453 
3454  /*
3455  * Draw texture onto destination
3456  */
3457  result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
3458 
3459  return (result);
3460 }
3461 
3462 
3474 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
3475 {
3476  Uint8 *co = (Uint8 *)&color;
3477  return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
3478 }
3479 
3480 
3495 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
3496 {
3497  Uint8 *c = (Uint8 *)&color;
3498  return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
3499 }
3500 
3515 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3516 {
3517  int result = 0;
3518  Sint16 curx = x;
3519  Sint16 cury = y;
3520  const char *curchar = s;
3521 
3522  while (*curchar && !result) {
3523  result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
3524  switch (charRotation)
3525  {
3526  case 0:
3527  curx += charWidthLocal;
3528  break;
3529  case 2:
3530  curx -= charWidthLocal;
3531  break;
3532  case 1:
3533  cury += charHeightLocal;
3534  break;
3535  case 3:
3536  cury -= charHeightLocal;
3537  break;
3538  }
3539  curchar++;
3540  }
3541 
3542  return (result);
3543 }
3544 
3545 /* ---- Bezier curve */
3546 
3556 double _evaluateBezier (double *data, int ndata, double t)
3557 {
3558  double mu, result;
3559  int n,k,kn,nn,nkn;
3560  double blend,muk,munk;
3561 
3562  /* Sanity check bounds */
3563  if (t<0.0) {
3564  return(data[0]);
3565  }
3566  if (t>=(double)ndata) {
3567  return(data[ndata-1]);
3568  }
3569 
3570  /* Adjust t to the range 0.0 to 1.0 */
3571  mu=t/(double)ndata;
3572 
3573  /* Calculate interpolate */
3574  n=ndata-1;
3575  result=0.0;
3576  muk = 1;
3577  munk = pow(1-mu,(double)n);
3578  for (k=0;k<=n;k++) {
3579  nn = n;
3580  kn = k;
3581  nkn = n - k;
3582  blend = muk * munk;
3583  muk *= mu;
3584  munk /= (1-mu);
3585  while (nn >= 1) {
3586  blend *= nn;
3587  nn--;
3588  if (kn > 1) {
3589  blend /= (double)kn;
3590  kn--;
3591  }
3592  if (nkn > 1) {
3593  blend /= (double)nkn;
3594  nkn--;
3595  }
3596  }
3597  result += data[k] * blend;
3598  }
3599 
3600  return (result);
3601 }
3602 
3615 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
3616 {
3617  Uint8 *c = (Uint8 *)&color;
3618  return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
3619 }
3620 
3636 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3637 {
3638  int result;
3639  int i;
3640  double *x, *y, t, stepsize;
3641  Sint16 x1, y1, x2, y2;
3642 
3643  /*
3644  * Sanity check
3645  */
3646  if (n < 3) {
3647  return (-1);
3648  }
3649  if (s < 2) {
3650  return (-1);
3651  }
3652 
3653  /*
3654  * Variable setup
3655  */
3656  stepsize=(double)1.0/(double)s;
3657 
3658  /* Transfer vertices into float arrays */
3659  if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3660  return(-1);
3661  }
3662  if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3663  free(x);
3664  return(-1);
3665  }
3666  for (i=0; i<n; i++) {
3667  x[i]=(double)vx[i];
3668  y[i]=(double)vy[i];
3669  }
3670  x[n]=(double)vx[0];
3671  y[n]=(double)vy[0];
3672 
3673  /*
3674  * Set color
3675  */
3676  result = 0;
3677  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
3678  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
3679 
3680  /*
3681  * Draw
3682  */
3683  t=0.0;
3684  x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
3685  y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
3686  for (i = 0; i <= (n*s); i++) {
3687  t += stepsize;
3688  x2=(Sint16)_evaluateBezier(x,n,t);
3689  y2=(Sint16)_evaluateBezier(y,n,t);
3690  result |= line(renderer, x1, y1, x2, y2);
3691  x1 = x2;
3692  y1 = y2;
3693  }
3694 
3695  /* Clean up temporary array */
3696  free(x);
3697  free(y);
3698 
3699  return (result);
3700 }
3701 
3702 
3716 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
3717 {
3718  Uint8 *c = (Uint8 *)&color;
3719  return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
3720 }
3721 
3738 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3739 {
3740  int wh;
3741  double dx, dy, dx1, dy1, dx2, dy2;
3742  double l, wl2, nx, ny, ang, adj;
3743  Sint16 px[4], py[4];
3744 
3745  if (renderer == NULL) {
3746  return -1;
3747  }
3748 
3749  if (width < 1) {
3750  return -1;
3751  }
3752 
3753  /* Special case: thick "point" */
3754  if ((x1 == x2) && (y1 == y2)) {
3755  wh = width / 2;
3756  return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
3757  }
3758 
3759  /* Special case: width == 1 */
3760  if (width == 1) {
3761  return lineRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
3762  }
3763 
3764  /* Calculate offsets for sides */
3765  dx = (double)(x2 - x1);
3766  dy = (double)(y2 - y1);
3767  l = SDL_sqrt(dx*dx + dy*dy);
3768  ang = SDL_atan2(dx, dy);
3769  adj = 0.1 + 0.9 * SDL_fabs(SDL_cos(2.0 * ang));
3770  wl2 = ((double)width - adj)/(2.0 * l);
3771  nx = dx * wl2;
3772  ny = dy * wl2;
3773 
3774  /* Build polygon */
3775  dx1 = (double)x1;
3776  dy1 = (double)y1;
3777  dx2 = (double)x2;
3778  dy2 = (double)y2;
3779  px[0] = (Sint16)(dx1 + ny);
3780  px[1] = (Sint16)(dx1 - ny);
3781  px[2] = (Sint16)(dx2 - ny);
3782  px[3] = (Sint16)(dx2 + ny);
3783  py[0] = (Sint16)(dy1 - nx);
3784  py[1] = (Sint16)(dy1 + nx);
3785  py[2] = (Sint16)(dy2 + nx);
3786  py[3] = (Sint16)(dy2 - nx);
3787 
3788  /* Draw polygon */
3789  return filledPolygonRGBA(renderer, px, py, 4, r, g, b, a);
3790 }
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.
int line(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
Draw line with alpha blending using the currently set color.
int _drawQuadrants(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 dx, Sint16 dy, Sint32 f)
Internal function to draw pixels or lines in 4 quadrants.
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 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.
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.
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 _ellipseRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Sint32 f)
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 vline(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2)
Draw vertical line in currently set color.
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.
#define ELLIPSE_OVERSCAN
Internal function to draw ellipse or filled ellipse with 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.