changeset 1045:0ab0deb0cfcc

added possibility to redraw only the parts of image that are already loaded
author nadvornik
date Mon, 08 Sep 2008 19:57:51 +0000
parents ea4e0c2df854
children e34e9bdef276
files src/image-load.c src/image-load.h src/image.c src/image.h src/layout.c src/pixbuf-renderer.c src/pixbuf-renderer.h src/print.c
diffstat 8 files changed, 138 insertions(+), 35 deletions(-) [+]
line wrap: on
line diff
--- a/src/image-load.c	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/image-load.c	Mon Sep 08 19:57:51 2008 +0000
@@ -172,6 +172,12 @@
 		il->area_param_list = g_list_delete_link(il->area_param_list, il->area_param_list);
 		}
 
+	while (il->area_param_delayed_list) 
+		{
+		g_free(il->area_param_delayed_list->data);
+		il->area_param_delayed_list = g_list_delete_link(il->area_param_delayed_list, il->area_param_delayed_list);
+		}
+
 	if (il->pixbuf) g_object_unref(il->pixbuf);
 
 	file_data_unref(il->fd);
@@ -267,6 +273,7 @@
 	g_idle_add_full(G_PRIORITY_HIGH, image_loader_emit_percent_cb, il, NULL);
 }
 
+/* this function expects that il->data_mutex is locked by caller */
 static void image_loader_emit_area_ready(ImageLoader *il, guint x, guint y, guint w, guint h)
 {
 	ImageLoaderAreaParam *par = g_new0(ImageLoaderAreaParam, 1);
@@ -276,9 +283,7 @@
 	par->w = w;
 	par->h = h;
 	
-	g_mutex_lock(il->data_mutex);
 	il->area_param_list = g_list_prepend(il->area_param_list, par);
-	g_mutex_unlock(il->data_mutex);
 	
 	g_idle_add_full(G_PRIORITY_HIGH, image_loader_emit_area_ready_cb, par, NULL);
 }
@@ -286,6 +291,21 @@
 /**************************************************************************************/
 /* the following functions may be executed in separate thread */
 
+/* this function expects that il->data_mutex is locked by caller */
+static void image_loader_queue_delayed_erea_ready(ImageLoader *il, guint x, guint y, guint w, guint h)
+{
+	ImageLoaderAreaParam *par = g_new0(ImageLoaderAreaParam, 1);
+	par->il = il;
+	par->x = x;
+	par->y = y;
+	par->w = w;
+	par->h = h;
+	
+	il->area_param_delayed_list = g_list_prepend(il->area_param_delayed_list, par);
+}
+
+
+
 static gint image_loader_get_stopping(ImageLoader *il)
 {
 	gint ret;
@@ -298,6 +318,7 @@
 	return ret;
 }
 
+
 static void image_loader_sync_pixbuf(ImageLoader *il)
 {
 	GdkPixbuf *pb;
@@ -340,7 +361,13 @@
 			log_printf("critical: area_ready signal with NULL pixbuf (out of mem?)\n");
 			}
 		}
-	image_loader_emit_area_ready(il, x, y, w, h);
+
+	g_mutex_lock(il->data_mutex);
+	if (il->delay_area_ready)
+		image_loader_queue_delayed_erea_ready(il, x, y, w, h);
+	else
+		image_loader_emit_area_ready(il, x, y, w, h);
+	g_mutex_unlock(il->data_mutex);
 }
 
 static void image_loader_area_prepared_cb(GdkPixbufLoader *loader, gpointer data)
@@ -666,6 +693,38 @@
 	
 }
 
+void image_loader_delay_area_ready(ImageLoader *il, gint enable)
+{
+	g_mutex_lock(il->data_mutex);
+	il->delay_area_ready = enable;
+	if (!enable)
+		{
+		/* send delayed */
+		GList *list, *work;
+		list = g_list_reverse(il->area_param_delayed_list);
+		il->area_param_delayed_list = NULL;
+		g_mutex_unlock(il->data_mutex);
+
+		work = list;
+
+		while (work)
+			{
+			ImageLoaderAreaParam *par = work->data;
+			work = work->next;
+			
+			g_signal_emit(il, signals[SIGNAL_AREA_READY], 0, par->x, par->y, par->w, par->h);
+			g_free(par);
+			}
+		g_list_free(list);
+		}
+	else
+		{
+		/* just unlock */
+		g_mutex_unlock(il->data_mutex);
+		}
+}
+
+
 /**************************************************************************************/
 /* execution via idle calls */
 
