SDL2_gfx  1.0.2
Graphics primitives and surface functions for SDL2
/build/libsdl2-gfx-F3NxcE/libsdl2-gfx-1.0.4+dfsg/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 boxRGBA(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+(xdir*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 DEFAULT_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 rxi, ryi;
1534  Sint32 rx2, ry2, rx22, ry22;
1535  Sint32 error;
1536  Sint32 curX, curY, curXp1, curYm1;
1537  Sint32 scrX, scrY, oldX, oldY;
1538  Sint32 deltaX, deltaY;
1539  Sint32 ellipseOverscan;
1540 
1541  /*
1542  * Sanity check radii
1543  */
1544  if ((rx < 0) || (ry < 0)) {
1545  return (-1);
1546  }
1547 
1548  /*
1549  * Set color
1550  */
1551  result = 0;
1552  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1553  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
1554 
1555  /*
1556  * Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
1557  */
1558  if (rx == 0) {
1559  if (ry == 0) {
1560  return (pixel(renderer, x, y));
1561  } else {
1562  return (vline(renderer, x, y - ry, y + ry));
1563  }
1564  } else {
1565  if (ry == 0) {
1566  return (hline(renderer, x - rx, x + rx, y));
1567  }
1568  }
1569 
1570  /*
1571  * Adjust overscan
1572  */
1573  rxi = rx;
1574  ryi = ry;
1575  if (rxi >= 512 || ryi >= 512)
1576  {
1577  ellipseOverscan = DEFAULT_ELLIPSE_OVERSCAN / 4;
1578  }
1579  else if (rxi >= 256 || ryi >= 256)
1580  {
1581  ellipseOverscan = DEFAULT_ELLIPSE_OVERSCAN / 2;
1582  }
1583  else
1584  {
1585  ellipseOverscan = DEFAULT_ELLIPSE_OVERSCAN / 1;
1586  }
1587 
1588  /*
1589  * Top/bottom center points.
1590  */
1591  oldX = scrX = 0;
1592  oldY = scrY = ryi;
1593  result |= _drawQuadrants(renderer, x, y, 0, ry, f);
1594 
1595  /* Midpoint ellipse algorithm with overdraw */
1596  rxi *= ellipseOverscan;
1597  ryi *= ellipseOverscan;
1598  rx2 = rxi * rxi;
1599  rx22 = rx2 + rx2;
1600  ry2 = ryi * ryi;
1601  ry22 = ry2 + ry2;
1602  curX = 0;
1603  curY = ryi;
1604  deltaX = 0;
1605  deltaY = rx22 * curY;
1606 
1607  /* Points in segment 1 */
1608  error = ry2 - rx2 * ryi + rx2 / 4;
1609  while (deltaX <= deltaY)
1610  {
1611  curX++;
1612  deltaX += ry22;
1613 
1614  error += deltaX + ry2;
1615  if (error >= 0)
1616  {
1617  curY--;
1618  deltaY -= rx22;
1619  error -= deltaY;
1620  }
1621 
1622  scrX = curX / ellipseOverscan;
1623  scrY = curY / ellipseOverscan;
1624  if ((scrX != oldX && scrY == oldY) || (scrX != oldX && scrY != oldY)) {
1625  result |= _drawQuadrants(renderer, x, y, scrX, scrY, f);
1626  oldX = scrX;
1627  oldY = scrY;
1628  }
1629  }
1630 
1631  /* Points in segment 2 */
1632  if (curY > 0)
1633  {
1634  curXp1 = curX + 1;
1635  curYm1 = curY - 1;
1636  error = ry2 * curX * curXp1 + ((ry2 + 3) / 4) + rx2 * curYm1 * curYm1 - rx2 * ry2;
1637  while (curY > 0)
1638  {
1639  curY--;
1640  deltaY -= rx22;
1641 
1642  error += rx2;
1643  error -= deltaY;
1644 
1645  if (error <= 0)
1646  {
1647  curX++;
1648  deltaX += ry22;
1649  error += deltaX;
1650  }
1651 
1652  scrX = curX / ellipseOverscan;
1653  scrY = curY / ellipseOverscan;
1654  if ((scrX != oldX && scrY == oldY) || (scrX != oldX && scrY != oldY)) {
1655  oldY--;
1656  for (;oldY >= scrY; oldY--) {
1657  result |= _drawQuadrants(renderer, x, y, scrX, oldY, f);
1658  /* prevent overdraw */
1659  if (f) {
1660  oldY = scrY - 1;
1661  }
1662  }
1663  oldX = scrX;
1664  oldY = scrY;
1665  }
1666  }
1667 
1668  /* Remaining points in vertical */
1669  if (!f) {
1670  oldY--;
1671  for (;oldY >= 0; oldY--) {
1672  result |= _drawQuadrants(renderer, x, y, scrX, oldY, f);
1673  }
1674  }
1675  }
1676 
1677  return (result);
1678 }
1679 
1692 int ellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1693 {
1694  Uint8 *c = (Uint8 *)&color;
1695  return _ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3], 0);
1696 }
1697 
1713 int ellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1714 {
1715  return _ellipseRGBA(renderer, x, y, rx, ry, r, g, b, a, 0);
1716 }
1717 
1718 /* ----- Filled Circle */
1719 
1731 int filledCircleColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
1732 {
1733  Uint8 *c = (Uint8 *)&color;
1734  return filledEllipseRGBA(renderer, x, y, rad, rad, c[0], c[1], c[2], c[3]);
1735 }
1736 
1751 int filledCircleRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1752 {
1753  return _ellipseRGBA(renderer, x, y, rad, rad, r, g ,b, a, 1);
1754 }
1755 
1756 
1757 /* ----- AA Ellipse */
1758 
1759 /* Windows targets do not have lrint, so provide a local inline version */
1760 #if defined(_MSC_VER)
1761 /* Detect 64bit and use intrinsic version */
1762 #ifdef _M_X64
1763 #include <emmintrin.h>
1764 static __inline long
1765  lrint(float f)
1766 {
1767  return _mm_cvtss_si32(_mm_load_ss(&f));
1768 }
1769 #elif defined(_M_IX86)
1770 __inline long int
1771  lrint (double flt)
1772 {
1773  int intgr;
1774  _asm
1775  {
1776  fld flt
1777  fistp intgr
1778  };
1779  return intgr;
1780 }
1781 #elif defined(_M_ARM)
1782 #include <armintr.h>
1783 #pragma warning(push)
1784 #pragma warning(disable: 4716)
1785 __declspec(naked) long int
1786  lrint (double flt)
1787 {
1788  __emit(0xEC410B10); // fmdrr d0, r0, r1
1789  __emit(0xEEBD0B40); // ftosid s0, d0
1790  __emit(0xEE100A10); // fmrs r0, s0
1791  __emit(0xE12FFF1E); // bx lr
1792 }
1793 #pragma warning(pop)
1794 #else
1795 #error lrint needed for MSVC on non X86/AMD64/ARM targets.
1796 #endif
1797 #endif
1798 
1811 int aaellipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
1812 {
1813  Uint8 *c = (Uint8 *)&color;
1814  return aaellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3]);
1815 }
1816 
1832 int aaellipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
1833 {
1834  int result;
1835  int i;
1836  int a2, b2, ds, dt, dxt, t, s, d;
1837  Sint16 xp, yp, xs, ys, dyt, od, xx, yy, xc2, yc2;
1838  float cp;
1839  double sab;
1840  Uint8 weight, iweight;
1841 
1842  /*
1843  * Sanity check radii
1844  */
1845  if ((rx < 0) || (ry < 0)) {
1846  return (-1);
1847  }
1848 
1849  /*
1850  * Special cases for rx=0 and/or ry=0: draw a hline/vline/pixel
1851  */
1852  if (rx == 0) {
1853  if (ry == 0) {
1854  return (pixelRGBA(renderer, x, y, r, g, b, a));
1855  } else {
1856  return (vlineRGBA(renderer, x, y - ry, y + ry, r, g, b, a));
1857  }
1858  } else {
1859  if (ry == 0) {
1860  return (hlineRGBA(renderer, x - rx, x + rx, y, r, g, b, a));
1861  }
1862  }
1863 
1864  /* Variable setup */
1865  a2 = rx * rx;
1866  b2 = ry * ry;
1867 
1868  ds = 2 * a2;
1869  dt = 2 * b2;
1870 
1871  xc2 = 2 * x;
1872  yc2 = 2 * y;
1873 
1874  sab = sqrt((double)(a2 + b2));
1875  od = (Sint16)lrint(sab*0.01) + 1; /* introduce some overdraw */
1876  dxt = (Sint16)lrint((double)a2 / sab) + od;
1877 
1878  t = 0;
1879  s = -2 * a2 * ry;
1880  d = 0;
1881 
1882  xp = x;
1883  yp = y - ry;
1884 
1885  /* Draw */
1886  result = 0;
1887  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
1888 
1889  /* "End points" */
1890  result |= pixelRGBA(renderer, xp, yp, r, g, b, a);
1891  result |= pixelRGBA(renderer, xc2 - xp, yp, r, g, b, a);
1892  result |= pixelRGBA(renderer, xp, yc2 - yp, r, g, b, a);
1893  result |= pixelRGBA(renderer, xc2 - xp, yc2 - yp, r, g, b, a);
1894 
1895  for (i = 1; i <= dxt; i++) {
1896  xp--;
1897  d += t - b2;
1898 
1899  if (d >= 0)
1900  ys = yp - 1;
1901  else if ((d - s - a2) > 0) {
1902  if ((2 * d - s - a2) >= 0)
1903  ys = yp + 1;
1904  else {
1905  ys = yp;
1906  yp++;
1907  d -= s + a2;
1908  s += ds;
1909  }
1910  } else {
1911  yp++;
1912  ys = yp + 1;
1913  d -= s + a2;
1914  s += ds;
1915  }
1916 
1917  t -= dt;
1918 
1919  /* Calculate alpha */
1920  if (s != 0) {
1921  cp = (float) abs(d) / (float) abs(s);
1922  if (cp > 1.0) {
1923  cp = 1.0;
1924  }
1925  } else {
1926  cp = 1.0;
1927  }
1928 
1929  /* Calculate weights */
1930  weight = (Uint8) (cp * 255);
1931  iweight = 255 - weight;
1932 
1933  /* Upper half */
1934  xx = xc2 - xp;
1935  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1936  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1937 
1938  result |= pixelRGBAWeight(renderer, xp, ys, r, g, b, a, weight);
1939  result |= pixelRGBAWeight(renderer, xx, ys, r, g, b, a, weight);
1940 
1941  /* Lower half */
1942  yy = yc2 - yp;
1943  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1944  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
1945 
1946  yy = yc2 - ys;
1947  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, weight);
1948  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
1949  }
1950 
1951  /* Replaces original approximation code dyt = abs(yp - yc); */
1952  dyt = (Sint16)lrint((double)b2 / sab ) + od;
1953 
1954  for (i = 1; i <= dyt; i++) {
1955  yp++;
1956  d -= s + a2;
1957 
1958  if (d <= 0)
1959  xs = xp + 1;
1960  else if ((d + t - b2) < 0) {
1961  if ((2 * d + t - b2) <= 0)
1962  xs = xp - 1;
1963  else {
1964  xs = xp;
1965  xp--;
1966  d += t - b2;
1967  t -= dt;
1968  }
1969  } else {
1970  xp--;
1971  xs = xp - 1;
1972  d += t - b2;
1973  t -= dt;
1974  }
1975 
1976  s += ds;
1977 
1978  /* Calculate alpha */
1979  if (t != 0) {
1980  cp = (float) abs(d) / (float) abs(t);
1981  if (cp > 1.0) {
1982  cp = 1.0;
1983  }
1984  } else {
1985  cp = 1.0;
1986  }
1987 
1988  /* Calculate weight */
1989  weight = (Uint8) (cp * 255);
1990  iweight = 255 - weight;
1991 
1992  /* Left half */
1993  xx = xc2 - xp;
1994  yy = yc2 - yp;
1995  result |= pixelRGBAWeight(renderer, xp, yp, r, g, b, a, iweight);
1996  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, iweight);
1997 
1998  result |= pixelRGBAWeight(renderer, xp, yy, r, g, b, a, iweight);
1999  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, iweight);
2000 
2001  /* Right half */
2002  xx = xc2 - xs;
2003  result |= pixelRGBAWeight(renderer, xs, yp, r, g, b, a, weight);
2004  result |= pixelRGBAWeight(renderer, xx, yp, r, g, b, a, weight);
2005 
2006  result |= pixelRGBAWeight(renderer, xs, yy, r, g, b, a, weight);
2007  result |= pixelRGBAWeight(renderer, xx, yy, r, g, b, a, weight);
2008  }
2009 
2010  return (result);
2011 }
2012 
2013 /* ---- Filled Ellipse */
2014 
2027 int filledEllipseColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
2028 {
2029  Uint8 *c = (Uint8 *)&color;
2030  return _ellipseRGBA(renderer, x, y, rx, ry, c[0], c[1], c[2], c[3], 1);
2031 }
2032 
2048 int filledEllipseRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2049 {
2050  return _ellipseRGBA(renderer, x, y, rx, ry, r, g, b, a, 1);
2051 }
2052 
2053 /* ----- Pie */
2054 
2074 /* TODO: rewrite algorithm; pie is not always accurate */
2075 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)
2076 {
2077  int result;
2078  double angle, start_angle, end_angle;
2079  double deltaAngle;
2080  double dr;
2081  int numpoints, i;
2082  Sint16 *vx, *vy;
2083 
2084  /*
2085  * Sanity check radii
2086  */
2087  if (rad < 0) {
2088  return (-1);
2089  }
2090 
2091  /*
2092  * Fixup angles
2093  */
2094  start = start % 360;
2095  end = end % 360;
2096 
2097  /*
2098  * Special case for rad=0 - draw a point
2099  */
2100  if (rad == 0) {
2101  return (pixelRGBA(renderer, x, y, r, g, b, a));
2102  }
2103 
2104  /*
2105  * Variable setup
2106  */
2107  dr = (double) rad;
2108  deltaAngle = 3.0 / dr;
2109  start_angle = (double) start *(2.0 * M_PI / 360.0);
2110  end_angle = (double) end *(2.0 * M_PI / 360.0);
2111  if (start > end) {
2112  end_angle += (2.0 * M_PI);
2113  }
2114 
2115  /* We will always have at least 2 points */
2116  numpoints = 2;
2117 
2118  /* Count points (rather than calculating it) */
2119  angle = start_angle;
2120  while (angle < end_angle) {
2121  angle += deltaAngle;
2122  numpoints++;
2123  }
2124 
2125  /* Allocate combined vertex array */
2126  vx = vy = (Sint16 *) malloc(2 * sizeof(Uint16) * numpoints);
2127  if (vx == NULL) {
2128  return (-1);
2129  }
2130 
2131  /* Update point to start of vy */
2132  vy += numpoints;
2133 
2134  /* Center */
2135  vx[0] = x;
2136  vy[0] = y;
2137 
2138  /* First vertex */
2139  angle = start_angle;
2140  vx[1] = x + (int) (dr * cos(angle));
2141  vy[1] = y + (int) (dr * sin(angle));
2142 
2143  if (numpoints<3)
2144  {
2145  result = lineRGBA(renderer, vx[0], vy[0], vx[1], vy[1], r, g, b, a);
2146  }
2147  else
2148  {
2149  /* Calculate other vertices */
2150  i = 2;
2151  angle = start_angle;
2152  while (angle < end_angle) {
2153  angle += deltaAngle;
2154  if (angle>end_angle)
2155  {
2156  angle = end_angle;
2157  }
2158  vx[i] = x + (int) (dr * cos(angle));
2159  vy[i] = y + (int) (dr * sin(angle));
2160  i++;
2161  }
2162 
2163  /* Draw */
2164  if (filled) {
2165  result = filledPolygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2166  } else {
2167  result = polygonRGBA(renderer, vx, vy, numpoints, r, g, b, a);
2168  }
2169  }
2170 
2171  /* Free combined vertex array */
2172  free(vx);
2173 
2174  return (result);
2175 }
2176 
2190 int pieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2191  Sint16 start, Sint16 end, Uint32 color)
2192 {
2193  Uint8 *c = (Uint8 *)&color;
2194  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 0);
2195 }
2196 
2213 int pieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2214  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2215 {
2216  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 0);
2217 }
2218 
2232 int filledPieColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
2233 {
2234  Uint8 *c = (Uint8 *)&color;
2235  return _pieRGBA(renderer, x, y, rad, start, end, c[0], c[1], c[2], c[3], 1);
2236 }
2237 
2254 int filledPieRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, Sint16 rad,
2255  Sint16 start, Sint16 end, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2256 {
2257  return _pieRGBA(renderer, x, y, rad, start, end, r, g, b, a, 1);
2258 }
2259 
2260 /* ------ Trigon */
2261 
2278 int trigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2279 {
2280  Sint16 vx[3];
2281  Sint16 vy[3];
2282 
2283  vx[0]=x1;
2284  vx[1]=x2;
2285  vx[2]=x3;
2286  vy[0]=y1;
2287  vy[1]=y2;
2288  vy[2]=y3;
2289 
2290  return(polygonColor(renderer,vx,vy,3,color));
2291 }
2292 
2310 int trigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2311  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2312 {
2313  Sint16 vx[3];
2314  Sint16 vy[3];
2315 
2316  vx[0]=x1;
2317  vx[1]=x2;
2318  vx[2]=x3;
2319  vy[0]=y1;
2320  vy[1]=y2;
2321  vy[2]=y3;
2322 
2323  return(polygonRGBA(renderer,vx,vy,3,r,g,b,a));
2324 }
2325 
2326 /* ------ AA-Trigon */
2327 
2344 int aatrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2345 {
2346  Sint16 vx[3];
2347  Sint16 vy[3];
2348 
2349  vx[0]=x1;
2350  vx[1]=x2;
2351  vx[2]=x3;
2352  vy[0]=y1;
2353  vy[1]=y2;
2354  vy[2]=y3;
2355 
2356  return(aapolygonColor(renderer,vx,vy,3,color));
2357 }
2358 
2376 int aatrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2377  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2378 {
2379  Sint16 vx[3];
2380  Sint16 vy[3];
2381 
2382  vx[0]=x1;
2383  vx[1]=x2;
2384  vx[2]=x3;
2385  vy[0]=y1;
2386  vy[1]=y2;
2387  vy[2]=y3;
2388 
2389  return(aapolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2390 }
2391 
2392 /* ------ Filled Trigon */
2393 
2410 int filledTrigonColor(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3, Uint32 color)
2411 {
2412  Sint16 vx[3];
2413  Sint16 vy[3];
2414 
2415  vx[0]=x1;
2416  vx[1]=x2;
2417  vx[2]=x3;
2418  vy[0]=y1;
2419  vy[1]=y2;
2420  vy[2]=y3;
2421 
2422  return(filledPolygonColor(renderer,vx,vy,3,color));
2423 }
2424 
2444 int filledTrigonRGBA(SDL_Renderer * renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Sint16 x3, Sint16 y3,
2445  Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2446 {
2447  Sint16 vx[3];
2448  Sint16 vy[3];
2449 
2450  vx[0]=x1;
2451  vx[1]=x2;
2452  vx[2]=x3;
2453  vy[0]=y1;
2454  vy[1]=y2;
2455  vy[2]=y3;
2456 
2457  return(filledPolygonRGBA(renderer,vx,vy,3,r,g,b,a));
2458 }
2459 
2460 /* ---- Polygon */
2461 
2473 int polygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2474 {
2475  Uint8 *c = (Uint8 *)&color;
2476  return polygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2477 }
2478 
2489 int polygon(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n)
2490 {
2491  /*
2492  * Draw
2493  */
2494  int result = 0;
2495  int i, nn;
2496  SDL_Point* points;
2497 
2498  /*
2499  * Vertex array NULL check
2500  */
2501  if (vx == NULL) {
2502  return (-1);
2503  }
2504  if (vy == NULL) {
2505  return (-1);
2506  }
2507 
2508  /*
2509  * Sanity check
2510  */
2511  if (n < 3) {
2512  return (-1);
2513  }
2514 
2515  /*
2516  * Create array of points
2517  */
2518  nn = n + 1;
2519  points = (SDL_Point*)malloc(sizeof(SDL_Point) * nn);
2520  if (points == NULL)
2521  {
2522  return -1;
2523  }
2524  for (i=0; i<n; i++)
2525  {
2526  points[i].x = vx[i];
2527  points[i].y = vy[i];
2528  }
2529  points[n].x = vx[0];
2530  points[n].y = vy[0];
2531 
2532  /*
2533  * Draw
2534  */
2535  result |= SDL_RenderDrawLines(renderer, points, nn);
2536  free(points);
2537 
2538  return (result);
2539 }
2540 
2555 int polygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2556 {
2557  /*
2558  * Draw
2559  */
2560  int result;
2561  const Sint16 *x1, *y1, *x2, *y2;
2562 
2563  /*
2564  * Vertex array NULL check
2565  */
2566  if (vx == NULL) {
2567  return (-1);
2568  }
2569  if (vy == NULL) {
2570  return (-1);
2571  }
2572 
2573  /*
2574  * Sanity check
2575  */
2576  if (n < 3) {
2577  return (-1);
2578  }
2579 
2580  /*
2581  * Pointer setup
2582  */
2583  x1 = x2 = vx;
2584  y1 = y2 = vy;
2585  x2++;
2586  y2++;
2587 
2588  /*
2589  * Set color
2590  */
2591  result = 0;
2592  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2593  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2594 
2595  /*
2596  * Draw
2597  */
2598  result |= polygon(renderer, vx, vy, n);
2599 
2600  return (result);
2601 }
2602 
2603 /* ---- AA-Polygon */
2604 
2616 int aapolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2617 {
2618  Uint8 *c = (Uint8 *)&color;
2619  return aapolygonRGBA(renderer, vx, vy, n, c[0], c[1], c[2], c[3]);
2620 }
2621 
2636 int aapolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2637 {
2638  int result;
2639  int i;
2640  const Sint16 *x1, *y1, *x2, *y2;
2641 
2642  /*
2643  * Vertex array NULL check
2644  */
2645  if (vx == NULL) {
2646  return (-1);
2647  }
2648  if (vy == NULL) {
2649  return (-1);
2650  }
2651 
2652  /*
2653  * Sanity check
2654  */
2655  if (n < 3) {
2656  return (-1);
2657  }
2658 
2659  /*
2660  * Pointer setup
2661  */
2662  x1 = x2 = vx;
2663  y1 = y2 = vy;
2664  x2++;
2665  y2++;
2666 
2667  /*
2668  * Draw
2669  */
2670  result = 0;
2671  for (i = 1; i < n; i++) {
2672  result |= _aalineRGBA(renderer, *x1, *y1, *x2, *y2, r, g, b, a, 0);
2673  x1 = x2;
2674  y1 = y2;
2675  x2++;
2676  y2++;
2677  }
2678 
2679  result |= _aalineRGBA(renderer, *x1, *y1, *vx, *vy, r, g, b, a, 0);
2680 
2681  return (result);
2682 }
2683 
2684 /* ---- Filled Polygon */
2685 
2694 int _gfxPrimitivesCompareInt(const void *a, const void *b)
2695 {
2696  return (*(const int *) a) - (*(const int *) b);
2697 }
2698 
2704 static int *gfxPrimitivesPolyIntsGlobal = NULL;
2705 
2711 static int gfxPrimitivesPolyAllocatedGlobal = 0;
2712 
2731 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)
2732 {
2733  int result;
2734  int i;
2735  int y, xa, xb;
2736  int miny, maxy;
2737  int x1, y1;
2738  int x2, y2;
2739  int ind1, ind2;
2740  int ints;
2741  int *gfxPrimitivesPolyInts = NULL;
2742  int *gfxPrimitivesPolyIntsNew = NULL;
2743  int gfxPrimitivesPolyAllocated = 0;
2744 
2745  /*
2746  * Vertex array NULL check
2747  */
2748  if (vx == NULL) {
2749  return (-1);
2750  }
2751  if (vy == NULL) {
2752  return (-1);
2753  }
2754 
2755  /*
2756  * Sanity check number of edges
2757  */
2758  if (n < 3) {
2759  return -1;
2760  }
2761 
2762  /*
2763  * Map polygon cache
2764  */
2765  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2766  /* Use global cache */
2767  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
2768  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
2769  } else {
2770  /* Use local cache */
2771  gfxPrimitivesPolyInts = *polyInts;
2772  gfxPrimitivesPolyAllocated = *polyAllocated;
2773  }
2774 
2775  /*
2776  * Allocate temp array, only grow array
2777  */
2778  if (!gfxPrimitivesPolyAllocated) {
2779  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
2780  gfxPrimitivesPolyAllocated = n;
2781  } else {
2782  if (gfxPrimitivesPolyAllocated < n) {
2783  gfxPrimitivesPolyIntsNew = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
2784  if (!gfxPrimitivesPolyIntsNew) {
2785  if (!gfxPrimitivesPolyInts) {
2786  free(gfxPrimitivesPolyInts);
2787  gfxPrimitivesPolyInts = NULL;
2788  }
2789  gfxPrimitivesPolyAllocated = 0;
2790  } else {
2791  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsNew;
2792  gfxPrimitivesPolyAllocated = n;
2793  }
2794  }
2795  }
2796 
2797  /*
2798  * Check temp array
2799  */
2800  if (gfxPrimitivesPolyInts==NULL) {
2801  gfxPrimitivesPolyAllocated = 0;
2802  }
2803 
2804  /*
2805  * Update cache variables
2806  */
2807  if ((polyInts==NULL) || (polyAllocated==NULL)) {
2808  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
2809  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
2810  } else {
2811  *polyInts = gfxPrimitivesPolyInts;
2812  *polyAllocated = gfxPrimitivesPolyAllocated;
2813  }
2814 
2815  /*
2816  * Check temp array again
2817  */
2818  if (gfxPrimitivesPolyInts==NULL) {
2819  return(-1);
2820  }
2821 
2822  /*
2823  * Determine Y maxima
2824  */
2825  miny = vy[0];
2826  maxy = vy[0];
2827  for (i = 1; (i < n); i++) {
2828  if (vy[i] < miny) {
2829  miny = vy[i];
2830  } else if (vy[i] > maxy) {
2831  maxy = vy[i];
2832  }
2833  }
2834 
2835  /*
2836  * Draw, scanning y
2837  */
2838  result = 0;
2839  for (y = miny; (y <= maxy); y++) {
2840  ints = 0;
2841  for (i = 0; (i < n); i++) {
2842  if (!i) {
2843  ind1 = n - 1;
2844  ind2 = 0;
2845  } else {
2846  ind1 = i - 1;
2847  ind2 = i;
2848  }
2849  y1 = vy[ind1];
2850  y2 = vy[ind2];
2851  if (y1 < y2) {
2852  x1 = vx[ind1];
2853  x2 = vx[ind2];
2854  } else if (y1 > y2) {
2855  y2 = vy[ind1];
2856  y1 = vy[ind2];
2857  x2 = vx[ind1];
2858  x1 = vx[ind2];
2859  } else {
2860  continue;
2861  }
2862  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
2863  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
2864  }
2865  }
2866 
2867  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
2868 
2869  /*
2870  * Set color
2871  */
2872  result = 0;
2873  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
2874  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
2875 
2876  for (i = 0; (i < ints); i += 2) {
2877  xa = gfxPrimitivesPolyInts[i] + 1;
2878  xa = (xa >> 16) + ((xa & 32768) >> 15);
2879  xb = gfxPrimitivesPolyInts[i+1] - 1;
2880  xb = (xb >> 16) + ((xb & 32768) >> 15);
2881  result |= hline(renderer, xa, xb, y);
2882  }
2883  }
2884 
2885  return (result);
2886 }
2887 
2899 int filledPolygonColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint32 color)
2900 {
2901  Uint8 *c = (Uint8 *)&color;
2902  return filledPolygonRGBAMT(renderer, vx, vy, n, c[0], c[1], c[2], c[3], NULL, NULL);
2903 }
2904 
2919 int filledPolygonRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
2920 {
2921  return filledPolygonRGBAMT(renderer, vx, vy, n, r, g, b, a, NULL, NULL);
2922 }
2923 
2924 /* ---- Textured Polygon */
2925 
2941 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)
2942 {
2943  Sint16 w;
2944  Sint16 xtmp;
2945  int result = 0;
2946  int texture_x_walker;
2947  int texture_y_start;
2948  SDL_Rect source_rect,dst_rect;
2949  int pixels_written,write_width;
2950 
2951  /*
2952  * Swap x1, x2 if required to ensure x1<=x2
2953  */
2954  if (x1 > x2) {
2955  xtmp = x1;
2956  x1 = x2;
2957  x2 = xtmp;
2958  }
2959 
2960  /*
2961  * Calculate width to draw
2962  */
2963  w = x2 - x1 + 1;
2964 
2965  /*
2966  * Determine where in the texture we start drawing
2967  */
2968  texture_x_walker = (x1 - texture_dx) % texture_w;
2969  if (texture_x_walker < 0){
2970  texture_x_walker = texture_w + texture_x_walker ;
2971  }
2972 
2973  texture_y_start = (y + texture_dy) % texture_h;
2974  if (texture_y_start < 0){
2975  texture_y_start = texture_h + texture_y_start;
2976  }
2977 
2978  /* setup the source rectangle; we are only drawing one horizontal line */
2979  source_rect.y = texture_y_start;
2980  source_rect.x = texture_x_walker;
2981  source_rect.h = 1;
2982 
2983  /* we will draw to the current y */
2984  dst_rect.y = y;
2985  dst_rect.h = 1;
2986 
2987  /* if there are enough pixels left in the current row of the texture */
2988  /* draw it all at once */
2989  if (w <= texture_w -texture_x_walker){
2990  source_rect.w = w;
2991  source_rect.x = texture_x_walker;
2992  dst_rect.x= x1;
2993  dst_rect.w = source_rect.w;
2994  result = (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
2995  } else {
2996  /* we need to draw multiple times */
2997  /* draw the first segment */
2998  pixels_written = texture_w - texture_x_walker;
2999  source_rect.w = pixels_written;
3000  source_rect.x = texture_x_walker;
3001  dst_rect.x= x1;
3002  dst_rect.w = source_rect.w;
3003  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
3004  write_width = texture_w;
3005 
3006  /* now draw the rest */
3007  /* set the source x to 0 */
3008  source_rect.x = 0;
3009  while (pixels_written < w){
3010  if (write_width >= w - pixels_written) {
3011  write_width = w - pixels_written;
3012  }
3013  source_rect.w = write_width;
3014  dst_rect.x = x1 + pixels_written;
3015  dst_rect.w = source_rect.w;
3016  result |= (SDL_RenderCopy(renderer, texture, &source_rect, &dst_rect) == 0);
3017  pixels_written += write_width;
3018  }
3019  }
3020 
3021  return result;
3022 }
3023 
3040 int texturedPolygonMT(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n,
3041  SDL_Surface * texture, int texture_dx, int texture_dy, int **polyInts, int *polyAllocated)
3042 {
3043  int result;
3044  int i;
3045  int y, xa, xb;
3046  int minx,maxx,miny, maxy;
3047  int x1, y1;
3048  int x2, y2;
3049  int ind1, ind2;
3050  int ints;
3051  int *gfxPrimitivesPolyInts = NULL;
3052  int *gfxPrimitivesPolyIntsTemp = NULL;
3053  int gfxPrimitivesPolyAllocated = 0;
3054  SDL_Texture *textureAsTexture = NULL;
3055 
3056  /*
3057  * Sanity check number of edges
3058  */
3059  if (n < 3) {
3060  return -1;
3061  }
3062 
3063  /*
3064  * Map polygon cache
3065  */
3066  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3067  /* Use global cache */
3068  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsGlobal;
3069  gfxPrimitivesPolyAllocated = gfxPrimitivesPolyAllocatedGlobal;
3070  } else {
3071  /* Use local cache */
3072  gfxPrimitivesPolyInts = *polyInts;
3073  gfxPrimitivesPolyAllocated = *polyAllocated;
3074  }
3075 
3076  /*
3077  * Allocate temp array, only grow array
3078  */
3079  if (!gfxPrimitivesPolyAllocated) {
3080  gfxPrimitivesPolyInts = (int *) malloc(sizeof(int) * n);
3081  gfxPrimitivesPolyAllocated = n;
3082  } else {
3083  if (gfxPrimitivesPolyAllocated < n) {
3084  gfxPrimitivesPolyIntsTemp = (int *) realloc(gfxPrimitivesPolyInts, sizeof(int) * n);
3085  if (gfxPrimitivesPolyIntsTemp == NULL) {
3086  /* Realloc failed - keeps original memory block, but fails this operation */
3087  return(-1);
3088  }
3089  gfxPrimitivesPolyInts = gfxPrimitivesPolyIntsTemp;
3090  gfxPrimitivesPolyAllocated = n;
3091  }
3092  }
3093 
3094  /*
3095  * Check temp array
3096  */
3097  if (gfxPrimitivesPolyInts==NULL) {
3098  gfxPrimitivesPolyAllocated = 0;
3099  }
3100 
3101  /*
3102  * Update cache variables
3103  */
3104  if ((polyInts==NULL) || (polyAllocated==NULL)) {
3105  gfxPrimitivesPolyIntsGlobal = gfxPrimitivesPolyInts;
3106  gfxPrimitivesPolyAllocatedGlobal = gfxPrimitivesPolyAllocated;
3107  } else {
3108  *polyInts = gfxPrimitivesPolyInts;
3109  *polyAllocated = gfxPrimitivesPolyAllocated;
3110  }
3111 
3112  /*
3113  * Check temp array again
3114  */
3115  if (gfxPrimitivesPolyInts==NULL) {
3116  return(-1);
3117  }
3118 
3119  /*
3120  * Determine X,Y minima,maxima
3121  */
3122  miny = vy[0];
3123  maxy = vy[0];
3124  minx = vx[0];
3125  maxx = vx[0];
3126  for (i = 1; (i < n); i++) {
3127  if (vy[i] < miny) {
3128  miny = vy[i];
3129  } else if (vy[i] > maxy) {
3130  maxy = vy[i];
3131  }
3132  if (vx[i] < minx) {
3133  minx = vx[i];
3134  } else if (vx[i] > maxx) {
3135  maxx = vx[i];
3136  }
3137  }
3138 
3139  /* Create texture for drawing */
3140  textureAsTexture = SDL_CreateTextureFromSurface(renderer, texture);
3141  if (textureAsTexture == NULL)
3142  {
3143  return -1;
3144  }
3145  SDL_SetTextureBlendMode(textureAsTexture, SDL_BLENDMODE_BLEND);
3146 
3147  /*
3148  * Draw, scanning y
3149  */
3150  result = 0;
3151  for (y = miny; (y <= maxy); y++) {
3152  ints = 0;
3153  for (i = 0; (i < n); i++) {
3154  if (!i) {
3155  ind1 = n - 1;
3156  ind2 = 0;
3157  } else {
3158  ind1 = i - 1;
3159  ind2 = i;
3160  }
3161  y1 = vy[ind1];
3162  y2 = vy[ind2];
3163  if (y1 < y2) {
3164  x1 = vx[ind1];
3165  x2 = vx[ind2];
3166  } else if (y1 > y2) {
3167  y2 = vy[ind1];
3168  y1 = vy[ind2];
3169  x2 = vx[ind1];
3170  x1 = vx[ind2];
3171  } else {
3172  continue;
3173  }
3174  if ( ((y >= y1) && (y < y2)) || ((y == maxy) && (y > y1) && (y <= y2)) ) {
3175  gfxPrimitivesPolyInts[ints++] = ((65536 * (y - y1)) / (y2 - y1)) * (x2 - x1) + (65536 * x1);
3176  }
3177  }
3178 
3179  qsort(gfxPrimitivesPolyInts, ints, sizeof(int), _gfxPrimitivesCompareInt);
3180 
3181  for (i = 0; (i < ints); i += 2) {
3182  xa = gfxPrimitivesPolyInts[i] + 1;
3183  xa = (xa >> 16) + ((xa & 32768) >> 15);
3184  xb = gfxPrimitivesPolyInts[i+1] - 1;
3185  xb = (xb >> 16) + ((xb & 32768) >> 15);
3186  result |= _HLineTextured(renderer, xa, xb, y, textureAsTexture, texture->w, texture->h, texture_dx, texture_dy);
3187  }
3188  }
3189 
3190  SDL_RenderPresent(renderer);
3191  SDL_DestroyTexture(textureAsTexture);
3192 
3193  return (result);
3194 }
3195 
3212 int texturedPolygon(SDL_Renderer *renderer, const Sint16 * vx, const Sint16 * vy, int n, SDL_Surface *texture, int texture_dx, int texture_dy)
3213 {
3214  /*
3215  * Draw
3216  */
3217  return (texturedPolygonMT(renderer, vx, vy, n, texture, texture_dx, texture_dy, NULL, NULL));
3218 }
3219 
3220 /* ---- Character */
3221 
3225 static SDL_Texture *gfxPrimitivesFont[256];
3226 
3230 static const unsigned char *currentFontdata = gfxPrimitivesFontdata;
3231 
3235 static Uint32 charWidth = 8;
3236 
3240 static Uint32 charHeight = 8;
3241 
3245 static Uint32 charWidthLocal = 8;
3246 
3250 static Uint32 charHeightLocal = 8;
3251 
3255 static Uint32 charPitch = 1;
3256 
3260 static Uint32 charRotation = 0;
3261 
3265 static Uint32 charSize = 8;
3266 
3280 void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
3281 {
3282  int i;
3283 
3284  if ((fontdata) && (cw) && (ch)) {
3285  currentFontdata = (unsigned char *)fontdata;
3286  charWidth = cw;
3287  charHeight = ch;
3288  } else {
3289  currentFontdata = gfxPrimitivesFontdata;
3290  charWidth = 8;
3291  charHeight = 8;
3292  }
3293 
3294  charPitch = (charWidth+7)/8;
3295  charSize = charPitch * charHeight;
3296 
3297  /* Maybe flip width/height for rendering */
3298  if ((charRotation==1) || (charRotation==3))
3299  {
3300  charWidthLocal = charHeight;
3301  charHeightLocal = charWidth;
3302  }
3303  else
3304  {
3305  charWidthLocal = charWidth;
3306  charHeightLocal = charHeight;
3307  }
3308 
3309  /* Clear character cache */
3310  for (i = 0; i < 256; i++) {
3311  if (gfxPrimitivesFont[i]) {
3312  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3313  gfxPrimitivesFont[i] = NULL;
3314  }
3315  }
3316 }
3317 
3326 void gfxPrimitivesSetFontRotation(Uint32 rotation)
3327 {
3328  int i;
3329 
3330  rotation = rotation & 3;
3331  if (charRotation != rotation)
3332  {
3333  /* Store rotation */
3334  charRotation = rotation;
3335 
3336  /* Maybe flip width/height for rendering */
3337  if ((charRotation==1) || (charRotation==3))
3338  {
3339  charWidthLocal = charHeight;
3340  charHeightLocal = charWidth;
3341  }
3342  else
3343  {
3344  charWidthLocal = charWidth;
3345  charHeightLocal = charHeight;
3346  }
3347 
3348  /* Clear character cache */
3349  for (i = 0; i < 256; i++) {
3350  if (gfxPrimitivesFont[i]) {
3351  SDL_DestroyTexture(gfxPrimitivesFont[i]);
3352  gfxPrimitivesFont[i] = NULL;
3353  }
3354  }
3355  }
3356 }
3357 
3372 int characterRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3373 {
3374  SDL_Rect srect;
3375  SDL_Rect drect;
3376  int result;
3377  Uint32 ix, iy;
3378  const unsigned char *charpos;
3379  Uint8 *curpos;
3380  Uint8 patt, mask;
3381  Uint8 *linepos;
3382  Uint32 pitch;
3383  SDL_Surface *character;
3384  SDL_Surface *rotatedCharacter;
3385  Uint32 ci;
3386 
3387  /*
3388  * Setup source rectangle
3389  */
3390  srect.x = 0;
3391  srect.y = 0;
3392  srect.w = charWidthLocal;
3393  srect.h = charHeightLocal;
3394 
3395  /*
3396  * Setup destination rectangle
3397  */
3398  drect.x = x;
3399  drect.y = y;
3400  drect.w = charWidthLocal;
3401  drect.h = charHeightLocal;
3402 
3403  /* Character index in cache */
3404  ci = (unsigned char) c;
3405 
3406  /*
3407  * Create new charWidth x charHeight bitmap surface if not already present.
3408  * Might get rotated later.
3409  */
3410  if (gfxPrimitivesFont[ci] == NULL) {
3411  /*
3412  * Redraw character into surface
3413  */
3414  character = SDL_CreateRGBSurface(SDL_SWSURFACE,
3415  charWidth, charHeight, 32,
3416  0xFF000000, 0x00FF0000, 0x0000FF00, 0x000000FF);
3417  if (character == NULL) {
3418  return (-1);
3419  }
3420 
3421  charpos = currentFontdata + ci * charSize;
3422  linepos = (Uint8 *)character->pixels;
3423  pitch = character->pitch;
3424 
3425  /*
3426  * Drawing loop
3427  */
3428  patt = 0;
3429  for (iy = 0; iy < charHeight; iy++) {
3430  mask = 0x00;
3431  curpos = linepos;
3432  for (ix = 0; ix < charWidth; ix++) {
3433  if (!(mask >>= 1)) {
3434  patt = *charpos++;
3435  mask = 0x80;
3436  }
3437  if (patt & mask) {
3438  *(Uint32 *)curpos = 0xffffffff;
3439  } else {
3440  *(Uint32 *)curpos = 0;
3441  }
3442  curpos += 4;
3443  }
3444  linepos += pitch;
3445  }
3446 
3447  /* Maybe rotate and replace cached image */
3448  if (charRotation>0)
3449  {
3450  rotatedCharacter = rotateSurface90Degrees(character, charRotation);
3451  SDL_FreeSurface(character);
3452  character = rotatedCharacter;
3453  }
3454 
3455  /* Convert temp surface into texture */
3456  gfxPrimitivesFont[ci] = SDL_CreateTextureFromSurface(renderer, character);
3457  SDL_FreeSurface(character);
3458 
3459  /*
3460  * Check pointer
3461  */
3462  if (gfxPrimitivesFont[ci] == NULL) {
3463  return (-1);
3464  }
3465  }
3466 
3467  /*
3468  * Set color
3469  */
3470  result = 0;
3471  result |= SDL_SetTextureColorMod(gfxPrimitivesFont[ci], r, g, b);
3472  result |= SDL_SetTextureAlphaMod(gfxPrimitivesFont[ci], a);
3473 
3474  /*
3475  * Draw texture onto destination
3476  */
3477  result |= SDL_RenderCopy(renderer, gfxPrimitivesFont[ci], &srect, &drect);
3478 
3479  return (result);
3480 }
3481 
3482 
3494 int characterColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, char c, Uint32 color)
3495 {
3496  Uint8 *co = (Uint8 *)&color;
3497  return characterRGBA(renderer, x, y, c, co[0], co[1], co[2], co[3]);
3498 }
3499 
3500 
3515 int stringColor(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
3516 {
3517  Uint8 *c = (Uint8 *)&color;
3518  return stringRGBA(renderer, x, y, s, c[0], c[1], c[2], c[3]);
3519 }
3520 
3535 int stringRGBA(SDL_Renderer * renderer, Sint16 x, Sint16 y, const char *s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3536 {
3537  int result = 0;
3538  Sint16 curx = x;
3539  Sint16 cury = y;
3540  const char *curchar = s;
3541 
3542  while (*curchar && !result) {
3543  result |= characterRGBA(renderer, curx, cury, *curchar, r, g, b, a);
3544  switch (charRotation)
3545  {
3546  case 0:
3547  curx += charWidthLocal;
3548  break;
3549  case 2:
3550  curx -= charWidthLocal;
3551  break;
3552  case 1:
3553  cury += charHeightLocal;
3554  break;
3555  case 3:
3556  cury -= charHeightLocal;
3557  break;
3558  }
3559  curchar++;
3560  }
3561 
3562  return (result);
3563 }
3564 
3565 /* ---- Bezier curve */
3566 
3576 double _evaluateBezier (double *data, int ndata, double t)
3577 {
3578  double mu, result;
3579  int n,k,kn,nn,nkn;
3580  double blend,muk,munk;
3581 
3582  /* Sanity check bounds */
3583  if (t<0.0) {
3584  return(data[0]);
3585  }
3586  if (t>=(double)ndata) {
3587  return(data[ndata-1]);
3588  }
3589 
3590  /* Adjust t to the range 0.0 to 1.0 */
3591  mu=t/(double)ndata;
3592 
3593  /* Calculate interpolate */
3594  n=ndata-1;
3595  result=0.0;
3596  muk = 1;
3597  munk = pow(1-mu,(double)n);
3598  for (k=0;k<=n;k++) {
3599  nn = n;
3600  kn = k;
3601  nkn = n - k;
3602  blend = muk * munk;
3603  muk *= mu;
3604  munk /= (1-mu);
3605  while (nn >= 1) {
3606  blend *= nn;
3607  nn--;
3608  if (kn > 1) {
3609  blend /= (double)kn;
3610  kn--;
3611  }
3612  if (nkn > 1) {
3613  blend /= (double)nkn;
3614  nkn--;
3615  }
3616  }
3617  result += data[k] * blend;
3618  }
3619 
3620  return (result);
3621 }
3622 
3635 int bezierColor(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint32 color)
3636 {
3637  Uint8 *c = (Uint8 *)&color;
3638  return bezierRGBA(renderer, vx, vy, n, s, c[0], c[1], c[2], c[3]);
3639 }
3640 
3656 int bezierRGBA(SDL_Renderer * renderer, const Sint16 * vx, const Sint16 * vy, int n, int s, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3657 {
3658  int result;
3659  int i;
3660  double *x, *y, t, stepsize;
3661  Sint16 x1, y1, x2, y2;
3662 
3663  /*
3664  * Sanity check
3665  */
3666  if (n < 3) {
3667  return (-1);
3668  }
3669  if (s < 2) {
3670  return (-1);
3671  }
3672 
3673  /*
3674  * Variable setup
3675  */
3676  stepsize=(double)1.0/(double)s;
3677 
3678  /* Transfer vertices into float arrays */
3679  if ((x=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3680  return(-1);
3681  }
3682  if ((y=(double *)malloc(sizeof(double)*(n+1)))==NULL) {
3683  free(x);
3684  return(-1);
3685  }
3686  for (i=0; i<n; i++) {
3687  x[i]=(double)vx[i];
3688  y[i]=(double)vy[i];
3689  }
3690  x[n]=(double)vx[0];
3691  y[n]=(double)vy[0];
3692 
3693  /*
3694  * Set color
3695  */
3696  result = 0;
3697  result |= SDL_SetRenderDrawBlendMode(renderer, (a == 255) ? SDL_BLENDMODE_NONE : SDL_BLENDMODE_BLEND);
3698  result |= SDL_SetRenderDrawColor(renderer, r, g, b, a);
3699 
3700  /*
3701  * Draw
3702  */
3703  t=0.0;
3704  x1=(Sint16)lrint(_evaluateBezier(x,n+1,t));
3705  y1=(Sint16)lrint(_evaluateBezier(y,n+1,t));
3706  for (i = 0; i <= (n*s); i++) {
3707  t += stepsize;
3708  x2=(Sint16)_evaluateBezier(x,n,t);
3709  y2=(Sint16)_evaluateBezier(y,n,t);
3710  result |= line(renderer, x1, y1, x2, y2);
3711  x1 = x2;
3712  y1 = y2;
3713  }
3714 
3715  /* Clean up temporary array */
3716  free(x);
3717  free(y);
3718 
3719  return (result);
3720 }
3721 
3722 
3736 int thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
3737 {
3738  Uint8 *c = (Uint8 *)&color;
3739  return thickLineRGBA(renderer, x1, y1, x2, y2, width, c[0], c[1], c[2], c[3]);
3740 }
3741 
3758 int thickLineRGBA(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
3759 {
3760  int wh;
3761  double dx, dy, dx1, dy1, dx2, dy2;
3762  double l, wl2, nx, ny, ang, adj;
3763  Sint16 px[4], py[4];
3764 
3765  if (renderer == NULL) {
3766  return -1;
3767  }
3768 
3769  if (width < 1) {
3770  return -1;
3771  }
3772 
3773  /* Special case: thick "point" */
3774  if ((x1 == x2) && (y1 == y2)) {
3775  wh = width / 2;
3776  return boxRGBA(renderer, x1 - wh, y1 - wh, x2 + width, y2 + width, r, g, b, a);
3777  }
3778 
3779  /* Special case: width == 1 */
3780  if (width == 1) {
3781  return lineRGBA(renderer, x1, y1, x2, y2, r, g, b, a);
3782  }
3783 
3784  /* Calculate offsets for sides */
3785  dx = (double)(x2 - x1);
3786  dy = (double)(y2 - y1);
3787  l = SDL_sqrt(dx*dx + dy*dy);
3788  ang = SDL_atan2(dx, dy);
3789  adj = 0.1 + 0.9 * SDL_fabs(SDL_cos(2.0 * ang));
3790  wl2 = ((double)width - adj)/(2.0 * l);
3791  nx = dx * wl2;
3792  ny = dy * wl2;
3793 
3794  /* Build polygon */
3795  dx1 = (double)x1;
3796  dy1 = (double)y1;
3797  dx2 = (double)x2;
3798  dy2 = (double)y2;
3799  px[0] = (Sint16)(dx1 + ny);
3800  px[1] = (Sint16)(dx1 - ny);
3801  px[2] = (Sint16)(dx2 - ny);
3802  px[3] = (Sint16)(dx2 + ny);
3803  py[0] = (Sint16)(dy1 - nx);
3804  py[1] = (Sint16)(dy1 + nx);
3805  py[2] = (Sint16)(dy2 + nx);
3806  py[3] = (Sint16)(dy2 - nx);
3807 
3808  /* Draw polygon */
3809  return filledPolygonRGBA(renderer, px, py, 4, r, g, b, a);
3810 }
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.
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 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 stringColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, const char *s, Uint32 color)
Draw a string in the currently set font.
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 aalineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw anti-aliased line with alpha blending.
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 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.
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 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 _ellipseRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint8 r, Uint8 g, Uint8 b, Uint8 a, Sint32 f)
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 pieColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Draw pie (outline) with alpha blending.
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 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.
#define AAbits
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 pixelColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Uint32 color)
Draw pixel with blending enabled if a<255.
int pixel(SDL_Renderer *renderer, Sint16 x, Sint16 y)
Draw pixel in currently set color.
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 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 _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 arcColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Arc with blending.
#define AAlevels
int circleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw circle with blending.
int filledEllipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw filled ellipse with blending.
int circleRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw circle 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 thickLineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint8 width, Uint32 color)
Draw a thick line with alpha 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 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 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 vline(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2)
Draw vertical line in currently set color.
int polygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw polygon with alpha blending.
int vlineColor(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint32 color)
Draw vertical line with blending.
int rectangleColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw rectangle with blending.
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 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 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 vlineRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y1, Sint16 y2, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw vertical line with blending.
int hlineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y, Uint32 color)
Draw horizontal line with 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.
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 filledCircleRGBA(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint8 r, Uint8 g, Uint8 b, Uint8 a)
Draw filled circle 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.
double _evaluateBezier(double *data, int ndata, double t)
Internal function to calculate bezier interpolator of data array with ndata values at position 't'.
int filledPieColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Sint16 start, Sint16 end, Uint32 color)
Draw filled pie with alpha blending.
int ellipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw ellipse 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 characterColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, char c, Uint32 color)
Draw a character of the currently set font.
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 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 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 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 hline(SDL_Renderer *renderer, Sint16 x1, Sint16 x2, Sint16 y)
Draw horizontal line in currently set color.
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 lineColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw line with alpha 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 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 filledPolygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw filled polygon with alpha blending.
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 _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 filledCircleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw filled circle with 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 line(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2)
Draw line with alpha blending using the currently set color.
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.
#define DEFAULT_ELLIPSE_OVERSCAN
Internal function to draw ellipse or filled ellipse with blending.
int aapolygonColor(SDL_Renderer *renderer, const Sint16 *vx, const Sint16 *vy, int n, Uint32 color)
Draw anti-aliased polygon with alpha blending.
int aacircleColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rad, Uint32 color)
Draw anti-aliased circle with blending.
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 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.
int _gfxPrimitivesCompareInt(const void *a, const void *b)
Internal helper qsort callback functions used in filled polygon drawing.
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.
void gfxPrimitivesSetFontRotation(Uint32 rotation)
Sets current global font character rotation steps.
int boxColor(SDL_Renderer *renderer, Sint16 x1, Sint16 y1, Sint16 x2, Sint16 y2, Uint32 color)
Draw box (filled rectangle) with blending.
void gfxPrimitivesSetFont(const void *fontdata, Uint32 cw, Uint32 ch)
Sets or resets the current global font data.
int aaellipseColor(SDL_Renderer *renderer, Sint16 x, Sint16 y, Sint16 rx, Sint16 ry, Uint32 color)
Draw anti-aliased ellipse with blending.
#define M_PI
SDL_Surface * rotateSurface90Degrees(SDL_Surface *src, int numClockwiseTurns)
Rotates a 8/16/24/32 bit surface in increments of 90 degrees.
The structure passed to the internal Bresenham iterator.
The structure passed to the internal Murphy iterator.