[gtk/wip/matthiasc/lottie-stroke: 6/16] 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: 6/16] Add an interactive test for stroking
- Date: Wed, 2 Dec 2020 05:19:29 +0000 (UTC)
commit bb58fb66fd4fbec2875af8b058afd9a2fde5c73b
Author: Matthias Clasen <mclasen redhat com>
Date: Sat Nov 28 13:30:35 2020 -0500
Add an interactive test for stroking
Give the curve test a full complement of stroke
parameters to play with and make it useful for
debugging various aspects of path functionality
and in particular path stroking.
tests/curve2.c | 223 +++++++++++++++++++++++++++++++++++++++++++++++++--------
1 file changed, 193 insertions(+), 30 deletions(-)
---
diff --git a/tests/curve2.c b/tests/curve2.c
index c4be5cf8f0..c3178d11e7 100644
--- a/tests/curve2.c
+++ b/tests/curve2.c
@@ -18,6 +18,13 @@ struct _DemoWidget
gboolean track;
gboolean show_bounding_box;
GtkWidget *label;
+
+ gboolean do_stroke;
+ GskPathMeasure *stroke_measure;
+ GskPath *stroke_path;
+ gboolean inside;
+ GskFillRule fill_rule;
+ GskStroke *stroke;
};
struct _DemoWidgetClass
@@ -33,29 +40,43 @@ motion (GtkEventControllerMotion *controller,
double y,
DemoWidget *self)
{
- float distance;
- char *text;
- float t;
+ if (self->track)
+ {
+ float distance;
+ char *text;
+ float t;
- if (!self->track)
- return;
+ self->x = x;
+ self->y = y;
- self->x = x;
- self->y = y;
- gsk_path_measure_get_closest_point_full (self->measure,
- &GRAPHENE_POINT_INIT (x, y),
- FLT_MAX,
- &distance,
- &self->point,
- &t,
- &self->tangent);
+ gsk_path_measure_get_closest_point_full (self->measure,
+ &GRAPHENE_POINT_INIT (x, y),
+ INFINITY,
+ &distance,
+ &self->point,
+ &t,
+ &self->tangent);
- gsk_path_measure_get_point (self->measure, t, &self->point2, NULL);
+ gsk_path_measure_get_point (self->measure, t, &self->point2, NULL);
- text = g_strdup_printf ("%.1f", distance);
- gtk_label_set_label (GTK_LABEL (self->label), text);
+ text = g_strdup_printf ("%.1f", distance);
+ gtk_label_set_label (GTK_LABEL (self->label), text);
- gtk_widget_queue_draw (GTK_WIDGET (self));
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ }
+
+ if (self->do_stroke)
+ {
+ gboolean inside = TRUE;
+
+ inside = gsk_path_measure_in_fill (self->stroke_measure, &GRAPHENE_POINT_INIT (x, y), self->fill_rule);
+
+ if (self->inside != inside)
+ {
+ self->inside = inside;
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+ }
+ }
}
static void
@@ -85,7 +106,6 @@ demo_widget_snapshot (GtkWidget *widget,
GskStroke *stroke;
GskPathBuilder *builder;
GskPath *path;
- graphene_point_t p;
if (!self->path)
return;
@@ -93,21 +113,55 @@ demo_widget_snapshot (GtkWidget *widget,
width = gtk_widget_get_width (widget);
height = gtk_widget_get_width (widget);
- stroke = gsk_stroke_new (1.0);
- gtk_snapshot_push_stroke (snapshot, self->path, stroke);
- gsk_stroke_free (stroke);
+ if (self->do_stroke)
+ {
+ 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_append_color (snapshot,
- &(GdkRGBA){ 0, 0, 0, 1},
- &GRAPHENE_RECT_INIT (0, 0, width, height ));
+ gtk_snapshot_pop (snapshot);
+ }
- 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);
+ }
+ else
+ {
+ stroke = gsk_stroke_new (1.0);
+ gtk_snapshot_push_stroke (snapshot, self->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);
+ }
if (self->show_bounding_box)
{
graphene_rect_t bounds;
- if (gsk_path_get_bounds (self->path, &bounds))
+ if (gsk_path_get_bounds (self->do_stroke ? self->stroke_path : self->path, &bounds))
{
builder = gsk_path_builder_new ();
@@ -131,6 +185,8 @@ demo_widget_snapshot (GtkWidget *widget,
if (self->track)
{
+ graphene_point_t p;
+
p.x = self->point.x + graphene_vec2_get_x (&self->tangent) * 40;
p.y = self->point.y + graphene_vec2_get_y (&self->tangent) * 40;
@@ -190,6 +246,9 @@ demo_widget_dispose (GObject *object)
g_clear_pointer (&self->path, gsk_path_unref);
g_clear_pointer (&self->measure, gsk_path_measure_unref);
+ g_clear_pointer (&self->stroke_path, gsk_path_unref);
+ g_clear_pointer (&self->stroke_measure, gsk_path_measure_unref);
+ g_clear_pointer (&self->stroke, gsk_stroke_free);
g_clear_pointer (&self->label, gtk_widget_unparent);
G_OBJECT_CLASS (demo_widget_parent_class)->dispose (object);
@@ -214,6 +273,21 @@ 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);
+
+ if (self->do_stroke)
+ {
+ 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
update_path (DemoWidget *self)
{
@@ -238,6 +312,8 @@ update_path (DemoWidget *self)
self->measure = gsk_path_measure_new (self->path);
+ update_stroke_path (self);
+
gtk_widget_queue_draw (GTK_WIDGET (self));
}
@@ -287,6 +363,8 @@ init_demo (DemoWidget *demo,
gtk_editable_set_text (editable, string);
g_free (string);
gsk_path_unref (path);
+
+ demo->stroke = gsk_stroke_new (20);
}
static void
@@ -305,6 +383,15 @@ bb_toggled (GtkCheckButton *button,
gtk_widget_queue_draw (GTK_WIDGET (self));
}
+static void
+stroke_toggled (GtkCheckButton *button,
+ DemoWidget *self)
+{
+ self->do_stroke = gtk_check_button_get_active (button);
+ update_stroke_path (self);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
static GtkWidget *start_scale;
static GtkWidget *end_scale;
@@ -333,12 +420,55 @@ range_changed (GtkRange *range,
update_path (self);
}
+static void
+fill_rule_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ self->fill_rule = (GskFillRule)gtk_drop_down_get_selected (combo);
+ gtk_widget_queue_draw (GTK_WIDGET (self));
+}
+
+static void
+cap_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ gsk_stroke_set_line_cap (self->stroke, (GskLineCap)gtk_drop_down_get_selected (combo));
+ update_stroke_path (self);
+}
+
+static void
+join_changed (GtkDropDown *combo,
+ GParamSpec *pspec,
+ DemoWidget *self)
+{
+ gsk_stroke_set_line_join (self->stroke, (GskLineJoin)gtk_drop_down_get_selected (combo));
+ update_stroke_path (self);
+}
+
+static void
+limit_changed (GtkSpinButton *spin,
+ DemoWidget *self)
+{
+ gsk_stroke_set_miter_limit (self->stroke, gtk_spin_button_get_value (spin));
+ update_stroke_path (self);
+}
+
+static void
+width_changed (GtkSpinButton *spin,
+ DemoWidget *self)
+{
+ gsk_stroke_set_line_width (self->stroke, gtk_spin_button_get_value (spin));
+ update_stroke_path (self);
+}
+
int
main (int argc, char *argv[])
{
GtkWidget *window, *box, *demo, *entry;
GtkWidget *popover, *button, *grid;
- GtkWidget *header, *toggle;
+ GtkWidget *header, *toggle, *combo, *spin;
gtk_init ();
@@ -368,11 +498,44 @@ main (int argc, char *argv[])
toggle = gtk_check_button_new_with_label ("Show closest point");
g_signal_connect (toggle, "toggled", G_CALLBACK (track_toggled), demo);
- gtk_grid_attach (GTK_GRID (grid), toggle, 0, 0, 1, 1);
+ gtk_grid_attach (GTK_GRID (grid), toggle, 1, 0, 1, 1);
toggle = gtk_check_button_new_with_label ("Show bounding box");
g_signal_connect (toggle, "toggled", G_CALLBACK (bb_toggled), demo);
- gtk_grid_attach (GTK_GRID (grid), toggle, 0, 1, 1, 1);
+ gtk_grid_attach (GTK_GRID (grid), toggle, 1, 1, 1, 1);
+
+ toggle = gtk_check_button_new_with_label ("Stroke path");
+ g_signal_connect (toggle, "toggled", G_CALLBACK (stroke_toggled), demo);
+ gtk_grid_attach (GTK_GRID (grid), toggle, 1, 2, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Fill rule"), 0, 3, 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, 3, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line cap:"), 0, 4, 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, 4, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line join:"), 0, 5, 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, 5, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Miter limit:"), 0, 6, 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, 6, 1, 1);
+
+ gtk_grid_attach (GTK_GRID (grid), gtk_label_new ("Line width:"), 0, 7, 1, 1);
+ spin = gtk_spin_button_new_with_range (1, 40, 1);
+ gtk_spin_button_set_value (GTK_SPIN_BUTTON (spin), 20);
+ g_signal_connect (spin, "value-changed", G_CALLBACK (width_changed), demo);
+ gtk_grid_attach (GTK_GRID (grid), spin, 1, 7, 1, 1);
+
entry = gtk_entry_new ();
g_signal_connect (entry, "activate", G_CALLBACK (activate), demo);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]