From e00da67278197c83a5b2a12160d1f30c91e92902 Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Wed, 23 Nov 2022 14:43:25 +0100 Subject: [PATCH 1/4] Refactor code to make rounded rectangles accessible This adds fl_rrect and fl_rrectf (note the additional `r`) so the user can draw rounded rectangles. This uses existing and optimised code that is rearranged. --- FL/Fl_Graphics_Driver.H | 3 +++ FL/fl_draw.H | 17 +++++++++++++++ src/Fl_Graphics_Driver.cxx | 44 ++++++++++++++++++++++++++++++++++++++ src/fl_rounded_box.cxx | 24 ++++----------------- 4 files changed, 68 insertions(+), 20 deletions(-) diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 5de983554c..0bf7565ed6 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 rrect(int x, int y, int w, int h, int r); + virtual void rrectf(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..3927c34b40 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_rrect(int x, int y, int w, int h, int r) { + fl_graphics_driver->rrect(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_rrectf(int x, int y, int w, int h, int r) { + fl_graphics_driver->rrectf(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/src/Fl_Graphics_Driver.cxx b/src/Fl_Graphics_Driver.cxx index 95f79ee223..eeb6783ad1 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::rrect(int x, int y, int w, int h, int r) { + _rbox(0, x, y, w, h, r); +} + +/** see fl_rrectf() */ +void Fl_Graphics_Driver::rrectf(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..8b5c8b0a06 100644 --- a/src/fl_rounded_box.cxx +++ b/src/fl_rounded_box.cxx @@ -23,35 +23,19 @@ // 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 Date: Wed, 23 Nov 2022 14:51:20 +0100 Subject: [PATCH 2/4] Adds documentation for fl_rrect and fl_rrectf --- documentation/src/drawing.dox | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/documentation/src/drawing.dox b/documentation/src/drawing.dox index a80286f686..446e4dd51b 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_rrect(int x, int y, int w, int h, int radius) +void fl_rrectf(int x, int y, int w, int h, int radius) + +\par +Draw outlined or filled rectangles 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) From 99a6566770acc655d346faa235fb40cf82b0576c Mon Sep 17 00:00:00 2001 From: Matthias Melcher Date: Thu, 24 Nov 2022 10:15:03 +0100 Subject: [PATCH 3/4] Update rounded rectangle naming --- FL/Fl_Graphics_Driver.H | 4 ++-- FL/fl_draw.H | 8 ++++---- documentation/src/drawing.dox | 6 +++--- src/Fl_Graphics_Driver.cxx | 4 ++-- src/fl_rounded_box.cxx | 4 ++-- 5 files changed, 13 insertions(+), 13 deletions(-) diff --git a/FL/Fl_Graphics_Driver.H b/FL/Fl_Graphics_Driver.H index 0bf7565ed6..0f25756d60 100644 --- a/FL/Fl_Graphics_Driver.H +++ b/FL/Fl_Graphics_Driver.H @@ -265,8 +265,8 @@ public: 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 rrect(int x, int y, int w, int h, int r); - virtual void rrectf(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 3927c34b40..fc3e401ca4 100644 --- a/FL/fl_draw.H +++ b/FL/fl_draw.H @@ -295,8 +295,8 @@ inline void fl_rect(int x, int y, int w, int h) { The radius code is optimized for speed and works best for values between 5 and 15 units. */ -inline void fl_rrect(int x, int y, int w, int h, int r) { - fl_graphics_driver->rrect(x, y, w, h, r); +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); } /** @@ -333,8 +333,8 @@ inline void fl_rectf(int x, int y, int w, int h) { The radius code is optimized for speed and works best for values between 5 and 15 units. */ -inline void fl_rrectf(int x, int y, int w, int h, int r) { - fl_graphics_driver->rrectf(x, y, w, h, r); +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. */ diff --git a/documentation/src/drawing.dox b/documentation/src/drawing.dox index 446e4dd51b..f69796d248 100644 --- a/documentation/src/drawing.dox +++ b/documentation/src/drawing.dox @@ -461,11 +461,11 @@ 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_rrect(int x, int y, int w, int h, int radius) -void fl_rrectf(int x, int y, int w, int h, int radius) +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 outlined or filled rectangles with rounded corners. +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 eeb6783ad1..9d120961e9 100644 --- a/src/Fl_Graphics_Driver.cxx +++ b/src/Fl_Graphics_Driver.cxx @@ -490,12 +490,12 @@ void Fl_Graphics_Driver::_rbox(int fill, int x, int y, int w, int h, int r) { } /** see fl_rrect() */ -void Fl_Graphics_Driver::rrect(int x, int y, int w, int h, int r) { +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::rrectf(int x, int y, int w, int h, int r) { +void Fl_Graphics_Driver::rounded_rectf(int x, int y, int w, int h, int r) { _rbox(1, x, y, w, h, r); } diff --git a/src/fl_rounded_box.cxx b/src/fl_rounded_box.cxx index 8b5c8b0a06..74da398311 100644 --- a/src/fl_rounded_box.cxx +++ b/src/fl_rounded_box.cxx @@ -33,9 +33,9 @@ static void rbox(int fill, int x, int y, int w, int h) { if (rs > rsy) rs = rsy; // use smaller radius if (rs > RS) rs = RS; if (fill) - fl_rrectf(x, y, w, h, rs); + fl_rounded_rectf(x, y, w, h, rs); else - fl_rrect(x, y, w, h, rs); + fl_rounded_rect(x, y, w, h, rs); } static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) { From 1ba1b3f46469501d642fa19f539b4e346aad4137 Mon Sep 17 00:00:00 2001 From: Albrecht Schlosser Date: Thu, 24 Nov 2022 11:46:29 +0100 Subject: [PATCH 4/4] Remove unused variable --- src/fl_rounded_box.cxx | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fl_rounded_box.cxx b/src/fl_rounded_box.cxx index 74da398311..f1b351144d 100644 --- a/src/fl_rounded_box.cxx +++ b/src/fl_rounded_box.cxx @@ -27,7 +27,6 @@ #define BW (Fl::box_shadow_width()) 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