summaryrefslogtreecommitdiff
path: root/demos
diff options
context:
space:
mode:
authorMatthias Clasen <mclasen@redhat.com>2023-02-11 21:38:42 -0500
committerMatthias Clasen <mclasen@redhat.com>2023-02-12 08:35:25 -0500
commit348803af7de44b7b37d9b45ced559d95b0c8be08 (patch)
tree7c380b64e2892101670d27e2120a9eda3bcbb4bd /demos
parentc8bfea7aa17efaacee316689b8fa0ec7a6289e7b (diff)
downloadgtk+-348803af7de44b7b37d9b45ced559d95b0c8be08.tar.gz
Add a mask node demo
Diffstat (limited to 'demos')
-rw-r--r--demos/gtk-demo/demo.gresource.xml7
-rw-r--r--demos/gtk-demo/demo4widget.c123
-rw-r--r--demos/gtk-demo/demo4widget.h8
-rw-r--r--demos/gtk-demo/hsla.c146
-rw-r--r--demos/gtk-demo/hsla.h15
-rw-r--r--demos/gtk-demo/mask.c46
-rw-r--r--demos/gtk-demo/meson.build3
7 files changed, 348 insertions, 0 deletions
diff --git a/demos/gtk-demo/demo.gresource.xml b/demos/gtk-demo/demo.gresource.xml
index 9eca1c16a7..3db485748a 100644
--- a/demos/gtk-demo/demo.gresource.xml
+++ b/demos/gtk-demo/demo.gresource.xml
@@ -215,6 +215,12 @@
<file>demo3widget.h</file>
<file>demo3widget.ui</file>
</gresource>
+ <gresource prefix="/mask">
+ <file>demo4widget.c</file>
+ <file>demo4widget.h</file>
+ <file>hsla.h</file>
+ <file>hsla.c</file>
+ </gresource>
<gresource prefix="/paintable_svg">
<file>svgpaintable.h</file>
<file>svgpaintable.c</file>
@@ -311,6 +317,7 @@
<file>list_store.c</file>
<file>main.c</file>
<file>markup.c</file>
+ <file>mask.c</file>
<file>menu.c</file>
<file>overlay.c</file>
<file>overlay_decorative.c</file>
diff --git a/demos/gtk-demo/demo4widget.c b/demos/gtk-demo/demo4widget.c
new file mode 100644
index 0000000000..3478272197
--- /dev/null
+++ b/demos/gtk-demo/demo4widget.c
@@ -0,0 +1,123 @@
+#include <math.h>
+#include "demo4widget.h"
+#include "hsla.h"
+
+struct _Demo4Widget
+{
+ GtkWidget parent_instance;
+ PangoLayout *layout;
+ GskColorStop stops[8];
+ gsize n_stops;
+
+ guint tick;
+};
+
+struct _Demo4WidgetClass
+{
+ GtkWidgetClass parent_class;
+};
+
+G_DEFINE_TYPE (Demo4Widget, demo4_widget, GTK_TYPE_WIDGET)
+
+static void
+rotate_color (GdkRGBA *rgba)
+{
+ GdkHSLA hsla;
+
+ _gdk_hsla_init_from_rgba (&hsla, rgba);
+ hsla.hue -= 1;
+ _gdk_rgba_init_from_hsla (rgba, &hsla);
+}
+
+static gboolean
+rotate_colors (GtkWidget *widget,
+ GdkFrameClock *clock,
+ gpointer user_data)
+{
+ Demo4Widget *self = DEMO4_WIDGET (widget);
+
+ for (unsigned int i = 0; i < self->n_stops; i++)
+ rotate_color (&self->stops[i].color);
+
+ gtk_widget_queue_draw (widget);
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+demo4_widget_init (Demo4Widget *self)
+{
+ PangoFontDescription *desc;
+
+ self->n_stops = 8;
+ self->stops[0].offset = 0;
+ self->stops[0].color = (GdkRGBA) { 1, 0, 0, 1 };
+
+ for (unsigned int i = 1; i < self->n_stops; i++)
+ {
+ GdkHSLA hsla;
+
+ self->stops[i].offset = i / (double)(self->n_stops - 1);
+ _gdk_hsla_init_from_rgba (&hsla, &self->stops[i - 1].color);
+ hsla.hue += 360.0 / (double)(self->n_stops - 1);
+ _gdk_rgba_init_from_hsla (&self->stops[i].color, &hsla);
+ }
+
+ self->layout = gtk_widget_create_pango_layout (GTK_WIDGET (self), "123");
+ desc = pango_font_description_from_string ("Cantarell Bold 210");
+ pango_layout_set_font_description (self->layout, desc);
+ pango_font_description_free (desc);
+
+ self->tick = gtk_widget_add_tick_callback (GTK_WIDGET (self), rotate_colors, NULL, NULL);
+}
+
+static void
+demo4_widget_dispose (GObject *object)
+{
+ Demo4Widget *self = DEMO4_WIDGET (object);
+
+ g_clear_object (&self->layout);
+ gtk_widget_remove_tick_callback (GTK_WIDGET (self), self->tick);
+
+ G_OBJECT_CLASS (demo4_widget_parent_class)->dispose (object);
+}
+
+static void
+demo4_widget_snapshot (GtkWidget *widget,
+ GtkSnapshot *snapshot)
+{
+ Demo4Widget *self = DEMO4_WIDGET (widget);
+ int width, height;
+
+ width = gtk_widget_get_width (widget);
+ height = gtk_widget_get_height (widget);
+
+ gtk_snapshot_push_mask (snapshot);
+ gtk_snapshot_append_layout (snapshot, self->layout, &(GdkRGBA) { 0, 0, 0, 1 });
+ gtk_snapshot_pop (snapshot);
+
+ gtk_snapshot_append_linear_gradient (snapshot,
+ &GRAPHENE_RECT_INIT (0, 0, width, height),
+ &GRAPHENE_POINT_INIT (0, 0),
+ &GRAPHENE_POINT_INIT (width, height),
+ self->stops,
+ self->n_stops);
+ gtk_snapshot_pop (snapshot);
+}
+
+static void
+demo4_widget_class_init (Demo4WidgetClass *class)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (class);
+ GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (class);
+
+ object_class->dispose = demo4_widget_dispose;
+
+ widget_class->snapshot = demo4_widget_snapshot;
+}
+
+GtkWidget *
+demo4_widget_new (void)
+{
+ return g_object_new (DEMO4_TYPE_WIDGET, NULL);
+}
diff --git a/demos/gtk-demo/demo4widget.h b/demos/gtk-demo/demo4widget.h
new file mode 100644
index 0000000000..4546a4c397
--- /dev/null
+++ b/demos/gtk-demo/demo4widget.h
@@ -0,0 +1,8 @@
+#pragma once
+
+#include <gtk/gtk.h>
+
+#define DEMO4_TYPE_WIDGET (demo4_widget_get_type ())
+G_DECLARE_FINAL_TYPE (Demo4Widget, demo4_widget, DEMO4, WIDGET, GtkWidget)
+
+GtkWidget * demo4_widget_new (void);
diff --git a/demos/gtk-demo/hsla.c b/demos/gtk-demo/hsla.c
new file mode 100644
index 0000000000..abf635ee7e
--- /dev/null
+++ b/demos/gtk-demo/hsla.c
@@ -0,0 +1,146 @@
+#include <gdk/gdk.h>
+#include "hsla.h"
+
+void
+_gdk_hsla_init_from_rgba (GdkHSLA *hsla,
+ const GdkRGBA *rgba)
+{
+ float min;
+ float max;
+ float red;
+ float green;
+ float blue;
+ float delta;
+
+ g_return_if_fail (hsla != NULL);
+ g_return_if_fail (rgba != NULL);
+
+ red = rgba->red;
+ green = rgba->green;
+ blue = rgba->blue;
+
+ if (red > green)
+ {
+ if (red > blue)
+ max = red;
+ else
+ max = blue;
+
+ if (green < blue)
+ min = green;
+ else
+ min = blue;
+ }
+ else
+ {
+ if (green > blue)
+ max = green;
+ else
+ max = blue;
+
+ if (red < blue)
+ min = red;
+ else
+ min = blue;
+ }
+
+ hsla->lightness = (max + min) / 2;
+ hsla->saturation = 0;
+ hsla->hue = 0;
+ hsla->alpha = rgba->alpha;
+
+ if (max != min)
+ {
+ if (hsla->lightness <= 0.5)
+ hsla->saturation = (max - min) / (max + min);
+ else
+ hsla->saturation = (max - min) / (2 - max - min);
+
+ delta = max -min;
+ if (red == max)
+ hsla->hue = (green - blue) / delta;
+ else if (green == max)
+ hsla->hue = 2 + (blue - red) / delta;
+ else if (blue == max)
+ hsla->hue = 4 + (red - green) / delta;
+
+ hsla->hue *= 60;
+ if (hsla->hue < 0.0)
+ hsla->hue += 360;
+ }
+}
+
+void
+_gdk_rgba_init_from_hsla (GdkRGBA *rgba,
+ const GdkHSLA *hsla)
+{
+ float hue;
+ float lightness;
+ float saturation;
+ float m1, m2;
+
+ lightness = hsla->lightness;
+ saturation = hsla->saturation;
+
+ if (lightness <= 0.5)
+ m2 = lightness * (1 + saturation);
+ else
+ m2 = lightness + saturation - lightness * saturation;
+ m1 = 2 * lightness - m2;
+
+ rgba->alpha = hsla->alpha;
+
+ if (saturation == 0)
+ {
+ rgba->red = lightness;
+ rgba->green = lightness;
+ rgba->blue = lightness;
+ }
+ else
+ {
+ hue = hsla->hue + 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ rgba->red = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ rgba->red = m2;
+ else if (hue < 240)
+ rgba->red = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ rgba->red = m1;
+
+ hue = hsla->hue;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ rgba->green = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ rgba->green = m2;
+ else if (hue < 240)
+ rgba->green = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ rgba->green = m1;
+
+ hue = hsla->hue - 120;
+ while (hue > 360)
+ hue -= 360;
+ while (hue < 0)
+ hue += 360;
+
+ if (hue < 60)
+ rgba->blue = m1 + (m2 - m1) * hue / 60;
+ else if (hue < 180)
+ rgba->blue = m2;
+ else if (hue < 240)
+ rgba->blue = m1 + (m2 - m1) * (240 - hue) / 60;
+ else
+ rgba->blue = m1;
+ }
+}
diff --git a/demos/gtk-demo/hsla.h b/demos/gtk-demo/hsla.h
new file mode 100644
index 0000000000..52c6bdc146
--- /dev/null
+++ b/demos/gtk-demo/hsla.h
@@ -0,0 +1,15 @@
+#pragma once
+
+typedef struct _GdkHSLA GdkHSLA;
+
+struct _GdkHSLA {
+ float hue;
+ float saturation;
+ float lightness;
+ float alpha;
+};
+
+void _gdk_hsla_init_from_rgba (GdkHSLA *hsla,
+ const GdkRGBA *rgba);
+void _gdk_rgba_init_from_hsla (GdkRGBA *rgba,
+ const GdkHSLA *hsla);
diff --git a/demos/gtk-demo/mask.c b/demos/gtk-demo/mask.c
new file mode 100644
index 0000000000..4266b44b52
--- /dev/null
+++ b/demos/gtk-demo/mask.c
@@ -0,0 +1,46 @@
+/* Masking
+ *
+ * Demonstrates mask nodes.
+ *
+ * This demo uses a text node as mask for
+ * an animated linear gradient.
+ */
+
+#include <gtk/gtk.h>
+#include "demo4widget.h"
+
+
+GtkWidget *
+do_mask (GtkWidget *do_widget)
+{
+ static GtkWidget *window = NULL;
+
+ if (!window)
+ {
+ GtkWidget *box;
+ GtkWidget *widget;
+
+ window = gtk_window_new ();
+ gtk_window_set_title (GTK_WINDOW (window), "Mask Nodes");
+ gtk_window_set_default_size (GTK_WINDOW (window), 600, 400);
+ gtk_window_set_display (GTK_WINDOW (window),
+ gtk_widget_get_display (do_widget));
+ g_object_add_weak_pointer (G_OBJECT (window), (gpointer *)&window);
+
+ box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
+ gtk_window_set_child (GTK_WINDOW (window), box);
+
+ widget = demo4_widget_new ();
+ gtk_widget_set_hexpand (widget, TRUE);
+ gtk_widget_set_vexpand (widget, TRUE);
+
+ gtk_box_append (GTK_BOX (box), widget);
+ }
+
+ if (!gtk_widget_get_visible (window))
+ gtk_widget_set_visible (window, TRUE);
+ else
+ gtk_window_destroy (GTK_WINDOW (window));
+
+ return window;
+}
diff --git a/demos/gtk-demo/meson.build b/demos/gtk-demo/meson.build
index 5537cf20a5..b1c21a9f9b 100644
--- a/demos/gtk-demo/meson.build
+++ b/demos/gtk-demo/meson.build
@@ -46,6 +46,7 @@ demos = files([
'links.c',
'listbox.c',
'listbox_controls.c',
+ 'mask.c',
'menu.c',
'flowbox.c',
'list_store.c',
@@ -114,6 +115,7 @@ extra_demo_sources = files([
'gtkshadertoy.c',
'gtkshaderstack.c',
'gskshaderpaintable.c',
+ 'hsla.c',
'puzzlepiece.c',
'bluroverlay.c',
'demoimage.c',
@@ -126,6 +128,7 @@ extra_demo_sources = files([
'four_point_transform.c',
'demo2widget.c',
'demo3widget.c',
+ 'demo4widget.c',
'pixbufpaintable.c',
'script-names.c',
'unicode-names.c',