Index: b/gdk-pixbuf/Makefile.am
===================================================================
--- a/gdk-pixbuf/Makefile.am	2010-04-10 14:52:04.113943135 +0200
+++ b/gdk-pixbuf/Makefile.am	2010-04-10 14:52:10.065944562 +0200
@@ -65,6 +65,7 @@
 	libgdk_pixbuf-2.0.la
 
 loaderdir = $(libdir)/gtk-2.0/$(GTK_BINARY_VERSION)/loaders
+loaderfilesdir = $(libdir)/gtk-2.0/$(GTK_BINARY_VERSION)/loader-files.d
 
 module_libs = libgdk_pixbuf-$(GTK_API_VERSION).la $(GDK_PIXBUF_DEP_LIBS)
 
@@ -532,7 +533,7 @@
 	$(GDK_PIXBUF_DEP_CFLAGS)		\
 	-DGDK_PIXBUF_ENABLE_BACKEND
 
-AM_CPPFLAGS = "-DPIXBUF_LIBDIR=\"$(loaderdir)\"" "-DBUILT_MODULES_DIR=\"$(srcdir)/.libs\""
+AM_CPPFLAGS = "-DPIXBUF_LIBDIR=\"$(loaderdir)\"" "-DPIXBUF_FILES_LIBDIR=\"$(loaderfilesdir)\"" "-DBUILT_MODULES_DIR=\"$(srcdir)/.libs\""
 LDADDS = libgdk_pixbuf-$(GTK_API_VERSION).la $(GDK_PIXBUF_DEP_LIBS)
 
 noinst_PROGRAMS = test-gdk-pixbuf
Index: b/gdk-pixbuf/gdk-pixbuf-io.c
===================================================================
--- a/gdk-pixbuf/gdk-pixbuf-io.c	2010-04-10 14:52:04.137946193 +0200
+++ b/gdk-pixbuf/gdk-pixbuf-io.c	2010-04-10 14:52:10.065944562 +0200
@@ -51,6 +51,9 @@
 #define SNIFF_BUFFER_SIZE 4096
 #define LOAD_BUFFER_SIZE 65536
 
+#define LOADERFILEEXT ".loaders"
+#define LOADERFILEEXT_LEN ((int) strlen (LOADERFILEEXT))
+
 #ifndef GDK_PIXBUF_USE_GIO_MIME 
 static gint 
 format_check (GdkPixbufModule *module, guchar *buffer, int size)
@@ -317,118 +320,93 @@
 gdk_pixbuf_load_module_unlocked (GdkPixbufModule *image_module,
 				 GError         **error);
 
+/* FIXME this is a static copy of a public pango function which should really
+ * livein glib */
+static char *
+_ugly_copy_of_pango_trim_string (const char *str)
+{
+  int len;
+
+  g_return_val_if_fail (str != NULL, NULL);
+  
+  while (*str && g_ascii_isspace (*str))
+    str++;
+
+  len = strlen (str);
+  while (len > 0 && g_ascii_isspace (str[len-1]))
+    len--;
+
+  return g_strndup (str, len);
+}
+
+/* FIXME this is a static copy of a public pango function which should really
+ * livein glib */
+char **
+_ugly_copy_of_pango_split_file_list (const char *str)
+{
+  int i = 0;
+  int j;
+  char **files;
+
+  files = g_strsplit (str, G_SEARCHPATH_SEPARATOR_S, -1);
+
+  while (files[i])
+    {
+      char *file = _ugly_copy_of_pango_trim_string (files[i]);
+
+      /* If the resulting file is empty, skip it */
+      if (file[0] == '\0')
+	{
+	  g_free(file);
+	  g_free (files[i]);
+	  
+	  for (j = i + 1; files[j]; j++)
+	    files[j - 1] = files[j];
+	  
+	  files[j - 1] = NULL;
+
+	  continue;
+	}
+#ifndef G_OS_WIN32
+      /* '~' is a quite normal and common character in file names on
+       * Windows, especially in the 8.3 versions of long file names, which
+       * still occur now and then. Also, few Windows user are aware of the
+       * Unix shell convention that '~' stands for the home directory,
+       * even if they happen to have a home directory.
+       */
+      if (file[0] == '~' && file[1] == G_DIR_SEPARATOR)
+	{
+	  char *tmp = g_strconcat (g_get_home_dir(), file + 1, NULL);
+	  g_free (file);
+	  file = tmp;
+	}
+      else if (file[0] == '~' && file[1] == '\0')
+	{
+	  g_free (file);
+	  file = g_strdup (g_get_home_dir());
+	}
+#endif
+      g_free (files[i]);
+      files[i] = file;
+	
+      i++;
+    }
+
+  return files;
+}
+
 static void 
