Replace last users of gtk_icon_paintable_download_texture ()

These now render the paintable to a cairo surface and convert that
to a texture. This is sort of a hack, but its only used in two
special cases internally and in two hacky test apps.
This commit is contained in:
Alexander Larsson 2020-02-06 17:10:13 +01:00
parent 8282698201
commit 6317fd3529
5 changed files with 172 additions and 80 deletions

View File

@ -55,7 +55,8 @@
#include "gtkgestureclick.h"
#include "gtkmodelbuttonprivate.h"
#include "gtkpopover.h"
#include "gtksnapshot.h"
#include "gdktextureprivate.h"
#include <glib/gprintf.h>
/**
@ -1137,6 +1138,36 @@ diff_sorted_arrays (GArray *array1,
}
}
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
texture = gdk_texture_new_for_surface (surface);
cairo_surface_destroy (surface);
return texture;
}
static void
add_pid_to_process_list_store (GtkMountOperation *mount_operation,
@ -1180,7 +1211,7 @@ add_pid_to_process_list_store (GtkMountOperation *mount_operation,
24, 1,
gtk_widget_get_direction (GTK_WIDGET (mount_operation->priv->dialog)),
0);
texture = gtk_icon_paintable_download_texture (icon);
texture = render_paintable_to_texture (GDK_PAINTABLE (icon));
g_object_unref (icon);
}

View File

@ -3999,6 +3999,37 @@ icon_size_compare (GdkTexture *a,
return area_a - area_b;
}
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
texture = gdk_texture_new_for_surface (surface);
cairo_surface_destroy (surface);
return texture;
}
static GList *
icon_list_from_theme (GtkWindow *window,
const gchar *name)
@ -4009,6 +4040,7 @@ icon_list_from_theme (GtkWindow *window,
GtkCssValue *value;
GtkIconTheme *icon_theme;
GtkIconPaintable *info;
GdkTexture *texture;
gint *sizes;
gint i;
@ -4036,14 +4068,10 @@ icon_list_from_theme (GtkWindow *window,
sizes[i], priv->scale,
gtk_widget_get_direction (GTK_WIDGET (window)),
0);
if (info)
{
GdkTexture *texture = gtk_icon_paintable_download_texture (info);
if (texture)
list = g_list_insert_sorted (list, texture, (GCompareFunc) icon_size_compare);
g_object_unref (info);
}
texture = render_paintable_to_texture (GDK_PAINTABLE (info));
list = g_list_insert_sorted (list, texture, (GCompareFunc) icon_size_compare);
g_object_unref (info);
}
g_free (sizes);

View File

@ -17,6 +17,48 @@
#include <gtk/gtk.h>
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
GBytes *bytes;
width = gdk_paintable_get_intrinsic_width (paintable);
height = gdk_paintable_get_intrinsic_height (paintable);
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
cairo_image_surface_get_height (surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
bytes,
cairo_image_surface_get_stride (surface));
g_bytes_unref (bytes);
cairo_surface_destroy (surface);
return texture;
}
static void
clipboard_changed_cb (GdkClipboard *clipboard,
GtkWidget *stack)
@ -292,7 +334,7 @@ get_button_list (GdkClipboard *clipboard,
48, 1,
gtk_widget_get_direction (box),
0);
texture = gtk_icon_paintable_download_texture (icon);
texture = render_paintable_to_texture (GDK_PAINTABLE (icon));
g_value_take_object (&value, gdk_pixbuf_get_from_texture (texture));
g_object_unref (texture);
g_object_unref (icon);

View File

@ -6,6 +6,53 @@
#include <io.h>
#endif
static GdkTexture *
render_paintable_to_texture (GdkPaintable *paintable)
{
GtkSnapshot *snapshot;
GskRenderNode *node;
int width, height;
cairo_surface_t *surface;
cairo_t *cr;
GdkTexture *texture;
GBytes *bytes;
width = gdk_paintable_get_intrinsic_width (paintable);
if (width == 0)
width = 32;
height = gdk_paintable_get_intrinsic_height (paintable);
if (height == 0)
height = 32;
surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, width, height);
snapshot = gtk_snapshot_new ();
gdk_paintable_snapshot (paintable, snapshot, width, height);
node = gtk_snapshot_free_to_node (snapshot);
cr = cairo_create (surface);
gsk_render_node_draw (node, cr);
cairo_destroy (cr);
gsk_render_node_unref (node);
bytes = g_bytes_new_with_free_func (cairo_image_surface_get_data (surface),
cairo_image_surface_get_height (surface)
* cairo_image_surface_get_stride (surface),
(GDestroyNotify) cairo_surface_destroy,
cairo_surface_reference (surface));
texture = gdk_memory_texture_new (cairo_image_surface_get_width (surface),
cairo_image_surface_get_height (surface),
GDK_MEMORY_DEFAULT,
bytes,
cairo_image_surface_get_stride (surface));
g_bytes_unref (bytes);
cairo_surface_destroy (surface);
return texture;
}
static GdkTexture *
get_image_texture (GtkImage *image,
int *out_size)
@ -13,7 +60,7 @@ get_image_texture (GtkImage *image,
GtkIconTheme *icon_theme;
const char *icon_name;
int width = 48;
GdkPaintable *paintable;
GdkPaintable *paintable = NULL;
GdkTexture *texture = NULL;
GtkIconPaintable *icon;
@ -21,29 +68,28 @@ get_image_texture (GtkImage *image,
{
case GTK_IMAGE_PAINTABLE:
paintable = gtk_image_get_paintable (image);
if (GDK_IS_TEXTURE (paintable))
{
*out_size = gdk_paintable_get_intrinsic_width (paintable);
texture = g_object_ref (GDK_TEXTURE (paintable));
}
break;
case GTK_IMAGE_ICON_NAME:
icon_name = gtk_image_get_icon_name (image);
icon_theme = gtk_icon_theme_get_for_display (gtk_widget_get_display (GTK_WIDGET (image)));
*out_size = width;
icon = gtk_icon_theme_lookup_icon (icon_theme,
icon_name,
NULL,
width, 1,
gtk_widget_get_direction (GTK_WIDGET (image)),
0);
if (icon)
texture = gtk_icon_paintable_download_texture (icon);
g_object_unref (icon);
paintable = GDK_PAINTABLE (icon);
break;
default:
g_warning ("Image storage type %d not handled",
gtk_image_get_storage_type (image));
}
if (paintable)
texture = render_paintable_to_texture (paintable);
g_object_unref (paintable);
return texture;
}
@ -238,11 +284,14 @@ update_source_icon (GtkDragSource *source,
int hot_x, hot_y;
int size = 48;
if (widget == NULL)
return;
icon = gtk_icon_theme_lookup_icon (gtk_icon_theme_get_for_display (gtk_widget_get_display (widget)),
icon_name,
NULL,
size, 1,
gtk_widget_get_direction (widget),
gtk_widget_get_direction (widget) ,
0);
switch (hotspot)
{

View File

@ -93,14 +93,7 @@ assert_icon_lookup_size (const char *icon_name,
g_assert (gtk_icon_paintable_get_filename (info) == NULL);
}
if (pixbuf_size > 0)
{
GdkTexture *texture;
texture = gtk_icon_paintable_download_texture (info);
g_assert_cmpint (gdk_texture_get_width (texture), ==, pixbuf_size);
g_object_unref (texture);
}
g_assert_cmpint (gdk_paintable_get_intrinsic_width (GDK_PAINTABLE (info)), ==, size);
g_object_unref (info);
}
@ -711,56 +704,6 @@ test_inherit (void)
"/icons2/scalable/one-two-symbolic-rtl.svg");
}
static void
test_nonsquare_symbolic (void)
{
gint width, height;
GtkIconTheme *icon_theme;
GtkIconPaintable *info;
GFile *file;
GIcon *icon;
GError *error = NULL;
GdkTexture *texture;
gchar *path = g_build_filename (g_test_get_dir (G_TEST_DIST),
"icons",
"scalable",
"nonsquare-symbolic.svg",
NULL);
/* load the original image for reference */
GdkPixbuf *pixbuf = gdk_pixbuf_new_from_file (path, &error);
g_assert_no_error (error);
g_assert_nonnull (pixbuf);
width = gdk_pixbuf_get_width (pixbuf);
height = gdk_pixbuf_get_height (pixbuf);
g_assert_cmpint (width, !=, height);
/* now load it through GtkIconTheme */
icon_theme = gtk_icon_theme_get_for_display (gdk_display_get_default ());
file = g_file_new_for_path (path);
icon = g_file_icon_new (file);
info = gtk_icon_theme_lookup_by_gicon (icon_theme, icon,
height, 1, GTK_TEXT_DIR_NONE, 0);
g_assert_nonnull (info);
g_object_unref (pixbuf);
texture = gtk_icon_paintable_download_texture (info);
/* we are loaded successfully */
g_assert_nonnull (texture);
/* the original dimensions have been preserved */
g_assert_cmpint (gdk_texture_get_width (texture), ==, width);
g_assert_cmpint (gdk_texture_get_height (texture), ==, height);
g_free (path);
g_object_unref (texture);
g_object_unref (file);
g_object_unref (icon);
g_object_unref (info);
}
int
main (int argc, char *argv[])
{
@ -777,7 +720,6 @@ main (int argc, char *argv[])
g_test_add_func ("/icontheme/size", test_size);
g_test_add_func ("/icontheme/list", test_list);
g_test_add_func ("/icontheme/inherit", test_inherit);
g_test_add_func ("/icontheme/nonsquare-symbolic", test_nonsquare_symbolic);
return g_test_run();
}