# Bazaar merge directive format 2 (Bazaar 0.90)
# revision_id: geoffrey.antos@gmail.com-20080731010416-\
#   074dgm6xx0qzxvko
# target_branch: ../upstream/
# testament_sha1: 758d5c512afa07b22cd8f7f31b77f8115a366015
# timestamp: 2008-07-30 21:08:43 -0400
# source_branch: .
# base_revision_id: geoffrey.antos@gmail.com-20080710203800-\
#   t4rvdfz8z76gtz2v
# 
# Begin patch
=== modified file 'ChangeLog'
--- ChangeLog	2008-07-10 20:38:00 +0000
+++ ChangeLog	2008-07-31 01:04:16 +0000
@@ -1,3 +1,26 @@
+2008-07-30  Geoffrey Antos <dynamotwain@aim.com>
+	* libgthumb/gth-nav-window.c: (size_changed_cb):
+		Remove assumptions about GtkAdjustment->lower being 0
+
+	* libgthumb/nav-window.c: (nav_window_events), (update_view):
+	* libgthumb/image-viewer-image.c, libgthumb/image-viewer-image.h:
+		Adjust [xy]-offset scales such that an offset of (0,0)
+		will draw the image in the center of the widget even if
+		widget is bigger or smaller than the image itself
+		(Important when there are two images with different sizes
+		 on the screen at once).
+
+	* libgthumb/image-viewer-image.c, libgthumb/image-viewer-image.h:
+		Have image paint itself to a cairo buffer to be used
+		by a transition or directly by the widget.
+
+		Removed the "repainted" signal as it is no longer needed
+		as scrolling triggers an "exposed" event that takes care
+		of it for gth-fullscreen.
+
+	* src/gth-fullscreeen.c:
+		No longer connect to the "repainted" event.
+
 2008-07-10  Geoffrey Antos <dynamotwain@aim.com>
 	* libgthumb/image-viewer.c:
 	* libgthumb/image-viewer-image.c:

=== modified file 'libgthumb/gth-nav-window.c'
--- libgthumb/gth-nav-window.c	2006-04-08 19:49:41 +0000
+++ libgthumb/gth-nav-window.c	2008-07-31 01:04:16 +0000
@@ -113,8 +113,8 @@
 	g_return_val_if_fail (hadj != NULL, FALSE);
 	g_return_val_if_fail (vadj != NULL, FALSE);
 
-	hide_vscr = (vadj->upper <= vadj->page_size);
-	hide_hscr = (hadj->upper <= hadj->page_size);
+	hide_vscr = (vadj->upper - vadj->lower <= vadj->page_size + 1e-6);
+	hide_hscr = (hadj->upper - hadj->lower <= hadj->page_size + 1e-6);
 
 	if (hide_vscr && hide_hscr) {
 		gtk_widget_hide (priv->viewer_vscr); 

=== modified file 'libgthumb/image-viewer-image.c'
--- libgthumb/image-viewer-image.c	2008-07-10 20:33:44 +0000
+++ libgthumb/image-viewer-image.c	2008-07-31 01:04:16 +0000
@@ -25,6 +25,8 @@
 #include "image-viewer.h"
 #include "image-viewer-image.h"
 
+#define FLOAT_EQUAL(a,b) (fabs ((a) - (b)) < 1e-6)
+
 #define MINIMUM_DELAY   10    /* When an animation frame has a 0 milli seconds
 			       * delay use this delay instead. */
 
@@ -57,6 +59,8 @@
 
 	gdouble                x_offset;           /* Scroll offsets. */
 	gdouble                y_offset;
+
+	cairo_surface_t       *buffer;
 };
 
 enum {
@@ -64,6 +68,8 @@
 	LAST_SIGNAL
 };
 
+cairo_surface_t*               pixbuf_to_surface (GdkPixbuf *pixbuf);
+
 static guint image_viewer_image_signals[LAST_SIGNAL] = { 0 };
 
 G_DEFINE_TYPE(ImageViewerImage, image_viewer_image, G_TYPE_OBJECT)
@@ -99,7 +105,6 @@
 image_viewer_image_init (ImageViewerImage *self)
 {
 	ImageViewerImagePrivate  *priv = IMAGE_VIEWER_IMAGE_GET_PRIVATE (self);
-	/* do stuff */
 
 	priv->viewer = NULL;
 	priv->is_animation = FALSE;
@@ -114,10 +119,12 @@
 	priv->static_pixbuf = NULL;
 
 	priv->zoom_level = 1.0;
-	priv->fit = GTH_FIT_SIZE_IF_LARGER;
+	priv->fit = GTH_FIT_NONE;
 
 	priv->x_offset = 0;
 	priv->y_offset = 0;
+
+	priv->buffer = NULL;
 }
 
 static void
@@ -159,6 +166,11 @@
 		priv->file = NULL;
 	}
 
+	if (priv->buffer != NULL) {
+		cairo_surface_destroy (priv->buffer);
+		priv->buffer = NULL;
+	}
+
         /* Chain up */
 	G_OBJECT_CLASS (image_viewer_image_parent_class)->finalize (object);
 }
@@ -187,6 +199,14 @@
 	GdkPixbufAnimationIter  *iter = priv->iter;
 	priv->anim_pixbuf = gdk_pixbuf_animation_iter_get_pixbuf (iter);
 	priv->frame_delay = gdk_pixbuf_animation_iter_get_delay_time (iter);
+
+	if (priv->buffer != NULL)
+	{
+		cairo_surface_destroy (priv->buffer);
+	}
+
+	priv->buffer = pixbuf_to_surface (priv->anim_pixbuf);
+
 	gtk_widget_queue_draw (GTK_WIDGET (priv->viewer));
 }
 
@@ -229,33 +249,37 @@
 	return FALSE;
 }
 
