# HG changeset patch # User nadvornik # Date 1220903871 0 # Node ID 0ab0deb0cfccd2b19331b4ff699ab712c53baa96 # Parent ea4e0c2df854d91e2e846e37220a34a0190433a9 added possibility to redraw only the parts of image that are already loaded diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/image-load.c --- 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 */ diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/image-load.h --- 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 diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/image.c --- 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) { diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/image.h --- 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); diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/layout.c --- 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); } diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/pixbuf-renderer.c --- 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); } diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/pixbuf-renderer.h --- 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); diff -r ea4e0c2df854 -r 0ab0deb0cfcc src/print.c --- 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); }