diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index 487993ecba..5dc73a1731 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,5 +1,10 @@ -1999-11-01 Federico Mena Quintero +1999-11-02 Elliot Lee + * src/gdk-pixbuf-loader.c: Reorganize gdk_pixbuf_loader_write into + three functions, and eliminate duplication of code from write() + and close(). Also fix bug where the 128-byte header was being + written twice. +1999-11-01 Federico Mena Quintero * src/gnome-canvas-pixbuf.c (recompute_bounding_box): Fixed bounding box computation. diff --git a/gdk-pixbuf/gdk-pixbuf-loader.c b/gdk-pixbuf/gdk-pixbuf-loader.c index ddb4ad3eec..160d139840 100644 --- a/gdk-pixbuf/gdk-pixbuf-loader.c +++ b/gdk-pixbuf/gdk-pixbuf-loader.c @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + /* GdkPixbuf library - Main header file * * Copyright (C) 1999 The Free Software Foundation @@ -48,11 +50,14 @@ static guint pixbuf_loader_signals[LAST_SIGNAL] = { 0 }; /* Internal data */ + +#define LOADER_HEADER_SIZE 128 + typedef struct { GdkPixbuf *pixbuf; gboolean closed; - gchar buf[128]; - gint buf_offset; + gchar header_buf[LOADER_HEADER_SIZE]; + gint header_buf_offset; GdkPixbufModule *image_module; gpointer context; } GdkPixbufLoaderPrivate; @@ -230,6 +235,60 @@ gdk_pixbuf_loader_new (void) return gtk_type_new (gdk_pixbuf_loader_get_type ()); } +static int +gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) +{ + GdkPixbufLoaderPrivate *priv = loader->private; + + priv->image_module = gdk_pixbuf_get_module (priv->header_buf, priv->header_buf_offset); + + if (priv->image_module == NULL) + return 0; + + if (priv->image_module->module == NULL) + gdk_pixbuf_load_module (priv->image_module); + + if (priv->image_module->module == NULL) + return 0; + + if ((priv->image_module->begin_load == NULL) || + (priv->image_module->stop_load == NULL) || + (priv->image_module->load_increment == NULL)) { + g_warning ("module %s does not support incremental loading.\n", + priv->image_module->module_name); + return 0; + } + + priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, loader); + + if (priv->context == NULL) { + g_warning("Failed to begin progressive load"); + return 0; + } + + if( (* priv->image_module->load_increment) (priv->context, priv->header_buf, priv->header_buf_offset) ) + return priv->header_buf_offset; + + return 0; +} + +static int +gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader, guchar *buf, size_t count) +{ + int nbytes; + GdkPixbufLoaderPrivate *priv = loader->private; + + nbytes = MIN(LOADER_HEADER_SIZE - priv->header_buf_offset, count); + memcpy (priv->header_buf + priv->header_buf_offset, buf, nbytes); + + priv->header_buf_offset += nbytes; + + if(priv->header_buf_offset >= LOADER_HEADER_SIZE) { + return gdk_pixbuf_loader_load_module(loader); + } else + return nbytes; +} + /** * gdk_pixbuf_loader_write: * @loader: A pixbuf loader. @@ -250,6 +309,7 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader, guchar *buf, size_t count) g_return_val_if_fail (loader != NULL, FALSE); g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE); + g_return_val_if_fail (buf != NULL, FALSE); g_return_val_if_fail (count >= 0, FALSE); @@ -259,56 +319,17 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader, guchar *buf, size_t count) g_return_val_if_fail (priv->closed == FALSE, FALSE); if (priv->image_module == NULL) { - gboolean retval = TRUE; + int eaten; - memcpy (priv->buf + priv->buf_offset, - buf, - (priv->buf_offset + count > 128) ? (128 - priv->buf_offset) : count); + eaten = gdk_pixbuf_loader_eat_header_write(loader, buf, count); + if (eaten <= 0) + return FALSE; - if (priv->buf_offset + count >= 128) { - /* We have enough data to start doing something with the image */ - priv->image_module = gdk_pixbuf_get_module (priv->buf, 128); - if (priv->image_module == NULL) - return FALSE; - else if (priv->image_module->module == NULL) - gdk_pixbuf_load_module (priv->image_module); - - if ((priv->image_module->begin_load == NULL) || - (priv->image_module->stop_load == NULL) || - (priv->image_module->load_increment == NULL)) { - g_warning ("module %s does not support incremental loading.\n", - priv->image_module->module_name); - return FALSE; - } else { - priv->context = (*priv->image_module->begin_load) ( - gdk_pixbuf_loader_prepare, loader); - - if (priv->context == NULL) { - g_warning("Failed to begin progressive load"); - return FALSE; - } - - retval = (* priv->image_module->load_increment) ( - priv->context, priv->buf, 128); - - /* if we had more then 128 bytes total, we want - * to send the rest of the buffer. - */ - - if (retval && (priv->buf_offset + count) > 128) { - retval = (* priv->image_module->load_increment) ( - priv->context, - buf, - count + priv->buf_offset - 128); - } - } - } else - priv->buf_offset += count; - - return retval; + count -= eaten; + buf += eaten; } - if (priv->image_module->load_increment) + if (count > 0 && priv->image_module->load_increment) return (* priv->image_module->load_increment) (priv->context, buf, count); return (FALSE); @@ -360,22 +381,8 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader) g_return_if_fail (priv->closed == FALSE); /* We have less the 128 bytes in the image. Flush it, and keep going. */ - if (priv->image_module == NULL) { - priv->image_module = gdk_pixbuf_get_module (priv->buf, priv->buf_offset); - if (priv->image_module && - ((priv->image_module->begin_load == NULL) || - (priv->image_module->stop_load == NULL) || - (priv->image_module->load_increment == NULL))) { - g_warning ("module %s does not support incremental loading.\n", - priv->image_module->module_name); - } else if (priv->image_module) { - g_print ("module loaded: name is %s\n", priv->image_module->module_name); - priv->context = (* priv->image_module->begin_load) ( - gdk_pixbuf_loader_prepare, loader); - (* priv->image_module->load_increment) (priv->context, - priv->buf, priv->buf_offset); - } - } + if (priv->image_module == NULL) + gdk_pixbuf_loader_load_module (loader); if (priv->image_module && priv->image_module->stop_load) (* priv->image_module->stop_load) (priv->context); diff --git a/gdk-pixbuf/io-jpeg.c b/gdk-pixbuf/io-jpeg.c index 82954d6134..89ab14ca2d 100644 --- a/gdk-pixbuf/io-jpeg.c +++ b/gdk-pixbuf/io-jpeg.c @@ -45,6 +45,8 @@ #include #include +#include +#include #include #include #include "gdk-pixbuf.h" @@ -53,13 +55,14 @@ /* we are a "source manager" as far as libjpeg is concerned */ +#define JPEG_PROG_BUF_SIZE 4096 + typedef struct { struct jpeg_source_mgr pub; /* public fields */ - JOCTET * buffer; /* start of buffer */ - gboolean start_of_file; /* have we gotten any data yet? */ + JOCTET buffer[JPEG_PROG_BUF_SIZE]; /* start of buffer */ long skip_next; /* number of bytes to skip next read */ - + } my_source_mgr; typedef my_source_mgr * my_src_ptr; @@ -85,8 +88,6 @@ typedef struct { struct error_handler_data jerr; } JpegProgContext; -#define JPEG_PROG_BUF_SIZE 4096 - GdkPixbuf *image_load (FILE *f); gpointer image_begin_load (ModulePreparedNotifyFunc func, gpointer user_data); void image_stop_load (gpointer context); @@ -227,7 +228,6 @@ init_source (j_decompress_ptr cinfo) { my_src_ptr src = (my_src_ptr) cinfo->src; - src->start_of_file = TRUE; src->skip_next = 0; } @@ -278,7 +278,7 @@ image_begin_load (ModulePreparedNotifyFunc func, gpointer user_data) JpegProgContext *context; my_source_mgr *src; - context = g_new (JpegProgContext, 1); + context = g_new0 (JpegProgContext, 1); context->notify_func = func; context->notify_user_data = user_data; context->pixbuf = NULL; @@ -289,9 +289,8 @@ image_begin_load (ModulePreparedNotifyFunc func, gpointer user_data) /* create libjpeg structures */ jpeg_create_decompress (&context->cinfo); - context->cinfo.src = (struct jpeg_source_mgr *) g_new (my_source_mgr, 1); + context->cinfo.src = (struct jpeg_source_mgr *) g_new0 (my_source_mgr, 1); src = (my_src_ptr) context->cinfo.src; - src->buffer = g_malloc (JPEG_PROG_BUF_SIZE); context->cinfo.err = jpeg_std_error (&context->jerr.pub); @@ -316,6 +315,7 @@ void image_stop_load (gpointer data) { JpegProgContext *context = (JpegProgContext *) data; + g_return_if_fail (context != NULL); if (context->pixbuf) @@ -324,8 +324,6 @@ image_stop_load (gpointer data) if (context->cinfo.src) { my_src_ptr src = (my_src_ptr) context->cinfo.src; - if (src->buffer) - g_free (src->buffer); g_free (src); } @@ -352,12 +350,12 @@ image_load_increment (gpointer data, guchar *buf, guint size) struct jpeg_decompress_struct *cinfo; my_src_ptr src; guint num_left, num_copy; - guchar *nextptr; g_return_val_if_fail (context != NULL, FALSE); g_return_val_if_fail (buf != NULL, FALSE); src = (my_src_ptr) context->cinfo.src; + cinfo = &context->cinfo; /* skip over data if requested, handle unsigned int sizes cleanly */ @@ -376,22 +374,26 @@ image_load_increment (gpointer data, guchar *buf, guint size) while (num_left > 0) { /* copy as much data into buffer as possible */ + + if(src->pub.bytes_in_buffer) + { + int space_used = + JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer; + + memmove(src->buffer, src->buffer + space_used, src->pub.bytes_in_buffer); + g_print("Moving %d bytes from offset %d to head\n", src->pub.bytes_in_buffer, space_used); + } + num_copy = MIN (JPEG_PROG_BUF_SIZE - src->pub.bytes_in_buffer, size); - if (num_copy == 0) - g_assert ("Buffer overflow!\n"); - - nextptr = src->buffer + src->pub.bytes_in_buffer; - memcpy (nextptr, buf, num_copy); - - if (src->pub.next_input_byte == NULL || - src->pub.bytes_in_buffer == 0) - src->pub.next_input_byte = src->buffer; - + g_error ("Buffer overflow!"); + memcpy(src->buffer + src->pub.bytes_in_buffer, buf, num_copy); + src->pub.next_input_byte = src->buffer; src->pub.bytes_in_buffer += num_copy; - num_left -= num_copy; + g_print("Copied %d bytes, now have %d in buffer, %d left\n", num_copy, src->pub.bytes_in_buffer, num_left); + G_BREAKPOINT(); /* try to load jpeg header */ if (!context->got_header) { @@ -399,6 +401,7 @@ image_load_increment (gpointer data, guchar *buf, guint size) rc = jpeg_read_header (cinfo, TRUE); context->src_initialized = TRUE; + if (rc == JPEG_SUSPENDED) continue; @@ -418,7 +421,7 @@ image_load_increment (gpointer data, guchar *buf, guint size) if (context->pixbuf == NULL) { /* Failed to allocate memory */ - g_assert ("Couldn't allocate gdkpixbuf\n"); + g_error ("Couldn't allocate gdkpixbuf"); } /* Use pixbuf buffer to store decompressed data */ @@ -430,7 +433,6 @@ image_load_increment (gpointer data, guchar *buf, guint size) (* context->notify_func) (context->pixbuf, context->notify_user_data); - src->start_of_file = FALSE; } else if (!context->did_prescan) { int rc; diff --git a/gtk/gdk-pixbuf-loader.c b/gtk/gdk-pixbuf-loader.c index ddb4ad3eec..160d139840 100644 --- a/gtk/gdk-pixbuf-loader.c +++ b/gtk/gdk-pixbuf-loader.c @@ -1,3 +1,5 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ + /* GdkPixbuf library - Main header file * * Copyright (C) 1999 The Free Software Foundation @@ -48,11 +50,14 @@ static guint pixbuf_loader_signals[LAST_SIGNAL] = { 0 }; /* Internal data */ + +#define LOADER_HEADER_SIZE 128 + typedef struct { GdkPixbuf *pixbuf; gboolean closed; - gchar buf[128]; - gint buf_offset; + gchar header_buf[LOADER_HEADER_SIZE]; + gint header_buf_offset; GdkPixbufModule *image_module; gpointer context; } GdkPixbufLoaderPrivate; @@ -230,6 +235,60 @@ gdk_pixbuf_loader_new (void) return gtk_type_new (gdk_pixbuf_loader_get_type ()); } +static int +gdk_pixbuf_loader_load_module(GdkPixbufLoader *loader) +{ + GdkPixbufLoaderPrivate *priv = loader->private; + + priv->image_module = gdk_pixbuf_get_module (priv->header_buf, priv->header_buf_offset); + + if (priv->image_module == NULL) + return 0; + + if (priv->image_module->module == NULL) + gdk_pixbuf_load_module (priv->image_module); + + if (priv->image_module->module == NULL) + return 0; + + if ((priv->image_module->begin_load == NULL) || + (priv->image_module->stop_load == NULL) || + (priv->image_module->load_increment == NULL)) { + g_warning ("module %s does not support incremental loading.\n", + priv->image_module->module_name); + return 0; + } + + priv->context = (*priv->image_module->begin_load) (gdk_pixbuf_loader_prepare, loader); + + if (priv->context == NULL) { + g_warning("Failed to begin progressive load"); + return 0; + } + + if( (* priv->image_module->load_increment) (priv->context, priv->header_buf, priv->header_buf_offset) ) + return priv->header_buf_offset; + + return 0; +} + +static int +gdk_pixbuf_loader_eat_header_write (GdkPixbufLoader *loader, guchar *buf, size_t count) +{ + int nbytes; + GdkPixbufLoaderPrivate *priv = loader->private; + + nbytes = MIN(LOADER_HEADER_SIZE - priv->header_buf_offset, count); + memcpy (priv->header_buf + priv->header_buf_offset, buf, nbytes); + + priv->header_buf_offset += nbytes; + + if(priv->header_buf_offset >= LOADER_HEADER_SIZE) { + return gdk_pixbuf_loader_load_module(loader); + } else + return nbytes; +} + /** * gdk_pixbuf_loader_write: * @loader: A pixbuf loader. @@ -250,6 +309,7 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader, guchar *buf, size_t count) g_return_val_if_fail (loader != NULL, FALSE); g_return_val_if_fail (GDK_IS_PIXBUF_LOADER (loader), FALSE); + g_return_val_if_fail (buf != NULL, FALSE); g_return_val_if_fail (count >= 0, FALSE); @@ -259,56 +319,17 @@ gdk_pixbuf_loader_write (GdkPixbufLoader *loader, guchar *buf, size_t count) g_return_val_if_fail (priv->closed == FALSE, FALSE); if (priv->image_module == NULL) { - gboolean retval = TRUE; + int eaten; - memcpy (priv->buf + priv->buf_offset, - buf, - (priv->buf_offset + count > 128) ? (128 - priv->buf_offset) : count); + eaten = gdk_pixbuf_loader_eat_header_write(loader, buf, count); + if (eaten <= 0) + return FALSE; - if (priv->buf_offset + count >= 128) { - /* We have enough data to start doing something with the image */ - priv->image_module = gdk_pixbuf_get_module (priv->buf, 128); - if (priv->image_module == NULL) - return FALSE; - else if (priv->image_module->module == NULL) - gdk_pixbuf_load_module (priv->image_module); - - if ((priv->image_module->begin_load == NULL) || - (priv->image_module->stop_load == NULL) || - (priv->image_module->load_increment == NULL)) { - g_warning ("module %s does not support incremental loading.\n", - priv->image_module->module_name); - return FALSE; - } else { - priv->context = (*priv->image_module->begin_load) ( - gdk_pixbuf_loader_prepare, loader); - - if (priv->context == NULL) { - g_warning("Failed to begin progressive load"); - return FALSE; - } - - retval = (* priv->image_module->load_increment) ( - priv->context, priv->buf, 128); - - /* if we had more then 128 bytes total, we want - * to send the rest of the buffer. - */ - - if (retval && (priv->buf_offset + count) > 128) { - retval = (* priv->image_module->load_increment) ( - priv->context, - buf, - count + priv->buf_offset - 128); - } - } - } else - priv->buf_offset += count; - - return retval; + count -= eaten; + buf += eaten; } - if (priv->image_module->load_increment) + if (count > 0 && priv->image_module->load_increment) return (* priv->image_module->load_increment) (priv->context, buf, count); return (FALSE); @@ -360,22 +381,8 @@ gdk_pixbuf_loader_close (GdkPixbufLoader *loader) g_return_if_fail (priv->closed == FALSE); /* We have less the 128 bytes in the image. Flush it, and keep going. */ - if (priv->image_module == NULL) { - priv->image_module = gdk_pixbuf_get_module (priv->buf, priv->buf_offset); - if (priv->image_module && - ((priv->image_module->begin_load == NULL) || - (priv->image_module->stop_load == NULL) || - (priv->image_module->load_increment == NULL))) { - g_warning ("module %s does not support incremental loading.\n", - priv->image_module->module_name); - } else if (priv->image_module) { - g_print ("module loaded: name is %s\n", priv->image_module->module_name); - priv->context = (* priv->image_module->begin_load) ( - gdk_pixbuf_loader_prepare, loader); - (* priv->image_module->load_increment) (priv->context, - priv->buf, priv->buf_offset); - } - } + if (priv->image_module == NULL) + gdk_pixbuf_loader_load_module (loader); if (priv->image_module && priv->image_module->stop_load) (* priv->image_module->stop_load) (priv->context);