-
 static void
 clamp_offsets (ImageViewerImage *image)
 {
 	ImageViewerImagePrivate *priv = IMAGE_VIEWER_IMAGE_GET_PRIVATE (image);
+	gint                     border, border2;
 	gint                     gdk_width, gdk_height;
-	gint                     width, height, border;
-
-	border = image_viewer_is_frame_visible (priv->viewer) ?
-		 FRAME_BORDER2 : 0;
-
-	gdk_width = GTK_WIDGET (priv->viewer)->allocation.width - border;
-	gdk_height = GTK_WIDGET (priv->viewer)->allocation.height - border;
+	gdouble                  width, height;
+
+	if (image_viewer_is_frame_visible (priv->viewer)) {
+		border  = FRAME_BORDER;
+		border2 = FRAME_BORDER2;
+	} else {
+		border = border2 = 0;
+	}
+
+	gdk_width = GTK_WIDGET (priv->viewer)->allocation.width - border2;
+	gdk_height = GTK_WIDGET (priv->viewer)->allocation.height - border2;
 
 	image_viewer_image_get_zoomed_size (image, &width, &height);
 
 	if (width > gdk_width)
 		priv->x_offset = CLAMP (priv->x_offset,
-				0,
-				width - gdk_width);
+				floor (-width/2 - border),
+				floor ( width/2 + border));
 	else
 		priv->x_offset = 0;
 
 	if (height > gdk_height)
 		priv->y_offset = CLAMP (priv->y_offset,
-				0,
-				height - gdk_height);
+				floor (-height/2 - border),
+				floor ( height/2 + border));
 	else
 		priv->y_offset = 0;
 }
@@ -305,11 +329,10 @@
 {
 	ImageViewerImagePrivate *priv = IMAGE_VIEWER_IMAGE_GET_PRIVATE (image);
 	GtkWidget               *widget = GTK_WIDGET (priv->viewer);
-	GdkPixbuf               *buf;
-	gint                     gdk_width, gdk_height, border;
+	gdouble                  gdk_width, gdk_height;
+	gint                     border;
 	gdouble                  zoom_ratio;
 
-	buf = image_viewer_image_get_pixbuf (image);
 	border = image_viewer_is_frame_visible (priv->viewer) ?
 		 FRAME_BORDER2 : 0;
 
@@ -319,8 +342,8 @@
 	/* try to keep the center of the view visible. */
 
 	zoom_ratio = zoom_level / priv->zoom_level;
-	priv->x_offset = ((priv->x_offset + center_x) * zoom_ratio - gdk_width / 2);
-	priv->y_offset = ((priv->y_offset + center_y) * zoom_ratio - gdk_height / 2);
+	priv->x_offset = ((priv->x_offset - gdk_width  / 2 + center_x) * zoom_ratio);
+	priv->y_offset = ((priv->y_offset - gdk_height / 2 + center_y) * zoom_ratio);
 
 	priv->zoom_level = zoom_level;
 
@@ -400,6 +423,10 @@
 		create_first_pixbuf (image);
 		add_change_frame_timeout(image);
 	}
+	else
+	{
+		priv->buffer = pixbuf_to_surface (priv->static_pixbuf);
+	}
 
 	return image;
 }
@@ -595,8 +622,8 @@
 
 void
 image_viewer_image_get_zoomed_size (ImageViewerImage *image,
-				    gint             *width,
-				    gint             *height)
+				    gdouble          *width,
+				    gdouble          *height)
 {
 	ImageViewerImagePrivate *priv;
 	gint w, h;
@@ -608,8 +635,8 @@
 	w = image_viewer_image_get_width (image);
 	h = image_viewer_image_get_height (image);
 
-	*width  = (int) floor ((double) w * priv->zoom_level);
-	*height = (int) floor ((double) h * priv->zoom_level);
+	*width  = floor ((double) w * priv->zoom_level);
+	*height = floor ((double) h * priv->zoom_level);
 }
 
 
@@ -862,3 +889,253 @@
 	set_zoom_centered (image, get_prev_zoom (priv->zoom_level));
 }
 
