]> Pileus Git - ~andy/gtk/commitdiff
new pixbuf loader, for X bitmap files. Basically a collision between
authorJohn Harper <jsh@eazel.com>
Mon, 22 Jan 2001 02:08:53 +0000 (02:08 +0000)
committerJohn Harper <jsh@src.gnome.org>
Mon, 22 Jan 2001 02:08:53 +0000 (02:08 +0000)
2001-01-20  John Harper  <jsh@eazel.com>

* io-xbm.c: new pixbuf loader, for X bitmap files. Basically a
collision between Xlib's RdBitF.c and io-tiff.c

* gdk-pixbuf-io.c, Makefile.am, pixbufloader_xbm.def: added
io-xbm.c support

[ merged from stable gdk-pixbuf module. Untested, but it
compiles, and works fine in the stable module ]

gdk-pixbuf/ChangeLog
gdk-pixbuf/Makefile.am
gdk-pixbuf/gdk-pixbuf-io.c
gdk-pixbuf/io-xbm.c [new file with mode: 0644]
gdk-pixbuf/pixbufloader_xbm.def [new file with mode: 0644]

index 1ad68aa79555b0266aa78c44f6522fb70dbadab3..e6819670fce7d4270a3019bc06e9a9a1e963c6fd 100644 (file)
@@ -1,3 +1,14 @@
+2001-01-20  John Harper  <jsh@eazel.com>
+
+       * io-xbm.c: new pixbuf loader, for X bitmap files. Basically a
+       collision between Xlib's RdBitF.c and io-tiff.c
+
+       * gdk-pixbuf-io.c, Makefile.am, pixbufloader_xbm.def: added
+       io-xbm.c support
+
+       [ merged from stable gdk-pixbuf module. Untested, but it
+       compiles, and works fine in the stable module ]
+
 2001-01-18  Tor Lillqvist  <tml@iki.fi>
 
        * gdk-pixbuf-io.c (get_libdir): (Win32) Use the new
index 6ae79ca9f26738100768c60168cee5b95d03c5c1..0d14cb15e370ab6876049609e28f623773a5c924 100644 (file)
@@ -84,6 +84,13 @@ libpixbufloader_static_wbmp_la_SOURCES = io-wbmp.c
 libpixbufloader_wbmp_la_SOURCES = io-wbmp.c
 libpixbufloader_wbmp_la_LDFLAGS = -avoid-version -module
 
+#
+# The XBM loader
+#
+libpixbufloader_xbm_la_SOURCES = io-xbm.c
+libpixbufloader_xbm_la_LDFLAGS = -version-info 1:0:0 -module
+libpixbufloader_xbm_la_LIBADD =
+
 if HAVE_PNG
 PNG_LIB = libpixbufloader-png.la
 endif
@@ -110,6 +117,8 @@ BMP_LIB = libpixbufloader-bmp.la
 
 WBMP_LIB = libpixbufloader-wbmp.la
 
+XBM_LIB = libpixbufloader-xbm.la
+
 if BUILD_DYNAMIC_MODULES
 
 loader_LTLIBRARIES =   \
@@ -122,7 +131,8 @@ loader_LTLIBRARIES =        \
        $(TIFF_LIB)     \
        $(PNM_LIB)      \
        $(BMP_LIB)      \
-       $(WBMP_LIB)
+       $(WBMP_LIB)     \
+       $(XBM_LIB)
 
 
 extra_sources = 
@@ -214,4 +224,6 @@ EXTRA_DIST =                        \
        pixbufloader_gif.def            \
        pixbufloader_png.def            \
        pixbufloader_tiff.def           \
-       pixbufloader_wbmp.def
+       pixbufloader_wbmp.def           \
+       pixbufloader_xbm.def
+
index 6238371d3a460e15ab7a182281c44968c6e68043..469f4743728ab2ce9f1f68cd7e90309c2745c7ed 100644 (file)
@@ -180,6 +180,26 @@ pixbuf_check_wbmp (guchar *buffer, int size)
   return FALSE;
 }
 
