diff options
-rw-r--r-- | demos/gtk-demo/demo.gresource.xml | 7 | ||||
-rw-r--r-- | demos/gtk-demo/demo4widget.c | 123 | ||||
-rw-r--r-- | demos/gtk-demo/demo4widget.h | 8 | ||||
-rw-r--r-- | demos/gtk-demo/hsla.c | 146 | ||||
-rw-r--r-- | demos/gtk-demo/hsla.h | 15 | ||||
-rw-r--r-- | demos/gtk-demo/mask.c | 46 | ||||
-rw-r--r-- | demos/gtk-demo/meson.build | 3 |
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', |