+/* image_viewer_image_paint */
+
+cairo_surface_t*
+pixbuf_to_surface (GdkPixbuf *pixbuf)
+{
+	/* based on gdk_cairo_set_source_pixbuf */
+	gint    width = gdk_pixbuf_get_width (pixbuf);
+	gint    height = gdk_pixbuf_get_height (pixbuf);
+	guchar *gdk_pixels = gdk_pixbuf_get_pixels (pixbuf);
+	int     gdk_rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+	int     n_channels = gdk_pixbuf_get_n_channels (pixbuf);
+	int     cairo_stride;
+	guchar *cairo_pixels;
+	cairo_format_t format;
+	cairo_surface_t *surface;
+	static const cairo_user_data_key_t key;
+	int j;
+
+	if (n_channels == 3)
+		format = CAIRO_FORMAT_RGB24;
+	else
+		format = CAIRO_FORMAT_ARGB32;
+
+	cairo_stride = cairo_format_stride_for_width (format, width);
+	/* XXX store this buffer in the struct; reuse for multiple frames of animation? */
+	cairo_pixels = g_malloc (cairo_stride * height);
+
+	surface = cairo_image_surface_create_for_data (
+			(unsigned char *)cairo_pixels,
+			format,
+			width, height, cairo_stride);
+	cairo_surface_set_user_data (surface, &key,
+			cairo_pixels, (cairo_destroy_func_t)g_free);
+
+	for (j = height; j; j--)
+	{
+		guchar *p = gdk_pixels;
+		guchar *q = cairo_pixels;
+
+		if (n_channels == 3)
+		{
+			guchar *end = p + 3 * width;
+
+			while (p < end)
+			{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+				q[0] = p[2];
+				q[1] = p[1];
+				q[2] = p[0];
+#else	  
+				q[1] = p[0];
+				q[2] = p[1];
+				q[3] = p[2];
+#endif
+				p += 3;
+				q += 4;
+			}
+		}
+		else
+		{
+			guchar *end = p + 4 * width;
+			guint t1,t2,t3;
+
+#define MULT(d,c,a,t) G_STMT_START { t = c * a + 0x7f; d = ((t >> 8) + t) >> 8; } G_STMT_END
+
+			while (p < end)
+			{
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+				MULT(q[0], p[2], p[3], t1);
+				MULT(q[1], p[1], p[3], t2);
+				MULT(q[2], p[0], p[3], t3);
+				q[3] = p[3];
+#else	  
+				q[0] = p[3];
+				MULT(q[1], p[0], p[3], t1);
+				MULT(q[2], p[1], p[3], t2);
+				MULT(q[3], p[2], p[3], t3);
+#endif
+
+				p += 4;
+				q += 4;
+			}
+
+#undef MULT
+		}
+
+		gdk_pixels += gdk_rowstride;
+		cairo_pixels += 4 * width;
+	}
+
+	return surface;
+}
+
+
+static cairo_surface_t*
+checker_pattern (int width, int height, double color1, double color2)
+{
+	cairo_surface_t *surface;
+	cairo_t         *cr;
+
+	surface = cairo_image_surface_create (CAIRO_FORMAT_RGB24,
+					      width * 2, height *2);
+	cr = cairo_create (surface);
+
+	cairo_set_source_rgb (cr, color1, color1, color1);
+	cairo_paint (cr);
+
+	cairo_set_source_rgb (cr, color2, color2, color2);
+	cairo_rectangle (cr, 0,     0,      width, height);
+	cairo_rectangle (cr, width, height, width, height);
+	cairo_fill (cr);
+	cairo_destroy (cr);
+
+	return surface;
+}
+
+
+void
+image_viewer_image_paint (ImageViewerImage *image,
+			  cairo_t          *cr)
+{
+	ImageViewerImagePrivate *priv;
+	GdkPixbuf               *pixbuf;
+	GtkStyle                *style;
+
+	gint                     border, border2;
+	gdouble                  gdk_width, gdk_height;
+	gdouble                  src_x, src_y;
+	gdouble                  width, height;
+	GthTranspType            transp_type;
+	GthZoomQuality           zoom_quality;
+	cairo_filter_t           filter;
+	cairo_matrix_t           matrix;
+	cairo_pattern_t         *pattern;	
+
+	g_return_if_fail (image != NULL);
+
+	priv   = IMAGE_VIEWER_IMAGE_GET_PRIVATE (image);
+	pixbuf = image_viewer_image_get_pixbuf (image);
+	style  = GTK_WIDGET (priv->viewer)->style;
+
+	if (image_viewer_is_frame_visible (priv->viewer)) {
+		border  = FRAME_BORDER;
+		border2 = FRAME_BORDER2;
+	} else {
+		border = border2 = 0;
+	}
+
+	gdk_width = GTK_WIDGET (priv->viewer)->allocation.width - border2;
+	gdk_height = GTK_WIDGET (priv->viewer)->allocation.height - border2;
+
+	image_viewer_image_get_zoomed_size (image, &width, &height);
+
+	transp_type = image_viewer_get_transp_type (priv->viewer);
+
+	zoom_quality = image_viewer_get_zoom_quality (priv->viewer);
+	if (zoom_quality == GTH_ZOOM_QUALITY_LOW)
+		filter = CAIRO_FILTER_FAST;
+	else
+		filter = CAIRO_FILTER_GOOD;
+/*		filter = CAIRO_FILTER_BEST;*/
+
+	if (FLOAT_EQUAL (priv->zoom_level, 1.0))
+		filter = CAIRO_FILTER_FAST;
+
+	src_x = floor ((gdk_width  - width)  / 2 - priv->x_offset + border);
+	src_y = floor ((gdk_height - height) / 2 - priv->y_offset + border);
+
+	cairo_save (cr);
+
+	if (image_viewer_image_get_has_alpha (image) &&
+			transp_type != GTH_TRANSP_TYPE_NONE) {
+		cairo_surface_t *checker;
+		int              check_size;
+		GthCheckType     check_type;
+		double           color1, color2;
+
+		switch (transp_type) {
+		case GTH_TRANSP_TYPE_NONE:
+			g_assert_not_reached ();
+			break;
+
+		case GTH_TRANSP_TYPE_BLACK:
+			color1 = color2 = 0;
+			break;
+
+		case GTH_TRANSP_TYPE_WHITE:
+			color1 = color2 = 1;
+			break;
+
+		case GTH_TRANSP_TYPE_CHECKED:
+			check_type = image_viewer_get_check_type (priv->viewer);
+			switch (check_type) {
+			case GTH_CHECK_TYPE_DARK:
+				color1 = 0;
+				color2 = 0.2;
+				break;
+
+			case GTH_CHECK_TYPE_MIDTONE:
+				color1 = 0.4;
+				color2 = 0.6;
+				break;
+
+			case GTH_CHECK_TYPE_LIGHT:
+				color1 = 0.8;
+				color2 = 1;
+				break;
+			}
+			break;
+		}
+
+		check_size = (int) image_viewer_get_check_size (priv->viewer);
+
+		checker = checker_pattern (check_size, check_size, color1, color2);
+		cairo_set_source_surface (cr, checker, -src_x, -src_y);
+		cairo_pattern_set_extend (cairo_get_source (cr), CAIRO_EXTEND_REPEAT);
+		cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_NEAREST);
+		cairo_rectangle (cr, src_x, src_y, width, height);
+		cairo_fill (cr);
+		cairo_surface_destroy (checker);
+	}
+
+	pattern = cairo_pattern_create_for_surface (priv->buffer);
+	cairo_matrix_init_scale (&matrix, 1/priv->zoom_level, 1/priv->zoom_level);
+	cairo_matrix_translate (&matrix, -src_x, -src_y);
+	cairo_pattern_set_matrix (pattern, &matrix);
+	cairo_pattern_set_filter (pattern, filter);
+
+	cairo_set_source (cr, pattern);
+	cairo_pattern_destroy(pattern);
+	cairo_paint (cr);
+
+	if(border != 0) {
+		cairo_set_antialias (cr, CAIRO_ANTIALIAS_NONE);
+		cairo_set_line_width (cr, 1);
+		gdk_cairo_set_source_color (cr, &style->dark[GTK_STATE_NORMAL]);
+		cairo_move_to (cr, src_x - border, src_y + height + border);
+		cairo_line_to (cr, src_x - border, src_y - border);
+		cairo_line_to (cr, src_x + width + border, src_y - border);
+		cairo_stroke (cr);
+		gdk_cairo_set_source_color (cr, &style->light[GTK_STATE_NORMAL]);
+		cairo_move_to (cr, src_x + width, src_y);
+		cairo_line_to (cr, src_x + width, src_y + height);
+		cairo_line_to (cr, src_x, src_y + height);
+		cairo_stroke (cr);
+	}
+
+	cairo_restore (cr);
+
+}

