diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H
index 5de983554c..0f25756d60 100644
--- a/FL/Fl_Graphics_Driver.H
+++ b/FL/Fl_Graphics_Driver.H
@@ -264,6 +264,9 @@ public:
virtual void rect(int x, int y, int w, int h);
virtual void focus_rect(int x, int y, int w, int h);
virtual void rectf(int x, int y, int w, int h);
+ virtual void _rbox(int fill, int x, int y, int w, int h, int r);
+ virtual void rounded_rect(int x, int y, int w, int h, int r);
+ virtual void rounded_rectf(int x, int y, int w, int h, int r);
// the default implementation is most likely enough
virtual void colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b);
virtual void line(int x, int y, int x1, int y1);
diff --git a/FL/fl_draw.H b/FL/fl_draw.H
index 359405b7d0..fc3e401ca4 100644
--- a/FL/fl_draw.H
+++ b/FL/fl_draw.H
@@ -290,6 +290,15 @@ inline void fl_rect(int x, int y, int w, int h) {
fl_graphics_driver->rect(x, y, w, h);
}
+/**
+ Draw a 1-pixel rounded border \e inside the given bounding box.
+ The radius code is optimized for speed and works best for values between
+ 5 and 15 units.
+ */
+inline void fl_rounded_rect(int x, int y, int w, int h, int r) {
+ fl_graphics_driver->rounded_rect(x, y, w, h, r);
+}
+
/**
Draw a 1-pixel border \e inside the given bounding box.
This is the same as fl_rect(int x, int y, int w, int h) but with
@@ -320,6 +329,14 @@ inline void fl_rectf(int x, int y, int w, int h) {
fl_graphics_driver->rectf(x, y, w, h);
}
+/** Color with current color a rounded rectangle that exactly fills the given bounding box.
+ The radius code is optimized for speed and works best for values between
+ 5 and 15 units.
+*/
+inline void fl_rounded_rectf(int x, int y, int w, int h, int r) {
+ fl_graphics_driver->rounded_rectf(x, y, w, h, r);
+}
+
/** Color with passed color a rectangle that exactly fills the given bounding box. */
inline void fl_rectf(int x, int y, int w, int h, Fl_Color c) {
fl_color(c);
diff --git a/documentation/src/drawing.dox b/documentation/src/drawing.dox
index a80286f686..f69796d248 100644
--- a/documentation/src/drawing.dox
+++ b/documentation/src/drawing.dox
@@ -461,6 +461,12 @@ void fl_rect(int x, int y, int w, int h, Fl_Color c)
\par
Draw a 1-pixel border \e inside this bounding box.
+void fl_rounded_rect(int x, int y, int w, int h, int radius)
+void fl_rounded_rectf(int x, int y, int w, int h, int radius)
+
+\par
+Draw an outlined or filled rectangle with rounded corners.
+
void fl_line(int x, int y, int x1, int y1)
void fl_line(int x, int y, int x1, int y1, int x2, int y2)
diff --git a/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx
index 95f79ee223..9d120961e9 100644
--- a/src/Fl_Graphics_Driver.cxx
+++ b/src/Fl_Graphics_Driver.cxx
@@ -455,6 +455,50 @@ void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {}
/** see fl_rectf() */
void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {}
+void Fl_Graphics_Driver::_rbox(int fill, int x, int y, int w, int h, int r) {
+ static double lut[] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
+ if (r == 5) r = 4; // use only even sizes for small corners (STR #2943)
+ if (r == 7) r = 8; // note: 8 is better than 6 (really)
+ double xd = x, yd = y, rd = (x+w-1), bd = (y+h-1);
+ double rr = r;
+ if (fill) begin_polygon(); else begin_loop();
+ // top left
+ transformed_vertex(xd+lut[0]*rr, yd+lut[4]*rr);
+ transformed_vertex(xd+lut[1]*rr, yd+lut[3]*rr);
+ transformed_vertex(xd+lut[2]*rr, yd+lut[2]*rr);
+ transformed_vertex(xd+lut[3]*rr, yd+lut[1]*rr);
+ transformed_vertex(xd+lut[4]*rr, yd+lut[0]*rr);
+ // top right
+ transformed_vertex(rd-lut[4]*rr, yd+lut[0]*rr);
+ transformed_vertex(rd-lut[3]*rr, yd+lut[1]*rr);
+ transformed_vertex(rd-lut[2]*rr, yd+lut[2]*rr);
+ transformed_vertex(rd-lut[1]*rr, yd+lut[3]*rr);
+ transformed_vertex(rd-lut[0]*rr, yd+lut[4]*rr);
+ // bottom right
+ transformed_vertex(rd-lut[0]*rr, bd-lut[4]*rr);
+ transformed_vertex(rd-lut[1]*rr, bd-lut[3]*rr);
+ transformed_vertex(rd-lut[2]*rr, bd-lut[2]*rr);
+ transformed_vertex(rd-lut[3]*rr, bd-lut[1]*rr);
+ transformed_vertex(rd-lut[4]*rr, bd-lut[0]*rr);
+ // bottom left
+ transformed_vertex(xd+lut[4]*rr, bd-lut[0]*rr);
+ transformed_vertex(xd+lut[3]*rr, bd-lut[1]*rr);
+ transformed_vertex(xd+lut[2]*rr, bd-lut[2]*rr);
+ transformed_vertex(xd+lut[1]*rr, bd-lut[3]*rr);
+ transformed_vertex(xd+lut[0]*rr, bd-lut[4]*rr);
+ if (fill) fl_end_polygon(); else fl_end_loop();
+}
+
+/** see fl_rrect() */
+void Fl_Graphics_Driver::rounded_rect(int x, int y, int w, int h, int r) {
+ _rbox(0, x, y, w, h, r);
+}
+
+/** see fl_rrectf() */
+void Fl_Graphics_Driver::rounded_rectf(int x, int y, int w, int h, int r) {
+ _rbox(1, x, y, w, h, r);
+}
+
void Fl_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
color(r, g, b);
rectf(x, y, w, h);
diff --git a/src/fl_rounded_box.cxx b/src/fl_rounded_box.cxx
index df41b4f6ed..f1b351144d 100644
--- a/src/fl_rounded_box.cxx
+++ b/src/fl_rounded_box.cxx
@@ -23,35 +23,18 @@
// RS = max. corner radius
// BW = box shadow width
-#define RN 5
#define RS (Fl::box_border_radius_max())
#define BW (Fl::box_shadow_width())
-static double offset[RN] = { 0.0, 0.07612, 0.29289, 0.61732, 1.0};
-
-static inline void fl_vertex_r(double x, double y) {
- fl_vertex(x + 0.5, y + 0.5);
-}
-
static void rbox(int fill, int x, int y, int w, int h) {
- int i;
int rs, rsy;
rs = w*2/5; rsy = h*2/5;
if (rs > rsy) rs = rsy; // use smaller radius
if (rs > RS) rs = RS;
- if (rs == 5) rs = 4; // use only even sizes for small corners (STR #2943)
- if (rs == 7) rs = 8; // note: 8 is better than 6 (really)
-
- if (fill) fl_begin_polygon(); else fl_begin_loop();
- for (i=0; i