mirror of
https://github.com/espruino/Espruino.git
synced 2025-12-08 19:06:15 +00:00
Graphics: You can now do g.fillRect({x,y,x2,y2,r}) for rounded rectangles
This commit is contained in:
parent
3064ca5653
commit
9c5e5f2355
@ -17,6 +17,7 @@
|
||||
g.wrapString now splits long words if they are too long for a line
|
||||
Add Storage.getStats to get more fine-grained info about Storage
|
||||
Add Bangle.midnight event that can be used for housekeeping tasks
|
||||
Graphics: You can now do `g.fillRect({x,y,x2,y2,r})` for rounded rectangles
|
||||
|
||||
2v12 : nRF52840: Flow control XOFF is now sent at only 3/8th full - delays in BLE mean we can sometimes fill our 1k input buffer otherwise
|
||||
__FILE__ is now set correctly for apps (fixes 2v11 regression)
|
||||
|
||||
@ -425,7 +425,7 @@ static void graphicsSetPixelDeviceBlended(JsGraphics *gfx, int x, int y, int amt
|
||||
graphicsSetPixelDevice(gfx, x, y, col);
|
||||
}
|
||||
|
||||
static void graphicsFillRectDevice(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col) {
|
||||
void graphicsFillRectDevice(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col) {
|
||||
if (x1>x2) {
|
||||
int t = x1;
|
||||
x1 = x2;
|
||||
|
||||
@ -206,6 +206,7 @@ unsigned int graphicsGetPixel(JsGraphics *gfx, int x, int y);
|
||||
void graphicsClear(JsGraphics *gfx);
|
||||
void graphicsFillRect(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col);
|
||||
void graphicsFallbackFillRect(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col); // Simple fillrect - doesn't call device-specific FR
|
||||
void graphicsFillRectDevice(JsGraphics *gfx, int x1, int y1, int x2, int y2, unsigned int col); // fillrect using device coordinates
|
||||
void graphicsFallbackScroll(JsGraphics *gfx, int xdir, int ydir, int x1, int y1, int x2, int y2);
|
||||
void graphicsDrawRect(JsGraphics *gfx, int x1, int y1, int x2, int y2);
|
||||
void graphicsDrawEllipse(JsGraphics *gfx, int x, int y, int x2, int y2);
|
||||
|
||||
@ -901,7 +901,8 @@ JsVar *jswrap_graphics_clear(JsVar *parent, bool resetState) {
|
||||
return jsvLockAgain(parent);
|
||||
}
|
||||
|
||||
void _jswrap_graphics_getRect(JsVar *opt, int *x1, int *y1, int *x2, int *y2) {
|
||||
void _jswrap_graphics_getRect(JsVar *opt, int *x1, int *y1, int *x2, int *y2, int *r) {
|
||||
*r = 0;
|
||||
if (jsvIsObject(opt)) {
|
||||
int w = -1,h = -1;
|
||||
jsvConfigObject configs[] = {
|
||||
@ -913,6 +914,7 @@ void _jswrap_graphics_getRect(JsVar *opt, int *x1, int *y1, int *x2, int *y2) {
|
||||
{"y2", JSV_INTEGER, y2},
|
||||
{"w", JSV_INTEGER, &w},
|
||||
{"h", JSV_INTEGER, &h},
|
||||
{"r", JSV_INTEGER, r}
|
||||
};
|
||||
jsvReadConfigObject(opt, configs, sizeof(configs) / sizeof(jsvConfigObject));
|
||||
if (w>=0) *x2 = *x1 + w;
|
||||
@ -921,6 +923,53 @@ void _jswrap_graphics_getRect(JsVar *opt, int *x1, int *y1, int *x2, int *y2) {
|
||||
*x1 = jsvGetInteger(opt);
|
||||
}
|
||||
|
||||
JsVar *_jswrap_graphics_fillRect_col(JsVar *parent, JsVar *opt, int y1, int x2, int y2, bool isFgCol) {
|
||||
int x1, r;
|
||||
_jswrap_graphics_getRect(opt, &x1, &y1, &x2, &y2, &r);
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
uint32_t col = isFgCol ? gfx.data.fgColor : gfx.data.bgColor;
|
||||
#ifndef SAVE_ON_FLASH
|
||||
if (r>0) {
|
||||
// rounded rects
|
||||
graphicsToDeviceCoordinates(&gfx, &x1, &y1);
|
||||
graphicsToDeviceCoordinates(&gfx, &x2, &y2);
|
||||
int x,y;
|
||||
if (x1 > x2) { x = x1; x1 = x2; x2 = x; }
|
||||
if (y1 > y2) { y = y1; y1 = y2; y2 = y; }
|
||||
// clip if radius too big
|
||||
x = (x2-x1)/2;
|
||||
y = (y2-y1)/2;
|
||||
if (x<r) r=x;
|
||||
if (y<r) r=y;
|
||||
// rect in middle
|
||||
int cx1 = x1+r, cx2 = x2-r;
|
||||
int cy1 = y1+r, cy2 = y2-r;
|
||||
graphicsFillRectDevice(&gfx, x1, cy1, x2, cy2, col);
|
||||
// draw rounded top and bottom
|
||||
int dx = 0;
|
||||
int dy = r;
|
||||
int r2 = r*r;
|
||||
int err = r2-(2*r-1)*r2;
|
||||
int e2;
|
||||
bool changed = false;
|
||||
do {
|
||||
changed = false;
|
||||
e2 = 2*err;
|
||||
if (e2 < (2*dx+1)*r2) { dx++; err += (2*dx+1)*r2; changed=true; }
|
||||
if (e2 > -(2*dy-1)*r2) {
|
||||
// draw only just before we change Y, to avoid a bunch of overdraw
|
||||
graphicsFillRectDevice(&gfx, cx1-dx,cy2+dy, cx2+dx,cy2+dy, col);
|
||||
graphicsFillRectDevice(&gfx, cx1-dx,cy1-dy, cx2+dx,cy1-dy, col);
|
||||
dy--; err -= (2*dy-1)*r2; changed=true;
|
||||
}
|
||||
} while (changed && dy >= 0);
|
||||
} else
|
||||
#endif
|
||||
graphicsFillRect(&gfx, x1,y1,x2,y2,col);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
return jsvLockAgain(parent);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
@ -936,16 +985,16 @@ void _jswrap_graphics_getRect(JsVar *opt, int *x1, int *y1, int *x2, int *y2) {
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Fill a rectangular area in the Foreground Color
|
||||
|
||||
On devices with enough memory, you can specify `{x,y,x2,y2,r}` as the first
|
||||
argument, which allows you to draw a rounded rectangle.
|
||||
*/
|
||||
JsVar *jswrap_graphics_fillRect(JsVar *parent, JsVar *opt, int y1, int x2, int y2) {
|
||||
int x1;
|
||||
_jswrap_graphics_getRect(opt, &x1, &y1, &x2, &y2);
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
graphicsFillRect(&gfx, x1,y1,x2,y2,gfx.data.fgColor);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
return jsvLockAgain(parent);
|
||||
return _jswrap_graphics_fillRect_col(parent,opt,y1,x2,y2,true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/*JSON{
|
||||
"type" : "method",
|
||||
"class" : "Graphics",
|
||||
@ -962,14 +1011,12 @@ JsVar *jswrap_graphics_fillRect(JsVar *parent, JsVar *opt, int y1, int x2, int y
|
||||
"return_object" : "Graphics"
|
||||
}
|
||||
Fill a rectangular area in the Background Color
|
||||
|
||||
On devices with enough memory, you can specify `{x,y,x2,y2,r}` as the first
|
||||
argument, which allows you to draw a rounded rectangle.
|
||||
*/
|
||||
JsVar *jswrap_graphics_clearRect(JsVar *parent, JsVar *opt, int y1, int x2, int y2) {
|
||||
int x1;
|
||||
_jswrap_graphics_getRect(opt, &x1, &y1, &x2, &y2);
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
graphicsFillRect(&gfx, x1,y1,x2,y2,gfx.data.bgColor);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
return jsvLockAgain(parent);
|
||||
return _jswrap_graphics_fillRect_col(parent,opt,y1,x2,y2,false);
|
||||
}
|
||||
|
||||
/*JSON{
|
||||
@ -989,8 +1036,8 @@ JsVar *jswrap_graphics_clearRect(JsVar *parent, JsVar *opt, int y1, int x2, int
|
||||
Draw an unfilled rectangle 1px wide in the Foreground Color
|
||||
*/
|
||||
JsVar *jswrap_graphics_drawRect(JsVar *parent, JsVar *opt, int y1, int x2, int y2) {
|
||||
int x1;
|
||||
_jswrap_graphics_getRect(opt, &x1, &y1, &x2, &y2);
|
||||
int x1, r;
|
||||
_jswrap_graphics_getRect(opt, &x1, &y1, &x2, &y2, &r);
|
||||
JsGraphics gfx; if (!graphicsGetFromVar(&gfx, parent)) return 0;
|
||||
graphicsDrawRect(&gfx, x1,y1,x2,y2);
|
||||
graphicsSetVar(&gfx); // gfx data changed because modified area
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user