[gtk/path-ops: 7/8] glyphs: Add a way to debug path reassembly




commit cdd4a5ac8ace3159c2afc702105621b7a4919d5a
Author: Matthias Clasen <mclasen redhat com>
Date:   Fri Mar 25 09:14:17 2022 -0400

    glyphs: Add a way to debug path reassembly
    
    Make it possible to step through the reassembled path.
    
    To use it, focus the demo widget, then hit backspace to
    remove the outline rendering, then hit space to bring it
    back, one segment at ta time.

 tests/glyphs.c | 190 ++++++++++++++++++++++++++++++++++++++++++++++++++-------
 1 file changed, 168 insertions(+), 22 deletions(-)
---
diff --git a/tests/glyphs.c b/tests/glyphs.c
index af5b6fcf21..10a8c6286c 100644
--- a/tests/glyphs.c
+++ b/tests/glyphs.c
@@ -34,8 +34,8 @@ struct _DemoWidget
   char *font_file;
   char *text;
 
-  GskPath *boundary;
-  GskPath *interior;
+  GskPath *short_path;
+  int short_count;
 };
 
 struct _DemoWidgetClass
@@ -45,9 +45,87 @@ struct _DemoWidgetClass
 
 G_DEFINE_TYPE (DemoWidget, demo_widget, GTK_TYPE_WIDGET)
 
