]> Pileus Git - ~andy/gtk/blobdiff - gdk-pixbuf/io-wbmp.c
Cleanups
[~andy/gtk] / gdk-pixbuf / io-wbmp.c
index 76cb8e65e0a26543a765952b095e53b58c7b9e64..94a6f61e11e1a154c978211a15c6b04700cd6234 100644 (file)
@@ -1,3 +1,4 @@
+/* -*- mode: C; c-file-style: "linux" -*- */
 /* GdkPixbuf library - Wireless Bitmap image loader
  *
  * Copyright (C) 2000 Red Hat, Inc.
@@ -30,7 +31,9 @@ Known bugs:
 
 #include <config.h>
 #include <stdio.h>
+#ifdef HAVE_UNISTD_H
 #include <unistd.h>
+#endif
 #include <string.h>
 #include "gdk-pixbuf-private.h"
 #include "gdk-pixbuf-io.h"
@@ -40,16 +43,16 @@ Known bugs:
 /* Progressive loading */
 
 struct wbmp_progressive_state {
-  ModulePreparedNotifyFunc prepared_func;
-  ModuleUpdatedNotifyFunc updated_func;
+  GdkPixbufModulePreparedFunc prepared_func;
+  GdkPixbufModuleUpdatedFunc updated_func;
   gpointer user_data;
 
-  gboolean need_type : 1;
-  gboolean need_header : 1;
-  gboolean need_width : 1;
-  gboolean need_height : 1;
-  gboolean needmore : 1;
-  gboolean call_progressive_updates : 1;
+  guint need_type : 1;
+  guint need_header : 1;
+  guint need_width : 1;
+  guint need_height : 1;
+  guint needmore : 1;
+  guint call_progressive_updates : 1;
 
   guchar last_buf[16]; /* Just needs to be big enough to hold the largest datum requestable via 'getin' */
   guint last_len;
@@ -60,46 +63,18 @@ struct wbmp_progressive_state {
   GdkPixbuf *pixbuf;   /* Our "target" */
 };
 
-gpointer
-gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
-                                 ModuleUpdatedNotifyFunc updated_func,
-                                 ModuleFrameDoneNotifyFunc frame_done_func,
-                                 ModuleAnimationDoneNotifyFunc
-                                 anim_done_func, gpointer user_data);
+static gpointer
+gdk_pixbuf__wbmp_image_begin_load(GdkPixbufModuleSizeFunc size_func, 
+                                  GdkPixbufModulePreparedFunc prepared_func,
+                                 GdkPixbufModuleUpdatedFunc updated_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);
-
-
-/* Shared library entry point --> This should be removed when
-   generic_image_load enters gdk-pixbuf-io. */
-GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f)
-{
-       size_t length;
-       char membuf[4096];
-       struct wbmp_progressive_state *State;
-
-       GdkPixbuf *pb;
-
-       State = gdk_pixbuf__wbmp_image_begin_load(NULL, NULL, NULL, NULL, NULL);
-
-       while (feof(f) == 0) {
-               length = fread(membuf, 1, 4096, f);
-               if (length > 0)
-                 gdk_pixbuf__wbmp_image_load_increment(State,
-                                                       membuf,
-                                                       length);
-
-       }
-       if (State->pixbuf != NULL)
-               gdk_pixbuf_ref(State->pixbuf);
-
-       pb = State->pixbuf;
-
-       gdk_pixbuf__wbmp_image_stop_load(State);
-       return pb;
-}
+static gboolean gdk_pixbuf__wbmp_image_stop_load(gpointer data, GError **error);
+static gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data,
+                                                      const guchar * buf,
+                                                      guint size,
+                                                      GError **error);
 
 /* 
  * func - called when we have pixmap created (but no image data)
@@ -107,12 +82,12 @@ GdkPixbuf *gdk_pixbuf__wbmp_image_load(FILE * f)
  * return context (opaque to user)
  */
 
