#include <unistd.h>
#endif
-#include "gdk-pixbuf-alias.h"
#include "gdk-pixbuf-private.h"
#include "gdk-pixbuf-io.h"
+#include "gdk-pixbuf-alias.h"
+
+#include <glib/gstdio.h>
#ifdef G_OS_WIN32
#define STRICT
static gint
format_check (GdkPixbufModule *module, guchar *buffer, int size)
{
- int j;
+ int i, j;
gchar m;
GdkPixbufModulePattern *pattern;
+ gboolean unanchored;
+ guchar *prefix, *mask;
for (pattern = module->info->signature; pattern->prefix; pattern++) {
- for (j = 0; j < size && pattern->prefix[j] != 0; j++) {
- m = pattern->mask ? pattern->mask[j] : ' ';
- if (m == ' ') {
- if (buffer[j] != pattern->prefix[j])
- break;
- }
- else if (m == '!') {
- if (buffer[j] == pattern->prefix[j])
- break;
- }
- else if (m == 'z') {
- if (buffer[j] != 0)
- break;
- }
- else if (m == 'n') {
- if (buffer[j] == 0)
- break;
- }
- }
- if (pattern->prefix[j] == 0)
- return pattern->relevance;
+ if (pattern->mask && pattern->mask[0] == '*') {
+ prefix = pattern->prefix + 1;
+ mask = pattern->mask + 1;
+ unanchored = TRUE;
+ }
+ else {
+ prefix = pattern->prefix;
+ mask = pattern->mask;
+ unanchored = FALSE;
+ }
+ for (i = 0; unanchored && i < size; i++) {
+ for (j = 0; i + j < size && prefix[j] != 0; j++) {
+ m = mask ? mask[j] : ' ';
+ if (m == ' ') {
+ if (buffer[i + j] != prefix[j])
+ break;
+ }
+ else if (m == '!') {
+ if (buffer[i + j] == prefix[j])
+ break;
+ }
+ else if (m == 'z') {
+ if (buffer[i + j] != 0)
+ break;
+ }
+ else if (m == 'n') {
+ if (buffer[i + j] == 0)
+ break;
+ }
+ }
+ if (prefix[j] == 0)
+ return pattern->relevance;
+ }
}
return 0;
}
G_LOCK_DEFINE_STATIC (init_lock);
G_LOCK_DEFINE_STATIC (threadunsafe_loader_lock);
-void
+gboolean
_gdk_pixbuf_lock (GdkPixbufModule *image_module)
{
- if (!(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
+ if (g_threads_got_initialized &&
+ !(image_module->info->flags & GDK_PIXBUF_FORMAT_THREADSAFE)) {
G_LOCK (threadunsafe_loader_lock);
+
+ return TRUE;
}
+
+ return FALSE;
}
void
}
}
-#endif
+#endif /* G_OS_WIN32 */
static gchar *
gdk_pixbuf_get_module_file (void)
char *path;
GModule *module;
gpointer sym;
-
+
g_return_val_if_fail (image_module->module == NULL, FALSE);
path = image_module->module_path;
GError **error)
{
gboolean ret;
+ gboolean locked = FALSE;
- G_LOCK (init_lock);
+ /* be extra careful, maybe the module initializes
+ * the thread system
+ */
+ if (g_threads_got_initialized)
+ {
+ G_LOCK (init_lock);
+ locked = TRUE;
+ }
ret = _gdk_pixbuf_load_module_unlocked (image_module, error);
- G_UNLOCK (init_lock);
-
+ if (locked)
+ G_UNLOCK (init_lock);
return ret;
}
-#else
+
+#else /* !USE_GMODULE */
#define module(type) \
extern void MODULE_ENTRY (type, fill_info) (GdkPixbufFormat *info); \
for (name = included_formats; *name; name++) {
module = g_new0 (GdkPixbufModule, 1);
module->module_name = *name;
- if (_gdk_pixbuf_load_module_unlocked (module, NULL))
+ if (_gdk_pixbuf_load_module (module, NULL))
file_formats = g_slist_prepend (file_formats, module);
else
g_free (module);
}
}
-#endif
+#endif /* !USE_GMODULE */
\f
GdkPixbuf *pixbuf = NULL;
GdkPixbufAnimation *animation = NULL;
gpointer context;
+ gboolean locked;
- _gdk_pixbuf_lock (module);
+ locked = _gdk_pixbuf_lock (module);
if (module->load != NULL) {
pixbuf = (* module->load) (f, error);
pixbuf = gdk_pixbuf_animation_get_static_image (animation);
g_object_ref (pixbuf);
-
g_object_unref (animation);
}
}
out:
- _gdk_pixbuf_unlock (module);
+ if (locked)
+ _gdk_pixbuf_unlock (module);
return pixbuf;
}
/**
* gdk_pixbuf_new_from_file:
- * @filename: Name of file to load.
+ * @filename: Name of file to load, in the GLib file name encoding
* @error: Return location for an error
*
* Creates a new pixbuf by loading an image from a file. The file format is
GdkPixbuf *pixbuf;
int size;
FILE *f;
- guchar buffer [128];
+ guchar buffer[256];
GdkPixbufModule *image_module;
gchar *display_name;
display_name = g_filename_display_name (filename);
- f = fopen (filename, "rb");
+ f = g_fopen (filename, "rb");
if (!f) {
g_set_error (error,
G_FILE_ERROR,
return pixbuf;
}
+#ifdef G_OS_WIN32
+
+#undef gdk_pixbuf_new_from_file
+GdkPixbuf *
+gdk_pixbuf_new_from_file (const char *filename,
+ GError **error)
+{
+ gchar *utf8_filename =
+ g_locale_to_utf8 (filename, -1, NULL, NULL, error);
+ GdkPixbuf *retval;
+
+ if (utf8_filename == NULL)
+ return NULL;
+
+ retval = gdk_pixbuf_new_from_file_utf8 (utf8_filename, error);
+
+ g_free (utf8_filename);
+
+ return retval;
+}
+#endif
+
static void
size_prepared_cb (GdkPixbufLoader *loader,
int width,
g_return_if_fail (width > 0 && height > 0);
- if(info->preserve_aspect_ratio) {
- if ((double)height * (double)info->width >
- (double)width * (double)info->height) {
+ if (info->preserve_aspect_ratio &&
+ (info->width > 0 || info->height > 0)) {
+ if (info->width < 0)
+ {
+ width = width * (double)info->height/(double)height;
+ height = info->height;
+ }
+ else if (info->height < 0)
+ {
+ height = height * (double)info->width/(double)width;
+ width = info->width;
+ }
+ else if ((double)height * (double)info->width >
+ (double)width * (double)info->height) {
width = 0.5 + (double)width * (double)info->height / (double)height;
height = info->height;
} else {
width = info->width;
}
} else {
- width = info->width;
- height = info->height;
+ if (info->width > 0)
+ width = info->width;
+ if (info->height > 0)
+ height = info->height;
}
gdk_pixbuf_loader_set_size (loader, width, height);
}
+/**
+ * gdk_pixbuf_new_from_file_at_size:
+ * @filename: Name of file to load, in the GLib file name encoding
+ * @width: The width the image should have or -1 to not constrain the width
+ * @height: The height the image should have or -1 to not constrain the height
+ * @error: Return location for an error
+ *
+ * Creates a new pixbuf by loading an image from a file. The file format is
+ * detected automatically. If %NULL is returned, then @error will be set.
+ * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
+ * The image will be scaled to fit in the requested size, preserving
+ * the image's aspect ratio.
+ *
+ * Return value: A newly-created pixbuf with a reference count of 1, or
+ * %NULL if any of several error conditions occurred: the file could not
+ * be opened, there was no loader for the file's format, there was not
+ * enough memory to allocate the image buffer, or the image file contained
+ * invalid data.
+ *
+ * Since: 2.4
+ **/
+GdkPixbuf *
+gdk_pixbuf_new_from_file_at_size (const char *filename,
+ int width,
+ int height,
+ GError **error)
+{
+ return gdk_pixbuf_new_from_file_at_scale (filename,
+ width, height,
+ TRUE, error);
+}
+
+#ifdef G_OS_WIN32
+
+#undef gdk_pixbuf_new_from_file_at_size
+
+GdkPixbuf *
+gdk_pixbuf_new_from_file_at_size (const char *filename,
+ int width,
+ int height,
+ GError **error)
+{
+ gchar *utf8_filename =
+ g_locale_to_utf8 (filename, -1, NULL, NULL, error);
+ GdkPixbuf *retval;
+
+ if (utf8_filename == NULL)
+ return NULL;
+
+ retval = gdk_pixbuf_new_from_file_at_size_utf8 (utf8_filename,
+ width, height,
+ error);
+
+ g_free (utf8_filename);
+
+ return retval;
+}
+#endif
+
/**
* gdk_pixbuf_new_from_file_at_scale:
- * @filename: Name of file to load.
- * @width: The width the image should have
- * @height: The height the image should have
+ * @filename: Name of file to load, in the GLib file name encoding
+ * @width: The width the image should have or -1 to not constrain the width
+ * @height: The height the image should have or -1 to not constrain the height
* @preserve_aspect_ratio: %TRUE to preserve the image's aspect ratio
* @error: Return location for an error
*
* detected automatically. If %NULL is returned, then @error will be set.
* Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
* The image will be scaled to fit in the requested size, optionally preserving
- * the image's aspect ratio.
+ * the image's aspect ratio.
+ *
+ * When preserving the aspect ratio, a @width of -1 will cause the image
+ * to be scaled to the exact given height, and a @height of -1 will cause
+ * the image to be scaled to the exact given width. When not preserving
+ * aspect ratio, a @width or @height of -1 means to not scale the image
+ * at all in that dimension. Negative values for @width and @height are
+ * allowed since 2.8.
*
* Return value: A newly-created pixbuf with a reference count of 1, or %NULL
* if any of several error conditions occurred: the file could not be opened,
} info;
g_return_val_if_fail (filename != NULL, NULL);
- g_return_val_if_fail (width > 0 && height > 0, NULL);
+ g_return_val_if_fail (width > 0 || width == -1, NULL);
+ g_return_val_if_fail (height > 0 || height == -1, NULL);
- f = fopen (filename, "rb");
+ f = g_fopen (filename, "rb");
if (!f) {
gchar *display_name = g_filename_display_name (filename);
g_set_error (error,
return pixbuf;
}
-/**
- * gdk_pixbuf_new_from_file_at_size:
- * @filename: Name of file to load.
- * @width: The width the image should have
- * @height: The height the image should have
- * @error: Return location for an error
- *
- * Creates a new pixbuf by loading an image from a file. The file format is
- * detected automatically. If %NULL is returned, then @error will be set.
- * Possible errors are in the #GDK_PIXBUF_ERROR and #G_FILE_ERROR domains.
- * The image will be scaled to fit in the requested size, preserving
- * the image's aspect ratio.
- *
- * Return value: A newly-created pixbuf with a reference count of 1, or
- * %NULL if any of several error conditions occurred: the file could not
- * be opened, there was no loader for the file's format, there was not
- * enough memory to allocate the image buffer, or the image file contained
- * invalid data.
- *
- * Since: 2.4
- **/
+#ifdef G_OS_WIN32
+
+#undef gdk_pixbuf_new_from_file_at_scale
+
GdkPixbuf *
-gdk_pixbuf_new_from_file_at_size (const char *filename,
- int width,
- int height,
- GError **error)
+gdk_pixbuf_new_from_file_at_scale (const char *filename,
+ int width,
+ int height,
+ gboolean preserve_aspect_ratio,
+ GError **error)
{
- return gdk_pixbuf_new_from_file_at_scale (filename,
- width, height,
- TRUE, error);
+ gchar *utf8_filename =
+ g_locale_to_utf8 (filename, -1, NULL, NULL, error);
+ GdkPixbuf *retval;
+
+ if (utf8_filename == NULL)
+ return NULL;
+
+ retval = gdk_pixbuf_new_from_file_at_scale_utf8 (utf8_filename,
+ width, height,
+ preserve_aspect_ratio,
+ error);
+
+ g_free (utf8_filename);
+
+ return retval;
}
+#endif
+
static void
info_cb (GdkPixbufLoader *loader,
g_return_val_if_fail (filename != NULL, NULL);
- f = fopen (filename, "rb");
+ f = g_fopen (filename, "rb");
if (!f)
return NULL;
GdkPixbuf *(* load_xpm_data) (const char **data);
GdkPixbuf *pixbuf;
GError *error = NULL;
- GdkPixbufModule *xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
+ GdkPixbufModule *xpm_module;
+ gboolean locked;
+
+ xpm_module = _gdk_pixbuf_get_named_module ("xpm", &error);
if (xpm_module == NULL) {
g_warning ("Error loading XPM image loader: %s", error->message);
g_error_free (error);
}
}
- _gdk_pixbuf_lock (xpm_module);
+ locked = _gdk_pixbuf_lock (xpm_module);
if (xpm_module->load_xpm_data == NULL) {
g_warning ("gdk-pixbuf XPM module lacks XPM data capability");
load_xpm_data = xpm_module->load_xpm_data;
pixbuf = (* load_xpm_data) (data);
}
-
- _gdk_pixbuf_unlock (xpm_module);
+
+ if (locked)
+ _gdk_pixbuf_unlock (xpm_module);
return pixbuf;
}
{
gboolean ret;
GdkPixbufModule *image_module = NULL;
+ gboolean locked;
image_module = _gdk_pixbuf_get_named_module (type, error);
if (!_gdk_pixbuf_load_module (image_module, error))
return FALSE;
- _gdk_pixbuf_lock (image_module);
+ locked = _gdk_pixbuf_lock (image_module);
if (image_module->save) {
/* save normally */
ret = FALSE;
}
- _gdk_pixbuf_unlock (image_module);
+ if (locked)
+ _gdk_pixbuf_unlock (image_module);
return ret;
}
gchar *buf = NULL;
gsize n;
gchar *filename = NULL;
+ gboolean locked;
buf = g_try_malloc (TMP_FILE_BUF_SIZE);
if (buf == NULL) {
goto end;
}
- _gdk_pixbuf_lock (image_module);
+ locked = _gdk_pixbuf_lock (image_module);
retval = (image_module->save) (f, pixbuf, keys, values, error);
- _gdk_pixbuf_unlock (image_module);
+ if (locked)
+ _gdk_pixbuf_unlock (image_module);
if (!retval)
goto end;
if (f)
fclose (f);
if (filename) {
- unlink (filename);
+ g_unlink (filename);
g_free (filename);
}
g_free (buf);
{
gboolean ret;
GdkPixbufModule *image_module = NULL;
+ gboolean locked;
image_module = _gdk_pixbuf_get_named_module (type, error);
if (!_gdk_pixbuf_load_module (image_module, error))
return FALSE;
- _gdk_pixbuf_lock (image_module);
+ locked = _gdk_pixbuf_lock (image_module);
if (image_module->save_to_callback) {
/* save normally */
ret = FALSE;
}
- _gdk_pixbuf_unlock (image_module);
+ if (locked)
+ _gdk_pixbuf_unlock (image_module);
return ret;
}
* @error: return location for error, or %NULL
* @Varargs: list of key-value save options
*
- * Saves pixbuf to a file in format @type. By default, "jpeg", "png" and
- * "ico" are possible file formats to save in, but more formats may be
+ * Saves pixbuf to a file in format @type. By default, "jpeg", "png", "ico"
+ * and "bmp" are possible file formats to save in, but more formats may be
* installed. The list of all writable formats can be determined in the
* following way:
*
* "quality", "100", NULL);
* </programlisting></informalexample>
*
- * Currently only few parameters exist. JPEG images can be saved with a
- * "quality" parameter; its value should be in the range [0,100].
+ * Currently only few parameters exist. JPEG images can be saved with a
+ * "quality" parameter; its value should be in the range [0,100].
+ *
* Text chunks can be attached to PNG images by specifying parameters of
* the form "tEXt::key", where key is an ASCII string of length 1-79.
- * The values are UTF-8 encoded strings.
+ * The values are UTF-8 encoded strings. The PNG compression level can
+ * be specified using the "compression" parameter; it's value is in an
+ * integer in the range of [0,9].
+ *
* ICO images can be saved in depth 16, 24, or 32, by using the "depth"
* parameter. When the ICO saver is given "x_hot" and "y_hot" parameters,
* it produces a CUR instead of an ICO.
return result;
}
+#ifdef G_OS_WIN32
+
+#undef gdk_pixbuf_save
+
+gboolean
+gdk_pixbuf_save (GdkPixbuf *pixbuf,
+ const char *filename,
+ const char *type,
+ GError **error,
+ ...)
+{
+ char *utf8_filename;
+ gchar **keys = NULL;
+ gchar **values = NULL;
+ va_list args;
+ gboolean result;
+
+ g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+ utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
+
+ if (utf8_filename == NULL)
+ return FALSE;
+
+ va_start (args, error);
+
+ collect_save_options (args, &keys, &values);
+
+ va_end (args);
+
+ result = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
+ keys, values,
+ error);
+
+ g_free (utf8_filename);
+
+ g_strfreev (keys);
+ g_strfreev (values);
+
+ return result;
+}
+
+#endif
+
/**
* gdk_pixbuf_savev:
* @pixbuf: a #GdkPixbuf.
* @option_values: values for named options
* @error: return location for error, or %NULL
*
- * Saves pixbuf to a file in @type, which is currently "jpeg", "png" or "ico".
+ * Saves pixbuf to a file in @type, which is currently "jpeg", "png", "ico" or "bmp".
* If @error is set, %FALSE will be returned.
* See gdk_pixbuf_save () for more details.
*
{
FILE *f = NULL;
gboolean result;
-
g_return_val_if_fail (filename != NULL, FALSE);
g_return_val_if_fail (type != NULL, FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
- f = fopen (filename, "wb");
+ f = g_fopen (filename, "wb");
if (f == NULL) {
gchar *display_name = g_filename_display_name (filename);
return TRUE;
}
+#ifdef G_OS_WIN32
+
+#undef gdk_pixbuf_savev
+
+gboolean
+gdk_pixbuf_savev (GdkPixbuf *pixbuf,
+ const char *filename,
+ const char *type,
+ char **option_keys,
+ char **option_values,
+ GError **error)
+{
+ char *utf8_filename;
+ gboolean retval;
+
+ g_return_val_if_fail (filename != NULL, FALSE);
+
+ utf8_filename = g_locale_to_utf8 (filename, -1, NULL, NULL, error);
+
+ if (utf8_filename == NULL)
+ return FALSE;
+
+ retval = gdk_pixbuf_savev_utf8 (pixbuf, utf8_filename, type,
+ option_keys, option_values, error);
+
+ g_free (utf8_filename);
+
+ return retval;
+}
+
+#endif
+
/**
* gdk_pixbuf_save_to_callback:
* @pixbuf: a #GdkPixbuf.
* @error: return location for error, or %NULL
*
* Saves pixbuf to a callback in format @type, which is currently "jpeg",
- * "png" or "ico". If @error is set, %FALSE will be returned. See
+ * "png", "ico" or "bmp". If @error is set, %FALSE will be returned. See
* gdk_pixbuf_save_to_callback () for more details.
*
* Return value: whether an error was set
* @Varargs: list of key-value save options
*
* Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
- * "png" or "ico". This is a convenience function that uses
+ * "png", "ico" or "bmp". This is a convenience function that uses
* gdk_pixbuf_save_to_callback() to do the real work. Note that the buffer
* is not nul-terminated and may contain embedded nuls.
* If @error is set, %FALSE will be returned and @string will be set to
* @error: return location for error, or %NULL
*
* Saves pixbuf to a new buffer in format @type, which is currently "jpeg",
- * "png" or "ico". See gdk_pixbuf_save_to_buffer() for more details.
+ * "png", "ico" or "bmp". See gdk_pixbuf_save_to_buffer() for more details.
*
* Return value: whether an error was set
*
}
+#define __GDK_PIXBUF_IO_C__
+#include "gdk-pixbuf-aliasdef.c"
+