brewpanel/sdlgui.c

changeset 425
c51265b518ce
parent 422
13502d0dda65
child 427
e8e548922e31
--- a/brewpanel/sdlgui.c	Thu Nov 19 15:05:19 2015 +0100
+++ b/brewpanel/sdlgui.c	Thu Nov 19 20:45:09 2015 +0100
@@ -495,6 +495,116 @@
 
 
 /*
+ * SDL_Surface 32-bit circle-fill algorithm without using trig
+ *
+ * While I humbly call this "Celdecea's Method", odds are that the 
+ * procedure has already been documented somewhere long ago.  All of
+ * the circle-fill examples I came across utilized trig functions or
+ * scanning neighbor pixels.  This algorithm identifies the width of
+ * a semi-circle at each pixel height and draws a scan-line covering
+ * that width.  
+ *
+ * The code is not optimized but very fast, owing to the fact that it
+ * alters pixels in the provided surface directly rather than through
+ * function calls.
+ */
+void SDLGui_fill_circle(SDL_Surface *surface, int cx, int cy, int radius, Uint32 pixel)
+{
+    /*
+     * Note that there is more to altering the bitrate of this 
+     * method than just changing this value.  See how pixels are
+     * altered at the following web page for tips:
+     * http://www.libsdl.org/intro.en/usingvideo.html
+     */
+    static const int	BPP = 4;
+    double 		r = (double)radius;
+    double		dy;
+
+    for (dy = 1; dy <= r; dy += 1.0) {
+	/*
+	 * This loop is unrolled a bit, only iterating through half of the
+	 * height of the circle.  The result is used to draw a scan line and
+	 * its mirror image below it.
+	 *
+	 * The following formula has been simplified from our original.  We
+	 * are using half of the width of the circle because we are provided
+	 * with a center and we need left/right coordinates.
+	 */
+	double dx = floor(sqrt((2.0 * r * dy) - (dy * dy)));
+	int x = cx - dx;
+
+	// Grab a pointer to the left-most pixel for each half of the circle
+	Uint8 *target_pixel_a = (Uint8 *)surface->pixels + ((int)(cy + r - dy)) * surface->pitch + x * BPP;
+	Uint8 *target_pixel_b = (Uint8 *)surface->pixels + ((int)(cy - r + dy)) * surface->pitch + x * BPP;
+
+	for (; x <= cx + dx; x++) {
+	    *(Uint32 *)target_pixel_a = pixel;
+	    *(Uint32 *)target_pixel_b = pixel;
+	    target_pixel_a += BPP;
+	    target_pixel_b += BPP;
+	}
+    }
+}
+
+
+
+static void SDLGUI_DrawLEDRed(const SGOBJ *bdlg, int objnum)
+{
+    Uint32	color;
+
+    if (bdlg[objnum].state & SG_SELECTED) {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 255, 64, 0);
+    } else {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 128, 16, 0);
+    }
+    SDLGui_fill_circle(pSdlGuiScrn, bdlg[objnum].x, bdlg[objnum].y, bdlg[objnum].w, color);
+}
+
+
+
+static void SDLGUI_DrawLEDBlue(const SGOBJ *bdlg, int objnum)
+{
+    Uint32      color;
+
+    if (bdlg[objnum].state & SG_SELECTED) {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 64, 160, 255);
+    } else {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 16, 48, 112);
+    }
+    SDLGui_fill_circle(pSdlGuiScrn, bdlg[objnum].x, bdlg[objnum].y, bdlg[objnum].w, color);
+}
+
+
+
+static void SDLGUI_DrawLEDGreen(const SGOBJ *bdlg, int objnum)
+{
+    Uint32      color;
+
+    if (bdlg[objnum].state & SG_SELECTED) {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 80, 240, 0);
+    } else {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 32, 112, 0);
+    }
+    SDLGui_fill_circle(pSdlGuiScrn, bdlg[objnum].x, bdlg[objnum].y, bdlg[objnum].w, color);
+}
+
+
+
+static void SDLGUI_DrawLEDYellow(const SGOBJ *bdlg, int objnum)
+{
+    Uint32      color;
+
+    if (bdlg[objnum].state & SG_SELECTED) {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 255, 255, 0);
+    } else {
+	color = SDL_MapRGB(pSdlGuiScrn->format, 160, 144, 0);
+    }
+    SDLGui_fill_circle(pSdlGuiScrn, bdlg[objnum].x, bdlg[objnum].y, bdlg[objnum].w, color);
+}
+
+
+
+/*
  * Draw a whole dialog.
  */
 void SDLGui_DrawDialog(const SGOBJ *dlg)
@@ -518,6 +628,18 @@
 	    case SGBUTTON:
 			SDLGui_DrawButton(dlg, i);
 			break;
+	    case SGLEDRED:
+			SDLGUI_DrawLEDRed(dlg, i);
+			break;
+	    case SGLEDBLUE:
+			SDLGUI_DrawLEDBlue(dlg, i);
+			break;
+	    case SGLEDGREEN:
+			SDLGUI_DrawLEDGreen(dlg, i);
+			break;
+	    case SGLEDYELLOW:
+			SDLGUI_DrawLEDYellow(dlg, i);
+			break;
 	}
     }
 

mercurial