--- a/src/image-load.h	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/image-load.h	Mon Sep 08 19:57:51 2008 +0000
@@ -45,6 +45,9 @@
 
 	gint idle_done_id;
 	GList *area_param_list;
+	GList *area_param_delayed_list;
+	
+	gint delay_area_ready;
 	
 	GMutex *data_mutex;
 	gint stopping;
@@ -73,6 +76,8 @@
 
 void image_loader_free(ImageLoader *il);
 
+/* delay area_ready signals */
+void image_loader_delay_area_ready(ImageLoader *il, gint enable);
 
 /* Speed up loading when you only need at most width x height size image,
  * only the jpeg GdkPixbuf loader benefits from it - so there is no
--- a/src/image.c	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/image.c	Mon Sep 08 19:57:51 2008 +0000
@@ -432,6 +432,8 @@
 	DEBUG_1("%s read ahead started for :%s", get_exec_time(), imd->read_ahead_fd->path);
 
 	imd->read_ahead_il = image_loader_new(imd->read_ahead_fd);
+	
+	image_loader_delay_area_ready(imd->read_ahead_il, TRUE); /* we will need the area_ready signals later */
 
 	g_signal_connect (G_OBJECT(imd->read_ahead_il), "error", (GCallback)image_read_ahead_error_cb, imd);
 	g_signal_connect (G_OBJECT(imd->read_ahead_il), "done", (GCallback)image_read_ahead_done_cb, imd);
@@ -491,7 +493,7 @@
 	if (success)
 		{
 		g_assert(imd->image_fd->pixbuf);
-		image_change_pixbuf(imd, imd->image_fd->pixbuf, image_zoom_get(imd));
+		image_change_pixbuf(imd, imd->image_fd->pixbuf, image_zoom_get(imd), FALSE);
 		}
 	
 	file_cache_dump(image_get_cache());
@@ -508,7 +510,7 @@
 {
 	if (image_get_pixbuf(imd) || !imd->il) return;
 
-	image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+	image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), FALSE);
 }
 
 static void image_load_area_cb(ImageLoader *il, guint x, guint y, guint w, guint h, gpointer data)
@@ -524,7 +526,7 @@
 		return;
 		}
 
-	if (!pr->pixbuf) image_load_pixbuf_ready(imd);
+	if (!pr->pixbuf) image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
 
 	pixbuf_renderer_area_changed(pr, x, y, w, h);
 }
@@ -549,7 +551,7 @@
 		GdkPixbuf *pixbuf;
 
 		pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
-		image_change_pixbuf(imd, pixbuf, image_zoom_get(imd));
+		image_change_pixbuf(imd, pixbuf, image_zoom_get(imd), FALSE);
 		g_object_unref(pixbuf);
 
 		imd->unknown = TRUE;
@@ -558,7 +560,7 @@
 	    image_get_pixbuf(imd) != image_loader_get_pixbuf(imd->il))
 		{
 		g_object_set(G_OBJECT(imd->pr), "complete", FALSE, NULL);
-		image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+		image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), FALSE);
 		}
 
 	image_loader_free(imd->il);
@@ -608,16 +610,18 @@
 
 		if (!imd->delay_flip)
 			{
-			image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd));
+			image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
 			}
 
+		image_loader_delay_area_ready(imd->il, FALSE); /* send the delayed area_ready signals */
+
 		file_data_unref(imd->read_ahead_fd);
 		imd->read_ahead_fd = NULL;
 		return TRUE;
 		}
 	else if (imd->read_ahead_fd->pixbuf)
 		{
-		image_change_pixbuf(imd, imd->read_ahead_fd->pixbuf, image_zoom_get(imd));
+		image_change_pixbuf(imd, imd->read_ahead_fd->pixbuf, image_zoom_get(imd), FALSE);
 
 		file_data_unref(imd->read_ahead_fd);
 		imd->read_ahead_fd = NULL;
@@ -684,8 +688,12 @@
 
 	image_state_set(imd, IMAGE_STATE_LOADING);
 
-	if (!imd->delay_flip && !image_get_pixbuf(imd)) image_load_pixbuf_ready(imd);
-
+/*
+	if (!imd->delay_flip && !image_get_pixbuf(imd) && image_loader_get_pixbuf(imd->il))
+		{
+		image_change_pixbuf(imd, image_loader_get_pixbuf(imd->il), image_zoom_get(imd), TRUE);
+		}
+*/	
 	return TRUE;
 }
 
