[goocanvas/wip/albfan/rect-radii: 2/2] Allow customize each corner radius for rectangle shape




commit 1723d954ea00a5eca240eb7be3d2703d7401bedd
Author: Alberto Fanjul <albertofanjul gmail com>
Date:   Sat Jan 16 10:06:23 2021 +0100

        Allow customize each corner radius for rectangle shape

 .gitignore             |   2 +
 demo/Makefile.am       |  12 ++-
 demo/mv-radii-demo.c   | 115 +++++++++++++++++++++
 demo/radii-demo.c      | 110 ++++++++++++++++++++
 docs/simple-canvas.xml |  10 +-
 src/goocanvasrect.c    | 265 ++++++++++++++++++++++++++++++++++++++++++++-----
 src/goocanvasrect.h    |   4 +-
 7 files changed, 491 insertions(+), 27 deletions(-)
---
diff --git a/.gitignore b/.gitignore
index ca651a9..990a437 100644
--- a/.gitignore
+++ b/.gitignore
@@ -29,10 +29,12 @@ Makefile.in
 /demo/mv-demo
 /demo/mv-generic-position-demo
 /demo/mv-scalability-demo
+/demo/mv-radii-demo
 /demo/mv-simple-demo
 /demo/mv-table-demo
 /demo/mv-rotate-skew-demo
 /demo/scalability-demo
+/demo/radii-demo
 /demo/simple-demo
 /demo/table-demo
 /demo/units-demo
diff --git a/demo/Makefile.am b/demo/Makefile.am
index 55edc04..b78cd49 100644
--- a/demo/Makefile.am
+++ b/demo/Makefile.am
@@ -11,7 +11,7 @@ DEMO_LIBS = $(top_builddir)/src/libgoocanvas-3.0.la @PACKAGE_LIBS@ $(INTLLIBS) -
 #      -DGDK_DISABLE_DEPRECATED -DGDK_PIXBUF_DISABLE_DEPRECATED \
 #      -DGTK_DISABLE_DEPRECATED
 
-noinst_PROGRAMS = demo table-demo generic-position-demo simple-demo scalability-demo units-demo widgets-demo 
mv-demo mv-table-demo mv-generic-position-demo mv-simple-demo mv-scalability-demo mv-rotate-skew-demo
+noinst_PROGRAMS = demo table-demo generic-position-demo radii-demo simple-demo scalability-demo units-demo 
widgets-demo mv-demo mv-table-demo mv-generic-position-demo mv-radii-demo mv-simple-demo mv-scalability-demo 
mv-rotate-skew-demo
 
 demo_SOURCES = \
        demo.c demo-fifteen.c demo-scalability.c demo-grabs.c \
@@ -40,6 +40,16 @@ mv_table_demo_SOURCES = \
 
 mv_table_demo_LDADD = $(DEMO_LIBS)
 
+radii_demo_SOURCES = \
+       radii-demo.c
+
+radii_demo_LDADD = $(DEMO_LIBS)
+
+mv_radii_demo_SOURCES = \
+       mv-radii-demo.c
+
+mv_radii_demo_LDADD = $(DEMO_LIBS)
+
 simple_demo_SOURCES = \
        simple-demo.c
 
