]> Pileus Git - ~andy/gtk/blobdiff - gdk-pixbuf/gdk-pixbuf-io.c
Interpret patterns where the first byte of the mask is '*' as unanchored.
[~andy/gtk] / gdk-pixbuf / gdk-pixbuf-io.c
index 3afb09f19049fd22172200357af3bf7e20ae9733..a8faa782f9bface00e013ff96a22fefe77cd6f32 100644 (file)
@@ -33,9 +33,9 @@
 #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>
 
 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;
 }
@@ -821,7 +835,7 @@ gdk_pixbuf_new_from_file (const char *filename,
        GdkPixbuf *pixbuf;
        int size;
        FILE *f;
-       guchar buffer [128];
+       guchar buffer[256];
        GdkPixbufModule *image_module;
        gchar *display_name;
 
@@ -906,7 +920,6 @@ gdk_pixbuf_new_from_file (const char *filename,
 #ifdef G_OS_WIN32
 
 #undef gdk_pixbuf_new_from_file
-
 GdkPixbuf *
 gdk_pixbuf_new_from_file (const char *filename,
                           GError    **error)
@@ -940,9 +953,20 @@ size_prepared_cb (GdkPixbufLoader *loader,
 
        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 {
@@ -950,8 +974,10 @@ size_prepared_cb (GdkPixbufLoader *loader,
                        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);
@@ -960,8 +986,8 @@ size_prepared_cb (GdkPixbufLoader *loader,
 /**
  * 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
- * @height: The height the image should have
+ * @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
@@ -1019,8 +1045,8 @@ gdk_pixbuf_new_from_file_at_size (const char *filename,
 /**
  * gdk_pixbuf_new_from_file_at_scale:
  * @filename: Name of file to load, in the GLib file name encoding
- * @width: The width the image should have
- * @height: The height the image should have
+ * @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
  *
@@ -1028,7 +1054,14 @@ gdk_pixbuf_new_from_file_at_size (const char *filename,
  * 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,
@@ -1058,7 +1091,8 @@ gdk_pixbuf_new_from_file_at_scale (const char *filename,
        } 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 = g_fopen (filename, "rb");
        if (!f) {
@@ -1528,8 +1562,8 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
  * @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:
  *
@@ -1557,11 +1591,15 @@ gdk_pixbuf_real_save_to_callback (GdkPixbuf         *pixbuf,
  *                  "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.
@@ -1599,6 +1637,50 @@ gdk_pixbuf_save (GdkPixbuf  *pixbuf,
         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.
@@ -1608,7 +1690,7 @@ gdk_pixbuf_save (GdkPixbuf  *pixbuf,
  * @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.
  *
@@ -1625,7 +1707,6 @@ gdk_pixbuf_savev (GdkPixbuf  *pixbuf,
 {
         FILE *f = NULL;
         gboolean result;
-        
        
         g_return_val_if_fail (filename != NULL, FALSE);
         g_return_val_if_fail (type != NULL, FALSE);
@@ -1672,6 +1753,38 @@ gdk_pixbuf_savev (GdkPixbuf  *pixbuf,
        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.
@@ -1738,7 +1851,7 @@ gdk_pixbuf_save_to_callback    (GdkPixbuf  *pixbuf,
  * @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
@@ -1784,7 +1897,7 @@ gdk_pixbuf_save_to_callbackv   (GdkPixbuf  *pixbuf,
  * @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
@@ -1872,7 +1985,7 @@ save_to_buffer_callback (const gchar *data,
  * @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
  *
@@ -2137,6 +2250,9 @@ gdk_pixbuf_get_formats (void)
 }
 
 
+#define __GDK_PIXBUF_IO_C__
+#include "gdk-pixbuf-aliasdef.c"
+