[gtk/matthiasc/lottie] More curve editing



commit 8ce669020550d4c80528df35a804d19a7615d7e4
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Nov 20 00:55:51 2020 -0500

    More curve editing
    
    Make right-click on curve points toggle between
    smooth and corner.

 tests/curve.c | 190 ++++++++++++++++++++++++++++++++++++++++------------------
 1 file changed, 131 insertions(+), 59 deletions(-)
---
diff --git a/tests/curve.c b/tests/curve.c
index 2c5c9177a3..13731c21b9 100644
--- a/tests/curve.c
+++ b/tests/curve.c
@@ -7,6 +7,7 @@ typedef struct
 {
   GtkWidget parent_instance;
   graphene_point_t *points;
+  gboolean *smooth;
   int n_points;
   int dragged;
   gboolean edit;
@@ -83,31 +84,42 @@ drag_update (GtkGestureDrag *gesture,
   if (self->dragged % 3 == 0)
     {
       /* point is on curve */
-      self->points[(self->dragged - 1 + self->n_points) % self->n_points].x += dx;
-      self->points[(self->dragged - 1 + self->n_points) % self->n_points].y += dy;
 
-      self->points[(self->dragged + 1) % self->n_points].x += dx;
-      self->points[(self->dragged + 1) % self->n_points].y += dy;
+      if (self->smooth[self->dragged])
+        {
+          self->points[(self->dragged - 1 + self->n_points) % self->n_points].x += dx;
+          self->points[(self->dragged - 1 + self->n_points) % self->n_points].y += dy;
+
+          self->points[(self->dragged + 1) % self->n_points].x += dx;
+          self->points[(self->dragged + 1) % self->n_points].y += dy;
+       }
     }
   else
     {
+      int point;
+
       if (self->dragged % 3 == 1)
         {
+          point = (self->dragged - 1 + self->n_points) % self->n_points;
           c = &self->points[(self->dragged - 2 + self->n_points) % self->n_points];
-          p = &self->points[(self->dragged - 1 + self->n_points) % self->n_points];
+          p = &self->points[point];
         }
       else if (self->dragged % 3 == 2)
         {
+          point = (self->dragged + 1) % self->n_points;
           c = &self->points[(self->dragged + 2) % self->n_points];
-          p = &self->points[(self->dragged + 1) % self->n_points];
+          p = &self->points[point];
         }
       else
         g_assert_not_reached ();
 
-      a = atan2 (self->points[self->dragged].y - p->y, self->points[self->dragged].x - p->x) + M_PI;
-      d = dist (c, p);
-      c->x = p->x + d * cos (a);
-      c->y = p->y + d * sin (a);
+      if (self->smooth[point])
+        {
+          a = atan2 (self->points[self->dragged].y - p->y, self->points[self->dragged].x - p->x) + M_PI;
+          d = dist (c, p);
+          c->x = p->x + d * cos (a);
+          c->y = p->y + d * sin (a);
+        }
     }
 
   gtk_widget_queue_draw (GTK_WIDGET (self));
@@ -123,6 +135,48 @@ drag_end (GtkGestureDrag *gesture,
   self->dragged = -1;
 }
 
+static void
+released (GtkGestureClick *gesture,
+          int              n_press,
+          double           x,
+          double           y,
+          DemoWidget      *self)
+{
+  graphene_point_t m = GRAPHENE_POINT_INIT (x, y);
+  int i;
+
+  if (!self->edit)
+    return;
+
+  for (i = 0; i < self->n_points; i++)
+    {
+      if (dist (&self->points[i], &m) < RADIUS)
+        {
+          if (i % 3 == 0)
+            {
+              self->smooth[i] = !self->smooth[i];
+              if (self->smooth[i])
+                {
+                  graphene_point_t *p, *c, *c2;
+                  float a, d;
+
+                  p = &self->points[i];
+                  c = &self->points[(i - 1 + self->n_points) % self->n_points];
+                  c2 = &self->points[(i + 1 + self->n_points) % self->n_points];
+
+                  a = atan2 (c2->y - p->y, c2->x - p->x) + M_PI;
+                  d = dist (c, p);
+                  c->x = p->x + d * cos (a);
+                  c->y = p->y + d * sin (a);
+                }
+
+              gtk_widget_queue_draw (GTK_WIDGET (self));
+            }
+          break;
+        }
+    }
+}
+
 static void
 init_points (DemoWidget *self)
 {
@@ -134,6 +188,7 @@ init_points (DemoWidget *self)
   float r = (w - 2 * pad) / 2;
   float k = 0.55228;
   float kr = k  * r;
+  int i;
 
   /* curve 1 */
   self->points[0] = GRAPHENE_POINT_INIT (cx, pad);
@@ -151,6 +206,9 @@ init_points (DemoWidget *self)
   /* curve 4 */
   self->points[10] = GRAPHENE_POINT_INIT (pad, cy - kr);
   self->points[11] = GRAPHENE_POINT_INIT (cx - kr, pad);
+
+  for (i = 0; i < self->n_points; i++)
+    self->smooth[i] = TRUE;
 }
 
 static void
@@ -162,13 +220,20 @@ demo_widget_init (DemoWidget *self)
   self->edit = FALSE;
 
   gesture = gtk_gesture_drag_new ();
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_PRIMARY);
   g_signal_connect (gesture, "drag-begin", G_CALLBACK (drag_begin), self);
   g_signal_connect (gesture, "drag-update", G_CALLBACK (drag_update), self);
   g_signal_connect (gesture, "drag-end", G_CALLBACK (drag_end), self);
   gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
 
+  gesture = gtk_gesture_click_new ();
+  gtk_gesture_single_set_button (GTK_GESTURE_SINGLE (gesture), GDK_BUTTON_SECONDARY);
+  g_signal_connect (gesture, "released", G_CALLBACK (released), self);
+  gtk_widget_add_controller (GTK_WIDGET (self), GTK_EVENT_CONTROLLER (gesture));
+
   self->n_points = 12;
   self->points = g_new (graphene_point_t, self->n_points);
+  self->smooth = g_new (gboolean, self->n_points);
 
   init_points (self);
 }
