]> Pileus Git - ~andy/gtk/blobdiff - gdk-pixbuf/gdk-pixbuf-io.c
0.6.0 - Federico
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-io.c
index 7fbcbd3b3d9ee50dbeaa35cdbb97579d69d7f566..491543a277525806f9c98c0d819e05b4121d7fc4 100644 (file)
@@ -23,6 +23,7 @@
 
 #include <config.h>
 #include <string.h>
+#include <glib.h>
 #include "gdk-pixbuf-io.h"
 
 \f
@@ -103,21 +104,8 @@ pixbuf_check_xpm (guchar *buffer, int size)
        return FALSE;
 }
 
-#if 0
 static gboolean
-pixbuf_check_bmp (guchar *buffer, int size)
-{
-       if (size < 20)
-               return FALSE;
-
-       if (buffer [0] != 'B' || buffer [1] != 'M')
-               return FALSE;
-
-       return TRUE;
-}
-
-static gboolean
-pixbuf_check_ppm (guchar *buffer, int size)
+pixbuf_check_pnm (guchar *buffer, int size)
 {
        if (size < 20)
                return FALSE;
@@ -133,131 +121,364 @@ pixbuf_check_ppm (guchar *buffer, int size)
        }
        return FALSE;
 }
-#endif
+static gboolean
+pixbuf_check_sunras (guchar *buffer, int size)
+{
+       if (size < 32)
+               return FALSE;
+
+       if (buffer [0] != 0x59 ||
+           buffer [1] != 0xA6 ||
+           buffer [2] != 0x6A ||
+           buffer [3] != 0x95)
+               return FALSE;
+
+       return TRUE;
+}
+
+static gboolean
+pixbuf_check_ico (guchar *buffer, int size)
+{
+       /* Note that this may cause false positives, but .ico's don't
+          have a magic number.*/
+       if (size < 6)
+               return FALSE;
+       if (buffer [0] != 0x0 ||
+           buffer [1] != 0x0 ||
+           ((buffer [2] != 0x1)&&(buffer[2]!=0x2)) ||
+           buffer [3] != 0x0 ||
+           buffer [5] != 0x0 )
+               return FALSE;
+
+       return TRUE;
+}
+
+
+static gboolean
+pixbuf_check_bmp (guchar *buffer, int size)
+{
+       if (size < 20)
+               return FALSE;
+
+       if (buffer [0] != 'B' || buffer [1] != 'M')
+               return FALSE;
+
+       return TRUE;
+}
 
