gtk+ r19914 - in trunk: . gdk-pixbuf



Author: tml
Date: Thu Mar 20 23:24:45 2008
New Revision: 19914
URL: http://svn.gnome.org/viewvc/gtk+?rev=19914&view=rev

Log:
2008-03-21  Tor Lillqvist  <tml novell com>

	Import the GDI+ gdk-pixbuf loaders for Windows by Dominic
	Lachowicz and Alberto Ruiz into the GTK+ tree, from the
	gdip-pixbuf-loader module.

	* configure.in: Add switch --disable-gdiplus-loaders that disables
	building of the GDI+ loaders.

	When including loaders in the gdk-pixbuf library, either build in
	abll the GDI+ ones or none of them. Use just -DINCLUDE_gdiplus in
	$INCLUDED_LOADER_DEFINE to signal building them in.

	Add Automake conditionals BUILD_GDIPLUS_LOADERS to indicate
	whether the GDI+ loaders should be built and INCLUDE_GDIPLUS to
	indicate whether they should be built-in.
	
	For the rest of the changes, see gdk-pixbuf/ChangeLog.

	In gdk-pixbuf:

	* Makefile.am: Add the bits and pieces for the GDI+ loaders. When
	building GDI+ loaders don't build the traditional ones for the
	same formats. Always build the traditional PNG loader, though, as
	it isn't possible to read and write PNG tEXt chunks through GDI+,
	and GIMP at least needs that functionality in the gdk-pixbuf PNG
	loader. 

	Either build all the GDI+ loaders (except the PNG one) into
	libgdk-pixbuf, or build them all as DLLs. I don't see any reason
	to enable cherry-picking among them whether to build in or not.

	* io-gdip-animation.c
	* io-gdip-animation.h
	* io-gdip-bmp.c
	* io-gdip-emf.c
	* io-gdip-gif.c
	* io-gdip-ico.c
	* io-gdip-jpeg.c
	* io-gdip-native.h
	* io-gdip-png.c
	* io-gdip-propertytags.h
	* io-gdip-tiff.c
	* io-gdip-utils.c
	* io-gdip-utils.h
	* io-gdip-wmf.c: New files. Note that io-gdip-png.c is not
	currently used.

	* gdk-pixbuf-io.c: Add the bits and pieces for built-in GDI+
	loaders.



Added:
   trunk/gdk-pixbuf/io-gdip-animation.c
   trunk/gdk-pixbuf/io-gdip-animation.h
   trunk/gdk-pixbuf/io-gdip-bmp.c
   trunk/gdk-pixbuf/io-gdip-emf.c
   trunk/gdk-pixbuf/io-gdip-gif.c
   trunk/gdk-pixbuf/io-gdip-ico.c
   trunk/gdk-pixbuf/io-gdip-jpeg.c
   trunk/gdk-pixbuf/io-gdip-native.h
   trunk/gdk-pixbuf/io-gdip-png.c
   trunk/gdk-pixbuf/io-gdip-propertytags.h
   trunk/gdk-pixbuf/io-gdip-tiff.c
   trunk/gdk-pixbuf/io-gdip-utils.c
   trunk/gdk-pixbuf/io-gdip-utils.h
   trunk/gdk-pixbuf/io-gdip-wmf.c
Modified:
   trunk/ChangeLog
   trunk/configure.in
   trunk/gdk-pixbuf/ChangeLog
   trunk/gdk-pixbuf/Makefile.am
   trunk/gdk-pixbuf/gdk-pixbuf-io.c

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Thu Mar 20 23:24:45 2008
@@ -783,7 +783,14 @@
             [AC_HELP_STRING([--without-libjasper],
                             [disable JPEG2000 loader for gdk-pixbuf])])
 
+AC_ARG_ENABLE(gdiplus,
+            [AC_HELP_STRING([--disable-gdiplus-loaders],
+                            [disable GDI+ loaders for gdk-pixbuf])])
+
+AM_CONDITIONAL(BUILD_GDIPLUS_LOADERS, [ test x$os_win32 = xyes && test x$enable_gdiplus != xno ])
+
 dnl Test for libtiff
+if test x$os_win32 = xno || test x$enable_gdiplus = xno; then
   if test x$with_libtiff != xno && test -z "$LIBTIFF"; then
     AC_CHECK_LIB(tiff, TIFFReadRGBAImageOriented,
       [AC_CHECK_HEADER(tiffio.h,
@@ -806,8 +813,10 @@
 *** --without-libtiff to configure but some programs using GTK+ may
 *** not work properly])
   fi
+fi
 
 dnl Test for libjpeg
+if test x$os_win32 = xno || test x$enable_gdiplus = xno; then
   if test x$with_libjpeg != xno && test -z "$LIBJPEG"; then
     AC_CHECK_LIB(jpeg, jpeg_destroy_decompress,
       jpeg_ok=yes,
@@ -842,6 +851,7 @@
 *** --without-libjpeg to configure but some programs using GTK+ may
 *** not work properly])
   fi
+fi
 
 dnl Test for libpng
   if test x$with_libpng != xno && test -z "$LIBPNG"; then
@@ -924,10 +934,23 @@
    fi
 fi
 
-all_loaders="png,bmp,wbmp,gif,ico,ani,jpeg,pnm,ras,tiff,xpm,xbm,tga,pcx,icns"
+# Use the traditional png loader instead of the GDI+ one on Windows,
+# because some important apps like GIMP need to read and write
+# arbitrary tEXt chunks which doesn't seem to be possible through GDI+
+
+all_loaders="ani,icns,pcx,ras,tga,png,pnm,wbmp,xbm,xpm"
 if test x$with_libjasper != xno; then
   all_loaders="$all_loaders,jasper"
 fi
+if test x$os_win32 = xyes && test x$enable_gdiplus != xno; then
+  # Skip PNG, see comment above
+  gdip_formats="bmp emf gif ico jpeg tiff wmf"
+  for f in $gdip_formats; do
+    all_loaders="$all_loaders,gdip-$f"
+  done
+else
+  all_loaders="$all_loaders,bmp,gif,ico,jpeg,tiff"
+fi
 included_loaders=""
 # If no loaders specified, include all
 if test "x$with_included_loaders" = xyes ; then
@@ -949,10 +972,23 @@
    AC_MSG_ERROR([the specified loader $loader does not exist])
  fi
 
+ loader_underscores=`echo $loader | sed -e 's/-/_/g'`
  INCLUDED_LOADER_OBJ="$INCLUDED_LOADER_OBJ libstatic-pixbufloader-$loader.la"
- INCLUDED_LOADER_DEFINE="$INCLUDED_LOADER_DEFINE -DINCLUDE_$loader"
- eval INCLUDE_$loader=yes
+
+ # Don't bother defining separate -DINCLUDE_gdip_foo for each gdip-foo loader
+ case $loader in
+   gdip-*) ;;
+   *) INCLUDED_LOADER_DEFINE="$INCLUDED_LOADER_DEFINE -DINCLUDE_$loader_underscores";;
+ esac
+ eval INCLUDE_$loader_underscores=yes
 done
+
+# Just define one -DINCLUDE_gdiplus for all the gdip-foo loaders
+# (except gdip-png, which isn't built at all)
+if test x"$INCLUDE_gdip_ico" = xyes; then
+  INCLUDED_LOADER_DEFINE="$INCLUDED_LOADER_DEFINE -DINCLUDE_gdiplus"
+fi
+
 IFS="$gtk_save_ifs"
 AC_SUBST(INCLUDED_LOADER_OBJ)
 AC_SUBST(INCLUDED_LOADER_DEFINE)
@@ -973,6 +1009,9 @@
 AM_CONDITIONAL(INCLUDE_PCX, [test x"$INCLUDE_pcx" = xyes])
 AM_CONDITIONAL(INCLUDE_ICNS, [test x"$INCLUDE_icns" = xyes])
 AM_CONDITIONAL(INCLUDE_JASPER, [test x"$INCLUDE_jasper" = xyes])
+# As all GDI+ loaders are either built-in or not, arbitrarily just
+# check one of the variables here
+AM_CONDITIONAL(INCLUDE_GDIPLUS, [test x"$INCLUDE_gdip_ico" = xyes])
 
 #
 # Allow building some or all immodules included
@@ -1147,7 +1186,7 @@
 AM_CONDITIONAL(USE_MMX, test x$use_mmx_asm = xyes)
 
 REBUILD_PNGS=
-if test -z "$LIBPNG"; then
+if test -z "$LIBPNG" && test x"$os_win32" = xno -o x$enable_gdiplus = xno; then
   REBUILD_PNGS=#
 fi
 

Modified: trunk/gdk-pixbuf/Makefile.am
==============================================================================
--- trunk/gdk-pixbuf/Makefile.am	(original)
+++ trunk/gdk-pixbuf/Makefile.am	Thu Mar 20 23:24:45 2008
@@ -13,6 +13,8 @@
 gdk_pixbuf_win32_res = gdk_pixbuf-win32-res.o
 gdk_pixbuf_win32_res_ldflag = -Wl,gdk_pixbuf-win32-res.o
 
+libole32 = -lole32
+
 gdk_pixbuf-win32-res.o : gdk_pixbuf.rc
 	$(WINDRES) gdk_pixbuf.rc $@
 
@@ -64,10 +66,10 @@
 #
 # The PNG loader
 #
+libstatic_pixbufloader_png_la_SOURCES = io-png.c
 libpixbufloader_png_la_SOURCES = io-png.c
 libpixbufloader_png_la_LDFLAGS = -avoid-version -module $(no_undefined)
 libpixbufloader_png_la_LIBADD = $(LIBPNG) $(module_libs)
-libstatic_pixbufloader_png_la_SOURCES = io-png.c
 
 #
 # The BMP loader
@@ -189,26 +191,163 @@
 libpixbufloader_jasper_la_LDFLAGS = -avoid-version -module $(no_undefined)
 libpixbufloader_jasper_la_LIBADD = $(LIBJASPER) $(module_libs)
 
-if HAVE_PNG
-if INCLUDE_PNG
-STATIC_PNG_LIB = libstatic-pixbufloader-png.la
-else
-PNG_LIB = libpixbufloader-png.la
-endif
+if BUILD_GDIPLUS_LOADERS
+
+if INCLUDE_GDIPLUS
+
+# When building the GDI+ loader statically, we put the "common" objects
+# only in one of the archives to avoid duplicate definitions
+
+STATIC_GDIPLUS_LIBS = \
+	libstatic-pixbufloader-gdip-ico.la \
+	libstatic-pixbufloader-gdip-wmf.la \
+	libstatic-pixbufloader-gdip-emf.la \
+	libstatic-pixbufloader-gdip-bmp.la \
+	libstatic-pixbufloader-gdip-gif.la \
+	libstatic-pixbufloader-gdip-jpeg.la \
+	libstatic-pixbufloader-gdip-tiff.la
+
+libstatic_pixbufloader_gdip_ico_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-ico.c
+
+libstatic_pixbufloader_gdip_wmf_la_SOURCES = 	\
+	io-gdip-wmf.c
+
+libstatic_pixbufloader_gdip_emf_la_SOURCES = 	\
+	io-gdip-emf.c
+
+libstatic_pixbufloader_gdip_bmp_la_SOURCES = 	\
+	io-gdip-bmp.c
+
+libstatic_pixbufloader_gdip_gif_la_SOURCES = 	\
+	io-gdip-gif.c
+
+libstatic_pixbufloader_gdip_jpeg_la_SOURCES = 	\
+	io-gdip-jpeg.c
+
+libstatic_pixbufloader_gdip_png_la_SOURCES = 	\
+	io-gdip-png.c
+
+libstatic_pixbufloader_gdip_tiff_la_SOURCES = 	\
+	io-gdip-tiff.c
+
+else
+
+GDIPLUS_LIBS = \
+	libpixbufloader-gdip-ico.la \
+	libpixbufloader-gdip-wmf.la \
+	libpixbufloader-gdip-emf.la \
+	libpixbufloader-gdip-bmp.la \
+	libpixbufloader-gdip-gif.la \
+	libpixbufloader-gdip-jpeg.la \
+	libpixbufloader-gdip-tiff.la
+
+libpixbufloader_gdip_ico_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_ico_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-ico.c
+libpixbufloader_gdip_ico_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_wmf_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_wmf_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-wmf.c
+libpixbufloader_gdip_wmf_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_emf_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_emf_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-emf.c
+libpixbufloader_gdip_emf_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_bmp_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_bmp_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-bmp.c
+libpixbufloader_gdip_bmp_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_gif_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_gif_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-gif.c
+libpixbufloader_gdip_gif_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_jpeg_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_jpeg_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-jpeg.c
+libpixbufloader_gdip_jpeg_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_png_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_png_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-png.c
+libpixbufloader_gdip_png_la_LIBADD = $(module_libs) $(libole32)
+
+libpixbufloader_gdip_tiff_la_LDFLAGS = -avoid-version -module -no-undefined
+libpixbufloader_gdip_tiff_la_SOURCES = 	\
+	io-gdip-native.h		\
+	io-gdip-propertytags.h		\
+	io-gdip-utils.h			\
+	io-gdip-utils.c			\
+	io-gdip-animation.c		\
+	io-gdip-animation.h		\
+	io-gdip-tiff.c
+libpixbufloader_gdip_tiff_la_LIBADD = $(module_libs) $(libole32)
+
 endif
 
+else
+
+# Loaders that aren't built if we build the GDI+ loader
+
 if INCLUDE_BMP
 STATIC_BMP_LIB = libstatic-pixbufloader-bmp.la
 else
 BMP_LIB = libpixbufloader-bmp.la
 endif
 
