#include <math.h>
#include "demo4widget.h"
#include "hsla.h"
enum
{
PROP_0,
PROP_PROGRESS,
N_PROPS
};
static GParamSpec *props[N_PROPS] = { NULL, };
struct _Demo4Widget
{
GtkWidget parent_instance;
PangoLayout *layout;
GskColorStop stops[8 ];
gsize n_stops;
double progress;
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)
{
PangoContext *context;
PangoFontDescription *desc;
self->progress = 0 .5 ;
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" );
context = pango_layout_get_context (self->layout);
desc = pango_font_description_copy (pango_context_get_font_description (context));
pango_font_description_set_weight (desc, PANGO_WEIGHT_BOLD);
pango_font_description_set_size (desc, 210 * PANGO_SCALE);
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_content (GtkWidget *widget,
GtkSnapshot *snapshot,
GskMaskMode mode)
{
Demo4Widget *self = DEMO4_WIDGET (widget);
int width, height, layout_width, layout_height;
double scale;
width = gtk_widget_get_width (widget);
height = gtk_widget_get_height (widget);
gtk_snapshot_push_mask (snapshot, mode);
pango_layout_get_pixel_size (self->layout, &layout_width, &layout_height);
scale = MIN ((double ) width / layout_width, (double ) height / layout_height);
gtk_snapshot_translate (snapshot,
&GRAPHENE_POINT_INIT ((width - scale * layout_width) / 2 ,
(height - scale * layout_height) / 2 ));
gtk_snapshot_scale (snapshot, scale, scale);
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_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, GSK_MASK_MODE_INVERTED_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0 , 0 , width, height),
&GRAPHENE_POINT_INIT (0 , 0 ),
&GRAPHENE_POINT_INIT (width, 0 ),
(GskColorStop[2 ]) {
{ MAX (0 .0 , self->progress - 5 .0 / width), { 1 , 1 , 1 , 1 } },
{ MIN (1 .0 , self->progress + 5 .0 / width), { 0 , 0 , 0 , 1 } }
}, 2 );
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_INVERTED_ALPHA);
gtk_snapshot_pop (snapshot);
gtk_snapshot_push_mask (snapshot, GSK_MASK_MODE_LUMINANCE);
gtk_snapshot_append_linear_gradient (snapshot,
&GRAPHENE_RECT_INIT (0 , 0 , width, height),
&GRAPHENE_POINT_INIT (0 , 0 ),
&GRAPHENE_POINT_INIT (width, 0 ),
(GskColorStop[2 ]) {
{ MAX (0 .0 , self->progress - 5 .0 / width), { 1 , 1 , 1 , 1 } },
{ MIN (1 .0 , self->progress + 5 .0 / width), { 0 , 0 , 0 , 1 } }
}, 2 );
gtk_snapshot_pop (snapshot);
demo4_widget_snapshot_content (widget, snapshot, GSK_MASK_MODE_ALPHA);
gtk_snapshot_pop (snapshot);
}
static void
demo4_widget_set_property (GObject *object,
guint prop_id,
const GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
self->progress = g_value_get_double (value);
gtk_widget_queue_draw (GTK_WIDGET (object));
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break ;
}
}
static void
demo4_widget_get_property (GObject *object,
guint prop_id,
GValue *value,
GParamSpec *pspec)
{
Demo4Widget *self = DEMO4_WIDGET (object);
switch (prop_id)
{
case PROP_PROGRESS:
g_value_set_double (value, self->progress);
break ;
default :
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break ;
}
}
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;
object_class->get_property = demo4_widget_get_property;
object_class->set_property = demo4_widget_set_property;
widget_class->snapshot = demo4_widget_snapshot;
props[PROP_PROGRESS] = g_param_spec_double ("progress" , NULL, NULL,
0 .0 , 1 .0 , 0 .5 ,
G_PARAM_READWRITE | G_PARAM_STATIC_NAME);
g_object_class_install_properties (object_class, N_PROPS, props);
}
GtkWidget *
demo4_widget_new (void )
{
return g_object_new (DEMO4_TYPE_WIDGET, NULL);
}
Messung V0.5 in Prozent C=100 H=93 G=96
¤ Dauer der Verarbeitung: 0.11 Sekunden
(vorverarbeitet am 2026-07-03)
¤
*© Formatika GbR, Deutschland