@@ -734,7 +742,7 @@
 			GdkPixbuf *pixbuf;
 
 			pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
-			image_change_pixbuf(imd, pixbuf, zoom);
+			image_change_pixbuf(imd, pixbuf, zoom, FALSE);
 			g_object_unref(pixbuf);
 
 			imd->unknown = TRUE;
@@ -747,12 +755,12 @@
 			GdkPixbuf *pixbuf;
 
 			pixbuf = pixbuf_inline(PIXBUF_INLINE_BROKEN);
-			image_change_pixbuf(imd, pixbuf, zoom);
+			image_change_pixbuf(imd, pixbuf, zoom, FALSE);
 			g_object_unref(pixbuf);
 			}
 		else
 			{
-			image_change_pixbuf(imd, NULL, zoom);
+			image_change_pixbuf(imd, NULL, zoom, FALSE);
 			}
 		imd->unknown = TRUE;
 		}
@@ -988,7 +996,7 @@
 	return pixbuf_renderer_get_pixbuf((PixbufRenderer *)imd->pr);
 }
 
-void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom)
+void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gint lazy)
 {
 
 	ExifData *exif = NULL;
@@ -1023,8 +1031,15 @@
 		imd->cm = NULL;
 		}
 
-	pixbuf_renderer_set_pixbuf((PixbufRenderer *)imd->pr, pixbuf, zoom);
-	pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, imd->orientation);
+	if (lazy)
+		{
+		pixbuf_renderer_set_pixbuf_lazy((PixbufRenderer *)imd->pr, pixbuf, zoom, imd->orientation);
+		}
+	else
+		{
+		pixbuf_renderer_set_pixbuf((PixbufRenderer *)imd->pr, pixbuf, zoom);
+		pixbuf_renderer_set_orientation((PixbufRenderer *)imd->pr, imd->orientation);
+		}
 
 	if (imd->color_profile_enable)
 		{
--- a/src/image.h	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/image.h	Mon Sep 08 19:57:51 2008 +0000
@@ -56,7 +56,7 @@
 
 /* load a new image */
 void image_change_fd(ImageWindow *imd, FileData *fd, gdouble zoom);
-void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom);
+void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom, gint lazy);
 void image_change_from_collection(ImageWindow *imd, CollectionData *cd, CollectInfo *info, gdouble zoom);
 CollectionData *image_get_collection(ImageWindow *imd, CollectInfo **info);
 void image_change_from_image(ImageWindow *imd, ImageWindow *source);
--- a/src/layout.c	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/layout.c	Mon Sep 08 19:57:51 2008 +0000
@@ -1988,7 +1988,7 @@
 		GdkPixbuf *pixbuf;
 
 		pixbuf = pixbuf_inline(PIXBUF_INLINE_LOGO);
-		image_change_pixbuf(lw->image, pixbuf, 1.0);
+		image_change_pixbuf(lw->image, pixbuf, 1.0, FALSE);
 		g_object_unref(pixbuf);
 		}
 
--- a/src/pixbuf-renderer.c	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/pixbuf-renderer.c	Mon Sep 08 19:57:51 2008 +0000
@@ -181,6 +181,7 @@
 	PR_ZOOM_NEW		= 1 << 1,
 	PR_ZOOM_CENTER		= 1 << 2,
 	PR_ZOOM_INVALIDATE	= 1 << 3,
+	PR_ZOOM_LAZY		= 1 << 4  /* wait with redraw for pixbuf_renderer_area_changed */
 } PrZoomFlags;
 
 static guint signals[SIGNAL_COUNT] = { 0 };
@@ -3192,6 +3193,7 @@
 	gboolean force = !!(flags & PR_ZOOM_FORCE);
 	gboolean new = !!(flags & PR_ZOOM_NEW);
 	gboolean invalidate = !!(flags & PR_ZOOM_INVALIDATE);
+	gboolean lazy = !!(flags & PR_ZOOM_LAZY);
 
 	zoom = CLAMP(zoom, pr->zoom_min, pr->zoom_max);
 
@@ -3285,7 +3287,7 @@
 	if (invalidate || invalid)
 		{
 		pr_tile_invalidate_all(pr);
-		pr_redraw(pr, TRUE);
+		if (!lazy) pr_redraw(pr, TRUE);
 		}
 	if (redrawn) *redrawn = (invalidate || invalid);
 
