
Here is a version for filled rectangles. Performance is roughly the same, faster for r<=12, slower for larger radii. Performance is an issue here, on my Bangle2, "bFillRoundedRectangle(10,10,160,160,13);" takes about 85ms. For UI use, i think a LUT for rounded corners would be the best approach. All coordinates needed for a circle covering the complete screen would take up just 52 bytes.
function bFillRoundedRectangle (x1,y1,x2,y2,r) { var f = 1  r; var ddF_x = 0; var ddF_y = 2 * r; var x = 0; var y = r; g.fillRect(x1+r,y1,x2r,y2); var cx1=x1+r; var cx2=x2r; var cy1=y1+r; var cy2=y2r; while(x < y) { if(f >= 0) { y; ddF_y += 2; f += ddF_y; } x++; ddF_x += 2; f += ddF_x + 1; g.drawLine(cx1x,cy1y,cx1x,cy2+y); g.drawLine(cx1y,cy1x,cx1y,cy2+x); g.drawLine(cx2+x,cy1y,cx2+x,cy2+y); g.drawLine(cx2+y,cy1x,cx2+y,cy2+x); } }

Great, thank you!
Concerning performance: you are using the C implementation of Bresenham which assumes that multiplications take longer than additions.
However, in Espruino, variable lookup may be more expensive than any kind of addition/multiplication. Thus, the BASIC implementation might be more efficient than yours (this is the one I used for the moon phase visualization).
It would be interesting to analyze that dependency...
this code is more compact than mine and doesn't need Math.sin, at least  but I'd have to modify it in order to be able to draw and/or fill a rounded rectangle. Radii below 12 are certainly the most common ones.
Thanks a lot for this contribution!