diff --git a/docs/releases.txt b/docs/releases.txt index 0e520252..1ff7828e 100644 --- a/docs/releases.txt +++ b/docs/releases.txt @@ -17,6 +17,7 @@ FIX: Fixing and improving arc rendering functions FIX: Preventing possible crash when no valid GWIN default font has been set FIX: Updating Windows binaries of the font encoder to improve compatibility FIX: Fix Progressbar bounds checking and decrementing +FEATURE: Added a dual circle with the same center drawing routine to GDISP *** Release 2.6 *** diff --git a/gfxconf.example.h b/gfxconf.example.h index 79ca89b2..8b3a53b5 100644 --- a/gfxconf.example.h +++ b/gfxconf.example.h @@ -68,6 +68,7 @@ //#define GDISP_NEED_VALIDATION TRUE //#define GDISP_NEED_CLIP TRUE //#define GDISP_NEED_CIRCLE FALSE +//#define GDISP_NEED_DUALCIRCLE FALSE //#define GDISP_NEED_ELLIPSE FALSE //#define GDISP_NEED_ARC FALSE //#define GDISP_NEED_ARCSECTORS FALSE 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