summaryrefslogtreecommitdiff
path: root/gdk-pixbuf
diff options
context:
space:
mode:
authorHavoc Pennington <hp@redhat.com>2000-10-18 18:42:54 +0000
committerHavoc Pennington <hp@src.gnome.org>2000-10-18 18:42:54 +0000
commit7a4c68938789206bfec3c6d15cc4bb922daf6443 (patch)
treee5f031fc609e50a8b7b12e7d6abf63cc78cc88e7 /gdk-pixbuf
parent7420908815651a1ff2ceb1c0fb5e92fe9b260619 (diff)
downloadgdk-pixbuf-7a4c68938789206bfec3c6d15cc4bb922daf6443.tar.gz
Some updates
2000-10-18 Havoc Pennington <hp@redhat.com> * gtk/gtk-sections.txt: Some updates * gdk/gdk-sections.txt: remove GdkPixbufAlphaMode * gdk-pixbuf/gdk-pixbuf-sections.txt: Add new API, remove GdkPixbufClass/GdkAnimationClass since those are private * gdk-pixbuf/Makefile.am (IGNORE_HFILES): ignore more headers 2000-10-18 Havoc Pennington <hp@redhat.com> * gtk/gtktextiter.c (gtk_text_iter_forward_to_newline): Fix a bug where any number of empty lines would get skipped * gtk/gtktextiter.h: Remove padding from GtkTextIter; live on the edge. * gtk/gtktextiter.c (gtk_text_iter_make_surreal): enhance the warning about invalid iterators (explain more thoroughly) (gtk_text_iter_in_region): rename gtk_text_iter_in_range * gtk/gtktextview.c (FOCUS_EDGE_WIDTH): Make focus rectangle less big * demos/*.c: Add error handling * gtk/gtktextbuffer.c: don't modify const iterators * gtk/gdk-pixbuf-loader.c: Add full error handling here * gtk/gtkimage.c (gtk_image_set_from_file): ignore errors on file load * gtk/gtkiconfactory.c: Update to reflect addition of error handling to gdk-pixbuf loaders 2000-10-16 Havoc Pennington <hp@redhat.com> * gdk-pixbuf-io.c (gdk_pixbuf_get_module) (gdk_pixbuf_get_named_module) (gdk_pixbuf_load_module): add error reporting here also * make-inline-pixbuf.c (main): use GError * io-xpm.c: include unistd.h * gdk-pixbuf-util.c: include string.h * io-*.c: add error reporting * gdk-pixbuf-animation.c (gdk_pixbuf_animation_new_from_file): add error reporting * gdk-pixbuf-io.c (gdk_pixbuf_new_from_file): Add error reporting * gdk-pixbuf-io.h: Add GError** to load_increment and load methods * gdk-pixbuf-io.c (gdk_pixbuf_save) (gdk_pixbuf_savev): return a G_FILE_ERROR if we fail to write or close the file. * gdk-pixbuf.h: remove GDK_PIXBUF_ERROR_IO, instead we'll use G_FILE_ERROR_*. Rename enum to GdkPixbufError, properly following the GError naming rules. Add GError** to load functions.
Diffstat (limited to 'gdk-pixbuf')
-rw-r--r--gdk-pixbuf/ChangeLog29
-rw-r--r--gdk-pixbuf/gdk-pixbuf-animation.c74
-rw-r--r--gdk-pixbuf/gdk-pixbuf-data.c130
-rw-r--r--gdk-pixbuf/gdk-pixbuf-io.c199
-rw-r--r--gdk-pixbuf/gdk-pixbuf-io.h24
-rw-r--r--gdk-pixbuf/gdk-pixbuf-loader.c114
-rw-r--r--gdk-pixbuf/gdk-pixbuf-loader.h6
-rw-r--r--gdk-pixbuf/gdk-pixbuf-util.c1
-rw-r--r--gdk-pixbuf/gdk-pixbuf.h31
-rw-r--r--gdk-pixbuf/gnome-canvas-pixbuf.c841
-rw-r--r--gdk-pixbuf/gnome-canvas-pixbuf.h64
-rw-r--r--gdk-pixbuf/io-bmp.c34
-rw-r--r--gdk-pixbuf/io-gif.c68
-rw-r--r--gdk-pixbuf/io-ico.c27
-rw-r--r--gdk-pixbuf/io-jpeg.c79
-rw-r--r--gdk-pixbuf/io-png.c135
-rw-r--r--gdk-pixbuf/io-pnm.c125
-rw-r--r--gdk-pixbuf/io-ras.c25
-rw-r--r--gdk-pixbuf/io-tiff.c3
-rw-r--r--gdk-pixbuf/io-wbmp.c28
-rw-r--r--gdk-pixbuf/io-xpm.c4
-rw-r--r--gdk-pixbuf/make-inline-pixbuf.c9
22 files changed, 888 insertions, 1162 deletions
diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog
index 321f5ad58..172bd5306 100644
--- a/gdk-pixbuf/ChangeLog
+++ b/gdk-pixbuf/ChangeLog
@@ -1,3 +1,32 @@
+2000-10-16 Havoc Pennington <hp@redhat.com>
+
+ * gdk-pixbuf-io.c (gdk_pixbuf_get_module)
+ (gdk_pixbuf_get_named_module) (gdk_pixbuf_load_module):
+ add error reporting here also
+
+ * make-inline-pixbuf.c (main): use GError
+
+ * io-xpm.c: include unistd.h
+
+ * gdk-pixbuf-util.c: include string.h
+
+ * io-*.c: add error reporting
+
+ * gdk-pixbuf-animation.c (gdk_pixbuf_animation_new_from_file): add
+ error reporting
+
+ * gdk-pixbuf-io.c (gdk_pixbuf_new_from_file): Add error reporting
+
+ * gdk-pixbuf-io.h: Add GError** to load_increment and load
+ methods
+
+ * gdk-pixbuf-io.c (gdk_pixbuf_save) (gdk_pixbuf_savev): return
+ a G_FILE_ERROR if we fail to write or close the file.
+
+ * gdk-pixbuf.h: remove GDK_PIXBUF_ERROR_IO, instead we'll use
+ G_FILE_ERROR_*. Rename enum to GdkPixbufError, properly following
+ the GError naming rules. Add GError** to load functions.
+
2000-10-06 Havoc Pennington <hp@redhat.com>
* gdk-pixbuf.h: add GdkPixbufAlphaMode
diff --git a/gdk-pixbuf/gdk-pixbuf-animation.c b/gdk-pixbuf/gdk-pixbuf-animation.c
index 25f5d7d17..16dc26d6c 100644
--- a/gdk-pixbuf/gdk-pixbuf-animation.c
+++ b/gdk-pixbuf/gdk-pixbuf-animation.c
@@ -22,6 +22,7 @@
*/
#include <config.h>
+#include <errno.h>
#include "gdk-pixbuf-io.h"
#include "gdk-pixbuf-private.h"
@@ -92,10 +93,12 @@ gdk_pixbuf_animation_finalize (GObject *object)
/**
* gdk_pixbuf_animation_new_from_file:
* @filename: Name of file to load.
+ * @error: return location for error
*
* Creates a new animation by loading it from a file. The file format is
* detected automatically. If the file's format does not support multi-frame
- * images, then an animation with a single frame will be created.
+ * images, then an animation with a single frame will be created. Possible errors
+ * are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
*
* Return value: A newly created animation with a reference count of 1, or NULL
* if any of several error conditions ocurred: the file could not be opened,
@@ -103,7 +106,8 @@ gdk_pixbuf_animation_finalize (GObject *object)
* allocate the image buffer, or the image file contained invalid data.
**/
GdkPixbufAnimation *
-gdk_pixbuf_animation_new_from_file (const char *filename)
+gdk_pixbuf_animation_new_from_file (const char *filename,
+ GError **error)
{
GdkPixbufAnimation *animation;
int size;
@@ -114,25 +118,39 @@ gdk_pixbuf_animation_new_from_file (const char *filename)
g_return_val_if_fail (filename != NULL, NULL);
f = fopen (filename, "rb");
- if (!f)
+ if (!f) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Failed to open file '%s': %s"),
+ filename, g_strerror (errno));
return NULL;
+ }
size = fread (&buffer, 1, sizeof (buffer), f);
if (size == 0) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image file '%s' contains no data"),
+ filename);
+
fclose (f);
return NULL;
}
- image_module = gdk_pixbuf_get_module (buffer, size);
+ image_module = gdk_pixbuf_get_module (buffer, size, filename, error);
if (!image_module) {
- g_warning ("Unable to find handler for file: %s", filename);
fclose (f);
return NULL;
}
if (image_module->module == NULL)
- gdk_pixbuf_load_module (image_module);
+ if (!gdk_pixbuf_load_module (image_module, error)) {
+ fclose (f);
+ return NULL;
+ }
if (image_module->load_animation == NULL) {
GdkPixbuf *pixbuf;
@@ -141,14 +159,35 @@ gdk_pixbuf_animation_new_from_file (const char *filename)
/* Keep this logic in sync with gdk_pixbuf_new_from_file() */
if (image_module->load == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
+ _("Don't know how to load the animation in file '%s'"),
+ filename);
fclose (f);
return NULL;
}
fseek (f, 0, SEEK_SET);
- pixbuf = (* image_module->load) (f);
+ pixbuf = (* image_module->load) (f, error);
fclose (f);
+ if (pixbuf == NULL && error != NULL && *error == NULL) {
+ /* I don't trust these crufty longjmp()'ing image libs
+ * to maintain proper error invariants, and I don't
+ * want user code to segfault as a result. We need to maintain
+ * the invariant that error gets set if NULL is returned.
+ */
+
+ g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.",
+ image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Failed to load image '%s': reason not known, probably a corrupt image file"),
+ filename);
+ }
+
if (pixbuf == NULL)
return NULL;
@@ -167,7 +206,26 @@ gdk_pixbuf_animation_new_from_file (const char *filename)
animation->height = gdk_pixbuf_get_height (pixbuf);
} else {
fseek (f, 0, SEEK_SET);
- animation = (* image_module->load_animation) (f);
+ animation = (* image_module->load_animation) (f, error);
+
+ if (animation == NULL && error != NULL && *error == NULL) {
+ /* I don't trust these crufty longjmp()'ing
+ * image libs to maintain proper error
+ * invariants, and I don't want user code to
+ * segfault as a result. We need to maintain
+ * the invariant that error gets set if NULL
+ * is returned.
+ */
+
+ g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.",
+ image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Failed to load animation '%s': reason not known, probably a corrupt animation file"),
+ filename);
+ }
+
fclose (f);
}
diff --git a/gdk-pixbuf/gdk-pixbuf-data.c b/gdk-pixbuf/gdk-pixbuf-data.c
index 94db20f37..a1b023240 100644
--- a/gdk-pixbuf/gdk-pixbuf-data.c
+++ b/gdk-pixbuf/gdk-pixbuf-data.c
@@ -23,6 +23,7 @@
#include <config.h>
#include "gdk-pixbuf.h"
#include "gdk-pixbuf-private.h"
+#include "gdk-pixbuf-i18n.h"
#include <stdlib.h>
#include <string.h>
@@ -106,7 +107,10 @@ read_bool (const guchar **p)
}
static GdkPixbuf*
-read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
+read_raw_inline (const guchar *data,
+ gboolean copy_pixels,
+ int length,
+ GError **error)
{
GdkPixbuf *pixbuf;
const guchar *p = data;
@@ -116,6 +120,11 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
if (length >= 0 && length < 12) {
/* Not enough buffer to hold the width/height/rowstride */
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image data is partially missing"));
+
return NULL;
}
@@ -123,9 +132,14 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
width = read_int (&p);
height = read_int (&p);
- if (rowstride < width)
+ if (rowstride < width) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an incorrect pixel rowstride, perhaps the data was corrupted somehow."));
return NULL; /* bad data from untrusted source. */
-
+ }
+
/* rowstride >= width, so we can trust width */
length -= 12;
@@ -133,37 +147,71 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
/* There's some better way like G_MAXINT/height > rowstride
* but I'm not sure it works, so stick to this for now.
*/
- if (((double)height) * ((double)rowstride) > (double)G_MAXINT)
+ if (((double)height) * ((double)rowstride) > (double)G_MAXINT) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image size is impossibly large, perhaps the data was corrupted somehow"));
+
return NULL; /* overflow */
-
+ }
+
if (length >= 0 &&
length < (height * rowstride + 13)) {
/* Not enough buffer to hold the remaining header
* information plus the data.
*/
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image data is partially missing, probably it was ocorrupted somehow."));
return NULL;
}
-
+
/* Read the remaining 13 bytes of header information */
has_alpha = read_bool (&p) != FALSE;
colorspace = read_int (&p);
n_channels = read_int (&p);
bits_per_sample = read_int (&p);
-
- if (colorspace != GDK_COLORSPACE_RGB)
+
+ if (colorspace != GDK_COLORSPACE_RGB) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an unknown colorspace code (%d), perhaps the image data was corrupted"),
+ colorspace);
return NULL;
+ }
- if (bits_per_sample != 8)
+ if (bits_per_sample != 8) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of bits per sample (%d), perhaps the image data was corrupted"),
+ bits_per_sample);
return NULL;
-
- if (has_alpha && n_channels != 4)
+ }
+
+ if (has_alpha && n_channels != 4) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of channels (%d), perhaps the image data was corrupted"),
+ n_channels);
return NULL;
-
- if (!has_alpha && n_channels != 3)
+ }
+
+ if (!has_alpha && n_channels != 3) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image has an improper number of channels (%d), perhaps the image data was corrupted"),
+ n_channels);
return NULL;
-
+ }
+
if (copy_pixels) {
guchar *pixels;
gint dest_rowstride;
@@ -172,10 +220,19 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
pixbuf = gdk_pixbuf_new (colorspace,
has_alpha, bits_per_sample,
width, height);
-
+
+ if (pixbuf == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Not enough memory to store a %d by %d image; try exiting some applications to free memory."),
+ width, height);
+ return NULL;
+ }
+
pixels = gdk_pixbuf_get_pixels (pixbuf);
dest_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
-
+
for (row = 0; row < height; row++) {
memcpy (pixels, p, rowstride);
pixels += dest_rowstride;
@@ -190,32 +247,42 @@ read_raw_inline (const guchar *data, gboolean copy_pixels, int length)
rowstride,
NULL, NULL);
}
-
+
return pixbuf;
}
/**
* gdk_pixbuf_new_from_inline:
- * @data: An inlined GdkPixbuf
+ * @inline_pixbuf: An inlined GdkPixbuf
* @copy_pixels: whether to copy the pixels out of the inline data, or to use them in-place
+ * @length: length of the inline data
+ * @error: return location for error
*
* Create a #GdkPixbuf from a custom format invented to store pixbuf
- * data in C program code. This library comes with a program called "make-inline-pixbuf"
- * that can write out a variable definition containing an inlined pixbuf.
- * This is useful if you want to ship a program with images, but
- * don't want to depend on any external files.
+ * data in C program code. This library comes with a program called
+ * "make-inline-pixbuf" that can write out a variable definition
+ * containing an inlined pixbuf. This is useful if you want to ship a
+ * program with images, but don't want to depend on any external
+ * files.
*
* The inline data format contains the pixels in #GdkPixbuf's native
* format. Since the inline pixbuf is read-only static data, you
* don't need to copy it unless you intend to write to it.
*
+ * If you create a pixbuf from const inline data compiled into your
+ * program, it's probably safe to ignore errors, since things will
+ * always succeed. For non-const inline data, you could get out of
+ * memory. For untrusted inline data located at runtime, you could
+ * have corrupt inline data in addition.
+ *
* Return value: A newly-created #GdkPixbuf structure with a reference count of
- * 1.
+ * 1, or NULL If error is set.
**/
GdkPixbuf*
gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
gboolean copy_pixels,
- int length)
+ int length,
+ GError **error)
{
const guchar *p;
GdkPixbuf *pixbuf;
@@ -225,12 +292,20 @@ gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
/* not enough bytes to contain even the magic number
* and format code.
*/
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image contained no data."));
return NULL;
}
p = inline_pixbuf;
if (read_int (&p) != GDK_PIXBUF_INLINE_MAGIC_NUMBER) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image isn't in the correct format (inline GdkPixbuf format)"));
return NULL;
}
@@ -239,10 +314,15 @@ gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
switch (format)
{
case GDK_PIXBUF_INLINE_RAW:
- pixbuf = read_raw_inline (p, copy_pixels, length - 8);
+ pixbuf = read_raw_inline (p, copy_pixels, length - 8, error);
break;
default:
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("This version of the software is unable to read images with type code %d"),
+ format);
return NULL;
}
diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c
index d861c5611..02a517e43 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.c
+++ b/gdk-pixbuf/gdk-pixbuf-io.c
@@ -275,8 +275,9 @@ get_libdir (void)
/* actually load the image handler - gdk_pixbuf_get_module only get a */
/* reference to the module to load, it doesn't actually load it */
/* perhaps these actions should be combined in one function */
-void
-gdk_pixbuf_load_module (GdkPixbufModule *image_module)
+gboolean
+gdk_pixbuf_load_module (GdkPixbufModule *image_module,
+ GError **error)
{
char *module_name;
char *path;
@@ -285,7 +286,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
gpointer save_sym;
char *name;
- g_return_if_fail (image_module->module == NULL);
+ g_return_val_if_fail (image_module->module == NULL, FALSE);
name = image_module->module_name;
@@ -304,10 +305,14 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
module = g_module_open (path, G_MODULE_BIND_LAZY);
if (!module) {
- g_warning ("Unable to load module: %s: %s", path, g_module_error ());
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Unable to load image-loading module: %s: %s"),
+ path, g_module_error ());
g_free (module_name);
g_free (path);
- return;
+ return FALSE;
}
g_free (path);
} else {
@@ -337,7 +342,9 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->load_animation = load_sym;
if (pixbuf_module_symbol (module, name, "image_save", &save_sym))
- image_module->save = save_sym;
+ image_module->save = save_sym;
+
+ return TRUE;
}
#else
@@ -406,8 +413,9 @@ m_stop_load (tiff);
m_load (xpm);
m_load_xpm_data (xpm);
-void
-gdk_pixbuf_load_module (GdkPixbufModule *image_module)
+gboolean
+gdk_pixbuf_load_module (GdkPixbufModule *image_module,
+ GError **error)
{
image_module->module = (void *) 1;
@@ -417,7 +425,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->load_increment = mname (png,load_increment);
image_module->stop_load = mname (png,stop_load);
image_module->save = mname (png,save);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "bmp") == 0){
@@ -425,7 +433,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->begin_load = mname (bmp,begin_load);
image_module->load_increment = mname (bmp,load_increment);
image_module->stop_load = mname (bmp,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "wbmp") == 0){
@@ -433,7 +441,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->begin_load = mname (wbmp,begin_load);
image_module->load_increment = mname (wbmp,load_increment);
image_module->stop_load = mname (wbmp,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "gif") == 0){
@@ -442,7 +450,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->load_increment = mname (gif,load_increment);
image_module->stop_load = mname (gif,stop_load);
image_module->load_animation = mname (gif,load_animation);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "ico") == 0){
@@ -450,7 +458,7 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->begin_load = mname (ico,begin_load);
image_module->load_increment = mname (ico,load_increment);
image_module->stop_load = mname (ico,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "jpeg") == 0){
@@ -459,34 +467,42 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
image_module->load_increment = mname (jpeg,load_increment);
image_module->stop_load = mname (jpeg,stop_load);
image_module->save = mname (jpeg,save);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "pnm") == 0){
image_module->load = mname (pnm,load);
image_module->begin_load = mname (pnm,begin_load);
image_module->load_increment = mname (pnm,load_increment);
image_module->stop_load = mname (pnm,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "ras") == 0){
image_module->load = mname (ras,load);
image_module->begin_load = mname (ras,begin_load);
image_module->load_increment = mname (ras,load_increment);
image_module->stop_load = mname (ras,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "tiff") == 0){
image_module->load = mname (tiff,load);
image_module->begin_load = mname (tiff,begin_load);
image_module->load_increment = mname (tiff,load_increment);
image_module->stop_load = mname (tiff,stop_load);
- return;
+ return TRUE;
}
if (strcmp (image_module->module_name, "xpm") == 0){
image_module->load = mname (xpm,load);
image_module->load_xpm_data = mname (xpm,load_xpm_data);
- return;
+ return TRUE;
}
+
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("Image type '%s' is not supported"),
+ image_module->module_name);
+
+ return FALSE;
}
@@ -495,7 +511,8 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module)
GdkPixbufModule *
-gdk_pixbuf_get_named_module (const char *name)
+gdk_pixbuf_get_named_module (const char *name,
+ GError **error)
{
int i;
@@ -504,11 +521,19 @@ gdk_pixbuf_get_named_module (const char *name)
return &(file_formats[i]);
}
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("Image type '%s' is not supported"),
+ name);
+
return NULL;
}
GdkPixbufModule *
-gdk_pixbuf_get_module (guchar *buffer, guint size)
+gdk_pixbuf_get_module (guchar *buffer, guint size,
+ const gchar *filename,
+ GError **error)
{
int i;
@@ -517,15 +542,30 @@ gdk_pixbuf_get_module (guchar *buffer, guint size)
return &(file_formats[i]);
}
+ if (filename)
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("Couldn't recognize the image file format for file '%s'"),
+ filename);
+ else
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("Unrecognized image file format"));
+
+
return NULL;
}
/**
* gdk_pixbuf_new_from_file:
* @filename: Name of file to load.
+ * @error: Return location for an error
*
* Creates a new pixbuf by loading an image from a file. The file format is
- * detected automatically.
+ * detected automatically. If NULL is returned, then @error will be set.
+ * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
*
* Return value: A newly-created pixbuf with a reference count of 1, or NULL if
* any of several error conditions occurred: the file could not be opened,
@@ -533,7 +573,8 @@ gdk_pixbuf_get_module (guchar *buffer, guint size)
* allocate the image buffer, or the image file contained invalid data.
**/
GdkPixbuf *
-gdk_pixbuf_new_from_file (const char *filename)
+gdk_pixbuf_new_from_file (const char *filename,
+ GError **error)
{
GdkPixbuf *pixbuf;
int size;
@@ -544,34 +585,82 @@ gdk_pixbuf_new_from_file (const char *filename)
g_return_val_if_fail (filename != NULL, NULL);
f = fopen (filename, "rb");
- if (!f)
+ if (!f) {
+ g_set_error (error,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
+ _("Failed to open file '%s': %s"),
+ filename, g_strerror (errno));
return NULL;
+ }
size = fread (&buffer, 1, sizeof (buffer), f);
if (size == 0) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Image file '%s' contains no data"),
+ filename);
+
fclose (f);
return NULL;
}
- image_module = gdk_pixbuf_get_module (buffer, size);
- if (!image_module) {
- g_warning ("Unable to find handler for file: %s", filename);
- fclose (f);
- return NULL;
- }
+ image_module = gdk_pixbuf_get_module (buffer, size, filename, error);
+ if (image_module == NULL) {
+ fclose (f);
+ return NULL;
+ }
if (image_module->module == NULL)
- gdk_pixbuf_load_module (image_module);
+ if (!gdk_pixbuf_load_module (image_module, error)) {
+ fclose (f);
+ return NULL;
+ }
if (image_module->load == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
+ _("Don't know how to load the image in file '%s'"),
+ filename);
+
fclose (f);
return NULL;
}
fseek (f, 0, SEEK_SET);
- pixbuf = (* image_module->load) (f);
+ pixbuf = (* image_module->load) (f, error);
fclose (f);
+ if (pixbuf == NULL && error != NULL && *error == NULL) {
+ /* I don't trust these crufty longjmp()'ing image libs
+ * to maintain proper error invariants, and I don't
+ * want user code to segfault as a result. We need to maintain
+ * the invariant that error gets set if NULL is returned.
+ */
+
+ g_warning ("Bug! gdk-pixbuf loader '%s' didn't set an error on failure.", image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Failed to load image '%s': reason not known, probably a corrupt image file"),
+ filename);
+
+ } else if (error != NULL && *error != NULL) {
+
+ /* Add the filename to the error message */
+ GError *e = *error;
+ gchar *old;
+
+ old = e->message;
+
+ e->message = g_strdup_printf (_("Failed to load image '%s': %s"),
+ filename, old);
+
+ g_free (old);
+ }
+
return pixbuf;
}
@@ -591,7 +680,7 @@ gdk_pixbuf_new_from_xpm_data (const char **data)
GdkPixbuf *pixbuf;
if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL)
- gdk_pixbuf_load_module (&file_formats[XPM_FILE_FORMAT_INDEX]);
+ gdk_pixbuf_load_module (&file_formats[XPM_FILE_FORMAT_INDEX], NULL);
if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
g_warning ("Can't find gdk-pixbuf module for parsing inline XPM data");
@@ -650,31 +739,26 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
gchar **values,
GError **error)
{
- int i;
GdkPixbufModule *image_module = NULL;
+
+ image_module = gdk_pixbuf_get_named_module (type, error);
+
+ if (image_module == NULL)
+ return FALSE;
- for (i = 0; file_formats[i].module_name; i++) {
- if (!strcmp (file_formats[i].module_name, type)) {
- image_module = &(file_formats[i]);
- break;
- }
- }
-
- if (!image_module) {
+ if (image_module->module == NULL)
+ if (!gdk_pixbuf_load_module (image_module, error))
+ return FALSE;
+
+ if (image_module->save == NULL) {
g_set_error (error,
GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
- _("This build of gdk-pixbuf does not support saving the image format: %s"), type);
+ GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
+ _("This build of gdk-pixbuf does not support saving the image format: %s"),
+ type);
return FALSE;
}
-
- if (image_module->module == NULL)
- gdk_pixbuf_load_module (image_module);
-
- g_return_val_if_fail (image_module->save != NULL, FALSE);
-
-
-
+
return (* image_module->save) (filehandle, pixbuf,
keys, values,
error);
@@ -691,7 +775,7 @@ gdk_pixbuf_real_save (GdkPixbuf *pixbuf,
*
* Saves pixbuf to a file in @type, which is currently "jpeg" or
* "png". If @error is set, FALSE will be returned. Possible errors include those
- * from #GdkPixbufErrorType and those from #GFileErrorType.
+ * in the #GDK_PIXBUF_ERROR domain and those in the #G_FILE_ERROR domain.
*
* The variable argument list should be NULL-terminated; if not empty,
* it should contain pairs of strings that modify the save
@@ -747,8 +831,7 @@ gdk_pixbuf_save (GdkPixbuf *pixbuf,
*
* Saves pixbuf to a file in @type, which is currently "jpeg" or "png".
* If @error is set, FALSE will be returned. See gdk_pixbuf_save () for more
- * details. Possible errors include those from #GdkPixbufErrorType and
- * those from #GFileErrorType.
+ * details.
*
* Return value: whether an error was set
**/
@@ -772,8 +855,8 @@ gdk_pixbuf_savev (GdkPixbuf *pixbuf,
if (f == NULL) {
g_set_error (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_IO,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
_("Failed to open '%s' for writing: %s"),
filename, g_strerror (errno));
return FALSE;
@@ -793,8 +876,8 @@ gdk_pixbuf_savev (GdkPixbuf *pixbuf,
if (fclose (f) < 0) {
g_set_error (error,
- GDK_PIXBUF_ERROR,
- GDK_PIXBUF_ERROR_IO,
+ G_FILE_ERROR,
+ g_file_error_from_errno (errno),
_("Failed to close '%s' while writing image, all data may not have been saved: %s"),
filename, g_strerror (errno));
return FALSE;
diff --git a/gdk-pixbuf/gdk-pixbuf-io.h b/gdk-pixbuf/gdk-pixbuf-io.h
index 3ce4d2f73..60046b8e7 100644
--- a/gdk-pixbuf/gdk-pixbuf-io.h
+++ b/gdk-pixbuf/gdk-pixbuf-io.h
@@ -55,7 +55,8 @@ struct _GdkPixbufModule {
char *module_name;
gboolean (* format_check) (guchar *buffer, int size);
GModule *module;
- GdkPixbuf *(* load) (FILE *f);
+ GdkPixbuf *(* load) (FILE *f,
+ GError **error);
GdkPixbuf *(* load_xpm_data) (const char **data);
/* Incremental loading */
@@ -64,26 +65,33 @@ struct _GdkPixbufModule {
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
void (* stop_load) (gpointer context);
gboolean (* load_increment) (gpointer context,
const guchar *buf,
- guint size);
+ guint size,
+ GError **error);
/* Animation loading */
- GdkPixbufAnimation *(* load_animation) (FILE *f);
+ GdkPixbufAnimation *(* load_animation) (FILE *f,
+ GError **error);
gboolean (* save) (FILE *f,
GdkPixbuf *pixbuf,
gchar **param_keys,
gchar **param_values,
- GError **err);
+ GError **error);
};
-GdkPixbufModule *gdk_pixbuf_get_module (guchar *buffer, guint size);
-GdkPixbufModule *gdk_pixbuf_get_named_module (const char *name);
-void gdk_pixbuf_load_module (GdkPixbufModule *image_module);
+GdkPixbufModule *gdk_pixbuf_get_module (guchar *buffer, guint size,
+ const gchar *filename,
+ GError **error);
+GdkPixbufModule *gdk_pixbuf_get_named_module (const char *name,
+ GError **error);
+gboolean gdk_pixbuf_load_module (GdkPixbufModule *image_module,
+ GError **error);
diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c
index 5f4320f22..42aec5d4c 100644
--- a/gdk-pixbuf/gdk-pixbuf-loader.c
+++ b/gdk-pixbuf/gdk-pixbuf-loader.c
@@ -338,20 +338,32 @@ gdk_pixbuf_loader_animation_done (GdkPixbuf *pixbuf,
}
static gint
-gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader, const char *image_type)
+gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader,
+ const char *image_type,
+ GError **error)
{
GdkPixbufLoaderPrivate *priv = loader->private;
- if(image_type)
- priv->image_module = gdk_pixbuf_get_named_module (image_type);
+ if (image_type)
+ {
+ priv->image_module = gdk_pixbuf_get_named_module (image_type,
+ error);
+ }
else
- priv->image_module = gdk_pixbuf_get_module (priv->header_buf, priv->header_buf_offset);
+ {
+ g_return_val_if_fail (priv->header_buf_offset > 0, 0);
+ priv->image_module = gdk_pixbuf_get_module (priv->header_buf,
+ priv->header_buf_offset,
+ NULL,
+ error);
+ }
if (priv->image_module == NULL)
return 0;
if (priv->image_module->module == NULL)
- gdk_pixbuf_load_module (priv->image_module);
+ if (!gdk_pixbuf_load_module (priv->image_module, error))
+ return 0;
if (priv->image_module->module == NULL)
return 0;
@@ -360,8 +372,12 @@ gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader, const char *image_type)
(priv->image_module->stop_load == NULL) ||
(priv->image_module->load_increment == NULL))
{
- g_warning (G_STRLOC ": module %s does not support incremental loading.\n",
- priv->image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
+ _("Incremental loading of image type '%s' is not supported"),
+ image_type);
+
return 0;
}
@@ -369,16 +385,33 @@ gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader, const char *image_type)
gdk_pixbuf_loader_update,
gdk_pixbuf_loader_frame_done,
gdk_pixbuf_loader_animation_done,
- loader);
+ loader,
+ error);
if (priv->context == NULL)
{
- g_warning (G_STRLOC ": Failed to begin progressive load");
+ /* Defense against broken loaders; DO NOT take this as a GError
+ * example
+ */
+ if (error && *error == NULL)
+ {
+ g_warning ("Bug! loader '%s' didn't set an error on failure",
+ priv->image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Internal error: Image loader module '%s'"
+ " failed to begin loading an image, but didn't"
+ " give a reason for the failure"),
+ priv->image_module->module_name);
+
+ }
+
return 0;
}
if (priv->header_buf_offset
- && priv->image_module->load_increment (priv->context, priv->header_buf, priv->header_buf_offset))
+ && priv->image_module->load_increment (priv->context, priv->header_buf, priv->header_buf_offset, error))
return priv->header_buf_offset;
return 0;
@@ -387,7 +420,8 @@ gdk_pixbuf_loader_load_module (GdkPixbufLoader *loader, const char *image_type)
static int
gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
const guchar *buf,
- gsize count)
+ gsize count,
+ GError **error)
{
gint n_bytes;
GdkPixbufLoaderPrivate *priv = loader->private;
@@ -399,7 +433,7 @@ gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
if (priv->header_buf_offset >= LOADER_HEADER_SIZE)
{
- if (gdk_pixbuf_loader_load_module (loader, NULL) == 0)
+ if (gdk_pixbuf_loader_load_module (loader, NULL, error) == 0)
return 0;
}
@@ -411,11 +445,14 @@ gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
* @loader: A pixbuf loader.
* @buf: Pointer to image data.
* @count: Length of the @buf buffer in bytes.
+ * @error: return location for errors
*
- * This will cause a pixbuf loader to parse the next @count bytes of an image.
- * It will return TRUE if the data was loaded successfully, and FALSE if an
- * error occurred. In the latter case, the loader will be closed, and will not
- * accept further writes.
+ * This will cause a pixbuf loader to parse the next @count bytes of
+ * an image. It will return TRUE if the data was loaded successfully,
+ * and FALSE if an error occurred. In the latter case, the loader
+ * will be closed, and will not accept further writes. If FALSE is
+ * returned, @error will be set to an error from the #GDK_PIXBUF_ERROR
+ * domain.
*
* Return value: #TRUE if the write was successful, or #FALSE if the loader
* cannot parse the buffer.
@@ -423,7 +460,8 @@ gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader,
gboolean
gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
const guchar *buf,
- gsize count)
+ gsize count,
+ GError **error)
{
GdkPixbufLoaderPrivate *priv;
@@ -442,7 +480,7 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
{
gint eaten;
- eaten = gdk_pixbuf_loader_eat_header_write(loader, buf, count);
+ eaten = gdk_pixbuf_loader_eat_header_write(loader, buf, count, error);
if (eaten <= 0)
return FALSE;
@@ -451,8 +489,27 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
}
if (count > 0 && priv->image_module->load_increment)
- return priv->image_module->load_increment (priv->context, buf, count);
-
+ {
+ gboolean retval;
+ retval = priv->image_module->load_increment (priv->context, buf, count,
+ error);
+ if (!retval && error && *error == NULL)
+ {
+ /* Fix up busted image loader */
+ g_warning ("Bug! loader '%s' didn't set an error on failure",
+ priv->image_module->module_name);
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Internal error: Image loader module '%s'"
+ " failed to begin loading an image, but didn't"
+ " give a reason for the failure"),
+ priv->image_module->module_name);
+ }
+
+ return retval;
+ }
+
return TRUE;
}
@@ -477,13 +534,22 @@ gdk_pixbuf_loader_new (void)
* Return value: A newly-created pixbuf loader.
**/
GdkPixbufLoader *
-gdk_pixbuf_loader_new_with_type (const char *image_type)
+gdk_pixbuf_loader_new_with_type (const char *image_type,
+ GError **error)
{
GdkPixbufLoader *retval;
-
+ GError *tmp;
+
retval = g_object_new (GDK_TYPE_PIXBUF_LOADER, NULL);
- gdk_pixbuf_loader_load_module(retval, image_type);
+ tmp = NULL;
+ gdk_pixbuf_loader_load_module(retval, image_type, &tmp);
+ if (tmp != NULL)
+ {
+ g_propagate_error (error, tmp);
+ g_object_unref (G_OBJECT (retval));
+ return NULL;
+ }
return retval;
}
@@ -579,7 +645,7 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader)
/* We have less the 128 bytes in the image. Flush it, and keep going. */
if (priv->image_module == NULL)
- gdk_pixbuf_loader_load_module (loader, NULL);
+ gdk_pixbuf_loader_load_module (loader, NULL, NULL);
if (priv->image_module && priv->image_module->stop_load)
priv->image_module->stop_load (priv->context);
diff --git a/gdk-pixbuf/gdk-pixbuf-loader.h b/gdk-pixbuf/gdk-pixbuf-loader.h
index c3d6d6f95..402b69725 100644
--- a/gdk-pixbuf/gdk-pixbuf-loader.h
+++ b/gdk-pixbuf/gdk-pixbuf-loader.h
@@ -72,10 +72,12 @@ struct _GdkPixbufLoaderClass
GtkType gdk_pixbuf_loader_get_type (void) G_GNUC_CONST;
GdkPixbufLoader * gdk_pixbuf_loader_new (void);
-GdkPixbufLoader * gdk_pixbuf_loader_new_with_type (const char *image_type);
+GdkPixbufLoader * gdk_pixbuf_loader_new_with_type (const char *image_type,
+ GError **error);
gboolean gdk_pixbuf_loader_write (GdkPixbufLoader *loader,
const guchar *buf,
- gsize count);
+ gsize count,
+ GError **error);
GdkPixbuf * gdk_pixbuf_loader_get_pixbuf (GdkPixbufLoader *loader);
GdkPixbufAnimation * gdk_pixbuf_loader_get_animation (GdkPixbufLoader *loader);
void gdk_pixbuf_loader_close (GdkPixbufLoader *loader);
diff --git a/gdk-pixbuf/gdk-pixbuf-util.c b/gdk-pixbuf/gdk-pixbuf-util.c
index 36fc29750..bee4fb5bb 100644
--- a/gdk-pixbuf/gdk-pixbuf-util.c
+++ b/gdk-pixbuf/gdk-pixbuf-util.c
@@ -23,6 +23,7 @@
#include <config.h>
#include "gdk-pixbuf-private.h"
+#include <string.h>
diff --git a/gdk-pixbuf/gdk-pixbuf.h b/gdk-pixbuf/gdk-pixbuf.h
index a61dc9366..e87737277 100644
--- a/gdk-pixbuf/gdk-pixbuf.h
+++ b/gdk-pixbuf/gdk-pixbuf.h
@@ -39,8 +39,8 @@ extern "C" {
/* Alpha compositing mode */
typedef enum
{
- GDK_PIXBUF_ALPHA_BILEVEL,
- GDK_PIXBUF_ALPHA_FULL
+ GDK_PIXBUF_ALPHA_BILEVEL,
+ GDK_PIXBUF_ALPHA_FULL
} GdkPixbufAlphaMode;
/* Color spaces; right now only RGB is supported.
@@ -71,14 +71,18 @@ typedef void (* GdkPixbufDestroyNotify) (guchar *pixels, gpointer data);
#define GDK_PIXBUF_ERROR gdk_pixbuf_error_quark ()
typedef enum {
- /* some kind of failure reading or writing files */
- GDK_PIXBUF_ERROR_IO,
+ /* image data hosed */
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ /* no mem to load image */
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
/* bad option value passed to save routine */
GDK_PIXBUF_ERROR_BAD_OPTION_VALUE,
/* unsupported image type (sort of an ENOSYS) */
GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ /* unsupported operation (load, save) for image type */
+ GDK_PIXBUF_ERROR_UNSUPPORTED_OPERATION,
GDK_PIXBUF_ERROR_FAILED
-} GdkPixbufErrorType;
+} GdkPixbufError;
GQuark gdk_pixbuf_error_quark () G_GNUC_CONST;
@@ -114,7 +118,8 @@ GdkPixbuf *gdk_pixbuf_copy (const GdkPixbuf *pixbuf);
/* Simple loading */
-GdkPixbuf *gdk_pixbuf_new_from_file (const char *filename);
+GdkPixbuf *gdk_pixbuf_new_from_file (const char *filename,
+ GError **error);
GdkPixbuf *gdk_pixbuf_new_from_data (const guchar *data,
GdkColorspace colorspace,
@@ -130,23 +135,24 @@ GdkPixbuf *gdk_pixbuf_new_from_xpm_data (const char **data);
/* Read an inline pixbuf */
GdkPixbuf *gdk_pixbuf_new_from_inline (const guchar *inline_pixbuf,
gboolean copy_pixels,
- int length);
+ int length,
+ GError **error);
/* Saving */
gboolean gdk_pixbuf_save (GdkPixbuf *pixbuf,
const char *filename,
- const char *format,
- GError **err,
+ const char *type,
+ GError **error,
...);
gboolean gdk_pixbuf_savev (GdkPixbuf *pixbuf,
const char *filename,
- const char *format,
+ const char *type,
char **option_keys,
char **option_values,
- GError **err);
+ GError **error);
/* Adding an alpha channel */
GdkPixbuf *gdk_pixbuf_add_alpha (const GdkPixbuf *pixbuf, gboolean substitute_color,
@@ -248,7 +254,8 @@ typedef enum {
GType gdk_pixbuf_animation_get_type (void) G_GNUC_CONST;
-GdkPixbufAnimation *gdk_pixbuf_animation_new_from_file (const char *filename);
+GdkPixbufAnimation *gdk_pixbuf_animation_new_from_file (const char *filename,
+ GError **error);
GdkPixbufAnimation *gdk_pixbuf_animation_ref (GdkPixbufAnimation *animation);
void gdk_pixbuf_animation_unref (GdkPixbufAnimation *animation);
diff --git a/gdk-pixbuf/gnome-canvas-pixbuf.c b/gdk-pixbuf/gnome-canvas-pixbuf.c
deleted file mode 100644
index a6372b997..000000000
--- a/gdk-pixbuf/gnome-canvas-pixbuf.c
+++ /dev/null
@@ -1,841 +0,0 @@
-/* GNOME libraries - GdkPixbuf item for the GNOME canvas
- *
- * Copyright (C) 1999 The Free Software Foundation
- *
- * Author: Federico Mena-Quintero <federico@gimp.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#include <config.h>
-#include <math.h>
-#include <libgnomeui/gnome-canvas.h>
-#include <libgnomeui/gnome-canvas-util.h>
-#include <libart_lgpl/art_rgb_affine.h>
-#include <libart_lgpl/art_rgb_rgba_affine.h>
-#include "gdk-pixbuf-private.h"
-#include "gnome-canvas-pixbuf.h"
-
-
-
-/* Private part of the GnomeCanvasPixbuf structure */
-typedef struct {
- /* Our gdk-pixbuf */
- GdkPixbuf *pixbuf;
-
- /* Width value */
- double width;
-
- /* Height value */
- double height;
-
- /* X translation */
- double x;
-
- /* Y translation */
- double y;
-
- /* Whether dimensions are set and whether they are in pixels or units */
- guint width_set : 1;
- guint width_in_pixels : 1;
- guint height_set : 1;
- guint height_in_pixels : 1;
- guint x_in_pixels : 1;
- guint y_in_pixels : 1;
-
- /* Whether the pixbuf has changed */
- guint need_pixbuf_update : 1;
-
- /* Whether the transformation or size have changed */
- guint need_xform_update : 1;
-} PixbufPrivate;
-
-
-
-/* Object argument IDs */
-enum {
- ARG_0,
- ARG_PIXBUF,
- ARG_WIDTH,
- ARG_WIDTH_SET,
- ARG_WIDTH_IN_PIXELS,
- ARG_HEIGHT,
- ARG_HEIGHT_SET,
- ARG_HEIGHT_IN_PIXELS,
- ARG_X,
- ARG_X_IN_PIXELS,
- ARG_Y,
- ARG_Y_IN_PIXELS
-};
-
-static void gnome_canvas_pixbuf_class_init (GnomeCanvasPixbufClass *class);
-static void gnome_canvas_pixbuf_init (GnomeCanvasPixbuf *cpb);
-static void gnome_canvas_pixbuf_destroy (GtkObject *object);
-static void gnome_canvas_pixbuf_set_arg (GtkObject *object, GtkArg *arg, guint arg_id);
-static void gnome_canvas_pixbuf_get_arg (GtkObject *object, GtkArg *arg, guint arg_id);
-
-static void gnome_canvas_pixbuf_update (GnomeCanvasItem *item, double *affine,
- ArtSVP *clip_path, int flags);
-static void gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
- int x, int y, int width, int height);
-static void gnome_canvas_pixbuf_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf);
-static double gnome_canvas_pixbuf_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
- GnomeCanvasItem **actual_item);
-static void gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item,
- double *x1, double *y1, double *x2, double *y2);
-
-static GnomeCanvasItemClass *parent_class;
-
-
-
-/**
- * gnome_canvas_pixbuf_get_type:
- * @void:
- *
- * Registers the #GnomeCanvasPixbuf class if necessary, and returns the type ID
- * associated to it.
- *
- * Return value: The type ID of the #GnomeCanvasPixbuf class.
- **/
-GtkType
-gnome_canvas_pixbuf_get_type (void)
-{
- static GtkType canvas_pixbuf_type = 0;
-
- if (!canvas_pixbuf_type) {
- static const GtkTypeInfo canvas_pixbuf_info = {
- "GnomeCanvasPixbuf",
- sizeof (GnomeCanvasPixbuf),
- sizeof (GnomeCanvasPixbufClass),
- (GtkClassInitFunc) gnome_canvas_pixbuf_class_init,
- (GtkObjectInitFunc) gnome_canvas_pixbuf_init,
- NULL, /* reserved_1 */
- NULL, /* reserved_2 */
- (GtkClassInitFunc) NULL
- };
-
- canvas_pixbuf_type = gtk_type_unique (gnome_canvas_item_get_type (),
- &canvas_pixbuf_info);
- }
-
- return canvas_pixbuf_type;
-}
-
-/* Class initialization function for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_class_init (GnomeCanvasPixbufClass *class)
-{
- GtkObjectClass *object_class;
- GnomeCanvasItemClass *item_class;
-
- object_class = (GtkObjectClass *) class;
- item_class = (GnomeCanvasItemClass *) class;
-
- parent_class = gtk_type_class (gnome_canvas_item_get_type ());
-
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::pixbuf",
- GTK_TYPE_POINTER, GTK_ARG_READWRITE, ARG_PIXBUF);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::width",
- GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_WIDTH);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::width_set",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_WIDTH_SET);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::width_in_pixels",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_WIDTH_IN_PIXELS);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::height",
- GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_HEIGHT);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::height_set",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HEIGHT_SET);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::height_in_pixels",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_HEIGHT_IN_PIXELS);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::x",
- GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_X);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::x_in_pixels",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_X_IN_PIXELS);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::y",
- GTK_TYPE_DOUBLE, GTK_ARG_READWRITE, ARG_Y);
- gtk_object_add_arg_type ("GnomeCanvasPixbuf::y_in_pixels",
- GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_Y_IN_PIXELS);
-
-
- object_class->destroy = gnome_canvas_pixbuf_destroy;
- object_class->set_arg = gnome_canvas_pixbuf_set_arg;
- object_class->get_arg = gnome_canvas_pixbuf_get_arg;
-
- item_class->update = gnome_canvas_pixbuf_update;
- item_class->draw = gnome_canvas_pixbuf_draw;
- item_class->render = gnome_canvas_pixbuf_render;
- item_class->point = gnome_canvas_pixbuf_point;
- item_class->bounds = gnome_canvas_pixbuf_bounds;
-}
-
-/* Object initialization function for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_init (GnomeCanvasPixbuf *gcp)
-{
- PixbufPrivate *priv;
-
- priv = g_new0 (PixbufPrivate, 1);
- gcp->priv = priv;
-
- priv->width = 0.0;
- priv->height = 0.0;
- priv->x = 0.0;
- priv->y = 0.0;
-}
-
-/* Destroy handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_destroy (GtkObject *object)
-{
- GnomeCanvasItem *item;
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
-
- g_return_if_fail (object != NULL);
- g_return_if_fail (GNOME_IS_CANVAS_PIXBUF (object));
-
- item = GNOME_CANVAS_ITEM (object);
- gcp = (GNOME_CANVAS_PIXBUF (object));
- priv = gcp->priv;
-
- gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
-
- if (priv->pixbuf)
- gdk_pixbuf_unref (priv->pixbuf);
-
- g_free (priv);
-
- if (GTK_OBJECT_CLASS (parent_class)->destroy)
- (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
-}
-
-
-
-/* Set_arg handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_set_arg (GtkObject *object, GtkArg *arg, guint arg_id)
-{
- GnomeCanvasItem *item;
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
- GdkPixbuf *pixbuf;
- double val;
-
- item = GNOME_CANVAS_ITEM (object);
- gcp = GNOME_CANVAS_PIXBUF (object);
- priv = gcp->priv;
-
- switch (arg_id) {
- case ARG_PIXBUF:
- pixbuf = GTK_VALUE_POINTER (*arg);
- if (pixbuf != priv->pixbuf) {
- if (pixbuf) {
- g_return_if_fail (pixbuf->colorspace == GDK_COLORSPACE_RGB);
- g_return_if_fail (pixbuf->n_channels == 3 || pixbuf->n_channels == 4);
- g_return_if_fail (pixbuf->bits_per_sample == 8);
-
- gdk_pixbuf_ref (pixbuf);
- }
-
- if (priv->pixbuf)
- gdk_pixbuf_unref (priv->pixbuf);
-
- priv->pixbuf = pixbuf;
- }
-
- priv->need_pixbuf_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_WIDTH:
- val = GTK_VALUE_DOUBLE (*arg);
- g_return_if_fail (val >= 0.0);
- priv->width = val;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_WIDTH_SET:
- priv->width_set = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_WIDTH_IN_PIXELS:
- priv->width_in_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_HEIGHT:
- val = GTK_VALUE_DOUBLE (*arg);
- g_return_if_fail (val >= 0.0);
- priv->height = val;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_HEIGHT_SET:
- priv->height_set = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_HEIGHT_IN_PIXELS:
- priv->height_in_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_X:
- priv->x = GTK_VALUE_DOUBLE (*arg);
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_X_IN_PIXELS:
- priv->x_in_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_Y:
- priv->y = GTK_VALUE_DOUBLE (*arg);
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- case ARG_Y_IN_PIXELS:
- priv->y_in_pixels = GTK_VALUE_BOOL (*arg) ? TRUE : FALSE;
- priv->need_xform_update = TRUE;
- gnome_canvas_item_request_update (item);
- break;
-
- default:
- break;
- }
-}
-
-/* Get_arg handler for the pixbuf canvasi item */
-static void
-gnome_canvas_pixbuf_get_arg (GtkObject *object, GtkArg *arg, guint arg_id)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
-
- gcp = GNOME_CANVAS_PIXBUF (object);
- priv = gcp->priv;
-
- switch (arg_id) {
- case ARG_PIXBUF:
- GTK_VALUE_POINTER (*arg) = priv->pixbuf;
- break;
-
- case ARG_WIDTH:
- GTK_VALUE_DOUBLE (*arg) = priv->width;
- break;
-
- case ARG_WIDTH_SET:
- GTK_VALUE_BOOL (*arg) = priv->width_set;
- break;
-
- case ARG_WIDTH_IN_PIXELS:
- GTK_VALUE_BOOL (*arg) = priv->width_in_pixels;
- break;
-
- case ARG_HEIGHT:
- GTK_VALUE_DOUBLE (*arg) = priv->height;
- break;
-
- case ARG_HEIGHT_SET:
- GTK_VALUE_BOOL (*arg) = priv->height_set;
- break;
-
- case ARG_HEIGHT_IN_PIXELS:
- GTK_VALUE_BOOL (*arg) = priv->height_in_pixels;
- break;
-
- case ARG_X:
- GTK_VALUE_DOUBLE (*arg) = priv->x;
- break;
-
- case ARG_X_IN_PIXELS:
- GTK_VALUE_BOOL (*arg) = priv->x_in_pixels;
- break;
-
- case ARG_Y:
- GTK_VALUE_DOUBLE (*arg) = priv->y;
- break;
-
- case ARG_Y_IN_PIXELS:
- GTK_VALUE_BOOL (*arg) = priv->y_in_pixels;
- break;
-
- default:
- arg->type = GTK_TYPE_INVALID;
- break;
- }
-}
-
-
-
-/* Bounds and utilities */
-
-/* Computes the amount by which the unit horizontal and vertical vectors will be
- * scaled by an affine transformation.
- */
-static void
-compute_xform_scaling (double *affine, ArtPoint *i_c, ArtPoint *j_c)
-{
- ArtPoint orig, orig_c;
- ArtPoint i, j;
-
- /* Origin */
-
- orig.x = 0.0;
- orig.y = 0.0;
- art_affine_point (&orig_c, &orig, affine);
-
- /* Horizontal and vertical vectors */
-
- i.x = 1.0;
- i.y = 0.0;
- art_affine_point (i_c, &i, affine);
- i_c->x -= orig_c.x;
- i_c->y -= orig_c.y;
-
- j.x = 0.0;
- j.y = 1.0;
- art_affine_point (j_c, &j, affine);
- j_c->x -= orig_c.x;
- j_c->y -= orig_c.y;
-}
-
-/* computes the addtional resolution dependent affine needed to
- * fit the image within its viewport defined by x,y,width and height
- * args
- */
-static void
-compute_viewport_affine (GnomeCanvasPixbuf *gcp, double *viewport_affine, double *i2c)
-{
- PixbufPrivate *priv;
- ArtPoint i_c, j_c;
- double i_len, j_len;
- double si_len, sj_len;
- double ti_len, tj_len;
- double scale[6], translate[6];
- double w, h;
-
- priv = gcp->priv;
-
- /* Compute scaling vectors and required width/height */
-
- compute_xform_scaling (i2c, &i_c, &j_c);
-
- i_len = sqrt (i_c.x * i_c.x + i_c.y * i_c.y);
- j_len = sqrt (j_c.x * j_c.x + j_c.y * j_c.y);
-
- if (priv->width_set)
- w = priv->width;
- else
- w = priv->pixbuf->width;
-
- if (priv->height_set)
- h = priv->height;
- else
- h = priv->pixbuf->height;
-
- /* Convert i_len and j_len into scaling factors */
-
- if (priv->width_in_pixels) {
- if (i_len > GNOME_CANVAS_EPSILON)
- si_len = 1.0 / i_len;
- else
- si_len = 0.0;
- } else
- si_len = 1.0;
-
- si_len *= w / priv->pixbuf->width;
-
- if (priv->height_in_pixels) {
- if (j_len > GNOME_CANVAS_EPSILON)
- sj_len = 1.0 / j_len;
- else
- sj_len = 0.0;
- } else
- sj_len = 1.0;
-
- sj_len *= h / priv->pixbuf->height;
-
- /* Calculate translation offsets */
-
- if (priv->x_in_pixels) {
- if (i_len > GNOME_CANVAS_EPSILON)
- ti_len = 1.0 / i_len;
- else
- ti_len = 0.0;
- } else
- ti_len = 1.0;
-
- ti_len *= priv->x;
-
- if (priv->y_in_pixels) {
- if (j_len > GNOME_CANVAS_EPSILON)
- tj_len = 1.0 / j_len;
- else
- tj_len = 0.0;
- } else
- tj_len = 1.0;
-
- tj_len *= priv->y;
-
- /* Compute the final affine */
-
- art_affine_scale (scale, si_len, sj_len);
- art_affine_translate (translate, ti_len, tj_len);
- art_affine_multiply (viewport_affine, scale, translate);
-}
-
-/* Computes the affine transformation with which the pixbuf needs to be
- * transformed to render it on the canvas. This is not the same as the
- * item_to_canvas transformation because we may need to scale the pixbuf
- * by some other amount.
- */
-static void
-compute_render_affine (GnomeCanvasPixbuf *gcp, double *render_affine, double *i2c)
-{
- double viewport_affine[6];
-
- compute_viewport_affine (gcp, viewport_affine, i2c);
- art_affine_multiply (render_affine, viewport_affine, i2c);
-}
-
-/* Recomputes the bounding box of a pixbuf canvas item. The horizontal and
- * vertical dimensions may be specified in units or pixels, separately, so we
- * have to compute the components individually for each dimension.
- */
-static void
-recompute_bounding_box (GnomeCanvasPixbuf *gcp)
-{
- GnomeCanvasItem *item;
- PixbufPrivate *priv;
- double i2c[6], render_affine[6];
- ArtDRect rect;
-
- item = GNOME_CANVAS_ITEM (gcp);
- priv = gcp->priv;
-
- if (!priv->pixbuf) {
- item->x1 = item->y1 = item->x2 = item->y2 = 0.0;
- return;
- }
-
- rect.x0 = 0.0;
- rect.x1 = priv->pixbuf->width;
-
- rect.y0 = 0.0;
- rect.y1 = priv->pixbuf->height;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- compute_render_affine (gcp, render_affine, i2c);
- art_drect_affine_transform (&rect, &rect, render_affine);
-
- item->x1 = floor (rect.x0);
- item->y1 = floor (rect.y0);
- item->x2 = ceil (rect.x1);
- item->y2 = ceil (rect.y1);
-}
-
-
-
-/* Update sequence */
-
-/* Update handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_update (GnomeCanvasItem *item, double *affine, ArtSVP *clip_path, int flags)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
-
- gcp = GNOME_CANVAS_PIXBUF (item);
- priv = gcp->priv;
-
- if (parent_class->update)
- (* parent_class->update) (item, affine, clip_path, flags);
-
- if (((flags & GNOME_CANVAS_UPDATE_VISIBILITY)
- && !(GTK_OBJECT_FLAGS (item) & GNOME_CANVAS_ITEM_VISIBLE))
- || (flags & GNOME_CANVAS_UPDATE_AFFINE)
- || priv->need_pixbuf_update
- || priv->need_xform_update)
- gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
-
- /* If we need a pixbuf update, or if the item changed visibility to
- * shown, recompute the bounding box.
- */
- if (priv->need_pixbuf_update
- || priv->need_xform_update
- || ((flags & GNOME_CANVAS_UPDATE_VISIBILITY)
- && (GTK_OBJECT_FLAGS (gcp) & GNOME_CANVAS_ITEM_VISIBLE))
- || (flags & GNOME_CANVAS_UPDATE_AFFINE)) {
- recompute_bounding_box (gcp);
- gnome_canvas_request_redraw (item->canvas, item->x1, item->y1, item->x2, item->y2);
- priv->need_pixbuf_update = FALSE;
- priv->need_xform_update = FALSE;
- }
-}
-
-
-
-/* Rendering */
-
-/* This is private to libart, but we need it. Sigh. */
-extern void art_rgb_affine_run (int *p_x0, int *p_x1, int y, int src_width, int src_height,
- const double affine[6]);
-
-/* Fills the specified buffer with the transformed version of a pixbuf */
-static void
-transform_pixbuf (guchar *dest, int x, int y, int width, int height, int rowstride,
- GdkPixbuf *pixbuf, double *affine)
-{
- int xx, yy;
- double inv[6];
- guchar *src, *d;
- ArtPoint src_p, dest_p;
- int run_x1, run_x2;
- int src_x, src_y;
- int i;
-
- art_affine_invert (inv, affine);
-
- for (yy = 0; yy < height; yy++) {
- dest_p.y = y + yy + 0.5;
-
- run_x1 = x;
- run_x2 = x + width;
- art_rgb_affine_run (&run_x1, &run_x2, yy + y,
- pixbuf->width, pixbuf->height,
- inv);
-
- d = dest + yy * rowstride + (run_x1 - x) * 4;
-
- for (xx = run_x1; xx < run_x2; xx++) {
- dest_p.x = xx + 0.5;
- art_affine_point (&src_p, &dest_p, inv);
- src_x = floor (src_p.x);
- src_y = floor (src_p.y);
-
- src = pixbuf->pixels + src_y * pixbuf->rowstride + src_x * pixbuf->n_channels;
-
- for (i = 0; i < pixbuf->n_channels; i++)
- *d++ = *src++;
-
- if (!pixbuf->has_alpha)
- *d++ = 255; /* opaque */
- }
- }
-}
-
-/* Draw handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_draw (GnomeCanvasItem *item, GdkDrawable *drawable,
- int x, int y, int width, int height)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
- double i2c[6], render_affine[6];
- guchar *buf;
- GdkPixbuf *pixbuf;
- ArtIRect p_rect, a_rect, d_rect;
- int w, h;
-
- gcp = GNOME_CANVAS_PIXBUF (item);
- priv = gcp->priv;
-
- if (!priv->pixbuf)
- return;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- compute_render_affine (gcp, render_affine, i2c);
-
- /* Compute the area we need to repaint */
-
- p_rect.x0 = item->x1;
- p_rect.y0 = item->y1;
- p_rect.x1 = item->x2;
- p_rect.y1 = item->y2;
-
- a_rect.x0 = x;
- a_rect.y0 = y;
- a_rect.x1 = x + width;
- a_rect.y1 = y + height;
-
- art_irect_intersect (&d_rect, &p_rect, &a_rect);
- if (art_irect_empty (&d_rect))
- return;
-
- /* Create a temporary buffer and transform the pixbuf there */
-
- w = d_rect.x1 - d_rect.x0;
- h = d_rect.y1 - d_rect.y0;
-
- buf = g_new0 (guchar, w * h * 4);
- transform_pixbuf (buf,
- d_rect.x0, d_rect.y0,
- w, h,
- w * 4,
- priv->pixbuf, render_affine);
-
- pixbuf = gdk_pixbuf_new_from_data (buf, GDK_COLORSPACE_RGB, TRUE, 8, w, h, w * 4, NULL, NULL);
-
- gdk_pixbuf_render_to_drawable_alpha (pixbuf, drawable,
- 0, 0,
- d_rect.x0 - x, d_rect.y0 - y,
- w, h,
- GDK_PIXBUF_ALPHA_BILEVEL,
- 128,
- GDK_RGB_DITHER_MAX,
- d_rect.x0, d_rect.y0);
-
- gdk_pixbuf_unref (pixbuf);
- g_free (buf);
-}
-
-/* Render handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_render (GnomeCanvasItem *item, GnomeCanvasBuf *buf)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
- double i2c[6], render_affine[6];
-
- gcp = GNOME_CANVAS_PIXBUF (item);
- priv = gcp->priv;
-
- if (!priv->pixbuf)
- return;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- compute_render_affine (gcp, render_affine, i2c);
- gnome_canvas_buf_ensure_buf (buf);
-
- if (priv->pixbuf->has_alpha)
- art_rgb_rgba_affine (buf->buf,
- buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
- buf->buf_rowstride,
- priv->pixbuf->pixels,
- priv->pixbuf->width, priv->pixbuf->height,
- priv->pixbuf->rowstride,
- render_affine,
- ART_FILTER_NEAREST,
- NULL);
- else
- art_rgb_affine (buf->buf,
- buf->rect.x0, buf->rect.y0, buf->rect.x1, buf->rect.y1,
- buf->buf_rowstride,
- priv->pixbuf->pixels,
- priv->pixbuf->width, priv->pixbuf->height,
- priv->pixbuf->rowstride,
- render_affine,
- ART_FILTER_NEAREST,
- NULL);
-
- buf->is_bg = FALSE;
-}
-
-
-
-/* Point handler for the pixbuf canvas item */
-static double
-gnome_canvas_pixbuf_point (GnomeCanvasItem *item, double x, double y, int cx, int cy,
- GnomeCanvasItem **actual_item)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
- double i2c[6], render_affine[6], inv[6];
- ArtPoint c, p;
- int px, py;
- double no_hit;
- guchar *src;
-
- gcp = GNOME_CANVAS_PIXBUF (item);
- priv = gcp->priv;
-
- *actual_item = item;
-
- no_hit = item->canvas->pixels_per_unit * 2 + 10;
-
- if (!priv->pixbuf)
- return no_hit;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- compute_render_affine (gcp, render_affine, i2c);
- art_affine_invert (inv, render_affine);
-
- c.x = cx;
- c.y = cy;
- art_affine_point (&p, &c, inv);
- px = p.x;
- py = p.y;
-
- if (px < 0 || px >= priv->pixbuf->width || py < 0 || py >= priv->pixbuf->height)
- return no_hit;
-
- if (!priv->pixbuf->has_alpha)
- return 0.0;
-
- src = priv->pixbuf->pixels + py * priv->pixbuf->rowstride + px * priv->pixbuf->n_channels;
-
- if (src[3] < 128)
- return no_hit;
- else
- return 0.0;
-}
-
-
-
-/* Bounds handler for the pixbuf canvas item */
-static void
-gnome_canvas_pixbuf_bounds (GnomeCanvasItem *item, double *x1, double *y1, double *x2, double *y2)
-{
- GnomeCanvasPixbuf *gcp;
- PixbufPrivate *priv;
- double i2c[6], viewport_affine[6];
- ArtDRect rect;
-
- gcp = GNOME_CANVAS_PIXBUF (item);
- priv = gcp->priv;
-
- if (!priv->pixbuf) {
- *x1 = *y1 = *x2 = *y2 = 0.0;
- return;
- }
-
- rect.x0 = 0.0;
- rect.x1 = priv->pixbuf->width;
-
- rect.y0 = 0.0;
- rect.y1 = priv->pixbuf->height;
-
- gnome_canvas_item_i2c_affine (item, i2c);
- compute_viewport_affine (gcp, viewport_affine, i2c);
- art_drect_affine_transform (&rect, &rect, viewport_affine);
-
- *x1 = rect.x0;
- *y1 = rect.y0;
- *x2 = rect.x1;
- *y2 = rect.y1;
-}
diff --git a/gdk-pixbuf/gnome-canvas-pixbuf.h b/gdk-pixbuf/gnome-canvas-pixbuf.h
deleted file mode 100644
index 822f5899f..000000000
--- a/gdk-pixbuf/gnome-canvas-pixbuf.h
+++ /dev/null
@@ -1,64 +0,0 @@
-/* GNOME libraries - GdkPixbuf item for the GNOME canvas
- *
- * Copyright (C) 1999 The Free Software Foundation
- *
- * Author: Federico Mena-Quintero <federico@gimp.org>
- *
- * This library is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 2 of the License, or (at your option) any later version.
- *
- * This library is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with this library; if not, write to the
- * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
- * Boston, MA 02111-1307, USA.
- */
-
-#ifndef GNOME_CANVAS_PIXBUF_H
-#define GNOME_CANVAS_PIXBUF_H
-
-#include <libgnome/gnome-defs.h>
-#include <libgnomeui/gnome-canvas.h>
-
-BEGIN_GNOME_DECLS
-
-
-
-#define GNOME_TYPE_CANVAS_PIXBUF (gnome_canvas_pixbuf_get_type ())
-#define GNOME_CANVAS_PIXBUF(obj) (GTK_CHECK_CAST ((obj), \
- GNOME_TYPE_CANVAS_PIXBUF, GnomeCanvasPixbuf))
-#define GNOME_CANVAS_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_CAST ((klass), \
- GNOME_TYPE_CANVAS_PIXBUF, GnomeCanvasPixbufClass))
-#define GNOME_IS_CANVAS_PIXBUF(obj) (GTK_CHECK_TYPE ((obj), GNOME_TYPE_CANVAS_PIXBUF))
-#define GNOME_IS_CANVAS_PIXBUF_CLASS(klass) (GTK_CHECK_CLASS_TYPE ((klass), \
- GNOME_TYPE_CANVAS_PIXBUF))
-
-
-typedef struct _GnomeCanvasPixbuf GnomeCanvasPixbuf;
-typedef struct _GnomeCanvasPixbufClass GnomeCanvasPixbufClass;
-
-struct _GnomeCanvasPixbuf {
- GnomeCanvasItem item;
-
- /* Private data */
- gpointer priv;
-};
-
-struct _GnomeCanvasPixbufClass {
- GnomeCanvasItemClass parent_class;
-};
-
-
-GtkType gnome_canvas_pixbuf_get_type (void) G_GNUC_CONST;
-
-
-
-END_GNOME_DECLS
-
-#endif
diff --git a/gdk-pixbuf/io-bmp.c b/gdk-pixbuf/io-bmp.c
index 18ef7bc90..b090957be 100644
--- a/gdk-pixbuf/io-bmp.c
+++ b/gdk-pixbuf/io-bmp.c
@@ -176,17 +176,19 @@ gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc
- anim_done_func, gpointer user_data);
+ anim_done_func, gpointer user_data,
+ GError **error);
void gdk_pixbuf__bmp_image_stop_load(gpointer data);
gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data, guchar * buf,
- guint size);
+ guint size,
+ GError **error);
/* Shared library entry point --> This should be removed when
generic_image_load enters gdk-pixbuf-io. */
-GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f)
+GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f, GError **error)
{
guchar membuf[4096];
size_t length;
@@ -195,15 +197,22 @@ GdkPixbuf *gdk_pixbuf__bmp_image_load(FILE * f)
GdkPixbuf *pb;
State =
- gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL, NULL, NULL);
+ gdk_pixbuf__bmp_image_begin_load(NULL, NULL, NULL, NULL, NULL,
+ error);
+ if (State == NULL)
+ return NULL;
+
while (feof(f) == 0) {
length = fread(membuf, 1, 4096, f);
if (length > 0)
- (void)
- gdk_pixbuf__bmp_image_load_increment(State,
- membuf,
- length);
+ if (!gdk_pixbuf__bmp_image_load_increment(State,
+ membuf,
+ length,
+ error)) {
+ gdk_pixbuf__bmp_image_stop_load (State);
+ return NULL;
+ }
}
if (State->pixbuf != NULL)
@@ -309,7 +318,8 @@ gdk_pixbuf__bmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc
- anim_done_func, gpointer user_data)
+ anim_done_func, gpointer user_data,
+ GError **error)
{
struct bmp_progressive_state *context;
@@ -695,8 +705,10 @@ void DoCompressedByte(struct bmp_progressive_state *context, guchar ** buf,
*
* append image data onto inrecrementally built output image
*/
-gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data, guchar * buf,
- guint size)
+gboolean gdk_pixbuf__bmp_image_load_increment(gpointer data,
+ guchar * buf,
+ guint size,
+ GError **error)
{
struct bmp_progressive_state *context =
(struct bmp_progressive_state *) data;
diff --git a/gdk-pixbuf/io-gif.c b/gdk-pixbuf/io-gif.c
index 681e915da..e61f41fb8 100644
--- a/gdk-pixbuf/io-gif.c
+++ b/gdk-pixbuf/io-gif.c
@@ -180,6 +180,9 @@ struct _GifContext
gint draw_xpos;
gint draw_ypos;
gint draw_pass;
+
+ /* error pointer */
+ GError **error;
};
static int GetDataBlock (GifContext *, unsigned char *);
@@ -204,7 +207,7 @@ gif_read (GifContext *context, guchar *buffer, size_t len)
count += len;
g_print ("Fsize :%d\tcount :%d\t", len, count);
#endif
- retval = (fread(buffer, len, 1, context->file) != 0);
+ retval = (fread(buffer, len, 1, context->file) != 0);
#ifdef IO_GIFDEBUG
if (len < 100) {
for (i = 0; i < len; i++)
@@ -212,6 +215,7 @@ gif_read (GifContext *context, guchar *buffer, size_t len)
}
g_print ("\n");
#endif
+
return retval;
} else {
#ifdef IO_GIFDEBUG
@@ -416,10 +420,21 @@ gif_lzw_fill_buffer (GifContext *context)
if (context->code_done) {
if (context->code_curbit >= context->code_lastbit) {
- g_message ("GIF: ran off the end of by bits\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("GIF file was missing some data (perhaps it was truncated somehow?)"));
+
return -2;
}
- g_message ("trying to read more data after we've done stuff\n");
+ /* Is this supposed to be an error or what? */
+ /* g_message ("trying to read more data after we've done stuff\n"); */
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Internal error in the GIF loader (%s)"),
+ G_STRLOC);
+
return -2;
}
@@ -563,8 +578,10 @@ lzw_read_byte (GifContext *context)
*(context->lzw_sp)++ = context->lzw_table[1][code];
if (code == context->lzw_table[0][code]) {
- /*g_message (_("GIF: circular table entry BIG ERROR\n"));*/
- /*gimp_quit ();*/
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Circular table entry in GIF file"));
return -2;
}
code = context->lzw_table[0][code];
@@ -890,12 +907,18 @@ gif_init (GifContext *context)
char version[4];
if (!gif_read (context, buf, 6)) {
- /* Unable to read magic number */
+ /* Unable to read magic number,
+ * gif_read() should have set error
+ */
return -1;
}
if (strncmp ((char *) buf, "GIF", 3) != 0) {
/* Not a GIF file */
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("File does not appear to be a GIF file"));
return -1;
}
@@ -904,12 +927,17 @@ gif_init (GifContext *context)
if ((strcmp (version, "87a") != 0) && (strcmp (version, "89a") != 0)) {
/* bad version number, not '87a' or '89a' */
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Version %s of the GIF file format is not supported"),
+ version);
return -1;
}
/* read the screen descriptor */
if (!gif_read (context, buf, 7)) {
- /* Failed to read screen descriptor */
+ /* Failed to read screen descriptor, error set */
return -1;
}
@@ -950,6 +978,12 @@ gif_get_frame_info (GifContext *context)
if (context->frame_height > context->height) {
/* we don't want to resize things. So we exit */
context->state = GIF_DONE;
+
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("GIF animation contained a frame with an incorrect size"));
+
return -2;
}
@@ -1092,7 +1126,7 @@ new_context (void)
}
/* Shared library entry point */
GdkPixbuf *
-gdk_pixbuf__gif_image_load (FILE *file)
+gdk_pixbuf__gif_image_load (FILE *file, GError **error)
{
GifContext *context;
GdkPixbuf *pixbuf;
@@ -1101,7 +1135,8 @@ gdk_pixbuf__gif_image_load (FILE *file)
context = new_context ();
context->file = file;
-
+ context->error = error;
+
gif_main_loop (context);
pixbuf = context->pixbuf;
@@ -1115,7 +1150,8 @@ gdk_pixbuf__gif_image_begin_load (ModulePreparedNotifyFunc prepare_func,
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
GifContext *context;
@@ -1123,6 +1159,7 @@ gdk_pixbuf__gif_image_begin_load (ModulePreparedNotifyFunc prepare_func,
count = 0;
#endif
context = new_context ();
+ context->error = error;
context->prepare_func = prepare_func;
context->update_func = update_func;
context->frame_done_func = frame_done_func;
@@ -1148,11 +1185,14 @@ gdk_pixbuf__gif_image_stop_load (gpointer data)
}
gboolean
-gdk_pixbuf__gif_image_load_increment (gpointer data, guchar *buf, guint size)
+gdk_pixbuf__gif_image_load_increment (gpointer data, guchar *buf, guint size,
+ GError **error)
{
gint retval;
GifContext *context = (GifContext *) data;
+ context->error = error;
+
if (context->amount_needed == 0) {
/* we aren't looking for some bytes. */
/* we can use buf now, but we don't want to keep it around at all.
@@ -1206,7 +1246,8 @@ gdk_pixbuf__gif_image_load_increment (gpointer data, guchar *buf, guint size)
}
GdkPixbufAnimation *
-gdk_pixbuf__gif_image_load_animation (FILE *file)
+gdk_pixbuf__gif_image_load_animation (FILE *file,
+ GError **error)
{
GifContext *context;
GdkPixbufAnimation *animation;
@@ -1214,6 +1255,9 @@ gdk_pixbuf__gif_image_load_animation (FILE *file)
g_return_val_if_fail (file != NULL, NULL);
context = new_context ();
+
+ context->error = error;
+
context->animation = g_object_new (GDK_TYPE_PIXBUF_ANIMATION, NULL);
context->animation->n_frames = 0;
diff --git a/gdk-pixbuf/io-ico.c b/gdk-pixbuf/io-ico.c
index 83e2cf93b..a85fee280 100644
--- a/gdk-pixbuf/io-ico.c
+++ b/gdk-pixbuf/io-ico.c
@@ -158,16 +158,18 @@ gdk_pixbuf__ico_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
void gdk_pixbuf__ico_image_stop_load(gpointer data);
-gboolean gdk_pixbuf__ico_image_load_increment(gpointer data, guchar * buf, guint size);
+gboolean gdk_pixbuf__ico_image_load_increment(gpointer data, guchar * buf, guint size,
+ GError **error);
/* Shared library entry point --> Can go when generic_image_load
enters gdk-pixbuf-io */
GdkPixbuf *
-gdk_pixbuf__ico_image_load(FILE * f)
+gdk_pixbuf__ico_image_load(FILE * f, GError **error)
{
guchar *membuf;
size_t length;
@@ -175,7 +177,11 @@ gdk_pixbuf__ico_image_load(FILE * f)
GdkPixbuf *pb;
- State = gdk_pixbuf__ico_image_begin_load(NULL, NULL, NULL, NULL, NULL);
+ State = gdk_pixbuf__ico_image_begin_load(NULL, NULL, NULL,
+ NULL, NULL, error);
+ if (State == NULL)
+ return NULL;
+
membuf = g_malloc(4096);
g_assert(membuf != NULL);
@@ -183,8 +189,11 @@ gdk_pixbuf__ico_image_load(FILE * f)
while (feof(f) == 0) {
length = fread(membuf, 1, 4096, f);
if (length > 0)
- gdk_pixbuf__ico_image_load_increment(State, membuf, length);
-
+ if (!gdk_pixbuf__ico_image_load_increment(State, membuf, length,
+ error)) {
+ gdk_pixbuf__ico_image_stop_load (State);
+ return NULL;
+ }
}
g_free(membuf);
if (State->pixbuf != NULL)
@@ -370,7 +379,8 @@ gdk_pixbuf__ico_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
struct ico_progressive_state *context;
@@ -633,7 +643,8 @@ static void OneLine(struct ico_progressive_state *context)
* append image data onto inrecrementally built output image
*/
gboolean
-gdk_pixbuf__ico_image_load_increment(gpointer data, guchar * buf, guint size)
+gdk_pixbuf__ico_image_load_increment(gpointer data, guchar * buf, guint size,
+ GError **error)
{
struct ico_progressive_state *context =
(struct ico_progressive_state *) data;
diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c
index 623077738..332de30c9 100644
--- a/gdk-pixbuf/io-jpeg.c
+++ b/gdk-pixbuf/io-jpeg.c
@@ -74,6 +74,7 @@ typedef my_source_mgr * my_src_ptr;
struct error_handler_data {
struct jpeg_error_mgr pub;
sigjmp_buf setjmp_buffer;
+ GError **error;
};
/* progressive loader context */
@@ -92,30 +93,51 @@ typedef struct {
struct error_handler_data jerr;
} JpegProgContext;
-GdkPixbuf *gdk_pixbuf__jpeg_image_load (FILE *f);
+GdkPixbuf *gdk_pixbuf__jpeg_image_load (FILE *f, GError **error);
gpointer gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc func,
ModuleUpdatedNotifyFunc func2,
ModuleFrameDoneNotifyFunc func3,
ModuleAnimationDoneNotifyFunc func4,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
void gdk_pixbuf__jpeg_image_stop_load (gpointer context);
-gboolean gdk_pixbuf__jpeg_image_load_increment(gpointer context, guchar *buf, guint size);
+gboolean gdk_pixbuf__jpeg_image_load_increment(gpointer context, guchar *buf, guint size,
+ GError **error);
static void
fatal_error_handler (j_common_ptr cinfo)
{
- /* FIXME:
- * We should somehow signal what error occurred to the caller so the
- * caller can handle the error message */
struct error_handler_data *errmgr;
-
+ char buffer[JMSG_LENGTH_MAX];
+
errmgr = (struct error_handler_data *) cinfo->err;
- cinfo->err->output_message (cinfo);
+
+ /* Create the message */
+ (* cinfo->err->format_message) (cinfo, buffer);
+
+ /* broken check for *error == NULL for robustness against
+ * crappy JPEG library
+ */
+ if (errmgr->error && *errmgr->error == NULL) {
+ g_set_error (errmgr->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Error interpreting JPEG image file (%s)"),
+ buffer);
+ }
+
siglongjmp (errmgr->setjmp_buffer, 1);
- /* incase the jmp buf isn't initted? */
- exit(1);
+ g_assert_not_reached ();
+}
+
+static void
+output_message_handler (j_common_ptr cinfo)
+{
+ /* This method keeps libjpeg from dumping crap to stderr */
+
+ /* do nothing */
}
/* Destroy notification function for the pixbuf */
@@ -158,7 +180,7 @@ explode_gray_into_buf (struct jpeg_decompress_struct *cinfo,
/* Shared library entry point */
GdkPixbuf *
-gdk_pixbuf__jpeg_image_load (FILE *f)
+gdk_pixbuf__jpeg_image_load (FILE *f, GError **error)
{
gint w, h, i;
guchar *pixels = NULL;
@@ -175,7 +197,10 @@ gdk_pixbuf__jpeg_image_load (FILE *f)
/* setup error handler */
cinfo.err = jpeg_std_error (&jerr.pub);
jerr.pub.error_exit = fatal_error_handler;
+ jerr.pub.output_message = output_message_handler;
+ jerr.error = error;
+
if (sigsetjmp (jerr.setjmp_buffer, 1)) {
/* Whoops there was a jpeg error */
if (pixels)
@@ -199,6 +224,17 @@ gdk_pixbuf__jpeg_image_load (FILE *f)
pixels = malloc (h * w * 3);
if (!pixels) {
jpeg_destroy_decompress (&cinfo);
+
+ /* broken check for *error == NULL for robustness against
+ * crappy JPEG library
+ */
+ if (error && *error == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to load image, try exiting some applications to free memory"));
+ }
+
return NULL;
}
@@ -286,7 +322,8 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
JpegProgContext *context;
my_source_mgr *src;
@@ -308,7 +345,9 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func,
context->cinfo.err = jpeg_std_error (&context->jerr.pub);
context->jerr.pub.error_exit = fatal_error_handler;
-
+ context->jerr.pub.output_message = output_message_handler;
+ context->jerr.error = error;
+
src = (my_src_ptr) context->cinfo.src;
src->pub.init_source = init_source;
src->pub.fill_input_buffer = fill_input_buffer;
@@ -318,6 +357,8 @@ gdk_pixbuf__jpeg_image_begin_load (ModulePreparedNotifyFunc prepared_func,
src->pub.bytes_in_buffer = 0;
src->pub.next_input_byte = NULL;
+ context->jerr.error = NULL;
+
return (gpointer) context;
}
@@ -364,7 +405,8 @@ gdk_pixbuf__jpeg_image_stop_load (gpointer data)
* append image data onto inrecrementally built output image
*/
gboolean
-gdk_pixbuf__jpeg_image_load_increment (gpointer data, guchar *buf, guint size)
+gdk_pixbuf__jpeg_image_load_increment (gpointer data, guchar *buf, guint size,
+ GError **error)
{
JpegProgContext *context = (JpegProgContext *)data;
struct jpeg_decompress_struct *cinfo;
@@ -382,6 +424,8 @@ gdk_pixbuf__jpeg_image_load_increment (gpointer data, guchar *buf, guint size)
cinfo = &context->cinfo;
+ context->jerr.error = error;
+
/* XXXXXXX (drmike) - loop(s) below need to be recoded now I
* have a grasp of what the flow needs to be!
*/
@@ -641,12 +685,13 @@ gdk_pixbuf__jpeg_image_save (FILE *f,
g_return_val_if_fail (pixels != NULL, FALSE);
/* allocate a small buffer to convert image data */
- buf = malloc (w * 3 * sizeof (guchar));
- g_return_val_if_fail (buf != NULL, FALSE);
+ buf = g_malloc (w * 3 * sizeof (guchar));
/* set up error handling */
jerr.pub.error_exit = fatal_error_handler;
-
+ jerr.pub.output_message = output_message_handler;
+ jerr.error = error;
+
cinfo.err = jpeg_std_error (&(jerr.pub));
if (sigsetjmp (jerr.setjmp_buffer, 1)) {
jpeg_destroy_compress (&cinfo);
diff --git a/gdk-pixbuf/io-png.c b/gdk-pixbuf/io-png.c
index 33fa2cf68..bd945f794 100644
--- a/gdk-pixbuf/io-png.c
+++ b/gdk-pixbuf/io-png.c
@@ -140,6 +140,38 @@ setup_png_transformations(png_structp png_read_ptr, png_infop png_info_ptr,
#endif
}
+static void
+png_simple_error_callback(png_structp png_save_ptr,
+ png_const_charp error_msg)
+{
+ GError **error;
+
+ error = png_get_error_ptr(png_save_ptr);
+
+ /* I don't trust libpng to call the error callback only once,
+ * so check for already-set error
+ */
+ if (error && *error == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_FAILED,
+ _("Fatal error saving PNG image file: %s"),
+ error_msg);
+ }
+}
+
+static void
+png_simple_warning_callback(png_structp png_save_ptr,
+ png_const_charp warning_msg)
+{
+ /* Don't print anything; we should not be dumping junk to
+ * stderr, since that may be bad for some apps. If it's
+ * important enough to display, we need to add a GError
+ * **warning return location wherever we have an error return
+ * location.
+ */
+}
+
/* Destroy notification function for the pixbuf */
static void
free_buffer (guchar *pixels, gpointer data)
@@ -149,7 +181,7 @@ free_buffer (guchar *pixels, gpointer data)
/* Shared library entry point */
GdkPixbuf *
-gdk_pixbuf__png_image_load (FILE *f)
+gdk_pixbuf__png_image_load (FILE *f, GError **error)
{
png_structp png_ptr;
png_infop info_ptr, end_info;
@@ -159,7 +191,10 @@ gdk_pixbuf__png_image_load (FILE *f)
png_bytepp rows;
guchar *pixels;
- png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING, NULL, NULL, NULL);
+ png_ptr = png_create_read_struct (PNG_LIBPNG_VER_STRING,
+ error,
+ png_simple_error_callback,
+ png_simple_warning_callback);
if (!png_ptr)
return NULL;
@@ -197,6 +232,16 @@ gdk_pixbuf__png_image_load (FILE *f)
pixels = malloc (w * h * bpp);
if (!pixels) {
+ /* Check error NULL, normally this would be broken,
+ * but libpng makes me want to code defensively.
+ */
+ if (error && *error == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to load PNG file"));
+ }
+
png_destroy_read_struct (&png_ptr, &info_ptr, &end_info);
return NULL;
}
@@ -273,6 +318,7 @@ struct _LoadContext {
guint fatal_error_occurred : 1;
+ GError **error;
};
gpointer
@@ -280,7 +326,8 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func,
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
LoadContext* lc;
@@ -297,6 +344,7 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func,
lc->first_pass_seen_in_chunk = -1;
lc->last_pass_seen_in_chunk = -1;
lc->max_row_seen_in_chunk = -1;
+ lc->error = error;
/* Create the main PNG context struct */
@@ -308,13 +356,15 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func,
if (lc->png_read_ptr == NULL) {
g_free(lc);
+ /* error callback should have set the error */
return NULL;
}
-
+
if (setjmp (lc->png_read_ptr->jmpbuf)) {
if (lc->png_info_ptr)
png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
g_free(lc);
+ /* error callback should have set the error */
return NULL;
}
@@ -325,6 +375,7 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func,
if (lc->png_info_ptr == NULL) {
png_destroy_read_struct(&lc->png_read_ptr, NULL, NULL);
g_free(lc);
+ /* error callback should have set the error */
return NULL;
}
@@ -335,6 +386,11 @@ gdk_pixbuf__png_image_begin_load (ModulePreparedNotifyFunc prepare_func,
png_end_callback);
+ /* We don't want to keep modifying error after returning here,
+ * it may no longer be valid.
+ */
+ lc->error = NULL;
+
return lc;
}
@@ -352,7 +408,8 @@ gdk_pixbuf__png_image_stop_load (gpointer context)
}
gboolean
-gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size)
+gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size,
+ GError **error)
{
LoadContext* lc = context;
@@ -364,17 +421,20 @@ gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size)
lc->first_pass_seen_in_chunk = -1;
lc->last_pass_seen_in_chunk = -1;
lc->max_row_seen_in_chunk = -1;
+ lc->error = error;
/* Invokes our callbacks as needed */
if (setjmp (lc->png_read_ptr->jmpbuf)) {
+ lc->error = NULL;
return FALSE;
} else {
png_process_data(lc->png_read_ptr, lc->png_info_ptr, buf, size);
}
- if (lc->fatal_error_occurred)
+ if (lc->fatal_error_occurred) {
+ lc->error = NULL;
return FALSE;
- else {
+ } else {
if (lc->first_row_seen_in_chunk >= 0) {
/* We saw at least one row */
gint pass_diff = lc->last_pass_seen_in_chunk - lc->first_pass_seen_in_chunk;
@@ -417,6 +477,8 @@ gdk_pixbuf__png_image_load_increment(gpointer context, guchar *buf, guint size)
lc->notify_user_data);
}
}
+
+ lc->error = NULL;
return TRUE;
}
@@ -437,7 +499,6 @@ png_info_callback (png_structp png_read_ptr,
if (lc->fatal_error_occurred)
return;
-
setup_png_transformations(lc->png_read_ptr,
lc->png_info_ptr,
@@ -458,6 +519,13 @@ png_info_callback (png_structp png_read_ptr,
if (lc->pixbuf == NULL) {
/* Failed to allocate memory */
lc->fatal_error_occurred = TRUE;
+ if (lc->error && *lc->error == NULL) {
+ g_set_error (lc->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to store a %ld by %ld image; try exiting some applications to reduce memory usage"),
+ width, height);
+ }
return;
}
@@ -521,8 +589,17 @@ png_error_callback(png_structp png_read_ptr,
lc = png_get_error_ptr(png_read_ptr);
lc->fatal_error_occurred = TRUE;
-
- fprintf(stderr, "Fatal error loading PNG: %s\n", error_msg);
+
+ /* I don't trust libpng to call the error callback only once,
+ * so check for already-set error
+ */
+ if (lc->error && *lc->error == NULL) {
+ g_set_error (lc->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Fatal error reading PNG image file: %s"),
+ error_msg);
+ }
}
static void
@@ -532,12 +609,18 @@ png_warning_callback(png_structp png_read_ptr,
LoadContext* lc;
lc = png_get_error_ptr(png_read_ptr);
-
- fprintf(stderr, "Warning loading PNG: %s\n", warning_msg);
+
+ /* Don't print anything; we should not be dumping junk to
+ * stderr, since that may be bad for some apps. If it's
+ * important enough to display, we need to add a GError
+ * **warning return location wherever we have an error return
+ * location.
+ */
}
/* Save */
+
gboolean
gdk_pixbuf__png_image_save (FILE *f,
GdkPixbuf *pixbuf,
@@ -545,8 +628,6 @@ gdk_pixbuf__png_image_save (FILE *f,
gchar **values,
GError **error)
{
- /* FIXME error handling is broken */
-
png_structp png_ptr;
png_infop info_ptr;
guchar *ptr;
@@ -583,7 +664,9 @@ gdk_pixbuf__png_image_save (FILE *f,
pixels = gdk_pixbuf_get_pixels (pixbuf);
png_ptr = png_create_write_struct (PNG_LIBPNG_VER_STRING,
- NULL, NULL, NULL);
+ error,
+ png_simple_error_callback,
+ png_simple_warning_callback);
g_return_val_if_fail (png_ptr != NULL, FALSE);
@@ -599,8 +682,8 @@ gdk_pixbuf__png_image_save (FILE *f,
png_init_io (png_ptr, f);
if (has_alpha) {
png_set_IHDR (png_ptr, info_ptr, w, h, bpc,
- PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
#ifdef WORDS_BIGENDIAN
png_set_swap_alpha (png_ptr);
#else
@@ -608,9 +691,23 @@ gdk_pixbuf__png_image_save (FILE *f,
#endif
} else {
png_set_IHDR (png_ptr, info_ptr, w, h, bpc,
- PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
- PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
+ PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
+ PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE);
data = malloc (w * 3 * sizeof (char));
+
+ if (data == NULL) {
+ /* Check error NULL, normally this would be broken,
+ * but libpng makes me want to code defensively.
+ */
+ if (error && *error == NULL) {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+ _("Insufficient memory to save PNG file"));
+ }
+ png_destroy_write_struct (&png_ptr, (png_infopp) NULL);
+ return FALSE;
+ }
}
sig_bit.red = bpc;
sig_bit.green = bpc;
diff --git a/gdk-pixbuf/io-pnm.c b/gdk-pixbuf/io-pnm.c
index c91658cfd..c352d611f 100644
--- a/gdk-pixbuf/io-pnm.c
+++ b/gdk-pixbuf/io-pnm.c
@@ -76,17 +76,21 @@ typedef struct {
gboolean got_header; /* have we loaded pnm header? */
guint scan_state;
+
+ GError **error;
} PnmLoaderContext;
-GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f);
+GdkPixbuf *gdk_pixbuf__pnm_image_load (FILE *f, GError **error);
gpointer gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc func,
ModuleUpdatedNotifyFunc func2,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
void gdk_pixbuf__pnm_image_stop_load (gpointer context);
-gboolean gdk_pixbuf__pnm_image_load_increment (gpointer context, guchar *buf, guint size);
+gboolean gdk_pixbuf__pnm_image_load_increment (gpointer context, guchar *buf, guint size,
+ GError **error);
static void explode_bitmap_into_buf (PnmLoaderContext *context);
static void explode_gray_into_buf (PnmLoaderContext *context);
@@ -178,7 +182,7 @@ explode_gray_into_buf (PnmLoaderContext *context)
/* skip over whitespace and comments in input buffer */
static gint
-pnm_skip_whitespace (PnmIOBuffer *inbuf)
+pnm_skip_whitespace (PnmIOBuffer *inbuf, GError **error)
{
register guchar *inptr;
guchar *inend;
@@ -208,7 +212,7 @@ pnm_skip_whitespace (PnmIOBuffer *inbuf)
/* read next number from buffer */
static gint
-pnm_read_next_value (PnmIOBuffer *inbuf, guint *value)
+pnm_read_next_value (PnmIOBuffer *inbuf, guint *value, GError **error)
{
register guchar *inptr, *word, *p;
guchar *inend, buf[128];
@@ -220,7 +224,7 @@ pnm_read_next_value (PnmIOBuffer *inbuf, guint *value)
g_return_val_if_fail (value != NULL, PNM_FATAL_ERR);
/* skip white space */
- if ((retval = pnm_skip_whitespace (inbuf)) != PNM_OK)
+ if ((retval = pnm_skip_whitespace (inbuf, error)) != PNM_OK)
return retval;
inend = inbuf->byte + inbuf->nbytes;
@@ -237,8 +241,13 @@ pnm_read_next_value (PnmIOBuffer *inbuf, guint *value)
/* get the value */
*value = strtol (buf, &endptr, 10);
- if (*endptr != '\0')
+ if (*endptr != '\0') {
+ g_set_error (error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM loader expected to find an integer, but didn't"));
return PNM_FATAL_ERR;
+ }
inbuf->byte = p;
inbuf->nbytes = (guint) (inend - p);
@@ -263,8 +272,13 @@ pnm_read_header (PnmLoaderContext *context)
if (inbuf->nbytes < 2)
return PNM_SUSPEND;
- if (*inbuf->byte != 'P')
+ if (*inbuf->byte != 'P') {
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an incorrect initial byte"));
return PNM_FATAL_ERR;
+ }
inbuf->byte++;
inbuf->nbytes--;
@@ -289,6 +303,10 @@ pnm_read_header (PnmLoaderContext *context)
context->type = PNM_FORMAT_PPM_RAW;
break;
default:
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file is not in a recognized PNM subformat"));
return PNM_FATAL_ERR;
}
@@ -303,13 +321,19 @@ pnm_read_header (PnmLoaderContext *context)
/* read the pixmap width */
guint width = 0;
- retval = pnm_read_next_value (inbuf, &width);
+ retval = pnm_read_next_value (inbuf, &width,
+ context->error);
- if (retval != PNM_OK)
+ if (retval != PNM_OK)
return retval;
- if (!width)
+ if (!width) {
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an image width of 0"));
return PNM_FATAL_ERR;
+ }
context->width = width;
}
@@ -318,13 +342,19 @@ pnm_read_header (PnmLoaderContext *context)
/* read the pixmap height */
guint height = 0;
- retval = pnm_read_next_value (inbuf, &height);
+ retval = pnm_read_next_value (inbuf, &height,
+ context->error);
if (retval != PNM_OK)
return retval;
- if (!height)
+ if (!height) {
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM file has an image height of 0"));
return PNM_FATAL_ERR;
+ }
context->height = height;
}
@@ -335,13 +365,19 @@ pnm_read_header (PnmLoaderContext *context)
case PNM_FORMAT_PGM:
case PNM_FORMAT_PGM_RAW:
if (!context->maxval) {
- retval = pnm_read_next_value (inbuf, &context->maxval);
+ retval = pnm_read_next_value (inbuf, &context->maxval,
+ context->error);
if (retval != PNM_OK)
return retval;
- if (context->maxval == 0)
+ if (context->maxval == 0) {
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Maximum color value in PNM file is 0"));
return PNM_FATAL_ERR;
+ }
}
break;
default:
@@ -375,7 +411,10 @@ pnm_read_raw_scanline (PnmLoaderContext *context)
numpix = inbuf->nbytes / 3;
break;
default:
- g_warning ("io-pnm.c: Illegal raw pnm type!\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
return PNM_FATAL_ERR;
}
@@ -400,7 +439,10 @@ pnm_read_raw_scanline (PnmLoaderContext *context)
offset = context->output_col * 3;
break;
default:
- g_warning ("io-pnm.c: Illegal raw pnm type!\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
return PNM_FATAL_ERR;
}
@@ -429,7 +471,11 @@ pnm_read_raw_scanline (PnmLoaderContext *context)
}
break;
default:
- g_warning ("Invalid raw pnm format!");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("Raw PNM image type is invalid"));
+ return PNM_FATAL_ERR;
}
inbuf->byte += numbytes;
@@ -485,7 +531,11 @@ pnm_read_ascii_scanline (PnmLoaderContext *context)
break;
default:
- g_warning ("Can't happen\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM image format is invalid"));
+
return PNM_FATAL_ERR;
}
@@ -499,7 +549,8 @@ pnm_read_ascii_scanline (PnmLoaderContext *context)
}
for (i = context->scan_state; i < numval; i++) {
- retval = pnm_read_next_value (inbuf, &value);
+ retval = pnm_read_next_value (inbuf, &value,
+ context->error);
if (retval != PNM_OK) {
/* save state and return */
context->scan_state = i;
@@ -522,7 +573,11 @@ pnm_read_ascii_scanline (PnmLoaderContext *context)
*dptr++ = (guchar)(255 * value / context->maxval);
break;
default:
- g_warning ("io-pnm.c: Illegal ascii pnm type!\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+ _("PNM image format is invalid"));
+ return PNM_FATAL_ERR;
break;
}
}
@@ -577,7 +632,11 @@ pnm_read_scanline (PnmLoaderContext *context)
return retval;
break;
default:
- g_warning ("Cannot load these image types (yet)\n");
+ g_set_error (context->error,
+ GDK_PIXBUF_ERROR,
+ GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
+ _("PNM image loader does not support this PNM subformat"));
+
return PNM_FATAL_ERR;
}
@@ -586,7 +645,7 @@ pnm_read_scanline (PnmLoaderContext *context)
/* Shared library entry point */
GdkPixbuf *
-gdk_pixbuf__pnm_image_load (FILE *f)
+gdk_pixbuf__pnm_image_load (FILE *f, GError **error)
{
PnmLoaderContext context;
PnmIOBuffer *inbuf;
@@ -608,6 +667,7 @@ gdk_pixbuf__pnm_image_load (FILE *f)
context.got_header = FALSE;
context.did_prescan = FALSE;
context.scan_state = 0;
+ context.error = error;
inbuf = &context.inbuf;
@@ -647,7 +707,8 @@ gdk_pixbuf__pnm_image_load (FILE *f)
/* scan until we hit image data */
if (!context.did_prescan) {
- retval = pnm_skip_whitespace (inbuf);
+ retval = pnm_skip_whitespace (inbuf,
+ context.error);
if (retval == PNM_FATAL_ERR)
return NULL;
else if (retval == PNM_SUSPEND)
@@ -675,7 +736,7 @@ gdk_pixbuf__pnm_image_load (FILE *f)
} else if (retval == PNM_FATAL_ERR) {
if (context.pixbuf)
gdk_pixbuf_unref (context.pixbuf);
- g_warning ("io-pnm.c: error reading rows..\n");
+
return NULL;
}
}
@@ -703,7 +764,8 @@ gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
PnmLoaderContext *context;
@@ -722,6 +784,8 @@ gdk_pixbuf__pnm_image_begin_load (ModulePreparedNotifyFunc prepared_func,
context->inbuf.nbytes = 0;
context->inbuf.byte = NULL;
+
+ context->error = error;
return (gpointer) context;
}
@@ -752,7 +816,8 @@ gdk_pixbuf__pnm_image_stop_load (gpointer data)
* append image data onto inrecrementally built output image
*/
gboolean
-gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size)
+gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size,
+ GError **error)
{
PnmLoaderContext *context = (PnmLoaderContext *)data;
PnmIOBuffer *inbuf;
@@ -764,6 +829,8 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size)
g_return_val_if_fail (context != NULL, FALSE);
g_return_val_if_fail (buf != NULL, FALSE);
+
+ context->error = error;
bufhd = buf;
inbuf = &context->inbuf;
@@ -811,7 +878,8 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size)
/* scan until we hit image data */
if (!context->did_prescan) {
- retval = pnm_skip_whitespace (inbuf);
+ retval = pnm_skip_whitespace (inbuf,
+ context->error);
if (retval == PNM_FATAL_ERR)
return FALSE;
@@ -850,7 +918,6 @@ gdk_pixbuf__pnm_image_load_increment (gpointer data, guchar *buf, guint size)
} else if (retval == PNM_FATAL_ERR) {
if (context->pixbuf)
gdk_pixbuf_unref (context->pixbuf);
- g_warning ("io-pnm.c: error reading rows.\n");
return FALSE;
} else if (retval == PNM_OK) {
/* send updated signal */
diff --git a/gdk-pixbuf/io-ras.c b/gdk-pixbuf/io-ras.c
index e70f4c9e0..dbcf7bc14 100644
--- a/gdk-pixbuf/io-ras.c
+++ b/gdk-pixbuf/io-ras.c
@@ -98,14 +98,16 @@ gdk_pixbuf__ras_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data);
+ gpointer user_data,
+ GError **error);
void gdk_pixbuf__ras_image_stop_load(gpointer data);
-gboolean gdk_pixbuf__ras_image_load_increment(gpointer data, guchar * buf, guint size);
+gboolean gdk_pixbuf__ras_image_load_increment(gpointer data, guchar * buf, guint size,
+ GError **error);
/* Shared library entry point */
-GdkPixbuf *gdk_pixbuf__ras_image_load(FILE * f)
+GdkPixbuf *gdk_pixbuf__ras_image_load(FILE * f, GError **error)
{
guchar *membuf;
size_t length;
@@ -113,7 +115,8 @@ GdkPixbuf *gdk_pixbuf__ras_image_load(FILE * f)
GdkPixbuf *pb;
- State = gdk_pixbuf__ras_image_begin_load(NULL, NULL, NULL, NULL, NULL);
+ State = gdk_pixbuf__ras_image_begin_load(NULL, NULL, NULL,
+ NULL, NULL, error);
membuf = g_malloc(4096);
@@ -121,8 +124,12 @@ GdkPixbuf *gdk_pixbuf__ras_image_load(FILE * f)
while (feof(f) == 0) {
length = fread(membuf, 1, 4096, f);
- (void)gdk_pixbuf__ras_image_load_increment(State, membuf, length);
- }
+ if (!gdk_pixbuf__ras_image_load_increment(State, membuf, length,
+ error)) {
+ gdk_pixbuf__ras_image_stop_load (State);
+ return NULL;
+ }
+ }
g_free(membuf);
if (State->pixbuf != NULL)
gdk_pixbuf_ref(State->pixbuf);
@@ -213,7 +220,8 @@ gdk_pixbuf__ras_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
struct ras_progressive_state *context;
@@ -385,7 +393,8 @@ static void OneLine(struct ras_progressive_state *context)
* append image data onto inrecrementally built output image
*/
gboolean
-gdk_pixbuf__ras_image_load_increment(gpointer data, guchar * buf, guint size)
+gdk_pixbuf__ras_image_load_increment(gpointer data, guchar * buf, guint size,
+ GError **error)
{
struct ras_progressive_state *context =
(struct ras_progressive_state *) data;
diff --git a/gdk-pixbuf/io-tiff.c b/gdk-pixbuf/io-tiff.c
index fdf517463..615714742 100644
--- a/gdk-pixbuf/io-tiff.c
+++ b/gdk-pixbuf/io-tiff.c
@@ -148,7 +148,8 @@ gdk_pixbuf__tiff_image_begin_load (ModulePreparedNotifyFunc prepare_func,
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
TiffData *context;
gint fd;
diff --git a/gdk-pixbuf/io-wbmp.c b/gdk-pixbuf/io-wbmp.c
index f8411ae26..bbca3e1a1 100644
--- a/gdk-pixbuf/io-wbmp.c
+++ b/gdk-pixbuf/io-wbmp.c
@@ -67,16 +67,18 @@ gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
ModuleUpdatedNotifyFunc updated_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc
- anim_done_func, gpointer user_data);
+ anim_done_func, gpointer user_data,
+ GError **error);
void gdk_pixbuf__wbmp_image_stop_load(gpointer data);
gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
- guint size);
+ guint size,
+ GError **error);
/* Shared library entry point --> This should be removed when
generic_image_load enters gdk-pixbuf-io. */
-GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f)
+GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f, GError **error)
{
size_t length;
char membuf[4096];
@@ -84,14 +86,19 @@ GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f)
GdkPixbuf *pb;
- State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL, NULL, NULL);
+ State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL, NULL, NULL,
+ error);
+ if (State == NULL)
+ return NULL;
+
while (feof(f) == 0) {
length = fread(membuf, 1, 4096, f);
if (length > 0)
gdk_pixbuf__wbmp_image_load_increment(State,
membuf,
- length);
+ length,
+ error);
}
if (State->pixbuf != NULL)
@@ -111,10 +118,11 @@ GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f)
gpointer
gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
- ModuleUpdatedNotifyFunc updated_func,
- ModuleFrameDoneNotifyFunc frame_done_func,
- ModuleAnimationDoneNotifyFunc
- anim_done_func, gpointer user_data)
+ ModuleUpdatedNotifyFunc updated_func,
+ ModuleFrameDoneNotifyFunc frame_done_func,
+ ModuleAnimationDoneNotifyFunc
+ anim_done_func, gpointer user_data,
+ GError **error)
{
struct wbmp_progressive_state *context;
@@ -221,7 +229,7 @@ get_mbi(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, i
* append image data onto inrecrementally built output image
*/
gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
- guint size)
+ guint size, GError **error)
{
struct wbmp_progressive_state *context =
(struct wbmp_progressive_state *) data;
diff --git a/gdk-pixbuf/io-xpm.c b/gdk-pixbuf/io-xpm.c
index 17e2a43f4..b762c8705 100644
--- a/gdk-pixbuf/io-xpm.c
+++ b/gdk-pixbuf/io-xpm.c
@@ -27,6 +27,7 @@
#include <stdlib.h>
#include <string.h>
#include <glib.h>
+#include <unistd.h>
#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
@@ -1400,7 +1401,8 @@ gdk_pixbuf__xpm_image_begin_load (ModulePreparedNotifyFunc prepare_func,
ModuleUpdatedNotifyFunc update_func,
ModuleFrameDoneNotifyFunc frame_done_func,
ModuleAnimationDoneNotifyFunc anim_done_func,
- gpointer user_data)
+ gpointer user_data,
+ GError **error)
{
XPMContext *context;
gint fd;
diff --git a/gdk-pixbuf/make-inline-pixbuf.c b/gdk-pixbuf/make-inline-pixbuf.c
index daf0a7e20..445fbd88a 100644
--- a/gdk-pixbuf/make-inline-pixbuf.c
+++ b/gdk-pixbuf/make-inline-pixbuf.c
@@ -187,15 +187,16 @@ main (int argc, char **argv)
while (i < argc)
{
GdkPixbuf *pixbuf;
+ GError *error;
g_assert ((i + 1) < argc);
-
- pixbuf = gdk_pixbuf_new_from_file (argv[i+1]);
+
+ error = NULL;
+ pixbuf = gdk_pixbuf_new_from_file (argv[i+1], &error);
if (pixbuf == NULL)
{
- fprintf (stderr, "Failed to open image file `%s': %s\n",
- argv[i+1], strerror (errno));
+ fprintf (stderr, "%s\n", error->message);
exit (1);
}