[gtk: 3/40] GtkIconInfo: Implement paintable
- From: Alexander Larsson <alexl src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gtk: 3/40] GtkIconInfo: Implement paintable
- Date: Thu, 30 Jan 2020 17:31:23 +0000 (UTC)
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]