[gtk/path-ops: 2/4] glyphs: Test boolean ops




commit 2ea06be26894a8c37065e90549591532e4b53a24
Author: Matthias Clasen <mclasen redhat com>
Date:   Tue Mar 22 23:21:58 2022 -0400

    glyphs: Test boolean ops

 tests/glyphs.c | 177 +++++++++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 134 insertions(+), 43 deletions(-)
---
diff --git a/tests/glyphs.c b/tests/glyphs.c
index 03d87cbaa1..af5b6fcf21 100644
--- a/tests/glyphs.c
+++ b/tests/glyphs.c
@@ -1,4 +1,5 @@
 #include <gtk/gtk.h>
+#include <gsk/gskcurveprivate.h>
 
 #define DEMO_TYPE_WIDGET (demo_widget_get_type ())
 G_DECLARE_FINAL_TYPE (DemoWidget, demo_widget, DEMO, WIDGET, GtkWidget)
@@ -6,7 +7,8 @@ G_DECLARE_FINAL_TYPE (DemoWidget, demo_widget, DEMO, WIDGET, GtkWidget)
 struct _DemoWidget
 {
   GtkWidget parent_instance;
-  GskPath *orig_path;
+  GskPath *orig_path1;
+  GskPath *orig_path2;
   GskPath *path;
   GskPath *control_path;
   graphene_point_t point;
@@ -20,6 +22,7 @@ struct _DemoWidget
   GskFillRule fill_rule;
   gboolean do_fill;
   gboolean do_outline;
+  int operation;
   gboolean show_points;
   gboolean show_controls;
   gboolean show_bounding_box;
@@ -29,7 +32,10 @@ struct _DemoWidget
   double zoom;
 
   char *font_file;
-  gunichar ch;
+  char *text;
+
+  GskPath *boundary;
+  GskPath *interior;
 };
 
 struct _DemoWidgetClass
@@ -48,22 +54,30 @@ demo_widget_init (DemoWidget *self)
   gtk_widget_set_valign (self->label, GTK_ALIGN_START);
   self->do_outline = TRUE;
   self->font_file = g_strdup ("/usr/share/fonts/cantarell/Cantarell-VF.otf");
-  self->ch = 'e';
+  self->text = g_strdup ("KP");
 }
 
 static void
-draw_point (GtkSnapshot            *snapshot,
-            const graphene_point_t *pt)
+draw_point2 (GtkSnapshot            *snapshot,
+             const graphene_point_t *pt,
+             GdkRGBA                *color,
+             float                   size)
 {
   graphene_rect_t bounds;
-  GdkRGBA color = { 1, 0, 0, 1 };
 
-  bounds.origin.x = pt->x - 2;
-  bounds.origin.y = pt->y - 2;
-  bounds.size.width = 4;
-  bounds.size.height = 4;
+  bounds.origin.x = pt->x - size / 2;
+  bounds.origin.y = pt->y - size / 2;
+  bounds.size.width = size;
+  bounds.size.height = size;
+
+  gtk_snapshot_append_color (snapshot, color, &bounds);
+}
 
-  gtk_snapshot_append_color (snapshot, &color, &bounds);
+static void
+draw_point (GtkSnapshot            *snapshot,
+            const graphene_point_t *pt)
+{
+  draw_point2 (snapshot, pt, &(GdkRGBA) { 1, 0, 0, 1 }, 4);
 }
 
 static gboolean
