[nautilus/wip/antoniof/hidpi-and-icons-cleanup: 4/11] file: Support HiDPI icons
- From: António Fernandes <antoniof src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [nautilus/wip/antoniof/hidpi-and-icons-cleanup: 4/11] file: Support HiDPI icons
- Date: Sun, 7 Aug 2022 23:42:29 +0000 (UTC)
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]