@@ -3305,6 +3307,7 @@
 	gboolean center_point = !!(flags & PR_ZOOM_CENTER);
 	gboolean force = !!(flags & PR_ZOOM_FORCE);
 	gboolean new = !!(flags & PR_ZOOM_NEW);
+	gboolean lazy = !!(flags & PR_ZOOM_LAZY);
 	PrZoomFlags clamp_flags = flags;
 	gdouble old_center_x = pr->norm_center_x;
 	gdouble old_center_y = pr->norm_center_y;
@@ -3325,6 +3328,7 @@
 		}
 
 	if (force) clamp_flags |= PR_ZOOM_INVALIDATE;
+	if (lazy) clamp_flags |= PR_ZOOM_LAZY;
 	if (!pr_zoom_clamp(pr, zoom, clamp_flags, &redrawn)) return;
 
 	clamped = pr_size_clamp(pr);
@@ -3374,7 +3378,15 @@
 	 * so redraw the window anyway :/
 	 */
 	if (sized || clamped) pr_border_clear(pr);
-	pr_redraw(pr, redrawn);
+	
+	if (lazy)
+		{
+		pr_queue_clear(pr);
+		}
+	else
+		{
+		pr_redraw(pr, redrawn);
+		}
 
 	pr_scroll_notify_signal(pr);
 	pr_zoom_signal(pr);
@@ -3820,8 +3832,12 @@
 		}
 }
 
-static void pr_pixbuf_sync(PixbufRenderer *pr, gdouble zoom)
+static void pr_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, PrZoomFlags flags)
 {
+	if (pixbuf) g_object_ref(pixbuf);
+	if (pr->pixbuf) g_object_unref(pr->pixbuf);
+	pr->pixbuf = pixbuf;
+
 	if (!pr->pixbuf)
 		{
 		GtkWidget *box;
@@ -3845,16 +3861,7 @@
 		}
 
 	pr_pixbuf_size_sync(pr);
-	pr_zoom_sync(pr, zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0);
-}
-
-static void pr_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom)
-{
-	if (pixbuf) g_object_ref(pixbuf);
-	if (pr->pixbuf) g_object_unref(pr->pixbuf);
-	pr->pixbuf = pixbuf;
-
-	pr_pixbuf_sync(pr, zoom);
+	pr_zoom_sync(pr, zoom, flags | PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0);
 }
 
 void pixbuf_renderer_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom)
@@ -3863,7 +3870,19 @@
 
 	pr_source_tile_unset(pr);
 
-	pr_set_pixbuf(pr, pixbuf, zoom);
+	pr_set_pixbuf(pr, pixbuf, zoom, 0);
+
+	pr_update_signal(pr);
+}
+
+void pixbuf_renderer_set_pixbuf_lazy(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, gint orientation)
+{
+	g_return_if_fail(IS_PIXBUF_RENDERER(pr));
+
+	pr_source_tile_unset(pr);
+
+	pr->orientation = orientation;
+	pr_set_pixbuf(pr, pixbuf, zoom, PR_ZOOM_LAZY);
 
 	pr_update_signal(pr);
 }
--- a/src/pixbuf-renderer.h	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/pixbuf-renderer.h	Mon Sep 08 19:57:51 2008 +0000
@@ -179,6 +179,11 @@
 /* display a pixbuf */
 
 void pixbuf_renderer_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom);
+
+/* same as pixbuf_renderer_set_pixbuf but waits with redrawing for pixbuf_renderer_area_changed */
+void pixbuf_renderer_set_pixbuf_lazy(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom, gint orientation);
+
+
 GdkPixbuf *pixbuf_renderer_get_pixbuf(PixbufRenderer *pr);
 
 void pixbuf_renderer_set_orientation(PixbufRenderer *pr, gint orientation);
--- a/src/print.c	Mon Sep 08 15:53:01 2008 +0000
+++ b/src/print.c	Mon Sep 08 19:57:51 2008 +0000
@@ -627,7 +627,7 @@
 	    gdk_pixbuf_get_height(pixbuf) != sh)
 		{
 		pixbuf = gdk_pixbuf_new(GDK_COLORSPACE_RGB, FALSE, 8, sw, sh);
-		image_change_pixbuf(pw->layout_image, pixbuf, 0.0);
+		image_change_pixbuf(pw->layout_image, pixbuf, 0.0, FALSE);
 		g_object_unref(pixbuf);
 		}