diff --git a/demo/mv-radii-demo.c b/demo/mv-radii-demo.c
new file mode 100644
index 0000000..d1ad8bd
--- /dev/null
+++ b/demo/mv-radii-demo.c
@@ -0,0 +1,115 @@
+#include <stdlib.h>
+#include <goocanvas.h>
+
+
+static gboolean on_rect_button_press (GooCanvasItem  *view,
+                                     GooCanvasItem  *target,
+                                     GdkEventButton *event,
+                                     gpointer        data);
+
+static gboolean on_delete_event      (GtkWidget      *window,
+                                     GdkEvent       *event,
+                                     gpointer        unused_data);
+
+
+int
+main (int argc, char *argv[])
+{
+  GtkWidget *window, *scrolled_win, *canvas;
+  GooCanvasItemModel *root, *rect_model, *text_model;
+  GooCanvasItem *rect_item;
+
+  /* Initialize GTK+. */
+  gtk_init (&argc, &argv);
+
+  /* Create the window and widgets. */
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
+  gtk_widget_show (window);
+  g_signal_connect (window, "delete_event", G_CALLBACK (on_delete_event),
+                   NULL);
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                      GTK_SHADOW_IN);
+  gtk_widget_show (scrolled_win);
+  gtk_container_add (GTK_CONTAINER (window), scrolled_win);
+
+  canvas = goo_canvas_new ();
+  gtk_widget_set_size_request (canvas, 600, 450);
+  goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
+  gtk_widget_show (canvas);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);
+
+  root = goo_canvas_group_model_new (NULL, NULL);
+
+  /* Add an item with all border modified. */
+  rect_model = goo_canvas_rect_model_new (root, 100, 100, 400, 400,
+                                         "line-width", 10.0,
+                                         "radius-top-left-x", 30.0,
+                                         "radius-top-left-y", 20.0,
+                                         "radius-top-right-x", 5.0,
+                                         "radius-top-right-y", 10.0,
+                                         "radius-bottom-left-x", 20.0,
+                                         "radius-bottom-left-y", 30.0,
+                                         "radius-bottom-right-x", 10.0,
+                                         "radius-bottom-right-y", 5.0,
+                                         "stroke-color", "green",
+                                         "fill-color", "blue",
+                                         NULL);
+
+
+  text_model = goo_canvas_text_model_new (root, "Hello World", 300, 300, -1,
+                                         GOO_CANVAS_ANCHOR_CENTER,
+                                         "font", "Sans 24",
+                                         NULL);
+  goo_canvas_item_model_rotate (text_model, 45, 300, 300);
+
+  goo_canvas_set_root_item_model (GOO_CANVAS (canvas), root);
+
+  rect_item = goo_canvas_get_item (GOO_CANVAS (canvas), rect_model);
+
+  /* Connect a signal handler for the rectangle item. */
+  g_signal_connect (rect_item, "button_press_event",
+                   G_CALLBACK (on_rect_button_press), NULL);
+
+  /* Pass control to the GTK+ main event loop. */
+  gtk_main ();
+
+  return 0;
+}
+
+
+/* The signal handler for the rectangle item. We show a dialog here. */
+static gboolean
+on_rect_button_press (GooCanvasItem  *item,
+                     GooCanvasItem  *target,
+                     GdkEventButton *event,
+                     gpointer        data)
+{
+  GooCanvas *canvas;
+  GtkWidget *window, *dialog;
+
+  canvas = goo_canvas_item_get_canvas (item);
+  window = gtk_widget_get_toplevel (GTK_WIDGET (canvas));
+  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                  GTK_DIALOG_DESTROY_WITH_PARENT,
+                                  GTK_MESSAGE_INFO,
+                                  GTK_BUTTONS_CLOSE,
+                                  "rect item received button press event");
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  return TRUE;
+}
+
+
+/* This is our handler for the "delete-event" signal of the window, which
+   is emitted when the 'x' close button is clicked. We just exit here. */
+static gboolean
+on_delete_event (GtkWidget *window,
+                GdkEvent  *event,
+                gpointer   unused_data)
+{
+  exit (0);
+}
diff --git a/demo/radii-demo.c b/demo/radii-demo.c
new file mode 100644
index 0000000..3e598a9
--- /dev/null
+++ b/demo/radii-demo.c
@@ -0,0 +1,110 @@
+#include <stdlib.h>
+#include <goocanvas.h>
+
+
+static gboolean on_rect_button_press (GooCanvasItem  *view,
+                                     GooCanvasItem  *target,
+                                     GdkEventButton *event,
+                                     gpointer        data);
+
+static gboolean on_delete_event      (GtkWidget      *window,
+                                     GdkEvent       *event,
+                                     gpointer        unused_data);
+
+
+int
+main (int argc, char *argv[])
+{
+  GtkWidget *window, *scrolled_win, *canvas;
+  GooCanvasItem *root, *rect_item, *text_item;
+
+  /* Initialize GTK+. */
+  gtk_init (&argc, &argv);
+
+  /* Create the window and widgets. */
+  window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
+  gtk_window_set_default_size (GTK_WINDOW (window), 640, 600);
+  gtk_widget_show (window);
+  g_signal_connect (window, "delete_event", G_CALLBACK (on_delete_event),
+                   NULL);
+
+  scrolled_win = gtk_scrolled_window_new (NULL, NULL);
+  gtk_scrolled_window_set_shadow_type (GTK_SCROLLED_WINDOW (scrolled_win),
+                                      GTK_SHADOW_IN);
+  gtk_widget_show (scrolled_win);
+  gtk_container_add (GTK_CONTAINER (window), scrolled_win);
+
+  canvas = goo_canvas_new ();
+  gtk_widget_set_size_request (canvas, 600, 450);
+  goo_canvas_set_bounds (GOO_CANVAS (canvas), 0, 0, 1000, 1000);
+  gtk_widget_show (canvas);
+  gtk_container_add (GTK_CONTAINER (scrolled_win), canvas);
+
+  root = goo_canvas_get_root_item (GOO_CANVAS (canvas));
+
+  /* Add an item with all borders modified. */
+  rect_item = goo_canvas_rect_new (root, 100, 100, 400, 400,
+                                  "line-width", 10.0,
+                                  "radius-top-left-x", 30.0,
+                                  "radius-top-left-y", 20.0,
+                                  "radius-top-right-x", 5.0,
+                                  "radius-top-right-y", 10.0,
+                                  "radius-bottom-left-x", 20.0,
+                                  "radius-bottom-left-y", 30.0,
+                                  "radius-bottom-right-x", 10.0,
+                                  "radius-bottom-right-y", 5.0,
+                                  "stroke-color", "green",
+                                  "fill-color", "blue",
+                                  NULL);
+
+
+  text_item = goo_canvas_text_new (root, "Hello World", 300, 300, -1,
+                                  GOO_CANVAS_ANCHOR_CENTER,
+                                  "font", "Sans 24",
+                                  NULL);
+  goo_canvas_item_rotate (text_item, 45, 300, 300);
+
+  /* Connect a signal handler for the rectangle item. */
+  g_signal_connect (rect_item, "button_press_event",
+                   G_CALLBACK (on_rect_button_press), NULL);
+
+  /* Pass control to the GTK+ main event loop. */
+  gtk_main ();
+
+  return 0;
+}
+
+
+/* The signal handler for the rectangle item. We show a dialog here. */
+static gboolean
+on_rect_button_press (GooCanvasItem  *item,
+                     GooCanvasItem  *target,
+                     GdkEventButton *event,
+                     gpointer        data)
+{
+  GooCanvas *canvas;
+  GtkWidget *window, *dialog;
+
+  canvas = goo_canvas_item_get_canvas (item);
+  window = gtk_widget_get_toplevel (GTK_WIDGET (canvas));
+  dialog = gtk_message_dialog_new (GTK_WINDOW (window),
+                                  GTK_DIALOG_DESTROY_WITH_PARENT,
+                                  GTK_MESSAGE_INFO,
+                                  GTK_BUTTONS_CLOSE,
+                                  "rect item received button press event");
+  gtk_dialog_run (GTK_DIALOG (dialog));
+  gtk_widget_destroy (dialog);
+
+  return TRUE;
+}
+
+
+/* This is our handler for the "delete-event" signal of the window, which
+   is emitted when the 'x' close button is clicked. We just exit here. */
+static gboolean
+on_delete_event (GtkWidget *window,
+                GdkEvent  *event,
+                gpointer   unused_data)
+{
+  exit (0);
+}
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 @@
     /&ast; Add a few simple items. &ast;/
     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]