=== modified file 'libgthumb/image-viewer-image.h'
--- libgthumb/image-viewer-image.h	2008-07-10 20:33:44 +0000
+++ libgthumb/image-viewer-image.h	2008-07-31 01:04:16 +0000
@@ -74,8 +74,11 @@
 gint              image_viewer_image_get_y_offset             (ImageViewerImage *image);
 gdouble           image_viewer_image_get_zoom_level           (ImageViewerImage *image);
 void              image_viewer_image_get_zoomed_size          (ImageViewerImage *image,
-							       gint             *width,
-							       gint             *height);
+							       gdouble          *width,
+							       gdouble          *height);
+
+void              image_viewer_image_paint                    (ImageViewerImage *image,
+							       cairo_t          *cr);
 
 void              image_viewer_image_scroll_relative          (ImageViewerImage *image,
 							       gdouble           delta_x,

=== modified file 'libgthumb/image-viewer.c'
--- libgthumb/image-viewer.c	2008-07-10 20:33:44 +0000
+++ libgthumb/image-viewer.c	2008-07-31 01:04:16 +0000
@@ -52,7 +52,7 @@
 			       * smaller than this value. */
 #define STEP_INCREMENT  20.0  /* Scroll increment. */
 
-#define FLOAT_EQUAL(a,b) (fabs (a - b) < 1e-6)
+#define FLOAT_EQUAL(a,b) (fabs ((a) - (b)) < 1e-6)
 
 typedef struct _ImageViewerPrivate ImageViewerPrivate;
 
@@ -72,8 +72,6 @@
 	GthTranspType    transp_type;
 	GthCheckType     check_type;
 	gint             check_size;
-	guint32          check_color1;
-	guint32          check_color2;
 
 	GdkCursor       *cursor;
 	GdkCursor       *cursor_void;
@@ -92,12 +90,6 @@
 	gint             drag_realx;
 	gint             drag_realy;
 
-	GdkPixbuf       *area_pixbuf;
-	gint             area_max_width;
-	gint             area_max_height;
-        int              area_bps;
-	GdkColorspace    area_color_space;
-
 	GtkAdjustment   *vadj, *hadj;
 
 	gboolean         black_bg;
@@ -105,9 +97,6 @@
 	gboolean         skip_zoom_change;
 	gboolean         skip_size_change;
 
-	gboolean         next_scroll_repaint; /* used in fullscreen mode to
-					       * delete the comment before
-					       * scrolling. */
 	gboolean         reset_scrollbars;	
 };
 
@@ -122,7 +111,6 @@
 	SET_ZOOM,
 	SET_FIT_MODE,
 	ZOOM_CHANGED,
-	REPAINTED,
 	MOUSE_WHEEL_SCROLL,
 	SCROLL,
 	LAST_SIGNAL
@@ -161,8 +149,6 @@
 					       GdkEventFocus    *event);
 static gint     image_viewer_scroll_event     (GtkWidget        *widget,
 					       GdkEventScroll   *event);
-static void     image_viewer_style_set        (GtkWidget        *widget,
-					       GtkStyle         *previous_style);
 static void     scroll_relative               (ImageViewer      *viewer,
 					       gdouble           delta_x,
 					       gdouble           delta_y);
@@ -295,15 +281,6 @@
 			      g_cclosure_marshal_VOID__VOID,
 			      G_TYPE_NONE,
 			      0);
