diff options
-rw-r--r-- | tests/curve3.c | 208 | ||||
-rw-r--r-- | tests/meson.build | 1 |
2 files changed, 209 insertions, 0 deletions
diff --git a/tests/curve3.c b/tests/curve3.c new file mode 100644 index 0000000000..827927b7fa --- /dev/null +++ b/tests/curve3.c @@ -0,0 +1,208 @@ +#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 *measure; + gboolean inside; + GskFillRule fill_rule; +}; + +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->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); +} + +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->path, self->fill_rule); + + gtk_snapshot_append_color (snapshot, + &(GdkRGBA){ 1, 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, 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); +} + +static void +demo_widget_dispose (GObject *object) +{ + DemoWidget *self = DEMO_WIDGET (object); + + g_clear_pointer (&self->path, gsk_path_unref); + g_clear_pointer (&self->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 +demo_widget_set_path (DemoWidget *self, + GskPath *path) +{ + g_clear_pointer (&self->path, gsk_path_unref); + g_clear_pointer (&self->measure, gsk_path_measure_unref); + self->path = gsk_path_ref (path); + self->measure = gsk_path_measure_new (path); + gtk_widget_queue_draw (GTK_WIDGET (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 void +init_demo (DemoWidget *demo) +{ + GskPathBuilder *builder; + GskPath *path; + + builder = gsk_path_builder_new (); + gsk_path_builder_add_circle (builder, &GRAPHENE_POINT_INIT (150, 150), 100); + gsk_path_builder_add_rect (builder, &GRAPHENE_RECT_INIT (100, 100, 100, 100)); + gsk_path_builder_move_to (builder, 300, 150); + gsk_path_builder_curve_to (builder, 300, 50, 400, 50, 400, 150); + gsk_path_builder_curve_to (builder, 400, 250, 500, 250, 500, 150); + 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)); +} + +int +main (int argc, char *argv[]) +{ + GtkWidget *window, *box, *demo; + GtkWidget *popover, *button, *grid; + GtkWidget *header, *combo; + + 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); + + init_demo (DEMO_WIDGET (demo)); + + 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; +} diff --git a/tests/meson.build b/tests/meson.build index 99f95009f0..9e696056d7 100644 --- a/tests/meson.build +++ b/tests/meson.build @@ -1,5 +1,6 @@ gtk_tests = [ # testname, optional extra sources + ['curve3'], ['testupload'], ['testtransform'], ['testdropdown'], |