Addl fix #521: zoom increment is not multiplicative
[geeqie.git] / src / pixbuf-renderer.c
index 32f8641..54a943f 100644 (file)
@@ -1,13 +1,22 @@
 /*
- * Geeqie
- * (C) 2006 John Ellis
- * Copyright (C) 2008 - 2012 The Geeqie Team
+ * Copyright (C) 2006 John Ellis
+ * Copyright (C) 2008 - 2016 The Geeqie Team
  *
  * Author: John Ellis
  *
- * This software is released under the GNU General Public License (GNU GPL).
- * Please read the included file COPYING for more information.
- * This software comes with no warranty of any kind, use at your own risk!
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
  */
 
 #include <stdio.h>
@@ -96,7 +105,8 @@ enum {
        PROP_WINDOW_LIMIT,
        PROP_WINDOW_LIMIT_VALUE,
        PROP_AUTOFIT_LIMIT,
-       PROP_AUTOFIT_LIMIT_VALUE
+       PROP_AUTOFIT_LIMIT_VALUE,
+       PROP_ENLARGEMENT_LIMIT_VALUE
 };
 
 typedef enum {
@@ -139,6 +149,16 @@ static void pr_stereo_temp_disable(PixbufRenderer *pr, gboolean disable);
  *-------------------------------------------------------------------
  */
 
+static void pixbuf_renderer_class_init_wrapper(void *g_class, void *class_data)
+{
+       pixbuf_renderer_class_init(g_class);
+}
+
+static void pixbuf_renderer_init_wrapper(PixbufRenderer *pr, void *class_data)
+{
+       pixbuf_renderer_init(pr);
+}
+
 GType pixbuf_renderer_get_type(void)
 {
        static GType pixbuf_renderer_type = 0;
@@ -150,12 +170,12 @@ GType pixbuf_renderer_get_type(void)
                        sizeof(PixbufRendererClass), /* class_size */
                        NULL,           /* base_init */
                        NULL,           /* base_finalize */
-                       (GClassInitFunc)pixbuf_renderer_class_init,
+                       (GClassInitFunc)pixbuf_renderer_class_init_wrapper,
                        NULL,           /* class_finalize */
                        NULL,           /* class_data */
                        sizeof(PixbufRenderer), /* instance_size */
                        0,              /* n_preallocs */
-                       (GInstanceInitFunc)pixbuf_renderer_init, /* instance_init */
+                       (GInstanceInitFunc)pixbuf_renderer_init_wrapper, /* instance_init */
                        NULL,           /* value_table */
                        };
 
@@ -203,7 +223,7 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class)
                                                          "Zoom quality",
                                                          NULL,
                                                          GDK_INTERP_NEAREST,
-                                                         GDK_INTERP_HYPER,
+                                                         GDK_INTERP_BILINEAR,
                                                          GDK_INTERP_BILINEAR,
                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
 
@@ -259,7 +279,7 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class)
        g_object_class_install_property(gobject_class,
                                        PROP_CACHE_SIZE_DISPLAY,
                                        g_param_spec_uint("cache_display",
-                                                         "Display cache size MB",
+                                                         "Display cache size MiB",
                                                          NULL,
                                                          0,
                                                          128,
@@ -320,6 +340,16 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class)
                                                          100,
                                                          G_PARAM_READABLE | G_PARAM_WRITABLE));
 