-	image_viewer_signals[REPAINTED] =
-		g_signal_new ("repainted",
-			      G_TYPE_FROM_CLASS (klass),
-			      G_SIGNAL_RUN_LAST,
-			      G_STRUCT_OFFSET (ImageViewerClass, repainted),
-			      NULL, NULL,
-			      g_cclosure_marshal_VOID__VOID,
-			      G_TYPE_NONE,
-			      0);
         image_viewer_signals[MOUSE_WHEEL_SCROLL] =
 		g_signal_new ("mouse_wheel_scroll",
 			      G_TYPE_FROM_CLASS (klass),
@@ -349,7 +326,6 @@
 	widget_class->motion_notify_event = image_viewer_motion_notify;
 
 	widget_class->scroll_event = image_viewer_scroll_event;
-	widget_class->style_set    = image_viewer_style_set;
 
 	klass->clicked        = NULL;
 	klass->image_loaded   = NULL;
@@ -478,9 +454,9 @@
 	gdouble              x_ofs, y_ofs;
 
 	g_return_val_if_fail (priv->image != NULL, FALSE);
-	
-	x_ofs = GTK_ADJUSTMENT (adj)->value
-		- image_viewer_image_get_x_offset (priv->image);
+
+	x_ofs = floor (adj->value + adj->page_size / 2) -
+		image_viewer_image_get_x_offset (priv->image);
 	y_ofs = 0;
 	scroll_relative_no_scrollbar (viewer, x_ofs, y_ofs);
 
@@ -494,12 +470,12 @@
 {
 	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 	gdouble              x_ofs, y_ofs;
+	
+	g_return_val_if_fail (priv->image != NULL, FALSE);
 
-	g_return_val_if_fail (priv->image != NULL, FALSE);
-	
 	x_ofs = 0;
-	y_ofs = GTK_ADJUSTMENT (adj)->value
-		- image_viewer_image_get_y_offset (priv->image);
+	y_ofs = floor (adj->value + adj->page_size / 2) -
+		image_viewer_image_get_y_offset (priv->image);
 	scroll_relative_no_scrollbar (viewer, x_ofs, y_ofs);
 
 	return FALSE;
@@ -512,14 +488,12 @@
 	ImageViewerPrivate  *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
 	GTK_WIDGET_SET_FLAGS (viewer, GTK_CAN_FOCUS);
-	GTK_WIDGET_UNSET_FLAGS (viewer, GTK_DOUBLE_BUFFERED);
+	/*GTK_WIDGET_UNSET_FLAGS (viewer, GTK_DOUBLE_BUFFERED);*/
 
 	/* Initialize data. */
 
 	priv->check_type = GTH_CHECK_TYPE_MIDTONE;
 	priv->check_size = GTH_CHECK_SIZE_LARGE;
-	priv->check_color1 = COLOR_GRAY_66;
-	priv->check_color2 = COLOR_GRAY_99;
 
 	priv->rendering = FALSE;
 	priv->cursor_visible = TRUE;
@@ -546,7 +520,6 @@
 
 	priv->skip_zoom_change = FALSE;
 	priv->skip_size_change = FALSE;
-	priv->next_scroll_repaint = FALSE;
 
 	priv->dragging = FALSE;
 	priv->double_click = FALSE;
@@ -554,12 +527,6 @@
 
 	priv->black_bg = FALSE;
 
-	priv->area_pixbuf = NULL;
-	priv->area_max_width = 0;
-	priv->area_max_height = 0;
-	priv->area_bps = 0;
-	priv->area_color_space = GDK_COLORSPACE_RGB;
-
 	priv->cursor = NULL;
 	priv->cursor_void = NULL;
 
@@ -586,112 +553,14 @@
 }
 
 
-static void
-paint (ImageViewer *viewer,
-       gint         src_x,
-       gint         src_y,
-       gint         dest_x,
-       gint         dest_y,
-       gint         width,
-       gint         height,
-       gint         interp_type)
-{
-	ImageViewerPrivate *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
-	GdkPixbuf          *pixbuf;
-	double              zoom_level;
-	int                 bits_per_sample;
-	GdkColorspace       color_space;
-
-	pixbuf = image_viewer_get_current_pixbuf (viewer);
-	zoom_level = image_viewer_image_get_zoom_level (priv->image);
-
-	color_space = gdk_pixbuf_get_colorspace (pixbuf);
-	bits_per_sample = gdk_pixbuf_get_bits_per_sample (pixbuf);
-
-	if ((priv->area_pixbuf == NULL)
-	    || (priv->area_max_width < width)
-	    || (priv->area_max_height < height)
-	    || (priv->area_bps != bits_per_sample)
-	    || (priv->area_color_space != color_space)) {
-		if (priv->area_pixbuf != NULL)
-			g_object_unref (priv->area_pixbuf);
-		priv->area_pixbuf = gdk_pixbuf_new (color_space,
-						      FALSE,
-						      bits_per_sample,
-						      width,
-						      height);
-		g_return_if_fail (priv->area_pixbuf != NULL);
-
-		priv->area_max_width = width;
-		priv->area_max_height = height;
-		priv->area_color_space = color_space;
-		priv->area_bps = bits_per_sample;
-	}
-
-	if (gdk_pixbuf_get_has_alpha (pixbuf))
-		gdk_pixbuf_composite_color (pixbuf,
-					    priv->area_pixbuf,
-					    0, 0,
-					    width, height,
-					    (double) -src_x,
-					    (double) -src_y,
-					    zoom_level,
-					    zoom_level,
-					    interp_type,
-					    255,
-					    src_x, src_y,
-					    priv->check_size,
-					    priv->check_color1,
-					    priv->check_color2);
-	else {
-		gdk_pixbuf_scale (pixbuf,
-				  priv->area_pixbuf,
-				  0, 0,
-				  width, height,
-				  (double) -src_x,
-				  (double) -src_y,
-				  zoom_level,
-				  zoom_level,
-				  interp_type);
-	}
-
-	gdk_draw_rgb_image_dithalign (GTK_WIDGET (viewer)->window,
-				      GTK_WIDGET (viewer)->style->black_gc,
-				      dest_x, dest_y,
-				      width, height,
-				      GDK_RGB_DITHER_MAX,
-				      gdk_pixbuf_get_pixels (priv->area_pixbuf),
-				      gdk_pixbuf_get_rowstride (priv->area_pixbuf),
-				      dest_x, dest_y);
-
-#if 0
-	gdk_draw_rectangle (GTK_WIDGET (viewer)->window,
-			    GTK_WIDGET (viewer)->style->black_gc,
-			    FALSE,
-			    dest_x, dest_y,
-			    width, height);
-#endif
-}
-
-
 static gint
 image_viewer_expose (GtkWidget      *widget,
 		     GdkEventExpose *event)
 {
 	ImageViewer        *viewer;
 	ImageViewerPrivate *priv;
-	gdouble              src_x, src_y;    /* Start to draw the image from this
-					* point. */
-	int           pixbuf_width;    /* Zoomed size of the image. */
-	int           pixbuf_height;
-	GdkRectangle  image_area;      /* Inside this rectangle there is the
-					* visible part of the image. */
-	GdkRectangle  paint_area;      /* The intersection between image_area
-					* and event->area. */
-	int           gdk_width;
-	int           gdk_height;
-	int           alloc_width;
-	int           alloc_height;
+	int                 gdk_width,   gdk_height;
+	int                 alloc_width, alloc_height;
 
 	viewer = IMAGE_VIEWER (widget);
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
@@ -701,187 +570,26 @@
 
 	priv->rendering = TRUE;
 
-	if (priv->image != NULL) {
-		image_viewer_image_get_zoomed_size (priv->image,
-						    &pixbuf_width,
-						    &pixbuf_height);
-		image_viewer_image_get_scroll_offsets (priv->image,
-						       &src_x,
-						       &src_y);
-	} else {
-		pixbuf_width = pixbuf_height = 0;
-		src_x = src_y = 0;
-	}
-	
 	alloc_width  = widget->allocation.width;
 	alloc_height = widget->allocation.height;
 	gdk_width    = alloc_width - priv->frame_border2;
 	gdk_height   = alloc_height - priv->frame_border2;
 
-	image_area.x      = MAX (priv->frame_border, (gdk_width - pixbuf_width) / 2);
-	image_area.y      = MAX (priv->frame_border, (gdk_height - pixbuf_height) / 2);
-	image_area.width  = MIN (pixbuf_width, gdk_width);
-	image_area.height = MIN (pixbuf_height, gdk_height);
-
-	/* Draw the background. */
-
-	if ((image_area.x > priv->frame_border)
-	    || (image_area.y > priv->frame_border)
-	    || (image_area.width < gdk_width)
-	    || (image_area.height < gdk_height)) {
-		int    rx, ry, rw, rh;
-		GdkGC *gc;
-
-		if (priv->black_bg)
-			gc = widget->style->black_gc;
-		else
-			gc = widget->style->bg_gc[GTK_STATE_NORMAL];
-
-		if (priv->image == NULL) {
-			gdk_draw_rectangle (widget->window,
-					    gc,
-					    TRUE,
-					    0, 0,
-					    alloc_width, alloc_height);
-
-		} else {
-			/* If an image is present draw in four phases to avoid
-			 * flickering. */
-
-			/* Top rectangle. */
-			rx = 0;
-			ry = 0;
-			rw = alloc_width;
-			rh = image_area.y;
-			if ((rw > 0) && (rh > 0))
-				gdk_draw_rectangle (widget->window,
-						    gc,
-						    TRUE,
-						    rx, ry,
-						    rw, rh);
-
-			/* Bottom rectangle. */
-			rx = 0;
-			ry = image_area.y + image_area.height;
-			rw = alloc_width;
-			rh = alloc_height - image_area.y - image_area.height;
-			if ((rw > 0) && (rh > 0))
-				gdk_draw_rectangle (widget->window,
-						    gc,
-						    TRUE,
-						    rx, ry,
-						    rw, rh);
-
-			/* Left rectangle. */
-			rx = 0;
-			ry = image_area.y - 1;
-			rw = image_area.x;
-			rh = image_area.height + 2;
-			if ((rw > 0) && (rh > 0))
-				gdk_draw_rectangle (widget->window,
-						    gc,
-						    TRUE,
-						    rx, ry,
-						    rw, rh);
-
-			/* Right rectangle. */
-			rx = image_area.x + image_area.width;
-			ry = image_area.y - 1;
-			rw = alloc_width - image_area.x - image_area.width;
-			rh = image_area.height + 2;
-			if ((rw > 0) && (rh > 0))
-				gdk_draw_rectangle (widget->window,
-						    gc,
-						    TRUE,
-						    rx, ry,
-						    rw, rh);
-		}
-	}
-
-	/* Draw the frame. */
-
-	if ((priv->frame_border > 0) && (priv->image != NULL)) {
-		int    x1, y1, x2, y2;
-		GdkGC *gc;
-
-		if (priv->black_bg)
-			gc = widget->style->black_gc;
-		else
-			gc = widget->style->light_gc[GTK_STATE_NORMAL];
-			/*gc = widget->style->dark_gc[GTK_STATE_NORMAL];*/
-
-		x1 = image_area.x + image_area.width;
-		y1 = image_area.y - 1;
-		x2 = image_area.x + image_area.width;
-		y2 = image_area.y + image_area.height;
-		gdk_draw_line (widget->window,
-			       gc,
-			       x1, y1,
-			       x2, y2);
-
-		x1 = image_area.x - 1;
-		y1 = image_area.y + image_area.height;
-		x2 = image_area.x + image_area.width;
-		y2 = image_area.y + image_area.height;
-		gdk_draw_line (widget->window,
-			       gc,
-			       x1, y1,
-			       x2, y2);
-
-		if (priv->black_bg)
-			gc = widget->style->black_gc;
-		else
-			gc = widget->style->dark_gc[GTK_STATE_NORMAL];
-
-		x1 = image_area.x - 1;
-		y1 = image_area.y - 1;
-		x2 = image_area.x - 1;
-		y2 = image_area.y + image_area.height;
-		gdk_draw_line (widget->window,
-			       gc,
-			       x1, y1,
-			       x2, y2);
-
-		x1 = image_area.x - 1;
-		y1 = image_area.y - 1;
-		x2 = image_area.x + image_area.width;
-		y2 = image_area.y - 1;
-		gdk_draw_line (widget->window,
-			       gc,
-			       x1, y1,
-			       x2, y2);
-	}
-
-	if ((priv->image != NULL)
-	    && gdk_rectangle_intersect (&event->area,
-					&image_area,
-					&paint_area)) {
-		int interp_type;
-
-		if (priv->zoom_quality == GTH_ZOOM_QUALITY_LOW)
-			interp_type = GDK_INTERP_NEAREST;
-		else
-			interp_type = GDK_INTERP_BILINEAR;
-/*			interp_type = GDK_INTERP_TILES;*/
-/*			interp_type = GDK_INTERP_HYPER;*/
-
-		if (FLOAT_EQUAL (
-			image_viewer_image_get_zoom_level (priv->image),
-			1.0))
-			interp_type = GDK_INTERP_NEAREST;
-
-		src_x += paint_area.x - image_area.x;
-		src_y += paint_area.y - image_area.y;
-
-		paint (viewer,
-		       src_x,
-		       src_y,
-		       paint_area.x,
-		       paint_area.y,
-		       paint_area.width,
-		       paint_area.height,
-		       interp_type);
-	}
+	if (priv->image != NULL)
+	{
+		cairo_t *cr;
+		cr = gdk_cairo_create (GTK_WIDGET (viewer)->window);
+
+		/* Only actually paint the regions that need redrawn */
+		gdk_cairo_region (cr, event->region);
+		cairo_clip (cr);
+
+		/* Paint the image */
+		image_viewer_image_paint (priv->image, cr);
+
+		cairo_destroy (cr);
+	}
+
 	priv->rendering = FALSE;
 
 	/* Draw the focus. */
@@ -965,13 +673,9 @@
 			      gdouble      delta_y)
 {
 	ImageViewerPrivate *priv     = IMAGE_VIEWER_GET_PRIVATE (viewer);
-	gint                gdk_width, gdk_height;
 
 	image_viewer_image_scroll_relative (priv->image, delta_x, delta_y);
 
-	gdk_width  = GTK_WIDGET (viewer)->allocation.width - priv->frame_border2;
-	gdk_height = GTK_WIDGET (viewer)->allocation.height - priv->frame_border2;
-
 	gtk_widget_queue_draw (GTK_WIDGET (viewer));
 }
 
@@ -1143,22 +847,16 @@
 		priv->vadj = NULL;
 	}
 