-ModuleType file_formats [] = {
-       { "png",  pixbuf_check_png,  NULL, NULL, NULL },
-       { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL },
-       { "tiff", pixbuf_check_tiff, NULL, NULL, NULL },
-       { "gif",  pixbuf_check_gif,  NULL, NULL, NULL },
+static GdkPixbufModule file_formats [] = {
+       { "png",  pixbuf_check_png, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { "jpeg", pixbuf_check_jpeg, NULL, NULL, NULL, NULL, NULL, NULL },
+       { "tiff", pixbuf_check_tiff, NULL, NULL, NULL, NULL, NULL, NULL },
+       { "gif",  pixbuf_check_gif, NULL,  NULL, NULL, NULL, NULL, NULL },
 #define XPM_FILE_FORMAT_INDEX 4
-       { "xpm",  pixbuf_check_xpm,  NULL, NULL, NULL },
-#if 0
-       { "bmp",  pixbuf_check_bmp,  NULL, NULL, NULL },
-       { "ppm",  pixbuf_check_ppm,  NULL, NULL, NULL },
-#endif
-       { NULL, NULL, NULL, NULL }
+       { "xpm",  pixbuf_check_xpm, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { "pnm",  pixbuf_check_pnm, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { "ras",  pixbuf_check_sunras, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { "ico",  pixbuf_check_ico, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { "bmp",  pixbuf_check_bmp, NULL,  NULL, NULL, NULL, NULL, NULL },
+       { NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL }
 };
 
-static void
-image_handler_load (ModuleType *image_module)
+#ifdef USE_GMODULE 
+static gboolean
+pixbuf_module_symbol (GModule *module, const char *module_name, const char *symbol_name, gpointer *symbol)
+{
+       char *full_symbol_name = g_strconcat ("gdk_pixbuf__", module_name, "_", symbol_name, NULL);
+       gboolean return_value;
+
+       return_value = g_module_symbol (module, full_symbol_name, symbol);
+       g_free (full_symbol_name);
+       
+       return return_value;
+}
+
+/* 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)
 {
        char *module_name;
        char *path;
        GModule *module;
-       void *load_sym;
-
-        g_return_if_fail(image_module->module == NULL);
-
-       module_name = g_strconcat ("pixbuf-", image_module->module_name, NULL);
+       gpointer load_sym;
+       char *name;
+       
+        g_return_if_fail (image_module->module == NULL);
+
+       name = image_module->module_name;
+       
+       module_name = g_strconcat ("pixbuf-", name, NULL);
        path = g_module_build_path (PIXBUF_LIBDIR, module_name);
-       g_free (module_name);
 
        module = g_module_open (path, G_MODULE_BIND_LAZY);
-       g_free (path);
        if (!module) {
-               g_warning ("Unable to load module: %s", path);
-               return;
-       }
+                /* Debug feature, check in present working directory */
+                g_free (path);
+                path = g_module_build_path ("", module_name);
+                module = g_module_open (path, G_MODULE_BIND_LAZY);
+
+                if (!module) {
+                        g_warning ("Unable to load module: %s: %s", path, g_module_error ());
+                        g_free (module_name);
+                        g_free (path);
+                        return;
+                }
+                g_free (path);
+       } else {
+                g_free (path);
+        }
+
+        g_free (module_name);
 
        image_module->module = module;
 
-       if (g_module_symbol (module, "image_load", &load_sym))
+       if (pixbuf_module_symbol (module, name, "image_load", &load_sym))
                image_module->load = load_sym;
 
-        if (g_module_symbol (module, "image_load_xpm_data", &load_sym))
+        if (pixbuf_module_symbol (module, name, "image_load_xpm_data", &load_sym))
                image_module->load_xpm_data = load_sym;
+
+        if (pixbuf_module_symbol (module, name, "image_begin_load", &load_sym))
+               image_module->begin_load = load_sym;
+
+        if (pixbuf_module_symbol (module, name, "image_stop_load", &load_sym))
+               image_module->stop_load = load_sym;
+
+        if (pixbuf_module_symbol (module, name, "image_load_increment", &load_sym))
+               image_module->load_increment = load_sym;
+
+        if (pixbuf_module_symbol (module, name, "image_load_animation", &load_sym))
+               image_module->load_animation = load_sym;
+}
+#else
+
+#define mname(type,fn) gdk_pixbuf__ ## type ## _image_ ##fn
+#define m_load(type)  extern GdkPixbuf * mname(type,load) (FILE *f);
+#define m_load_xpm_data(type)  extern GdkPixbuf * mname(type,load_xpm_data) (const char **data);
+#define m_begin_load(type)  \
+   extern gpointer mname(type,begin_load) (ModulePreparedNotifyFunc prepare_func, \
+                                ModuleUpdatedNotifyFunc update_func, \
+                                ModuleFrameDoneNotifyFunc frame_done_func,\
+                                ModuleAnimationDoneNotifyFunc anim_done_func,\
+                                gpointer user_data);
+#define m_stop_load(type)  extern void mname(type,stop_load) (gpointer context);
+#define m_load_increment(type)  extern gboolean mname(type,load_increment) (gpointer context, const guchar *buf, guint size);
+#define m_load_animation(type)  extern GdkPixbufAnimation * mname(type,load_animation) (FILE *f);
+
+m_load (png);
+m_begin_load (png);
+m_load_increment (png);
+m_stop_load (png);
+m_load (bmp);
+m_begin_load (bmp);
+m_load_increment (bmp);
+m_stop_load (bmp);
+m_load (gif);
+m_begin_load (gif);
+m_load_increment (gif);
+m_stop_load (gif);
+m_load_animation (gif);
+m_load (ico);
+m_begin_load (ico);
+m_load_increment (ico);
+m_stop_load (ico);
+m_load (jpeg);
+m_begin_load (jpeg);
+m_load_increment (jpeg);
+m_stop_load (jpeg);
+m_load (pnm);
+m_begin_load (pnm);
+m_load_increment (pnm);
+m_stop_load (pnm);
+m_load (ras);
+m_begin_load (ras);
+m_load_increment (ras);
+m_stop_load (ras);
+m_load (tiff);
+m_begin_load (tiff);
+m_load_increment (tiff);
+m_stop_load (tiff);
+m_load (xpm);
+m_load_xpm_data (xpm);
+
+void
+gdk_pixbuf_load_module (GdkPixbufModule *image_module)
+{
+       image_module->module = (void *) 1;
+       
+       if (strcmp (image_module->module_name, "png") == 0){
+               image_module->load           = mname (png,load);
+               image_module->begin_load     = mname (png,begin_load);
+               image_module->load_increment = mname (png,load_increment);
+               image_module->stop_load      = mname (png,stop_load);
+               return;
+       }
+
+       if (strcmp (image_module->module_name, "bmp") == 0){
+               image_module->load           = mname (bmp,load);
+               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;
+       }
+
+       if (strcmp (image_module->module_name, "gif") == 0){
+               image_module->load           = mname (gif,load);
+               image_module->begin_load     = mname (gif,begin_load);
+               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;
+       }
+
+       if (strcmp (image_module->module_name, "ico") == 0){
+               image_module->load           = mname (ico,load);
+               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;
+       }
+
+       if (strcmp (image_module->module_name, "jpeg") == 0){
+               image_module->load           = mname (jpeg,load);
+               image_module->begin_load     = mname (jpeg,begin_load);
+               image_module->load_increment = mname (jpeg,load_increment);
+               image_module->stop_load      = mname (jpeg,stop_load);
+               return;
+       }
+       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;
+       }
+       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;
+       }
+       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;
+       }
+       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;
+       }
 }
 
