[gtk+] GtkImage: Drop support for storing pixbufs



commit 2b194089dd525b74c532fdd95c0ab654ac88d295
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Oct 23 14:47:50 2017 +0200

    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.

 demos/gtk-demo/images.c              |   11 +---
 demos/gtk-demo/main.c                |    2 +-
 docs/reference/gtk/gtk4-sections.txt |    1 -
 gtk/a11y/gtkimageaccessible.c        |   12 ++--
 gtk/gtkimage.c                       |  105 ++++++++++++++--------------------
 gtk/gtkimage.h                       |    7 +-
 gtk/gtktoolbutton.c                  |   35 +++++++----
 tests/testimage.c                    |   17 +++---
 8 files changed, 85 insertions(+), 105 deletions(-)
---
diff --git a/demos/gtk-demo/images.c b/demos/gtk-demo/images.c
index c80f5f2..bf0618a 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 d0cca8c..49f368b 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 186dea7..683f3b3 100644
--- a/docs/reference/gtk/gtk4-sections.txt
+++ b/docs/reference/gtk/gtk4-sections.txt
@@ -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
diff --git a/gtk/a11y/gtkimageaccessible.c b/gtk/a11y/gtkimageaccessible.c
index 7c394d0..edf2003 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 d0e65f7..b94f960 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 != NULL)
-    _gtk_icon_helper_set_pixbuf (&priv->icon_helper, pixbuf);
+  if (pixbuf)
+    surface = gdk_cairo_surface_create_from_pixbuf (pixbuf, 1, gtk_widget_get_window (GTK_WIDGET (image)));
 
-  g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_PIXBUF]);
+  gtk_image_set_from_surface (image, surface);
 
-  g_object_thaw_notify (G_OBJECT (image));
+  if (surface)
+    cairo_surface_destroy (surface);
 }
 
 /**
@@ -1065,29 +1067,6 @@ gtk_image_get_storage_type (GtkImage *image)
 }
 
 /**
- * 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 52c5d49..79fc191 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 c94e1fd..a3c019e 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;
 
-         src_pixbuf = gtk_image_get_pixbuf (image);
-         dest_pixbuf = gdk_pixbuf_scale_simple (src_pixbuf, width, height,
-                                                GDK_INTERP_BILINEAR);
-
-         cloned_image = gtk_image_new_from_pixbuf (dest_pixbuf);
-         g_object_unref (dest_pixbuf);
+      if (gtk_icon_size_lookup (GTK_ICON_SIZE_MENU, &width, &height))
+        {
+          cairo_surface_t *src_surface, *dest_surface;
+          GtkWidget *cloned_image;
+          gint scale = gtk_widget_get_scale_factor (GTK_WIDGET (image));
+          cairo_t *cr;
+
+          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_surface (dest_surface);
+          cairo_surface_destroy (dest_surface);
 
          return cloned_image;
        }
diff --git a/tests/testimage.c b/tests/testimage.c
index aa33374..a9be868 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, 


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]