-	if (priv->area_pixbuf != NULL) {
+	/*if (priv->area_pixbuf != NULL) {
 		g_object_unref (priv->area_pixbuf);
 		priv->area_pixbuf = NULL;
-	}
+	}*/
 
         /* Chain up */
 	G_OBJECT_CLASS (image_viewer_parent_class)->finalize (object);
 }
 
 
-static int
-to_255 (int v)
-{
-	return v * 255 / 65535;
-}
-
 
 static void
 image_viewer_realize (GtkWidget *widget)
@@ -1206,20 +904,6 @@
 	priv->cursor = cursor_get (widget->window, CURSOR_HAND_OPEN);
 	priv->cursor_void = cursor_get (widget->window, CURSOR_VOID);
 	gdk_window_set_cursor (widget->window, priv->cursor);
-
-	if (priv->transp_type == GTH_TRANSP_TYPE_NONE) {
-		GdkColor color;
-		guint    base_color;
-
-		color = GTK_WIDGET (viewer)->style->bg[GTK_STATE_NORMAL];
-		base_color = (0xFF000000
-			      | (to_255 (color.red) << 16)
-			      | (to_255 (color.green) << 8)
-			      | (to_255 (color.blue) << 0));
-
-		priv->check_color1 = base_color;
-		priv->check_color2 = base_color;
-	}
 }
 
 