+       g_object_class_install_property(gobject_class,
+                                       PROP_ENLARGEMENT_LIMIT_VALUE,
+                                       g_param_spec_uint("enlargement_limit_value",
+                                                         "Size increase limit of image when autofitting",
+                                                         NULL,
+                                                         100,
+                                                         999,
+                                                         500,
+                                                         G_PARAM_READABLE | G_PARAM_WRITABLE));
+
 
        signals[SIGNAL_ZOOM] =
                g_signal_new("zoom",
@@ -381,12 +411,12 @@ static void pixbuf_renderer_class_init(PixbufRendererClass *class)
 
 static RendererFuncs *pr_backend_renderer_new(PixbufRenderer *pr)
 {
-       if (options->image.use_clutter_renderer)
+       if (options->image.use_clutter_renderer && !options->disable_gpu)
                {
 #ifdef HAVE_CLUTTER
                return renderer_clutter_new(pr);
 #else
-               DEBUG_0("Geeqie is built without clutter renderer support");
+               log_printf("Warning: Geeqie is built without clutter renderer support");
 #endif
                }
        return renderer_tiles_new(pr);
@@ -426,6 +456,10 @@ static void pixbuf_renderer_init(PixbufRenderer *pr)
 
        pr->stereo_mode = PR_STEREO_NONE;
 
+       pr->color.red =0;
+       pr->color.green =0;
+       pr->color.blue =0;
+
        pr->renderer = pr_backend_renderer_new(pr);
 
        pr->renderer2 = NULL;
@@ -517,6 +551,9 @@ static void pixbuf_renderer_set_property(GObject *object, guint prop_id,
                case PROP_AUTOFIT_LIMIT_VALUE:
                        pr->autofit_limit_size = g_value_get_uint(value);
                        break;
+               case PROP_ENLARGEMENT_LIMIT_VALUE:
+                       pr->enlargement_limit_size = g_value_get_uint(value);
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
                        break;
@@ -580,6 +617,9 @@ static void pixbuf_renderer_get_property(GObject *object, guint prop_id,
                case PROP_AUTOFIT_LIMIT_VALUE:
                        g_value_set_uint(value, pr->autofit_limit_size);
                        break;
+               case PROP_ENLARGEMENT_LIMIT_VALUE:
+                       g_value_set_uint(value, pr->enlargement_limit_size);
+                       break;
                default:
                        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
                        break;
@@ -890,28 +930,20 @@ static void pr_scroller_stop(PixbufRenderer *pr)
 
 void pixbuf_renderer_set_color(PixbufRenderer *pr, GdkColor *color)
 {
-       GtkStyle *style;
-       GtkWidget *widget;
-
        g_return_if_fail(IS_PIXBUF_RENDERER(pr));
 
-       widget = GTK_WIDGET(pr);
-
-       if (color) {
-               GdkColor *slot;
-
-               style = gtk_style_copy(gtk_widget_get_style(widget));
-               slot = &style->bg[GTK_STATE_NORMAL];
-
-               slot->red = color->red;
-               slot->green = color->green;
-               slot->blue = color->blue;
+       if (color)
+               {
+               pr->color.red = color->red;
+               pr->color.green = color->green;
+               pr->color.blue = color->blue;
+               }
+       else
+               {
+               pr->color.red = 0;
+               pr->color.green = 0;
+               pr->color.blue = 0;
                }
-       else {
-               style = gtk_style_copy(gtk_widget_get_default_style());
-       }
-
-       gtk_widget_set_style(widget, style);
 
        pr->renderer->update_viewport(pr->renderer);
        if (pr->renderer2) pr->renderer2->update_viewport(pr->renderer2);
@@ -1160,7 +1192,7 @@ void pixbuf_renderer_set_tiles(PixbufRenderer *pr, gint width, gint height,
                               gdouble zoom)
 {
        g_return_if_fail(IS_PIXBUF_RENDERER(pr));
-       g_return_if_fail(tile_width >= 32 && tile_width >= 32);
+       g_return_if_fail(tile_width >= 32 && tile_height >= 32);
        g_return_if_fail(width >= 32 && height > 32);
        g_return_if_fail(func_request != NULL);
 
@@ -1227,26 +1259,68 @@ static void pr_zoom_adjust_real(PixbufRenderer *pr, gdouble increment,
                        }
                }
 
-       if (increment < 0.0)
+       if (options->image.zoom_style == ZOOM_GEOMETRIC)
                {
-               if (zoom >= 1.0 && zoom + increment < 1.0)
+               if (increment < 0.0)
                        {
-                       zoom = zoom + increment - 2.0;
+                       if (zoom >= 1.0)
+                               {
+                               if (zoom / -(increment - 1.0) < 1.0)
+                                       {
+                                       zoom = 1.0 / (zoom / (increment - 1.0));
+                                       }
+                               else
+                                       {
+                                       zoom = zoom / -(increment - 1.0) ;
+                                       }
+                               }
+                       else
+                               {
+                               zoom = zoom * -(increment - 1.0);
+                               }
                        }
                else
                        {
-                       zoom = zoom + increment;
+                       if (zoom <= -1.0 )
+                               {
+                               if (zoom / (increment + 1.0) > -1.0)
+                                       {
+                                       zoom = -(1.0 / (zoom / (increment + 1.0)));
+                                       }
+                               else
+                                       {
+                                       zoom = zoom / (increment + 1.0) ;
+                                       }
+                               }
+                       else
+                               {
+                               zoom = zoom * (increment + 1.0);
+                               }
                        }
                }
        else
                {
-               if (zoom <= -1.0 && zoom + increment > -1.0)
+               if (increment < 0.0)
                        {
-                       zoom = zoom + increment + 2.0;
+                       if (zoom >= 1.0 && zoom + increment < 1.0)
+                               {
+                               zoom = zoom + increment - 2.0;
+                               }
+                       else
+                               {
+                               zoom = zoom + increment;
+                               }
                        }
                else
                        {
-                       zoom = zoom + increment;
+                       if (zoom <= -1.0 && zoom + increment > -1.0)
+                               {
+                               zoom = zoom + increment + 2.0;
+                               }
+                       else
+                               {
+                               zoom = zoom + increment;
+                               }
                        }
                }
 
@@ -1295,9 +1369,9 @@ void pr_render_complete_signal(PixbufRenderer *pr)
                }
 }
 
-static void pr_drag_signal(PixbufRenderer *pr, GdkEventButton *bevent)
+static void pr_drag_signal(PixbufRenderer *pr, GdkEventMotion *event)
 {
-       g_signal_emit(pr, signals[SIGNAL_DRAG], 0, bevent);
+       g_signal_emit(pr, signals[SIGNAL_DRAG], 0, event);
 }
 
 static void pr_update_pixel_signal(PixbufRenderer *pr)
@@ -1657,6 +1731,17 @@ static gboolean pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom,
                                scale = scale * factor;
                                }
 
+                       if (pr->zoom_expand)
+                               {
+                               gdouble factor = (gdouble)pr->enlargement_limit_size / 100;
+                               if (scale > factor)
+                                       {
+                                       w = w * factor / scale;
+                                       h = h * factor / scale;
+                                       scale = factor;
+                                       }
+                               }
+
                        if (w < 1) w = 1;
                        if (h < 1) h = 1;
                        }
@@ -1946,28 +2031,38 @@ void pixbuf_renderer_set_scroll_center(PixbufRenderer *pr, gdouble x, gdouble y)
  *-------------------------------------------------------------------
  */
 
-static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gpointer data)
+static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventMotion *event, gpointer data)
 {
        PixbufRenderer *pr;
        gint accel;
+#if GTK_CHECK_VERSION(3,0,0)
+       GdkDeviceManager *device_manager;
+       GdkDevice *device;
+#endif
 
        /* This is a hack, but work far the best, at least for single pointer systems.
         * See http://bugzilla.gnome.org/show_bug.cgi?id=587714 for more. */
        gint x, y;
-       gdk_window_get_pointer (bevent->window, &x, &y, NULL);
-       bevent->x = x;
-       bevent->y = y;
+#if GTK_CHECK_VERSION(3,0,0)
+       device_manager = gdk_display_get_device_manager(gdk_window_get_display(event->window));
+       device = gdk_device_manager_get_client_pointer(device_manager);
+       gdk_window_get_device_position(event->window, device, &x, &y, NULL);
+#else
+       gdk_window_get_pointer (event->window, &x, &y, NULL);
+#endif
+       event->x = x;
+       event->y = y;
 
        pr = PIXBUF_RENDERER(widget);
 
        if (pr->scroller_id)
                {
-               pr->scroller_xpos = bevent->x;
-               pr->scroller_ypos = bevent->y;
+               pr->scroller_xpos = event->x;
+               pr->scroller_ypos = event->y;
                }
 
-       pr->x_mouse = bevent->x;
-       pr->y_mouse = bevent->y;
+       pr->x_mouse = event->x;
+       pr->y_mouse = event->y;
        pr_update_pixel_signal(pr);
 
        if (!pr->in_drag || !gdk_pointer_is_grabbed()) return FALSE;
@@ -1981,7 +2076,7 @@ static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gp
                widget_set_cursor(widget, GDK_FLEUR);
                }
 
