summaryrefslogtreecommitdiff
path: root/gdk-pixbuf/gdk-pixbuf-loader.c
diff options
context:
space:
mode:
authorMatthias Clasen <matthiasc@src.gnome.org>2002-07-06 23:10:46 +0000
committerMatthias Clasen <matthiasc@src.gnome.org>2002-07-06 23:10:46 +0000
commit7a7315974bbe8e43fa45384766ad8acadc687b39 (patch)
tree501210ec71c71966efdf24cf90ccdc4c4bb3999b /gdk-pixbuf/gdk-pixbuf-loader.c
parent290ef37e0568b83f6111072d99a07e2d569d52f5 (diff)
downloadgdk-pixbuf-7a7315974bbe8e43fa45384766ad8acadc687b39.tar.gz
Load-at-size functionality for gdk-pixbuf.
Diffstat (limited to 'gdk-pixbuf/gdk-pixbuf-loader.c')
-rw-r--r--gdk-pixbuf/gdk-pixbuf-loader.c141
1 files changed, 121 insertions, 20 deletions
diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c
index 52b1f112a..bcb7382e3 100644
--- a/gdk-pixbuf/gdk-pixbuf-loader.c
+++ b/gdk-pixbuf/gdk-pixbuf-loader.c
@@ -31,8 +31,9 @@
#include "gdk-pixbuf-marshal.h"
enum {
- AREA_UPDATED,
+ SIZE_PREPARED,
AREA_PREPARED,
+ AREA_UPDATED,
CLOSED,
LAST_SIGNAL
};
@@ -58,6 +59,10 @@ typedef struct
gint header_buf_offset;
GdkPixbufModule *image_module;
gpointer context;
+ gint width;
+ gint height;
+ gboolean size_fixed;
+ gboolean needs_scale;
} GdkPixbufLoaderPrivate;
@@ -109,6 +114,17 @@ gdk_pixbuf_loader_class_init (GdkPixbufLoaderClass *class)
object_class->finalize = gdk_pixbuf_loader_finalize;
+ pixbuf_loader_signals[SIZE_PREPARED] =
+ g_signal_new ("size_prepared",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (GdkPixbufLoaderClass, size_prepared),
+ NULL, NULL,
+ gdk_pixbuf_marshal_VOID__INT_INT,
+ G_TYPE_NONE, 2,
+ G_TYPE_INT,
+ G_TYPE_INT);
+
pixbuf_loader_signals[AREA_PREPARED] =
g_signal_new ("area_prepared",
G_TYPE_FROM_CLASS (object_class),
@@ -170,14 +186,73 @@ gdk_pixbuf_loader_finalize (GObject *object)
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+/**
+ * gdk_pixbuf_loader_set_size:
+ * @loader: A pixbuf loader.
+ * @width: The desired width of the image being loaded.
+ * @height: The desired height of the image being loaded.
+ *
+ * Causes the image to be scaled while it is loaded. The desired
+ * image size can be determined relative to the original size of
+ * the image by calling gdk_pixbuf_loader_set_size() from a
+ * signal handler for the ::size_prepared signal.
+ *
+ * Attempts to set the desired image size are ignored after the
+ * emission of the ::size_prepared signal.
+ */
+void
+gdk_pixbuf_loader_set_size (GdkPixbufLoader *loader,
+ gint width,
+ gint height)
+{
+ GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
+ g_return_if_fail (width > 0 && height > 0);
+
+ if (!priv->size_fixed) {
+ priv->width = width;
+ priv->height = height;
+ }
+}
+
+static void
+gdk_pixbuf_loader_size_func (gint *width, gint *height, gpointer loader)
+{
+ GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
+
+ /* allow calling gdk_pixbuf_loader_set_size() before the signal */
+ if (priv->width == 0 && priv->height == 0) {
+ priv->width = *width;
+ priv->height = *height;
+ }
+
+ g_signal_emit (loader, pixbuf_loader_signals[SIZE_PREPARED], 0, *width, *height);
+ priv->size_fixed = TRUE;
+
+ *width = priv->width;
+ *height = priv->height;
+}
+
static void
gdk_pixbuf_loader_prepare (GdkPixbuf *pixbuf,
GdkPixbufAnimation *anim,
gpointer loader)
{
- GdkPixbufLoaderPrivate *priv = NULL;
-
- priv = GDK_PIXBUF_LOADER (loader)->priv;
+ GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
+ g_return_if_fail (pixbuf != NULL);
+
+ if (!priv->size_fixed) {
+ /* Defend against lazy loaders which don't call size_func */
+ gint width = gdk_pixbuf_get_width (pixbuf);
+ gint height = gdk_pixbuf_get_height (pixbuf);
+
+ gdk_pixbuf_loader_size_func (&width, &height, loader);
+ }
+
+ priv->needs_scale = FALSE;
+ if (priv->width > 0 && priv->height > 0 &&
+ (priv->width != gdk_pixbuf_get_width (pixbuf) ||
+ priv->height != gdk_pixbuf_get_height (pixbuf)))
+ priv->needs_scale = TRUE;
if (anim)
g_object_ref (anim);
@@ -186,7 +261,8 @@ gdk_pixbuf_loader_prepare (GdkPixbuf *pixbuf,
priv->animation = anim;
- g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
+ if (!priv->needs_scale)
+ g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
}
static void
@@ -197,17 +273,16 @@ gdk_pixbuf_loader_update (GdkPixbuf *pixbuf,
gint height,
gpointer loader)
{
- GdkPixbufLoaderPrivate *priv = NULL;
-
- priv = GDK_PIXBUF_LOADER (loader)->priv;
-
- g_signal_emit (loader,
- pixbuf_loader_signals[AREA_UPDATED],
- 0,
- x, y,
- /* sanity check in here. Defend against an errant loader */
- MIN (width, gdk_pixbuf_animation_get_width (priv->animation)),
- MIN (height, gdk_pixbuf_animation_get_height (priv->animation)));
+ GdkPixbufLoaderPrivate *priv = GDK_PIXBUF_LOADER (loader)->priv;
+
+ if (!priv->needs_scale)
+ g_signal_emit (loader,
+ pixbuf_loader_signals[AREA_UPDATED],
+ 0,
+ x, y,
+ /* sanity check in here. Defend against an errant loader */
+ MIN (width, gdk_pixbuf_animation_get_width (priv->animation)),
+ MIN (height, gdk_pixbuf_animation_get_height (priv->animation)));
}
static gint
@@ -253,10 +328,11 @@ gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader,
return 0;
}
- priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_prepare,
- gdk_pixbuf_loader_update,
- loader,
- error);
+ priv->context = priv->image_module->begin_load (gdk_pixbuf_loader_size_func,
+ gdk_pixbuf_loader_prepare,
+ gdk_pixbuf_loader_update,
+ loader,
+ error);
if (priv->context == NULL)
{
@@ -536,12 +612,33 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader,
retval = FALSE;
}
}
+
if (priv->image_module && priv->image_module->stop_load && priv->context) {
if (!priv->image_module->stop_load (priv->context, error))
retval = FALSE;
}
priv->closed = TRUE;
+
+ if (priv->needs_scale) {
+ GdkPixbuf *tmp, *pixbuf;
+
+ tmp = gdk_pixbuf_animation_get_static_image (priv->animation);
+ g_object_ref (tmp);
+ pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, tmp->has_alpha, 8, priv->width, priv->height);
+ g_object_unref (priv->animation);
+ priv->animation = gdk_pixbuf_non_anim_new (pixbuf);
+ g_signal_emit (loader, pixbuf_loader_signals[AREA_PREPARED], 0);
+ gdk_pixbuf_scale (tmp, pixbuf, 0, 0, priv->width, priv->height, 0, 0,
+ (double) priv->width / tmp->width,
+ (double) priv->height / tmp->height,
+ GDK_INTERP_BILINEAR);
+ g_object_unref (tmp);
+
+ g_signal_emit (loader, pixbuf_loader_signals[AREA_UPDATED], 0,
+ 0, 0, priv->width, priv->height);
+ }
+
g_signal_emit (loader, pixbuf_loader_signals[CLOSED], 0);
@@ -549,3 +646,7 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader,
}
+
+
+
+