mirror of
https://gitlab.gnome.org/GNOME/gtk.git
synced 2024-11-15 05:00:09 +00:00
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.
This commit is contained in:
parent
3ac7e30455
commit
b96ab7453b
@ -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;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user