-       if (bevent->state & GDK_CONTROL_MASK)
+       if (event->state & GDK_CONTROL_MASK)
                {
                accel = PR_PAN_SHIFT_MULTIPLIER;
                }
@@ -1990,20 +2085,22 @@ static gboolean pr_mouse_motion_cb(GtkWidget *widget, GdkEventButton *bevent, gp
                accel = 1;
                }
 
-       /* do the scroll */
-       pixbuf_renderer_scroll(pr, (pr->drag_last_x - bevent->x) * accel,
-                              (pr->drag_last_y - bevent->y) * accel);
-
-       pr_drag_signal(pr, bevent);
+       /* do the scroll - not when drawing rectangle*/
+       if (!options->draw_rectangle)
+               {
+               pixbuf_renderer_scroll(pr, (pr->drag_last_x - event->x) * accel,
+                                       (pr->drag_last_y - event->y) * accel);
+               }
+       pr_drag_signal(pr, event);
 
-       pr->drag_last_x = bevent->x;
-       pr->drag_last_y = bevent->y;
+       pr->drag_last_x = event->x;
+       pr->drag_last_y = event->y;
 
        /* This is recommended by the GTK+ documentation, but does not work properly.
         * Use deprecated way until GTK+ gets a solution for correct motion hint handling:
         * http://bugzilla.gnome.org/show_bug.cgi?id=587714
         */
