[gtk: 3/40] GtkIconInfo: Implement paintable



commit b96ab7453b0cad6705ca0720ffbd692b1afa9b51
Author: Alexander Larsson <alexl redhat com>
Date:   Mon Jan 27 13:59:34 2020 +0100

    GtkIconInfo: Implement paintable
    
    This makes GtkIconInfo directly implement paintable by loading
    the icon as needed. This is done in a blocking fashion for now, but
    could be made more async in the future.
    
    It also means we can't return errors to the called, but I doubt
    anyone actually does anything useful with them other than showing
    nothing (which we already do).
    
    This also changes a fringe behaviour for unthemed icons. They used to
    be never scaled down, but that means we can't tell without i/o the
    size of the paintable. Since this is the only case we can't know the
    size i took an executive decision and removed that behaviour. I don't
    think picking some arbitrary much larger than requested size is ever
    right, nor do i think using GtkIconTheme with unthemed icons is overly
    useful. If you want to display some random non-iconish image, use
    GtkImage instead.

 gtk/gtkicontheme.c | 137 +++++++++++++++++++++++++++++++++++++++++++++++++++--
 1 file changed, 132 insertions(+), 5 deletions(-)
---
diff --git a/gtk/gtkicontheme.c b/gtk/gtkicontheme.c
index 12d6eeaaaf..c8c4cbf40f 100644
--- a/gtk/gtkicontheme.c
+++ b/gtk/gtkicontheme.c
@@ -48,6 +48,7 @@
 #include "gtksettingsprivate.h"
 #include "gtkstylecontextprivate.h"
 #include "gtkprivate.h"
+#include "gtksnapshot.h"
 #include "gdkpixbufutilsprivate.h"
 #include "gdk/gdktextureprivate.h"
 #include "gdk/gdkprofilerprivate.h"
@@ -293,6 +294,7 @@ struct _GtkIconInfo
    */
   gint desired_size;
   gint desired_scale;
+  gint rendered_size;
   gdouble unscaled_scale;
   guint forced_size     : 1;
   guint is_svg          : 1;
@@ -386,6 +388,7 @@ static IconSuffix   theme_dir_get_icon_suffix (IconThemeDir     *dir,
 static GtkIconInfo *icon_info_new             (IconThemeDirType  type,
                                                gint              dir_size,
                                                gint              dir_scale);
+static void         icon_info_compute_rendered_size (GtkIconInfo *icon_info);
 static IconSuffix   suffix_from_name          (const gchar      *name);
 static gboolean     icon_info_ensure_scale_and_texture__locked (GtkIconInfo* icon_info);
 static void         unset_display             (GtkIconTheme     *self);
@@ -1883,6 +1886,8 @@ real_choose_icon (GtkIconTheme       *self,
             }
         }
 
+      icon_info_compute_rendered_size (icon_info);
+
       icon_info->key.icon_names = g_strdupv ((char **)icon_names);
       icon_info->key.size = size;
       icon_info->key.scale = scale;