-gdk_pixbuf_io_init (void)
+process_module_file (const gchar *filename, GIOChannel *channel)
 {
 #ifdef USE_GMODULE
-	GIOChannel *channel;
 	gchar *line_buf;
 	gsize term;
 	GString *tmp_buf = g_string_new (NULL);
 	gboolean have_error = FALSE;
 	GdkPixbufModule *module = NULL;
-	gchar *filename = gdk_pixbuf_get_module_file ();
 	int flags;
 	int n_patterns = 0;
 	GdkPixbufModulePattern *pattern;
-	GError *error = NULL;
-#endif
-	GdkPixbufModule *builtin_module ;
-
-        /*  initialize on separate line to avoid compiler warnings in the
-         *  common case of no compiled-in modules.
-         */
-	builtin_module = NULL;
-
-#define load_one_builtin_module(format)					\
-	builtin_module = g_new0 (GdkPixbufModule, 1);			\
-	builtin_module->module_name = #format;				\
-	if (gdk_pixbuf_load_module_unlocked (builtin_module, NULL))		\
-		file_formats = g_slist_prepend (file_formats, builtin_module);\
-	else								\
-		g_free (builtin_module)
-
-#ifdef INCLUDE_ani
-	load_one_builtin_module (ani);
-#endif
-#ifdef INCLUDE_png
-	load_one_builtin_module (png);
-#endif
-#ifdef INCLUDE_bmp
-	load_one_builtin_module (bmp);
-#endif
-#ifdef INCLUDE_wbmp
-	load_one_builtin_module (wbmp);
-#endif
-#ifdef INCLUDE_gif
-	load_one_builtin_module (gif);
-#endif
-#ifdef INCLUDE_ico
-	load_one_builtin_module (ico);
-#endif
-#ifdef INCLUDE_jpeg
-	load_one_builtin_module (jpeg);
-#endif
-#ifdef INCLUDE_pnm
-	load_one_builtin_module (pnm);
-#endif
-#ifdef INCLUDE_ras
-	load_one_builtin_module (ras);
-#endif
-#ifdef INCLUDE_tiff
-	load_one_builtin_module (tiff);
-#endif
-#ifdef INCLUDE_xpm
-	load_one_builtin_module (xpm);
-#endif
-#ifdef INCLUDE_xbm
-	load_one_builtin_module (xbm);
-#endif
-#ifdef INCLUDE_tga
-	load_one_builtin_module (tga);
-#endif
-#ifdef INCLUDE_pcx
-	load_one_builtin_module (pcx);
-#endif
-#ifdef INCLUDE_icns
-	load_one_builtin_module (icns);
-#endif
-#ifdef INCLUDE_jasper
-	load_one_builtin_module (jasper);
-#endif
-#ifdef INCLUDE_qtif
-	load_one_builtin_module (qtif);
-#endif
-#ifdef INCLUDE_gdiplus
-	/* We don't bother having the GDI+ loaders individually selectable
-	 * for building in or not.
-	 */
-	load_one_builtin_module (ico);
-	load_one_builtin_module (wmf);
-	load_one_builtin_module (emf);
-	load_one_builtin_module (bmp);
-	load_one_builtin_module (gif);
-	load_one_builtin_module (jpeg);
-	load_one_builtin_module (tiff);
-#endif
-#ifdef INCLUDE_gdip_png
-	/* Except the gdip-png loader which normally isn't built at all even */
-	load_one_builtin_module (png);
-#endif
-
-#undef load_one_builtin_module
-
-#ifdef USE_GMODULE
-	channel = g_io_channel_new_file (filename, "r",  &error);
-	if (!channel) {
-		/* Don't bother warning if we have some built-in loaders */
-		if (file_formats == NULL)
-			g_warning ("Cannot open pixbuf loader module file '%s': %s",
-				   filename, error->message);
-		g_string_free (tmp_buf, TRUE);
-		g_free (filename);
-		return;
-	}
 	
 	while (!have_error && g_io_channel_read_line (channel, &line_buf, NULL, &term, NULL) == G_IO_STATUS_NORMAL) {
 		const char *p;
@@ -566,8 +544,159 @@
 		g_free (line_buf);
 	}
 	g_string_free (tmp_buf, TRUE);
-	g_io_channel_unref (channel);
-	g_free (filename);
+#endif /* USE_GMODULE */
+}
+
+
+static void 
+gdk_pixbuf_io_init (void)
+{
+#ifdef USE_GMODULE
+	GIOChannel *channel;
+	gchar *gdkpixbuf_module_file_str = gdk_pixbuf_get_module_file ();
+	gchar *list_str;
+	char **files;
+	GError *error = NULL;
+	int n;
+#endif
+	GdkPixbufModule *builtin_module = NULL;
+
+#define load_one_builtin_module(format)					\
+	builtin_module = g_new0 (GdkPixbufModule, 1);			\
+	builtin_module->module_name = #format;				\
+	if (gdk_pixbuf_load_module_unlocked (builtin_module, NULL))		\
+		file_formats = g_slist_prepend (file_formats, builtin_module);\
+	else								\
+		g_free (builtin_module)
+
+#ifdef INCLUDE_ani
+	load_one_builtin_module (ani);
+#endif
+#ifdef INCLUDE_png
+	load_one_builtin_module (png);
+#endif
+#ifdef INCLUDE_bmp
+	load_one_builtin_module (bmp);
+#endif
+#ifdef INCLUDE_wbmp
+	load_one_builtin_module (wbmp);
+#endif
+#ifdef INCLUDE_gif
+	load_one_builtin_module (gif);
+#endif
+#ifdef INCLUDE_ico
+	load_one_builtin_module (ico);
+#endif
+#ifdef INCLUDE_jpeg
+	load_one_builtin_module (jpeg);
+#endif
+#ifdef INCLUDE_pnm
+	load_one_builtin_module (pnm);
+#endif
+#ifdef INCLUDE_ras
+	load_one_builtin_module (ras);
+#endif
+#ifdef INCLUDE_tiff
+	load_one_builtin_module (tiff);
+#endif
+#ifdef INCLUDE_xpm
+	load_one_builtin_module (xpm);
+#endif
+#ifdef INCLUDE_xbm
+	load_one_builtin_module (xbm);
+#endif
+#ifdef INCLUDE_tga
+	load_one_builtin_module (tga);
+#endif
+#ifdef INCLUDE_pcx
+	load_one_builtin_module (pcx);
+#endif
+#ifdef INCLUDE_icns
+	load_one_builtin_module (icns);
+#endif
+#ifdef INCLUDE_jasper
+	load_one_builtin_module (jasper);
+#endif
+#ifdef INCLUDE_qtif
+	load_one_builtin_module (qtif);
+#endif
+#ifdef INCLUDE_gdiplus
+	/* We don't bother having the GDI+ loaders individually selectable
+	 * for building in or not.
+	 */
+	load_one_builtin_module (ico);
+	load_one_builtin_module (wmf);
+	load_one_builtin_module (emf);
+	load_one_builtin_module (bmp);
+	load_one_builtin_module (gif);
+	load_one_builtin_module (jpeg);
+	load_one_builtin_module (tiff);
+#endif
+#ifdef INCLUDE_gdip_png
+	/* Except the gdip-png loader which normally isn't built at all even */
+	load_one_builtin_module (png);
+#endif
+
+#undef load_one_builtin_module
+
+#ifdef USE_GMODULE
+	list_str = g_strjoin (G_SEARCHPATH_SEPARATOR_S,
+			      gdkpixbuf_module_file_str,
+			      PIXBUF_FILES_LIBDIR,
+			      NULL);
+
+	files = _ugly_copy_of_pango_split_file_list (list_str);
+
+	n = 0;
+	while (files[n])
+		n++;
+
+	while (n-- > 0) {
+		GDir *dir = g_dir_open (files[n], 0, NULL);
+		if (dir) {
+			const char *dent;
+
+			while ((dent = g_dir_read_name (dir))) {
+				int len = strlen (dent);
+				if (len > LOADERFILEEXT_LEN && strcmp (dent + len - LOADERFILEEXT_LEN, LOADERFILEEXT) == 0) {
+					gchar *pathname = g_build_filename (files[n], dent, NULL);
+					channel = g_io_channel_new_file (pathname, "r",  &error);
+					if (!channel) {
+						/* we don't care about issuing a warning
+						 * g_warning ("Cannot open pixbuf loader module file '%s': %s",
+						 *	   pathname,
+						 *	   error->message);
+						 */
+						g_error_free (error);
+						error = NULL;
+					} else {
+						process_module_file (pathname, channel);
+						g_io_channel_unref (channel);
+					}
+					g_free (pathname);
+				}
+			}
+			g_dir_close (dir);
+		} else {
+			channel = g_io_channel_new_file (files[n], "r", &error);
+			if (!channel) {
+				/* we don't care about issuing a warning
+				 * g_warning ("Cannot open pixbuf loader module file '%s': %s",
+				 *	   files[n],
+				 *	   error->message);
+				 */
+				g_error_free (error);
+				error = NULL;
+			} else {
+				process_module_file (files[n], channel);
+				g_io_channel_unref (channel);
+			}
+		}
+	}
+
+	g_strfreev (files);
+	g_free (list_str);
+	g_free (gdkpixbuf_module_file_str);
 #endif
 }
 
