mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-12-29 06:51:10 +00:00
colorbutton: Render with Cairo
In particular, this gets rid of gdk_draw_pixbuf() and GdkGC usage.
This commit is contained in:
parent
d203b830a9
commit
de6314d084
@ -47,15 +47,12 @@
|
|||||||
|
|
||||||
/* Size of checks and gray levels for alpha compositing checkerboard */
|
/* Size of checks and gray levels for alpha compositing checkerboard */
|
||||||
#define CHECK_SIZE 4
|
#define CHECK_SIZE 4
|
||||||
#define CHECK_DARK 21845 /* 65535 / 3 */
|
#define CHECK_DARK (1.0 / 3.0)
|
||||||
#define CHECK_LIGHT 43690
|
#define CHECK_LIGHT (2.0 / 3.0)
|
||||||
|
|
||||||
|
|
||||||
struct _GtkColorButtonPrivate
|
struct _GtkColorButtonPrivate
|
||||||
{
|
{
|
||||||
GdkPixbuf *pixbuf; /* Pixbuf for rendering sample */
|
|
||||||
GdkGC *gc; /* GC for drawing */
|
|
||||||
|
|
||||||
GtkWidget *draw_area; /* Widget where we draw the color sample */
|
GtkWidget *draw_area; /* Widget where we draw the color sample */
|
||||||
GtkWidget *cs_dialog; /* Color selection dialog */
|
GtkWidget *cs_dialog; /* Color selection dialog */
|
||||||
|
|
||||||
@ -96,12 +93,8 @@ static void gtk_color_button_get_property (GObject *object,
|
|||||||
GParamSpec *pspec);
|
GParamSpec *pspec);
|
||||||
|
|
||||||
/* gtkwidget signals */
|
/* gtkwidget signals */
|
||||||
static void gtk_color_button_realize (GtkWidget *widget);
|
|
||||||
static void gtk_color_button_unrealize (GtkWidget *widget);
|
|
||||||
static void gtk_color_button_state_changed (GtkWidget *widget,
|
static void gtk_color_button_state_changed (GtkWidget *widget,
|
||||||
GtkStateType previous_state);
|
GtkStateType previous_state);
|
||||||
static void gtk_color_button_style_set (GtkWidget *widget,
|
|
||||||
GtkStyle *previous_style);
|
|
||||||
|
|
||||||
/* gtkbutton signals */
|
/* gtkbutton signals */
|
||||||
static void gtk_color_button_clicked (GtkButton *button);
|
static void gtk_color_button_clicked (GtkButton *button);
|
||||||
@ -149,9 +142,6 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
|
|||||||
gobject_class->set_property = gtk_color_button_set_property;
|
gobject_class->set_property = gtk_color_button_set_property;
|
||||||
gobject_class->finalize = gtk_color_button_finalize;
|
gobject_class->finalize = gtk_color_button_finalize;
|
||||||
widget_class->state_changed = gtk_color_button_state_changed;
|
widget_class->state_changed = gtk_color_button_state_changed;
|
||||||
widget_class->realize = gtk_color_button_realize;
|
|
||||||
widget_class->unrealize = gtk_color_button_unrealize;
|
|
||||||
widget_class->style_set = gtk_color_button_style_set;
|
|
||||||
button_class->clicked = gtk_color_button_clicked;
|
button_class->clicked = gtk_color_button_clicked;
|
||||||
klass->color_set = NULL;
|
klass->color_set = NULL;
|
||||||
|
|
||||||
@ -241,102 +231,34 @@ gtk_color_button_class_init (GtkColorButtonClass *klass)
|
|||||||
g_type_class_add_private (gobject_class, sizeof (GtkColorButtonPrivate));
|
g_type_class_add_private (gobject_class, sizeof (GtkColorButtonPrivate));
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static gboolean
|
||||||
render (GtkColorButton *color_button)
|
gtk_color_button_has_alpha (GtkColorButton *color_button)
|
||||||
{
|
{
|
||||||
gint dark_r, dark_g, dark_b;
|
return color_button->priv->use_alpha &&
|
||||||
gint light_r, light_g, light_b;
|
color_button->priv->alpha < 65535;
|
||||||
gint i, j, rowstride;
|
}
|
||||||
gint width, height;
|
|
||||||
gint c1[3], c2[3];
|
|
||||||
guchar *pixels;
|
|
||||||
guint8 insensitive_r = 0;
|
|
||||||
guint8 insensitive_g = 0;
|
|
||||||
guint8 insensitive_b = 0;
|
|
||||||
|
|
||||||
width = color_button->priv->draw_area->allocation.width;
|
static cairo_pattern_t *
|
||||||
height = color_button->priv->draw_area->allocation.height;
|
gtk_color_button_get_checkered (void)
|
||||||
if (color_button->priv->pixbuf == NULL ||
|
{
|
||||||
gdk_pixbuf_get_width (color_button->priv->pixbuf) != width ||
|
/* need to respect pixman's stride being a multiple of 4 */
|
||||||
gdk_pixbuf_get_height (color_button->priv->pixbuf) != height)
|
static unsigned char data[8] = { 0xFF, 0x00, 0x00, 0x00,
|
||||||
|
0x00, 0xFF, 0x00, 0x00 };
|
||||||
|
static cairo_surface_t *checkered = NULL;
|
||||||
|
cairo_pattern_t *pattern;
|
||||||
|
|
||||||
|
if (checkered == NULL)
|
||||||
{
|
{
|
||||||
if (color_button->priv->pixbuf != NULL)
|
checkered = cairo_image_surface_create_for_data (data,
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
CAIRO_FORMAT_A8,
|
||||||
color_button->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, width, height);
|
2, 2, 4);
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Compute dark and light check colors */
|
|
||||||
|
|
||||||
insensitive_r = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].red >> 8;
|
|
||||||
insensitive_g = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].green >> 8;
|
|
||||||
insensitive_b = GTK_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE].blue >> 8;
|
|
||||||
|
|
||||||
if (color_button->priv->use_alpha)
|
|
||||||
{
|
|
||||||
dark_r = ((CHECK_DARK << 16) + (color_button->priv->color.red - CHECK_DARK) * color_button->priv->alpha) >> 24;
|
|
||||||
dark_g = ((CHECK_DARK << 16) + (color_button->priv->color.green - CHECK_DARK) * color_button->priv->alpha) >> 24;
|
|
||||||
dark_b = ((CHECK_DARK << 16) + (color_button->priv->color.blue - CHECK_DARK) * color_button->priv->alpha) >> 24;
|
|
||||||
|
|
||||||
light_r = ((CHECK_LIGHT << 16) + (color_button->priv->color.red - CHECK_LIGHT) * color_button->priv->alpha) >> 24;
|
|
||||||
light_g = ((CHECK_LIGHT << 16) + (color_button->priv->color.green - CHECK_LIGHT) * color_button->priv->alpha) >> 24;
|
|
||||||
light_b = ((CHECK_LIGHT << 16) + (color_button->priv->color.blue - CHECK_LIGHT) * color_button->priv->alpha) >> 24;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dark_r = light_r = color_button->priv->color.red >> 8;
|
|
||||||
dark_g = light_g = color_button->priv->color.green >> 8;
|
|
||||||
dark_b = light_b = color_button->priv->color.blue >> 8;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Fill image buffer */
|
pattern = cairo_pattern_create_for_surface (checkered);
|
||||||
pixels = gdk_pixbuf_get_pixels (color_button->priv->pixbuf);
|
cairo_pattern_set_extend (pattern, CAIRO_EXTEND_REPEAT);
|
||||||
rowstride = gdk_pixbuf_get_rowstride (color_button->priv->pixbuf);
|
cairo_pattern_set_filter (pattern, CAIRO_FILTER_NEAREST);
|
||||||
for (j = 0; j < height; j++)
|
|
||||||
{
|
return pattern;
|
||||||
if ((j / CHECK_SIZE) & 1)
|
|
||||||
{
|
|
||||||
c1[0] = dark_r;
|
|
||||||
c1[1] = dark_g;
|
|
||||||
c1[2] = dark_b;
|
|
||||||
|
|
||||||
c2[0] = light_r;
|
|
||||||
c2[1] = light_g;
|
|
||||||
c2[2] = light_b;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
c1[0] = light_r;
|
|
||||||
c1[1] = light_g;
|
|
||||||
c1[2] = light_b;
|
|
||||||
|
|
||||||
c2[0] = dark_r;
|
|
||||||
c2[1] = dark_g;
|
|
||||||
c2[2] = dark_b;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; i < width; i++)
|
|
||||||
{
|
|
||||||
if (!gtk_widget_is_sensitive (GTK_WIDGET (color_button)) && (i+j)%2)
|
|
||||||
{
|
|
||||||
*(pixels + j * rowstride + i * 3) = insensitive_r;
|
|
||||||
*(pixels + j * rowstride + i * 3 + 1) = insensitive_g;
|
|
||||||
*(pixels + j * rowstride + i * 3 + 2) = insensitive_b;
|
|
||||||
}
|
|
||||||
else if ((i / CHECK_SIZE) & 1)
|
|
||||||
{
|
|
||||||
*(pixels + j * rowstride + i * 3) = c1[0];
|
|
||||||
*(pixels + j * rowstride + i * 3 + 1) = c1[1];
|
|
||||||
*(pixels + j * rowstride + i * 3 + 2) = c1[2];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*(pixels + j * rowstride + i * 3) = c2[0];
|
|
||||||
*(pixels + j * rowstride + i * 3 + 1) = c2[1];
|
|
||||||
*(pixels + j * rowstride + i * 3 + 2) = c2[2];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Handle exposure events for the color picker's drawing area */
|
/* Handle exposure events for the color picker's drawing area */
|
||||||
@ -346,81 +268,61 @@ expose_event (GtkWidget *widget,
|
|||||||
gpointer data)
|
gpointer data)
|
||||||
{
|
{
|
||||||
GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
|
GtkColorButton *color_button = GTK_COLOR_BUTTON (data);
|
||||||
|
GtkAllocation allocation;
|
||||||
|
cairo_pattern_t *checkered;
|
||||||
|
cairo_t *cr;
|
||||||
|
|
||||||
gint width = color_button->priv->draw_area->allocation.width;
|
cr = gdk_cairo_create (event->window);
|
||||||
gint height = color_button->priv->draw_area->allocation.height;
|
|
||||||
|
|
||||||
if (color_button->priv->pixbuf == NULL ||
|
gtk_widget_get_allocation (widget, &allocation);
|
||||||
width != gdk_pixbuf_get_width (color_button->priv->pixbuf) ||
|
gdk_cairo_rectangle (cr, &allocation);
|
||||||
height != gdk_pixbuf_get_height (color_button->priv->pixbuf))
|
cairo_clip (cr);
|
||||||
render (color_button);
|
|
||||||
|
if (gtk_color_button_has_alpha (color_button))
|
||||||
|
{
|
||||||
|
cairo_save (cr);
|
||||||
|
|
||||||
|
cairo_set_source_rgb (cr, CHECK_DARK, CHECK_DARK, CHECK_DARK);
|
||||||
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
cairo_set_source_rgb (cr, CHECK_LIGHT, CHECK_LIGHT, CHECK_LIGHT);
|
||||||
|
cairo_scale (cr, CHECK_SIZE, CHECK_SIZE);
|
||||||
|
|
||||||
|
checkered = gtk_color_button_get_checkered ();
|
||||||
|
cairo_mask (cr, checkered);
|
||||||
|
cairo_pattern_destroy (checkered);
|
||||||
|
|
||||||
|
cairo_restore (cr);
|
||||||
|
|
||||||
|
cairo_set_source_rgba (cr,
|
||||||
|
color_button->priv->color.red / 65535.,
|
||||||
|
color_button->priv->color.green / 65535.,
|
||||||
|
color_button->priv->color.blue / 65535.,
|
||||||
|
color_button->priv->alpha / 65535.);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
gdk_cairo_set_source_color (cr, &color_button->priv->color);
|
||||||
|
}
|
||||||
|
|
||||||
|
cairo_paint (cr);
|
||||||
|
|
||||||
|
if (!gtk_widget_is_sensitive (GTK_WIDGET (color_button)))
|
||||||
|
{
|
||||||
|
gdk_cairo_set_source_color (cr, >K_WIDGET(color_button)->style->bg[GTK_STATE_INSENSITIVE]);
|
||||||
|
checkered = gtk_color_button_get_checkered ();
|
||||||
|
cairo_mask (cr, checkered);
|
||||||
|
cairo_pattern_destroy (checkered);
|
||||||
|
}
|
||||||
|
|
||||||
gdk_draw_pixbuf (widget->window,
|
|
||||||
color_button->priv->gc,
|
|
||||||
color_button->priv->pixbuf,
|
|
||||||
event->area.x - widget->allocation.x,
|
|
||||||
event->area.y - widget->allocation.y,
|
|
||||||
event->area.x,
|
|
||||||
event->area.y,
|
|
||||||
event->area.width,
|
|
||||||
event->area.height,
|
|
||||||
GDK_RGB_DITHER_MAX,
|
|
||||||
event->area.x - widget->allocation.x,
|
|
||||||
event->area.y - widget->allocation.y);
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_color_button_realize (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
GtkColorButton *color_button = GTK_COLOR_BUTTON (widget);
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (gtk_color_button_parent_class)->realize (widget);
|
|
||||||
|
|
||||||
color_button->priv->gc = gdk_gc_new (widget->window);
|
|
||||||
|
|
||||||
render (color_button);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_color_button_unrealize (GtkWidget *widget)
|
|
||||||
{
|
|
||||||
GtkColorButton *color_button = GTK_COLOR_BUTTON (widget);
|
|
||||||
|
|
||||||
g_object_unref (color_button->priv->gc);
|
|
||||||
color_button->priv->gc = NULL;
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (gtk_color_button_parent_class)->unrealize (widget);
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
|
||||||
gtk_color_button_style_set (GtkWidget *widget,
|
|
||||||
GtkStyle *previous_style)
|
|
||||||
{
|
|
||||||
GtkColorButton *color_button = GTK_COLOR_BUTTON (widget);
|
|
||||||
|
|
||||||
GTK_WIDGET_CLASS (gtk_color_button_parent_class)->style_set (widget, previous_style);
|
|
||||||
|
|
||||||
if (gtk_widget_get_realized (widget))
|
|
||||||
{
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gtk_color_button_state_changed (GtkWidget *widget,
|
gtk_color_button_state_changed (GtkWidget *widget,
|
||||||
GtkStateType previous_state)
|
GtkStateType previous_state)
|
||||||
{
|
{
|
||||||
GtkColorButton *color_button = GTK_COLOR_BUTTON (widget);
|
gtk_widget_queue_draw (widget);
|
||||||
|
|
||||||
if (widget->state == GTK_STATE_INSENSITIVE || previous_state == GTK_STATE_INSENSITIVE)
|
|
||||||
{
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
@ -455,10 +357,6 @@ gtk_color_button_drag_data_received (GtkWidget *widget,
|
|||||||
color_button->priv->color.blue = dropped[2];
|
color_button->priv->color.blue = dropped[2];
|
||||||
color_button->priv->alpha = dropped[3];
|
color_button->priv->alpha = dropped[3];
|
||||||
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (color_button->priv->draw_area);
|
gtk_widget_queue_draw (color_button->priv->draw_area);
|
||||||
|
|
||||||
g_signal_emit (color_button, color_button_signals[COLOR_SET], 0);
|
g_signal_emit (color_button, color_button_signals[COLOR_SET], 0);
|
||||||
@ -558,13 +456,6 @@ gtk_color_button_init (GtkColorButton *color_button)
|
|||||||
|
|
||||||
color_button->priv->title = g_strdup (_("Pick a Color")); /* default title */
|
color_button->priv->title = g_strdup (_("Pick a Color")); /* default title */
|
||||||
|
|
||||||
/* Create the buffer for the image so that we can create an image.
|
|
||||||
* Also create the picker's pixmap.
|
|
||||||
*/
|
|
||||||
color_button->priv->pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, rect.width, rect.height);
|
|
||||||
|
|
||||||
color_button->priv->gc = NULL;
|
|
||||||
|
|
||||||
/* Start with opaque black, alpha disabled */
|
/* Start with opaque black, alpha disabled */
|
||||||
|
|
||||||
color_button->priv->color.red = 0;
|
color_button->priv->color.red = 0;
|
||||||
@ -601,10 +492,6 @@ gtk_color_button_finalize (GObject *object)
|
|||||||
gtk_widget_destroy (color_button->priv->cs_dialog);
|
gtk_widget_destroy (color_button->priv->cs_dialog);
|
||||||
color_button->priv->cs_dialog = NULL;
|
color_button->priv->cs_dialog = NULL;
|
||||||
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
|
|
||||||
g_free (color_button->priv->title);
|
g_free (color_button->priv->title);
|
||||||
color_button->priv->title = NULL;
|
color_button->priv->title = NULL;
|
||||||
|
|
||||||
@ -661,10 +548,6 @@ dialog_ok_clicked (GtkWidget *widget,
|
|||||||
gtk_color_selection_get_current_color (color_selection, &color_button->priv->color);
|
gtk_color_selection_get_current_color (color_selection, &color_button->priv->color);
|
||||||
color_button->priv->alpha = gtk_color_selection_get_current_alpha (color_selection);
|
color_button->priv->alpha = gtk_color_selection_get_current_alpha (color_selection);
|
||||||
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
|
|
||||||
gtk_widget_hide (color_button->priv->cs_dialog);
|
gtk_widget_hide (color_button->priv->cs_dialog);
|
||||||
|
|
||||||
gtk_widget_queue_draw (color_button->priv->draw_area);
|
gtk_widget_queue_draw (color_button->priv->draw_area);
|
||||||
@ -778,10 +661,6 @@ gtk_color_button_set_color (GtkColorButton *color_button,
|
|||||||
color_button->priv->color.green = color->green;
|
color_button->priv->color.green = color->green;
|
||||||
color_button->priv->color.blue = color->blue;
|
color_button->priv->color.blue = color->blue;
|
||||||
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (color_button->priv->draw_area);
|
gtk_widget_queue_draw (color_button->priv->draw_area);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (color_button), "color");
|
g_object_notify (G_OBJECT (color_button), "color");
|
||||||
@ -805,10 +684,6 @@ gtk_color_button_set_alpha (GtkColorButton *color_button,
|
|||||||
|
|
||||||
color_button->priv->alpha = alpha;
|
color_button->priv->alpha = alpha;
|
||||||
|
|
||||||
if (color_button->priv->pixbuf != NULL)
|
|
||||||
g_object_unref (color_button->priv->pixbuf);
|
|
||||||
color_button->priv->pixbuf = NULL;
|
|
||||||
|
|
||||||
gtk_widget_queue_draw (color_button->priv->draw_area);
|
gtk_widget_queue_draw (color_button->priv->draw_area);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (color_button), "alpha");
|
g_object_notify (G_OBJECT (color_button), "alpha");
|
||||||
@ -873,7 +748,6 @@ gtk_color_button_set_use_alpha (GtkColorButton *color_button,
|
|||||||
{
|
{
|
||||||
color_button->priv->use_alpha = use_alpha;
|
color_button->priv->use_alpha = use_alpha;
|
||||||
|
|
||||||
render (color_button);
|
|
||||||
gtk_widget_queue_draw (color_button->priv->draw_area);
|
gtk_widget_queue_draw (color_button->priv->draw_area);
|
||||||
|
|
||||||
g_object_notify (G_OBJECT (color_button), "use-alpha");
|
g_object_notify (G_OBJECT (color_button), "use-alpha");
|
||||||
|
Loading…
Reference in New Issue
Block a user