-gpointer
-gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
-                                ModuleUpdatedNotifyFunc updated_func,
-                                ModuleFrameDoneNotifyFunc frame_done_func,
-                                ModuleAnimationDoneNotifyFunc
-                                anim_done_func, gpointer user_data)
+static gpointer
+gdk_pixbuf__wbmp_image_begin_load(GdkPixbufModuleSizeFunc size_func, 
+                                  GdkPixbufModulePreparedFunc prepared_func,
+                                  GdkPixbufModuleUpdatedFunc updated_func,
+                                  gpointer user_data,
+                                  GError **error)
 {
        struct wbmp_progressive_state *context;
 
@@ -133,20 +108,27 @@ gdk_pixbuf__wbmp_image_begin_load(ModulePreparedNotifyFunc prepared_func,
  *
  * free context, unref gdk_pixbuf
  */
-void gdk_pixbuf__wbmp_image_stop_load(gpointer data)
+static gboolean gdk_pixbuf__wbmp_image_stop_load(gpointer data,
+                                                 GError **error)
 {
        struct wbmp_progressive_state *context =
            (struct wbmp_progressive_state *) data;
 
-       g_return_if_fail(context != NULL);
+        /* FIXME this thing needs to report errors if
+         * we have unused image data
+         */
+        
+       g_return_val_if_fail(context != NULL, TRUE);
        if (context->pixbuf)
-         gdk_pixbuf_unref(context->pixbuf);
+         g_object_unref(context->pixbuf);
 
        g_free(context);
+
+        return TRUE;
 }
 
 static gboolean
-getin(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, guchar *ptr, int datum_size)
+getin(struct wbmp_progressive_state *context, const guchar **buf, guint *buf_size, guchar *ptr, int datum_size)
 {
   int last_num, buf_num;
 
@@ -181,10 +163,10 @@ save_rest(struct wbmp_progressive_state *context, const guchar *buf, guint buf_s
 }
 
 static gboolean
-get_mbi(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, int *val)
+get_mbi(struct wbmp_progressive_state *context, const guchar **buf, guint *buf_size, int *val)
 {
   guchar intbuf[16];
-  int i, n;
+  int n;
   gboolean rv;
 
   *val = 0;
@@ -199,7 +181,7 @@ get_mbi(struct wbmp_progressive_state *context, guchar **buf, guint *buf_size, i
   } while(n < sizeof(intbuf) && (intbuf[n-1] & 0x80));
 
  out:
-  if(!rv || !(intbuf[n-1] & 0x80))
+  if(!rv || (intbuf[n-1] & 0x80))
     {
       rv = save_rest(context, intbuf, n);
 
@@ -218,12 +200,13 @@ 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)
+static gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data,
+                                                      const guchar * buf,
+                                                      guint size, GError **error)
 {
        struct wbmp_progressive_state *context =
            (struct wbmp_progressive_state *) data;
-       gboolean bv;
+       gboolean bv = FALSE;
 
        do
          {
@@ -253,8 +236,19 @@ gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
            else if(context->need_width)
              {
                bv = get_mbi(context, &buf, &size, &context->width);
-               if(bv)
+               if(bv) {
                  context->need_width = FALSE;
+
+                  if (context->width <= 0) {
+                   g_set_error (error,
+                                GDK_PIXBUF_ERROR,
+                                GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                _("Image has zero width"));
+
+                   return FALSE;
+                 }
+                }
+               
              }
            else if(context->need_height)
              {
@@ -262,9 +256,29 @@ gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
                if(bv)
                  {
                    context->need_height = FALSE;
+
+                   if (context->height <= 0) {
+                     g_set_error (error,
+                                  GDK_PIXBUF_ERROR,
+                                  GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                                  _("Image has zero height"));
+                     
+                     return FALSE;
+                   }
+
                    context->pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, context->width, context->height);
+                   
+                   if (!context->pixbuf) {
+                     g_set_error (error,
+                                  GDK_PIXBUF_ERROR,
+                                  GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY,
+                                  _("Not enough memory to load image"));
+                     return FALSE;
+                   }
+
+
                    if(context->prepared_func)
-                     context->prepared_func(context->pixbuf, context->user_data);
+                     context->prepared_func(context->pixbuf, NULL, context->user_data);
                  }
              }
            else if(context->needmore)
@@ -283,10 +297,13 @@ gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
                          goto out;
 
                        ptr = context->pixbuf->pixels + context->pixbuf->rowstride * context->cury + context->curx * 3;
-                       for(xoff = 0; xoff < 8; xoff++, ptr += 3)
+                       for(xoff = 7; xoff >= 0; xoff--, ptr += 3)
                          {
                            guchar pixval;
 
+                           if (context->curx + (7 - xoff) == context->width)
+                             break;
+
                            if(byte & (1<<xoff))
                              pixval = 0xFF;
                            else
@@ -299,16 +316,58 @@ gboolean gdk_pixbuf__wbmp_image_load_increment(gpointer data, guchar * buf,
                context->needmore = FALSE;
 
              out:
-               context->updated_func(context->pixbuf, 0, first_row, context->width, context->cury - first_row + 1,
-                                     context->user_data);
+               if(context->updated_func)
+                 context->updated_func(context->pixbuf, 0, first_row, context->width, context->cury - first_row + 1,
+                                       context->user_data);
              }
            else
              bv = FALSE; /* Nothing left to do, stop feeding me data! */
 
          } while(bv);
 
-       if(size)
-         return save_rest(context, buf, size);
-       else
-         return context->needmore;
+       if(size) {
+         bv = save_rest(context, buf, size);
+         if (!bv) {
+             g_set_error (error,
+                          GDK_PIXBUF_ERROR,
+                          GDK_PIXBUF_ERROR_CORRUPT_IMAGE,
+                          _("Couldn't save the rest"));
+
+             return FALSE;
+         }
+       }
+       return TRUE;
+}
+
+void
+MODULE_ENTRY (wbmp, fill_vtable) (GdkPixbufModule *module)
+{
+       module->begin_load = gdk_pixbuf__wbmp_image_begin_load;
+       module->stop_load = gdk_pixbuf__wbmp_image_stop_load;
+       module->load_increment = gdk_pixbuf__wbmp_image_load_increment;
+}
+
+void
+MODULE_ENTRY (wbmp, fill_info) (GdkPixbufFormat *info)
+{
+       static GdkPixbufModulePattern signature[] = {
+               { " ", "z", 1 }, 
+               { NULL, NULL, 0 }
+       };
+       static gchar * mime_types[] = {
+               "image/vnd.wap.wbmp",
+               NULL
+       };
+       static gchar * extensions[] = {
+               "wbmp",
+               NULL
+       };
+
+       info->name = "wbmp";
+       info->signature = signature;
+       info->description = N_("The WBMP image format");
+       info->mime_types = mime_types;
+       info->extensions = extensions;
+       info->flags = GDK_PIXBUF_FORMAT_THREADSAFE;
+       info->license = "LGPL";
 }