@@ -181,7 +246,7 @@ demo_widget_snapshot (GtkWidget   *widget,
   GskPathBuilder *builder;
   GskPath *path;
   GskStroke *stroke;
-  int i;
+  int i, j;
   float width;
   float height;
 
@@ -226,68 +291,75 @@ demo_widget_snapshot (GtkWidget   *widget,
 
   if (self->edit)
     {
-      if (self->dragged != -1)
+      const char *colors[] = {
+        "white",
+        "red",
+        "green",
+        "blue"
+      };
+      GdkRGBA color;
+
+      for (j = 0; j < 4; j++)
         {
           builder = gsk_path_builder_new ();
-          gsk_path_builder_add_circle (builder, &self->points[self->dragged], RADIUS);
+
+          for (i = 0; i < self->n_points; i++)
+            {
+              switch (j)
+                {
+                case 0:
+                  if (i == self->dragged)
+                    break;
+                  else
+                    continue;
+
+                case 1:
+                  if (i != self->dragged &&
+                      i % 3 == 0 &&
+                      self->smooth[i])
+                    break;
+                  else
+                    continue;
+
+                case 2:
+                  if (i != self->dragged &&
+                      i % 3 == 0 &&
+                      !self->smooth[i])
+                    break;
+                  else
+                    continue;
+
+                case 3:
+                  if (i != self->dragged &&
+                      i % 3 != 0)
+                    break;
+                  else
+                    continue;
+
+                default:
+                  g_assert_not_reached ();
+                }
+
+              gsk_path_builder_add_circle (builder, &self->points[i], RADIUS);
+            }
+
           path = gsk_path_builder_free_to_path (builder);
 
           gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
-          gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 1, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
+          gdk_rgba_parse (&color, colors[j]);
+          gtk_snapshot_append_color (snapshot, &color, &GRAPHENE_RECT_INIT (0, 0, width, height));
           gtk_snapshot_pop (snapshot);
 
           stroke = gsk_stroke_new (1.0);
           gtk_snapshot_push_stroke (snapshot, path, stroke);
           gsk_stroke_free (stroke);
-          gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
+
+          gdk_rgba_parse (&color, "black");
+          gtk_snapshot_append_color (snapshot, &color, &GRAPHENE_RECT_INIT (0, 0, width, height));
           gtk_snapshot_pop (snapshot);
 
           gsk_path_unref (path);
         }
-
-      builder = gsk_path_builder_new ();
-
-      for (i = 0; i < self->n_points; i++)
-        {
-          if (i % 3 == 0 && i != self->dragged)
-            gsk_path_builder_add_circle (builder, &self->points[i], RADIUS);
-        }
-
-      path = gsk_path_builder_free_to_path (builder);
-
-      gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
-      gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 1, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
-      gtk_snapshot_pop (snapshot);
-
-      stroke = gsk_stroke_new (1.0);
-      gtk_snapshot_push_stroke (snapshot, path, stroke);
-      gsk_stroke_free (stroke);
-      gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
-      gtk_snapshot_pop (snapshot);
-
-      gsk_path_unref (path);
-
-      builder = gsk_path_builder_new ();
-
-      for (i = 0; i < self->n_points; i++)
-        {
-          if (i % 3 != 0 && i != self->dragged)
-            gsk_path_builder_add_circle (builder, &self->points[i], RADIUS);
-        }
-
-      path = gsk_path_builder_free_to_path (builder);
-
-      gtk_snapshot_push_fill (snapshot, path, GSK_FILL_RULE_WINDING);
-      gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 1, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
-      gtk_snapshot_pop (snapshot);
-
-      stroke = gsk_stroke_new (1.0);
-      gtk_snapshot_push_stroke (snapshot, path, stroke);
-      gsk_stroke_free (stroke);
-      gtk_snapshot_append_color (snapshot, &(GdkRGBA) { 0, 0, 0, 1 }, &GRAPHENE_RECT_INIT (0, 0, width, 
height));
-      gtk_snapshot_pop (snapshot);
-
-      gsk_path_unref (path);
     }
 }
 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]