[goocanvas/wip/albfan/rect-radii] Allow customize each corner radius for rectangle shape
- From: Alberto Fanjul <albfan src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [goocanvas/wip/albfan/rect-radii] Allow customize each corner radius for rectangle shape
- Date: Tue, 14 Jan 2020 13:01:41 +0000 (UTC)
commit 7254904dc268e2dcc796eb32a949871d00d567ca
Author: Alberto Fanjul <albertofanjul gmail com>
Date: Tue Jan 14 11:52:20 2020 +0100
Allow customize each corner radius for rectangle shape
Control each corners radius with new properties
demo/mv-simple-demo.c | 4 +-
demo/simple-demo.c | 8 +-
docs/simple-canvas.xml | 10 +-
src/goocanvasrect.c | 265 ++++++++++++++++++++++++++++++++++++++++++++-----
src/goocanvasrect.h | 4 +-
5 files changed, 260 insertions(+), 31 deletions(-)
---
diff --git a/demo/mv-simple-demo.c b/demo/mv-simple-demo.c
index 39c5edd..de2da73 100644
--- a/demo/mv-simple-demo.c
+++ b/demo/mv-simple-demo.c
@@ -46,8 +46,8 @@ main (int argc, char *argv[])
/* Add a few simple items. */
rect_model = goo_canvas_rect_model_new (root, 100, 100, 400, 400,
"line-width", 10.0,
- "radius-x", 20.0,
- "radius-y", 10.0,
+ "radius-top-left-x", 30.0,
+ "radius-top-left-y", 20.0,
"stroke-color", "yellow",
"fill-color", "red",
NULL);
diff --git a/demo/simple-demo.c b/demo/simple-demo.c
index 3da3d62..593bb16 100644
--- a/demo/simple-demo.c
+++ b/demo/simple-demo.c
@@ -44,9 +44,11 @@ main (int argc, char *argv[])
/* Add a few simple items. */
rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
- "line-width", 10.0,
- "radius-x", 20.0,
- "radius-y", 10.0,
+ "line-width", 1.0,
+ "radius-bottom-left-x", 60.0,
+ "radius-bottom-left-y", 60.0,
+ "radius-bottom-right-x", 60.0,
+ "radius-bottom-right-y", 60.0,
"stroke-color", "yellow",
"fill-color", "red",
NULL);
diff --git a/docs/simple-canvas.xml b/docs/simple-canvas.xml
index 085b3d6..a072fe1 100644
--- a/docs/simple-canvas.xml
+++ b/docs/simple-canvas.xml
@@ -68,8 +68,14 @@
/* Add a few simple items. */
rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
"line-width", 10.0,
- "radius-x", 20.0,
- "radius-y", 10.0,
+ "radius-top-left-x", 10.0,
+ "radius-top-left-y", 10.0,
+ "radius-top-right-x", 60.0,
+ "radius-top-right-y", 60.0,
+ "radius-bottom-right-x", 30.0,
+ "radius-bottom-right-y", 30.0,
+ "radius-bottom-left-x", 15.0,
+ "radius-bottom-left-y", 15.0,
"stroke-color", "yellow",
"fill-color", "red",
NULL);
diff --git a/src/goocanvasrect.c b/src/goocanvasrect.c
index cb8d4a6..68588db 100644
--- a/src/goocanvasrect.c
+++ b/src/goocanvasrect.c
@@ -40,7 +40,15 @@ enum {
PROP_WIDTH,
PROP_HEIGHT,
PROP_RADIUS_X,
- PROP_RADIUS_Y
+ PROP_RADIUS_Y,
+ PROP_RADIUS_TOP_LEFT_X,
+ PROP_RADIUS_TOP_LEFT_Y,
+ PROP_RADIUS_TOP_RIGHT_X,
+ PROP_RADIUS_TOP_RIGHT_Y,
+ PROP_RADIUS_BOTTOM_RIGHT_X,
+ PROP_RADIUS_BOTTOM_RIGHT_Y,
+ PROP_RADIUS_BOTTOM_LEFT_X,
+ PROP_RADIUS_BOTTOM_LEFT_Y
};
@@ -98,6 +106,62 @@ goo_canvas_rect_install_common_properties (GObjectClass *gobject_class)
_("The vertical radius to use for rounded corners"),
0.0, G_MAXDOUBLE, 0.0,
G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_TOP_LEFT_X,
+ g_param_spec_double ("radius_top_left_x",
+ _("Radius Top Left X"),
+ _("The horizontal top left radius to use for rounded
corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_TOP_LEFT_Y,
+ g_param_spec_double ("radius_top_left_y",
+ _("Radius Top Left Y"),
+ _("The vertical top left radius to use for rounded
corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_TOP_RIGHT_X,
+ g_param_spec_double ("radius_top_right_x",
+ _("Radius Top Right X"),
+ _("The horizontal top right radius to use for rounded
corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_TOP_RIGHT_Y,
+ g_param_spec_double ("radius_top_right_y",
+ _("Radius Top Right Y"),
+ _("The vertical top right radius to use for rounded
corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_BOTTOM_RIGHT_X,
+ g_param_spec_double ("radius_bottom_right_x",
+ _("Radius Bottom Right X"),
+ _("The horizontal bottom right radius to use for
rounded corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_BOTTOM_RIGHT_Y,
+ g_param_spec_double ("radius_bottom_right_y",
+ _("Radius Bottom Right"),
+ _("The vertical bottom right radius to use for
rounded corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_BOTTOM_LEFT_X,
+ g_param_spec_double ("radius_bottom_left_x",
+ _("Radius Bottom Left X"),
+ _("The horizontal bottom left radius to use for
rounded corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (gobject_class, PROP_RADIUS_BOTTOM_LEFT_Y,
+ g_param_spec_double ("radius_bottom_left_y",
+ _("Radius Bottom Left Y"),
+ _("The vertical bottom left radius to use for rounded
corners"),
+ 0.0, G_MAXDOUBLE, 0.0,
+ G_PARAM_READWRITE));
}
@@ -158,6 +222,14 @@ goo_canvas_rect_new (GooCanvasItem *parent,
rect_data->height = height;
rect_data->radius_x = 0;
rect_data->radius_y = 0;
+ rect_data->radius_top_right_x = 0;
+ rect_data->radius_top_right_y = 0;
+ rect_data->radius_top_left_x = 0;
+ rect_data->radius_top_left_y = 0;
+ rect_data->radius_bottom_right_x = 0;
+ rect_data->radius_bottom_right_y = 0;
+ rect_data->radius_bottom_left_x = 0;
+ rect_data->radius_bottom_left_y = 0;
va_start (var_args, height);
first_property = va_arg (var_args, char*);
@@ -218,6 +290,30 @@ goo_canvas_rect_get_common_property (GObject *object,
case PROP_RADIUS_Y:
g_value_set_double (value, rect_data->radius_y);
break;
+ case PROP_RADIUS_TOP_LEFT_X:
+ g_value_set_double (value, rect_data->radius_top_left_x);
+ break;
+ case PROP_RADIUS_TOP_LEFT_Y:
+ g_value_set_double (value, rect_data->radius_top_left_y);
+ break;
+ case PROP_RADIUS_TOP_RIGHT_X:
+ g_value_set_double (value, rect_data->radius_top_right_x);
+ break;
+ case PROP_RADIUS_TOP_RIGHT_Y:
+ g_value_set_double (value, rect_data->radius_top_right_y);
+ break;
+ case PROP_RADIUS_BOTTOM_RIGHT_X:
+ g_value_set_double (value, rect_data->radius_bottom_right_x);
+ break;
+ case PROP_RADIUS_BOTTOM_RIGHT_Y:
+ g_value_set_double (value, rect_data->radius_bottom_right_y);
+ break;
+ case PROP_RADIUS_BOTTOM_LEFT_X:
+ g_value_set_double (value, rect_data->radius_bottom_left_x);
+ break;
+ case PROP_RADIUS_BOTTOM_LEFT_Y:
+ g_value_set_double (value, rect_data->radius_bottom_left_y);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -265,6 +361,30 @@ goo_canvas_rect_set_common_property (GObject *object,
case PROP_RADIUS_Y:
rect_data->radius_y = g_value_get_double (value);
break;
+ case PROP_RADIUS_TOP_LEFT_X:
+ rect_data->radius_top_left_x = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_TOP_LEFT_Y:
+ rect_data->radius_top_left_y = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_TOP_RIGHT_X:
+ rect_data->radius_top_right_x = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_TOP_RIGHT_Y:
+ rect_data->radius_top_right_y = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_BOTTOM_RIGHT_X:
+ rect_data->radius_bottom_right_x = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_BOTTOM_RIGHT_Y:
+ rect_data->radius_bottom_right_y = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_BOTTOM_LEFT_X:
+ rect_data->radius_bottom_left_x = g_value_get_double (value);
+ break;
+ case PROP_RADIUS_BOTTOM_LEFT_Y:
+ rect_data->radius_bottom_left_y = g_value_get_double (value);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -303,51 +423,142 @@ goo_canvas_rect_create_path (GooCanvasItemSimple *simple,
cairo_new_path (cr);
/* Check if we need to draw rounded corners. */
- if (rect_data->radius_x > 0 && rect_data->radius_y > 0)
+ if ((rect_data->radius_x > 0 && rect_data->radius_y > 0)
+ || (rect_data->radius_top_left_x > 0 && rect_data->radius_top_left_y > 0)
+ || (rect_data->radius_top_right_x > 0 && rect_data->radius_top_right_y > 0)
+ || (rect_data->radius_bottom_right_x > 0 && rect_data->radius_bottom_right_y > 0)
+ || (rect_data->radius_bottom_left_x > 0 && rect_data->radius_bottom_left_y > 0))
{
+ /* Half the size of the rect. */
+ double half_width = rect_data->width / 2;
+ double half_height = rect_data->height / 2;
+
/* The radii can't be more than half the size of the rect. */
- double rx = MIN (rect_data->radius_x, rect_data->width / 2);
- double ry = MIN (rect_data->radius_y, rect_data->height / 2);
+ double rx = MIN (rect_data->radius_x, half_width);
+ double ry = MIN (rect_data->radius_y, half_height);
+ double r_tl_x = MIN (rect_data->radius_top_left_x, MIN (half_width, half_height));
+ if (r_tl_x == 0) {
+ r_tl_x = rx;
+ }
+ double r_tl_y = MIN (rect_data->radius_top_left_y, MIN (half_width, half_height));
+ if (r_tl_y == 0) {
+ r_tl_y = ry;
+ }
+ double r_tr_x = MIN (rect_data->radius_top_right_x, MIN (half_width, half_height));
+ if (r_tr_x == 0) {
+ r_tr_x = rx;
+ }
+ double r_tr_y = MIN (rect_data->radius_top_right_y, MIN (half_width, half_height));
+ if (r_tr_y == 0) {
+ r_tr_y = ry;
+ }
+ double r_bl_x = MIN (rect_data->radius_bottom_left_x, MIN (half_width, half_height));
+ if (r_bl_x == 0) {
+ r_bl_x = rx;
+ }
+ double r_bl_y = MIN (rect_data->radius_bottom_left_y, MIN (half_width, half_height));
+ if (r_bl_y == 0) {
+ r_bl_y = ry;
+ }
+ double r_br_x = MIN (rect_data->radius_bottom_right_x, MIN (half_width, half_height));
+ if (r_br_x == 0) {
+ r_br_x = rx;
+ }
+ double r_br_y = MIN (rect_data->radius_bottom_right_y, MIN (half_width, half_height));
+ if (r_br_y == 0) {
+ r_br_y = ry;
+ }
/* Draw the top-right arc. */
cairo_save (cr);
- cairo_translate (cr, rect_data->x + rect_data->width - rx,
- rect_data->y + ry);
- cairo_scale (cr, rx, ry);
- cairo_arc (cr, 0.0, 0.0, 1.0, 1.5 * M_PI, 2.0 * M_PI);
+ if (r_tr_x > 0 && r_tr_y > 0)
+ {
+ cairo_translate (cr, rect_data->x + rect_data->width - r_tr_x,
+ rect_data->y + r_tr_y);
+ cairo_scale (cr, r_tr_x, r_tr_y);
+ cairo_arc (cr, 0.0, 0.0, 1.0, 1.5 * M_PI, 2.0 * M_PI);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x + rect_data->width, rect_data->y);
+ }
cairo_restore (cr);
/* Draw the line down the right side. */
- cairo_line_to (cr, rect_data->x + rect_data->width,
- rect_data->y + rect_data->height - ry);
+ if (r_br_x > 0 && r_br_y > 0)
+ {
+ cairo_line_to (cr, rect_data->x + rect_data->width,
+ rect_data->y + rect_data->height - r_br_y);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x + rect_data->width,
+ rect_data->y + rect_data->height);
+ }
/* Draw the bottom-right arc. */
cairo_save (cr);
- cairo_translate (cr, rect_data->x + rect_data->width - rx,
- rect_data->y + rect_data->height - ry);
- cairo_scale (cr, rx, ry);
- cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 0.5 * M_PI);
+ if (r_br_x > 0 && r_br_y > 0)
+ {
+ cairo_translate (cr, rect_data->x + rect_data->width - r_br_x,
+ rect_data->y + rect_data->height - r_br_y);
+ cairo_scale (cr, r_br_x, r_br_y);
+ cairo_arc (cr, 0.0, 0.0, 1.0, 0.0, 0.5 * M_PI);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x + rect_data->width,
+ rect_data->y + rect_data->height);
+ }
cairo_restore (cr);
/* Draw the line left across the bottom. */
- cairo_line_to (cr, rect_data->x + rx, rect_data->y + rect_data->height);
+ if (r_br_x > 0 && r_br_y > 0)
+ {
+ cairo_line_to (cr, rect_data->x + r_br_x, rect_data->y + rect_data->height);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x + r_bl_x, rect_data->y + rect_data->height);
+ }
/* Draw the bottom-left arc. */
cairo_save (cr);
- cairo_translate (cr, rect_data->x + rx,
- rect_data->y + rect_data->height - ry);
- cairo_scale (cr, rx, ry);
- cairo_arc (cr, 0.0, 0.0, 1.0, 0.5 * M_PI, M_PI);
+ if (r_bl_x > 0 && r_bl_y > 0)
+ {
+ cairo_translate (cr, rect_data->x + r_bl_x,
+ rect_data->y + rect_data->height - r_bl_y);
+ cairo_scale (cr, r_bl_x, r_bl_y);
+ cairo_arc (cr, 0.0, 0.0, 1.0, 0.5 * M_PI, M_PI);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x, rect_data->y + rect_data->height);
+ }
cairo_restore (cr);
/* Draw the line up the left side. */
- cairo_line_to (cr, rect_data->x, rect_data->y + ry);
+ if (r_tl_x > 0 && r_tl_y > 0)
+ {
+ cairo_line_to (cr, rect_data->x, rect_data->y + r_tl_y);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x, rect_data->y);
+ }
/* Draw the top-left arc. */
cairo_save (cr);
- cairo_translate (cr, rect_data->x + rx, rect_data->y + ry);
- cairo_scale (cr, rx, ry);
- cairo_arc (cr, 0.0, 0.0, 1.0, M_PI, 1.5 * M_PI);
+ if (r_tl_x > 0 && r_tl_y > 0)
+ {
+ cairo_translate (cr, rect_data->x + r_tl_x, rect_data->y + r_tl_y);
+ cairo_scale (cr, r_tl_x, r_tl_y);
+ cairo_arc (cr, 0.0, 0.0, 1.0, M_PI, 1.5 * M_PI);
+ }
+ else
+ {
+ cairo_line_to (cr, rect_data->x, rect_data->y);
+ }
cairo_restore (cr);
/* Close the path across the top. */
@@ -535,6 +746,14 @@ goo_canvas_rect_model_new (GooCanvasItemModel *parent,
rect_data->height = height;
rect_data->radius_x = 0;
rect_data->radius_y = 0;
+ rect_data->radius_top_left_x = 0;
+ rect_data->radius_top_left_y = 0;
+ rect_data->radius_top_right_x = 0;
+ rect_data->radius_top_right_y = 0;
+ rect_data->radius_bottom_right_x = 0;
+ rect_data->radius_bottom_right_y = 0;
+ rect_data->radius_bottom_left_x = 0;
+ rect_data->radius_bottom_left_y = 0;
va_start (var_args, height);
first_property = va_arg (var_args, char*);
diff --git a/src/goocanvasrect.h b/src/goocanvasrect.h
index 653a6bb..ed102cf 100644
--- a/src/goocanvasrect.h
+++ b/src/goocanvasrect.h
@@ -17,7 +17,9 @@ G_BEGIN_DECLS
typedef struct _GooCanvasRectData GooCanvasRectData;
struct _GooCanvasRectData
{
- gdouble x, y, width, height, radius_x, radius_y;
+ gdouble x, y, width, height, radius_x, radius_y,
+ radius_top_left_x, radius_top_left_y, radius_top_right_x, radius_top_right_y,
+ radius_bottom_right_x, radius_bottom_right_y, radius_bottom_left_x, radius_bottom_left_y;
};
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]