[gtk/wip/matthiasc/lottie-stroke: 54/57] Add an interactive test for stroking
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk/wip/matthiasc/lottie-stroke: 54/57] Add an interactive test for stroking
- Date: Mon, 30 Nov 2020 22:19:45 +0000 (UTC)
commit 3d47c9555d67fec81b61d77a5b232b0e43627fdf
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Nov 28 13:30:35 2020 -0500
Add an interactive test for stroking
Give the curve3 test a full complement of stroke
parameters to play with and make it useful for
debugging stroking.
tests/curve3.c | 334 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 334 insertions(+)
---
diff --git a/tests/curve3.c b/tests/curve3.c
new file mode 100644
index 0000000000..f413f7b412
--- /dev/null
+++ b/tests/curve3.c
@@ -0,0 +1,334 @@
+#include <gtk/gtk.h>
+
+#define DEMO_TYPE_WIDGET (demo_widget_get_type ())
+G_DECLARE_FINAL_TYPE (DemoWidget, demo_widget, DEMO, WIDGET, GtkWidget)
+
+struct _DemoWidget
+{
+ GtkWidget parent_instance;
+ GskPath *path;
+ GskPathMeasure *stroke_measure;
+ GskPath *stroke_path;
+ gboolean inside;
+ GskFillRule fill_rule;
+ GskStroke *stroke;
+};
+
+struct _DemoWidgetClass
+{
+ GtkWidgetClass parent_class;
+};
+
+G_DEFINE_TYPE (DemoWidget, demo_widget, GTK_TYPE_WIDGET)
+
+static void
+motion (GtkEventControllerMotion *controller,
+ double x,
+ double y,
+ DemoWidget *self)
+{
+ gboolean inside = TRUE;
+
+ inside = gsk_path_measure_in_fill (self->stroke_measure, &GRAPHENE_POINT_INIT (x, y), self->fill_rule);
+ if (self->inside == inside)
+ return;
+
+ self->inside = inside;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+demo_widget_init (DemoWidget *self)
+{
+ GtkEventController *controller;
+
+ controller = gtk_event_controller_motion_new ();
+ g_signal_connect (controller, "motion", G_CALLBACK (motion), self);
+ gtk_widget_add_controller (GTK_WIDGET (self), controller);
+
+ self->stroke = gsk_stroke_new (40.f);
+}
+
+static void
+demo_widget_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ DemoWidget *self = DEMO_WIDGET (widget);
+ int width, height;
+ GskStroke *stroke;
+
+ if (!self->path)
+ return;
+
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_width (widget);
+
+ if (self->inside)
+ {
+ gtk_snapshot_push_fill (snapshot, self->stroke_path, self->fill_rule);
+
+ gtk_snapshot_append_color (snapshot,
+ &(GdkRGBA){ 1, 0, 1, 0.3},
+ &GRAPHENE_RECT_INIT (0, 0, width, height ));
+
+ gtk_snapshot_pop (snapshot);
+ }
+
+ stroke = gsk_stroke_new (1.0);
+ gtk_snapshot_push_stroke (snapshot, self->stroke_path, stroke);
+
+ gtk_snapshot_append_color (snapshot,
+ &(GdkRGBA){ 0, 0, 0, 1},
+ &GRAPHENE_RECT_INIT (0, 0, width, height ));
+
+ gtk_snapshot_pop (snapshot);
+
+ gtk_snapshot_push_stroke (snapshot, self->path, 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);
+}
+
+static void
+demo_widget_dispose (GObject *object)
+{
+ DemoWidget *self = DEMO_WIDGET (object);
+
+ g_clear_pointer (&self->path, gsk_path_unref);
+ g_clear_pointer (&self->stroke_path, gsk_path_unref);
+ g_clear_pointer (&self->stroke, gsk_stroke_free);
+ g_clear_pointer (&self->stroke_measure, gsk_path_measure_unref);
+
+ G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
+}
+
+static void
+demo_widget_class_init (DemoWidgetClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->dispose = demo_widget_dispose;
+
+ widget_class->snapshot = demo_widget_snapshot;
+
+ gtk_widget_class_set_layout_manager_type (widget_class, GTK_TYPE_BIN_LAYOUT);
+}
+
+static GtkWidget *
+demo_widget_new (void)
+{
+ return g_object_new (DEMO_TYPE_WIDGET, NULL);
+}
+
+static void
+update_stroke_path (DemoWidget *self)
+{
+ g_clear_pointer (&self->stroke_path, gsk_path_unref);
+ g_clear_pointer (&self->stroke_measure, gsk_path_measure_unref);
+
+ self->stroke_path = gsk_path_to_stroke (self->path, self->stroke);
+ self->stroke_measure = gsk_path_measure_new (self->stroke_path);
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+demo_widget_set_path (DemoWidget *self,
+ GskPath *path)
+{
+ g_clear_pointer (&self->path, gsk_path_unref);
+ self->path = gsk_path_ref (path);
+ update_stroke_path (self);
+}
+
+static void
+demo_widget_set_fill_rule (DemoWidget *self,
+ GskFillRule fill_rule)
+{
+ self->fill_rule = fill_rule;
+
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static const GskStroke *
+demo_widget_get_stroke (DemoWidget *self)
+{
+ return self->stroke;
+}
+
+static void
+demo_widget_set_stroke (DemoWidget *self,
+ GskStroke *stroke)
+{
+ gsk_stroke_free (self->stroke);
+ self->stroke = gsk_stroke_copy (stroke);
+ update_stroke_path (self);
+}
+
+static void
+init_demo (DemoWidget *demo, float squeeze)
+{
+ GskPathBuilder *builder;
+ GskPath *path;
+
+ builder = gsk_path_builder_new ();
+
+ gsk_path_builder_move_to (builder, 400, 100);
+ gsk_path_builder_curve_to (builder, 450, 100,
+ 500, 150,
+ 500, 200);
+ gsk_path_builder_curve_to (builder, 500, 250,
+ 450, 300,
+ 400, 300);
+ gsk_path_builder_curve_to (builder, 350, 300,
+ 300, 250,
+ 300, 200);
+ gsk_path_builder_curve_to (builder, 300, 150,
+ 350, 100,
+ 400, 100);
+ gsk_path_builder_close (builder);
+
+ gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (300, 300, 100, 100));
+
+ gsk_path_builder_move_to (builder, 100, 100);
+ gsk_path_builder_curve_to (builder, 100, 200, 200, 200, 210, 100);
+ gsk_path_builder_curve_to (builder, 210+squeeze, 200, 310+squeeze, 200, 310+squeeze, 100);
+
+ gsk_path_builder_move_to (builder, 20, 20);
+
+ path = gsk_path_builder_free_to_path (builder);
+
+ demo_widget_set_path (demo, path);
+
+ gsk_path_unref (path);
+}
+
+static void
+fill_rule_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ demo_widget_set_fill_rule (self, (GskFillRule)gtk_drop_down_get_selected (combo));
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+cap_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ GskStroke *stroke;
+
+ stroke = gsk_stroke_copy (demo_widget_get_stroke (self));
+ gsk_stroke_set_line_cap (stroke, (GskLineCap)gtk_drop_down_get_selected (combo));
+ demo_widget_set_stroke (self, stroke);
+ gsk_stroke_free (stroke);
+}
+
+static void
+join_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ GskStroke *stroke;
+
+ stroke = gsk_stroke_copy (demo_widget_get_stroke (self));
+ gsk_stroke_set_line_join (stroke, (GskLineJoin)gtk_drop_down_get_selected (combo));
+ demo_widget_set_stroke (self, stroke);
+ gsk_stroke_free (stroke);
+}
+
+static void
+limit_changed (GtkSpinButton *spin,
+ DemoWidget *self)
+{
+ GskStroke *stroke;
+
+ stroke = gsk_stroke_copy (demo_widget_get_stroke (self));
+ gsk_stroke_set_miter_limit (stroke, gtk_spin_button_get_value (spin));
+ demo_widget_set_stroke (self, stroke);
+ gsk_stroke_free (stroke);
+}
+
+static void
+squeeze_cb (GtkRange *range, DemoWidget *self)
+{
+ init_demo (self, gtk_range_get_value (range));
+}
+
+int
+main (int argc, char *argv[])
+{
+ GtkWidget *window, *box, *demo;
+ GtkWidget *popover, *button, *grid;
+ GtkWidget *header, *combo;
+ GtkWidget *scale;
+ GtkWidget *spin;
+
+ gtk_init ();
+
+ window = gtk_window_new ();
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_window_set_child (GTK_WINDOW (window), box);
+
+ demo = demo_widget_new ();
+ gtk_widget_set_hexpand (demo, TRUE);
+ gtk_widget_set_vexpand (demo, TRUE);
+ gtk_box_append (GTK_BOX (box), demo);
+
+ header = gtk_header_bar_new ();
+ button = gtk_menu_button_new ();
+ gtk_menu_button_set_icon_name (GTK_MENU_BUTTON (button), "emblem-system-symbolic");
+ gtk_header_bar_pack_start (GTK_HEADER_BAR (header), button);
+ gtk_window_set_titlebar (GTK_WINDOW (window), header);
+
+ popover = gtk_popover_new ();
+ gtk_menu_button_set_popover (GTK_MENU_BUTTON (button), popover);
+
+ grid = gtk_grid_new ();
+ gtk_grid_set_row_spacing (GTK_GRID (grid), 6);
+ gtk_grid_set_column_spacing (GTK_GRID (grid), 6);
+ gtk_popover_set_child (GTK_POPOVER (popover), grid);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Fill rule"), 0, 0, 1, 1);
+
+ combo = gtk_drop_down_new_from_strings ((const char *[]){"Winding", "Even-Odd", NULL });
+ g_signal_connect (combo, "notify::selected", G_CALLBACK (fill_rule_changed), demo);
+ gtk_grid_attach (GTK_GRID (grid), combo, 1, 0, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line cap:"), 0, 1, 1, 1);
+ combo = gtk_drop_down_new_from_strings ((const char *[]){"Butt", "Round", "Square", NULL});
+ g_signal_connect (combo, "notify::selected", G_CALLBACK (cap_changed), demo);
+ gtk_grid_attach (GTK_GRID (grid), combo, 1, 1, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line join:"), 0, 2, 1, 1);
+ combo = gtk_drop_down_new_from_strings ((const char *[]){"Miter", "Miter-clip", "Round", "Bevel", NULL});
+ g_signal_connect (combo, "notify::selected", G_CALLBACK (join_changed), demo);
+ gtk_grid_attach (GTK_GRID (grid), combo, 1, 2, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Miter limit:"), 0, 3, 1, 1);
+ spin = gtk_spin_button_new_with_range (0, 10, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 4);
+ g_signal_connect (spin, "value-changed", G_CALLBACK (limit_changed), demo);
+ gtk_grid_attach (GTK_GRID (grid), spin, 1, 3, 1, 1);
+
+ scale = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL, 0, 100, 1);
+ gtk_range_set_value (GTK_RANGE (scale), 50);
+ g_signal_connect (scale, "value-changed", G_CALLBACK (squeeze_cb), demo);
+ gtk_box_append (GTK_BOX (box), scale);
+
+ init_demo (DEMO_WIDGET (demo), 50);
+
+ gtk_window_present (GTK_WINDOW (window));
+
+ while (g_list_model_get_n_items (gtk_window_get_toplevels ()) > 0)
+ g_main_context_iteration (NULL, TRUE);
+
+ return 0;
+}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]