@@ -114,10 +128,11 @@ point_cb (GskPathOperation        op,
   switch (op)
     {
     case GSK_PATH_MOVE:
+      draw_point2 (snapshot, &pts[0], &(GdkRGBA) { 0, 0, 1, 1 }, 8);
       break;
 
     case GSK_PATH_CLOSE:
-      draw_point (snapshot, &pts[0]);
+      draw_point (snapshot, &pts[1]);
       break;
 
     case GSK_PATH_LINE:
@@ -198,6 +213,18 @@ 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)
@@ -274,9 +301,12 @@ demo_widget_dispose (GObject *object)
 {
   DemoWidget *self = DEMO_WIDGET (object);
 
+  g_clear_pointer (&self->orig_path1, gsk_path_unref);
+  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->label, gtk_widget_unparent);
+  g_free (self->text);
   g_free (self->font_file);
 
   G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
@@ -336,14 +366,46 @@ control_cb (GskPathOperation        op,
 
 static void
 demo_widget_set_path (DemoWidget *self,
-                      GskPath    *path)
+                      GskPath    *path1,
+                      GskPath    *path2)
 {
   GskPathBuilder *builder;
 
+  g_clear_pointer (&self->orig_path1, gsk_path_unref);
+  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);
 
-  self->path = gsk_path_simplify (path);
+  self->orig_path1 = gsk_path_ref (path1);
+  self->orig_path2 = gsk_path_ref (path2);
+  switch (self->operation)
+    {
+    case 0:
+      builder = gsk_path_builder_new ();
+      gsk_path_builder_add_path (builder, path1);
+      gsk_path_builder_add_path (builder, path2);
+      self->path = gsk_path_builder_free_to_path (builder);
+      break;
+    case 1:
+      self->path = gsk_path_simplify (path1);
+      break;
+    case 2:
+      self->path = gsk_path_op (1, path1, path2, &self->boundary, &self->interior);
+      break;
+    case 3:
+      self->path = gsk_path_op (2, path1, path2, &self->boundary, &self->interior);
+      break;
+    case 4:
+      self->path = gsk_path_difference (path1, path2);
+      break;
+    case 5:
+      self->path = gsk_path_symmetric_difference (path1, path2);
+      break;
+    default:
+      g_assert_not_reached ();
+    }
 
   builder = gsk_path_builder_new ();
   gsk_path_foreach (self->path, GSK_PATH_FOREACH_ALLOW_CURVE, control_cb, builder);
@@ -406,23 +468,24 @@ close_path (hb_draw_funcs_t *dfuncs,
   gsk_path_builder_close (builder);
 }
 
-static void
-init_demo (DemoWidget *demo)
+static GskPath *
+char_to_path (hb_font_t *font,
+              gunichar   ch)
 {
-  hb_blob_t *blob;
-  hb_face_t *face;
-  hb_font_t *font;
-  hb_draw_funcs_t *funcs;
   hb_codepoint_t glyph;
-  GskPathBuilder *builder;
-  GskPath *path;
   hb_glyph_extents_t extents;
+  GskPathBuilder *builder;
+  hb_draw_funcs_t *funcs;
 
   builder = gsk_path_builder_new ();
 
-  blob = hb_blob_create_from_file (demo->font_file);
-  face = hb_face_create (blob, 0);
-  font = hb_font_create (face);
+  hb_font_get_nominal_glyph (font, ch, &glyph);
+  hb_font_get_glyph_extents (font, glyph, &extents);
+
+  glyph_x0 = 10 + extents.x_bearing;
+  glyph_y0 = 10 + extents.y_bearing;
+
+  gsk_path_builder_move_to (builder, extents.x_bearing, - extents.height);
 
   funcs = hb_draw_funcs_create ();
 
@@ -431,28 +494,36 @@ init_demo (DemoWidget *demo)
   hb_draw_funcs_set_cubic_to_func (funcs, (hb_draw_cubic_to_func_t) cubic_to, NULL, NULL);
   hb_draw_funcs_set_close_path_func (funcs, (hb_draw_close_path_func_t) close_path, NULL, NULL);
 
-  hb_font_get_nominal_glyph (font, demo->ch, &glyph);
-
-  hb_font_get_glyph_extents (font, glyph, &extents);
+  hb_font_get_glyph_shape (font, glyph, funcs, builder);
 
-  glyph_x0 = 10 + extents.x_bearing;
-  glyph_y0 = 10 + extents.y_bearing;
+  hb_draw_funcs_destroy (funcs);
 
-  gsk_path_builder_move_to (builder, extents.x_bearing, - extents.height);
+  return gsk_path_builder_free_to_path (builder);
+}
 
-  hb_font_get_glyph_shape (font, glyph, funcs, builder);
+static void
+init_demo (DemoWidget *demo)
+{
+  hb_blob_t *blob;
+  hb_face_t *face;
+  hb_font_t *font;
+  GskPath *path1, *path2;
 
-  hb_draw_funcs_destroy (funcs);
+  blob = hb_blob_create_from_file (demo->font_file);
+  face = hb_face_create (blob, 0);
+  font = hb_font_create (face);
 
-  hb_font_destroy (font);
-  hb_face_destroy (face);
-  hb_blob_destroy (blob);
+  path1 = char_to_path (font, g_utf8_get_char (demo->text));
 
-  path = gsk_path_builder_free_to_path (builder);
+  if (g_utf8_next_char (demo->text))
+    path2 = char_to_path (font, g_utf8_get_char (g_utf8_next_char (demo->text)));
+  else
+    path2 = gsk_path_ref (path1);
 
-  demo_widget_set_path (demo, path);
+  demo_widget_set_path (demo, path1, path2);
 
-  gsk_path_unref (path);
+  gsk_path_unref (path1);
+  gsk_path_unref (path2);
 
   demo->zoom = 1;
 }
@@ -467,10 +538,10 @@ demo_widget_set_font_file (DemoWidget *demo,
 }
 
 static void
-demo_widget_set_char (DemoWidget *demo,
+demo_widget_set_text (DemoWidget *demo,
                       const char *text)
 {
-  demo->ch = g_utf8_get_char (text);
+  demo->text = g_strdup (text);
   init_demo (demo);
 }
 
@@ -514,6 +585,21 @@ controls_toggled (GtkCheckButton *button,
   gtk_widget_queue_draw (GTK_WIDGET (self));
 }
 
+static void
+operation_changed (GtkDropDown *combo,
+                   GParamSpec  *pspec,
+                   DemoWidget  *self)
+{
+  GskPath *path1, *path2;
+
+  self->operation = (int)gtk_drop_down_get_selected (combo);
+  path1 = gsk_path_ref (self->orig_path1);
+  path2 = gsk_path_ref (self->orig_path2);
+  demo_widget_set_path (self, path1, path2);
+  gsk_path_unref (path1);
+  gsk_path_unref (path2);
+}
+
 static void
 outline_toggled (GtkCheckButton *button,
                  DemoWidget      *self)
@@ -577,7 +663,7 @@ static void
 activate_entry (GtkEntry   *entry,
                 DemoWidget *demo)
 {
-  demo_widget_set_char (demo, gtk_editable_get_text (GTK_EDITABLE (entry)));
+  demo_widget_set_text (demo, gtk_editable_get_text (GTK_EDITABLE (entry)));
 }
 
 int
@@ -611,10 +697,15 @@ main (int argc, char *argv[])
 
   g_signal_connect (button, "clicked", G_CALLBACK (filechooser_cb), demo);
   entry = gtk_entry_new ();
-  gtk_editable_set_text (GTK_EDITABLE (entry), "e");
+  gtk_editable_set_text (GTK_EDITABLE (entry), "KP");
+  gtk_editable_set_width_chars (GTK_EDITABLE (entry), 2);
   gtk_box_append (GTK_BOX (hbox), entry);
   g_signal_connect (entry, "activate", G_CALLBACK (activate_entry), demo);
 
+  combo = gtk_drop_down_new_from_strings ((const char *[]){ "Original", "Simplified", "Union", 
"Intersection", "Difference", "Symmetric Difference", NULL });
+  g_signal_connect (combo, "notify::selected", G_CALLBACK (operation_changed), demo);
+  gtk_box_append (GTK_BOX (hbox), combo);
+
   toggle = gtk_check_button_new_with_label ("Outline");
   gtk_check_button_set_active (GTK_CHECK_BUTTON (toggle), TRUE);
   g_signal_connect (toggle, "toggled", G_CALLBACK (outline_toggled), demo);


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