+static int short_count;
+
+static gboolean
+short_cb (GskPathOperation        op,
+          const graphene_point_t *pts,
+          gsize                   n_pts,
+          float                   weight,
+          gpointer                user_data)
+{
+  GskPathBuilder *builder = user_data;
+
+  if (short_count <= 0)
+    return FALSE;
+
+  short_count--;
+
+  switch (op)
+    {
+    case GSK_PATH_MOVE:
+      gsk_path_builder_move_to (builder, pts[0].x, pts[0].y);
+      break;
+    case GSK_PATH_CLOSE:
+      gsk_path_builder_close (builder);
+      break;
+    case GSK_PATH_LINE:
+      gsk_path_builder_line_to (builder, pts[1].x, pts[1].y);
+      break;
+    case GSK_PATH_CURVE:
+      gsk_path_builder_curve_to (builder,
+                                 pts[1].x, pts[1].y,
+                                 pts[2].x, pts[2].y,
+                                 pts[3].x, pts[3].y);
+      break;
+    case GSK_PATH_CONIC:
+    default:
+      g_assert_not_reached ();
+    }
+
+  return TRUE;
+}
+
+static void
+update_short_path (DemoWidget *self)
+{
+  GskPathBuilder *builder;
+
+  g_clear_pointer (&self->short_path, gsk_path_unref);
+
+  builder = gsk_path_builder_new ();
+
+  short_count = self->short_count;
+  gsk_path_foreach (self->path, GSK_PATH_FOREACH_ALLOW_CURVE, short_cb, builder);
+  self->short_path = gsk_path_builder_free_to_path (builder);
+
+  gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+pressed_cb (GtkEventController *controller,
+            guint               keyval,
+            guint               keycode,
+            GdkModifierType     state,
+            gpointer            data)
+{
+  DemoWidget *self = (DemoWidget *)gtk_event_controller_get_widget (controller);
+
+  if (keyval == GDK_KEY_BackSpace)
+    self->short_count = 0;
+  else
+   self->short_count++;
+
+  update_short_path (self);
+}
+
 static void
 demo_widget_init (DemoWidget *self)
 {
+  GtkEventController *controller;
+
+  gtk_widget_set_focusable (GTK_WIDGET (self), TRUE);
+
   self->label = gtk_label_new ("");
   gtk_widget_set_parent (self->label, GTK_WIDGET (self));
   gtk_widget_set_halign (self->label, GTK_ALIGN_END);
@@ -55,6 +133,10 @@ demo_widget_init (DemoWidget *self)
   self->do_outline = TRUE;
   self->font_file = g_strdup ("/usr/share/fonts/cantarell/Cantarell-VF.otf");
   self->text = g_strdup ("KP");
+
+  controller = gtk_event_controller_key_new ();
+  g_signal_connect (controller, "key-pressed", G_CALLBACK (pressed_cb), NULL);
+  gtk_widget_add_controller (GTK_WIDGET (self), controller);
 }
 
 static void
@@ -184,14 +266,25 @@ demo_widget_snapshot (GtkWidget   *widget,
       GskStroke *stroke;
 
       stroke = gsk_stroke_new (1.0);
-      gtk_snapshot_push_stroke (snapshot, self->path, stroke);
+      gtk_snapshot_push_stroke (snapshot, self->orig_path1, stroke);
+      gtk_snapshot_append_color (snapshot,
+                                 &(GdkRGBA){ 0, 0, 0, 0.3 },
+                                 &GRAPHENE_RECT_INIT (0, 0, width, height ));
+      gtk_snapshot_pop (snapshot);
+      gtk_snapshot_push_stroke (snapshot, self->orig_path2, stroke);
+      gtk_snapshot_append_color (snapshot,
+                                 &(GdkRGBA){ 0, 0, 0, 0.3 },
+                                 &GRAPHENE_RECT_INIT (0, 0, width, height ));
+      gtk_snapshot_pop (snapshot);
       gsk_stroke_free (stroke);
 
+      stroke = gsk_stroke_new (2.0);
+      gtk_snapshot_push_stroke (snapshot, self->short_path, stroke);
       gtk_snapshot_append_color (snapshot,
-                                 &(GdkRGBA){ 0, 0, 0, 1},
+                                 &(GdkRGBA){ 0, 0, 0, 1.0 },
                                  &GRAPHENE_RECT_INIT (0, 0, width, height ));
-
       gtk_snapshot_pop (snapshot);
+      gsk_stroke_free (stroke);
     }
 
   if (self->show_controls)
@@ -213,18 +306,6 @@ demo_widget_snapshot (GtkWidget   *widget,
   else if (self->show_points)
     {
       gsk_path_foreach (self->path, GSK_PATH_FOREACH_ALLOW_CURVE, point_cb, snapshot);
-
-      if (self->boundary && self->interior)
-        {
-          GskStroke *stroke;
-          stroke = gsk_stroke_new (1.0);
-          gtk_snapshot_push_stroke (snapshot, self->interior, stroke);
-          gtk_snapshot_append_color (snapshot,
-                                     &(GdkRGBA){ 1, 0, 0, 1},
-                                     &GRAPHENE_RECT_INIT (0, 0, width, height ));
-          gtk_snapshot_pop (snapshot);
-          gsk_stroke_free (stroke);
-        }
     }
 
   if (self->show_bounding_box)
@@ -375,8 +456,7 @@ demo_widget_set_path (DemoWidget *self,
   g_clear_pointer (&self->orig_path2, gsk_path_unref);
   g_clear_pointer (&self->path, gsk_path_unref);
   g_clear_pointer (&self->control_path, gsk_path_unref);
-  g_clear_pointer (&self->boundary, gsk_path_unref);
-  g_clear_pointer (&self->interior, gsk_path_unref);
+  g_clear_pointer (&self->short_path, gsk_path_unref);
 
   self->orig_path1 = gsk_path_ref (path1);
   self->orig_path2 = gsk_path_ref (path2);
@@ -392,10 +472,10 @@ demo_widget_set_path (DemoWidget *self,
       self->path = gsk_path_simplify (path1);
       break;
     case 2:
-      self->path = gsk_path_op (1, path1, path2, &self->boundary, &self->interior);
+      self->path = gsk_path_union (path1, path2);
       break;
     case 3:
-      self->path = gsk_path_op (2, path1, path2, &self->boundary, &self->interior);
+      self->path = gsk_path_intersection (path1, path2);
       break;
     case 4:
       self->path = gsk_path_difference (path1, path2);
@@ -413,6 +493,9 @@ demo_widget_set_path (DemoWidget *self,
 
   gsk_path_get_bounds (self->path, &self->bounds);
 
+  self->short_count = 10000;
+  update_short_path (self);
+
   gtk_widget_queue_draw (GTK_WIDGET (self));
 }
 
@@ -666,6 +749,56 @@ activate_entry (GtkEntry   *entry,
   demo_widget_set_text (demo, gtk_editable_get_text (GTK_EDITABLE (entry)));
 }
 
+static void
+text_changed (GtkTextBuffer *buffer,
+              DemoWidget    *demo)
+{
+  GtkTextIter start, end;
+  char *text;
+  char *p;
+  GskPath *path1, *path2;
+
+  gtk_text_buffer_get_bounds (buffer, &start, &end);
+  text = gtk_text_buffer_get_text (buffer, &start, &end, FALSE);
+
+  p = strstr (text, "\n\n");
+  if (p)
+    {
+      char *text1, *text2;
+
+      g_print ("got two paragraphs\n");
+
+      text1 = g_strndup (text, p - text);
+      text2 = g_strdup (p + 2);
+
+      path1 = gsk_path_parse (text1);
+      path2 = gsk_path_parse (text2);
+
+      if (path1 && path2)
+        g_print ("got two paths\n");
+
+      g_free (text1);
+      g_free (text2);
+    }
+  else
+    {
+      path1 = gsk_path_parse (text);
+      path2 = NULL;
+    }
+
+  g_free (text);
+
+  if (!path1)
+    path1 = gsk_path_parse ("");
+  if (!path2)
+    path2 = gsk_path_ref (path1);
+
+  demo_widget_set_path (demo, path1, path2);
+
+  gsk_path_unref (path1);
+  gsk_path_unref (path2);
+}
+
 int
 main (int argc, char *argv[])
 {
@@ -675,6 +808,9 @@ main (int argc, char *argv[])
   GtkWidget *combo, *sw;
   GtkWidget *zoom_scale;
   GtkWidget *hbox, *entry;
+  GtkWidget *text;
+  GtkWidget *paned;
+  GtkTextBuffer *buffer;
 
   gtk_init ();
 
@@ -687,9 +823,12 @@ main (int argc, char *argv[])
   gtk_widget_set_hexpand (demo, TRUE);
   gtk_widget_set_vexpand (demo, TRUE);
   sw = gtk_scrolled_window_new ();
-  gtk_box_append (GTK_BOX (box), sw);
   gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), demo);
 
+  paned = gtk_paned_new (GTK_ORIENTATION_HORIZONTAL);
+  gtk_paned_set_start_child (GTK_PANED (paned), sw);
+  gtk_box_append (GTK_BOX (box), paned);
+
   hbox = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 10);
   gtk_box_append (GTK_BOX (box), hbox);
   button = gtk_button_new_with_label ("Cantarell-VF.otf");
@@ -731,6 +870,13 @@ main (int argc, char *argv[])
   g_signal_connect (combo, "notify::selected", G_CALLBACK (fill_rule_changed), demo);
   gtk_box_append (GTK_BOX (hbox), combo);
 
+  sw = gtk_scrolled_window_new ();
+  text = gtk_text_view_new ();
+  buffer = gtk_text_view_get_buffer (GTK_TEXT_VIEW (text));
+  g_signal_connect (buffer, "changed", G_CALLBACK (text_changed), demo);
+  gtk_scrolled_window_set_child (GTK_SCROLLED_WINDOW (sw), text);
+  gtk_paned_set_end_child (GTK_PANED (paned), sw);
+
   init_demo (DEMO_WIDGET (demo));
 
   header = gtk_header_bar_new ();


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