@@ -3317,7 +3322,12 @@ theme_subdir_load (GtkIconTheme *self,
  * GtkIconInfo
  */
 
-G_DEFINE_TYPE (GtkIconInfo, gtk_icon_info, G_TYPE_OBJECT)
+static void icon_info_paintable_init (GdkPaintableInterface *iface);
+
+
+G_DEFINE_TYPE_WITH_CODE (GtkIconInfo, gtk_icon_info, G_TYPE_OBJECT,
+                         G_IMPLEMENT_INTERFACE (GDK_TYPE_PAINTABLE,
+                                                icon_info_paintable_init))
 
 static void
 gtk_icon_info_init (GtkIconInfo *icon_info)
@@ -3341,10 +3351,50 @@ icon_info_new (IconThemeDirType type,
   icon_info->unscaled_scale = 1.0;
   icon_info->is_svg = FALSE;
   icon_info->is_resource = FALSE;
+  icon_info->rendered_size = -1;
 
   return icon_info;
 }
 
+static void
+icon_info_compute_rendered_size (GtkIconInfo *icon_info)
+{
+  int rendered_size;
+
+  if (icon_info->forced_size ||
+      icon_info->dir_type == ICON_THEME_DIR_UNTHEMED)
+    {
+      rendered_size = icon_info->desired_size;
+    }
+  else if (icon_info->dir_type == ICON_THEME_DIR_FIXED ||
+           icon_info->dir_type == ICON_THEME_DIR_THRESHOLD)
+    {
+      rendered_size = icon_info->dir_size * icon_info->dir_scale * icon_info->unscaled_scale /  
icon_info->desired_scale;
+    }
+  else /* Scalable */
+    {
+      gdouble dir_scale = icon_info->dir_scale;
+      gint scaled_desired_size;
+
+      scaled_desired_size = icon_info->desired_size * icon_info->desired_scale;
+
+      /* See icon_info_ensure_scale_and_texture() comment for why we do this */
+      if (icon_info->is_svg)
+        dir_scale = icon_info->desired_scale;
+
+      if (scaled_desired_size < icon_info->min_size * dir_scale)
+        rendered_size = icon_info->min_size * dir_scale;
+      else if (scaled_desired_size > icon_info->max_size * dir_scale)
+        rendered_size = icon_info->max_size * dir_scale;
+      else
+        rendered_size = scaled_desired_size;
+
+      rendered_size /= icon_info->desired_scale;
+    }
+
+  icon_info->rendered_size = rendered_size;
+}
+
 /* This only copies whatever is needed to load the pixbuf,
  * so that we can do a load in a thread without affecting
  * the original IconInfo from the thread.
@@ -3369,6 +3419,7 @@ icon_info_dup (GtkIconInfo *icon_info)
   dup->desired_size = icon_info->desired_size;
   dup->desired_scale = icon_info->desired_scale;
   dup->forced_size = icon_info->forced_size;
+  dup->rendered_size = icon_info->rendered_size;
   dup->is_resource = icon_info->is_resource;
   dup->min_size = icon_info->min_size;
   dup->max_size = icon_info->max_size;
@@ -3756,10 +3807,6 @@ icon_info_ensure_scale_and_texture__locked (GtkIconInfo *icon_info)
         icon_info->scale = (gdouble)scaled_desired_size / (gdouble)image_size;
       else
         icon_info->scale = 1.0;
-
-      if (icon_info->dir_type == ICON_THEME_DIR_UNTHEMED && 
-          !icon_info->forced_size)
-        icon_info->scale = MIN (icon_info->scale, 1.0);
     }
 
   if (icon_info->is_svg ||
@@ -3785,6 +3832,76 @@ icon_info_ensure_scale_and_texture__locked (GtkIconInfo *icon_info)
   return TRUE;
 }
 
+
+static void
+icon_info_paintable_snapshot (GdkPaintable *paintable,
+                              GdkSnapshot  *snapshot,
+                              double        width,
+                              double        height)
+{
+  GtkIconInfo *icon_info = GTK_ICON_INFO (paintable);
+  GdkTexture *texture = NULL;
+
+  g_mutex_lock (&icon_info->cache_lock);
+
+  if (!icon_info->texture)
+    icon_info_ensure_scale_and_texture__locked (icon_info);
+
+  if (icon_info->texture)
+    texture = g_object_ref (icon_info->texture);
+
+  g_mutex_unlock (&icon_info->cache_lock);
+
+  if (texture)
+    {
+      if (icon_info->desired_scale != 1)
+        {
+          gtk_snapshot_save (snapshot);
+          gtk_snapshot_scale (snapshot, 1.0 / icon_info->desired_scale, 1.0 / icon_info->desired_scale);
+        }
+
+      gtk_snapshot_append_texture (snapshot, texture,
+                                   &GRAPHENE_RECT_INIT (0, 0, width * icon_info->desired_scale, height * 
icon_info->desired_scale));
+
+      if (icon_info->desired_scale != 1)
+        gtk_snapshot_restore (snapshot);
+
+      g_object_unref (texture);
+    }
+}
+
+static GdkPaintableFlags
+icon_info_paintable_get_flags (GdkPaintable *paintable)
+{
+  return GDK_PAINTABLE_STATIC_SIZE | GDK_PAINTABLE_STATIC_CONTENTS;
+}
+
+static int
+icon_info_paintable_get_intrinsic_width (GdkPaintable *paintable)
+{
+  GtkIconInfo *icon_info = GTK_ICON_INFO (paintable);
+
+  return icon_info->rendered_size;
+}
+
+static int
+icon_info_paintable_get_intrinsic_height (GdkPaintable *paintable)
+{
+  GtkIconInfo *icon_info = GTK_ICON_INFO (paintable);
+
+  return icon_info->rendered_size;
+}
+
+static void
+icon_info_paintable_init (GdkPaintableInterface *iface)
+{
+  iface->snapshot = icon_info_paintable_snapshot;
+  iface->get_flags = icon_info_paintable_get_flags;
+  iface->get_intrinsic_width = icon_info_paintable_get_intrinsic_width;
+  iface->get_intrinsic_height = icon_info_paintable_get_intrinsic_height;
+}
+
+
 /**
  * gtk_icon_info_load_icon:
  * @self: a #GtkIconInfo from gtk_icon_theme_lookup_icon()
@@ -4684,6 +4801,8 @@ gtk_icon_info_new_for_file (GFile *file,
  info->desired_scale = scale;
  info->forced_size = FALSE;
 
+ info->rendered_size = size;
+
  return info;
 }
 
@@ -4692,10 +4811,18 @@ gtk_icon_info_new_for_pixbuf (GtkIconTheme *icon_theme,
                               GdkPixbuf    *pixbuf)
 {
   GtkIconInfo *info;
+  gint width, height, max;
+
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+  max = MAX (width, height);
 
   info = icon_info_new (ICON_THEME_DIR_UNTHEMED, 0, 1);
   info->texture = gdk_texture_new_for_pixbuf (pixbuf);
+  info->desired_size = max;
+  info->desired_scale = 1.0;
   info->scale = 1.0;
+  info->rendered_size = max;
 
   return info;
 }


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