aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorinmarket <andrewh@inmarket.com.au>2014-10-27 16:44:53 +1000
committerinmarket <andrewh@inmarket.com.au>2014-10-27 16:44:53 +1000
commit3825cec8f857ffd80cf9df0822ae39b639812842 (patch)
tree0b5eff9b34cecba6f8b15878f1ee10104048c96f
parentcb668266b54fb0feb7cda9f973b0cc6bc40873ab (diff)
downloaduGFX-3825cec8f857ffd80cf9df0822ae39b639812842.tar.gz
uGFX-3825cec8f857ffd80cf9df0822ae39b639812842.tar.bz2
uGFX-3825cec8f857ffd80cf9df0822ae39b639812842.zip
Added new arc sector drawing routines (Thanks to steved for the inspiration).
Added demo to match.
-rw-r--r--demos/modules/gdisp/arcsectors/demo.mk3
-rw-r--r--demos/modules/gdisp/arcsectors/gfxconf.h52
-rw-r--r--demos/modules/gdisp/arcsectors/main.c76
-rw-r--r--docs/releases.txt5
-rw-r--r--src/gdisp/gdisp_gdisp.c263
-rw-r--r--src/gdisp/sys_defs.h111
6 files changed, 494 insertions, 16 deletions
diff --git a/demos/modules/gdisp/arcsectors/demo.mk b/demos/modules/gdisp/arcsectors/demo.mk
new file mode 100644
index 00000000..200bcbd5
--- /dev/null
+++ b/demos/modules/gdisp/arcsectors/demo.mk
@@ -0,0 +1,3 @@
+DEMODIR = $(GFXLIB)/demos/modules/gdisp/arcsectors
+GFXINC += $(DEMODIR)
+GFXSRC += $(DEMODIR)/main.c
diff --git a/demos/modules/gdisp/arcsectors/gfxconf.h b/demos/modules/gdisp/arcsectors/gfxconf.h
new file mode 100644
index 00000000..49470b2f
--- /dev/null
+++ b/demos/modules/gdisp/arcsectors/gfxconf.h
@@ -0,0 +1,52 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _GFXCONF_H
+#define _GFXCONF_H
+
+/* The operating system to use. One of these must be defined - preferably in your Makefile */
+//#define GFX_USE_OS_CHIBIOS FALSE
+//#define GFX_USE_OS_WIN32 FALSE
+//#define GFX_USE_OS_LINUX FALSE
+//#define GFX_USE_OS_OSX FALSE
+
+/* GFX sub-systems to turn on */
+#define GFX_USE_GDISP TRUE
+#define GFX_USE_GINPUT TRUE
+#define GFX_USE_GEVENT TRUE
+#define GFX_USE_GTIMER TRUE
+
+/* Features for the GDISP subsystem. */
+#define GDISP_NEED_VALIDATION TRUE
+#define GDISP_NEED_ARCSECTORS TRUE
+
+#define GINPUT_NEED_MOUSE TRUE
+
+#endif /* _GFXCONF_H */
+
diff --git a/demos/modules/gdisp/arcsectors/main.c b/demos/modules/gdisp/arcsectors/main.c
new file mode 100644
index 00000000..9d282207
--- /dev/null
+++ b/demos/modules/gdisp/arcsectors/main.c
@@ -0,0 +1,76 @@
+/*
+ * Copyright (c) 2012, 2013, Joel Bodenmann aka Tectu <joel@unormal.org>
+ * Copyright (c) 2012, 2013, Andrew Hannam aka inmarket
+ *
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the <organization> nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "gfx.h"
+
+GListener gl;
+
+int main(void) {
+ coord_t width, height, r1, r2, cx, cy;
+ uint8_t sectors;
+ GEventMouse *pme;
+
+ // Initialize and clear the display
+ gfxInit();
+
+ // Get the screen size
+ width = gdispGetWidth();
+ height = gdispGetHeight();
+ r1 = width > height ? height/3 : width/3;
+ r2 = r1*3/4;
+ cx = width/2;
+ cy = height/2;
+ sectors = 1;
+
+ // We want to listen for mouse button events
+ geventListenerInit(&gl);
+ geventAttachSource(&gl, ginputGetMouse(0), GLISTEN_MOUSEMETA);
+
+ while(1) {
+ // Draw the arc sectors
+ gdispClear(White);
+ gdispDrawArcSectors(cx, cy, r1, sectors, Blue);
+ gdispFillArcSectors(cx, cy, r2, sectors, Red);
+
+ // Get an Event
+ pme = (GEventMouse *)geventEventWait(&gl, TIME_INFINITE);
+
+ // Change our sectors based on the event.
+ switch(pme->type) {
+ case GEVENT_MOUSE:
+ case GEVENT_TOUCH:
+ if (pme->buttons & GMETA_MOUSE_CLICK)
+ sectors++;
+ else if (pme->buttons & GMETA_MOUSE_CXTCLICK)
+ sectors--;
+ break;
+ }
+ }
+}
+
diff --git a/docs/releases.txt b/docs/releases.txt
index adf7ca12..cf401935 100644
--- a/docs/releases.txt
+++ b/docs/releases.txt
@@ -31,11 +31,12 @@ FIX: Improve memory usage for the GWIN Frame widget.
FEATURE: Added transparent custom draws for GWIN containers and frame widgets
FEATURE: Added image custom draws for GWIN containers and frame widgets
FEATURE: Added GDRIVER infrastructure. Ported GDISP to use it.
+FEATURE: Added gdispDrawArcSectors() and gdispFillArcSectors().
*** Release 2.1 ***
FIX: Significant improvements to the way the MCU touch driver works.
-FEATURE: Add support for edge to edge touch calibration.
+FEATURE: Add support for edge to edge touch calibration.
FEATURE: Added progressbar widget
FEATURE: Added gdispGDrawThickLine() by user jpa-
DEPRECATE: TDISP module removed
@@ -78,7 +79,7 @@ FEATURE: GDISP Streaming API and demos.
DEPRECATE: GDISP_NEED_ASYNC is now deprecated.
DEPRECATE: 3rd party boing demo is now deprecated (replaced by GDISP Streaming demo)
FIX: Remove GOS definitions from demo conf files so that it can be supplied by a makefile.
-FEATURE: Repair GDISP low level driver interfaces so they can now be included in the doxygen documentation.
+FEATURE: Repair GDISP low level driver interfaces so they can now be included in the doxygen documentation.
FEATURE: New driver interface for GDISP
FEATURE: Multiple display support
FEATURE: Multiple controller support
diff --git a/src/gdisp/gdisp_gdisp.c b/src/gdisp/gdisp_gdisp.c
index 1552cea6..f5675a82 100644
--- a/src/gdisp/gdisp_gdisp.c
+++ b/src/gdisp/gdisp_gdisp.c
@@ -1420,8 +1420,233 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c
}
#endif
+#if GDISP_NEED_ARCSECTORS
+ void gdispGDrawArcSectors(GDisplay *g, coord_t x, coord_t y, coord_t radius, uint8_t sectors, color_t color) {
+ coord_t a, b, P;
+
+ MUTEX_ENTER(g);
+
+ // Calculate intermediates
+ a = 1; // x in many explanations
+ b = radius; // y in many explanations
+ P = 4 - radius;
+ g->p.color = color;
+
+ // Away we go using Bresenham's circle algorithm
+ // Optimized to prevent double drawing
+ if (sectors & 0x06) { g->p.x = x; g->p.y = y - b; drawpixel_clip(g); } // Upper upper
+ if (sectors & 0x60) { g->p.x = x; g->p.y = y + b; drawpixel_clip(g); } // Lower lower
+ if (sectors & 0x81) { g->p.x = x + b; g->p.y = y; drawpixel_clip(g); } // Right right
+ if (sectors & 0x18) { g->p.x = x - b; g->p.y = y; drawpixel_clip(g); } // Left left
+
+ do {
+ if (sectors & 0x01) { g->p.x = x + b; g->p.y = y - a; drawpixel_clip(g); } // Upper right right
+ if (sectors & 0x02) { g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); } // Upper upper right
+ if (sectors & 0x04) { g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); } // Upper upper left
+ if (sectors & 0x08) { g->p.x = x - b; g->p.y = y - a; drawpixel_clip(g); } // Upper left left
+ if (sectors & 0x10) { g->p.x = x - b; g->p.y = y + a; drawpixel_clip(g); } // Lower left left
+ if (sectors & 0x20) { g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); } // Lower lower left
+ if (sectors & 0x40) { g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); } // Lower lower right
+ if (sectors & 0x80) { g->p.x = x + b; g->p.y = y + a; drawpixel_clip(g); } // Lower right right
+ if (P < 0)
+ P += 3 + 2*a++;
+ else
+ P += 5 + 2*(a++ - b--);
+ } while(a < b);
+
+ if (sectors & 0xC0) { g->p.x = x + a; g->p.y = y + b; drawpixel_clip(g); } // Lower right
+ if (sectors & 0x03) { g->p.x = x + a; g->p.y = y - b; drawpixel_clip(g); } // Upper right
+ if (sectors & 0x30) { g->p.x = x - a; g->p.y = y + b; drawpixel_clip(g); } // Lower left
+ if (sectors & 0x0C) { g->p.x = x - a; g->p.y = y - b; drawpixel_clip(g); } // Upper left
+
+ autoflush(g);
+ MUTEX_EXIT(g);
+ }
+#endif
+
+#if GDISP_NEED_ARCSECTORS
+ void gdispGFillArcSectors(GDisplay *g, coord_t x, coord_t y, coord_t radius, uint8_t sectors, color_t color) {
+ coord_t a, b, P;
+
+ MUTEX_ENTER(g);
+
+ // Calculate intermediates
+ a = 1; // x in many explanations
+ b = radius; // y in many explanations
+ P = 4 - radius;
+ g->p.color = color;
+
+ // Away we go using Bresenham's circle algorithm
+ // Optimized to prevent double drawing
+ if (sectors & 0x06) { g->p.x = x; g->p.y = y - b; drawpixel_clip(g); } // Upper upper
+ if (sectors & 0x60) { g->p.x = x; g->p.y = y + b; drawpixel_clip(g); } // Lower lower
+ if (sectors & 0x81) { // Center right
+ g->p.y = y; g->p.x = x; g->p.x1 = x + b;
+ if (sectors & 0x18) g->p.x -= b; // Left right
+ hline_clip(g);
+ } else if (sectors & 0x18) { // Left center
+ g->p.x = x - b; g->p.x1 = x; g->p.y = y;
+ hline_clip(g);
+ }
+
+ do {
+ // Top half
+ switch(sectors & 0x0F) {
+ case 0x01:
+ g->p.y = y - a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x02:
+ g->p.y = y - b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x03:
+ g->p.y = y - b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x04:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ break;
+ case 0x05:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x06:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x07:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x08:
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ break;
+ case 0x09:
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0A:
+ g->p.y = y - b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x0B:
+ g->p.y = y - b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0C:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x; hline_clip(g);
+ break;
+ case 0x0D:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x; hline_clip(g);
+ g->p.y = y - a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0E:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x0F:
+ g->p.y = y - b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y - a; g->p.x = x - b; g->p.x1 = x + b; hline_clip(g);
+ break;
+ }
+
+ // Bottom half
+ switch((sectors & 0xF0)>>4) {
+ case 0x01:
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ break;
+ case 0x02:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ break;
+ case 0x03:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x; hline_clip(g);
+ break;
+ case 0x04:
+ g->p.y = y + b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x05:
+ g->p.y = y + b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x06:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x07:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x + a; hline_clip(g);
+ break;
+ case 0x08:
+ g->p.y = y + a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x09:
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0A:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0B:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x; hline_clip(g);
+ g->p.y = y + a; g->p.x = x + a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0C:
+ g->p.y = y + b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0D:
+ g->p.y = y + b; g->p.x = x; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x - a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0E:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - a; g->p.x1 = x + b; hline_clip(g);
+ break;
+ case 0x0F:
+ g->p.y = y + b; g->p.x = x - a; g->p.x1 = x + a; hline_clip(g);
+ g->p.y = y + a; g->p.x = x - b; g->p.x1 = x + b; hline_clip(g);
+ break;
+ }
+
+ if (P < 0)
+ P += 3 + 2*a++;
+ else
+ P += 5 + 2*(a++ - b--);
+ } while(a < b);
+
+ // Top half
+ if (sectors & 0x02) { g->p.y = y - a; g->p.x = x; g->p.x1 = x + a; hline_clip(g); }
+ else if (sectors & 0x01) { g->p.y = y - a; g->p.x = x + a; drawpixel_clip(g); }
+ if (sectors & 0x04) { g->p.y = y - a; g->p.x = x - a; g->p.x1 = x; hline_clip(g); }
+ else if (sectors & 0x08) { g->p.y = y - a; g->p.x = x - a; drawpixel_clip(g); }
+
+ // Bottom half
+ if (sectors & 0x40) { g->p.y = y + a; g->p.x = x; g->p.x1 = x + a; hline_clip(g); }
+ else if (sectors & 0x80) { g->p.y = y + a; g->p.x = x + a; drawpixel_clip(g); }
+ if (sectors & 0x20) { g->p.y = y + a; g->p.x = x - a; g->p.x1 = x; hline_clip(g); }
+ else if (sectors & 0x10) { g->p.y = y + a; g->p.x = x - a; drawpixel_clip(g); }
+
+ autoflush(g);
+ MUTEX_EXIT(g);
+ }
+#endif
+
#if GDISP_NEED_ARC
- #if !GMISC_NEED_FIXEDTRIG && !GMISC_NEED_FASTTRIG
+ #if (!GMISC_NEED_FIXEDTRIG && !GMISC_NEED_FASTTRIG) || !GFX_USE_GMISC
#include <math.h>
#endif
@@ -2102,27 +2327,34 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c
autoflush(g);
MUTEX_EXIT(g);
}
-
#endif
-#if GDISP_NEED_ARC
+#if GDISP_NEED_ARC || GDISP_NEED_ARCSECTORS
void gdispGDrawRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
if (2*radius > cx || 2*radius > cy) {
gdispGDrawBox(g, x, y, cx, cy, color);
return;
}
- gdispGDrawArc(g, x+radius, y+radius, radius, 90, 180, color);
+
+ #if GDISP_NEED_ARCSECTORS
+ gdispGFillArcSectors(g, x+radius, y+radius, radius, 0x0C, color);
+ gdispGFillArcSectors(g, x+cx-1-radius, y+radius, radius, 0x03, color);
+ gdispGFillArcSectors(g, x+cx-1-radius, y+cy-1-radius, radius, 0xC0, color);
+ gdispGFillArcSectors(g, x+radius, y+cy-1-radius, radius, 0x30, color);
+ #else
+ gdispGDrawArc(g, x+radius, y+radius, radius, 90, 180, color);
+ gdispGDrawArc(g, x+cx-1-radius, y+radius, radius, 0, 90, color);
+ gdispGDrawArc(g, x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
+ gdispGDrawArc(g, x+radius, y+cy-1-radius, radius, 180, 270, color);
+ #endif
gdispGDrawLine(g, x+radius+1, y, x+cx-2-radius, y, color);
- gdispGDrawArc(g, x+cx-1-radius, y+radius, radius, 0, 90, color);
gdispGDrawLine(g, x+cx-1, y+radius+1, x+cx-1, y+cy-2-radius, color);
- gdispGDrawArc(g, x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
gdispGDrawLine(g, x+radius+1, y+cy-1, x+cx-2-radius, y+cy-1, color);
- gdispGDrawArc(g, x+radius, y+cy-1-radius, radius, 180, 270, color);
gdispGDrawLine(g, x, y+radius+1, x, y+cy-2-radius, color);
}
#endif
-#if GDISP_NEED_ARC
+#if GDISP_NEED_ARC || GDISP_NEED_ARCSECTORS
void gdispGFillRoundedBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, coord_t radius, color_t color) {
coord_t radius2;
@@ -2131,12 +2363,19 @@ void gdispGBlitArea(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, c
gdispGFillArea(g, x, y, cx, cy, color);
return;
}
- gdispGFillArc(g, x+radius, y+radius, radius, 90, 180, color);
+ #if GDISP_NEED_ARCSECTORS
+ gdispGFillArcSectors(g, x+radius, y+radius, radius, 0x0C, color);
+ gdispGFillArcSectors(g, x+cx-1-radius, y+radius, radius, 0x03, color);
+ gdispGFillArcSectors(g, x+cx-1-radius, y+cy-1-radius, radius, 0xC0, color);
+ gdispGFillArcSectors(g, x+radius, y+cy-1-radius, radius, 0x30, color);
+ #else
+ gdispGFillArc(g, x+radius, y+radius, radius, 90, 180, color);
+ gdispGFillArc(g, x+cx-1-radius, y+radius, radius, 0, 90, color);
+ gdispGFillArc(g, x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
+ gdispGFillArc(g, x+radius, y+cy-1-radius, radius, 180, 270, color);
+ #endif
gdispGFillArea(g, x+radius+1, y, cx-radius2, radius, color);
- gdispGFillArc(g, x+cx-1-radius, y+radius, radius, 0, 90, color);
- gdispGFillArc(g, x+cx-1-radius, y+cy-1-radius, radius, 270, 360, color);
gdispGFillArea(g, x+radius+1, y+cy-radius, cx-radius2, radius, color);
- gdispGFillArc(g, x+radius, y+cy-1-radius, radius, 180, 270, color);
gdispGFillArea(g, x, y+radius, cx, cy-radius2, color);
}
#endif
diff --git a/src/gdisp/sys_defs.h b/src/gdisp/sys_defs.h
index 6ebfe8b5..e5580e90 100644
--- a/src/gdisp/sys_defs.h
+++ b/src/gdisp/sys_defs.h
@@ -430,6 +430,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Start a streaming operation.
* @details Stream data to a window on the display sequentially and very fast.
+ * @pre GDISP_NEED_STREAMING must be TRUE in your gfxconf.h
* @note While streaming is in operation - no other calls to GDISP functions
* can be made (with the exception of @p gdispBlendColor() and streaming
* functions). If a call is made (eg in a multi-threaded application) the other
@@ -456,6 +457,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Send pixel data to the stream.
* @details Write a pixel to the next position in the streamed area and increment the position
+ * @pre GDISP_NEED_STREAMING must be TRUE in your gfxconf.h
* @pre @p gdispStreamStart() has been called.
* @note If the gdispStreamStart() has not been called (or failed due to clipping), the
* data provided here is simply thrown away.
@@ -471,6 +473,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Finish the current streaming operation.
* @details Completes the current streaming operation and allows other GDISP calls to operate again.
+ * @pre GDISP_NEED_STREAMING must be TRUE in your gfxconf.h
* @pre @p gdispStreamStart() has been called.
* @note If the gdispStreamStart() has not been called (or failed due to clipping), this
* call is simply ignored.
@@ -488,6 +491,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_CLIP || defined(__DOXYGEN__)
/**
* @brief Clip all drawing to the defined area.
+ * @pre GDISP_NEED_CLIP must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The start position
@@ -504,6 +508,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_CIRCLE || defined(__DOXYGEN__)
/**
* @brief Draw a circle.
+ * @pre GDISP_NEED_CIRCLE must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The center of the circle
@@ -517,6 +522,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a filled circle.
+ * @pre GDISP_NEED_CIRCLE must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The center of the circle
@@ -534,6 +540,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_ELLIPSE || defined(__DOXYGEN__)
/**
* @brief Draw an ellipse.
+ * @pre GDISP_NEED_ELLIPSE must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The center of the ellipse
@@ -547,6 +554,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a filled ellipse.
+ * @pre GDISP_NEED_ELLIPSE must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The center of the ellipse
@@ -560,10 +568,70 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#endif
/* Arc Functions */
+#if GDISP_NEED_ARCSECTORS || defined(__DOXYGEN__)
+ /**
+ * @brief Draw a selection of 45 degree arcs of a circle
+ * @pre GDISP_NEED_ARCSECTORS 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] radius The radius of the circle
+ * @param[in] sectors Bits determine which sectors are drawn.
+ * Bits go anti-clockwise from the 0 degree mark (y = 0, x is positive), as follows:
+ * bit 0 - upper right right -----
+ * bit 1 - upper upper right /2 1\
+ * bit 2 - upper upper left /3 0\
+ * bit 3 - upper left left \4 7/
+ * bit 4 - lower left left \5 6/
+ * bit 5 - lower lower left -----
+ * bit 6 - lower lower right
+ * bit 7 - lower left left
+ * @param[in] color The color to use
+ *
+ * @note This is a more limited versions of the general arc drawing routine. It
+ * doesn't require trig libraries or tables or floating point and is smaller in code size.
+ * There is probably little point in including both this and the general
+ * arc routine as the general arc routine can do everything this can do.
+ *
+ * @api
+ */
+ void gdispGDrawArcSectors(GDisplay *g, coord_t x, coord_t y, coord_t radius, uint8_t sectors, color_t color);
+ #define gdispDrawArcSectors(x,y,r,s,c) gdispGDrawArcSectors(GDISP,x,y,r,s,c)
+
+ /**
+ * @brief Fill a selection of 45 degree arcs of a circle
+ * @pre GDISP_NEED_ARCSECTORS 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] radius The radius of the circle
+ * @param[in] sectors Bits determine which sectors are drawn.
+ * Bits go anti-clockwise from the 0 degree mark (y = 0, x is positive), as follows:
+ * bit 0 - upper right right -----
+ * bit 1 - upper upper right /2 1\
+ * bit 2 - upper upper left /3 0\
+ * bit 3 - upper left left \4 7/
+ * bit 4 - lower left left \5 6/
+ * bit 5 - lower lower left -----
+ * bit 6 - lower lower right
+ * bit 7 - lower left left
+ * @param[in] color The color to use
+ *
+ * @note This is a more limited versions of the general arc filling routine. It
+ * doesn't require trig libraries or tables or floating point and is smaller in code size.
+ * There is probably little point in including both this and the general
+ * arc routine as the general arc routine can do everything this can do.
+ *
+ * @api
+ */
+ void gdispGFillArcSectors(GDisplay *g, coord_t x, coord_t y, coord_t radius, uint8_t sectors, color_t color);
+ #define gdispFillArcSectors(x,y,r,s,c) gdispGFillArcSectors(GDISP,x,y,r,s,c)
+#endif
#if GDISP_NEED_ARC || defined(__DOXYGEN__)
/*
* @brief Draw an arc.
+ * @pre GDISP_NEED_ARC must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x0,y0 The center point
@@ -572,6 +640,15 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
* @param[in] end The end angle (0 to 360)
* @param[in] color The color of the arc
*
+ * @note If you are just doing 45 degree angles consider using @p gdispDrawArcSectors() instead.
+ * @note This routine requires trig support. It can either come from your C runtime library
+ * cos() and sin() which requires floating point support (and is slow), or you can define GFX_USE_GMISC
+ * and either GMISC_NEED_FIXEDTRIG or GMISC_NEED_FASTTRIG.
+ * GMISC_NEED_FASTTRIG uses table based floating point trig operations.
+ * GMISC_NEED_FIXEDTRIG uses fixed point integer trig operations.
+ * Note accuracy on both the table based options are more than adequate for the one degree
+ * resolution provided by these arc routines. Both are much faster than your C runtime library.
+ *
* @api
*/
void gdispGDrawArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
@@ -579,7 +656,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/*
* @brief Draw a filled arc.
- * @note Not very efficient currently - does lots of overdrawing
+ * @pre GDISP_NEED_ARC must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x0,y0 The center point
@@ -588,6 +665,15 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
* @param[in] end The end angle (0 to 360)
* @param[in] color The color of the arc
*
+ * @note If you are just doing 45 degree angles consider using @p gdispFillArcSectors() instead.
+ * @note This routine requires trig support. It can either come from your C runtime library
+ * cos() and sin() which requires floating point support (and is slow), or you can define GFX_USE_GMISC
+ * and either GMISC_NEED_FIXEDTRIG or GMISC_NEED_FASTTRIG.
+ * GMISC_NEED_FASTTRIG uses table based floating point trig operations.
+ * GMISC_NEED_FIXEDTRIG uses fixed point integer trig operations.
+ * Note accuracy on both the table based options are more than adequate for the one degree
+ * resolution provided by these arc routines. Both are much faster than your C runtime library.
+ *
* @api
*/
void gdispGFillArc(GDisplay *g, coord_t x, coord_t y, coord_t radius, coord_t startangle, coord_t endangle, color_t color);
@@ -600,6 +686,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Get the color of a pixel.
* @return The color of the pixel.
+ * @pre GDISP_NEED_PIXELREAD must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position of the pixel
@@ -636,6 +723,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_CONTROL || defined(__DOXYGEN__)
/**
* @brief Control hardware specific parts of the display. eg powermodes, backlight etc
+ * @pre GDISP_NEED_CONTROL must be TRUE in your gfxconf.h
* @note Depending on the hardware implementation this function may not
* support some codes. They will be ignored.
*
@@ -654,6 +742,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_QUERY || defined(__DOXYGEN__)
/**
* @brief Query a property of the display.
+ * @pre GDISP_NEED_QUERY must be TRUE in your gfxconf.h
* @note The result must be typecast to the correct type.
* @note An unsupported query will return (void *)-1.
*
@@ -669,6 +758,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_CONVEX_POLYGON || defined(__DOXYGEN__)
/**
* @brief Draw an enclosed polygon (convex, non-convex or complex).
+ * @pre GDISP_NEED_CONVEX_POLYGON must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] tx, ty Transform all points in pntarray by tx, ty
@@ -684,6 +774,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Fill a convex polygon
* @details Doesn't handle non-convex or complex polygons.
+ * @pre GDISP_NEED_CONVEX_POLYGON must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] tx, ty Transform all points in pntarray by tx, ty
@@ -708,6 +799,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
* @brief Draw a line with a specified thickness
* @details The line thickness is specified in pixels. The line ends can
* be selected to be either flat or round.
+ * @pre GDISP_NEED_CONVEX_POLYGON must be TRUE in your gfxconf.h
* @note Uses gdispGFillConvexPoly() internally to perform the drawing.
*
* @param[in] g The display to use
@@ -728,6 +820,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
#if GDISP_NEED_TEXT || defined(__DOXYGEN__)
/**
* @brief Draw a text character.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position for the text
@@ -742,6 +835,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a text character with a filled background.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position for the text
@@ -757,6 +851,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a text string.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position for the text
@@ -771,6 +866,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a text string.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position for the text
@@ -786,6 +882,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a text string vertically centered within the specified box.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The position for the text (need to define top-right or base-line - check code)
@@ -802,6 +899,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a text string vertically centered within the specified box. The box background is filled with the specified background color.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
* @note The entire box is filled
*
* @param[in] g The display to use
@@ -821,6 +919,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Get a metric of a font.
* @return The metric requested in pixels.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] font The font to test
* @param[in] metric The metric to measure
@@ -832,6 +931,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Get the pixel width of a character.
* @return The width of the character in pixels. Does not include any between character padding.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] c The character to draw
* @param[in] font The font to use
@@ -843,6 +943,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Get the pixel width of a string.
* @return The width of the string in pixels.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] str The string to measure
* @param[in] font The font to use
@@ -855,6 +956,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
* @brief Find a font and return it.
* @details The supplied name is matched against the font name. A '*' will replace 0 or more characters.
* @return Returns a font or NULL if no matching font could be found.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] name The font name to find.
*
@@ -866,6 +968,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Release a font after use.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] font The font to release.
*
@@ -877,6 +980,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
* @brief Make a scaled copy of an existing font.
* @details Allocates memory for new font metadata using gfxAlloc, remember to close font after use!
* @return A new font or NULL if out of memory.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] font The base font to use.
* @param[in] scale_x The scale factor in horizontal direction.
@@ -887,6 +991,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Get the name of the specified font.
* @returns The name of the font.
+ * @pre GDISP_NEED_TEXT must be TRUE in your gfxconf.h
*
* @param[in] font The font to get the name for.
*
@@ -897,9 +1002,10 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/* Extra Arc Functions */
-#if GDISP_NEED_ARC || defined(__DOXYGEN__)
+#if GDISP_NEED_ARC || GDISP_NEED_ARCSECTORS || defined(__DOXYGEN__)
/**
* @brief Draw a rectangular box with rounded corners
+ * @pre GDISP_NEED_ARC or GDISP_NEED_ARCSECTORS must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The start position
@@ -914,6 +1020,7 @@ void gdispGDrawBox(GDisplay *g, coord_t x, coord_t y, coord_t cx, coord_t cy, co
/**
* @brief Draw a filled rectangular box with rounded corners
+ * @pre GDISP_NEED_ARC or GDISP_NEED_ARCSECTORS must be TRUE in your gfxconf.h
*
* @param[in] g The display to use
* @param[in] x,y The start position