Commit 91f3f5c6 authored by Matthias Clasen's avatar Matthias Clasen
Browse files

image, picture: Move pixbuf code to gdkpixbufutils

This cleans up and moves the code to load files
while taking the scale into account. Along the way,
we drop the last uses of GdkPixbufAnimation, and
consolidate the pixbuf using code in one place.
parent 486a2c96
......@@ -18,6 +18,7 @@
#include <gdk/gdk.h>
#include "gdkpixbufutilsprivate.h"
#include "gtkscalerprivate.h"
static GdkPixbuf *
load_from_stream (GdkPixbufLoader *loader,
......@@ -572,3 +573,130 @@ gtk_make_symbolic_texture_from_file (GFile *file,
return texture;
}
typedef struct {
int scale_factor;
} LoaderData;
static void
on_loader_size_prepared (GdkPixbufLoader *loader,
int width,
int height,
gpointer user_data)
{
LoaderData *loader_data = user_data;
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;
}
gdk_pixbuf_loader_set_size (loader,
width * loader_data->scale_factor,
height * loader_data->scale_factor);
}
GdkPaintable *
gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
int scale_factor)
{
GdkPixbufLoader *loader;
GdkPixbuf *pixbuf = NULL;
LoaderData loader_data;
GdkTexture *texture;
GdkPaintable *paintable;
loader_data.scale_factor = scale_factor;
loader = gdk_pixbuf_loader_new ();
g_signal_connect (loader, "size-prepared",
G_CALLBACK (on_loader_size_prepared), &loader_data);
if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
goto out;
if (!gdk_pixbuf_loader_close (loader, NULL))
goto out;
pixbuf = gdk_pixbuf_loader_get_pixbuf (loader);
if (pixbuf != NULL)
g_object_ref (pixbuf);
out:
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
if (!pixbuf)
return NULL;
texture = gdk_texture_new_for_pixbuf (pixbuf);
if (loader_data.scale_factor != 1)
paintable = gtk_scaler_new (GDK_PAINTABLE (texture), loader_data.scale_factor);
else
paintable = g_object_ref ((GdkPaintable *)texture);
g_object_unref (pixbuf);
g_object_unref (texture);
return paintable;
}
GdkPaintable *
gdk_paintable_new_from_path_scaled (const char *path,
int scale_factor)
{
char *contents;
gsize length;
GBytes *bytes;
GdkPaintable *paintable;
if (!g_file_get_contents (path, &contents, &length, NULL))
return NULL;
bytes = g_bytes_new_take (contents, length);
paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
g_bytes_unref (bytes);
return paintable;
}
GdkPaintable *
gdk_paintable_new_from_resource_scaled (const char *path,
int scale_factor)
{
GBytes *bytes;
GdkPaintable *paintable;
bytes = g_resources_lookup_data (path, G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
if (!bytes)
return NULL;
paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
g_bytes_unref (bytes);
return paintable;
}
GdkPaintable *
gdk_paintable_new_from_file_scaled (GFile *file,
int scale_factor)
{
GBytes *bytes;
GdkPaintable *paintable;
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
if (!bytes)
return NULL;
paintable = gdk_paintable_new_from_bytes_scaled (bytes, scale_factor);
g_bytes_unref (bytes);
return paintable;
}
......@@ -86,6 +86,16 @@ GdkTexture *gtk_make_symbolic_texture_from_resource (const char *path,
int height,
double scale,
GError **error);
GdkPaintable *gdk_paintable_new_from_bytes_scaled (GBytes *bytes,
int scale_factor);
GdkPaintable *gdk_paintable_new_from_path_scaled (const char *path,
int scale_factor);
GdkPaintable *gdk_paintable_new_from_resource_scaled (const char *path,
int scale_factor);
GdkPaintable *gdk_paintable_new_from_file_scaled (GFile *file,
int scale_factor);
G_END_DECLS
#endif /* __GDK_PIXBUF_UTILS_PRIVATE_H__ */
......@@ -30,10 +30,10 @@
#include "gtkicontheme.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkscalerprivate.h"
#include "gtksnapshot.h"
#include "gtktypebuiltins.h"
#include "gtkwidgetprivate.h"
#include "gdkpixbufutilsprivate.h"
#include <math.h>
#include <string.h>
......@@ -581,96 +581,6 @@ gtk_image_new_from_gicon (GIcon *icon)
return GTK_WIDGET (image);
}
typedef struct {
GtkImage *image;
int scale_factor;
} LoaderData;
static void
on_loader_size_prepared (GdkPixbufLoader *loader,
int width,
int height,
gpointer user_data)
{
LoaderData *loader_data = user_data;
int 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 char *file_path,
const char *resource_path,
int *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:
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
g_bytes_unref (bytes);
return animation;
}
/**
* gtk_image_set_from_file: (attributes org.gtk.Method.set_property=file)
* @image: a `GtkImage`
......@@ -681,18 +591,16 @@ load_scalable_with_loader (GtkImage *image,
* See [ctor@Gtk.Image.new_from_file] for details.
*/
void
gtk_image_set_from_file (GtkImage *image,
const char *filename)
gtk_image_set_from_file (GtkImage *image,
const char *filename)
{
GdkPixbufAnimation *anim;
int scale_factor;
GdkTexture *texture;
GdkPaintable *scaler;
GdkPaintable *paintable;
g_return_if_fail (GTK_IS_IMAGE (image));
g_object_freeze_notify (G_OBJECT (image));
gtk_image_clear (image);
if (filename == NULL)
......@@ -702,23 +610,19 @@ gtk_image_set_from_file (GtkImage *image,
return;
}
anim = load_scalable_with_loader (image, filename, NULL, &scale_factor);
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image));
paintable = gdk_paintable_new_from_path_scaled (filename, scale_factor);
if (anim == NULL)
if (paintable == NULL)
{
gtk_image_set_from_icon_name (image, "image-missing");
g_object_thaw_notify (G_OBJECT (image));
return;
}
texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (anim));
scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor);
gtk_image_set_from_paintable (image, scaler);
gtk_image_set_from_paintable (image, paintable);
g_object_unref (scaler);
g_object_unref (texture);
g_object_unref (anim);
g_object_unref (paintable);
image->filename = g_strdup (filename);
......@@ -765,13 +669,11 @@ out:
* See [ctor@Gtk.Image.new_from_resource] for details.
*/
void
gtk_image_set_from_resource (GtkImage *image,
const char *resource_path)
gtk_image_set_from_resource (GtkImage *image,
const char *resource_path)
{
GdkPixbufAnimation *animation;
int scale_factor = 1;
GdkTexture *texture;
GdkPaintable *scaler;
int scale_factor;
GdkPaintable *paintable;
g_return_if_fail (GTK_IS_IMAGE (image));
......@@ -788,34 +690,29 @@ gtk_image_set_from_resource (GtkImage *image,
if (resource_is_pixdata (resource_path))
{
g_warning ("GdkPixdata format images are not supported, remove the \"to-pixdata\" option from your GResource files");
animation = NULL;
paintable = NULL;
}
else
{
animation = load_scalable_with_loader (image, NULL, resource_path, &scale_factor);
scale_factor = gtk_widget_get_scale_factor (GTK_WIDGET (image));
paintable = gdk_paintable_new_from_resource_scaled (resource_path, scale_factor);
}
if (animation == NULL)
if (paintable == NULL)
{
gtk_image_set_from_icon_name (image, "image-missing");
g_object_thaw_notify (G_OBJECT (image));
return;
}
texture = gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (animation));
scaler = gtk_scaler_new (GDK_PAINTABLE (texture), scale_factor);
gtk_image_set_from_paintable (image, scaler);
gtk_image_set_from_paintable (image, paintable);
g_object_unref (scaler);
g_object_unref (texture);
g_object_unref (paintable);
image->resource_path = g_strdup (resource_path);
g_object_notify_by_pspec (G_OBJECT (image), image_props[PROP_RESOURCE]);
g_object_unref (animation);
g_object_thaw_notify (G_OBJECT (image));
}
......
......@@ -26,9 +26,9 @@
#include "gtkcssstyleprivate.h"
#include "gtkintl.h"
#include "gtkprivate.h"
#include "gtkscalerprivate.h"
#include "gtksnapshot.h"
#include "gtkwidgetprivate.h"
#include "gdkpixbufutilsprivate.h"
/**
* GtkPicture:
......@@ -560,77 +560,6 @@ gtk_picture_new_for_resource (const char *resource_path)
return result;
}
typedef struct {
int scale_factor;
} LoaderData;
static void
on_loader_size_prepared (GdkPixbufLoader *loader,
int width,
int height,
gpointer user_data)
{
LoaderData *loader_data = user_data;
GdkPixbufFormat *format;
/* Let the regular icon helper code path handle non-scalable pictures */
format = gdk_pixbuf_loader_get_format (loader);
if (!gdk_pixbuf_format_is_scalable (format))
{
loader_data->scale_factor = 1;
return;
}
gdk_pixbuf_loader_set_size (loader,
width * loader_data->scale_factor,
height * loader_data->scale_factor);
}
static GdkPaintable *
load_scalable_with_loader (GFile *file,
int scale_factor)
{
GdkPixbufLoader *loader;
GBytes *bytes;
GdkPixbufAnimation *animation;
GdkPaintable *result, *scaler;
LoaderData loader_data;
result = NULL;
loader = gdk_pixbuf_loader_new ();
loader_data.scale_factor = scale_factor;
g_signal_connect (loader, "size-prepared", G_CALLBACK (on_loader_size_prepared), &loader_data);
bytes = g_file_load_bytes (file, NULL, NULL, NULL);
if (bytes == NULL)
goto out1;
if (!gdk_pixbuf_loader_write_bytes (loader, bytes, NULL))
goto out2;
if (!gdk_pixbuf_loader_close (loader, NULL))
goto out2;
animation = gdk_pixbuf_loader_get_animation (loader);
if (animation == NULL)
goto out2;
result = GDK_PAINTABLE (gdk_texture_new_for_pixbuf (gdk_pixbuf_animation_get_static_image (animation)));
scaler = gtk_scaler_new (result, loader_data.scale_factor);
g_object_unref (result);
result = scaler;
out2:
g_bytes_unref (bytes);
out1:
gdk_pixbuf_loader_close (loader, NULL);
g_object_unref (loader);
return result;
}
/**
* gtk_picture_set_file: (attributes org.gtk.Method.set_property=file)
* @self: a `GtkPicture`
......@@ -657,7 +586,7 @@ gtk_picture_set_file (GtkPicture *self,
g_set_object (&self->file, file);
g_object_notify_by_pspec (G_OBJECT (self), properties[PROP_FILE]);
paintable = load_scalable_with_loader (file, gtk_widget_get_scale_factor (GTK_WIDGET (self)));
paintable = gdk_paintable_new_from_file_scaled (file, gtk_widget_get_scale_factor (GTK_WIDGET (self)));
gtk_picture_set_paintable (self, paintable);
g_clear_object (&paintable);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment