[nautilus/wip/antoniof/hidpi-and-icons-cleanup: 4/11] file: Support HiDPI icons




commit 503ef03509169bcb15aa748a06451daabce03662
Author: António Fernandes <antoniof gnome org>
Date:   Sun Aug 7 16:59:51 2022 +0100

    file: Support HiDPI icons
    
    This brings back a feature originally introduced by commit 0d4555d76f86ba2d49f48836b7eea11f1adfb2fd
    
    Back then, it used gdk_cairo_surface_create_from_pixbuf() to apply the
    scaling factor, but in GTK 4 we can no longer consume cairo surfaces
    directly. Instead, we are to use paintables.
    
    For themed icons we already use GtkIconPaintable, which just works.
    
    For thumbnails, which we get in the form of GdkPixbuf, we need to
    create a paintable encapsulating a render node which scales the
    pixbuf into the final logical area.
    
    We've also been scaling thumbnails down in advance using GdkPixbuf API,
    and keeping a cache of scaled thumbnails.
    
    But nowadays we can push that scaling job into the render nodes,
    taking advantage of GPU. This is a lot simpler.
    
    Also port the film holds effect to snapshots, for necessity.

 src/nautilus-directory-async.c |  5 ---
 src/nautilus-file-private.h    |  3 --
 src/nautilus-file.c            | 93 ++++++++++++------------------------------
 src/nautilus-grid-cell.c       |  9 +++-
 src/nautilus-icon-info.c       | 31 +++++++-------
 src/nautilus-icon-info.h       |  2 +-
 src/nautilus-name-cell.c       |  9 +++-
 src/nautilus-ui-utilities.c    | 46 +++++++++++----------
 src/nautilus-ui-utilities.h    |  4 +-
 9 files changed, 85 insertions(+), 117 deletions(-)
---
diff --git a/src/nautilus-directory-async.c b/src/nautilus-directory-async.c
index 4899ea7b6..3e7f421e6 100644
--- a/src/nautilus-directory-async.c
+++ b/src/nautilus-directory-async.c
@@ -3608,11 +3608,6 @@ thumbnail_done (NautilusDirectory *directory,
         g_object_unref (file->details->thumbnail);
         file->details->thumbnail = NULL;
     }