-       /* gdk_event_request_motions (bevent); */
+       /* gdk_event_request_motions (event); */
        return FALSE;
 }
 
@@ -2150,7 +2247,11 @@ static void pr_signals_connect(PixbufRenderer *pr)
  */
 
 #define COLOR_BYTES 3   /* rgb */
-static void pr_create_anaglyph_RC(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+#define RC 0            /* Red-Cyan */
+#define GM 1            /* Green-Magenta */
+#define YB 2            /* Yellow-Blue */
+
+static void pr_create_anaglyph_color(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
 {
        gint srs, drs;
        guchar *s_pix, *d_pix;
@@ -2172,14 +2273,26 @@ static void pr_create_anaglyph_RC(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, g
                dp = dpi + (i * drs);
                for (j = 0; j < w; j++)
                        {
-                       *dp = *sp; /* copy red channel */
+                       switch(mode)
+                               {
+                               case RC:
+                                       dp[0] = sp[0]; /* copy red channel */
+                                       break;
+                               case GM:
+                                       dp[1] = sp[1];
+                                       break;
+                               case YB:
+                                       dp[0] = sp[0];
+                                       dp[1] = sp[1];
+                                       break;
+                               }
                        sp += COLOR_BYTES;
                        dp += COLOR_BYTES;
                        }
                }
 }
 
-static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
 {
        gint srs, drs;
        guchar *s_pix, *d_pix;
@@ -2204,28 +2317,63 @@ static void pr_create_anaglyph_gray(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x,
                        {
                        guchar g1 = dp[0] * gc[0] + dp[1] * gc[1] + dp[2] * gc[2];
                        guchar g2 = sp[0] * gc[0] + sp[1] * gc[1] + sp[2] * gc[2];
-                       dp[0] = g2; /* red channel from sp */
-                       dp[1] = g1; /* green and blue from dp */
-                       dp[2] = g1;
+                       switch(mode)
+                               {
+                               case RC:
+                                       dp[0] = g2; /* red channel from sp */
+                                       dp[1] = g1; /* green and blue from dp */
+                                       dp[2] = g1;
+                                       break;
+                               case GM:
+                                       dp[0] = g1;
+                                       dp[1] = g2;
+                                       dp[2] = g1;
+                                       break;
+                               case YB:
+                                       dp[0] = g2;
+                                       dp[1] = g2;
+                                       dp[2] = g1;
+                                       break;
+                               }
                        sp += COLOR_BYTES;
                        dp += COLOR_BYTES;
                        }
                }
 }
 
-const double pr_dubois_matrix[3][6] = {
-       { 0.456,  0.500,  0.176, -0.043, -0.088, -0.002},
-       {-0.040, -0.038, -0.016,  0.378,  0.734, -0.018},
-       {-0.015, -0.021, -0.005, -0.072, -0.113,  1.226}
-       };
-
-static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
+static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h, guint mode)
 {
        gint srs, drs;
        guchar *s_pix, *d_pix;
        guchar *sp, *dp;
        guchar *spi, *dpi;
        gint i, j, k;
+       double pr_dubois_matrix[3][6];
+       static const double pr_dubois_matrix_RC[3][6] = {
+               { 0.456,  0.500,  0.176, -0.043, -0.088, -0.002},
+               {-0.040, -0.038, -0.016,  0.378,  0.734, -0.018},
+               {-0.015, -0.021, -0.005, -0.072, -0.113,  1.226}};
+       static const double pr_dubois_matrix_GM[3][6] = {
+               {-0.062, -0.158, -0.039,  0.529,  0.705,  0.024},
+               { 0.284,  0.668,  0.143, -0.016, -0.015, -0.065},
+               {-0.015, -0.027,  0.021,  0.009,  0.075,  0.937}};
+       static const double pr_dubois_matrix_YB[3][6] = {
+               { 1.000, -0.193,  0.282, -0.015, -0.116, -0.016},
+               {-0.024,  0.855,  0.064,  0.006,  0.058, -0.016},
+               {-0.036, -0.163,  0.021,  0.089,  0.174,  0.858}};
+
+       switch(mode)
+               {
+               case RC:
+                       memcpy(pr_dubois_matrix, pr_dubois_matrix_RC, sizeof pr_dubois_matrix);
+                       break;
+               case GM:
+                       memcpy(pr_dubois_matrix, pr_dubois_matrix_GM, sizeof pr_dubois_matrix);
+                       break;
+               case YB:
+                       memcpy(pr_dubois_matrix, pr_dubois_matrix_YB, sizeof pr_dubois_matrix);
+                       break;
+               }
 
        srs = gdk_pixbuf_get_rowstride(right);
        s_pix = gdk_pixbuf_get_pixels(right);
@@ -2261,11 +2409,23 @@ static void pr_create_anaglyph_dubois(GdkPixbuf *pixbuf, GdkPixbuf *right, gint
 void pr_create_anaglyph(guint mode, GdkPixbuf *pixbuf, GdkPixbuf *right, gint x, gint y, gint w, gint h)
 {
        if (mode & PR_STEREO_ANAGLYPH_RC)
-               pr_create_anaglyph_RC(pixbuf, right, x, y, w, h);
-       else if (mode & PR_STEREO_ANAGLYPH_GRAY)
-               pr_create_anaglyph_gray(pixbuf, right, x, y, w, h);
-       else if (mode & PR_STEREO_ANAGLYPH_DB)
-               pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h);
+               pr_create_anaglyph_color(pixbuf, right, x, y, w, h, RC);
+       else if (mode & PR_STEREO_ANAGLYPH_GM)
+               pr_create_anaglyph_color(pixbuf, right, x, y, w, h, GM);
+       else if (mode & PR_STEREO_ANAGLYPH_YB)
+               pr_create_anaglyph_color(pixbuf, right, x, y, w, h, YB);
+       else if (mode & PR_STEREO_ANAGLYPH_GRAY_RC)
+               pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, RC);
+       else if (mode & PR_STEREO_ANAGLYPH_GRAY_GM)
+               pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, GM);
+       else if (mode & PR_STEREO_ANAGLYPH_GRAY_YB)
+               pr_create_anaglyph_gray(pixbuf, right, x, y, w, h, YB);
+       else if (mode & PR_STEREO_ANAGLYPH_DB_RC)
+               pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, RC);
+       else if (mode & PR_STEREO_ANAGLYPH_DB_GM)
+               pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, GM);
+       else if (mode & PR_STEREO_ANAGLYPH_DB_YB)
+               pr_create_anaglyph_dubois(pixbuf, right, x, y, w, h, YB);
 }
 
 /*
@@ -2697,6 +2857,7 @@ gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint
        gint p_alpha, prs;
        guchar *p_pix, *pp;
        gint map_x, map_y, map_w, map_h;
+       size_t xoff, yoff;
 
        g_return_val_if_fail(IS_PIXBUF_RENDERER(pr), FALSE);
        g_return_val_if_fail(r_mouse != NULL && g_mouse != NULL && b_mouse != NULL, FALSE);
@@ -2725,7 +2886,9 @@ gboolean pixbuf_renderer_get_pixel_colors(PixbufRenderer *pr, gint x_pixel, gint
        prs = gdk_pixbuf_get_rowstride(pb);
        p_pix = gdk_pixbuf_get_pixels(pb);
 
-       pp = p_pix + map_y * prs + (map_x * (p_alpha ? 4 : 3));
+       xoff = (size_t)map_x * (p_alpha ? 4 : 3);
+       yoff = (size_t)map_y * prs;
+       pp = p_pix + yoff + xoff;
        *r_mouse = *pp;
        pp++;
        *g_mouse = *pp;
@@ -2754,10 +2917,15 @@ gboolean pixbuf_renderer_get_mouse_position(PixbufRenderer *pr, gint *x_pixel_re
        x_pixel_clamped = CLAMP(x_pixel, 0, pr->image_width - 1);
        y_pixel_clamped = CLAMP(y_pixel, 0, pr->image_height - 1);
 
-       if(x_pixel != x_pixel_clamped || y_pixel != y_pixel_clamped)
+       if (x_pixel != x_pixel_clamped)
                {
                /* mouse is not on pr */