-if INCLUDE_WBMP
-STATIC_WBMP_LIB = libstatic-pixbufloader-wbmp.la
-else
-WBMP_LIB = libpixbufloader-wbmp.la
-endif
-
 if INCLUDE_GIF
 STATIC_GIF_LIB = libstatic-pixbufloader-gif.la
 else
@@ -221,12 +360,6 @@
 ICO_LIB = libpixbufloader-ico.la
 endif
 
-if INCLUDE_ANI
-STATIC_ANI_LIB = libstatic-pixbufloader-ani.la
-else
-ANI_LIB = libpixbufloader-ani.la
-endif
-
 if HAVE_JPEG
 if INCLUDE_JPEG
 STATIC_JPEG_LIB = libstatic-pixbufloader-jpeg.la
@@ -235,6 +368,37 @@
 endif
 endif
 
+if HAVE_TIFF
+if INCLUDE_TIFF
+STATIC_TIFF_LIB = libstatic-pixbufloader-tiff.la
+else
+TIFF_LIB = libpixbufloader-tiff.la
+endif
+endif
+
+# End of loaders not built if building GDI+ loader
+endif
+
+if HAVE_PNG
+if INCLUDE_PNG
+STATIC_PNG_LIB = libstatic-pixbufloader-png.la
+else
+PNG_LIB = libpixbufloader-png.la
+endif
+endif
+
+if INCLUDE_WBMP
+STATIC_WBMP_LIB = libstatic-pixbufloader-wbmp.la
+else
+WBMP_LIB = libpixbufloader-wbmp.la
+endif
+
+if INCLUDE_ANI
+STATIC_ANI_LIB = libstatic-pixbufloader-ani.la
+else
+ANI_LIB = libpixbufloader-ani.la
+endif
+
 if INCLUDE_PNM
 STATIC_PNM_LIB = libstatic-pixbufloader-pnm.la
 else
@@ -247,14 +411,6 @@
 RAS_LIB = libpixbufloader-ras.la
 endif
 
-if HAVE_TIFF
-if INCLUDE_TIFF
-STATIC_TIFF_LIB = libstatic-pixbufloader-tiff.la
-else
-TIFF_LIB = libpixbufloader-tiff.la
-endif
-endif
-
 if INCLUDE_XPM
 STATIC_XPM_LIB = libstatic-pixbufloader-xpm.la
 else
@@ -311,7 +467,8 @@
 	$(TGA_LIB)	\
 	$(ICNS_LIB)	\
 	$(PCX_LIB)	\
-	$(JASPER_LIB)
+	$(JASPER_LIB)	\
+	$(GDIPLUS_LIBS)
 
 
 endif
@@ -332,7 +489,8 @@
 	$(STATIC_TGA_LIB)	\
 	$(STATIC_ICNS_LIB)	\
 	$(STATIC_PCX_LIB)	\
-	$(STATIC_JASPER_LIB)
+	$(STATIC_JASPER_LIB)	\
+	$(STATIC_GDIPLUS_LIBS)
 
 builtin_objs = @INCLUDED_LOADER_OBJ@
 
@@ -394,7 +552,7 @@
 	$(gdk_pixbuf_symbols)
 
 
-libgdk_pixbuf_2_0_la_LIBADD = pixops/libpixops.la $(builtin_objs) $(GDK_PIXBUF_DEP_LIBS)
+libgdk_pixbuf_2_0_la_LIBADD = pixops/libpixops.la $(builtin_objs) $(GDK_PIXBUF_DEP_LIBS) $(libole32)
 libgdk_pixbuf_2_0_la_DEPENDENCIES = pixops/libpixops.la $(builtin_objs) $(gdk_pixbuf_def) $(gdk_pixbuf_win32_res)
 
 gdk_pixbuf_headers = 			\

Modified: trunk/gdk-pixbuf/gdk-pixbuf-io.c
==============================================================================
--- trunk/gdk-pixbuf/gdk-pixbuf-io.c	(original)
+++ trunk/gdk-pixbuf/gdk-pixbuf-io.c	Thu Mar 20 23:24:45 2008
@@ -363,6 +363,22 @@
 #ifdef INCLUDE_pcx
 	load_one_builtin_module (pcx);
 #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
 
@@ -576,6 +592,14 @@
 module (xbm);
 module (tga);
 module (pcx);
+module (gdip_ico);
+module (gdip_wmf);
+module (gdip_emf);
+module (gdip_bmp);
+module (gdip_gif);
+module (gdip_jpeg);
+module (gdip_png);
+module (gdip_tiff);
 
 #undef module
 
@@ -588,53 +612,65 @@
 	GdkPixbufModuleFillInfoFunc fill_info = NULL;
         GdkPixbufModuleFillVtableFunc fill_vtable = NULL;
 
-#define try_module(format)						\
+#define try_module(format,id)						\
 	if (fill_info == NULL &&					\
 	    strcmp (image_module->module_name, #format) == 0) {		\
-                fill_info = _gdk_pixbuf__##format##_fill_info;		\
-                fill_vtable = _gdk_pixbuf__##format##_fill_vtable;	\
+                fill_info = _gdk_pixbuf__##id##_fill_info;		\
+                fill_vtable = _gdk_pixbuf__##id##_fill_vtable;	\
 	}
 #ifdef INCLUDE_png	
-	try_module (png);
+	try_module (png,png);
 #endif
 #ifdef INCLUDE_bmp
-	try_module (bmp);
+	try_module (bmp,bmp);
 #endif
 #ifdef INCLUDE_wbmp
-	try_module (wbmp);
+	try_module (wbmp,wbmp);
 #endif
 #ifdef INCLUDE_gif
-	try_module (gif);
+	try_module (gif,gif);
 #endif
 #ifdef INCLUDE_ico
-	try_module (ico);
+	try_module (ico,ico);
 #endif
 #ifdef INCLUDE_ani
-	try_module (ani);
+	try_module (ani,ani);
 #endif
 #ifdef INCLUDE_jpeg
-	try_module (jpeg);
+	try_module (jpeg,jpeg);
 #endif
 #ifdef INCLUDE_pnm
-	try_module (pnm);
+	try_module (pnm,pnm);
 #endif
 #ifdef INCLUDE_ras
-	try_module (ras);
+	try_module (ras,ras);
 #endif
 #ifdef INCLUDE_tiff
-	try_module (tiff);
+	try_module (tiff,tiff);
 #endif
 #ifdef INCLUDE_xpm
-	try_module (xpm);
+	try_module (xpm,xpm);
 #endif
 #ifdef INCLUDE_xbm
-	try_module (xbm);
+	try_module (xbm,xbm);
 #endif
 #ifdef INCLUDE_tga
-	try_module (tga);
+	try_module (tga,tga);
 #endif
 #ifdef INCLUDE_pcx
-	try_module (pcx);
+	try_module (pcx,pcx);
+#endif
+#ifdef INCLUDE_gdiplus
+	try_module (ico,gdip_ico);
+	try_module (wmf,gdip_wmf);
+	try_module (emf,gdip_emf);
+	try_module (bmp,gdip_bmp);
+	try_module (gif,gdip_gif);
+	try_module (jpeg,gdip_jpeg);
+	try_module (tiff,gdip_tiff);
+#endif
+#ifdef INCLUDE_gdip_png
+	try_module (png,gdip_png);
 #endif
 
 #undef try_module

Added: trunk/gdk-pixbuf/io-gdip-animation.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-animation.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,383 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - animated gdip support
+ *
+ * Copyright (C) 1999 The Free Software Foundation
+ *
+ * Authors: Jonathan Blandford <jrb redhat com>
+ *          Havoc Pennington <hp redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include <errno.h>
+#include "io-gdip-native.h"
+#include "io-gdip-animation.h"
+
+static void gdk_pixbuf_gdip_anim_class_init (GdkPixbufGdipAnimClass *klass);
+static void gdk_pixbuf_gdip_anim_finalize   (GObject        *object);
+
+static gboolean                gdk_pixbuf_gdip_anim_is_static_image  (GdkPixbufAnimation *animation);
+static GdkPixbuf*              gdk_pixbuf_gdip_anim_get_static_image (GdkPixbufAnimation *animation);
+
+static void                    gdk_pixbuf_gdip_anim_get_size (GdkPixbufAnimation *anim,
+                                                             int                *width,
+                                                             int                *height);
+static GdkPixbufAnimationIter* gdk_pixbuf_gdip_anim_get_iter (GdkPixbufAnimation *anim,
+                                                             const GTimeVal     *start_time);
+
+static gpointer parent_class;
+
+GType
+gdk_pixbuf_gdip_anim_get_type (void)
+{
+        static GType object_type = 0;
+
+        if (!object_type) {
+                static const GTypeInfo object_info = {
+                        sizeof (GdkPixbufGdipAnimClass),
+                        (GBaseInitFunc) NULL,
+                        (GBaseFinalizeFunc) NULL,
+                        (GClassInitFunc) gdk_pixbuf_gdip_anim_class_init,
+                        NULL,           /* class_finalize */
+                        NULL,           /* class_data */
+                        sizeof (GdkPixbufGdipAnim),
+                        0,              /* n_preallocs */
+                        (GInstanceInitFunc) NULL,
+                };
+
+                object_type = g_type_from_name ("GdkPixbufGdipAnim");
+                if (object_type == 0) {
+                  object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION,
+                                                        g_intern_static_string ("GdkPixbufGdipAnim"),
+                                                        &object_info, 0);
+                }
+        }
+        
+        return object_type;
+}
+
+static void
+gdk_pixbuf_gdip_anim_class_init (GdkPixbufGdipAnimClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        GdkPixbufAnimationClass *anim_class = GDK_PIXBUF_ANIMATION_CLASS (klass);
+        
+        parent_class = g_type_class_peek_parent (klass);
+        
+        object_class->finalize = gdk_pixbuf_gdip_anim_finalize;
+
+        anim_class->is_static_image = gdk_pixbuf_gdip_anim_is_static_image;
+        anim_class->get_static_image = gdk_pixbuf_gdip_anim_get_static_image;
+        anim_class->get_size = gdk_pixbuf_gdip_anim_get_size;
+        anim_class->get_iter = gdk_pixbuf_gdip_anim_get_iter;
+}
+
+static void
+gdk_pixbuf_gdip_anim_finalize (GObject *object)
+{
+        GdkPixbufGdipAnim *gdip_anim = GDK_PIXBUF_GDIP_ANIM (object);
+
+        GList *l;
+        GdkPixbufFrame *frame;
+        
+        for (l = gdip_anim->frames; l; l = l->next) {
+                frame = l->data;
+                g_object_unref (frame->pixbuf);
+                g_free (frame);
+        }
+        
+        g_list_free (gdip_anim->frames);
+        
+        G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gdk_pixbuf_gdip_anim_is_static_image  (GdkPixbufAnimation *animation)
+{
+        GdkPixbufGdipAnim *gdip_anim;
+
+        gdip_anim = GDK_PIXBUF_GDIP_ANIM (animation);
+
+        return (gdip_anim->frames != NULL &&
+                gdip_anim->frames->next == NULL);
+}
+
+static GdkPixbuf*
+gdk_pixbuf_gdip_anim_get_static_image (GdkPixbufAnimation *animation)
+{
+        GdkPixbufGdipAnim *gdip_anim;
+
+        gdip_anim = GDK_PIXBUF_GDIP_ANIM (animation);
+
+        if (gdip_anim->frames == NULL)
+                return NULL;
+        else
+                return GDK_PIXBUF (((GdkPixbufFrame*)gdip_anim->frames->data)->pixbuf);        
+}
+
+static void
+gdk_pixbuf_gdip_anim_get_size (GdkPixbufAnimation *anim,
+                              int                *width,
+                              int                *height)
+{
+        GdkPixbufGdipAnim *gdip_anim;
+
+        gdip_anim = GDK_PIXBUF_GDIP_ANIM (anim);
+
+        if (width)
+                *width = gdip_anim->width;
+
+        if (height)
+                *height = gdip_anim->height;
+}
+
+
+static void
+iter_clear (GdkPixbufGdipAnimIter *iter)
+{
+        iter->current_frame = NULL;
+}
+
+static void
+iter_restart (GdkPixbufGdipAnimIter *iter)
+{
+        iter_clear (iter);
+  
+        iter->current_frame = iter->gdip_anim->frames;
+}
+
+static GdkPixbufAnimationIter*
+gdk_pixbuf_gdip_anim_get_iter (GdkPixbufAnimation *anim,
+                              const GTimeVal     *start_time)
+{
+        GdkPixbufGdipAnimIter *iter;
+
+        iter = g_object_new (GDK_TYPE_PIXBUF_GDIP_ANIM_ITER, NULL);
+
+        iter->gdip_anim = GDK_PIXBUF_GDIP_ANIM (anim);
+
+        g_object_ref (iter->gdip_anim);
+        
+        iter_restart (iter);
+
+        iter->start_time = *start_time;
+        iter->current_time = *start_time;
+        iter->first_loop_slowness = 0;
+        
+        return GDK_PIXBUF_ANIMATION_ITER (iter);
+}
+
+static void gdk_pixbuf_gdip_anim_iter_class_init (GdkPixbufGdipAnimIterClass *klass);
+static void gdk_pixbuf_gdip_anim_iter_finalize   (GObject                   *object);
+
+static int        gdk_pixbuf_gdip_anim_iter_get_delay_time             (GdkPixbufAnimationIter *iter);
+static GdkPixbuf* gdk_pixbuf_gdip_anim_iter_get_pixbuf                 (GdkPixbufAnimationIter *iter);
+static gboolean   gdk_pixbuf_gdip_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *iter);
+static gboolean   gdk_pixbuf_gdip_anim_iter_advance                    (GdkPixbufAnimationIter *iter,
+                                                                       const GTimeVal         *current_time);
+
+static gpointer iter_parent_class;
+
+GType
+gdk_pixbuf_gdip_anim_iter_get_type (void)
+{
+        static GType object_type = 0;
+
+        if (!object_type) {
+                static const GTypeInfo object_info = {
+                        sizeof (GdkPixbufGdipAnimIterClass),
+                        (GBaseInitFunc) NULL,
+                        (GBaseFinalizeFunc) NULL,
+                        (GClassInitFunc) gdk_pixbuf_gdip_anim_iter_class_init,
+                        NULL,           /* class_finalize */
+                        NULL,           /* class_data */
+                        sizeof (GdkPixbufGdipAnimIter),
+                        0,              /* n_preallocs */
+                        (GInstanceInitFunc) NULL,
+                };
+                
+                object_type = g_type_from_name ("GdkPixbufGdipAnimIter");
+                if (object_type == 0) {
+                  object_type = g_type_register_static (GDK_TYPE_PIXBUF_ANIMATION_ITER,
+                                                        g_intern_static_string ("GdkPixbufGdipAnimIter"),
+                                                        &object_info, 0);
+                }
+        }
+        
+        return object_type;
+}
+
+static void
+gdk_pixbuf_gdip_anim_iter_class_init (GdkPixbufGdipAnimIterClass *klass)
+{
+        GObjectClass *object_class = G_OBJECT_CLASS (klass);
+        GdkPixbufAnimationIterClass *anim_iter_class =
+                GDK_PIXBUF_ANIMATION_ITER_CLASS (klass);
+        
+        iter_parent_class = g_type_class_peek_parent (klass);
+        
+        object_class->finalize = gdk_pixbuf_gdip_anim_iter_finalize;
+
+        anim_iter_class->get_delay_time = gdk_pixbuf_gdip_anim_iter_get_delay_time;
+        anim_iter_class->get_pixbuf = gdk_pixbuf_gdip_anim_iter_get_pixbuf;
+        anim_iter_class->on_currently_loading_frame = gdk_pixbuf_gdip_anim_iter_on_currently_loading_frame;
+        anim_iter_class->advance = gdk_pixbuf_gdip_anim_iter_advance;
+}
+
+static void
+gdk_pixbuf_gdip_anim_iter_finalize (GObject *object)
+{
+        GdkPixbufGdipAnimIter *iter = GDK_PIXBUF_GDIP_ANIM_ITER (object);
+
+        iter_clear (iter);
+
+        g_object_unref (iter->gdip_anim);
+        
+        G_OBJECT_CLASS (iter_parent_class)->finalize (object);
+}
+
+static gboolean
+gdk_pixbuf_gdip_anim_iter_advance (GdkPixbufAnimationIter *anim_iter,
+                                  const GTimeVal         *current_time)
+{
+        GdkPixbufGdipAnimIter *iter;
+        gint elapsed;
+        gint loop;
+        GList *tmp;
+        GList *old;
+        
+        iter = GDK_PIXBUF_GDIP_ANIM_ITER (anim_iter);
+        
+        iter->current_time = *current_time;
+
+        /* We use milliseconds for all times */
+        elapsed =
+          (((iter->current_time.tv_sec - iter->start_time.tv_sec) * G_USEC_PER_SEC +
+            iter->current_time.tv_usec - iter->start_time.tv_usec)) / 1000;
+
+        if (elapsed < 0) {
+                /* Try to compensate; probably the system clock
+                 * was set backwards
+                 */
+                iter->start_time = iter->current_time;
+                elapsed = 0;
+        }
+
+        g_assert (iter->gdip_anim->total_time > 0);
+        
+        /* See how many times we've already played the full animation,
+         * and subtract time for that.
+         */
+
+        if (iter->gdip_anim->loading)
+                loop = 0;
+        else {
+                /* If current_frame is NULL at this point, we have loaded the
+                 * animation from a source which fell behind the speed of the 
+                 * display. We remember how much slower the first loop was due
+                 * to this and correct the position calculation in order to not
+                 * jump in the middle of the second loop.
+                 */
+                if (iter->current_frame == NULL)
+                        iter->first_loop_slowness = MAX(0, elapsed - iter->gdip_anim->total_time);
+
+                loop = (elapsed - iter->first_loop_slowness) / iter->gdip_anim->total_time;
+                elapsed = (elapsed - iter->first_loop_slowness) % iter->gdip_anim->total_time;
+        }
+
+        iter->position = elapsed;
+
+        /* Now move to the proper frame */
+        if (iter->gdip_anim->loop == 0 || loop < iter->gdip_anim->loop) 
+                tmp = iter->gdip_anim->frames;
+        else 
+                tmp = NULL;
+        while (tmp != NULL) {
+                GdkPixbufFrame *frame = tmp->data;
+                
+                if (iter->position >= frame->elapsed &&
+                    iter->position < (frame->elapsed + frame->delay_time))
+                        break;
+                
+                tmp = tmp->next;
+        }
+
+        old = iter->current_frame;
+        
+        iter->current_frame = tmp;
+
+        return iter->current_frame != old;
+}
+
+int
+gdk_pixbuf_gdip_anim_iter_get_delay_time (GdkPixbufAnimationIter *anim_iter)
+{
+        GdkPixbufFrame *frame;
+        GdkPixbufGdipAnimIter *iter;
+  
+        iter = GDK_PIXBUF_GDIP_ANIM_ITER (anim_iter);
+
+        if (iter->current_frame) {
+                frame = iter->current_frame->data;
+
+#if 0
+                g_print ("frame start: %d pos: %d frame len: %d frame remaining: %d\n",
+                         frame->elapsed,
+                         iter->position,
+                         frame->delay_time,
+                         frame->delay_time - (iter->position - frame->elapsed));
+#endif
+                
+                return frame->delay_time - (iter->position - frame->elapsed);
+        } else 
+                return -1; /* show last frame forever */
+}
+
+GdkPixbuf*
+gdk_pixbuf_gdip_anim_iter_get_pixbuf (GdkPixbufAnimationIter *anim_iter)
+{
+        GdkPixbufGdipAnimIter *iter;
+        GdkPixbufFrame *frame;
+        
+        iter = GDK_PIXBUF_GDIP_ANIM_ITER (anim_iter);
+
+        frame = iter->current_frame ? iter->current_frame->data : g_list_last (iter->gdip_anim->frames)->data;
+
+#if 0
+        if (FALSE && frame)
+          g_print ("current frame %d dispose mode %d  %d x %d\n",
+                   g_list_index (iter->gdip_anim->frames,
+                                 frame),
+                   frame->action,
+                   gdk_pixbuf_get_width (frame->pixbuf),
+                   gdk_pixbuf_get_height (frame->pixbuf));
+#endif
+        
+        if (frame == NULL)
+                return NULL;
+
+        return frame->pixbuf;
+}
+
+static gboolean
+gdk_pixbuf_gdip_anim_iter_on_currently_loading_frame (GdkPixbufAnimationIter *anim_iter)
+{
+        GdkPixbufGdipAnimIter *iter;
+  
+        iter = GDK_PIXBUF_GDIP_ANIM_ITER (anim_iter);
+
+        return iter->current_frame == NULL || iter->current_frame->next == NULL;  
+}

