mirror of
https://github.com/fltk/fltk.git
synced 2026-05-30 21:25:30 +08:00
Refactor code to make rounded rectangles accessible (#553)
This adds fl_rounded_rect and fl_rounded_rectf so the user can draw rounded rectangles. This uses existing and optimised code that is rearranged.
This commit is contained in:
@@ -264,6 +264,9 @@ public:
|
|||||||
virtual void rect(int x, int y, int w, int h);
|
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 focus_rect(int x, int y, int w, int h);
|
||||||
virtual void rectf(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
|
// 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 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);
|
virtual void line(int x, int y, int x1, int y1);
|
||||||
|
|||||||
@@ -290,6 +290,15 @@ inline void fl_rect(int x, int y, int w, int h) {
|
|||||||
fl_graphics_driver->rect(x, y, w, 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.
|
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
|
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);
|
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. */
|
/** 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) {
|
inline void fl_rectf(int x, int y, int w, int h, Fl_Color c) {
|
||||||
fl_color(c);
|
fl_color(c);
|
||||||
|
|||||||
@@ -461,6 +461,12 @@ void fl_rect(int x, int y, int w, int h, Fl_Color c)
|
|||||||
\par
|
\par
|
||||||
Draw a 1-pixel border \e inside this bounding box.
|
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) <br>
|
void fl_line(int x, int y, int x1, int y1) <br>
|
||||||
void fl_line(int x, int y, int x1, int y1, int x2, int y2)
|
void fl_line(int x, int y, int x1, int y1, int x2, int y2)
|
||||||
|
|
||||||
|
|||||||
@@ -455,6 +455,50 @@ void Fl_Graphics_Driver::rect(int x, int y, int w, int h) {}
|
|||||||
/** see fl_rectf() */
|
/** see fl_rectf() */
|
||||||
void Fl_Graphics_Driver::rectf(int x, int y, int w, int h) {}
|
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) {
|
void Fl_Graphics_Driver::colored_rectf(int x, int y, int w, int h, uchar r, uchar g, uchar b) {
|
||||||
color(r, g, b);
|
color(r, g, b);
|
||||||
rectf(x, y, w, h);
|
rectf(x, y, w, h);
|
||||||
|
|||||||
+4
-21
@@ -23,35 +23,18 @@
|
|||||||
// RS = max. corner radius
|
// RS = max. corner radius
|
||||||
// BW = box shadow width
|
// BW = box shadow width
|
||||||
|
|
||||||
#define RN 5
|
|
||||||
#define RS (Fl::box_border_radius_max())
|
#define RS (Fl::box_border_radius_max())
|
||||||
#define BW (Fl::box_shadow_width())
|
#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) {
|
static void rbox(int fill, int x, int y, int w, int h) {
|
||||||
int i;
|
|
||||||
int rs, rsy;
|
int rs, rsy;
|
||||||
rs = w*2/5; rsy = h*2/5;
|
rs = w*2/5; rsy = h*2/5;
|
||||||
if (rs > rsy) rs = rsy; // use smaller radius
|
if (rs > rsy) rs = rsy; // use smaller radius
|
||||||
if (rs > RS) rs = RS;
|
if (rs > RS) rs = RS;
|
||||||
if (rs == 5) rs = 4; // use only even sizes for small corners (STR #2943)
|
if (fill)
|
||||||
if (rs == 7) rs = 8; // note: 8 is better than 6 (really)
|
fl_rounded_rectf(x, y, w, h, rs);
|
||||||
|
else
|
||||||
if (fill) fl_begin_polygon(); else fl_begin_loop();
|
fl_rounded_rect(x, y, w, h, rs);
|
||||||
for (i=0; i<RN; i++)
|
|
||||||
fl_vertex_r(x + offset[RN-i-1]*rs, y + offset[i] * rs);
|
|
||||||
for (i=0; i<RN; i++)
|
|
||||||
fl_vertex_r(x + offset[i]*rs, y + h-1 - offset[RN-i-1] * rs);
|
|
||||||
for (i=0; i<RN; i++)
|
|
||||||
fl_vertex_r(x + w-1 - offset[RN-i-1]*rs, y + h-1 - offset[i] * rs);
|
|
||||||
for (i=0; i<RN; i++)
|
|
||||||
fl_vertex_r(x + w-1 - offset[i]*rs, y + offset[RN-i-1] * rs);
|
|
||||||
if (fill) fl_end_polygon(); else fl_end_loop();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) {
|
static void fl_rflat_box(int x, int y, int w, int h, Fl_Color c) {
|
||||||
|
|||||||
Reference in New Issue
Block a user