summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCosimo Cecchi <cosimoc@gnome.org>2014-07-19 13:03:58 -0700
committerCosimo Cecchi <cosimoc@gnome.org>2014-07-29 10:13:21 +0200
commit7e425f301950a35fbba031a6ba548209e2ec2c1e (patch)
tree14bd4daba4fafa7c2967e9a1260c084214411cdc
parenta23c29c0fb7c9f5064fd16f42c66a79f8f386352 (diff)
downloadgtk+-7e425f301950a35fbba031a6ba548209e2ec2c1e.tar.gz
image: support scale factor when loading from GResource and file
Currently, when loading an image from a GResource or file we don't take the scale factor of the display into consideration, and let GtkIconHelper scale it accordingly. While this in general works for non-scalable images, we can take advantage of the native loader's scaling for e.g. SVG images, and load them at the right scale factor automatically. This is achieved by switching to a pixbuf loader instead of using the native function. https://bugzilla.gnome.org/show_bug.cgi?id=733416
-rw-r--r--gtk/gtkimage.c99
1 files changed, 97 insertions, 2 deletions
diff --git a/gtk/gtkimage.c b/gtk/gtkimage.c
index bd19cd276d..98c969eb3f 100644
--- a/gtk/gtkimage.c
+++ b/gtk/gtkimage.c
@@ -817,6 +817,95 @@ gtk_image_new_from_gicon (GIcon *icon,
return GTK_WIDGET (image);
}
+typedef struct {
+ GtkImage *image;
+ gint scale_factor;
+} LoaderData;
+
+static void
+on_loader_size_prepared (GdkPixbufLoader *loader,
+ gint width,
+ gint height,
+ gpointer user_data)
+{
+ LoaderData *loader_data = user_data;
+ gint scale_factor;
+ GdkPixbufFormat *format;
+
+ /* Let the regular icon helper code path handle non-scalable images */
+ format = gdk_pixbuf_loader_get_format (loader);
+ if (!gdk_pixbuf_format_is_scalable (format))
+ {
+ loader_data->scale_factor = 1;
+ return;
+ }
+
+ scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (loader_data->image));
+ gdk_pixbuf_loader_set_size (loader, width * scale_factor, height * scale_factor);
+ loader_data->scale_factor = scale_factor;
+}
+
+static GdkPixbufAnimation *
+load_scalable_with_loader (GtkImage *image,
+ const gchar *file_path,
+ const gchar *resource_path,
+ gint *scale_factor_out)
+{
+ GdkPixbufLoader *loader;
+ GBytes *bytes;
+ char *contents;
+ gsize length;
+ gboolean res;
+ GdkPixbufAnimation *animation;
+ LoaderData loader_data;
+
+ animation = NULL;
+ bytes = NULL;
+
+ loader = gdk_pixbuf_loader_new ();
+ loader_data.image = image;
+
+ g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);
+
+ if (resource_path != NULL)
+ {
+ bytes = g_resources_lookup_data (resource_path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ }
+ else if (file_path != NULL)
+ {
+ res = g_file_get_contents (file_path, &contents, &length, NULL);
+ if (res)
+ bytes = g_bytes_new_take (contents, length);
+ }
+ else
+ {
+ g_assert_not_reached ();
+ }
+
+ if (!bytes)
+ goto out;
+
+ if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
+ goto out;
+
+ if (!gdk_pixbuf_loader_close (loader, NULL))
+ goto out;
+
+ animation = gdk_pixbuf_loader_get_animation (loader);
+ if (animation != NULL)
+ {
+ g_object_ref (animation);
+ if (scale_factor_out != NULL)
+ *scale_factor_out = loader_data.scale_factor;
+ }
+
+ out:
+ g_object_unref (loader);
+ g_bytes_unref (bytes);
+
+ return animation;
+}
+
/**
* gtk_image_set_from_file:
* @image: a #GtkImage
@@ -830,6 +919,7 @@ gtk_image_set_from_file (GtkImage *image,
{
GtkImagePrivate *priv;
GdkPixbufAnimation *anim;
+ gint scale_factor;
g_return_if_fail (GTK_IS_IMAGE (image));
@@ -846,7 +936,7 @@ gtk_image_set_from_file (GtkImage *image,
return;
}
- anim = gdk_pixbuf_animation_new_from_file (filename, NULL);
+ anim = load_scalable_with_loader (image, filename, NULL, &scale_factor);
if (anim == NULL)
{
@@ -868,6 +958,8 @@ gtk_image_set_from_file (GtkImage *image,
else
gtk_image_set_from_animation (image, anim);
+ _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);
+
g_object_unref (anim);
priv->filename = g_strdup (filename);
@@ -888,6 +980,7 @@ gtk_image_set_from_resource (GtkImage *image,
{
GtkImagePrivate *priv;
GdkPixbufAnimation *animation;
+ gint scale_factor;
g_return_if_fail (GTK_IS_IMAGE (image));
@@ -903,7 +996,7 @@ gtk_image_set_from_resource (GtkImage *image,
return;
}
- animation = gdk_pixbuf_animation_new_from_resource (resource_path, NULL);
+ animation = load_scalable_with_loader (image, NULL, resource_path, &scale_factor);
if (animation == NULL)
{
@@ -921,6 +1014,8 @@ gtk_image_set_from_resource (GtkImage *image,
else
gtk_image_set_from_animation (image, animation);
+ _gtk_icon_helper_set_pixbuf_scale (priv->icon_helper, scale_factor);
+
g_object_notify (G_OBJECT (image), "resource");
g_object_unref (animation);