added possibility to redraw only the parts of image that are already
authorVladimir Nadvornik <nadvornik@suse.cz>
Mon, 8 Sep 2008 19:57:51 +0000 (19:57 +0000)
committerVladimir Nadvornik <nadvornik@suse.cz>
Mon, 8 Sep 2008 19:57:51 +0000 (19:57 +0000)
loaded

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

index 1c2d429..b18e6bd 100644 (file)
@@ -172,6 +172,12 @@ static void image_loader_finalize(GObject *object)
                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 @@ static void image_loader_emit_percent(ImageLoader *il)
        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 @@ static void image_loader_emit_area_ready(ImageLoader *il, guint x, guint y, guin
        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 @@ static void image_loader_emit_area_ready(ImageLoader *il, guint x, guint y, guin
 /**************************************************************************************/
 /* 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 @@ static gint image_loader_get_stopping(ImageLoader *il)
        return ret;
 }
 
+
 static void image_loader_sync_pixbuf(ImageLoader *il)
 {
        GdkPixbuf *pb;
@@ -340,7 +361,13 @@ static void image_loader_area_updated_cb(GdkPixbufLoader *loader,
                        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 @@ static void image_loader_stop(ImageLoader *il)
        
 }
 
+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 */
 
index 94d2ece..7893eb9 100644 (file)
@@ -45,6 +45,9 @@ struct _ImageLoader
 
        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 @@ ImageLoader *image_loader_new(FileData *fd);
 
 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
index 94154cd..ad1bb6f 100644 (file)
@@ -432,6 +432,8 @@ static void image_read_ahead_start(ImageWindow *imd)
        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 @@ static gint image_cache_get(ImageWindow *imd)
        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 @@ static void image_load_pixbuf_ready(ImageWindow *imd)
 {
        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 @@ static void image_load_area_cb(ImageLoader *il, guint x, guint y, guint w, guint
                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 @@ static void image_load_done_cb(ImageLoader *il, gpointer data)
                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 @@ static void image_load_done_cb(ImageLoader *il, gpointer data)
            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 @@ static gint image_read_ahead_check(ImageWindow *imd)
 
                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 @@ static gint image_load_begin(ImageWindow *imd, FileData *fd)
 
        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 @@ static void image_change_complete(ImageWindow *imd, gdouble zoom, gint new)
                        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 @@ static void image_change_complete(ImageWindow *imd, gdouble zoom, gint new)
                        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 @@ GdkPixbuf *image_get_pixbuf(ImageWindow *imd)
        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 @@ void image_change_pixbuf(ImageWindow *imd, GdkPixbuf *pixbuf, gdouble zoom)
                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)
                {
index 28ccb04..a7b34cd 100644 (file)
@@ -56,7 +56,7 @@ void image_set_fd(ImageWindow *imd, FileData *fd);
 
 /* 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);
index 7ee2ec3..3988c60 100644 (file)
@@ -1988,7 +1988,7 @@ LayoutWindow *layout_new_with_geometry(FileData *dir_fd, gint popped, gint hidde
                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);
                }
 
index f7125db..7143bcf 100644 (file)
@@ -181,6 +181,7 @@ typedef enum {
        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 @@ static gint pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom,
        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 @@ static gint pr_zoom_clamp(PixbufRenderer *pr, gdouble zoom,
        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 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom,
        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 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom,
                }
 
        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 @@ static void pr_zoom_sync(PixbufRenderer *pr, gdouble zoom,
         * 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_size_sync(PixbufRenderer *pr)
                }
 }
 
-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,25 +3861,28 @@ static void pr_pixbuf_sync(PixbufRenderer *pr, gdouble zoom)
                }
 
        pr_pixbuf_size_sync(pr);
-       pr_zoom_sync(pr, zoom, PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0);
+       pr_zoom_sync(pr, zoom, flags | PR_ZOOM_FORCE | PR_ZOOM_NEW, 0, 0);
 }
 
-static void pr_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom)
+void pixbuf_renderer_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;
+       g_return_if_fail(IS_PIXBUF_RENDERER(pr));
 
-       pr_pixbuf_sync(pr, zoom);
+       pr_source_tile_unset(pr);
+
+       pr_set_pixbuf(pr, pixbuf, zoom, 0);
+
+       pr_update_signal(pr);
 }
 
-void pixbuf_renderer_set_pixbuf(PixbufRenderer *pr, GdkPixbuf *pixbuf, gdouble zoom)
+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_set_pixbuf(pr, pixbuf, zoom);
+       pr->orientation = orientation;
+       pr_set_pixbuf(pr, pixbuf, zoom, PR_ZOOM_LAZY);
 
        pr_update_signal(pr);
 }
index 63674cb..fa3d954 100644 (file)
@@ -179,6 +179,11 @@ GtkWindow *pixbuf_renderer_get_parent(PixbufRenderer *pr);
 /* 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);
index 2339bbd..79f0686 100644 (file)
@@ -627,7 +627,7 @@ static void print_window_layout_size(PrintWindow *pw)
            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);
                }