From 545a719db9f706d47d1135c5056faab82e22f230 Mon Sep 17 00:00:00 2001
From: inmarket <inmarket@ugfx.org>
Date: Wed, 9 Nov 2016 16:41:44 +1000
Subject: New dual circle drawing in GDISP

---
 src/gdisp/gdisp.c         | 77 +++++++++++++++++++++++++++++++++++++++++++++++
 src/gdisp/gdisp.h         | 18 +++++++++++
 src/gdisp/gdisp_options.h |  8 +++++
 3 files changed, 103 insertions(+)

(limited to 'src/gdisp')

diff --git a/src/gdisp/gdisp.c b/src/gdisp/gdisp.c
index 691cab85..9e7c25e0 100644
--- a/src/gdisp/gdisp.c
+++ b/src/gdisp/gdisp.c
@@ -1347,6 +1347,83 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c
 	}
 #endif
 
+#if GDISP_NEED_DUALCIRCLE
+
+	#define DRAW_DUALLINE(yval, r1, r2) 										\
+		g->p.y = yval;															\
+		g->p.x = x-r1;   g->p.x1 = x-r2+1; hline_clip(g);						\
+		g->p.x = x-r2;   g->p.x1 = x+r2;   g->p.color = color2; hline_clip(g);	\
+		g->p.x = x+r2+1; g->p.x1 = x+r1;   g->p.color = color1; hline_clip(g)
+	#define DRAW_SINGLELINE(yval, r)	g->p.y = yval; g->p.x = x-r; g->p.x1 = x+r; hline_clip(g)
+
+	void gdispGFillDualCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius1, color_t color1, coord_t radius2, color_t color2) {
+		coord_t a, b1, b2, p1, p2;
+
+		MUTEX_ENTER(g);
+
+		// Do the combined circle where the inner circle < 45 deg (and outer circle)
+		g->p.color = color1;
+		a = 0; b1 = radius1; b2 = radius2; p1 = p2 = 1;
+		do {
+			DRAW_DUALLINE(y+a, b1, b2);
+			DRAW_DUALLINE(y-a, b1, b2);
+			if (p1 >= 0) p1 -= b1--;
+			p1 += a;
+			if (p2 >= 0) p2 -= b2--;
+			p2 += a;
+		} while(++a < b2);
+
+		// Do the combined circle where inner circle > 45 deg, outer circle < 45
+		do {
+			DRAW_DUALLINE(y+a, b1, b2);
+			DRAW_DUALLINE(y-a, b1, b2);
+			if (p1 >= 0) p1 -= b1--;
+			p1 += a;
+			do { p2 -= --b2; } while (p2+a >= b2);
+			p2 += a;
+		} while(++a <= radius2 && a < b1);
+		
+		if (a < radius2) {
+			// Do the combined circle where inner circle > 45 deg, outer circle > 45
+			do {
+				DRAW_DUALLINE(y+a, b1, b2);
+				DRAW_DUALLINE(y-a, b1, b2);
+				do { p1 -= --b1; } while (p1+a >= b1);
+				p1 += a;
+				do { p2 -= --b2; } while (p2+a >= b2);
+				p2 += a++;
+			} while(b2 > 0);
+			
+		} else {
+			// Do the outer circle above the inner circle but < 45 deg
+			do {
+				DRAW_SINGLELINE(y+a, b1);
+				DRAW_SINGLELINE(y-a, b1);
+				if (p1 >= 0) p1 -= b1--;
+				p1 += a++;
+			} while(a < b1);
+			DRAW_SINGLELINE(y+a, b1);
+			DRAW_SINGLELINE(y-a, b1);
+		}
+
+		// Do the top and bottom part of the outer circle (outer circle > 45deg and above inner circle)
+		a = 0; b1 = radius1; p1 = 1;
+		do {
+			if (p1 >= 0) {
+				DRAW_SINGLELINE(y+b1, a);
+				DRAW_SINGLELINE(y-b1, a);
+				p1 -= b1--;
+			}
+			p1 += a++;
+		} while(b1 > radius2 && a < b1);
+
+		autoflush(g);
+		MUTEX_EXIT(g);
+	}
+	#undef DRAW_DUALLINE
+	#undef DRAW_SINGLELINE
+#endif
+
 #if GDISP_NEED_ELLIPSE
 	void gdispGDrawEllipse(GDisplay *g, coord_t x, coord_t y, coord_t a, coord_t b, color_t color) {
 		coord_t	dx, dy;
diff --git a/src/gdisp/gdisp.h b/src/gdisp/gdisp.h
index 5cb91896..22ee8877 100644
--- a/src/gdisp/gdisp.h
+++ b/src/gdisp/gdisp.h
@@ -574,6 +574,24 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
 	#define gdispFillCircle(x,y,r,c)						gdispGFillCircle(GDISP,x,y,r,c)
 #endif
 
+#if GDISP_NEED_DUALCIRCLE || defined(__DOXYGEN__)
+	/**
+	 * @brief   Draw two filled circles with the same centre.
+	 * @pre		GDISP_NEED_DUALCIRCLE must be TRUE in your gfxconf.h
+	 *
+	 * @param[in] g 		The display to use
+	 * @param[in] x,y		The center of the circle
+	 * @param[in] radius1	The radius of the larger circle
+	 * @param[in] color1	The color to use for the larger circle
+	 * @param[in] radius2	The radius of the smaller circle
+	 * @param[in] color2	The color to use for the smaller circle
+	 *
+	 * @api
+	 */
+	void gdispGFillDualCircle(GDisplay *g, coord_t x, coord_t y, coord_t radius1, color_t color1, coord_t radius2, color_t color2);
+	#define gdispFillDualCircle(x,y,r,c)					gdispGFillDualCircle(GDISP,x,y,r1,c1,r2,c2)
+#endif
+
 /* Ellipse Functions */
 
 #if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
diff --git a/src/gdisp/gdisp_options.h b/src/gdisp/gdisp_options.h
index 4c004808..09502618 100644
--- a/src/gdisp/gdisp_options.h
+++ b/src/gdisp/gdisp_options.h
@@ -93,6 +93,14 @@
 	#ifndef GDISP_NEED_CIRCLE
 		#define GDISP_NEED_CIRCLE				FALSE
 	#endif
+	/**
+	 * @brief   Are dual circle functions needed (one circle inside another).
+	 * @details	Defaults to FALSE
+	 * @note	Uses integer algorithms only. It does not use any trig or floating point.
+	 */
+	#ifndef GDISP_NEED_DUALCIRCLE
+		#define GDISP_NEED_DUALCIRCLE			FALSE
+	#endif
 	/**
 	 * @brief   Are ellipse functions needed.
 	 * @details	Defaults to FALSE
-- 
cgit v1.2.3