+
+static gboolean
+pixbuf_check_xbm (guchar *buffer, int size)
+{
+       if (size < 20)
+               return FALSE;
+
+       if (buffer [0] != '#'
+           || buffer [1] != 'd'
+           || buffer [2] != 'e'
+           || buffer [3] != 'f'
+           || buffer [4] != 'i'
+           || buffer [5] != 'n'
+           || buffer [6] != 'e'
+           || buffer [7] != ' ')
+               return FALSE;
+
+       return TRUE;
+}
+
 static GdkPixbufModule file_formats [] = {
        { "png",  pixbuf_check_png, NULL,  NULL, NULL, NULL, NULL, NULL, NULL, },
        { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
@@ -192,6 +212,7 @@ static GdkPixbufModule file_formats [] = {
        { "ico",  pixbuf_check_ico, NULL,  NULL, NULL, NULL, NULL, NULL, NULL },
        { "bmp",  pixbuf_check_bmp, NULL,  NULL, NULL, NULL, NULL, NULL, NULL },
        { "wbmp", pixbuf_check_wbmp, NULL, NULL, NULL, NULL, NULL, NULL, NULL },
+       { "xbm",  pixbuf_check_xbm, NULL,  NULL, NULL, NULL, NULL, NULL, NULL },
        { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
@@ -376,6 +397,11 @@ m_stop_load (tiff);
 /* XPM */
 m_load (xpm);
 m_load_xpm_data (xpm);
+/* XBM */
+m_load (xbm);
+m_begin_load (xbm);
+m_load_increment (xbm);
+m_stop_load (xbm);
 
 gboolean
 gdk_pixbuf_load_module (GdkPixbufModule *image_module,
@@ -484,6 +510,24 @@ gdk_pixbuf_load_module (GdkPixbufModule *image_module,
        }
 #endif
 
+#ifdef INCLUDE_xpm
+       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 TRUE;
+       }
+#endif
+
+#ifdef INCLUDE_tiff
+       if (strcmp (image_module->module_name, "xbm") == 0){
+               image_module->load           = mname (xbm,load);
+               image_module->begin_load     = mname (xbm,begin_load);
+               image_module->load_increment = mname (xbm,load_increment);
+               image_module->stop_load      = mname (xbm,stop_load);
+               return TRUE;
+       }
+#endif
+
         g_set_error (error,
                      GDK_PIXBUF_ERROR,
                      GDK_PIXBUF_ERROR_UNKNOWN_TYPE,
diff --git a/gdk-pixbuf/io-xbm.c b/gdk-pixbuf/io-xbm.c
new file mode 100644 (file)
index 0000000..affa148
--- /dev/null
@@ -0,0 +1,406 @@
+/* GdkPixbuf library - XBM image loader
+ *
+ * Copyright (C) 1999 Mark Crichton
+ * Copyright (C) 1999 The Free Software Foundation
+ * Copyright (C) 2001 Eazel, Inc.
+ *
+ * Authors: Mark Crichton <crichton@gimp.org>
+ *          Federico Mena-Quintero <federico@gimp.org>
+ *          Jonathan Blandford <jrb@redhat.com>
+ *         John Harper <jsh@eazel.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library 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
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library 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.
+ */
+
+/* Following code adapted from io-tiff.c, which was ``(almost) blatantly
+   ripped from Imlib'' */
+
+#include <config.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdio.h>
+#include <ctype.h>
+#include "gdk-pixbuf-private.h"
+#include "gdk-pixbuf-io.h"
+
+\f
+
+typedef struct _XBMData XBMData;
+struct _XBMData
+{
+       ModulePreparedNotifyFunc prepare_func;
+       ModuleUpdatedNotifyFunc update_func;
+       gpointer user_data;
+
+       gchar *tempname;
+       FILE *file;
+       gboolean all_okay;
+};
+
+\f
+/* xbm parser borrowed from xc/lib/X11/RdBitF.c */
+
+#define MAX_SIZE 255
+
+/* shared data for the image read/parse logic */
+static short hex_table[256];           /* conversion value */
+static gboolean initialized = FALSE;   /* easier to fill in at run time */
+
+
+/* Table index for the hex values. Initialized once, first time.
+ * Used for translation value or delimiter significance lookup.
+ */
+static void
+init_hex_table (void)
+{
+       /*
+        * We build the table at run time for several reasons:
+        *
+        * 1. portable to non-ASCII machines.
+        * 2. still reentrant since we set the init flag after setting table.
+        * 3. easier to extend.
+        * 4. less prone to bugs.
+        */
+       hex_table['0'] = 0;
+       hex_table['1'] = 1;
+       hex_table['2'] = 2;
+       hex_table['3'] = 3;
+       hex_table['4'] = 4;
+       hex_table['5'] = 5;
+       hex_table['6'] = 6;
+       hex_table['7'] = 7;
+       hex_table['8'] = 8;
+       hex_table['9'] = 9;
+       hex_table['A'] = 10;
+       hex_table['B'] = 11;
+       hex_table['C'] = 12;
+       hex_table['D'] = 13;
+       hex_table['E'] = 14;
+       hex_table['F'] = 15;
+       hex_table['a'] = 10;
+       hex_table['b'] = 11;
+       hex_table['c'] = 12;
+       hex_table['d'] = 13;
+       hex_table['e'] = 14;
+       hex_table['f'] = 15;
+
+       /* delimiters of significance are flagged w/ negative value */
+       hex_table[' '] = -1;
+       hex_table[','] = -1;
+       hex_table['}'] = -1;
+       hex_table['\n'] = -1;
+       hex_table['\t'] = -1;
+
+       initialized = TRUE;
+}
+
+/* Read next hex value in the input stream, return -1 if EOF */
+static int
+next_int (FILE *fstream)
+{
+       int ch;
+       int value = 0;
+       int gotone = 0;
+       int done = 0;
+    
+       /* loop, accumulate hex value until find delimiter 
+          skip any initial delimiters found in read stream */
+
+       while (!done) {
+               ch = getc (fstream);
+               if (ch == EOF) {
+                       value = -1;
+                       done++;
+               } else {
+                       /* trim high bits, check type and accumulate */
+                       ch &= 0xff;
+                       if (isascii (ch) && isxdigit (ch)) {
+                               value = (value << 4) + hex_table[ch];
+                               gotone++;
+                       } else if ((hex_table[ch]) < 0 && gotone) {
+                               done++;
+                       }
+               }
+       }
+       return value;
+}
+
+static gboolean
+read_bitmap_file_data (FILE *fstream,
+                      guint *width, guint *height,
+                      guchar **data,
+                      int *x_hot, int *y_hot)
+{
+       guchar *bits = NULL;            /* working variable */
+       char line[MAX_SIZE];            /* input line from file */
+       int size;                       /* number of bytes of data */
+       char name_and_type[MAX_SIZE];   /* an input line */
+       char *type;                     /* for parsing */
+       int value;                      /* from an input line */
+       int version10p;                 /* boolean, old format */
+       int padding;                    /* to handle alignment */
+       int bytes_per_line;             /* per scanline of data */
+       guint ww = 0;                   /* width */
+       guint hh = 0;                   /* height */
+       int hx = -1;                    /* x hotspot */
+       int hy = -1;                    /* y hotspot */
+
+       /* first time initialization */
+       if (!initialized) {
+               init_hex_table ();
+       }
+
+       /* error cleanup and return macro */
+#define        RETURN(code) { g_free (bits); return code; }
+
+       while (fgets (line, MAX_SIZE, fstream)) {
+               if (strlen (line) == MAX_SIZE-1)
+                       RETURN (FALSE);
+               if (sscanf (line,"#define %s %d",name_and_type,&value) == 2) {
+                       if (!(type = strrchr (name_and_type, '_')))
+                               type = name_and_type;
+                       else {
+                               type++;
+                       }
+
+                       if (!strcmp ("width", type))
+                               ww = (unsigned int) value;
+                       if (!strcmp ("height", type))
+                               hh = (unsigned int) value;
+                       if (!strcmp ("hot", type)) {
+                               if (type-- == name_and_type
+                                   || type-- == name_and_type)
+                                       continue;
+                               if (!strcmp ("x_hot", type))
+                                       hx = value;
+                               if (!strcmp ("y_hot", type))
+                                       hy = value;
+                       }
+                       continue;
+               }
+    
+               if (sscanf (line, "static short %s = {", name_and_type) == 1)
+                       version10p = 1;
+               else if (sscanf (line,"static unsigned char %s = {",name_and_type) == 1)
+                       version10p = 0;
+               else if (sscanf (line, "static char %s = {", name_and_type) == 1)
+                       version10p = 0;
+               else
+                       continue;
+
+               if (!(type = strrchr (name_and_type, '_')))
+                       type = name_and_type;
+               else
+                       type++;
+
+               if (strcmp ("bits[]", type))
+                       continue;
+    
+               if (!ww || !hh)
+                       RETURN (FALSE);
+
+               if ((ww % 16) && ((ww % 16) < 9) && version10p)
+                       padding = 1;
+               else
+                       padding = 0;
+
+               bytes_per_line = (ww+7)/8 + padding;
+
+               size = bytes_per_line * hh;
+               bits = g_malloc (size);
+
+               if (version10p) {
+                       unsigned char *ptr;
+                       int bytes;
+
+                       for (bytes = 0, ptr = bits; bytes < size; (bytes += 2)) {
+                               if ((value = next_int (fstream)) < 0)
+                                       RETURN (FALSE);
+                               *(ptr++) = value;
+                               if (!padding || ((bytes+2) % bytes_per_line))
+                                       *(ptr++) = value >> 8;
+                       }
+               } else {
+                       unsigned char *ptr;
+                       int bytes;
+
+                       for (bytes = 0, ptr = bits; bytes < size; bytes++, ptr++) {
+                               if ((value = next_int (fstream)) < 0) 
+                                       RETURN (FALSE);
+                               *ptr=value;
+                       }
+               }
+       }
+
+       if (!bits)
+               RETURN (FALSE);
+
+       *data = bits;
+       *width = ww;
+       *height = hh;
+       if (x_hot)
+               *x_hot = hx;
+       if (y_hot)
+               *y_hot = hy;
+
+       return TRUE;
+}
+
+\f
+
+GdkPixbuf *
+gdk_pixbuf__xbm_image_load_real (FILE *f, XBMData *context)
+{
+       guint w, h;
+       int x_hot, y_hot;
+       guchar *data, *ptr;
+       guchar *pixels;
+       guint row_stride;
+       int x, y;
+       int reg, bits;
+
+       int num_pixs;
+       GdkPixbuf *pixbuf;
+
+       if (!read_bitmap_file_data (f, &w, &h, &data, &x_hot, &y_hot)) {
+               g_message ("Invalid XBM file: %s", context->tempname);
+               return NULL;
+       }
+
+       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, w, h);
+       pixels = gdk_pixbuf_get_pixels (pixbuf);
+       row_stride = gdk_pixbuf_get_rowstride (pixbuf);
+
+       if (context)
+               (* context->prepare_func) (pixbuf, context->user_data);
+
+
+       /* Initialize PIXBUF */
+
+       ptr = data;
+       for (y = 0; y < h; y++) {
+               bits = 0;
+               for (x = 0; x < w; x++) {
+                       guchar channel;
+                       if (bits == 0) {
+                               reg = *ptr++;
+                               bits = 8;
+                       }
+
+                       channel = (reg & 1) ? 0 : 255;
+                       reg >>= 1;
+                       bits--;
+
+                       pixels[x*3+0] = channel;
+                       pixels[x*3+1] = channel;
+                       pixels[x*3+2] = channel;
+               }
+               pixels += row_stride;
+       }
+
+       if (context) {
+               (* context->update_func) (pixbuf, 0, 0, w, h, context->user_data);
+               gdk_pixbuf_unref (pixbuf);
+               pixbuf = NULL;
+       }
+
+       return pixbuf;
+}
+
+\f
+/* Static loader */
+
+GdkPixbuf *
+gdk_pixbuf__xbm_image_load (FILE *f)
+{
+       return gdk_pixbuf__xbm_image_load_real (f, NULL);
+}
+
+\f
+/* Progressive loader */
+
+/*
+ * Proper XBM progressive loading isn't implemented.  Instead we write
+ * it to a file, then load the file when it's done.  It's not pretty.
+ */
+
+gpointer
+gdk_pixbuf__xbm_image_begin_load (ModulePreparedNotifyFunc prepare_func,
+                                 ModuleUpdatedNotifyFunc update_func,
+                                 ModuleFrameDoneNotifyFunc frame_done_func,
+                                 ModuleAnimationDoneNotifyFunc anim_done_func,
+                                 gpointer user_data,
+                                 GError **error)
+{
+       XBMData *context;
+       gint fd;
+
+       context = g_new (XBMData, 1);
+       context->prepare_func = prepare_func;
+       context->update_func = update_func;
+       context->user_data = user_data;
+       context->all_okay = TRUE;
+       context->tempname = g_strdup ("/tmp/gdkpixbuf-xbm-tmp.XXXXXX");
+       fd = mkstemp (context->tempname);
+       if (fd < 0) {
+               g_free (context->tempname);
+               g_free (context);
+               return NULL;
+       }
+
+       context->file = fdopen (fd, "w+");
+       if (context->file == NULL) {
+               g_free (context->tempname);
+               g_free (context);
+               return NULL;
+       }
+
+       return context;
+}
+
+void
+gdk_pixbuf__xbm_image_stop_load (gpointer data)
+{
+       XBMData *context = (XBMData*) data;
+
+       g_return_if_fail (data != NULL);
+
+       fflush (context->file);
+       rewind (context->file);
+       if (context->all_okay)
+               gdk_pixbuf__xbm_image_load_real (context->file, context);
+
+       fclose (context->file);
+       unlink (context->tempname);
+       g_free (context->tempname);
+       g_free ((XBMData *) context);
+}
+
+gboolean
+gdk_pixbuf__xbm_image_load_increment (gpointer data, guchar *buf, guint size)
+{
+       XBMData *context = (XBMData *) data;
+
+       g_return_val_if_fail (data != NULL, FALSE);
+
+       if (fwrite (buf, sizeof (guchar), size, context->file) != size) {
+               context->all_okay = FALSE;
+               return FALSE;
+       }
+
+       return TRUE;
+}
diff --git a/gdk-pixbuf/pixbufloader_xbm.def b/gdk-pixbuf/pixbufloader_xbm.def
new file mode 100644 (file)
index 0000000..c25979e
--- /dev/null
@@ -0,0 +1,5 @@
+EXPORTS
+       gdk_pixbuf__xbm_image_load
+       gdk_pixbuf__xbm_image_begin_load
+       gdk_pixbuf__xbm_image_stop_load
+       gdk_pixbuf__xbm_image_load_increment