canvas-item: Drop gtk_style_context_get_background_color()

Even though more convoluted than the previous solution, this one
should last longer. Canvas item icons are now colorized by first drawing
the background to a Cairo surface and then multiplying the color values
of the original icon pixbuf and the ones from the newly created one.
This commit is contained in:
Ernestas Kulik 2018-05-23 12:54:43 +03:00
parent ad18383afd
commit 487213ad9b
3 changed files with 64 additions and 40 deletions

View file

@ -105,11 +105,11 @@ eel_create_spotlight_pixbuf (GdkPixbuf *src)
return dest;
}
/* this routine colorizes the passed-in pixbuf by multiplying each pixel with the passed in color */
/* This routine colorizes %src by multiplying each pixel with colors in %dest. */
GdkPixbuf *
eel_create_colorized_pixbuf (GdkPixbuf *src,
GdkRGBA *color)
GdkPixbuf *dest)
{
int i, j;
int width, height, has_alpha, src_row_stride, dst_row_stride;
@ -117,21 +117,21 @@ eel_create_colorized_pixbuf (GdkPixbuf *src,
guchar *original_pixels;
guchar *pixsrc;
guchar *pixdest;
GdkPixbuf *dest;
gint red_value, green_value, blue_value;
g_return_val_if_fail (gdk_pixbuf_get_colorspace (src) == GDK_COLORSPACE_RGB, NULL);
g_return_val_if_fail (gdk_pixbuf_get_colorspace (dest) == GDK_COLORSPACE_RGB, NULL);
g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (src)
&& gdk_pixbuf_get_n_channels (src) == 3)
|| (gdk_pixbuf_get_has_alpha (src)
&& gdk_pixbuf_get_n_channels (src) == 4), NULL);
g_return_val_if_fail ((!gdk_pixbuf_get_has_alpha (dest)
&& gdk_pixbuf_get_n_channels (dest) == 3)
|| (gdk_pixbuf_get_has_alpha (dest)
&& gdk_pixbuf_get_n_channels (dest) == 4), NULL);
g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (src) == 8, NULL);
red_value = (gint) floor (color->red * 255);
green_value = (gint) floor (color->green * 255);
blue_value = (gint) floor (color->blue * 255);
dest = create_new_pixbuf (src);
g_return_val_if_fail (gdk_pixbuf_get_bits_per_sample (dest) == 8, NULL);
has_alpha = gdk_pixbuf_get_has_alpha (src);
width = gdk_pixbuf_get_width (src);
@ -147,9 +147,12 @@ eel_create_colorized_pixbuf (GdkPixbuf *src,
pixsrc = original_pixels + i * src_row_stride;
for (j = 0; j < width; j++)
{
*pixdest++ = (*pixsrc++ *red_value) >> 8;
*pixdest++ = (*pixsrc++ *green_value) >> 8;
*pixdest++ = (*pixsrc++ *blue_value) >> 8;
*pixdest = (*pixsrc++ * *pixdest) >> 8;
pixdest++;
*pixdest = (*pixsrc++ * *pixdest) >> 8;
pixdest++;
*pixdest = (*pixsrc++ * *pixdest) >> 8;
pixdest++;
if (has_alpha)
{
*pixdest++ = *pixsrc++;

View file

@ -29,4 +29,4 @@ GdkPixbuf *eel_create_spotlight_pixbuf (GdkPixbuf *source_pixbuf);
/* return a pixbuf colorized with the color specified by the parameters */
GdkPixbuf* eel_create_colorized_pixbuf (GdkPixbuf *source_pixbuf,
GdkRGBA *color);
GdkPixbuf *dest);

View file

@ -1189,51 +1189,72 @@ static cairo_surface_t *
real_map_surface (NautilusCanvasItem *canvas_item)
{
EelCanvas *canvas;
GdkPixbuf *temp_pixbuf, *old_pixbuf;
GtkStyleContext *style;
GdkRGBA color;
cairo_surface_t *surface;
g_autoptr (GdkPixbuf) temp_pixbuf = NULL;
gint scale_factor;
GdkWindow *window;
temp_pixbuf = canvas_item->details->pixbuf;
canvas = EEL_CANVAS_ITEM (canvas_item)->canvas;
g_object_ref (temp_pixbuf);
temp_pixbuf = g_object_ref (canvas_item->details->pixbuf);
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (canvas));
window = gtk_widget_get_window (GTK_WIDGET (canvas));
if (canvas_item->details->is_prelit ||
canvas_item->details->is_highlighted_for_clipboard)
{
old_pixbuf = temp_pixbuf;
g_autoptr (GdkPixbuf) old_pixbuf = NULL;
old_pixbuf = temp_pixbuf;
temp_pixbuf = eel_create_spotlight_pixbuf (temp_pixbuf);
g_object_unref (old_pixbuf);
}
if (canvas_item->details->is_highlighted_for_selection
|| canvas_item->details->is_highlighted_for_drop)
{
style = gtk_widget_get_style_context (GTK_WIDGET (canvas));
GtkWidget *widget;
GtkStyleContext *style;
gboolean has_focus;
GtkStateFlags state;
gint width;
gint height;
gboolean has_alpha;
cairo_format_t format;
cairo_surface_t *surface;
cairo_t *cr;
g_autoptr (GdkPixbuf) pixbuf = NULL;
g_autoptr (GdkPixbuf) old_pixbuf = NULL;
if (gtk_widget_has_focus (GTK_WIDGET (canvas)))
{
gtk_style_context_get_background_color (style, GTK_STATE_FLAG_SELECTED, &color);
}
else
{
gtk_style_context_get_background_color (style, GTK_STATE_FLAG_ACTIVE, &color);
}
widget = GTK_WIDGET (canvas);
style = gtk_widget_get_style_context (widget);
has_focus = gtk_widget_has_focus (widget);
state = has_focus? GTK_STATE_FLAG_SELECTED : GTK_STATE_FLAG_ACTIVE;
width = gdk_pixbuf_get_width (temp_pixbuf);
height = gdk_pixbuf_get_height (temp_pixbuf);
has_alpha = gdk_pixbuf_get_has_alpha (temp_pixbuf);
format = has_alpha? CAIRO_FORMAT_ARGB32 : CAIRO_FORMAT_RGB24;
surface = cairo_image_surface_create (format, width, height);
cr = cairo_create (surface);
gtk_style_context_save (style);
gtk_style_context_set_state (style, state);
gtk_render_background (style, cr,
0, 0,
width, height);
gtk_style_context_restore (style);
cairo_surface_flush (surface);
pixbuf = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
old_pixbuf = temp_pixbuf;
temp_pixbuf = eel_create_colorized_pixbuf (temp_pixbuf, &color);
g_object_unref (old_pixbuf);
temp_pixbuf = eel_create_colorized_pixbuf (temp_pixbuf, g_steal_pointer (&pixbuf));
cairo_destroy (cr);
cairo_surface_destroy (surface);
}
surface = gdk_cairo_surface_create_from_pixbuf (temp_pixbuf,
gtk_widget_get_scale_factor (GTK_WIDGET (canvas)),
gtk_widget_get_window (GTK_WIDGET (canvas)));
g_object_unref (temp_pixbuf);
return surface;
return gdk_cairo_surface_create_from_pixbuf (temp_pixbuf, scale_factor, window);
}
static cairo_surface_t *