diff options
author | Cosimo Cecchi <cosimoc@gnome.org> | 2014-07-19 13:03:58 -0700 |
---|---|---|
committer | Cosimo Cecchi <cosimoc@gnome.org> | 2014-07-29 10:13:21 +0200 |
commit | 7e425f301950a35fbba031a6ba548209e2ec2c1e (patch) | |
tree | 14bd4daba4fafa7c2967e9a1260c084214411cdc | |
parent | a23c29c0fb7c9f5064fd16f42c66a79f8f386352 (diff) | |
download | gtk+-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.c | 99 |
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); |