Added: trunk/gdk-pixbuf/io-gdip-animation.h
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-animation.h	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,117 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* GdkPixbuf library - GDIP loader declarations
+ *
+ * Copyright (C) 1999 The Free Software Foundation
+ *
+ * Authors: Mark Crichton <crichton gimp org>
+ *          Miguel de Icaza <miguel gnu org>
+ *          Federico Mena-Quintero <federico gimp org>
+ *          Havoc Pennington <hp redhat com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser 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.
+ */
+
+#ifndef GDK_PIXBUF_GDIP_H
+#define GDK_PIXBUF_GDIP_H
+
+#include <gdk-pixbuf/gdk-pixbuf-animation.h>
+
+typedef struct _GdkPixbufGdipAnim GdkPixbufGdipAnim;
+typedef struct _GdkPixbufGdipAnimClass GdkPixbufGdipAnimClass;
+typedef struct _GdkPixbufFrame GdkPixbufFrame;
+
+#define GDK_TYPE_PIXBUF_GDIP_ANIM              (gdk_pixbuf_gdip_anim_get_type ())
+#define GDK_PIXBUF_GDIP_ANIM(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_GDIP_ANIM, GdkPixbufGdipAnim))
+#define GDK_IS_PIXBUF_GDIP_ANIM(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_GDIP_ANIM))
+
+#define GDK_PIXBUF_GDIP_ANIM_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_GDIP_ANIM, GdkPixbufGdipAnimClass))
+#define GDK_IS_PIXBUF_GDIP_ANIM_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_GDIP_ANIM))
+#define GDK_PIXBUF_GDIP_ANIM_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_GDIP_ANIM, GdkPixbufGdipAnimClass))
+
+/* Private part of the GdkPixbufGdipAnim structure */
+struct _GdkPixbufGdipAnim {
+        GdkPixbufAnimation parent_instance;
+
+        /* Number of frames */
+        int n_frames;
+
+        /* Total length of animation */
+        int total_time;
+        
+	/* List of GdkPixbufFrame structures */
+        GList *frames;
+
+	/* bounding box size */
+	int width, height;
+        
+        int loop;
+        gboolean loading;
+};
+
+struct _GdkPixbufGdipAnimClass {
+        GdkPixbufAnimationClass parent_class;
+        
+};
+
+GType gdk_pixbuf_gdip_anim_get_type (void) G_GNUC_CONST;
+
+typedef struct _GdkPixbufGdipAnimIter GdkPixbufGdipAnimIter;
+typedef struct _GdkPixbufGdipAnimIterClass GdkPixbufGdipAnimIterClass;
+
+
+#define GDK_TYPE_PIXBUF_GDIP_ANIM_ITER              (gdk_pixbuf_gdip_anim_iter_get_type ())
+#define GDK_PIXBUF_GDIP_ANIM_ITER(object)           (G_TYPE_CHECK_INSTANCE_CAST ((object), GDK_TYPE_PIXBUF_GDIP_ANIM_ITER, GdkPixbufGdipAnimIter))
+#define GDK_IS_PIXBUF_GDIP_ANIM_ITER(object)        (G_TYPE_CHECK_INSTANCE_TYPE ((object), GDK_TYPE_PIXBUF_GDIP_ANIM_ITER))
+
+#define GDK_PIXBUF_GDIP_ANIM_ITER_CLASS(klass)      (G_TYPE_CHECK_CLASS_CAST ((klass), GDK_TYPE_PIXBUF_GDIP_ANIM_ITER, GdkPixbufGdipAnimIterClass))
+#define GDK_IS_PIXBUF_GDIP_ANIM_ITER_CLASS(klass)   (G_TYPE_CHECK_CLASS_TYPE ((klass), GDK_TYPE_PIXBUF_GDIP_ANIM_ITER))
+#define GDK_PIXBUF_GDIP_ANIM_ITER_GET_CLASS(obj)    (G_TYPE_INSTANCE_GET_CLASS ((obj), GDK_TYPE_PIXBUF_GDIP_ANIM_ITER, GdkPixbufGdipAnimIterClass))
+
+struct _GdkPixbufGdipAnimIter {
+        GdkPixbufAnimationIter parent_instance;
+        
+        GdkPixbufGdipAnim   *gdip_anim;
+
+        GTimeVal            start_time;
+        GTimeVal            current_time;
+
+        /* Time in milliseconds into this run of the animation */
+        gint                position;
+        
+        GList              *current_frame;
+        
+        gint                first_loop_slowness;
+};
+
+struct _GdkPixbufGdipAnimIterClass {
+        GdkPixbufAnimationIterClass parent_class;
+
+};
+
+GType gdk_pixbuf_gdip_anim_iter_get_type (void) G_GNUC_CONST;
+
+struct _GdkPixbufFrame {
+	/* The pixbuf with this frame's image data */
+	GdkPixbuf *pixbuf;
+
+	/* Frame duration in ms */
+	int delay_time;
+
+        /* Sum of preceding delay times */
+        int elapsed;        
+};
+
+#endif

