GtkImage: Drop support for storing pixbufs

This drops the pixbuf property and the pixbuf getters. We keep
gtk_image_new/set_from_pixbuf, but these are small helpers that
immediately convert to a surface, and there is no way to later get
back the pixbuf you passed in.

The from file/resource codepaths are also changed to load a surface
instead of a pixbuf.
This commit is contained in:
Alexander Larsson 2017-10-23 14:47:50 +02:00
parent 7ee2ab32b8
commit 2b194089dd
8 changed files with 83 additions and 103 deletions

View File

@ -54,17 +54,8 @@ progressive_updated_callback (GdkPixbufLoader *loader,
image = GTK_WIDGET (data);
/* We know the pixbuf inside the GtkImage has changed, but the image
* itself doesn't know this; so give it a hint by setting the pixbuf
* again. Queuing a redraw used to be sufficient, but nowadays GtkImage
* uses GtkIconHelper which caches the pixbuf state and will just redraw
* from the cache.
*/
pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (image));
g_object_ref (pixbuf);
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
g_object_unref (pixbuf);
}
static gint

View File

@ -556,7 +556,7 @@ add_data_tab (const gchar *demoname)
resource_name = g_strconcat (resource_dir, "/", resources[i], NULL);
widget = gtk_image_new_from_resource (resource_name);
if (gtk_image_get_pixbuf (GTK_IMAGE (widget)) == NULL &&
if (gtk_image_get_surface (GTK_IMAGE (widget)) == NULL &&
gtk_image_get_animation (GTK_IMAGE (widget)) == NULL)
{
GBytes *bytes;

View File

@ -1486,7 +1486,6 @@ GtkIconViewPrivate
<TITLE>GtkImage</TITLE>
GtkImage
GtkImageType
gtk_image_get_pixbuf
gtk_image_get_surface
gtk_image_get_animation
gtk_image_get_icon_name

View File

@ -270,13 +270,13 @@ gtk_image_accessible_get_image_size (AtkImage *image,
image_type = gtk_image_get_storage_type (gtk_image);
switch (image_type)
{
case GTK_IMAGE_PIXBUF:
case GTK_IMAGE_SURFACE:
{
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
pixbuf = gtk_image_get_pixbuf (gtk_image);
*height = gdk_pixbuf_get_height (pixbuf);
*width = gdk_pixbuf_get_width (pixbuf);
surface = gtk_image_get_surface (gtk_image);
*height = cairo_image_surface_get_height (surface);
*width = cairo_image_surface_get_width (surface);
break;
}
case GTK_IMAGE_ICON_NAME:
@ -298,7 +298,7 @@ gtk_image_accessible_get_image_size (AtkImage *image,
break;
}
case GTK_IMAGE_EMPTY:
case GTK_IMAGE_SURFACE:
case GTK_IMAGE_PIXBUF:
default:
{
*height = -1;

View File

@ -84,8 +84,8 @@ struct _GtkImagePrivate
float baseline_align;
gchar *filename; /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_PIXBUF */
gchar *resource_path; /* Only used with GTK_IMAGE_PIXBUF */
gchar *filename; /* Only used with GTK_IMAGE_ANIMATION, GTK_IMAGE_SURFACE */
gchar *resource_path; /* Only used with GTK_IMAGE_SURFACE */
};
@ -121,7 +121,6 @@ static void gtk_image_get_property (GObject *object,
enum
{
PROP_0,
PROP_PIXBUF,
PROP_SURFACE,
PROP_FILE,
PROP_ICON_SIZE,
@ -146,7 +145,7 @@ gtk_image_class_init (GtkImageClass *class)
GtkWidgetClass *widget_class;
gobject_class = G_OBJECT_CLASS (class);
gobject_class->set_property = gtk_image_set_property;
gobject_class->get_property = gtk_image_get_property;
gobject_class->finalize = gtk_image_finalize;
@ -159,13 +158,6 @@ gtk_image_class_init (GtkImageClass *class)
widget_class->unrealize = gtk_image_unrealize;
widget_class->style_updated = gtk_image_style_updated;
image_props[PROP_PIXBUF] =
g_param_spec_object ("pixbuf",
P_("Pixbuf"),
P_("A GdkPixbuf to display"),
GDK_TYPE_PIXBUF,
GTK_PARAM_READWRITE);
image_props[PROP_SURFACE] =
g_param_spec_boxed ("surface",
P_("Surface"),
@ -330,9 +322,6 @@ gtk_image_set_property (GObject *object,
switch (prop_id)
{
case PROP_PIXBUF:
gtk_image_set_from_pixbuf (image, g_value_get_object (value));
break;
case PROP_SURFACE:
gtk_image_set_from_surface (image, g_value_get_boxed (value));
break;
@ -384,9 +373,6 @@ gtk_image_get_property (GObject *object,
switch (prop_id)
{
case PROP_PIXBUF:
g_value_set_object (value, _gtk_icon_helper_peek_pixbuf (&priv->icon_helper));
break;
case PROP_SURFACE:
g_value_set_boxed (value, _gtk_icon_helper_peek_surface (&priv->icon_helper));
break;
@ -438,7 +424,7 @@ gtk_image_get_property (GObject *object,
*
* If you need to detect failures to load the file, use
* gdk_pixbuf_new_from_file() to load the file yourself, then create
* the #GtkImage from the pixbuf. (Or for animations, use
* the #GtkImage from the surface. (Or for animations, use
* gdk_pixbuf_animation_new_from_file()).
*
* The storage type (gtk_image_get_storage_type()) of the returned
@ -504,7 +490,10 @@ gtk_image_new_from_resource (const gchar *resource_path)
* The #GtkImage does not assume a reference to the
* pixbuf; you still need to unref it if you own references.
* #GtkImage will add its own reference rather than adopting yours.
*
*
* This is a helper for gtk_image_new_from_surface, and you can't
* get back the exact pixbuf once this is called, only a surface.
*
* Note that this function just creates an #GtkImage from the pixbuf. The
* #GtkImage created will not react to state changes. Should you want that,
* you should use gtk_image_new_from_icon_name().
@ -767,17 +756,22 @@ gtk_image_set_from_file (GtkImage *image,
*/
if (gdk_pixbuf_animation_is_static_image (anim))
gtk_image_set_from_pixbuf (image,
gdk_pixbuf_animation_get_static_image (anim));
{
cairo_surface_t *surface = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_get_static_image (anim),
scale_factor, _gtk_widget_get_window (GTK_WIDGET (image)));
gtk_image_set_from_surface (image, surface);
cairo_surface_destroy (surface);
}
else
gtk_image_set_from_animation (image, anim);
_gtk_icon_helper_set_pixbuf_scale (&priv->icon_helper, scale_factor);
{
gtk_image_set_from_animation (image, anim);
_gtk_icon_helper_set_pixbuf_scale (&priv->icon_helper, scale_factor);
}
g_object_unref (anim);
priv->filename = g_strdup (filename);
g_object_thaw_notify (G_OBJECT (image));
}
@ -858,11 +852,17 @@ gtk_image_set_from_resource (GtkImage *image,
}
if (gdk_pixbuf_animation_is_static_image (animation))
gtk_image_set_from_pixbuf (image, gdk_pixbuf_animation_get_static_image (animation));
{
cairo_surface_t *surface = gdk_cairo_surface_create_from_pixbuf (gdk_pixbuf_animation_get_static_image (animation),
scale_factor, _gtk_widget_get_window (GTK_WIDGET (image)));
gtk_image_set_from_surface (image, surface);
cairo_surface_destroy (surface);
}
else
gtk_image_set_from_animation (image, animation);
_gtk_icon_helper_set_pixbuf_scale (&priv->icon_helper, scale_factor);
{
gtk_image_set_from_animation (image, animation);
_gtk_icon_helper_set_pixbuf_scale (&priv->icon_helper, scale_factor);
}
priv->resource_path = g_strdup (resource_path);
@ -880,27 +880,29 @@ gtk_image_set_from_resource (GtkImage *image,
* @pixbuf: (allow-none): a #GdkPixbuf or %NULL
*
* See gtk_image_new_from_pixbuf() for details.
*
* Note: This is a helper for gtk_image_new_from_surface, and you can't
* get back the exact pixbuf once this is called, only a surface.
*
**/
void
gtk_image_set_from_pixbuf (GtkImage *image,
GdkPixbuf *pixbuf)
{
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
cairo_surface_t *surface = NULL;
g_return_if_fail (GTK_IS_IMAGE (image));
g_return_if_fail (pixbuf == NULL ||
GDK_IS_PIXBUF (pixbuf));
g_object_freeze_notify (G_OBJECT (image));
gtk_image_clear (image);
if (pixbuf)
surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, gtk_widget_get_window (GTK_WIDGET (image)));
if (pixbuf != NULL)
_gtk_icon_helper_set_pixbuf (&priv->icon_helper, pixbuf);
gtk_image_set_from_surface (image, surface);
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF]);
g_object_thaw_notify (G_OBJECT (image));
if (surface)
cairo_surface_destroy (surface);
}
/**
@ -1064,29 +1066,6 @@ gtk_image_get_storage_type (GtkImage *image)
return _gtk_icon_helper_get_storage_type (&priv->icon_helper);
}
/**
* gtk_image_get_pixbuf:
* @image: a #GtkImage
*
* Gets the #GdkPixbuf being displayed by the #GtkImage.
* The storage type of the image must be %GTK_IMAGE_EMPTY or
* %GTK_IMAGE_PIXBUF (see gtk_image_get_storage_type()).
* The caller of this function does not own a reference to the
* returned pixbuf.
*
* Returns: (nullable) (transfer none): the displayed pixbuf, or %NULL if
* the image is empty
**/
GdkPixbuf*
gtk_image_get_pixbuf (GtkImage *image)
{
GtkImagePrivate *priv = gtk_image_get_instance_private (image);
g_return_val_if_fail (GTK_IS_IMAGE (image), NULL);
return _gtk_icon_helper_peek_pixbuf (&priv->icon_helper);
}
/**
* gtk_image_get_surface:
* @image: a #GtkImage
@ -1387,9 +1366,6 @@ gtk_image_notify_for_storage_type (GtkImage *image,
{
switch (storage_type)
{
case GTK_IMAGE_PIXBUF:
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF]);
break;
case GTK_IMAGE_ANIMATION:
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF_ANIMATION]);
break;
@ -1402,6 +1378,9 @@ gtk_image_notify_for_storage_type (GtkImage *image,
case GTK_IMAGE_SURFACE:
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_SURFACE]);
break;
case GTK_IMAGE_PIXBUF:
g_warning ("pixbuf not supported");
break;
case GTK_IMAGE_EMPTY:
default:
break;

View File

@ -67,6 +67,10 @@ typedef struct _GtkImageClass GtkImageClass;
* call gtk_image_get_pixbuf(). For empty images, you can request any
* storage type (call any of the "get" functions), but they will all
* return %NULL values.
*
* Note: GTK_IMAGE_PIXBUF is not not supported as storage by GtkImage. Any
* pixbuf set on the GtkImage will be converted to a surface and can only
* be read back as a GTK_IMAGE_SURFACE.
*/
typedef enum
{
@ -154,9 +158,6 @@ void gtk_image_set_pixel_size (GtkImage *image,
GDK_AVAILABLE_IN_ALL
GtkImageType gtk_image_get_storage_type (GtkImage *image);
GDK_AVAILABLE_IN_ALL
GdkPixbuf* gtk_image_get_pixbuf (GtkImage *image);
GDK_AVAILABLE_IN_3_94
cairo_surface_t *gtk_image_get_surface (GtkImage *image);

View File

@ -723,21 +723,32 @@ clone_image_menu_size (GtkImage *image)
gtk_image_get_gicon (image, &icon, NULL);
return gtk_image_new_from_gicon (icon, GTK_ICON_SIZE_MENU);
}
else if (storage_type == GTK_IMAGE_PIXBUF)
else if (storage_type == GTK_IMAGE_SURFACE)
{
gint width, height;
if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height))
{
GdkPixbuf *src_pixbuf, *dest_pixbuf;
GtkWidget *cloned_image;
{
cairo_surface_t *src_surface, *dest_surface;
GtkWidget *cloned_image;
gint scale = gtk_widget_get_scale_factor (GTK_WIDGET (image));
cairo_t *cr;
src_pixbuf = gtk_image_get_pixbuf (image);
dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
GDK_INTERP_BILINEAR);
src_surface = gtk_image_get_surface (image);
dest_surface =
gdk_window_create_similar_image_surface (gtk_widget_get_window (GTK_WIDGET(image)),
CAIRO_FORMAT_ARGB32,
width * scale, height * scale, scale);
cr = cairo_create (dest_surface);
cairo_set_source_surface (cr, src_surface, 0, 0);
cairo_scale (cr,
width / cairo_image_surface_get_width (src_surface),
height / cairo_image_surface_get_height (src_surface));
cairo_paint (cr);
cairo_destroy (cr);
cloned_image = gtk_image_new_from_pixbuf (dest_pixbuf);
g_object_unref (dest_pixbuf);
cloned_image = gtk_image_new_from_surface (dest_surface);
cairo_surface_destroy (dest_surface);
return cloned_image;
}

View File

@ -40,9 +40,9 @@ drag_data_get (GtkWidget *widget,
{
GtkWidget *image = GTK_WIDGET (data);
GdkPixbuf *pixbuf = gtk_image_get_pixbuf (GTK_IMAGE (image));
cairo_surface_t *surface = gtk_image_get_surface (GTK_IMAGE (image));
gtk_selection_data_set_pixbuf (selection_data, pixbuf);
gtk_selection_data_set_surface (selection_data, surface);
}
static void
@ -56,15 +56,14 @@ drag_data_received (GtkWidget *widget,
gpointer data)
{
GtkWidget *image = GTK_WIDGET (data);
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
if (gtk_selection_data_get_length (selection_data) < 0)
return;
pixbuf = gtk_selection_data_get_pixbuf (selection_data);
surface = gtk_selection_data_get_surface (selection_data);
gtk_image_set_from_pixbuf (GTK_IMAGE (image), pixbuf);
gtk_image_set_from_surface (GTK_IMAGE (image), surface);
}
static gboolean
@ -81,7 +80,7 @@ main (int argc, char **argv)
GtkWidget *window, *grid;
GtkWidget *label, *image;
GtkIconTheme *theme;
GdkPixbuf *pixbuf;
cairo_surface_t *surface;
gchar *icon_name = "help-browser";
gchar *anim_filename = NULL;
GIcon *icon;
@ -111,8 +110,8 @@ main (int argc, char **argv)
gtk_grid_attach (GTK_GRID (grid), label, 0, 1, 1, 1);
theme = gtk_icon_theme_get_default ();
pixbuf = gtk_icon_theme_load_icon (theme, icon_name, 48, 0, NULL);
image = gtk_image_new_from_pixbuf (pixbuf);
surface = gtk_icon_theme_load_surface (theme, icon_name, 48, gtk_widget_get_scale_factor (window), gtk_widget_get_window (window), 0, NULL);
image = gtk_image_new_from_surface (surface);
gtk_grid_attach (GTK_GRID (grid), image, 2, 1, 1, 1);
gtk_drag_source_set (image, GDK_BUTTON1_MASK,