diff --git a/demos/gtk-demo/images.c b/demos/gtk-demo/images.c index c80f5f2f2f..bf0618adc3 100644 --- a/demos/gtk-demo/images.c +++ b/demos/gtk-demo/images.c @@ -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 diff --git a/demos/gtk-demo/main.c b/demos/gtk-demo/main.c index d0cca8c8f0..49f368b653 100644 --- a/demos/gtk-demo/main.c +++ b/demos/gtk-demo/main.c @@ -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; diff --git a/docs/reference/gtk/gtk4-sections.txt b/docs/reference/gtk/gtk4-sections.txt index 186dea70bd..683f3b33e0 100644 --- a/docs/reference/gtk/gtk4-sections.txt +++ b/docs/reference/gtk/gtk4-sections.txt @@ -1486,7 +1486,6 @@ GtkIconViewPrivate GtkImage GtkImage GtkImageType -gtk_image_get_pixbuf gtk_image_get_surface gtk_image_get_animation gtk_image_get_icon_name diff --git a/gtk/a11y/gtkimageaccessible.c b/gtk/a11y/gtkimageaccessible.c index 7c394d0aff..edf20031ba 100644 --- a/gtk/a11y/gtkimageaccessible.c +++ b/gtk/a11y/gtkimageaccessible.c @@ -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; diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c index d0e65f74bf..b94f960ed4 100644 --- a/gtk/gtkimage.c +++ b/gtk/gtkimage.c @@ -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; diff --git a/gtk/gtkimage.h b/gtk/gtkimage.h index 52c5d49c61..79fc19191d 100644 --- a/gtk/gtkimage.h +++ b/gtk/gtkimage.h @@ -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); diff --git a/gtk/gtktoolbutton.c b/gtk/gtktoolbutton.c index c94e1fd226..a3c019e496 100644 --- a/gtk/gtktoolbutton.c +++ b/gtk/gtktoolbutton.c @@ -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; } diff --git a/tests/testimage.c b/tests/testimage.c index aa333740cf..a9be8683d2 100644 --- a/tests/testimage.c +++ b/tests/testimage.c @@ -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,