[gthumb: 3/40] Use a two step policy to load images
- From: Paolo Bacchilega <paobac src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gthumb: 3/40] Use a two step policy to load images
- Date: Fri, 10 Sep 2010 16:56:27 +0000 (UTC)
commit df17e42bddb38955609dd338e3dd84151c9f07b0
Author: Paolo Bacchilega <paobac src gnome org>
Date: Thu Sep 2 13:29:59 2010 +0200
Use a two step policy to load images
In the first step the image is loaded at a smaller size to minimize load time, in the second step it is loaded at full size to maximize quality.
extensions/file_viewer/gth-file-viewer-page.c | 8 +-
extensions/flicker/dlg-import-from-flickr.c | 10 +-
extensions/gstreamer_tools/gth-media-viewer-page.c | 2 +-
extensions/image_viewer/gth-image-viewer-page.c | 73 +++-
extensions/picasaweb/dlg-import-from-picasaweb.c | 10 +-
extensions/raw_files/main.c | 3 +
extensions/slideshow/gth-slideshow.c | 27 +-
gthumb/glib-utils.c | 22 +-
gthumb/glib-utils.h | 2 +
gthumb/gth-image-loader.c | 60 +++-
gthumb/gth-image-loader.h | 10 +-
gthumb/gth-image-preloader.c | 479 ++++++++++++--------
gthumb/gth-image-preloader.h | 38 +-
gthumb/gth-main.h | 3 +
gthumb/gth-marshal.list | 1 +
gthumb/gth-thumb-loader.c | 31 +-
gthumb/gth-thumb-loader.h | 2 +-
gthumb/gth-viewer-page.c | 10 +-
gthumb/gth-viewer-page.h | 2 +
gthumb/pixbuf-io.c | 52 ++-
gthumb/pixbuf-io.h | 6 +
21 files changed, 593 insertions(+), 258 deletions(-)
---
diff --git a/extensions/file_viewer/gth-file-viewer-page.c b/extensions/file_viewer/gth-file-viewer-page.c
index 10a95cb..f2f3923 100644
--- a/extensions/file_viewer/gth-file-viewer-page.c
+++ b/extensions/file_viewer/gth-file-viewer-page.c
@@ -39,6 +39,7 @@ struct _GthFileViewerPagePrivate {
GtkWidget *viewer;
GtkWidget *icon;
GtkWidget *label;
+ GthFileData *file_data;
guint merge_id;
GthThumbLoader *thumb_loader;
gulong thumb_loader_ready_event;
@@ -91,7 +92,7 @@ thumb_loader_ready_cb (GthThumbLoader *il,
{
if (error == NULL)
gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->icon), gth_thumb_loader_get_pixbuf (self->priv->thumb_loader));
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), TRUE);
+ gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), self->priv->file_data, TRUE);
}
@@ -227,6 +228,9 @@ gth_file_viewer_page_real_view (GthViewerPage *base,
if (icon != NULL)
gtk_image_set_from_gicon (GTK_IMAGE (self->priv->icon), icon, GTK_ICON_SIZE_DIALOG);
+ _g_object_unref (self->priv->file_data);
+ self->priv->file_data = g_object_ref (file_data);
+
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
gth_thumb_loader_set_file (self->priv->thumb_loader, file_data);
gth_thumb_loader_load (self->priv->thumb_loader);
@@ -280,6 +284,7 @@ gth_file_viewer_page_finalize (GObject *obj)
self = GTH_FILE_VIEWER_PAGE (obj);
+ _g_object_unref (self->priv->file_data);
_g_object_unref (self->priv->thumb_loader);
G_OBJECT_CLASS (gth_file_viewer_page_parent_class)->finalize (obj);
@@ -318,6 +323,7 @@ gth_file_viewer_page_instance_init (GthFileViewerPage *self)
{
self->priv = GTH_FILE_VIEWER_PAGE_GET_PRIVATE (self);
self->priv->thumb_loader = NULL;
+ self->priv->file_data = NULL;
}
diff --git a/extensions/flicker/dlg-import-from-flickr.c b/extensions/flicker/dlg-import-from-flickr.c
index 6f86cea..4d82082 100644
--- a/extensions/flicker/dlg-import-from-flickr.c
+++ b/extensions/flicker/dlg-import-from-flickr.c
@@ -427,12 +427,14 @@ photoset_combobox_changed_cb (GtkComboBox *widget,
static GdkPixbufAnimation *
flickr_thumbnail_loader (GthFileData *file_data,
- GError **error,
- gpointer data)
+ int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
+ GError **error)
{
GdkPixbufAnimation *animation = NULL;
- GthThumbLoader *thumb_loader = data;
- int requested_size;
+ GthThumbLoader *thumb_loader = user_data;
FlickrPhoto *photo;
const char *uri = NULL;
diff --git a/extensions/gstreamer_tools/gth-media-viewer-page.c b/extensions/gstreamer_tools/gth-media-viewer-page.c
index 30bbf47..af7f6f4 100644
--- a/extensions/gstreamer_tools/gth-media-viewer-page.c
+++ b/extensions/gstreamer_tools/gth-media-viewer-page.c
@@ -1065,7 +1065,7 @@ gth_media_viewer_page_real_view (GthViewerPage *base,
/**/
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), TRUE);
+ gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), self->priv->file_data, TRUE);
g_signal_handlers_block_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
gtk_adjustment_set_value (GTK_ADJUSTMENT (GET_WIDGET ("adjustment_position")), 0.0);
g_signal_handlers_unblock_by_func(GET_WIDGET ("adjustment_position"), position_value_changed_cb, self);
diff --git a/extensions/image_viewer/gth-image-viewer-page.c b/extensions/image_viewer/gth-image-viewer-page.c
index 3e5ceeb..adcc574 100644
--- a/extensions/image_viewer/gth-image-viewer-page.c
+++ b/extensions/image_viewer/gth-image-viewer-page.c
@@ -45,6 +45,7 @@ struct _GthImageViewerPagePrivate {
guint motion_signal;
gboolean pixbuf_changed;
gboolean shrink_wrap;
+ GFile *last_loaded;
};
static gpointer gth_image_viewer_page_parent_class = NULL;
@@ -203,6 +204,22 @@ static GtkToggleActionEntry image_viewer_toggle_action_entries[] = {
static void
+gth_image_viewer_page_file_loaded (GthImageViewerPage *self,
+ gboolean success)
+{
+ if (_g_file_equal (self->priv->last_loaded, self->priv->file_data->file))
+ return;
+
+ _g_object_unref (self->priv->last_loaded);
+ self->priv->last_loaded = g_object_ref (self->priv->file_data->file);
+
+ gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self),
+ self->priv->file_data,
+ success);
+}
+
+
+static void
viewer_image_ready_cb (GtkWidget *widget,
GthImageViewerPage *self)
{
@@ -213,7 +230,7 @@ viewer_image_ready_cb (GtkWidget *widget,
gth_image_history_add_image (self->priv->history,
gth_image_viewer_get_current_pixbuf (GTH_IMAGE_VIEWER (self->priv->viewer)),
FALSE);
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), TRUE);
+ gth_image_viewer_page_file_loaded (self, TRUE);
}
@@ -284,24 +301,20 @@ viewer_key_press_cb (GtkWidget *widget,
static void
image_preloader_requested_ready_cb (GthImagePreloader *preloader,
+ GthFileData *requested,
+ GthImageLoader *image_loader,
GError *error,
GthImageViewerPage *self)
{
- GthImageLoader *image_loader;
-
- if (error != NULL) {
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), FALSE);
+ if (! _g_file_equal (requested->file, self->priv->file_data->file))
return;
- }
- image_loader = gth_image_preloader_get_loader (self->priv->preloader, gth_image_preloader_get_requested (self->priv->preloader));
- if (image_loader == NULL) {
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), FALSE);
+ if (error != NULL) {
+ gth_image_viewer_page_file_loaded (self, FALSE);
return;
}
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
-
gth_image_viewer_load_from_image_loader (GTH_IMAGE_VIEWER (self->priv->viewer), image_loader);
}
@@ -629,19 +642,25 @@ gth_image_viewer_page_real_view (GthViewerPage *base,
GthFileStore *file_store;
GtkTreeIter iter;
GthFileData *next_file_data = NULL;
+ GthFileData *next2_file_data = NULL;
GthFileData *prev_file_data = NULL;
+ GtkAllocation allocation;
+ int window_width;
+ int window_height;
self = (GthImageViewerPage*) base;
g_return_if_fail (file_data != NULL);
gth_viewer_page_focus (GTH_VIEWER_PAGE (self));
+ _g_clear_object (&self->priv->last_loaded);
+
if ((self->priv->file_data != NULL)
&& g_file_equal (file_data->file, self->priv->file_data->file)
&& (gth_file_data_get_mtime (file_data) == gth_file_data_get_mtime (self->priv->file_data))
&& ! self->priv->pixbuf_changed)
{
- gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), TRUE);
+ gth_image_viewer_page_file_loaded (self, TRUE);
return;
}
@@ -649,22 +668,46 @@ gth_image_viewer_page_real_view (GthViewerPage *base,
self->priv->file_data = gth_file_data_dup (file_data);
file_store = gth_browser_get_file_store (self->priv->browser);
- if (gth_file_store_find_visible (file_store, file_data->file, &iter)) {
+ if (gth_file_store_find_visible (file_store, self->priv->file_data->file, &iter)) {
GtkTreeIter iter2;
+ GtkTreeIter iter3;
iter2 = iter;
if (gth_file_store_get_next_visible (file_store, &iter2))
next_file_data = gth_file_store_get_file (file_store, &iter2);
+ iter3 = iter2;
+ if (gth_file_store_get_next_visible (file_store, &iter3))
+ next2_file_data = gth_file_store_get_file (file_store, &iter3);
+
iter2 = iter;
if (gth_file_store_get_prev_visible (file_store, &iter2))
prev_file_data = gth_file_store_get_file (file_store, &iter2);
}
+ window_width = -1;
+ window_height = -1;
+
+ gtk_widget_get_allocation (self->priv->viewer, &allocation);
+ if ((allocation.width > 1) && (allocation.height > 1)) {
+ window_width = allocation.width;
+ window_height = allocation.height;
+ }
+ else {
+ GtkWidget *toplevel;
+
+ toplevel = gtk_widget_get_toplevel (self->priv->viewer);
+ if (gtk_widget_is_toplevel (toplevel))
+ gtk_window_get_size (GTK_WINDOW (toplevel), &window_width, &window_height);
+ }
+
gth_image_preloader_load (self->priv->preloader,
- file_data,
+ self->priv->file_data,
+ MAX (window_width, window_height),
next_file_data,
- prev_file_data);
+ next2_file_data,
+ prev_file_data,
+ NULL);
}
@@ -1007,6 +1050,7 @@ gth_image_viewer_page_finalize (GObject *obj)
g_object_unref (self->priv->history);
_g_object_unref (self->priv->file_data);
+ _g_object_unref (self->priv->last_loaded);
G_OBJECT_CLASS (gth_image_viewer_page_parent_class)->finalize (obj);
}
@@ -1048,6 +1092,7 @@ gth_image_viewer_page_instance_init (GthImageViewerPage *self)
self->priv = GTH_IMAGE_VIEWER_PAGE_GET_PRIVATE (self);
self->priv->history = gth_image_history_new ();
self->priv->shrink_wrap = FALSE;
+ self->priv->last_loaded = NULL;
}
diff --git a/extensions/picasaweb/dlg-import-from-picasaweb.c b/extensions/picasaweb/dlg-import-from-picasaweb.c
index f795814..15df4d8 100644
--- a/extensions/picasaweb/dlg-import-from-picasaweb.c
+++ b/extensions/picasaweb/dlg-import-from-picasaweb.c
@@ -843,12 +843,14 @@ album_combobox_changed_cb (GtkComboBox *widget,
GdkPixbufAnimation *
picasa_web_thumbnail_loader (GthFileData *file_data,
- GError **error,
- gpointer data)
+ int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
+ GError **error)
{
GdkPixbufAnimation *animation = NULL;
- GthThumbLoader *thumb_loader = data;
- int requested_size;
+ GthThumbLoader *thumb_loader = user_data;
PicasaWebPhoto *photo;
const char *uri;
diff --git a/extensions/raw_files/main.c b/extensions/raw_files/main.c
index bab5a42..1adac9e 100644
--- a/extensions/raw_files/main.c
+++ b/extensions/raw_files/main.c
@@ -271,6 +271,9 @@ get_file_mtime (const char *path)
static GdkPixbufAnimation *
openraw_pixbuf_animation_new_from_file (GthFileData *file_data,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
GError **error)
{
GdkPixbufAnimation *animation;
diff --git a/extensions/slideshow/gth-slideshow.c b/extensions/slideshow/gth-slideshow.c
index bdcff06..e4a1c13 100644
--- a/extensions/slideshow/gth-slideshow.c
+++ b/extensions/slideshow/gth-slideshow.c
@@ -125,6 +125,9 @@ _gth_slideshow_load_current_image (GthSlideshow *self)
GthFileData *requested_file;
GthFileData *next_file;
GthFileData *prev_file;
+ int screen_width;
+ int screen_height;
+ GdkScreen *screen;
if (self->priv->next_event != 0) {
g_source_remove (self->priv->next_event);
@@ -148,10 +151,21 @@ _gth_slideshow_load_current_image (GthSlideshow *self)
prev_file = (GthFileData *) self->priv->current->prev->data;
else
prev_file = NULL;
+
+ screen_width = -1;
+ screen_height = -1;
+ screen = gtk_widget_get_screen (GTK_WIDGET (self));
+ if (screen != NULL) {
+ screen_width = gdk_screen_get_width (screen);
+ screen_height = gdk_screen_get_height (screen);
+ }
+
gth_image_preloader_load (self->priv->preloader,
requested_file,
+ MAX (screen_width, screen_height),
next_file,
- prev_file);
+ prev_file,
+ NULL);
}
@@ -211,11 +225,12 @@ view_next_image_automatically (GthSlideshow *self)
static void
image_preloader_requested_ready_cb (GthImagePreloader *preloader,
+ GthFileData *requested,
+ GthImageLoader *image_loader,
GError *error,
gpointer user_data)
{
GthSlideshow *self = user_data;
- GthImageLoader *image_loader;
GdkPixbuf *pixbuf;
if (error != NULL) {
@@ -224,12 +239,6 @@ image_preloader_requested_ready_cb (GthImagePreloader *preloader,
return;
}
- image_loader = gth_image_preloader_get_loader (self->priv->preloader, (GthFileData *) self->priv->current->data);
- if (image_loader == NULL) {
- _gth_slideshow_load_next_image (self);
- return;
- }
-
pixbuf = gth_image_loader_get_pixbuf (image_loader);
if (pixbuf == NULL) {
_gth_slideshow_load_next_image (self);
@@ -260,7 +269,7 @@ gth_slideshow_init (GthSlideshow *self)
self->priv->direction = GTH_SLIDESHOW_DIRECTION_FORWARD;
self->priv->random_order = FALSE;
- self->priv->preloader = gth_image_preloader_new ();
+ self->priv->preloader = gth_image_preloader_new (GTH_LOAD_POLICY_ONE_STEP, 3);
g_signal_connect (self->priv->preloader,
"requested_ready",
G_CALLBACK (image_preloader_requested_ready_cb),
diff --git a/gthumb/glib-utils.c b/gthumb/glib-utils.c
index 437407e..7fec8b1 100644
--- a/gthumb/glib-utils.c
+++ b/gthumb/glib-utils.c
@@ -19,6 +19,7 @@
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
+#include <config.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -2263,7 +2264,26 @@ int
_g_file_cmp_uris (GFile *a,
GFile *b)
{
- return g_file_equal (a, b) ? 0 : 1;
+ char *uri_a;
+ char *uri_b;
+ int result;
+
+ uri_a = g_file_get_uri (a);
+ uri_b = g_file_get_uri (b);
+ result = g_strcmp0 (uri_a, uri_b);
+
+ g_free (uri_b);
+ g_free (uri_a);
+
+ return result;
+}
+
+
+gboolean
+_g_file_equal_uris (GFile *a,
+ GFile *b)
+{
+ return _g_file_cmp_uris (a, b) == 0;
}
diff --git a/gthumb/glib-utils.h b/gthumb/glib-utils.h
index d1f71b6..692ee45 100644
--- a/gthumb/glib-utils.h
+++ b/gthumb/glib-utils.h
@@ -260,6 +260,8 @@ void _g_file_get_modification_time (GFile *file,
time_t _g_file_get_mtime (GFile *file);
int _g_file_cmp_uris (GFile *a,
GFile *b);
+gboolean _g_file_equal_uris (GFile *a,
+ GFile *b);
int _g_file_cmp_modification_time (GFile *a,
GFile *b);
goffset _g_file_get_size (GFile *info);
diff --git a/gthumb/gth-image-loader.c b/gthumb/gth-image-loader.c
index ccf966d..d2606ba 100644
--- a/gthumb/gth-image-loader.c
+++ b/gthumb/gth-image-loader.c
@@ -45,8 +45,11 @@ G_LOCK_DEFINE_STATIC (pixbuf_loader_lock);
struct _GthImageLoaderPrivate {
GthFileData *file;
+ int requested_size;
GdkPixbuf *pixbuf;
GdkPixbufAnimation *animation;
+ int original_width;
+ int original_height;
gboolean as_animation; /* Whether to load the image in a
* GdkPixbufAnimation structure. */
@@ -74,7 +77,7 @@ struct _GthImageLoaderPrivate {
GMutex *start_loading_mutex;
GCond *start_loading_cond;
- LoaderFunc loader;
+ PixbufLoader loader;
gpointer loader_data;
};
@@ -201,6 +204,9 @@ load_image_thread (void *thread_data)
for (;;) {
GthFileData *file;
gboolean exit_thread;
+ int requested_size;
+ int original_width;
+ int original_height;
g_mutex_lock (iloader->priv->start_loading_mutex);
while (! iloader->priv->start_loading)
@@ -210,6 +216,7 @@ load_image_thread (void *thread_data)
g_mutex_lock (iloader->priv->exit_thread_mutex);
exit_thread = iloader->priv->exit_thread;
+ requested_size = iloader->priv->requested_size;
g_mutex_unlock (iloader->priv->exit_thread_mutex);
if (exit_thread)
@@ -219,18 +226,30 @@ load_image_thread (void *thread_data)
G_LOCK (pixbuf_loader_lock);
+ original_width = -1;
+ original_height = -1;
animation = NULL;
if (file != NULL) {
error = NULL;
if (iloader->priv->loader != NULL) {
- animation = (*iloader->priv->loader) (file, &error, iloader->priv->loader_data);
+ animation = (*iloader->priv->loader) (file,
+ requested_size,
+ &original_width,
+ &original_height,
+ iloader->priv->loader_data,
+ &error);
}
else {
PixbufLoader loader;
loader = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (file));
if (loader != NULL)
- animation = loader (file, -1, &error);
+ animation = loader (file,
+ requested_size,
+ &original_width,
+ &original_height,
+ NULL,
+ &error);
else
error = g_error_new_literal (G_IO_ERROR, G_IO_ERROR_NOT_SUPPORTED, _("No suitable loader available for this file type"));
}
@@ -244,11 +263,14 @@ load_image_thread (void *thread_data)
if (iloader->priv->animation != NULL)
g_object_unref (iloader->priv->animation);
iloader->priv->animation = animation;
+ iloader->priv->original_width = original_width;
+ iloader->priv->original_height = original_height;
+
if ((animation == NULL) || (error != NULL)) {
iloader->priv->error = error;
iloader->priv->ready = FALSE;
}
- else {
+ else if (requested_size == iloader->priv->requested_size) {
iloader->priv->error = NULL;
iloader->priv->ready = TRUE;
}
@@ -270,6 +292,7 @@ gth_image_loader_init (GthImageLoader *iloader)
iloader->priv->pixbuf = NULL;
iloader->priv->animation = NULL;
iloader->priv->file = NULL;
+ iloader->priv->requested_size = -1;
iloader->priv->ready = FALSE;
iloader->priv->error = NULL;
@@ -359,7 +382,7 @@ gth_image_loader_new (gboolean as_animation)
void
gth_image_loader_set_loader (GthImageLoader *iloader,
- LoaderFunc loader,
+ PixbufLoader loader,
gpointer loader_data)
{
g_return_if_fail (iloader != NULL);
@@ -664,6 +687,14 @@ _gth_image_loader_load__step2 (GthImageLoader *iloader)
void
gth_image_loader_load (GthImageLoader *iloader)
{
+ gth_image_loader_load_at_size (iloader, -1);
+}
+
+
+void
+gth_image_loader_load_at_size (GthImageLoader *iloader,
+ int requested_size)
+{
gboolean no_file = FALSE;
g_return_if_fail (iloader != NULL);
@@ -671,6 +702,7 @@ gth_image_loader_load (GthImageLoader *iloader)
g_mutex_lock (iloader->priv->data_mutex);
if (iloader->priv->file == NULL)
no_file = TRUE;
+ iloader->priv->requested_size = requested_size;
g_mutex_unlock (iloader->priv->data_mutex);
if (no_file)
@@ -684,6 +716,7 @@ gth_image_loader_load (GthImageLoader *iloader)
}
+
/* -- gth_image_loader_stop -- */
@@ -691,7 +724,7 @@ static void
_gth_image_loader_stop__step2 (GthImageLoader *iloader,
gboolean use_idle_cb)
{
- DataFunc done_func = iloader->priv->done_func;
+ DataFunc done_func;
GError *error;
g_mutex_lock (iloader->priv->data_mutex);
@@ -704,6 +737,7 @@ _gth_image_loader_stop__step2 (GthImageLoader *iloader,
_gth_image_loader_sync_pixbuf (iloader);
iloader->priv->loading = FALSE;
+ done_func = iloader->priv->done_func;
iloader->priv->done_func = NULL;
if (done_func != NULL) {
IdleCall *call;
@@ -744,7 +778,7 @@ _gth_image_loader_stop (GthImageLoader *iloader,
void
gth_image_loader_cancel (GthImageLoader *iloader,
- DataFunc done_func,
+ DataFunc done_func,
gpointer done_func_data)
{
g_mutex_lock (iloader->priv->data_mutex);
@@ -801,6 +835,18 @@ gth_image_loader_get_animation (GthImageLoader *iloader)
}
+void
+gth_image_loader_get_original_size (GthImageLoader *iloader,
+ int *width,
+ int *height)
+{
+ g_mutex_lock (iloader->priv->data_mutex);
+ *width = iloader->priv->original_width;
+ *height = iloader->priv->original_height;
+ g_mutex_unlock (iloader->priv->data_mutex);
+}
+
+
gboolean
gth_image_loader_is_ready (GthImageLoader *iloader)
{
diff --git a/gthumb/gth-image-loader.h b/gthumb/gth-image-loader.h
index 69ae22b..3ed6b77 100644
--- a/gthumb/gth-image-loader.h
+++ b/gthumb/gth-image-loader.h
@@ -26,6 +26,7 @@
#include <gdk-pixbuf/gdk-pixbuf.h>
#include "typedefs.h"
#include "gth-file-data.h"
+#include "gth-main.h"
G_BEGIN_DECLS
@@ -56,12 +57,10 @@ struct _GthImageLoaderClass
GError *error);
};
-typedef GdkPixbufAnimation * (*LoaderFunc) (GthFileData *file, GError **error, gpointer data);
-
GType gth_image_loader_get_type (void);
GthImageLoader * gth_image_loader_new (gboolean as_animation);
void gth_image_loader_set_loader (GthImageLoader *iloader,
- LoaderFunc loader,
+ PixbufLoader loader,
gpointer data);
void gth_image_loader_set_file_data (GthImageLoader *iloader,
GthFileData *file);
@@ -73,8 +72,13 @@ void gth_image_loader_set_pixbuf (GthImageLoader
GdkPixbuf *pixbuf);
GdkPixbuf * gth_image_loader_get_pixbuf (GthImageLoader *iloader);
GdkPixbufAnimation * gth_image_loader_get_animation (GthImageLoader *iloader);
+void gth_image_loader_get_original_size (GthImageLoader *iloader,
+ int *width,
+ int *height);
gboolean gth_image_loader_is_ready (GthImageLoader *iloader);
void gth_image_loader_load (GthImageLoader *iloader);
+void gth_image_loader_load_at_size (GthImageLoader *iloader,
+ int requested_size);
void gth_image_loader_cancel (GthImageLoader *iloader,
DataFunc done_func,
gpointer done_func_data);
diff --git a/gthumb/gth-image-preloader.c b/gthumb/gth-image-preloader.c
index 9005732..d05f220 100644
--- a/gthumb/gth-image-preloader.c
+++ b/gthumb/gth-image-preloader.c
@@ -25,12 +25,13 @@
#include <glib.h>
#include "glib-utils.h"
#include "gth-image-preloader.h"
+#include "gth-marshal.h"
+#undef DEBUG_PRELOADER
#define GTH_IMAGE_PRELOADER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), GTH_TYPE_IMAGE_PRELOADER, GthImagePreloaderPrivate))
#define NEXT_LOAD_SMALL_TIMEOUT 100
-#define NEXT_LOAD_BIG_TIMEOUT 400
-#define N_LOADERS 3
+#define NEXT_LOAD_BIG_TIMEOUT 300
enum {
@@ -41,29 +42,35 @@ enum {
typedef struct {
GthFileData *file_data;
+ int requested_size;
GthImageLoader *loader;
gboolean loaded;
gboolean error;
- GthImagePreloader *image_preloader;
+ GthImagePreloader *self;
} Preloader;
struct _GthImagePreloaderPrivate {
- Preloader *loader[N_LOADERS]; /* Array of loaders, each loader
- * will load an image. */
- int requested; /* This is the loader with the
- * requested image. The
- * requested image is the image
- * the user has expressly
- * requested to view, when this
- * image is loaded a
- * requested_ready signal is
- * emitted.
- * Other images do not trigger
- * any signal. */
- int current; /* This is the loader that has
- * a loading underway. */
- guint load_id;
+ GthLoadPolicy load_policy;
+ int n_preloaders;
+ Preloader **loader; /* Array of loaders, each loader
+ * will load an image. */
+ int requested; /* This is the loader with the
+ * requested image. The
+ * requested image is the image
+ * the user has expressly
+ * requested to view, when this
+ * image is loaded a
+ * requested_ready signal is
+ * emitted.
+ * Other images do not trigger
+ * any signal. */
+ GFile *requested_file;
+ int requested_size;
+ GthFileData **files;
+ int current; /* This is the loader that has
+ * a loading underway. */
+ guint load_id;
};
@@ -73,57 +80,89 @@ static guint gth_image_preloader_signals[LAST_SIGNAL] = { 0 };
/* -- Preloader -- */
-static void start_next_loader (GthImagePreloader *image_preloader);
-static Preloader * current_preloader (GthImagePreloader *image_preloader);
-static Preloader * requested_preloader (GthImagePreloader *image_preloader);
+static void start_next_loader (GthImagePreloader *self);
+static Preloader * current_preloader (GthImagePreloader *self);
+static Preloader * requested_preloader (GthImagePreloader *self);
static gboolean
load_next (gpointer data)
{
- GthImagePreloader *image_preloader = data;
+ GthImagePreloader *self = data;
- if (image_preloader->priv->load_id != 0) {
- g_source_remove (image_preloader->priv->load_id);
- image_preloader->priv->load_id = 0;
+ if (self->priv->load_id != 0) {
+ g_source_remove (self->priv->load_id);
+ self->priv->load_id = 0;
}
- start_next_loader (image_preloader);
+ start_next_loader (self);
return FALSE;
}
+static gboolean
+preloader_need_second_step (Preloader *preloader)
+{
+ int original_width;
+ int original_height;
+
+ gth_image_loader_get_original_size (preloader->loader, &original_width, &original_height);
+
+ return (! preloader->error
+ && (preloader->requested_size != -1)
+ && ((original_width > preloader->requested_size) || (original_height > preloader->requested_size))
+ && gdk_pixbuf_animation_is_static_image (gth_image_loader_get_animation (preloader->loader)));
+}
+
+
static void
-image_loader_ready_cb (GthImageLoader *il,
+image_loader_ready_cb (GthImageLoader *iloader,
GError *error,
Preloader *preloader)
{
- GthImagePreloader *image_preloader = preloader->image_preloader;
- int timeout = NEXT_LOAD_SMALL_TIMEOUT;
+ GthImagePreloader *self = preloader->self;
+ int interval = NEXT_LOAD_SMALL_TIMEOUT;
preloader->loaded = (error == NULL);
preloader->error = (error != NULL);
- g_object_ref (image_preloader);
+ g_object_ref (self);
- if (preloader == requested_preloader (image_preloader)) {
- g_signal_emit (G_OBJECT (image_preloader),
+ if (_g_file_equal (preloader->file_data->file, self->priv->requested_file)) {
+#if DEBUG_PRELOADER
+ debug (DEBUG_INFO, "[requested] %s => %s [size: %d]", (error == NULL) ? "ready" : "error", g_file_get_uri (preloader->file_data->file), preloader->requested_size);
+#endif
+
+ g_signal_emit (G_OBJECT (self),
gth_image_preloader_signals[REQUESTED_READY],
0,
+ preloader->file_data,
+ preloader->loader,
error);
- debug (DEBUG_INFO, "[requested] error");
- timeout = NEXT_LOAD_BIG_TIMEOUT;
+
+ /* Reload only if the original size is bigger then the
+ * requested size, and if the image is not an animation. */
+
+ if ((self->priv->load_policy == GTH_LOAD_POLICY_TWO_STEPS)
+ && preloader_need_second_step (preloader))
+ {
+ /* Reload the image at the original size */
+ preloader->loaded = FALSE;
+ preloader->requested_size = -1;
+ }
+
+ interval = NEXT_LOAD_BIG_TIMEOUT;
}
- image_preloader->priv->load_id = g_idle_add (load_next, image_preloader);
+ self->priv->load_id = g_timeout_add (interval, load_next, self);
- g_object_unref (image_preloader);
+ g_object_unref (self);
}
-static Preloader*
-preloader_new (GthImagePreloader *image_preloader)
+static Preloader *
+preloader_new (GthImagePreloader *self)
{
Preloader *preloader;
@@ -132,7 +171,7 @@ preloader_new (GthImagePreloader *image_preloader)
preloader->loaded = FALSE;
preloader->error = FALSE;
preloader->loader = GTH_IMAGE_LOADER (gth_image_loader_new (TRUE));
- preloader->image_preloader = image_preloader;
+ preloader->self = self;
g_signal_connect (G_OBJECT (preloader->loader),
"ready",
@@ -181,23 +220,34 @@ preloader_set_file_data (Preloader *preloader,
static void
gth_image_preloader_finalize (GObject *object)
{
- GthImagePreloader *image_preloader;
+ GthImagePreloader *self;
int i;
g_return_if_fail (object != NULL);
g_return_if_fail (GTH_IS_IMAGE_PRELOADER (object));
- image_preloader = GTH_IMAGE_PRELOADER (object);
+ self = GTH_IMAGE_PRELOADER (object);
- if (image_preloader->priv->load_id != 0) {
- g_source_remove (image_preloader->priv->load_id);
- image_preloader->priv->load_id = 0;
+ if (self->priv->load_id != 0) {
+ g_source_remove (self->priv->load_id);
+ self->priv->load_id = 0;
}
- for (i = 0; i < N_LOADERS; i++) {
- preloader_free (image_preloader->priv->loader[i]);
- image_preloader->priv->loader[i] = NULL;
+ for (i = 0; i < self->priv->n_preloaders; i++) {
+ preloader_free (self->priv->loader[i]);
+ self->priv->loader[i] = NULL;
}
+ g_free (self->priv->loader);
+ self->priv->loader = NULL;
+
+ _g_object_unref (self->priv->requested_file);
+
+ for (i = 0; i < self->priv->n_preloaders; i++) {
+ _g_object_unref (self->priv->files[i]);
+ self->priv->files[i] = NULL;
+ }
+ g_free (self->priv->files);
+ self->priv->files = NULL;
/* Chain up */
G_OBJECT_CLASS (parent_class)->finalize (object);
@@ -218,9 +268,11 @@ gth_image_preloader_class_init (GthImagePreloaderClass *class)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GthImagePreloaderClass, requested_ready),
NULL, NULL,
- g_cclosure_marshal_VOID__POINTER,
+ gth_marshal_VOID__OBJECT_OBJECT_POINTER,
G_TYPE_NONE,
- 1,
+ 3,
+ G_TYPE_OBJECT,
+ G_TYPE_OBJECT,
G_TYPE_POINTER);
object_class = G_OBJECT_CLASS (class);
@@ -229,16 +281,15 @@ gth_image_preloader_class_init (GthImagePreloaderClass *class)
static void
-gth_image_preloader_init (GthImagePreloader *image_preloader)
+gth_image_preloader_init (GthImagePreloader *self)
{
- int i;
-
- image_preloader->priv = GTH_IMAGE_PRELOADER_GET_PRIVATE (image_preloader);
-
- for (i = 0; i < N_LOADERS; i++)
- image_preloader->priv->loader[i] = preloader_new (image_preloader);
- image_preloader->priv->requested = -1;
- image_preloader->priv->current = -1;
+ self->priv = GTH_IMAGE_PRELOADER_GET_PRIVATE (self);
+ self->priv->loader = NULL;
+ self->priv->requested = -1;
+ self->priv->requested_file = NULL;
+ self->priv->current = -1;
+ self->priv->files = NULL;
+ self->priv->load_policy = GTH_LOAD_POLICY_ONE_STEP;
}
@@ -271,81 +322,57 @@ gth_image_preloader_get_type (void)
GthImagePreloader *
-gth_image_preloader_new (void)
+gth_image_preloader_new (GthLoadPolicy load_policy,
+ int n_preloaders)
{
- return (GthImagePreloader *) g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
+ GthImagePreloader *self;
+ int i;
+
+ g_return_val_if_fail (n_preloaders > 0, NULL);
+
+ self = g_object_new (GTH_TYPE_IMAGE_PRELOADER, NULL);
+
+ self->priv->n_preloaders = n_preloaders;
+ self->priv->load_policy = load_policy;
+ self->priv->loader = g_new0 (Preloader *, self->priv->n_preloaders);
+ for (i = 0; i < self->priv->n_preloaders; i++)
+ self->priv->loader[i] = preloader_new (self);
+ self->priv->files = g_new0 (GthFileData *, self->priv->n_preloaders);
+
+ return self;
}
static Preloader *
-current_preloader (GthImagePreloader *image_preloader)
+current_preloader (GthImagePreloader *self)
{
- if (image_preloader->priv->current == -1)
+ if (self->priv->current == -1)
return NULL;
else
- return image_preloader->priv->loader[image_preloader->priv->current];
+ return self->priv->loader[self->priv->current];
}
static Preloader *
-requested_preloader (GthImagePreloader *image_preloader)
+requested_preloader (GthImagePreloader *self)
{
- if (image_preloader->priv->requested == -1)
+ if (self->priv->requested == -1)
return NULL;
else
- return image_preloader->priv->loader[image_preloader->priv->requested];
+ return self->priv->loader[self->priv->requested];
}
/* -- gth_image_preloader_load -- */
-#define N_ARGS 3
-
-
typedef struct {
- GthImagePreloader *image_preloader;
+ GthImagePreloader *self;
GthFileData *requested;
- GthFileData *next1;
- GthFileData *prev1;
+ int requested_size;
} LoadData;
-static GthFileData *
-check_file (GthFileData *file_data)
-{
- if (file_data == NULL)
- return NULL;
-
- if (! g_file_is_native (file_data->file))
- return NULL;
-
- if (! _g_mime_type_is_image (gth_file_data_get_mime_type (file_data)))
- return NULL;
-
- return gth_file_data_dup (file_data);
-}
-
-
-static LoadData*
-load_data_new (GthImagePreloader *image_preloader,
- GthFileData *requested,
- GthFileData *next1,
- GthFileData *prev1)
-{
- LoadData *load_data;
-
- load_data = g_new0 (LoadData, 1);
-
- load_data->image_preloader = image_preloader;
- load_data->requested = gth_file_data_dup (requested);
- load_data->next1 = check_file (next1);
- load_data->prev1 = check_file (prev1);
-
- return load_data;
-}
-
-
static void
load_data_free (LoadData *load_data)
{
@@ -353,8 +380,6 @@ load_data_free (LoadData *load_data)
return;
_g_object_unref (load_data->requested);
- _g_object_unref (load_data->next1);
- _g_object_unref (load_data->prev1);
g_free (load_data);
}
@@ -362,36 +387,40 @@ load_data_free (LoadData *load_data)
void
gth_image_preloader_load__step2 (LoadData *load_data)
{
- GthImagePreloader *image_preloader = load_data->image_preloader;
- GthFileData *requested = load_data->requested;
- GthFileData *next1 = load_data->next1;
- GthFileData *prev1 = load_data->prev1;
- GthFileData *files[N_ARGS];
- gboolean file_assigned[N_LOADERS];
- gboolean loader_assigned[N_LOADERS];
+ GthImagePreloader *self = load_data->self;
+ gboolean *file_assigned;
+ gboolean *loader_assigned;
+ GthFileData *requested;
int i, j;
- files[0] = requested;
- files[1] = next1;
- files[2] = prev1;
+ if (! _g_file_equal (load_data->requested->file, self->priv->requested_file)
+ || (load_data->requested_size != self->priv->requested_size))
+ {
+ load_data_free (load_data);
+ return;
+ }
+
+ requested = load_data->requested;
- for (i = 0; i < N_LOADERS; i++) {
+ file_assigned = g_new (gboolean, self->priv->n_preloaders);
+ loader_assigned = g_new (gboolean, self->priv->n_preloaders);
+ for (i = 0; i < self->priv->n_preloaders; i++) {
loader_assigned[i] = FALSE;
file_assigned[i] = FALSE;
}
- image_preloader->priv->requested = -1;
+ self->priv->requested = -1;
- for (j = 0; j < N_ARGS; j++) {
- GthFileData *file_data = files[j];
+ for (j = 0; j < self->priv->n_preloaders; j++) {
+ GthFileData *file_data = self->priv->files[j];
if (file_data == NULL)
continue;
/* check whether the image has already been loaded. */
- for (i = 0; i < N_LOADERS; i++) {
- Preloader *preloader = image_preloader->priv->loader[i];
+ for (i = 0; i < self->priv->n_preloaders; i++) {
+ Preloader *preloader = self->priv->loader[i];
if ((preloader->file_data != NULL)
&& g_file_equal (preloader->file_data->file, file_data->file)
@@ -399,30 +428,50 @@ gth_image_preloader_load__step2 (LoadData *load_data)
gth_file_data_get_modification_time (preloader->file_data)) == 0)
&& preloader->loaded)
{
- char *uri;
-
loader_assigned[i] = TRUE;
file_assigned[j] = TRUE;
if ((requested != NULL) && g_file_equal (file_data->file, requested->file)) {
- image_preloader->priv->requested = i;
- g_signal_emit (G_OBJECT (image_preloader), gth_image_preloader_signals[REQUESTED_READY], 0, NULL);
+ self->priv->requested = i;
+ g_signal_emit (G_OBJECT (self),
+ gth_image_preloader_signals[REQUESTED_READY],
+ 0,
+ preloader->file_data,
+ preloader->loader,
+ NULL);
+#if DEBUG_PRELOADER
debug (DEBUG_INFO, "[requested] preloaded");
+#endif
+
+ if ((self->priv->load_policy == GTH_LOAD_POLICY_TWO_STEPS)
+ && preloader_need_second_step (preloader))
+ {
+ /* Reload the image at the original size */
+ preloader->loaded = FALSE;
+ preloader->requested_size = -1;
+ }
}
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[=] [%d] <- %s", i, uri);
- g_free (uri);
+#if DEBUG_PRELOADER
+ {
+ char *uri;
+
+ uri = g_file_get_uri (file_data->file);
+ debug (DEBUG_INFO, "[=] [%d] <- %s", i, uri);
+ g_free (uri);
+ }
+#endif
+
+ break;
}
}
}
- /* assign remaining paths. */
+ /* assign remaining files */
- for (j = 0; j < N_ARGS; j++) {
- GthFileData *file_data = files[j];
+ for (j = 0; j < self->priv->n_preloaders; j++) {
+ GthFileData *file_data = self->priv->files[j];
Preloader *preloader;
int k;
- char *uri;
if (file_data == NULL)
continue;
@@ -431,60 +480,119 @@ gth_image_preloader_load__step2 (LoadData *load_data)
continue;
/* find the first non-assigned loader */
- for (k = 0; (k < N_LOADERS) && loader_assigned[k]; k++)
+ for (k = 0; (k < self->priv->n_preloaders) && loader_assigned[k]; k++)
/* void */;
- g_return_if_fail (k < N_LOADERS);
+ g_return_if_fail (k < self->priv->n_preloaders);
- preloader = image_preloader->priv->loader[k];
+ preloader = self->priv->loader[k];
loader_assigned[k] = TRUE;
preloader_set_file_data (preloader, file_data);
+ preloader->requested_size = load_data->requested_size;
if ((requested != NULL) && g_file_equal (file_data->file, requested->file)) {
- image_preloader->priv->requested = k;
+ self->priv->requested = k;
+#if DEBUG_PRELOADER
+ {
+ char *uri;
- uri = g_file_get_uri (file_data->file);
- debug (DEBUG_INFO, "[requested] %s", uri);
- g_free (uri);
+ uri = g_file_get_uri (file_data->file);
+ debug (DEBUG_INFO, "[requested] %s", uri);
+ g_free (uri);
+ }
+#endif
}
+#if DEBUG_PRELOADER
uri = g_file_get_uri (file_data->file);
debug (DEBUG_INFO, "[+] [%d] <- %s", k, uri);
g_free (uri);
+#endif
}
load_data_free (load_data);
+ g_free (loader_assigned);
+ g_free (file_assigned);
+
+ start_next_loader (self);
+}
+
+
+static GthFileData *
+check_file (GthFileData *file_data)
+{
+ if (file_data == NULL)
+ return NULL;
- start_next_loader (image_preloader);
+ if (! g_file_is_native (file_data->file))
+ return NULL;
+
+ if (! _g_mime_type_is_image (gth_file_data_get_mime_type (file_data)))
+ return NULL;
+
+ return gth_file_data_dup (file_data);
}
void
-gth_image_preloader_load (GthImagePreloader *image_preloader,
- GthFileData *requested,
- GthFileData *next1,
- GthFileData *prev1)
+gth_image_preloader_load (GthImagePreloader *self,
+ GthFileData *requested,
+ int requested_size,
+ ...)
{
- LoadData *load_data;
+ int i;
+ int n;
+ va_list args;
+ GthFileData *file_data;
+ LoadData *load_data;
+
+ _g_object_unref (self->priv->requested_file);
+ self->priv->requested_file = g_object_ref (requested->file);
+ self->priv->requested_size = requested_size;
+ self->priv->requested = -1;
+
+ for (i = 0; i < self->priv->n_preloaders; i++) {
+ _g_object_unref (self->priv->files[i]);
+ self->priv->files[i] = NULL;
+ }
+
+ self->priv->files[0] = gth_file_data_dup (requested);
+ n = 1;
+ va_start (args, requested_size);
+ while ((n < self->priv->n_preloaders) && (file_data = va_arg (args, GthFileData *)) != NULL)
+ self->priv->files[n++] = check_file (file_data);
+ va_end (args);
+
+ load_data = g_new0 (LoadData, 1);
+ load_data->self = self;
+ load_data->requested = gth_file_data_dup (requested);
+ load_data->requested_size = requested_size;
+
+ gth_image_preloader_stop (self, (DataFunc) gth_image_preloader_load__step2, load_data);
+}
+
- load_data = load_data_new (image_preloader, requested, next1, prev1);
- gth_image_preloader_stop (image_preloader, (DataFunc) gth_image_preloader_load__step2, load_data);
+void
+gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
+ GthLoadPolicy policy)
+{
+ self->priv->load_policy = policy;
}
GthImageLoader *
-gth_image_preloader_get_loader (GthImagePreloader *image_preloader,
+gth_image_preloader_get_loader (GthImagePreloader *self,
GthFileData *file_data)
{
int i;
- g_return_val_if_fail (image_preloader != NULL, NULL);
+ g_return_val_if_fail (self != NULL, NULL);
if (file_data == NULL)
return NULL;
- for (i = 0; i < N_LOADERS; i++) {
- Preloader *preloader = image_preloader->priv->loader[i];
+ for (i = 0; i < self->priv->n_preloaders; i++) {
+ Preloader *preloader = self->priv->loader[i];
if ((preloader->file_data != NULL)
&& g_file_equal (preloader->file_data->file, file_data->file)
@@ -501,11 +609,11 @@ gth_image_preloader_get_loader (GthImagePreloader *image_preloader,
GthFileData *
-gth_image_preloader_get_requested (GthImagePreloader *image_preloader)
+gth_image_preloader_get_requested (GthImagePreloader *self)
{
Preloader *preloader;
- preloader = requested_preloader (image_preloader);
+ preloader = requested_preloader (self);
if (preloader == NULL)
return NULL;
else
@@ -514,30 +622,29 @@ gth_image_preloader_get_requested (GthImagePreloader *image_preloader)
static void
-start_next_loader (GthImagePreloader *image_preloader)
+start_next_loader (GthImagePreloader *self)
{
- int i;
Preloader *preloader;
- char *uri;
+ int i;
- preloader = requested_preloader (image_preloader);
+ preloader = requested_preloader (self);
if ((preloader != NULL)
&& (preloader->file_data != NULL)
&& ! preloader->error
&& ! preloader->loaded)
{
- i = image_preloader->priv->requested;
+ i = self->priv->requested;
}
else {
int n = 0;
- if (image_preloader->priv->current == -1)
+ if (self->priv->current == -1)
i = 0;
else
- i = (image_preloader->priv->current + 1) % N_LOADERS;
+ i = (self->priv->current + 1) % self->priv->n_preloaders;
- for (i = 0; n < N_LOADERS; i = (i + 1) % N_LOADERS) {
- preloader = image_preloader->priv->loader[i];
+ for (i = 0; n < self->priv->n_preloaders; i = (i + 1) % self->priv->n_preloaders) {
+ preloader = self->priv->loader[i];
if ((preloader != NULL)
&& (preloader->file_data != NULL)
@@ -550,40 +657,50 @@ start_next_loader (GthImagePreloader *image_preloader)
n++;
}
- if (n >= N_LOADERS) {
- image_preloader->priv->current = -1;
+ if (n >= self->priv->n_preloaders) {
+ self->priv->current = -1;
+#if DEBUG_PRELOADER
debug (DEBUG_INFO, "done");
+#endif
return;
}
}
- image_preloader->priv->current = i;
- preloader = current_preloader (image_preloader);
+ self->priv->current = i;
+ preloader = current_preloader (self);
- gth_image_loader_load (preloader->loader);
+#if DEBUG_PRELOADER
+ {
+ char *uri;
- uri = g_file_get_uri (preloader->file_data->file);
- debug (DEBUG_INFO, "load %s", uri);
- g_free (uri);
+ uri = g_file_get_uri (preloader->file_data->file);
+ debug (DEBUG_INFO, "load %s [size: %d]", uri, preloader->requested_size);
+ g_free (uri);
+ }
+#endif
+
+ gth_image_loader_load_at_size (preloader->loader, preloader->requested_size);
}
void
-gth_image_preloader_stop (GthImagePreloader *image_preloader,
+gth_image_preloader_stop (GthImagePreloader *self,
DataFunc done_func,
gpointer done_func_data)
{
Preloader *preloader;
- if (image_preloader->priv->current == -1) {
+ preloader = current_preloader (self);
+
+ if (preloader == NULL) {
+#if DEBUG_PRELOADER
debug (DEBUG_INFO, "stopped");
+#endif
call_when_idle (done_func, done_func_data);
return;
}
- preloader = current_preloader (image_preloader);
- image_preloader->priv->current = -1;
-
+ self->priv->current = -1;
gth_image_loader_cancel (preloader->loader, done_func, done_func_data);
}
@@ -597,7 +714,9 @@ gth_image_preloader_set (GthImagePreloader *dest,
if (src == NULL)
return;
- for (i = 0; i < N_LOADERS; i++) {
+ g_return_if_fail (src->priv->n_preloaders == dest->priv->n_preloaders);
+
+ for (i = 0; i < src->priv->n_preloaders; i++) {
Preloader *src_loader = src->priv->loader[i];
Preloader *dest_loader = dest->priv->loader[i];
diff --git a/gthumb/gth-image-preloader.h b/gthumb/gth-image-preloader.h
index 6a9de2a..38df535 100644
--- a/gthumb/gth-image-preloader.h
+++ b/gthumb/gth-image-preloader.h
@@ -25,6 +25,10 @@
#include "gth-image-loader.h"
#include "gth-file-data.h"
+typedef enum {
+ GTH_LOAD_POLICY_ONE_STEP,
+ GTH_LOAD_POLICY_TWO_STEPS,
+} GthLoadPolicy;
#define GTH_TYPE_IMAGE_PRELOADER (gth_image_preloader_get_type ())
#define GTH_IMAGE_PRELOADER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), GTH_TYPE_IMAGE_PRELOADER, GthImagePreloader))
@@ -51,24 +55,28 @@ struct _GthImagePreloaderClass {
/*< signals >*/
void (* requested_ready) (GthImagePreloader *preloader,
+ GthFileData *requested,
+ GthImageLoader *image_loader,
GError *error);
};
-GType gth_image_preloader_get_type (void) G_GNUC_CONST;
-GthImagePreloader * gth_image_preloader_new (void);
-/* images get loaded in the following order : requested, next1, prev1. */
-void gth_image_preloader_load (GthImagePreloader *preloader,
- GthFileData *requested,
- GthFileData *next1,
- GthFileData *prev1);
-void gth_image_preloader_stop (GthImagePreloader *preloader,
- DataFunc done_func,
- gpointer done_func_data);
-GthImageLoader * gth_image_preloader_get_loader (GthImagePreloader *preloader,
- GthFileData *file_data);
-GthFileData * gth_image_preloader_get_requested (GthImagePreloader *preloader);
-void gth_image_preloader_set (GthImagePreloader *dest,
- GthImagePreloader *src);
+GType gth_image_preloader_get_type (void) G_GNUC_CONST;
+GthImagePreloader * gth_image_preloader_new (GthLoadPolicy load_policy,
+ int max_preloaders);
+void gth_image_preloader_load (GthImagePreloader *self,
+ GthFileData *requested,
+ int requested_size,
+ ...);
+void gth_image_prelaoder_set_load_policy (GthImagePreloader *self,
+ GthLoadPolicy policy);
+void gth_image_preloader_stop (GthImagePreloader *self,
+ DataFunc done_func,
+ gpointer done_func_data);
+GthImageLoader * gth_image_preloader_get_loader (GthImagePreloader *self,
+ GthFileData *file_data);
+GthFileData * gth_image_preloader_get_requested (GthImagePreloader *self);
+void gth_image_preloader_set (GthImagePreloader *dest,
+ GthImagePreloader *src);
#endif /* GTH_IMAGE_PRELOADER_H */
diff --git a/gthumb/gth-main.h b/gthumb/gth-main.h
index 741068a..2afbb49 100644
--- a/gthumb/gth-main.h
+++ b/gthumb/gth-main.h
@@ -51,6 +51,9 @@ typedef struct _GthMainClass GthMainClass;
typedef GdkPixbufAnimation* (*PixbufLoader) (GthFileData *file_data,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
GError **error);
struct _GthMain {
diff --git a/gthumb/gth-marshal.list b/gthumb/gth-marshal.list
index 6054fa7..b83cc20 100644
--- a/gthumb/gth-marshal.list
+++ b/gthumb/gth-marshal.list
@@ -4,6 +4,7 @@ VOID:INT, INT
VOID:OBJECT, BOOLEAN
VOID:OBJECT, BOXED, ENUM
VOID:OBJECT, OBJECT
+VOID:OBJECT, OBJECT, POINTER
VOID:OBJECT, POINTER
VOID:OBJECT, STRING
VOID:OBJECT, UINT
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index d8eebfe..e662571 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -476,15 +476,24 @@ image_loader_ready_cb (GthImageLoader *iloader,
}
-static GdkPixbufAnimation*
+static GdkPixbufAnimation *
thumb_loader (GthFileData *file_data,
- GError **error,
- gpointer data)
+ int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer data,
+ GError **error)
{
GthThumbLoader *self = data;
GdkPixbuf *pixbuf = NULL;
GdkPixbufAnimation *animation;
+ if (original_width != NULL)
+ *original_width = -1;
+
+ if (original_height != NULL)
+ *original_height = -1;
+
animation = NULL;
if (! self->priv->loading_from_cache) {
char *uri;
@@ -498,13 +507,23 @@ thumb_loader (GthFileData *file_data,
thumbnailer = gth_main_get_pixbuf_loader (gth_file_data_get_mime_type (file_data));
if (thumbnailer != NULL)
- animation = thumbnailer (file_data, self->priv->cache_max_size, error);
+ animation = thumbnailer (file_data,
+ self->priv->cache_max_size,
+ original_width,
+ original_height,
+ NULL,
+ error);
}
g_free (uri);
}
else
- pixbuf = gth_pixbuf_new_from_file (file_data, -1, error);
+ pixbuf = gth_pixbuf_new_from_file (file_data,
+ -1,
+ original_width,
+ original_height,
+ FALSE,
+ error);
if (pixbuf != NULL) {
g_clear_error (error);
@@ -548,7 +567,7 @@ gth_thumb_loader_new (int size)
void
gth_thumb_loader_set_loader (GthThumbLoader *self,
- LoaderFunc loader)
+ PixbufLoader loader)
{
if (loader != NULL)
gth_image_loader_set_loader (self->priv->iloader, loader, self);
diff --git a/gthumb/gth-thumb-loader.h b/gthumb/gth-thumb-loader.h
index c2c2b2a..e92feb5 100644
--- a/gthumb/gth-thumb-loader.h
+++ b/gthumb/gth-thumb-loader.h
@@ -60,7 +60,7 @@ struct _GthThumbLoaderClass
GType gth_thumb_loader_get_type (void);
GthThumbLoader * gth_thumb_loader_new (int size);
void gth_thumb_loader_set_loader (GthThumbLoader *self,
- LoaderFunc loader);
+ PixbufLoader loader);
void gth_thumb_loader_set_requested_size (GthThumbLoader *self,
int size);
int gth_thumb_loader_get_requested_size (GthThumbLoader *self);
diff --git a/gthumb/gth-viewer-page.c b/gthumb/gth-viewer-page.c
index fc03671..4cc9c94 100644
--- a/gthumb/gth-viewer-page.c
+++ b/gthumb/gth-viewer-page.c
@@ -20,8 +20,10 @@
*/
#include <config.h>
+#include "gth-marshal.h"
#include "gth-viewer-page.h"
+
enum {
FILE_LOADED,
LAST_SIGNAL
@@ -44,9 +46,10 @@ gth_viewer_page_base_init (gpointer g_iface)
G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GthViewerPageIface, file_loaded),
NULL, NULL,
- g_cclosure_marshal_VOID__BOOLEAN,
+ gth_marshal_VOID__OBJECT_BOOLEAN,
G_TYPE_NONE,
- 1,
+ 2,
+ G_TYPE_OBJECT,
G_TYPE_BOOLEAN);
initialized = TRUE;
@@ -191,7 +194,8 @@ gth_viewer_page_revert (GthViewerPage *self)
void
gth_viewer_page_file_loaded (GthViewerPage *self,
+ GthFileData *file_data,
gboolean success)
{
- g_signal_emit (self, gth_viewer_page_signals[FILE_LOADED], 0, success);
+ g_signal_emit (self, gth_viewer_page_signals[FILE_LOADED], 0, file_data, success);
}
diff --git a/gthumb/gth-viewer-page.h b/gthumb/gth-viewer-page.h
index ec3adec..70611d2 100644
--- a/gthumb/gth-viewer-page.h
+++ b/gthumb/gth-viewer-page.h
@@ -74,6 +74,7 @@ struct _GthViewerPageIface {
/*< signals >*/
void (*file_loaded) (GthViewerPage *self,
+ GthFileData *file_data,
gboolean success);
};
@@ -103,6 +104,7 @@ void gth_viewer_page_save_as (GthViewerPage *self,
gpointer data);
void gth_viewer_page_revert (GthViewerPage *self);
void gth_viewer_page_file_loaded (GthViewerPage *self,
+ GthFileData *file_data,
gboolean success);
G_END_DECLS
diff --git a/gthumb/pixbuf-io.c b/gthumb/pixbuf-io.c
index ca66296..37d54a8 100644
--- a/gthumb/pixbuf-io.c
+++ b/gthumb/pixbuf-io.c
@@ -30,6 +30,7 @@
#include "gth-main.h"
#include "gth-pixbuf-saver.h"
#include "pixbuf-io.h"
+#include "pixbuf-utils.h"
char *
@@ -219,38 +220,59 @@ _gdk_pixbuf_save_async (GdkPixbuf *pixbuf,
}
-GdkPixbuf*
+GdkPixbuf *
gth_pixbuf_new_from_file (GthFileData *file_data,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gboolean scale_to_original,
GError **error)
{
GdkPixbuf *pixbuf = NULL;
char *path;
gboolean scale_pixbuf;
+ int original_w;
+ int original_h;
+
+ if (original_width != NULL)
+ *original_width = -1;
+
+ if (original_height != NULL)
+ *original_height = -1;
if (file_data == NULL)
return NULL;
path = g_file_get_path (file_data->file);
+ if (path == NULL)
+ return NULL;
scale_pixbuf = FALSE;
+ original_w = -1;
+ original_h = -1;
if (requested_size > 0) {
- int w, h;
-
- if (gdk_pixbuf_get_file_info (path, &w, &h) == NULL) {
- w = -1;
- h = -1;
+ if (gdk_pixbuf_get_file_info (path, &original_w, &original_h) == NULL) {
+ original_w = -1;
+ original_h = -1;
}
- if ((w > requested_size) || (h > requested_size))
+ if ((original_w > requested_size) || (original_h > requested_size))
scale_pixbuf = TRUE;
}
- if (scale_pixbuf)
+ if (scale_pixbuf) {
pixbuf = gdk_pixbuf_new_from_file_at_scale (path,
requested_size,
requested_size,
TRUE,
error);
+ if (scale_to_original) {
+ GdkPixbuf *tmp;
+
+ tmp = _gdk_pixbuf_scale_simple_safe (pixbuf, original_w, original_h, GDK_INTERP_NEAREST);
+ g_object_unref (pixbuf);
+ pixbuf = tmp;
+ }
+ }
else
pixbuf = gdk_pixbuf_new_from_file (path, error);
@@ -264,15 +286,24 @@ gth_pixbuf_new_from_file (GthFileData *file_data,
}
}
+ if (original_width != NULL)
+ *original_width = original_w;
+
+ if (original_height != NULL)
+ *original_height = original_h;
+
g_free (path);
return pixbuf;
}
-GdkPixbufAnimation*
+GdkPixbufAnimation *
gth_pixbuf_animation_new_from_file (GthFileData *file_data,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
GError **error)
{
GdkPixbufAnimation *animation = NULL;
@@ -297,6 +328,9 @@ gth_pixbuf_animation_new_from_file (GthFileData *file_data,
pixbuf = gth_pixbuf_new_from_file (file_data,
requested_size,
+ original_width,
+ original_height,
+ FALSE,
error);
if (pixbuf != NULL) {
diff --git a/gthumb/pixbuf-io.h b/gthumb/pixbuf-io.h
index 1fb7fca..f437e1c 100644
--- a/gthumb/pixbuf-io.h
+++ b/gthumb/pixbuf-io.h
@@ -58,10 +58,16 @@ void _gdk_pixbuf_save_async (GdkPixbuf *pixbuf,
gpointer data);
GdkPixbuf * gth_pixbuf_new_from_file (GthFileData *file,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gboolean scale_to_original,
GError **error);
GdkPixbufAnimation*
gth_pixbuf_animation_new_from_file (GthFileData *file_data,
int requested_size,
+ int *original_width,
+ int *original_height,
+ gpointer user_data,
GError **error);
G_END_DECLS
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]