@@ -1267,7 +951,7 @@
 {
 	ImageViewer        *viewer = IMAGE_VIEWER (widget);
 	ImageViewerPrivate *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
-	gint                gdk_width, gdk_height;
+	gdouble             gdk_width, gdk_height;
 
 	widget->allocation = *allocation;
 	gdk_width = allocation->width - priv->frame_border2;
@@ -1276,7 +960,7 @@
 	/* If a fit type is active update the zoom level. */
 
 	if (priv->image != NULL) {
-		gint       width, height;
+		gdouble    width, height;
 		gdouble	   off_x, off_y;
 
 		/* Re-fit the image to the new widget size if a fit-mode is active */
@@ -1287,23 +971,24 @@
 
 		image_viewer_image_get_zoomed_size (priv->image, &width, &height);
 
-		if ((width != priv->hadj->upper) || (height != priv->vadj->upper))
+		if (!FLOAT_EQUAL(width,  priv->hadj->upper - priv->hadj->lower) ||
+		    !FLOAT_EQUAL(height, priv->vadj->upper - priv->vadj->lower))
 			gth_iviewer_size_changed (GTH_IVIEWER (viewer));
 
 		/* Change adjustment values. */
 
-		priv->hadj->lower          = 0.0;
-		priv->hadj->upper          = width;
-		priv->hadj->value          = off_x;
+		priv->hadj->lower          = floor (-width / 2 - priv->frame_border);
+		priv->hadj->upper          = floor ( width / 2 + priv->frame_border);
+		priv->hadj->value          = floor (off_x - gdk_width / 2);
 		priv->hadj->step_increment = STEP_INCREMENT;
-		priv->hadj->page_increment = gdk_width / 2;
+		priv->hadj->page_increment = floor (gdk_width / 2);
 		priv->hadj->page_size      = gdk_width;
 
-		priv->vadj->lower          = 0.0;
-		priv->vadj->upper          = height;
-		priv->vadj->value          = off_y;
+		priv->vadj->lower          = floor (-height / 2 - priv->frame_border);
+		priv->vadj->upper          = floor ( height / 2 + priv->frame_border);
+		priv->vadj->value          = floor ( off_y - gdk_height / 2);
 		priv->vadj->step_increment = STEP_INCREMENT;
-		priv->vadj->page_increment = gdk_height / 2;
+		priv->vadj->page_increment = floor (gdk_height / 2);
 		priv->vadj->page_size      = gdk_height;
 	} else {
 		priv->hadj->lower     = 0.0;
@@ -2083,86 +1768,17 @@
 }
 
 
-static void
-image_viewer_style_set (GtkWidget *widget,
-			GtkStyle  *previous_style)
-{
-	ImageViewer        *viewer = IMAGE_VIEWER (widget);
-	ImageViewerPrivate *priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
-
-	GTK_WIDGET_CLASS (image_viewer_parent_class)->style_set (widget, previous_style);
-
-	if (priv->transp_type == GTH_TRANSP_TYPE_NONE) {
-		GdkColor color;
-		guint    base_color;
-
-		color = GTK_WIDGET (viewer)->style->bg[GTK_STATE_NORMAL];
-		base_color = (0xFF000000
-			      | (to_255 (color.red) << 16)
-			      | (to_255 (color.green) << 8)
-			      | (to_255 (color.blue) << 0));
-
-		priv->check_color1 = base_color;
-		priv->check_color2 = base_color;
-	}
-}
-
-
 void
 image_viewer_set_transp_type (ImageViewer   *viewer,
 			      GthTranspType  transp_type)
 {
 	ImageViewerPrivate *priv;
-	GdkColor color;
-	guint    base_color;
 
 	g_return_if_fail (viewer != NULL);
 
 	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
 
 	priv->transp_type = transp_type;
-
-	color = GTK_WIDGET (viewer)->style->bg[GTK_STATE_NORMAL];
-	base_color = (0xFF000000
-		      | (to_255 (color.red) << 16)
-		      | (to_255 (color.green) << 8)
-		      | (to_255 (color.blue) << 0));
-
-	switch (transp_type) {
-	case GTH_TRANSP_TYPE_BLACK:
-		priv->check_color1 = COLOR_GRAY_00;
-		priv->check_color2 = COLOR_GRAY_00;
-		break;
-
-	case GTH_TRANSP_TYPE_NONE:
-		priv->check_color1 = base_color;
-		priv->check_color2 = base_color;
-		break;
-
-	case GTH_TRANSP_TYPE_WHITE:
-		priv->check_color1 = COLOR_GRAY_FF;
-		priv->check_color2 = COLOR_GRAY_FF;
-		break;
-
-	case GTH_TRANSP_TYPE_CHECKED:
-		switch (priv->check_type) {
-		case GTH_CHECK_TYPE_DARK:
-			priv->check_color1 = COLOR_GRAY_00;
-			priv->check_color2 = COLOR_GRAY_33;
-			break;
-
-		case GTH_CHECK_TYPE_MIDTONE:
-			priv->check_color1 = COLOR_GRAY_66;
-			priv->check_color2 = COLOR_GRAY_99;
-			break;
-
-		case GTH_CHECK_TYPE_LIGHT:
-			priv->check_color1 = COLOR_GRAY_CC;
-			priv->check_color2 = COLOR_GRAY_FF;
-			break;
-		}
-		break;
-	}
 }
 
 
@@ -2518,13 +2134,22 @@
 				   gboolean     set_black)
 {
 	ImageViewerPrivate *priv;
+	GtkWidget          *widget;
 
 	g_return_if_fail (IS_IMAGE_VIEWER (viewer));
 
-	priv = IMAGE_VIEWER_GET_PRIVATE (viewer);
+	priv   = IMAGE_VIEWER_GET_PRIVATE (viewer);
+	widget = GTK_WIDGET (viewer);
 
 	priv->black_bg = set_black;
-	gtk_widget_queue_draw (GTK_WIDGET (viewer));
+
+	if (set_black) {
+		gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, &widget->style->black);
+	} else {
+		gtk_widget_modify_bg (widget, GTK_STATE_NORMAL, NULL);
+	}
+
+	gtk_widget_queue_draw (widget);
 }
 
 