Added: trunk/gdk-pixbuf/io-gdip-bmp.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-bmp.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+static gboolean
+gdk_pixbuf__gdip_image_save_BMP_to_callback (GdkPixbufSaveFunc   save_func,
+                                             gpointer            user_data,
+                                             GdkPixbuf          *pixbuf,
+                                             gchar             **keys,
+                                             gchar             **values,
+                                             GError            **error)
+{
+  return gdip_save_pixbuf (pixbuf, L"image/bmp", NULL, save_func, user_data, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_save_BMP (FILE          *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_BMP_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_bmp_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_BMP_to_callback;
+  module->save = gdk_pixbuf__gdip_image_save_BMP; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "BM", NULL, 100 }, /* BMP */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/bmp",
+    "image/x-bmp",
+    "image/x-MS-bmp",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "bmp",
+    NULL
+  };
+
+  info->name        = "bmp";
+  info->signature   = signature;
+  info->description = _("The BMP image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-emf.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-emf.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_emf_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vector_vtable (module);
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "\x01\x00\x00\x00", NULL, 100 }, /* EMF */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "application/emf",
+    "application/x-emf",
+    "image/x-emf",
+    "image/x-mgx-emf",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "emf",
+    NULL
+  };
+
+  info->name        = "emf";
+  info->signature   = signature;
+  info->description = _("The EMF image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-gif.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-gif.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,85 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+static gboolean
+gdk_pixbuf__gdip_image_save_GIF_to_callback (GdkPixbufSaveFunc   save_func,
+                                             gpointer            user_data,
+                                             GdkPixbuf          *pixbuf,
+                                             gchar             **keys,
+                                             gchar             **values,
+                                             GError            **error)
+{
+  return gdip_save_pixbuf (pixbuf, L"image/gif", NULL, save_func, user_data, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_save_GIF (FILE          *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_GIF_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_gif_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_GIF_to_callback;
+  module->save = gdk_pixbuf__gdip_image_save_GIF; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "GIF8", NULL, 100 }, /* GIF */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/gif",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "gif",
+    NULL
+  };
+
+  info->name        = "gif";
+  info->signature   = signature;
+  info->description = _("The GIF image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-ico.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-ico.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,64 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_ico_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "  \x1   ", "zz znz", 100 }, /* ICO */
+    { "  \x2   ", "zz znz", 100 }, /* ICO */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/x-icon",
+    "image/x-ico",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "ico",
+    "cur",
+    NULL
+  };
+
+  info->name        = "ico";
+  info->signature   = signature;
+  info->description = _("The ICO image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-jpeg.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-jpeg.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,141 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#define INITGUID
+#include "io-gdip-utils.h"
+
+DEFINE_GUID(EncoderQuality, 0x1d5be4b5,0xfa4a,0x452d,0x9c,0xdd,0x5d,0xb3,0x51,0x05,0xe7,0xeb);
+
+static gboolean
+gdk_pixbuf__gdip_image_save_JPEG_to_callback (GdkPixbufSaveFunc   save_func,
+                                              gpointer            user_data,
+                                              GdkPixbuf          *pixbuf,
+                                              gchar             **keys,
+                                              gchar             **values,
+                                              GError            **error)
+{
+  EncoderParameters encoder_params;
+  LONG quality = 75; /* default; must be between 0 and 100 */
+
+  if (keys && *keys) {
+    gchar **kiter = keys;
+    gchar **viter = values;
+    
+    while (*kiter) {
+      if (strcmp (*kiter, "quality") == 0) {
+        char *endptr = NULL;
+        quality = strtol (*viter, &endptr, 10);
+        
+        if (endptr == *viter) {
+          g_set_error (error,
+                       GDK_PIXBUF_ERROR,
+                       GDK_PIXBUF_ERROR_BAD_OPTION,
+                       _("JPEG quality must be a value between 0 and 100; value '%s' could not be parsed."),
+                       *viter);
+          
+          return FALSE;
+        }
+        
+        if (quality < 0 ||
+            quality > 100) {
+          /* This is a user-visible error;
+           * lets people skip the range-checking
+           * in their app.
+           */
+          g_set_error (error,
+                       GDK_PIXBUF_ERROR,
+                       GDK_PIXBUF_ERROR_BAD_OPTION,
+                       _("JPEG quality must be a value between 0 and 100; value '%d' is not allowed."),
+                       (int)quality);
+          
+          return FALSE;
+        }
+      } else {
+        g_warning ("Unrecognized parameter (%s) passed to JPEG saver.", *kiter);
+      }
+      
+      ++kiter;
+      ++viter;
+    }
+  }
+
+  encoder_params.Count = 1;
+  encoder_params.Parameter[0].Guid = EncoderQuality;
+  encoder_params.Parameter[0].Type = EncoderParameterValueTypeLong;
+  encoder_params.Parameter[0].NumberOfValues = 1;
+  encoder_params.Parameter[0].Value = &quality;
+     
+  return gdip_save_pixbuf (pixbuf, L"image/jpeg", &encoder_params, save_func, user_data, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_save_JPEG (FILE         *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_JPEG_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_jpeg_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_JPEG_to_callback;
+  module->save = gdk_pixbuf__gdip_image_save_JPEG; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "\xff\xd8", NULL, 100 }, /* JPEG */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/jpeg",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "jpeg",
+    "jpe",
+    "jpg",
+    NULL
+  };
+
+  info->name        = "jpeg";
+  info->signature   = signature;
+  info->description = _("The JPEG image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-native.h
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-native.h	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,235 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2007 Google (Evan Stade)
+ * Copyright (C) 2008 Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#ifndef _HAVE_IO_GDIP_NATIVE_H
+#define _HAVE_IO_GDIP_NATIVE_H
+
+#include <windows.h>
+
+#include <glib.h>
+
+/* //////////// Native API ///////////// */
+
+#define WINGDIPAPI __stdcall
+
+typedef gulong ARGB;
+typedef gint PixelFormat;
+
+typedef enum {
+    EncoderParameterValueTypeByte = 1,
+    EncoderParameterValueTypeASCII = 2,
+    EncoderParameterValueTypeShort = 3,
+    EncoderParameterValueTypeLong = 4,
+    EncoderParameterValueTypeRational = 5,
+    EncoderParameterValueTypeLongRange = 6,
+    EncoderParameterValueTypeUndefined = 7,
+    EncoderParameterValueTypeRationalRange = 8,
+    EncoderParameterValueTypePointer = 9
+} EncoderParameterValueType;
+
+#define    PixelFormatIndexed   0x00010000
+#define    PixelFormatGDI       0x00020000
+#define    PixelFormatAlpha     0x00040000
+#define    PixelFormatPAlpha    0x00080000
+#define    PixelFormatExtended  0x00100000
+#define    PixelFormatCanonical 0x00200000
+
+#define    PixelFormatUndefined 0
+#define    PixelFormatDontCare  0
+
+#define    PixelFormat1bppIndexed       (1 | ( 1 << 8) | PixelFormatIndexed | PixelFormatGDI)
+#define    PixelFormat4bppIndexed       (2 | ( 4 << 8) | PixelFormatIndexed | PixelFormatGDI)
+#define    PixelFormat8bppIndexed       (3 | ( 8 << 8) | PixelFormatIndexed | PixelFormatGDI)
+#define    PixelFormat16bppGrayScale    (4 | (16 << 8) | PixelFormatExtended)
+#define    PixelFormat16bppRGB555       (5 | (16 << 8) | PixelFormatGDI)
+#define    PixelFormat16bppRGB565       (6 | (16 << 8) | PixelFormatGDI)
+#define    PixelFormat16bppARGB1555     (7 | (16 << 8) | PixelFormatAlpha | PixelFormatGDI)
+#define    PixelFormat24bppRGB          (8 | (24 << 8) | PixelFormatGDI)
+#define    PixelFormat32bppRGB          (9 | (32 << 8) | PixelFormatGDI)
+#define    PixelFormat32bppARGB         (10 | (32 << 8) | PixelFormatAlpha | PixelFormatGDI | PixelFormatCanonical)
+#define    PixelFormat32bppPARGB        (11 | (32 << 8) | PixelFormatAlpha | PixelFormatPAlpha | PixelFormatGDI)
+#define    PixelFormat48bppRGB          (12 | (48 << 8) | PixelFormatExtended)
+#define    PixelFormat64bppARGB         (13 | (64 << 8) | PixelFormatAlpha  | PixelFormatCanonical | PixelFormatExtended)
+#define    PixelFormat64bppPARGB        (14 | (64 << 8) | PixelFormatAlpha  | PixelFormatPAlpha | PixelFormatExtended)
+#define    PixelFormatMax               15
+
+enum _Status
+{
+    Ok                          = 0,
+    GenericError                = 1,
+    InvalidParameter            = 2,
+    OutOfMemory                 = 3,
+    ObjectBusy                  = 4,
+    InsufficientBuffer          = 5,
+    NotImplemented              = 6,
+    Win32Error                  = 7,
+    WrongState                  = 8,
+    Aborted                     = 9,
+    FileNotFound                = 10,
+    ValueOverflow               = 11,
+    AccessDenied                = 12,
+    UnknownImageFormat          = 13,
+    FontFamilyNotFound          = 14,
+    FontStyleNotFound           = 15,
+    NotTrueTypeFont             = 16,
+    UnsupportedGdiplusVersion   = 17,
+    GdiplusNotInitialized       = 18,
+    PropertyNotFound            = 19,
+    PropertyNotSupported        = 20,
+    ProfileNotFound             = 21
+};
+typedef enum _Status Status;
+typedef enum _Status GpStatus;
+
+typedef enum {
+    ImageFlagsNone = 0,
+    ImageFlagsScalable = 0x0001,
+    ImageFlagsHasAlpha = 0x0002,
+    ImageFlagsHasTranslucent = 0x0004,
+    ImageFlagsPartiallyScalable = 0x0008,
+    ImageFlagsColorSpaceRGB = 0x0010,
+    ImageFlagsColorSpaceCMYK = 0x0020,
+    ImageFlagsColorSpaceGRAY = 0x0040,
+    ImageFlagsColorSpaceYCBCR = 0x0080,
+    ImageFlagsColorSpaceYCCK = 0x0100,
+    ImageFlagsHasRealDPI = 0x1000,
+    ImageFlagsHasRealPixelSize = 0x2000,
+    ImageFlagsReadOnly = 0x00010000,
+    ImageFlagsCaching = 0x00020000
+} ImageFlags;
+
+enum _ImageLockMode
+{
+    ImageLockModeRead           = 1,
+    ImageLockModeWrite          = 2,
+    ImageLockModeUserInputBuf   = 4
+};
+typedef enum _ImageLockMode ImageLockMode;
+
+enum _ImageType
+{
+    ImageTypeUnknown,
+    ImageTypeBitmap,
+    ImageTypeMetafile
+};
+typedef enum _ImageType ImageType;
+
+typedef struct _GpImage GpImage;
+typedef struct _GpBitmap GpBitmap;
+typedef struct _GpGraphics GpGraphics;
+
+struct _GdiplusStartupInput
+{
+    UINT32 GdiplusVersion;
+    gpointer DebugEventCallback;
+    BOOL SuppressBackgroundThread;
+    BOOL SuppressExternalCodecs;
+};
+typedef struct _GdiplusStartupInput GdiplusStartupInput;
+
+struct _PropItem
+{
+  ULONG id;
+  ULONG length;
+  WORD type;
+  VOID *value;
+};
+typedef struct _PropItem PropertyItem;
+
+struct _EncoderParameter
+{
+    GUID    Guid;
+    ULONG   NumberOfValues;
+    ULONG   Type;
+    VOID*   Value;
+};
+typedef struct _EncoderParameter EncoderParameter;
+
+struct _EncoderParameters
+{
+    UINT Count;                      /* Number of parameters in this structure */
+    EncoderParameter Parameter[1];   /* Parameter values */
+};
+typedef struct _EncoderParameters EncoderParameters;
+
+struct _ImageCodecInfo
+{
+    CLSID Clsid;
+    GUID  FormatID;
+    const WCHAR* CodecName;
+    const WCHAR* DllName;
+    const WCHAR* FormatDescription;
+    const WCHAR* FilenameExtension;
+    const WCHAR* MimeType;
+    DWORD Flags;
+    DWORD Version;
+    DWORD SigCount;
+    DWORD SigSize;
+    const BYTE* SigPattern;
+    const BYTE* SigMask;
+};
+typedef struct _ImageCodecInfo ImageCodecInfo;
+
+#ifndef IStream_Release
+#define IStream_Release(This) (This)->lpVtbl->Release(This)
+#endif
+
+#ifndef IStream_Seek
+#define IStream_Seek(This,dlibMove,dwOrigin,plibNewPosition) (This)->lpVtbl->Seek(This,dlibMove,dwOrigin,plibNewPosition)
+#endif
+
+#ifndef IStream_Read
+#define IStream_Read(This,pv,cb,pcbRead) (This)->lpVtbl->Read(This,pv,cb,pcbRead)
+#endif
+
+typedef GpStatus (WINGDIPAPI* GdiplusStartupFunc) (gpointer, const gpointer, gpointer);
+typedef GpStatus (WINGDIPAPI* GdipCreateBitmapFromStreamFunc) (gpointer, GpBitmap**);
+typedef GpStatus (WINGDIPAPI* GdipBitmapGetPixelFunc) (GpBitmap*, gint x, gint y, ARGB*);
+typedef GpStatus (WINGDIPAPI* GdipGetImageWidthFunc) (GpImage*, guint*);
+typedef GpStatus (WINGDIPAPI* GdipGetImageHeightFunc) (GpImage*, guint*);
+typedef GpStatus (WINGDIPAPI* GdipDisposeImageFunc) (GpImage*);
+typedef GpStatus (WINGDIPAPI* GdipGetImageFlagsFunc) (GpImage *, guint*);
+typedef GpStatus (WINGDIPAPI* GdipImageGetFrameCountFunc) (GpImage *image, const GUID* dimensionID, UINT* count);
+typedef GpStatus (WINGDIPAPI* GdipImageSelectActiveFrameFunc) (GpImage *image, const GUID* dimensionID, UINT frameIndex);
+typedef GpStatus (WINGDIPAPI* GdipGetPropertyItemSizeFunc) (GpImage *image, int propId, guint* size);
+typedef GpStatus (WINGDIPAPI* GdipGetPropertyItemFunc) (GpImage *image, int propId, guint propSize, PropertyItem* buffer);
+typedef GpStatus (WINGDIPAPI* GdipGetPropertyCountFunc) (GpImage *image, guint* numOfProperty);
+typedef GpStatus (WINGDIPAPI* GdipGetPropertyIdListFunc) (GpImage *image, guint numOfProperty, PROPID* list);
+typedef GpStatus (WINGDIPAPI* GdipCreateBitmapFromScan0Func) (INT width, INT height, INT stride, PixelFormat format, BYTE* scan0, 
+                                                              GpBitmap** bitmap);
+typedef GpStatus (WINGDIPAPI* GdipSaveImageToStreamFunc) (GpImage *image, IStream* stream, const CLSID* clsidEncoder, 
+                                                          const EncoderParameters* encoderParams);
+
+typedef GpStatus (WINGDIPAPI* GdipGetImageEncodersFunc) (UINT numEncoders, UINT size, ImageCodecInfo *encoders);
+typedef GpStatus (WINGDIPAPI* GdipGetImageEncodersSizeFunc) (UINT *numEncoders, UINT *size);
+typedef GpStatus (WINGDIPAPI* GdipBitmapSetPixelFunc) (GpBitmap* bitmap, INT x, INT y, ARGB color);
+
+typedef GpStatus (WINGDIPAPI* GdipDrawImageIFunc) (GpGraphics *graphics, GpImage *image, INT x, INT y);
+typedef GpStatus (WINGDIPAPI* GdipGetImageGraphicsContextFunc) (GpImage *image, GpGraphics **graphics);
+typedef GpStatus (WINGDIPAPI* GdipFlushFunc) (GpGraphics *graphics, INT intention);
+typedef GpStatus (WINGDIPAPI* GdipGraphicsClearFunc) (GpGraphics *graphics, ARGB color);
+typedef GpStatus (WINGDIPAPI* GdipBitmapSetResolutionFunc) (GpBitmap* bitmap, float xdpi, float ydpi);
+typedef GpStatus (WINGDIPAPI* GdipGetImageHorizontalResolutionFunc) (GpImage *image, float *resolution);
+typedef GpStatus (WINGDIPAPI* GdipGetImageVerticalResolutionFunc) (GpImage *image, float *resolution);
+typedef GpStatus (WINGDIPAPI* GdipLoadImageFromStreamFunc) (IStream* stream, GpImage **image);
+typedef GpStatus (WINGDIPAPI* GdipDeleteGraphicsFunc) (GpGraphics *graphics);
+
+#endif

Added: trunk/gdk-pixbuf/io-gdip-png.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-png.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,138 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#define INITGUID
+#include "io-gdip-utils.h"
+
+DEFINE_GUID(EncoderCompression, 0xe09d739d,0xccd4,0x44ee,0x8e,0xba,0x3f,0xbf,0x8b,0xe4,0xfc,0x58);
+
+static gboolean
+gdk_pixbuf__gdip_image_save_PNG_to_callback (GdkPixbufSaveFunc   save_func,
+                                             gpointer            user_data,
+                                             GdkPixbuf          *pixbuf,
+                                             gchar             **keys,
+                                             gchar             **values,
+                                             GError            **error)
+{
+  EncoderParameters encoder_params;
+  LONG compression = 5;
+
+  if (keys && *keys) {
+    gchar **kiter = keys;
+    gchar **viter = values;
+    
+    while (*kiter) {
+      if (strncmp (*kiter, "tEXt::", 6) == 0) {
+        /* TODO: support exif data and the like */
+      }
+      else if (strcmp (*kiter, "compression") == 0) {
+        char *endptr = NULL;
+        compression = strtol (*viter, &endptr, 10);
+        
+        if (endptr == *viter) {
+          g_set_error (error,
+                       GDK_PIXBUF_ERROR,
+                       GDK_PIXBUF_ERROR_BAD_OPTION,
+                       _("PNG compression level must be a value between 0 and 9; value '%s' could not be parsed."),
+                       *viter);
+          return FALSE;
+        }
+        if (compression < 0 || compression > 9) {
+          /* This is a user-visible error;
+           * lets people skip the range-checking
+           * in their app.
+           */
+          g_set_error (error,
+                       GDK_PIXBUF_ERROR,
+                       GDK_PIXBUF_ERROR_BAD_OPTION,
+                       _("PNG compression level must be a value between 0 and 9; value '%d' is not allowed."),
+                       (int)compression);
+          return FALSE;
+        }       
+      } else {
+        g_warning ("Unrecognized parameter (%s) passed to PNG saver.", *kiter);
+      }
+      
+      ++kiter;
+      ++viter;
+    }
+  }
+
+  encoder_params.Count = 1;
+  encoder_params.Parameter[0].Guid = EncoderCompression;
+  encoder_params.Parameter[0].Type = EncoderParameterValueTypeLong;
+  encoder_params.Parameter[0].NumberOfValues = 1;
+  encoder_params.Parameter[0].Value = &compression;
+
+  return gdip_save_pixbuf (pixbuf, L"image/png", &encoder_params, save_func, user_data, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_save_PNG (FILE          *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_PNG_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
+
+#ifndef INCLUDE_gdip_png
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_png_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_PNG_to_callback;
+  module->save = gdk_pixbuf__gdip_image_save_PNG; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "\x89PNG\r\n\x1a\x0a", NULL, 100 }, /* PNG */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/png",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "png",
+    NULL
+  };
+
+  info->name        = "png";
+  info->signature   = signature;
+  info->description = _("The PNG image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-propertytags.h
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-propertytags.h	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,228 @@
+#ifndef HAVE_IO_GDIP_PROPERTIES_H
+#define HAVE_IO_GDIP_PROPERTIES_H
+
+#define PropertyTagTypeByte        1
+#define PropertyTagTypeASCII       2
+#define PropertyTagTypeShort       3
+#define PropertyTagTypeLong        4
+#define PropertyTagTypeRational    5
+#define PropertyTagTypeUndefined   7
+#define PropertyTagTypeSLONG       9
+#define PropertyTagTypeSRational  10
+
+#define PropertyTagExifIFD             0x8769
+#define PropertyTagGpsIFD              0x8825
+#define PropertyTagNewSubfileType      0x00FE
+#define PropertyTagSubfileType         0x00FF
+#define PropertyTagImageWidth          0x0100
+#define PropertyTagImageHeight         0x0101
+#define PropertyTagBitsPerSample       0x0102
+#define PropertyTagCompression         0x0103
+#define PropertyTagPhotometricInterp   0x0106
+#define PropertyTagThreshHolding       0x0107
+#define PropertyTagCellWidth           0x0108
+#define PropertyTagCellHeight          0x0109
+#define PropertyTagFillOrder           0x010A
+#define PropertyTagDocumentName        0x010D
+#define PropertyTagImageDescription    0x010E
+#define PropertyTagEquipMake           0x010F
+#define PropertyTagEquipModel          0x0110
+#define PropertyTagStripOffsets        0x0111
+#define PropertyTagOrientation         0x0112
+#define PropertyTagSamplesPerPixel     0x0115
+#define PropertyTagRowsPerStrip        0x0116
+#define PropertyTagStripBytesCount     0x0117
+#define PropertyTagMinSampleValue      0x0118
+#define PropertyTagMaxSampleValue      0x0119
+#define PropertyTagXResolution         0x011A   
+#define PropertyTagYResolution         0x011B   
+#define PropertyTagPlanarConfig        0x011C   
+#define PropertyTagPageName            0x011D
+#define PropertyTagXPosition           0x011E
+#define PropertyTagYPosition           0x011F
+#define PropertyTagFreeOffset          0x0120
+#define PropertyTagFreeByteCounts      0x0121
+#define PropertyTagGrayResponseUnit    0x0122
+#define PropertyTagGrayResponseCurve   0x0123
+#define PropertyTagT4Option            0x0124
+#define PropertyTagT6Option            0x0125
+#define PropertyTagResolutionUnit      0x0128   
+#define PropertyTagPageNumber          0x0129
+#define PropertyTagTransferFuncition   0x012D
+#define PropertyTagSoftwareUsed        0x0131
+#define PropertyTagDateTime            0x0132
+#define PropertyTagArtist              0x013B
+#define PropertyTagHostComputer        0x013C
+#define PropertyTagPredictor           0x013D
+#define PropertyTagWhitePoint          0x013E
+#define PropertyTagPrimaryChromaticities 0x013F
+#define PropertyTagColorMap            0x0140
+#define PropertyTagHalftoneHints       0x0141
+#define PropertyTagTileWidth           0x0142
+#define PropertyTagTileLength          0x0143
+#define PropertyTagTileOffset          0x0144
+#define PropertyTagTileByteCounts      0x0145
+#define PropertyTagInkSet              0x014C
+#define PropertyTagInkNames            0x014D
+#define PropertyTagNumberOfInks        0x014E
+#define PropertyTagDotRange            0x0150
+#define PropertyTagTargetPrinter       0x0151
+#define PropertyTagExtraSamples        0x0152
+#define PropertyTagSampleFormat        0x0153
+#define PropertyTagSMinSampleValue     0x0154
+#define PropertyTagSMaxSampleValue     0x0155
+#define PropertyTagTransferRange       0x0156
+#define PropertyTagJPEGProc            0x0200
+#define PropertyTagJPEGInterFormat     0x0201
+#define PropertyTagJPEGInterLength     0x0202
+#define PropertyTagJPEGRestartInterval 0x0203
+#define PropertyTagJPEGLosslessPredictors  0x0205
+#define PropertyTagJPEGPointTransforms     0x0206
+#define PropertyTagJPEGQTables         0x0207
+#define PropertyTagJPEGDCTables        0x0208
+#define PropertyTagJPEGACTables        0x0209
+#define PropertyTagYCbCrCoefficients   0x0211
+#define PropertyTagYCbCrSubsampling    0x0212
+#define PropertyTagYCbCrPositioning    0x0213
+#define PropertyTagREFBlackWhite       0x0214
+#define PropertyTagICCProfile          0x8773   
+#define PropertyTagGamma               0x0301
+#define PropertyTagICCProfileDescriptor 0x0302
+#define PropertyTagSRGBRenderingIntent 0x0303
+#define PropertyTagImageTitle          0x0320
+#define PropertyTagCopyright           0x8298
+#define PropertyTagResolutionXUnit           0x5001
+#define PropertyTagResolutionYUnit           0x5002
+#define PropertyTagResolutionXLengthUnit     0x5003
+#define PropertyTagResolutionYLengthUnit     0x5004
+#define PropertyTagPrintFlags                0x5005
+#define PropertyTagPrintFlagsVersion         0x5006
+#define PropertyTagPrintFlagsCrop            0x5007
+#define PropertyTagPrintFlagsBleedWidth      0x5008
+#define PropertyTagPrintFlagsBleedWidthScale 0x5009
+#define PropertyTagHalftoneLPI               0x500A
+#define PropertyTagHalftoneLPIUnit           0x500B
+#define PropertyTagHalftoneDegree            0x500C
+#define PropertyTagHalftoneShape             0x500D
+#define PropertyTagHalftoneMisc              0x500E
+#define PropertyTagHalftoneScreen            0x500F
+#define PropertyTagJPEGQuality               0x5010
+#define PropertyTagGridSize                  0x5011
+#define PropertyTagThumbnailFormat           0x5012  
+#define PropertyTagThumbnailWidth            0x5013
+#define PropertyTagThumbnailHeight           0x5014
+#define PropertyTagThumbnailColorDepth       0x5015
+#define PropertyTagThumbnailPlanes           0x5016
+#define PropertyTagThumbnailRawBytes         0x5017
+#define PropertyTagThumbnailSize             0x5018
+#define PropertyTagThumbnailCompressedSize   0x5019
+#define PropertyTagColorTransferFunction     0x501A
+#define PropertyTagThumbnailData             0x501B
+#define PropertyTagThumbnailImageWidth       0x5020  
+#define PropertyTagThumbnailImageHeight      0x5021  
+#define PropertyTagThumbnailBitsPerSample    0x5022  
+#define PropertyTagThumbnailCompression      0x5023  
+#define PropertyTagThumbnailPhotometricInterp 0x5024 
+#define PropertyTagThumbnailImageDescription 0x5025  
+#define PropertyTagThumbnailEquipMake        0x5026  
+#define PropertyTagThumbnailEquipModel       0x5027  
+#define PropertyTagThumbnailStripOffsets     0x5028  
+#define PropertyTagThumbnailOrientation      0x5029  
+#define PropertyTagThumbnailSamplesPerPixel  0x502A  
+#define PropertyTagThumbnailRowsPerStrip     0x502B  
+#define PropertyTagThumbnailStripBytesCount  0x502C  
+#define PropertyTagThumbnailResolutionX      0x502D  
+#define PropertyTagThumbnailResolutionY      0x502E  
+#define PropertyTagThumbnailPlanarConfig     0x502F  
+#define PropertyTagThumbnailResolutionUnit   0x5030  
+#define PropertyTagThumbnailTransferFunction 0x5031  
+#define PropertyTagThumbnailSoftwareUsed     0x5032  
+#define PropertyTagThumbnailDateTime         0x5033  
+#define PropertyTagThumbnailArtist           0x5034  
+#define PropertyTagThumbnailWhitePoint       0x5035  
+#define PropertyTagThumbnailPrimaryChromaticities 0x5036 
+#define PropertyTagThumbnailYCbCrCoefficients 0x5037 
+#define PropertyTagThumbnailYCbCrSubsampling 0x5038  
+#define PropertyTagThumbnailYCbCrPositioning 0x5039  
+#define PropertyTagThumbnailRefBlackWhite    0x503A  
+#define PropertyTagThumbnailCopyRight        0x503B  
+#define PropertyTagLuminanceTable            0x5090
+#define PropertyTagChrominanceTable          0x5091
+#define PropertyTagFrameDelay                0x5100
+#define PropertyTagLoopCount                 0x5101
+#define PropertyTagPixelUnit         0x5110  
+#define PropertyTagPixelPerUnitX     0x5111  
+#define PropertyTagPixelPerUnitY     0x5112  
+#define PropertyTagPaletteHistogram  0x5113  
+#define PropertyTagExifExposureTime  0x829A
+#define PropertyTagExifFNumber       0x829D
+#define PropertyTagExifExposureProg  0x8822
+#define PropertyTagExifSpectralSense 0x8824
+#define PropertyTagExifISOSpeed      0x8827
+#define PropertyTagExifOECF          0x8828
+#define PropertyTagExifVer            0x9000
+#define PropertyTagExifDTOrig         0x9003 
+#define PropertyTagExifDTDigitized    0x9004 
+#define PropertyTagExifCompConfig     0x9101
+#define PropertyTagExifCompBPP        0x9102
+#define PropertyTagExifShutterSpeed   0x9201
+#define PropertyTagExifAperture       0x9202
+#define PropertyTagExifBrightness     0x9203
+#define PropertyTagExifExposureBias   0x9204
+#define PropertyTagExifMaxAperture    0x9205
+#define PropertyTagExifSubjectDist    0x9206
+#define PropertyTagExifMeteringMode   0x9207
+#define PropertyTagExifLightSource    0x9208
+#define PropertyTagExifFlash          0x9209
+#define PropertyTagExifFocalLength    0x920A
+#define PropertyTagExifMakerNote      0x927C
+#define PropertyTagExifUserComment    0x9286
+#define PropertyTagExifDTSubsec       0x9290  
+#define PropertyTagExifDTOrigSS       0x9291  
+#define PropertyTagExifDTDigSS        0x9292  
+#define PropertyTagExifFPXVer         0xA000
+#define PropertyTagExifColorSpace     0xA001
+#define PropertyTagExifPixXDim        0xA002
+#define PropertyTagExifPixYDim        0xA003
+#define PropertyTagExifRelatedWav     0xA004  
+#define PropertyTagExifInterop        0xA005
+#define PropertyTagExifFlashEnergy    0xA20B
+#define PropertyTagExifSpatialFR      0xA20C  
+#define PropertyTagExifFocalXRes      0xA20E  
+#define PropertyTagExifFocalYRes      0xA20F  
+#define PropertyTagExifFocalResUnit   0xA210  
+#define PropertyTagExifSubjectLoc     0xA214
+#define PropertyTagExifExposureIndex  0xA215
+#define PropertyTagExifSensingMethod  0xA217
+#define PropertyTagExifFileSource     0xA300
+#define PropertyTagExifSceneType      0xA301
+#define PropertyTagExifCfaPattern     0xA302
+#define PropertyTagGpsVer             0x0000
+#define PropertyTagGpsLatitudeRef     0x0001
+#define PropertyTagGpsLatitude        0x0002
+#define PropertyTagGpsLongitudeRef    0x0003
+#define PropertyTagGpsLongitude       0x0004
+#define PropertyTagGpsAltitudeRef     0x0005
+#define PropertyTagGpsAltitude        0x0006
+#define PropertyTagGpsGpsTime         0x0007
+#define PropertyTagGpsGpsSatellites   0x0008
+#define PropertyTagGpsGpsStatus       0x0009
+#define PropertyTagGpsGpsMeasureMode  0x00A
+#define PropertyTagGpsGpsDop          0x000B  
+#define PropertyTagGpsSpeedRef        0x000C
+#define PropertyTagGpsSpeed           0x000D
+#define PropertyTagGpsTrackRef        0x000E
+#define PropertyTagGpsTrack           0x000F
+#define PropertyTagGpsImgDirRef       0x0010
+#define PropertyTagGpsImgDir          0x0011
+#define PropertyTagGpsMapDatum        0x0012
+#define PropertyTagGpsDestLatRef      0x0013
+#define PropertyTagGpsDestLat         0x0014
+#define PropertyTagGpsDestLongRef     0x0015
+#define PropertyTagGpsDestLong        0x0016
+#define PropertyTagGpsDestBearRef     0x0017
+#define PropertyTagGpsDestBear        0x0018
+#define PropertyTagGpsDestDistRef     0x0019
+#define PropertyTagGpsDestDist        0x001A
+
+#endif

Added: trunk/gdk-pixbuf/io-gdip-tiff.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-tiff.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,87 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+static gboolean
+gdk_pixbuf__gdip_image_save_TIFF_to_callback (GdkPixbufSaveFunc   save_func,
+                                              gpointer            user_data,
+                                              GdkPixbuf          *pixbuf,
+                                              gchar             **keys,
+                                              gchar             **values,
+                                              GError            **error)
+{
+  return gdip_save_pixbuf (pixbuf, L"image/tiff", NULL, save_func, user_data, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_save_TIFF (FILE         *f,
+                                 GdkPixbuf     *pixbuf,
+                                 gchar        **keys,
+                                 gchar        **values,
+                                 GError       **error)
+{
+  return gdk_pixbuf__gdip_image_save_TIFF_to_callback (gdip_save_to_file_callback, f, pixbuf, keys, values, error);
+}
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_tiff_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vtable (module);
+
+  module->save_to_callback = gdk_pixbuf__gdip_image_save_TIFF_to_callback;
+  module->save = gdk_pixbuf__gdip_image_save_TIFF; /* for gtk < 2.14, you need to implement both. otherwise gdk-pixbuf-queryloaders fails */
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "MM \x2a", "  z ", 100 }, /* TIFF */
+    { "II\x2a ", "   z", 100 }, /* TIFF */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/tiff",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "tiff",
+    "tif",
+    NULL
+  };
+
+  info->name        = "tiff";
+  info->signature   = signature;
+  info->description = "The TIFF image format";
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_WRITABLE | GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}

Added: trunk/gdk-pixbuf/io-gdip-utils.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-utils.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,996 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#define INITGUID
+#include <ole2.h>
+
+#include "io-gdip-utils.h"
+#include "io-gdip-native.h"
+#include "io-gdip-propertytags.h"
+#include "io-gdip-animation.h"
+
+#define LOAD_BUFFER_SIZE 65536
+
+static GdiplusStartupFunc GdiplusStartup;
+static GdipCreateBitmapFromStreamFunc GdipCreateBitmapFromStream;
+static GdipBitmapGetPixelFunc GdipBitmapGetPixel;
+static GdipGetImageHeightFunc GdipGetImageHeight;
+static GdipDisposeImageFunc GdipDisposeImage;
+static GdipGetImageFlagsFunc GdipGetImageFlags;
+static GdipGetImageWidthFunc GdipGetImageWidth;
+static GdipImageGetFrameCountFunc GdipImageGetFrameCount;
+static GdipImageSelectActiveFrameFunc GdipImageSelectActiveFrame;
+static GdipGetPropertyItemSizeFunc GdipGetPropertyItemSize;
+static GdipGetPropertyItemFunc GdipGetPropertyItem;
+static GdipGetPropertyCountFunc GdipGetPropertyCount;
+static GdipGetPropertyIdListFunc GdipGetPropertyIdList;
+static GdipCreateBitmapFromScan0Func GdipCreateBitmapFromScan0;
+static GdipSaveImageToStreamFunc GdipSaveImageToStream;
+static GdipBitmapSetPixelFunc GdipBitmapSetPixel;
+static GdipDrawImageIFunc GdipDrawImageI;
+static GdipGetImageGraphicsContextFunc GdipGetImageGraphicsContext;
+static GdipFlushFunc GdipFlush;
+static GdipGraphicsClearFunc GdipGraphicsClear;
+static GdipBitmapSetResolutionFunc GdipBitmapSetResolution;
+static GdipGetImageHorizontalResolutionFunc GdipGetImageHorizontalResolution;
+static GdipGetImageVerticalResolutionFunc GdipGetImageVerticalResolution;
+static GdipLoadImageFromStreamFunc GdipLoadImageFromStream;
+static GdipDeleteGraphicsFunc GdipDeleteGraphics;
+static GdipGetImageEncodersFunc GdipGetImageEncoders;
+static GdipGetImageEncodersSizeFunc GdipGetImageEncodersSize;
+
+DEFINE_GUID(FrameDimensionTime, 0x6aedbd6d,0x3fb5,0x418a,0x83,0xa6,0x7f,0x45,0x22,0x9d,0xc8,0x72);
+DEFINE_GUID(FrameDimensionPage, 0x7462dc86,0x6180,0x4c7e,0x8e,0x3f,0xee,0x73,0x33,0xa7,0xa4,0x83);
+
+static void
+gdip_set_error_from_hresult (GError **error, gint code, HRESULT hr, const char *format)
+{
+  gchar *msg;
+  
+  msg = g_win32_error_message (hr);
+  
+  if (msg) {
+    g_set_error (error, GDK_PIXBUF_ERROR, code, format, msg);
+    g_free (msg);
+  }
+}
+
+static void
+gdip_set_error_from_gpstatus (GError **error, gint code, GpStatus status)
+{
+  const char *msg;
+
+  switch (status)
+    {
+#define CASE(x) case x: msg = #x; break
+    CASE (GenericError);
+    CASE (InvalidParameter);
+    CASE (OutOfMemory);
+    CASE (ObjectBusy);
+    CASE (InsufficientBuffer);
+    CASE (NotImplemented);
+    CASE (Win32Error);
+    CASE (WrongState);
+    CASE (Aborted);
+    CASE (FileNotFound);
+    CASE (ValueOverflow);
+    CASE (AccessDenied);
+    CASE (UnknownImageFormat);
+    CASE (FontFamilyNotFound);
+    CASE (FontStyleNotFound);
+    CASE (NotTrueTypeFont);
+    CASE (UnsupportedGdiplusVersion);
+    CASE (GdiplusNotInitialized);
+    CASE (PropertyNotFound);
+    CASE (PropertyNotSupported);
+    CASE (ProfileNotFound);
+    default:
+      msg = "Unknown error";
+    }
+  g_set_error (error, GDK_PIXBUF_ERROR, code, msg);
+}
+
+static gboolean
+gdip_init (void)
+{
+  GdiplusStartupInput input;
+  ULONG_PTR gdiplusToken = 0;
+  static HINSTANCE gdipluslib = NULL;
+
+  if (!gdipluslib)
+    gdipluslib = LoadLibrary ("gdiplus.dll");
+  else
+    return TRUE; /* gdip_init() is idempotent */
+
+  if (!gdipluslib)
+    return FALSE;
+
+#define LOOKUP(func) \
+  G_STMT_START { \
+    func = (func##Func) GetProcAddress (gdipluslib, #func); \
+    if (!func) {\
+      g_warning ("Couldn't find GDI+ function %s\n", #func); \
+      return FALSE; \
+    } \
+  } G_STMT_END
+
+  LOOKUP (GdiplusStartup);
+  LOOKUP (GdipCreateBitmapFromStream);
+  LOOKUP (GdipBitmapGetPixel);
+  LOOKUP (GdipGetImageHeight);
+  LOOKUP (GdipDisposeImage);
+  LOOKUP (GdipGetImageFlags);
+  LOOKUP (GdipGetImageWidth);
+  LOOKUP (GdipImageGetFrameCount);
+  LOOKUP (GdipImageSelectActiveFrame);
+  LOOKUP (GdipGetPropertyItemSize);
+  LOOKUP (GdipGetPropertyItem);
+  LOOKUP (GdipGetPropertyCount);
+  LOOKUP (GdipGetPropertyIdList);
+  LOOKUP (GdipCreateBitmapFromScan0);
+  LOOKUP (GdipSaveImageToStream);
+  LOOKUP (GdipBitmapSetPixel);
+  LOOKUP (GdipDrawImageI);
+  LOOKUP (GdipGetImageGraphicsContext);
+  LOOKUP (GdipFlush);
+  LOOKUP (GdipGraphicsClear);
+  LOOKUP (GdipBitmapSetResolution);
+  LOOKUP (GdipGetImageHorizontalResolution);
+  LOOKUP (GdipGetImageVerticalResolution);
+  LOOKUP (GdipLoadImageFromStream);
+  LOOKUP (GdipDeleteGraphics);
+  LOOKUP (GdipGetImageEncoders);
+  LOOKUP (GdipGetImageEncodersSize);
+
+#undef LOOKUP
+
+  input.GdiplusVersion = 1;
+  input.DebugEventCallback = NULL;
+  input.SuppressBackgroundThread = input.SuppressExternalCodecs = FALSE;
+  
+  return (GdiplusStartup (&gdiplusToken, &input, NULL) == 0 ? TRUE : FALSE);
+}
+
+static gboolean
+GetEncoderClsid (const WCHAR *format, CLSID *pClsid)
+{
+  UINT num, size;
+  int j;
+  ImageCodecInfo *pImageCodecInfo;
+    
+  if (Ok != GdipGetImageEncodersSize (&num, &size))
+    return FALSE;
+    
+  pImageCodecInfo = (ImageCodecInfo *) g_malloc (size);
+    
+  if (Ok != GdipGetImageEncoders (num, size, pImageCodecInfo)) {
+    g_free (pImageCodecInfo);
+    return FALSE;
+  }
+
+  for (j = 0; j < num; j++) {
+    if (wcscmp (pImageCodecInfo[j].MimeType, format) == 0) {
+      *pClsid = pImageCodecInfo[j].Clsid;
+      g_free (pImageCodecInfo);
+      return TRUE;
+    }
+  }
+ 
+  g_free (pImageCodecInfo);
+
+  return FALSE;
+}
+
+static HGLOBAL
+gdip_buffer_to_hglobal (const gchar *buffer, size_t size, GError **error)
+{
+  HGLOBAL hg = NULL;
+
+  hg = GlobalAlloc (GPTR, size);
+
+  if (!hg) {
+    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, GetLastError (), _("Could not allocate memory: %s"));
+    return NULL;
+  }
+
+  CopyMemory (hg, buffer, size);
+
+  return hg;
+}
+
+static gboolean
+gdip_save_bitmap_to_callback (GpBitmap *bitmap,
+                              const CLSID *format,
+                              const EncoderParameters *encoder_params,
+                              GdkPixbufSaveFunc save_func,
+                              gpointer user_data,
+                              GError **error)
+{
+  HRESULT hr;  
+  IStream *streamOut = NULL;
+  gboolean success = FALSE;
+  guint64 zero = 0;
+  GpStatus status;
+
+  hr = CreateStreamOnHGlobal (NULL, TRUE, &streamOut);
+  if (!SUCCEEDED (hr)) {
+    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not create stream: %s"));
+    return FALSE;
+  }
+
+  status = GdipSaveImageToStream ((GpImage *)bitmap, streamOut, format, encoder_params);
+  if (Ok != status) {
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+    IStream_Release (streamOut);
+    return FALSE;
+  }
+
+  /* seek back to the beginning of the stream */
+  hr = IStream_Seek (streamOut, *(LARGE_INTEGER *)&zero, STREAM_SEEK_SET, NULL);
+  if (!SUCCEEDED (hr)) {
+    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not seek stream: %s"));
+    IStream_Release (streamOut);
+    return FALSE;
+  }
+  
+  for (;;) {
+    char buffer[LOAD_BUFFER_SIZE];
+    ULONG nread;
+    
+    hr = IStream_Read (streamOut, buffer, sizeof(buffer), &nread);
+    if (!SUCCEEDED (hr))
+      {
+        gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not read from stream: %s"));
+        break;
+      }
+    else if (0 == nread) {
+      success = TRUE; /* EOF */
+      break;
+    }
+    else if (!(*save_func) (buffer, nread, error, user_data))
+      break;
+  }
+  
+  IStream_Release (streamOut);
+  
+  return success;
+}                     
+
+static GpBitmap *
+gdip_pixbuf_to_bitmap (GdkPixbuf *pixbuf)
+{
+  GpBitmap *bitmap = NULL;
+
+  int width, height, stride, n_channels;
+  guint8 *pixels;
+
+  width = gdk_pixbuf_get_width (pixbuf);
+  height = gdk_pixbuf_get_height (pixbuf);
+  stride = gdk_pixbuf_get_rowstride (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+  pixels = gdk_pixbuf_get_pixels (pixbuf);
+
+  if (n_channels == 3 || n_channels == 4) {
+    /* rgbX. need to convert to argb. pass a null data to get an empty bitmap */
+    GdipCreateBitmapFromScan0 (width, height, 0, PixelFormat32bppARGB, NULL, &bitmap);
+    
+    if (bitmap) {
+      int x, y;
+      
+      for (y = 0; y < height; y++) {
+        for (x = 0; x < width; x++) {
+          ARGB p;
+          guint8 alpha;
+          guchar *base = pixels + (y * stride + (x * n_channels));
+          
+          if (n_channels == 4)
+            alpha = base[3];
+          else
+            alpha = 0xff;
+                  
+          if (alpha == 0) 
+            p = 0;
+          else {
+            guint8 red = base[0];
+            guint8 green = base[1];
+            guint8 blue = base[2];
+            
+            p = (alpha << 24) | (red << 16) | (green << 8) | (blue << 0);
+          }
+          
+          GdipBitmapSetPixel (bitmap, x, y, p);
+        }
+      }
+    }
+  }
+  else {
+    g_warning ("Unsupported number of channels: %d\n", n_channels);
+  }
+  
+  return bitmap;
+}
+
+static GpBitmap *
+gdip_buffer_to_bitmap (const gchar *buffer, size_t size, GError **error)
+{
+  HRESULT hr;
+  HGLOBAL hg = NULL;
+  GpBitmap *bitmap = NULL;
+  IStream *stream = NULL;
+  GpStatus status;
+
+  hg = gdip_buffer_to_hglobal (buffer, size, error);
+
+  if (!hg)
+    return NULL;
+
+  hr = CreateStreamOnHGlobal (hg, FALSE, (LPSTREAM *)&stream);
+
+  if (!SUCCEEDED (hr)) {
+    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not create stream: %s"));
+    GlobalFree (hg);
+    return NULL;
+  }
+  
+  status = GdipCreateBitmapFromStream (stream, &bitmap);
+
+  if (Ok != status)
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+
+  IStream_Release (stream);
+  GlobalFree (hg);
+
+  return bitmap;
+}
+
+static GpImage *
+gdip_buffer_to_image (const gchar *buffer, size_t size, GError **error)
+{
+  HRESULT hr;
+  HGLOBAL hg = NULL;
+  GpImage *image = NULL;
+  IStream *stream = NULL;
+  GpStatus status;
+
+  hg = gdip_buffer_to_hglobal (buffer, size, error);
+
+  if (!hg)
+    return NULL;
+
+  hr = CreateStreamOnHGlobal (hg, FALSE, (LPSTREAM *)&stream);
+
+  if (!SUCCEEDED (hr)) {
+    gdip_set_error_from_hresult (error, GDK_PIXBUF_ERROR_FAILED, hr, _("Could not create stream: %s"));
+    GlobalFree (hg);
+    return NULL;
+  }
+  
+  status = GdipLoadImageFromStream (stream, &image);
+
+  if (Ok != status)
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+
+  IStream_Release (stream);
+  GlobalFree (hg);
+
+  return image;
+}
+
+static void
+gdip_bitmap_get_size (GpBitmap *bitmap, guint *width, guint *height)
+{
+  if (bitmap == NULL || width == NULL || height == NULL)
+    return;
+
+  *width = *height = 0;
+
+  GdipGetImageWidth ((GpImage *) bitmap, width);
+  GdipGetImageHeight ((GpImage *) bitmap, height);
+}
+
+static void
+gdip_bitmap_get_has_alpha (GpBitmap *bitmap, gboolean *has_alpha)
+{
+  guint flags = 0;
+
+  if (bitmap == NULL || has_alpha == NULL)
+    return;
+
+  GdipGetImageFlags ((GpImage *) bitmap, &flags);
+  *has_alpha = (flags & ImageFlagsHasAlpha);
+}
+
+static gboolean
+gdip_bitmap_get_n_frames (GpBitmap *bitmap, guint *n_frames, gboolean timeDimension)
+{
+  if (bitmap == NULL || n_frames == NULL)
+    return FALSE;
+
+  *n_frames = 1;
+
+  return (Ok == GdipImageGetFrameCount ((GpImage *) bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), n_frames));
+}
+
+static gboolean
+gdip_bitmap_select_frame (GpBitmap *bitmap, guint frame, gboolean timeDimension)
+{
+  if (bitmap == NULL)
+    return FALSE;
+
+  return (Ok == GdipImageSelectActiveFrame ((GpImage *)bitmap, (timeDimension ? &FrameDimensionTime : &FrameDimensionPage), frame));
+}
+
+static gboolean
+gdip_bitmap_get_property_as_string (GpBitmap *bitmap, guint propertyId, gchar **str)
+{
+  guint item_size;
+  gboolean success = FALSE;
+
+  if (bitmap == NULL || str == NULL)
+    return FALSE;
+
+  *str = 0;
+
+  if (Ok == GdipGetPropertyItemSize ((GpImage *)bitmap, propertyId, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (Ok == GdipGetPropertyItem ((GpImage *)bitmap, propertyId, item_size, item)) {
+      GString *gstr;
+      int i;
+      
+      gstr = g_string_new (NULL);
+      
+      success = TRUE;
+      switch (item->type) {
+      case PropertyTagTypeByte:
+        for (i = 0; i < item->length / sizeof(guint8); i++) {
+          guint8 *bytes = (guint8 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c(gstr, ',');
+          g_string_append_printf (gstr, "%u", (guint32)bytes[i]);
+        }
+        break;
+        
+      case PropertyTagTypeASCII:
+        g_string_append_len (gstr, (const char *)item->value, item->length);
+        break;
+        
+      case PropertyTagTypeShort:
+        for (i = 0; i < item->length / sizeof(guint16); i++) {
+          guint16 *shorts = (guint16 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%u", (guint32)shorts[i]);
+        }
+        break;
+        
+      case PropertyTagTypeLong:
+        for (i = 0; i < item->length / sizeof(guint32); i++) {
+          guint32 *longs = (guint32 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%u", longs[i]);
+        }
+        break;
+
+      case PropertyTagTypeSLONG:
+        for (i = 0; i < item->length / sizeof(guint32); i++) {
+          gint32 *longs = (gint32 *)item->value;
+          
+          if (gstr->len != 0)
+            g_string_append_c (gstr, ',');
+          g_string_append_printf (gstr, "%d", longs[i]);
+        }
+        break;
+        
+      default:
+        success = FALSE;
+        break;
+      }
+      
+      if (gstr->len > 0)
+        *str = g_string_free (gstr, FALSE);
+      else
+        g_string_free (gstr, TRUE);
+    }
+    
+    g_free (item);
+  }
+  
+  return success;
+}
+
+static gboolean
+gdip_bitmap_get_frame_delay (GpBitmap *bitmap, guint *delay)
+{
+  guint item_size;
+  gboolean success = FALSE;
+
+  if (bitmap == NULL || delay == NULL)
+    return FALSE;
+
+  *delay = 0;
+
+  if (Ok == GdipGetPropertyItemSize ((GpImage *)bitmap, PropertyTagFrameDelay, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (Ok == GdipGetPropertyItem ((GpImage *)bitmap, PropertyTagFrameDelay, item_size, item)) {
+      /* PropertyTagFrameDelay. Time delay, in hundredths of a second, between two frames in an animated GIF image. */
+      *delay = *((long *)item->value);
+      success = TRUE;
+    }
+    
+    g_free (item);
+  }
+  
+  return success;
+}
+
+static gboolean
+gdip_bitmap_get_n_loops (GpBitmap *bitmap, guint *loops)
+{
+  guint item_size;
+  gboolean success = FALSE;
+
+  if (bitmap == NULL || loops == NULL)
+    return FALSE;
+
+  *loops = 1;
+
+  /* PropertyTagLoopCount. 0 == infinitely */
+  if (Ok == GdipGetPropertyItemSize ((GpImage *)bitmap, PropertyTagLoopCount, &item_size)) {
+    PropertyItem *item;
+    
+    item = (PropertyItem *)g_try_malloc (item_size);
+    if (Ok == GdipGetPropertyItem ((GpImage *)bitmap, PropertyTagLoopCount, item_size, item)) {
+      *loops = *((short *)item->value);
+      success = TRUE;
+    }
+    
+    g_free (item);
+  }
+  
+  return success;
+}
+
+/*************************************************************************/
+/*************************************************************************/
+
+struct _GdipContext {
+  GdkPixbufModuleUpdatedFunc  updated_func;
+  GdkPixbufModulePreparedFunc prepared_func;
+  GdkPixbufModuleSizeFunc     size_func;
+
+  gpointer                    user_data;
+
+  GByteArray                 *buffer;
+};
+typedef struct _GdipContext GdipContext;
+
+static void
+destroy_gdipcontext (GdipContext *context)
+{
+  if (context != NULL) {
+    g_byte_array_free (context->buffer, TRUE);
+    g_free (context);
+  }
+}
+
+static void
+emit_updated (GdipContext *context, GdkPixbuf *pixbuf)
+{
+  if (context->updated_func)
+    (*context->updated_func) (pixbuf,
+                              0, 0,
+                              gdk_pixbuf_get_width (pixbuf),
+                              gdk_pixbuf_get_height (pixbuf),
+                              context->user_data);
+}
+
+static void
+emit_prepared (GdipContext *context, GdkPixbuf *pixbuf, GdkPixbufAnimation *anim)
+{
+  if (context->prepared_func)
+    (*context->prepared_func) (pixbuf, anim, context->user_data);
+}
+
+static gpointer
+gdk_pixbuf__gdip_image_begin_load (GdkPixbufModuleSizeFunc size_func,
+                                   GdkPixbufModulePreparedFunc prepared_func,
+                                   GdkPixbufModuleUpdatedFunc  updated_func,
+                                   gpointer user_data,
+                                   GError **error)
+{
+  GdipContext *context = g_new0 (GdipContext, 1);
+
+  context->size_func     = size_func;
+  context->prepared_func = prepared_func;
+  context->updated_func  = updated_func;
+  context->user_data     = user_data;
+  context->buffer        = g_byte_array_new ();
+
+  return context;
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_load_increment (gpointer data,
+                                       const guchar *buf, guint size,
+                                       GError **error)
+{
+  GdipContext *context = (GdipContext *)data;
+  GByteArray *image_buffer = context->buffer;
+
+  g_byte_array_append (image_buffer, (guint8 *)buf, size);
+
+  return TRUE;
+}
+
+static GdkPixbuf *
+gdip_bitmap_to_pixbuf (GpBitmap *bitmap)
+{
+  GdkPixbuf *pixbuf = NULL;
+  guchar *cursor = NULL;
+  gint rowstride;
+  gboolean has_alpha = FALSE;
+  gint n_channels = 0;
+  gchar *option;
+
+  guint width = 0, height = 0, x, y;
+
+  gdip_bitmap_get_size (bitmap, &width, &height);
+  gdip_bitmap_get_has_alpha (bitmap, &has_alpha);
+
+  pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, has_alpha, 8, width, height);
+
+  if (!pixbuf)
+    return NULL;
+
+  rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+  cursor = gdk_pixbuf_get_pixels (pixbuf);
+  n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+
+  for (y = 0; y < height; y++) {
+    for (x = 0; x < width; x++) {
+      ARGB pixel;
+      guchar *b = cursor + (y * rowstride + (x * n_channels));
+      
+      if (Ok != GdipBitmapGetPixel (bitmap, x, y, &pixel)) {
+        g_object_unref (pixbuf);
+        return NULL;
+      }
+      
+      b[0] = (pixel & 0xff0000) >> 16;
+      b[1] = (pixel & 0x00ff00) >> 8;
+      b[2] = (pixel & 0x0000ff) >> 0;
+      
+      if (has_alpha)      
+        b[3] = (pixel & 0xff000000) >> 24;
+    }
+  }
+
+  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagOrientation, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "orientation", option);
+    g_free (option);
+  }
+
+  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagArtist, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "Author", option);
+    g_free (option);
+  }
+
+  if (gdip_bitmap_get_property_as_string (bitmap, PropertyTagImageTitle, &option)) {
+    gdk_pixbuf_set_option (pixbuf, "Title", option);
+    g_free (option);
+  }
+
+  return pixbuf;
+}
+
+static gboolean
+stop_load (GpBitmap *bitmap, GdipContext *context, GError **error)
+{
+  guint       n_frames = 1, i;
+  GdkPixbufGdipAnim *animation = NULL;
+
+  gdip_bitmap_get_n_frames (bitmap, &n_frames, TRUE);
+
+  for (i = 0; i < n_frames; i++) {
+    GdkPixbuf *pixbuf = NULL;
+    GdkPixbufFrame *frame;
+    guint frame_delay = 0;
+
+    gdip_bitmap_select_frame (bitmap, i, TRUE);
+    
+    pixbuf = gdip_bitmap_to_pixbuf (bitmap);
+    
+    if (!pixbuf) {
+      if (animation != NULL)
+        g_object_unref (G_OBJECT (animation));
+
+      destroy_gdipcontext (context);
+      g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_INSUFFICIENT_MEMORY, _("Couldn't create pixbuf"));
+      return FALSE;
+    }
+    
+    if (animation == NULL) {
+      guint n_loops = 1;
+
+      animation = g_object_new (GDK_TYPE_PIXBUF_GDIP_ANIM, NULL);
+      gdip_bitmap_get_n_loops (bitmap, &n_loops);
+      animation->loop = n_loops;
+    }
+
+    frame = g_new (GdkPixbufFrame, 1);
+    frame->pixbuf = pixbuf;
+
+    gdip_bitmap_get_frame_delay (bitmap, &frame_delay);
+  
+    animation->n_frames++;
+    animation->frames = g_list_append (animation->frames, frame);
+
+    animation->width = gdk_pixbuf_get_width (pixbuf);
+    animation->height = gdk_pixbuf_get_height (pixbuf);
+
+    /* GIF delay is in hundredths, we want thousandths */
+    frame->delay_time = frame_delay * 10;
+    frame->elapsed = animation->total_time;
+    
+    /* Some GIFs apparently have delay time of 0,
+     * that crashes everything so set it to "fast".
+     * Also, timeouts less than 20 or so just lock up
+     * the app or make the animation choppy, so fix them.
+     */
+    if (frame->delay_time < 20)
+      frame->delay_time = 20; /* 20 = "fast" */
+
+    animation->total_time += frame->delay_time;
+
+    if (i == 0)
+      emit_prepared (context, pixbuf, GDK_PIXBUF_ANIMATION (animation));
+
+    emit_updated (context, pixbuf);
+  }
+
+  if (animation != NULL)
+    g_object_unref (G_OBJECT (animation));
+
+  destroy_gdipcontext (context);
+  
+  return TRUE;
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_stop_load (gpointer data, GError **error)
+{
+  GdipContext *context = (GdipContext *)data;
+  GpBitmap    *bitmap = NULL;
+  GByteArray *image_buffer = context->buffer;
+
+  bitmap = gdip_buffer_to_bitmap ((gchar *)image_buffer->data, image_buffer->len, error);
+
+  if (!bitmap) {
+    destroy_gdipcontext (context);
+    g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Couldn't load bitmap"));
+    return FALSE;
+  }
+
+  return stop_load (bitmap, context, error);
+}
+
+static gboolean
+gdk_pixbuf__gdip_image_stop_vector_load (gpointer data, GError **error)
+{
+  GdipContext *context = (GdipContext *)data;
+  GByteArray *image_buffer = context->buffer;
+
+  GpImage *metafile;
+  GpGraphics *graphics;
+  GpBitmap *bitmap;
+  GpStatus status;
+  float metafile_xres, metafile_yres;
+  guint width, height;
+
+  metafile = gdip_buffer_to_image ((gchar *)image_buffer->data, image_buffer->len, error);
+  if (!metafile) {
+    destroy_gdipcontext (context);
+    g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_CORRUPT_IMAGE, _("Couldn't load metafile"));
+    return FALSE;
+  }
+
+  GdipGetImageWidth (metafile, &width);
+  GdipGetImageHeight (metafile, &height);
+
+  status = GdipCreateBitmapFromScan0 (width, height, 0, PixelFormat32bppARGB, NULL, &bitmap);
+  if (Ok != status) {
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+    GdipDisposeImage (metafile);
+    
+    return FALSE;
+  }
+
+  GdipGetImageHorizontalResolution (metafile, &metafile_xres);
+  GdipGetImageVerticalResolution (metafile, &metafile_yres);
+  GdipBitmapSetResolution (bitmap, metafile_xres, metafile_yres);
+
+  status = GdipGetImageGraphicsContext ((GpImage *)bitmap, &graphics);
+  if (Ok != status) {
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+    GdipDisposeImage ((GpImage *)bitmap);
+    GdipDisposeImage (metafile);
+    
+    return FALSE;
+  }
+  
+  /* gotta clear the bitmap */
+  GdipGraphicsClear (graphics, 0xffffffff);
+  
+  status = GdipDrawImageI (graphics, metafile, 0, 0);
+  if (Ok != status) {
+    gdip_set_error_from_gpstatus (error, GDK_PIXBUF_ERROR_FAILED, status);
+    GdipDeleteGraphics (graphics);
+    GdipDisposeImage ((GpImage *)bitmap);
+    GdipDisposeImage (metafile);
+    
+    return FALSE;
+  }
+  
+  GdipFlush (graphics, 1);
+  
+  GdipDeleteGraphics (graphics);
+  GdipDisposeImage (metafile);
+
+  return stop_load (bitmap, context, error);
+}
+
+static void 
+gdip_animation_prepare (GdkPixbuf *pixbuf,
+                        GdkPixbufAnimation *animation,
+                        gpointer user_data)
+{
+  GdkPixbufAnimation **anim;
+
+  anim = (GdkPixbufAnimation **)user_data;
+
+  /* save a reference to the animation */
+  g_object_ref (animation);
+  *anim = animation;
+}
+
+static GdkPixbufAnimation *
+gdk_pixbuf__gdip_image_load_animation (FILE *file,
+                                       GError **error)
+{
+  GdkPixbufAnimation *animation = NULL;
+
+  gpointer context;
+  char buffer[LOAD_BUFFER_SIZE];
+  size_t length;
+
+  context = gdk_pixbuf__gdip_image_begin_load (NULL, gdip_animation_prepare, NULL, &animation, error);
+
+  while (!feof (file) && !ferror (file)) {
+    length = fread (buffer, 1, sizeof (buffer), file);
+    if (length > 0) {
+      if (!gdk_pixbuf__gdip_image_load_increment (context, buffer, length, error)) {
+        gdk_pixbuf__gdip_image_stop_load (context, NULL);
+
+        if (animation)
+          g_object_unref (animation);
+
+        return NULL;
+      }
+    }
+  }
+
+  if (!gdk_pixbuf__gdip_image_stop_load(context, error)) {
+    if (animation)
+      g_object_unref (animation);
+    
+    return NULL;
+  }
+
+  return animation;
+}
+
+gboolean
+gdip_save_to_file_callback (const gchar *buf,
+                            gsize        count,
+                            GError     **error,
+                            gpointer     data)
+{
+  FILE *filehandle = data;
+  gsize n;
+  
+  n = fwrite (buf, 1, count, filehandle);
+  if (n != count) {
+    gint save_errno = errno;
+    g_set_error (error,
+                 G_FILE_ERROR,
+                 g_file_error_from_errno (save_errno),
+                 _("Error writing to image file: %s"),
+                 g_strerror (save_errno));
+    return FALSE;
+  }
+  
+  return TRUE;
+}
+
+void
+gdip_fill_vtable (GdkPixbufModule *module)
+{
+  if (gdip_init ()) {
+    module->begin_load     = gdk_pixbuf__gdip_image_begin_load;
+    module->stop_load      = gdk_pixbuf__gdip_image_stop_load;
+    module->load_increment = gdk_pixbuf__gdip_image_load_increment;
+    
+    /* this is the only way to get gtk_image_new_from_file() to load animations. it regrettably
+       does not use the GdkPixbufLoader interface. */
+    module->load_animation = gdk_pixbuf__gdip_image_load_animation;
+  }
+}
+
+void
+gdip_fill_vector_vtable (GdkPixbufModule *module)
+{
+  if (gdip_init ()) {
+    module->begin_load     = gdk_pixbuf__gdip_image_begin_load;
+    module->stop_load      = gdk_pixbuf__gdip_image_stop_vector_load;
+    module->load_increment = gdk_pixbuf__gdip_image_load_increment;
+  }
+}
+
+gboolean
+gdip_save_pixbuf (GdkPixbuf *pixbuf,
+                  const WCHAR *format,
+                  const EncoderParameters *encoder_params,
+                  GdkPixbufSaveFunc save_func,
+                  gpointer user_data,
+                  GError **error)
+{
+  GpBitmap *image;
+  CLSID clsid;
+  gboolean success;
+
+  if (!GetEncoderClsid (format, &clsid)) {
+    g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, _("Unsupported image format for GDI+"));
+    return FALSE;
+  }
+  
+  image = gdip_pixbuf_to_bitmap (pixbuf);
+
+  if (image == NULL) {
+    g_set_error (error, GDK_PIXBUF_ERROR, GDK_PIXBUF_ERROR_FAILED, _("Couldn't save"));
+    return FALSE;
+  }
+  
+  success = gdip_save_bitmap_to_callback (image, &clsid, encoder_params, save_func, user_data, error);
+
+  GdipDisposeImage ((GpImage *)image);
+
+  return success;
+}

Added: trunk/gdk-pixbuf/io-gdip-utils.h
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-utils.h	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,52 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#ifndef _HAVE_IO_GDIP_UTILS_H
+#define _HAVE_IO_GDIP_UTILS_H
+
+#include "gdk-pixbuf.h"
+#include "gdk-pixbuf-i18n.h"
+
+#include "io-gdip-native.h"
+
+gboolean
+gdip_save_to_file_callback (const gchar *buf,
+                            gsize        count,
+                            GError     **error,
+                            gpointer     data);
+
+void
+gdip_fill_vtable (GdkPixbufModule *module);
+
+void
+gdip_fill_vector_vtable (GdkPixbufModule *module);
+
+gboolean
+gdip_save_pixbuf (GdkPixbuf *pixbuf,
+                  const WCHAR *format,
+                  const EncoderParameters *encoder_params,
+                  GdkPixbufSaveFunc save_func,
+                  gpointer user_data,
+                  GError **error);
+
+#endif

Added: trunk/gdk-pixbuf/io-gdip-wmf.c
==============================================================================
--- (empty file)
+++ trunk/gdk-pixbuf/io-gdip-wmf.c	Thu Mar 20 23:24:45 2008
@@ -0,0 +1,63 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
+/* GdkPixbuf library - Win32 GDI+ Pixbuf Loader
+ *
+ * Copyright (C) 2008 Dominic Lachowicz
+ * Copyright (C) 2008 Alberto Ruiz
+ *
+ * Authors: Dominic Lachowicz <domlachowicz gmail com>
+ *          Alberto Ruiz <aruiz gnome org>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser 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
+ * Lesser General Public License for more  * You should have received a copy of the GNU Lesser 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.
+ */
+
+#include "io-gdip-utils.h"
+
+#ifndef INCLUDE_gdiplus
+#define MODULE_ENTRY(function) G_MODULE_EXPORT void function
+#else
+#define MODULE_ENTRY(function) void _gdk_pixbuf__gdip_wmf_ ## function
+#endif
+
+MODULE_ENTRY (fill_vtable) (GdkPixbufModule *module)
+{
+  gdip_fill_vector_vtable (module);
+}
+
+MODULE_ENTRY (fill_info) (GdkPixbufFormat *info)
+{
+  static GdkPixbufModulePattern signature[] = {
+    { "\xd7\xcd\xc6\x9a", NULL, 100 }, /* WMF */
+    { "\x01\x00\x09\x00", NULL, 100 }, /* WMF */
+    { NULL, NULL, 0 }
+  };
+
+  static gchar *mime_types[] = {
+    "image/x-wmf",
+    NULL
+  };
+
+  static gchar *extensions[] = {
+    "wmf",
+    "apm",
+    NULL
+  };
+
+  info->name        = "wmf";
+  info->signature   = signature;
+  info->description = _("The WMF image format");
+  info->mime_types  = mime_types;
+  info->extensions  = extensions;
+  info->flags       = GDK_PIXBUF_FORMAT_THREADSAFE;
+  info->license     = "LGPL";
+}



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]