diff options
author | Tor Lillqvist <tml@novell.com> | 2008-03-20 23:24:45 +0000 |
---|---|---|
committer | Tor Lillqvist <tml@src.gnome.org> | 2008-03-20 23:24:45 +0000 |
commit | 6d15bbbe1da2a30a2bf4b519cd03bf3bc80ccfaf (patch) | |
tree | 7f865e3e03fc46190ca21516069defda81150860 /gdk-pixbuf | |
parent | 84fa2c6194c90ddaa05c353ab75fe89750f47677 (diff) | |
download | gtk+-6d15bbbe1da2a30a2bf4b519cd03bf3bc80ccfaf.tar.gz |
Import the GDI+ gdk-pixbuf loaders for Windows by Dominic Lachowicz and
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.
svn path=/trunk/; revision=19914
Diffstat (limited to 'gdk-pixbuf')
-rw-r--r-- | gdk-pixbuf/ChangeLog | 36 | ||||
-rw-r--r-- | gdk-pixbuf/Makefile.am | 216 | ||||
-rw-r--r-- | gdk-pixbuf/gdk-pixbuf-io.c | 70 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-animation.c | 383 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-animation.h | 117 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-bmp.c | 87 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-emf.c | 64 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-gif.c | 85 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-ico.c | 64 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-jpeg.c | 141 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-native.h | 235 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-png.c | 138 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-propertytags.h | 228 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-tiff.c | 87 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-utils.c | 996 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-utils.h | 52 | ||||
-rw-r--r-- | gdk-pixbuf/io-gdip-wmf.c | 63 |
17 files changed, 3016 insertions, 46 deletions
diff --git a/gdk-pixbuf/ChangeLog b/gdk-pixbuf/ChangeLog index d8e689776c..2205d3d2c0 100644 --- a/gdk-pixbuf/ChangeLog +++ b/gdk-pixbuf/ChangeLog @@ -1,3 +1,39 @@ +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. + + * 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. + 2008-03-11 Claudio Saavedra <csaavedra@alumnos.utalca.cl> * io-bmp.c: (gdk_pixbuf__bmp_image_stop_load): Set a diff --git a/gdk-pixbuf/Makefile.am b/gdk-pixbuf/Makefile.am index 263c968fc6..d90aa43ca7 100644 --- a/gdk-pixbuf/Makefile.am +++ b/gdk-pixbuf/Makefile.am @@ -13,6 +13,8 @@ gdk_pixbuf_symbols = -export-symbols gdk_pixbuf.def 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 @@ module_libs = libgdk_pixbuf-$(GTK_API_VERSION).la $(GDK_PIXBUF_DEP_LIBS) # # 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_SOURCES = io-jasper.c 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 +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 -PNG_LIB = libpixbufloader-png.la -endif + +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 @@ else 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 @@ JPEG_LIB = libpixbufloader-jpeg.la 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 @@ else 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 @@ loader_LTLIBRARIES = \ $(TGA_LIB) \ $(ICNS_LIB) \ $(PCX_LIB) \ - $(JASPER_LIB) + $(JASPER_LIB) \ + $(GDIPLUS_LIBS) endif @@ -332,7 +489,8 @@ noinst_LTLIBRARIES = \ $(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 @@ libgdk_pixbuf_2_0_la_LDFLAGS = \ $(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 = \ diff --git a/gdk-pixbuf/gdk-pixbuf-io.c b/gdk-pixbuf/gdk-pixbuf-io.c index 0255cbfb40..9214ce4cd6 100644 --- a/gdk-pixbuf/gdk-pixbuf-io.c +++ b/gdk-pixbuf/gdk-pixbuf-io.c @@ -363,6 +363,22 @@ gdk_pixbuf_io_init (void) #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 (wbmp); 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 @@ _gdk_pixbuf_load_module (GdkPixbufModule *image_module, 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 diff --git a/gdk-pixbuf/io-gdip-animation.c b/gdk-pixbuf/io-gdip-animation.c new file mode 100644 index 0000000000..14cd034bc2 --- /dev/null +++ b/gdk-pixbuf/io-gdip-animation.c @@ -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; +} diff --git a/gdk-pixbuf/io-gdip-animation.h b/gdk-pixbuf/io-gdip-animation.h new file mode 100644 index 0000000000..01e827876d --- /dev/null +++ b/gdk-pixbuf/io-gdip-animation.h @@ -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 diff --git a/gdk-pixbuf/io-gdip-bmp.c b/gdk-pixbuf/io-gdip-bmp.c new file mode 100644 index 0000000000..40f6a5f536 --- /dev/null +++ b/gdk-pixbuf/io-gdip-bmp.c @@ -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";
+}
diff --git a/gdk-pixbuf/io-gdip-emf.c b/gdk-pixbuf/io-gdip-emf.c new file mode 100644 index 0000000000..07ee0b0200 --- /dev/null +++ b/gdk-pixbuf/io-gdip-emf.c @@ -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"; +} diff --git a/gdk-pixbuf/io-gdip-gif.c b/gdk-pixbuf/io-gdip-gif.c new file mode 100644 index 0000000000..f991a9d3de --- /dev/null +++ b/gdk-pixbuf/io-gdip-gif.c @@ -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";
+}
diff --git a/gdk-pixbuf/io-gdip-ico.c b/gdk-pixbuf/io-gdip-ico.c new file mode 100644 index 0000000000..8538b58111 --- /dev/null +++ b/gdk-pixbuf/io-gdip-ico.c @@ -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"; +} diff --git a/gdk-pixbuf/io-gdip-jpeg.c b/gdk-pixbuf/io-gdip-jpeg.c new file mode 100644 index 0000000000..8bd3058606 --- /dev/null +++ b/gdk-pixbuf/io-gdip-jpeg.c @@ -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";
+}
diff --git a/gdk-pixbuf/io-gdip-native.h b/gdk-pixbuf/io-gdip-native.h new file mode 100644 index 0000000000..f5787ea835 --- /dev/null +++ b/gdk-pixbuf/io-gdip-native.h @@ -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 diff --git a/gdk-pixbuf/io-gdip-png.c b/gdk-pixbuf/io-gdip-png.c new file mode 100644 index 0000000000..8b094bfca4 --- /dev/null +++ b/gdk-pixbuf/io-gdip-png.c @@ -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";
+}
diff --git a/gdk-pixbuf/io-gdip-propertytags.h b/gdk-pixbuf/io-gdip-propertytags.h new file mode 100644 index 0000000000..95243bfe1a --- /dev/null +++ b/gdk-pixbuf/io-gdip-propertytags.h @@ -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 diff --git a/gdk-pixbuf/io-gdip-tiff.c b/gdk-pixbuf/io-gdip-tiff.c new file mode 100644 index 0000000000..7e0a1898ea --- /dev/null +++ b/gdk-pixbuf/io-gdip-tiff.c @@ -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";
+}
diff --git a/gdk-pixbuf/io-gdip-utils.c b/gdk-pixbuf/io-gdip-utils.c new file mode 100644 index 0000000000..392c3bfc6a --- /dev/null +++ b/gdk-pixbuf/io-gdip-utils.c @@ -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; +} diff --git a/gdk-pixbuf/io-gdip-utils.h b/gdk-pixbuf/io-gdip-utils.h new file mode 100644 index 0000000000..14681c1e26 --- /dev/null +++ b/gdk-pixbuf/io-gdip-utils.h @@ -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 diff --git a/gdk-pixbuf/io-gdip-wmf.c b/gdk-pixbuf/io-gdip-wmf.c new file mode 100644 index 0000000000..3c89d4a3d7 --- /dev/null +++ b/gdk-pixbuf/io-gdip-wmf.c @@ -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"; +} |