-               x_pixel = y_pixel = -1;
+               x_pixel = -1;
+               }
+       if (y_pixel != y_pixel_clamped)
+               {
+               /* mouse is not on pr */
+               y_pixel = -1;
                }
 
        *x_pixel_return = x_pixel;
@@ -2846,7 +3014,7 @@ gboolean pixbuf_renderer_get_virtual_rect(PixbufRenderer *pr, GdkRectangle *rect
 void pixbuf_renderer_set_size_early(PixbufRenderer *pr, guint width, guint height)
 {
 #if 0
-       /* FIXME: this function does not consider the image orientation,
+       /** @FIXME this function does not consider the image orientation,
        so it probably only breaks something */
        gdouble zoom;
        gint w, h;
@@ -2865,4 +3033,13 @@ void pixbuf_renderer_set_size_early(PixbufRenderer *pr, guint width, guint heigh
 #endif
 }
 
+void pixbuf_renderer_set_ignore_alpha(PixbufRenderer *pr, gint ignore_alpha)
+{
+   g_return_if_fail(IS_PIXBUF_RENDERER(pr));
+
+   pr->ignore_alpha = ignore_alpha;
+   pr_pixbuf_size_sync(pr);
+   pr_zoom_sync(pr, pr->zoom, PR_ZOOM_FORCE, 0, 0);
+}
+
 /* vim: set shiftwidth=8 softtabstop=0 cindent cinoptions={1s: */