-    if (file->details->scaled_thumbnail)
-    {
-        g_object_unref (file->details->scaled_thumbnail);
-        file->details->scaled_thumbnail = NULL;
-    }
 
     if (pixbuf)
     {
diff --git a/src/nautilus-file-private.h b/src/nautilus-file-private.h
index 831ed8d44..e575edb62 100644
--- a/src/nautilus-file-private.h
+++ b/src/nautilus-file-private.h
@@ -91,9 +91,6 @@ struct NautilusFileDetails
        GdkPixbuf *thumbnail;
        time_t thumbnail_mtime;
 
-       GdkPixbuf *scaled_thumbnail;
-       double thumbnail_scale;
-
        GList *mime_list; /* If this is a directory, the list of MIME types in it. */
 
        /* Info you might get from a link (.desktop, .directory or nautilus link) */
diff --git a/src/nautilus-file.c b/src/nautilus-file.c
index b60d65d9b..24e24a5bd 100644
--- a/src/nautilus-file.c
+++ b/src/nautilus-file.c
@@ -912,10 +912,6 @@ finalize (GObject *object)
     {
         g_object_unref (file->details->thumbnail);
     }
-    if (file->details->scaled_thumbnail)
-    {
-        g_object_unref (file->details->scaled_thumbnail);
-    }
 
     if (file->details->mount)
     {
@@ -5146,69 +5142,42 @@ nautilus_file_get_thumbnail_icon (NautilusFile          *file,
                                   int                    scale,
                                   NautilusFileIconFlags  flags)
 {
-    int modified_size;
-    GdkPixbuf *pixbuf;
-    int w, h, s;
-    double thumb_scale;
-    GIcon *gicon;
+    g_autoptr (GdkPaintable) paintable = NULL;
     NautilusIconInfo *icon;
 
     icon = NULL;
-    gicon = NULL;
-    pixbuf = NULL;
 
+<<<<<<< HEAD
     modified_size = size * scale;
-
-    if (file->details->thumbnail)
+=======
+    if (file->details->thumbnail != NULL)
     {
-        w = gdk_pixbuf_get_width (file->details->thumbnail);
-        h = gdk_pixbuf_get_height (file->details->thumbnail);
+        GdkPixbuf *pixbuf = file->details->thumbnail;
+        double width = gdk_pixbuf_get_width (pixbuf) / scale;
+        double height = gdk_pixbuf_get_height (pixbuf) / scale;
+        g_autoptr (GdkTexture) texture = gdk_texture_new_for_pixbuf (pixbuf);
+        g_autoptr (GtkSnapshot) snapshot = gtk_snapshot_new ();
+>>>>>>> 0b7293ad3 (file: Support HiDPI icons)
 
-        s = MAX (w, h);
-        /* Don't scale up small thumbnails in the standard view */
-        if (s <= NAUTILUS_GRID_ICON_SIZE_MEDIUM)
-        {
-            thumb_scale = (double) size / NAUTILUS_GRID_ICON_SIZE_SMALL;
-        }
-        else
+        if (MAX (width, height) > size)
         {
-            thumb_scale = (double) modified_size / s;
-        }
+            float scale_down_factor = MAX (width, height) / size;
 
-        /* Make sure that icons don't get smaller than NAUTILUS_LIST_ICON_SIZE_SMALL */
-        if (s * thumb_scale <= NAUTILUS_LIST_ICON_SIZE_SMALL)
-        {
-            thumb_scale = (double) NAUTILUS_LIST_ICON_SIZE_SMALL / s;
+            width = width / scale_down_factor;
+            height = height / scale_down_factor;
         }
 
-        if (file->details->thumbnail_scale == thumb_scale &&
-            file->details->scaled_thumbnail != NULL)
-        {
-            pixbuf = file->details->scaled_thumbnail;
-        }
-        else
-        {
-            pixbuf = gdk_pixbuf_scale_simple (file->details->thumbnail,
-                                              MAX (w * thumb_scale, 1),
-                                              MAX (h * thumb_scale, 1),
-                                              GDK_INTERP_BILINEAR);
-
-            /* We don't want frames around small icons */
-            if (!gdk_pixbuf_get_has_alpha (file->details->thumbnail) || s >= 128 * scale)
-            {
-                if (nautilus_is_video_file (file))
-                {
-                    nautilus_ui_frame_video (&pixbuf);
-                }
-            }
+        gdk_paintable_snapshot (GDK_PAINTABLE (texture),
+                                GDK_SNAPSHOT (snapshot),
+                                width, height);
 
-            g_clear_object (&file->details->scaled_thumbnail);
-            file->details->scaled_thumbnail = pixbuf;
-            file->details->thumbnail_scale = thumb_scale;
+        if (size >= NAUTILUS_GRID_ICON_SIZE_SMALL &&
+            nautilus_is_video_file (file))
+        {
+            nautilus_ui_frame_video (snapshot, width, height);
         }
 
-        DEBUG ("Returning thumbnailed image, at size %d %d",
-               (int) (w * thumb_scale), (int) (h * thumb_scale));
+        paintable = gtk_snapshot_to_paintable (snapshot, NULL);
     }
     else if (file->details->thumbnail_path == NULL &&
              file->details->can_read &&
@@ -5219,27 +5188,19 @@ nautilus_file_get_thumbnail_icon (NautilusFile          *file,
         nautilus_create_thumbnail (file);
     }
 
-    if (pixbuf != NULL)
+    if (paintable != NULL)
     {
-        gicon = G_ICON (g_object_ref (pixbuf));
+        icon = nautilus_icon_info_new_for_paintable (paintable, scale);
     }
     else if (file->details->is_thumbnailing)
     {
-        gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
-    }
+        g_autoptr (GIcon) gicon = NULL;
 
-    if (gicon != NULL)
-    {
-        if (g_icon_equal (gicon, G_ICON (pixbuf)))
-        {
-            icon = nautilus_icon_info_new_for_pixbuf (pixbuf, scale);
-        }
-        else
+        gicon = g_themed_icon_new (ICON_NAME_THUMBNAIL_LOADING);
+        if (gicon != NULL)
         {
             icon = nautilus_icon_info_lookup (gicon, size, scale);
         }
-
-        g_object_unref (gicon);
     }
 
     return icon;
diff --git a/src/nautilus-grid-cell.c b/src/nautilus-grid-cell.c
index 63d9dc576..6599408cc 100644
--- a/src/nautilus-grid-cell.c
+++ b/src/nautilus-grid-cell.c
@@ -34,15 +34,22 @@ update_icon (NautilusGridCell *self)
     GtkStyleContext *style_context;
     NautilusFile *file;
     guint icon_size;
+    gint scale_factor;
     g_autofree gchar *thumbnail_path = NULL;
 
     item = nautilus_view_cell_get_item (NAUTILUS_VIEW_CELL (self));
     g_return_if_fail (item != NULL);
     file = nautilus_view_item_get_file (item);
     icon_size = nautilus_view_item_get_icon_size (item);
+<<<<<<< HEAD
     flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS;
+=======
+    scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self));
+    flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS |
+            NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE;
+>>>>>>> 0b7293ad3 (file: Support HiDPI icons)
 
-    icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, 1, flags);
+    icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, scale_factor, flags);
     gtk_picture_set_paintable (GTK_PICTURE (self->icon), icon_paintable);
 
     /* Set the same height and width for all icons regardless of aspect ratio.
diff --git a/src/nautilus-icon-info.c b/src/nautilus-icon-info.c
index 0831ae168..b5754518c 100644
--- a/src/nautilus-icon-info.c
+++ b/src/nautilus-icon-info.c
@@ -28,8 +28,6 @@ struct _NautilusIconInfo
     GdkPaintable *paintable;
 
     char *icon_name;
-
-    gint orig_scale;
 };
 
 static void schedule_reap_cache (void);
@@ -103,20 +101,18 @@ nautilus_icon_info_class_init (NautilusIconInfoClass *icon_info_class)
 }
 
 NautilusIconInfo *
-nautilus_icon_info_new_for_pixbuf (GdkPixbuf *pixbuf,
-                                   gint       scale)
+nautilus_icon_info_new_for_paintable (GdkPaintable *paintable,
+                                      gint          scale)
 {
     NautilusIconInfo *icon;
 
     icon = g_object_new (NAUTILUS_TYPE_ICON_INFO, NULL);
 
-    if (pixbuf)
+    if (paintable != NULL)
     {
-        icon->paintable = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (pixbuf));
+        icon->paintable = g_object_ref (paintable);
     }
 
-    icon->orig_scale = scale;
-
     return icon;
 }
 
@@ -128,9 +124,7 @@ nautilus_icon_info_new_for_icon_paintable (GtkIconPaintable *icon_paintable,
     g_autoptr (GFile) file = NULL;
     char *basename, *p;
 
-    icon = g_object_new (NAUTILUS_TYPE_ICON_INFO, NULL);
-
-    icon->paintable = GDK_PAINTABLE (g_object_ref (icon_paintable));
+    icon = nautilus_icon_info_new_for_paintable (GDK_PAINTABLE (icon_paintable), scale);
 
     file = gtk_icon_paintable_get_file (icon_paintable);
     if (file != NULL)
@@ -148,8 +142,6 @@ nautilus_icon_info_new_for_icon_paintable (GtkIconPaintable *icon_paintable,
         icon->icon_name = g_strdup (gtk_icon_paintable_get_icon_name (icon_paintable));
     }
 
-    icon->orig_scale = scale;
-
     return icon;
 }
 
@@ -344,7 +336,8 @@ nautilus_icon_info_lookup (GIcon *icon,
 
     if (G_IS_LOADABLE_ICON (icon))
     {
-        GdkPixbuf *pixbuf;
+        g_autoptr (GdkPixbuf) pixbuf = NULL;
+        g_autoptr (GdkTexture) texture = NULL;
         LoadableIconKey lookup_key;
         LoadableIconKey *key;
         GInputStream *stream;
@@ -368,7 +361,6 @@ nautilus_icon_info_lookup (GIcon *icon,
             return g_object_ref (icon_info);
         }
 
-        pixbuf = NULL;
         stream = g_loadable_icon_load (G_LOADABLE_ICON (icon),
                                        size * scale,
                                        NULL, NULL, NULL);
@@ -382,7 +374,12 @@ nautilus_icon_info_lookup (GIcon *icon,
             g_object_unref (stream);
         }
 
-        icon_info = nautilus_icon_info_new_for_pixbuf (pixbuf, scale);
+        if (pixbuf != NULL)
+        {
+            texture = gdk_texture_new_for_pixbuf (pixbuf);
+        }
+
+        icon_info = nautilus_icon_info_new_for_paintable (GDK_PAINTABLE (texture), scale);
 
         key = loadable_icon_key_new (icon, scale, size);
         g_hash_table_insert (loadable_icon_cache, key, icon_info);
@@ -394,7 +391,7 @@ nautilus_icon_info_lookup (GIcon *icon,
                                                      icon, size, scale, GTK_TEXT_DIR_NONE, 0);
     if (icon_paintable == NULL)
     {
-        return nautilus_icon_info_new_for_pixbuf (NULL, scale);
+        return nautilus_icon_info_new_for_paintable (NULL, scale);
     }
 
     if (G_IS_THEMED_ICON (icon))
diff --git a/src/nautilus-icon-info.h b/src/nautilus-icon-info.h
index 074789fda..727d3b226 100644
--- a/src/nautilus-icon-info.h
+++ b/src/nautilus-icon-info.h
@@ -14,7 +14,7 @@ G_BEGIN_DECLS
 #define NAUTILUS_TYPE_ICON_INFO (nautilus_icon_info_get_type ())
 G_DECLARE_FINAL_TYPE (NautilusIconInfo, nautilus_icon_info, NAUTILUS, ICON_INFO, GObject)
 
-NautilusIconInfo *    nautilus_icon_info_new_for_pixbuf               (GdkPixbuf         *pixbuf,
+NautilusIconInfo *    nautilus_icon_info_new_for_paintable            (GdkPaintable      *paintable,
                                                                       int                scale);
 NautilusIconInfo *    nautilus_icon_info_lookup                       (GIcon             *icon,
                                                                       int                size,
diff --git a/src/nautilus-name-cell.c b/src/nautilus-name-cell.c
index bab99561b..c1a1cf6bd 100644
--- a/src/nautilus-name-cell.c
+++ b/src/nautilus-name-cell.c
@@ -128,6 +128,7 @@ update_icon (NautilusNameCell *self)
     NautilusViewItem *item;
     NautilusFile *file;
     guint icon_size;
+    gint scale_factor;
     int icon_height;
     int extra_margin;
     g_autofree gchar *thumbnail_path = NULL;
@@ -137,9 +138,15 @@ update_icon (NautilusNameCell *self)
 
     file = nautilus_view_item_get_file (item);
     icon_size = nautilus_view_item_get_icon_size (item);
+<<<<<<< HEAD
     flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS;
+=======
+    scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (self));
+    flags = NAUTILUS_FILE_ICON_FLAGS_USE_THUMBNAILS |
+            NAUTILUS_FILE_ICON_FLAGS_FORCE_THUMBNAIL_SIZE;
+>>>>>>> 0b7293ad3 (file: Support HiDPI icons)
 
-    icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, 1, flags);
+    icon_paintable = nautilus_file_get_icon_paintable (file, icon_size, scale_factor, flags);
     gtk_picture_set_paintable (GTK_PICTURE (self->icon), icon_paintable);
 
     /* Set the same width for all icons regardless of aspect ratio.
diff --git a/src/nautilus-ui-utilities.c b/src/nautilus-ui-utilities.c
index 74bba91f2..d87422460 100644
--- a/src/nautilus-ui-utilities.c
+++ b/src/nautilus-ui-utilities.c
@@ -164,39 +164,41 @@ ensure_filmholes (void)
 }
 
 void
-nautilus_ui_frame_video (GdkPixbuf **pixbuf)
+nautilus_ui_frame_video (GtkSnapshot *snapshot,
+                         gdouble      width,
+                         gdouble      height)
 {
-    int width, height;
+    g_autoptr (GdkTexture) left_texture = NULL;
+    g_autoptr (GdkTexture) right_texture = NULL;
     int holes_width, holes_height;
-    int i;
 
     if (!ensure_filmholes ())
     {
         return;
     }
 
-    width = gdk_pixbuf_get_width (*pixbuf);
-    height = gdk_pixbuf_get_height (*pixbuf);
     holes_width = gdk_pixbuf_get_width (filmholes_left);
     holes_height = gdk_pixbuf_get_height (filmholes_left);
 
-    for (i = 0; i < height; i += holes_height)
-    {
-        gdk_pixbuf_composite (filmholes_left, *pixbuf, 0, i,
-                              MIN (width, holes_width),
-                              MIN (height - i, holes_height),
-                              0, i, 1, 1, GDK_INTERP_NEAREST, 255);
-    }
-
-    for (i = 0; i < height; i += holes_height)
-    {
-        gdk_pixbuf_composite (filmholes_right, *pixbuf,
-                              width - holes_width, i,
-                              MIN (width, holes_width),
-                              MIN (height - i, holes_height),
-                              width - holes_width, i,
-                              1, 1, GDK_INTERP_NEAREST, 255);
-    }
+    /* Left */
+    gtk_snapshot_push_repeat (snapshot,
+                              &GRAPHENE_RECT_INIT (0, 0, holes_width, height),
+                              NULL);
+    left_texture = gdk_texture_new_for_pixbuf (filmholes_left);
+    gtk_snapshot_append_texture (snapshot,
+                                 left_texture,
+                                 &GRAPHENE_RECT_INIT (0, 0, holes_width, holes_height));
+    gtk_snapshot_pop (snapshot);
+
+    /* Right */
+    gtk_snapshot_push_repeat (snapshot,
+                              &GRAPHENE_RECT_INIT (width - holes_width, 0, holes_width, height),
+                              NULL);
+    right_texture = gdk_texture_new_for_pixbuf (filmholes_right);
+    gtk_snapshot_append_texture (snapshot,
+                                 right_texture,
+                                 &GRAPHENE_RECT_INIT (width - holes_width, 0, holes_width, holes_height));
+    gtk_snapshot_pop (snapshot);
 }
 
 gboolean
diff --git a/src/nautilus-ui-utilities.h b/src/nautilus-ui-utilities.h
index 44af13586..f3df67f9c 100644
--- a/src/nautilus-ui-utilities.h
+++ b/src/nautilus-ui-utilities.h
@@ -35,7 +35,9 @@ void        nautilus_g_menu_replace_string_in_item  (GMenu             *menu,
                                                      const gchar       *attribute,
                                                      const gchar       *string);
 
-void        nautilus_ui_frame_video                 (GdkPixbuf        **pixbuf);
+void        nautilus_ui_frame_video                 (GtkSnapshot       *snapshot,
+                                                     gdouble            width,
+                                                     gdouble            height);
 
 gboolean    nautilus_date_time_is_between_dates     (GDateTime         *date,
                                                      GDateTime         *initial_date,


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