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);
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);
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);
}
/**************************************************************************************/
/* 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;
return ret;
}
+
static void image_loader_sync_pixbuf(ImageLoader *il)
{
GdkPixbuf *pb;
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)
}
+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 */
gint idle_done_id;
GList *area_param_list;
+ GList *area_param_delayed_list;
+
+ gint delay_area_ready;
GMutex *data_mutex;
gint stopping;
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
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);
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());
{
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)
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);
}
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;
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);
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;
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;
}
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;
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;
}
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;
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)
{
/* 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);
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);
}
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 };
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);
if (invalidate || invalid)
{
pr_tile_invalidate_all(pr);
- pr_redraw(pr, TRUE);
+ if (!lazy) pr_redraw(pr, TRUE);
}
if (redrawn) *redrawn = (invalidate || invalid);
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;
}
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);
* 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);
}
}
-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;
}
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);
}
/* 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);
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);
}