+
+#endif
+
 \f
 
-ModuleType *
-gdk_pixbuf_get_module (gchar *buffer, gint size)
+GdkPixbufModule *
+gdk_pixbuf_get_module (guchar *buffer, guint size)
 {
-       gint i;
+       int i;
 
        for (i = 0; file_formats [i].module_name; i++) {
                if ((* file_formats [i].format_check) (buffer, size))
                        return &(file_formats[i]);
        }
+
        return NULL;
 }
 
+/**
+ * gdk_pixbuf_new_from_file:
+ * @filename: Name of file to load.
+ *
+ * Creates a new pixbuf by loading an image from a file.  The file format is
+ * detected automatically.
+ *
+ * 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,
+ * there was no loader for the file's format, there was not enough memory to
+ * allocate the image buffer, or the image file contained invalid data.
+ **/
 GdkPixbuf *
 gdk_pixbuf_new_from_file (const char *filename)
 {
        GdkPixbuf *pixbuf;
-       gint size;
+       int size;
        FILE *f;
-       char buffer [128];
-       ModuleType *image_module;
+       guchar buffer [128];
+       GdkPixbufModule *image_module;
+
+       g_return_val_if_fail (filename != NULL, NULL);
 
        f = fopen (filename, "r");
        if (!f)
                return NULL;
 
        size = fread (&buffer, 1, sizeof (buffer), f);
-
        if (size == 0) {
                fclose (f);
                return NULL;
        }
 
        image_module = gdk_pixbuf_get_module (buffer, size);
-       if (image_module){
-               if (!image_module->load)
-                       image_handler_load (image_module);
-
-               if (!image_module->load) {
-                       fclose (f);
-                       return NULL;
-               }
-
-               fseek (f, 0, SEEK_SET);
-               pixbuf = (* image_module->load) (f);
+       if (!image_module) {
+               g_warning ("Unable to find handler for file: %s", filename);
                fclose (f);
+               return NULL;
+       }
 
-               if (pixbuf)
-                       g_assert (pixbuf->ref_count != 0);
+       if (image_module->module == NULL)
+               gdk_pixbuf_load_module (image_module);
 
-               return pixbuf;
-       } else {
-               g_warning ("Unable to find handler for file: %s", filename);
+       if (image_module->load == NULL) {
+               fclose (f);
+               return NULL;
        }
 
+       fseek (f, 0, SEEK_SET);
+       pixbuf = (* image_module->load) (f);
        fclose (f);
-       return NULL;
+
+       if (pixbuf)
+               g_assert (pixbuf->ref_count > 0);
+
+       return pixbuf;
 }
 
+/**
+ * gdk_pixbuf_new_from_xpm_data:
+ * @data: Pointer to inline XPM data.
+ *
+ * Creates a new pixbuf by parsing XPM data in memory.  This data is commonly
+ * the result of including an XPM file into a program's C source.
+ *
+ * Return value: A newly-created pixbuf with a reference count of 1.
+ **/
 GdkPixbuf *
-gdk_pixbuf_new_from_xpm_data (const gchar **data)
+gdk_pixbuf_new_from_xpm_data (const char **data)
 {
-        GdkPixbuf *(* load_xpm_data) (const gchar **data);
-        GdkPixbuf *pixbuf;
-
-        if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
-                image_handler_load(&file_formats[XPM_FILE_FORMAT_INDEX]);
-        }
+       GdkPixbuf *(* load_xpm_data) (const char **data);
+       GdkPixbuf *pixbuf;
 
-        if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
-                g_warning("Can't find gdk-pixbuf module for parsing inline XPM data");
-                return NULL;
-        } else {
-                load_xpm_data = file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data;
-        }
+       if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL)
+               gdk_pixbuf_load_module (&file_formats[XPM_FILE_FORMAT_INDEX]);
 
-        pixbuf = load_xpm_data(data);
+       if (file_formats[XPM_FILE_FORMAT_INDEX].module == NULL) {
+               g_warning ("Can't find gdk-pixbuf module for parsing inline XPM data");
+               return NULL;
+       } else if (file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data == NULL) {
+               g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
+               return NULL;
+       } else
+               load_xpm_data = file_formats[XPM_FILE_FORMAT_INDEX].load_xpm_data;
 
-        return pixbuf;
+       pixbuf = (* load_xpm_data) (data);
+       return pixbuf;
 }
-