=== modified file 'libgthumb/nav-window.c'
--- libgthumb/nav-window.c	2007-01-28 09:27:15 +0000
+++ libgthumb/nav-window.c	2008-07-31 01:04:16 +0000
@@ -174,8 +174,8 @@
 	nav_win->sqr_height = MIN (nav_win->sqr_height, popup_height); 
 
 	gth_iviewer_get_scroll_offset (viewer, &x_offset, &y_offset);
-	nav_win->sqr_x = x_offset * factor;
-	nav_win->sqr_y = y_offset * factor;
+	nav_win->sqr_x = x_offset * factor + popup_width / 2;
+	nav_win->sqr_y = y_offset * factor + popup_width / 2;
 
 	/* Popup window position. */
 
@@ -267,8 +267,8 @@
 		my = (int) y;
 		nav_window_draw_sqr (nav_win, TRUE, mx, my);
 
-		mx = (int) (x / nav_win->factor);
-		my = (int) (y / nav_win->factor);
+		mx = (int) ((x - nav_win->popup_width  / 2) / nav_win->factor);
+		my = (int) ((y - nav_win->popup_height / 2) / nav_win->factor);
 		gth_iviewer_scroll_to (viewer, mx, my);
 
 		return TRUE;

=== modified file 'src/gth-fullscreen.c'
--- src/gth-fullscreen.c	2008-07-10 20:38:00 +0000
+++ src/gth-fullscreen.c	2008-07-31 01:04:16 +0000
@@ -1281,15 +1281,6 @@
 }
 
 
-static gboolean
-fs_repainted_cb (GtkWidget     *widget,
-		 GthFullscreen *fullscreen)
-{
-	fullscreen->priv->comment_visible = FALSE;
-	return TRUE;
-}
-
-
 static int
 image_button_release_cb (GtkWidget      *widget,
 			 GdkEventButton *event,
@@ -1630,10 +1621,6 @@
 				"expose_event",
 				G_CALLBACK (fs_expose_event_cb),
 				fullscreen);
-	g_signal_connect_after (G_OBJECT (priv->viewer),
-				"repainted",
-				G_CALLBACK (fs_repainted_cb),
-				fullscreen);
 	g_signal_connect_swapped (G_OBJECT (priv->viewer),
 				  "clicked",
 				  G_CALLBACK (load_next_image),

