[gthumb] Use a cairo_surface to store thumbnails



commit 03200b8ca91c73e2f0736ca2996f6d992e8b715b
Author: Paolo Bacchilega <paobac src gnome org>
Date:   Mon Jun 24 21:55:16 2013 +0200

    Use a cairo_surface to store thumbnails
    
    this avoids to converts the GdkPixbuf to a cairo_surface
    each time a thumbnail is drawn on the screen.

 extensions/file_viewer/gth-file-viewer-page.c |   15 ++-
 extensions/list_tools/gth-script.c            |   13 ++-
 gthumb/cairo-utils.c                          |    6 +
 gthumb/cairo-utils.h                          |    5 +
 gthumb/gth-file-list.c                        |   93 +++++++++---------
 gthumb/gth-file-store.c                       |   53 +++++-----
 gthumb/gth-file-store.h                       |    4 +-
 gthumb/gth-grid-view.c                        |   68 +++++++------
 gthumb/gth-icon-cache.c                       |   49 ++++++++--
 gthumb/gth-icon-cache.h                       |   23 +++--
 gthumb/gth-thumb-loader.c                     |  126 ++++++++++++++-----------
 gthumb/gth-thumb-loader.h                     |    2 +-
 12 files changed, 267 insertions(+), 190 deletions(-)
---
diff --git a/extensions/file_viewer/gth-file-viewer-page.c b/extensions/file_viewer/gth-file-viewer-page.c
index 0da4ef7..4a1a32b 100644
--- a/extensions/file_viewer/gth-file-viewer-page.c
+++ b/extensions/file_viewer/gth-file-viewer-page.c
@@ -220,19 +220,26 @@ thumb_loader_ready_cb (GObject      *source_object,
        ViewData          *view_data = user_data;
        GthFileViewerPage *self = view_data->self;
        gboolean           success;
-       GdkPixbuf         *pixbuf = NULL;
+       cairo_surface_t   *image = NULL;
 
        success = gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
                                                result,
-                                               &pixbuf,
+                                               &image,
                                                NULL);
        if (g_file_equal (self->priv->file_data->file, view_data->file_data->file)) {
-               if (success)
+               if (success) {
+                       GdkPixbuf *pixbuf;
+
+                       pixbuf = _gdk_pixbuf_new_from_cairo_surface (image);
                        gtk_image_set_from_pixbuf (GTK_IMAGE (self->priv->icon), pixbuf);
+
+                       _g_object_unref (pixbuf);
+               }
+
                gth_viewer_page_file_loaded (GTH_VIEWER_PAGE (self), self->priv->file_data, TRUE);
        }
 
-       _g_object_unref (pixbuf);
+       cairo_surface_destroy (image);
        view_data_free (view_data);
 }
 
diff --git a/extensions/list_tools/gth-script.c b/extensions/list_tools/gth-script.c
index 0dce0de..74defbf 100644
--- a/extensions/list_tools/gth-script.c
+++ b/extensions/list_tools/gth-script.c
@@ -562,20 +562,25 @@ thumb_loader_ready_cb (GObject      *source_object,
                       GAsyncResult *result,
                       gpointer      user_data)
 {
-       GtkBuilder *builder = user_data;
-       GdkPixbuf  *pixbuf;
+       GtkBuilder      *builder = user_data;
+       cairo_surface_t *image;
 
        if (! gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
                                            result,
-                                           &pixbuf,
+                                           &image,
                                            NULL))
        {
                return;
        }
 
-       if (pixbuf != NULL) {
+       if (image != NULL) {
+               GdkPixbuf *pixbuf;
+
+               pixbuf = _gdk_pixbuf_new_from_cairo_surface (image);
                gtk_image_set_from_pixbuf (GTK_IMAGE (_gtk_builder_get_widget (builder, "request_image")), 
pixbuf);
+
                g_object_unref (pixbuf);
+               cairo_surface_destroy (image);
        }
 
        g_object_unref (builder);
diff --git a/gthumb/cairo-utils.c b/gthumb/cairo-utils.c
index de9a1e0..ae99a12 100644
--- a/gthumb/cairo-utils.c
+++ b/gthumb/cairo-utils.c
@@ -25,6 +25,12 @@
 #include "cairo-utils.h"
 
 
+G_DEFINE_BOXED_TYPE (GthCairoSurface,
+                    gth_cairo_surface,
+                    (GBoxedCopyFunc) cairo_surface_reference,
+                    (GBoxedFreeFunc) cairo_surface_destroy)
+
+
 const unsigned char cairo_channel[4] = { CAIRO_RED, CAIRO_GREEN, CAIRO_BLUE, CAIRO_ALPHA };
 
 
diff --git a/gthumb/cairo-utils.h b/gthumb/cairo-utils.h
index 92e3dad..d3c0ea4 100644
--- a/gthumb/cairo-utils.h
+++ b/gthumb/cairo-utils.h
@@ -118,6 +118,11 @@
 
 /* types */
 
+typedef cairo_surface_t GthCairoSurface;
+
+GType gth_cairo_surface_get_type (void);
+#define GTH_TYPE_CAIRO_SURFACE (gth_cairo_surface_get_type ())
+
 typedef struct {
        guchar r;
        guchar g;
diff --git a/gthumb/gth-file-list.c b/gthumb/gth-file-list.c
index 847705d..29ee78b 100644
--- a/gthumb/gth-file-list.c
+++ b/gthumb/gth-file-list.c
@@ -86,7 +86,7 @@ typedef struct {
                                  * image. */
        guint thumb_created : 1; /* Whether a thumb has been
                                  * created for this image. */
-       GdkPixbuf *pixbuf;
+       cairo_surface_t *image;
 } ThumbData;
 
 
@@ -415,7 +415,7 @@ thumb_data_unref (ThumbData *data)
        data->ref--;
        if (data->ref > 0)
                return;
-       _g_object_unref (data->pixbuf);
+       cairo_surface_destroy (data->image);
        g_free (data);
 }
 
@@ -888,11 +888,11 @@ gfl_add_files (GthFileList *file_list,
 
        cache_base_uri = g_strconcat (get_home_uri (), "/.thumbnails", NULL);
        for (scan = files; scan; scan = scan->next) {
-               GthFileData *file_data = scan->data;
-               char        *uri;
-               ThumbData   *thumb_data;
-               GIcon       *icon;
-               GdkPixbuf   *pixbuf = NULL;
+               GthFileData     *file_data = scan->data;
+               char            *uri;
+               ThumbData       *thumb_data;
+               GIcon           *icon;
+               cairo_surface_t *image = NULL;
 
                if (g_file_info_get_file_type (file_data->info) != G_FILE_TYPE_REGULAR)
                        continue;
@@ -912,14 +912,13 @@ gfl_add_files (GthFileList *file_list,
                                     thumb_data);
 
                icon = g_file_info_get_icon (file_data->info);
-               pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+               image = gth_icon_cache_get_surface (file_list->priv->icon_cache, icon);
                gth_file_store_queue_add (file_store,
                                          file_data,
-                                         pixbuf,
+                                         image,
                                          TRUE);
 
-               if (pixbuf != NULL)
-                       g_object_unref (pixbuf);
+               cairo_surface_destroy (image);
                g_free (uri);
        }
        g_free (cache_base_uri);
@@ -1239,10 +1238,10 @@ gfl_enable_thumbs (GthFileList *file_list,
        file_store = (GthFileStore*) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
        if (gth_file_store_get_first (file_store, &iter)) {
                do {
-                       GthFileData *file_data;
-                       ThumbData   *thumb_data;
-                       GIcon       *icon;
-                       GdkPixbuf   *pixbuf;
+                       GthFileData     *file_data;
+                       ThumbData       *thumb_data;
+                       GIcon           *icon;
+                       cairo_surface_t *image;
 
                        file_data = gth_file_store_get_file (file_store, &iter);
 
@@ -1251,14 +1250,14 @@ gfl_enable_thumbs (GthFileList *file_list,
                        thumb_data->thumb_loaded = FALSE;
 
                        icon = g_file_info_get_icon (file_data->info);
-                       pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+                       image = gth_icon_cache_get_surface (file_list->priv->icon_cache, icon);
                        gth_file_store_queue_set (file_store,
                                                  &iter,
-                                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+                                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, image,
                                                  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
                                                  -1);
 
-                       _g_object_unref (pixbuf);
+                       cairo_surface_destroy (image);
                }
                while (gth_file_store_get_next (file_store, &iter));
 
@@ -1476,12 +1475,12 @@ update_thumb_in_file_view (GthFileList *file_list,
        if (thumb_data == NULL)
                return;
 
-       if (thumb_data->pixbuf == NULL)
+       if (thumb_data->image == NULL)
                return;
 
        gth_file_store_queue_set (file_store,
                                  &iter,
-                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, thumb_data->pixbuf,
+                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, thumb_data->image,
                                  GTH_FILE_STORE_IS_ICON_COLUMN, FALSE,
                                  -1);
        queue_flash_updates (file_list);
@@ -1493,25 +1492,25 @@ set_mime_type_icon (GthFileList *file_list,
                    GthFileData *file_data,
                    int          try_pos)
 {
-       GthFileStore *file_store;
-       GtkTreeIter   iter;
-       GIcon        *icon;
-       GdkPixbuf    *pixbuf;
+       GthFileStore    *file_store;
+       GtkTreeIter      iter;
+       GIcon           *icon;
+       cairo_surface_t *image;
 
        file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
        if (! get_file_data_iter_with_suggested_pos (file_store, file_data, try_pos, &iter))
                return;
 
        icon = g_file_info_get_icon (file_data->info);
-       pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+       image = gth_icon_cache_get_surface (file_list->priv->icon_cache, icon);
        gth_file_store_queue_set (file_store,
                                  &iter,
-                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, image,
                                  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
                                  -1);
        queue_flash_updates (file_list);
 
-       _g_object_unref (pixbuf);
+       cairo_surface_destroy (image);
 }
 
 
@@ -1520,37 +1519,37 @@ thumbnail_job_ready_cb (GObject      *source_object,
                        GAsyncResult *result,
                        gpointer      user_data)
 {
-       ThumbnailJob *job = user_data;
-       GthFileList  *file_list = job->file_list;
-       gboolean      success;
-       GdkPixbuf    *pixbuf = NULL;
-       GError       *error = NULL;
-       ThumbData    *thumb_data;
+       ThumbnailJob    *job = user_data;
+       GthFileList     *file_list = job->file_list;
+       gboolean         success;
+       cairo_surface_t *image = NULL;
+       GError          *error = NULL;
+       ThumbData       *thumb_data;
 
        success = gth_thumb_loader_load_finish (GTH_THUMB_LOADER (source_object),
                                                result,
-                                               &pixbuf,
+                                               &image,
                                                &error);
        job->started = FALSE;
 
        if ((! success && g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
            || file_list->priv->cancelling)
        {
-               _g_object_unref (pixbuf);
+               cairo_surface_destroy (image);
                thumbnail_job_free (job);
                return;
        }
 
        thumb_data = g_hash_table_lookup (file_list->priv->thumb_data, job->file_data->file);
        if (thumb_data == NULL) {
-               _g_object_unref (pixbuf);
+               cairo_surface_destroy (image);
                thumbnail_job_free (job);
                _gth_file_list_update_next_thumb (file_list);
                return;
        }
 
-       _g_object_unref (thumb_data->pixbuf);
-       thumb_data->pixbuf = NULL;
+       cairo_surface_destroy (thumb_data->image);
+       thumb_data->image = NULL;
 
        if (! success) {
                thumb_data->thumb_created = FALSE;
@@ -1561,7 +1560,7 @@ thumbnail_job_ready_cb (GObject      *source_object,
                thumb_data->error = TRUE;
        }
        else {
-               thumb_data->pixbuf = g_object_ref (pixbuf);
+               thumb_data->image = cairo_surface_reference (image);
                thumb_data->thumb_created = TRUE;
                thumb_data->error = FALSE;
                if (job->update_in_view) {
@@ -1570,7 +1569,7 @@ thumbnail_job_ready_cb (GObject      *source_object,
                }
        }
 
-       _g_object_unref (pixbuf);
+       cairo_surface_destroy (image);
        thumbnail_job_free (job);
 
        _gth_file_list_update_next_thumb (file_list);
@@ -1582,25 +1581,25 @@ set_loading_icon (GthFileList *file_list,
                  GthFileData *file_data,
                  int          try_pos)
 {
-       GthFileStore *file_store;
-       GtkTreeIter   iter;
-       GIcon        *icon;
-       GdkPixbuf    *pixbuf;
+       GthFileStore    *file_store;
+       GtkTreeIter      iter;
+       GIcon           *icon;
+       cairo_surface_t *image;
 
        file_store = (GthFileStore *) gth_file_view_get_model (GTH_FILE_VIEW (file_list->priv->view));
        if (! get_file_data_iter_with_suggested_pos (file_store, file_data, try_pos, &iter))
                return;
 
        icon = g_themed_icon_new ("image-loading");
-       pixbuf = gth_icon_cache_get_pixbuf (file_list->priv->icon_cache, icon);
+       image = gth_icon_cache_get_surface (file_list->priv->icon_cache, icon);
        gth_file_store_queue_set (file_store,
                                  &iter,
-                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, pixbuf,
+                                 GTH_FILE_STORE_THUMBNAIL_COLUMN, image,
                                  GTH_FILE_STORE_IS_ICON_COLUMN, TRUE,
                                  -1);
        queue_flash_updates (file_list);
 
-       _g_object_unref (pixbuf);
+       cairo_surface_destroy (image);
        g_object_unref (icon);
 }
 
diff --git a/gthumb/gth-file-store.c b/gthumb/gth-file-store.c
index 5a23416..bc5c30b 100644
--- a/gthumb/gth-file-store.c
+++ b/gthumb/gth-file-store.c
@@ -21,6 +21,7 @@
 
 #include <config.h>
 #include <glib/gi18n.h>
+#include "cairo-utils.h"
 #include "glib-utils.h"
 #include "gth-file-store.h"
 #include "gth-marshal.h"
@@ -44,11 +45,10 @@ static guint gth_file_store_signals[LAST_SIGNAL] = { 0 };
 
 
 typedef struct {
-       int          ref_count;
-
-       GthFileData *file_data;
-       GdkPixbuf   *thumbnail;
-       gboolean     is_icon : 1;
+       int              ref_count;
+       GthFileData     *file_data;
+       cairo_surface_t *thumbnail;
+       gboolean         is_icon : 1;
 
        /*< private >*/
 
@@ -115,13 +115,13 @@ _gth_file_row_set_file (GthFileRow  *row,
 
 
 static void
-_gth_file_row_set_thumbnail (GthFileRow *row,
-                            GdkPixbuf  *thumbnail)
+_gth_file_row_set_thumbnail (GthFileRow      *row,
+                            cairo_surface_t *thumbnail)
 {
        if (thumbnail != NULL) {
-               g_object_ref (thumbnail);
+               cairo_surface_reference (thumbnail);
                if (row->thumbnail != NULL)
-                       g_object_unref (row->thumbnail);
+                       cairo_surface_destroy (row->thumbnail);
                row->thumbnail = thumbnail;
        }
 }
@@ -162,7 +162,7 @@ _gth_file_row_unref (GthFileRow *row)
        if (row->file_data != NULL)
                g_object_unref (row->file_data);
        if (row->thumbnail != NULL)
-               g_object_unref (row->thumbnail);
+               cairo_surface_destroy (row->thumbnail);
        g_free (row);
 }
 
@@ -263,7 +263,7 @@ gth_file_store_init (GthFileStore *file_store)
 
        if (column_type[0] == G_TYPE_INVALID) {
                column_type[GTH_FILE_STORE_FILE_DATA_COLUMN] = GTH_TYPE_FILE_DATA;
-               column_type[GTH_FILE_STORE_THUMBNAIL_COLUMN] = GDK_TYPE_PIXBUF;
+               column_type[GTH_FILE_STORE_THUMBNAIL_COLUMN] = GTH_TYPE_CAIRO_SURFACE;
                column_type[GTH_FILE_STORE_IS_ICON_COLUMN] = G_TYPE_BOOLEAN;
                column_type[GTH_FILE_STORE_EMBLEMS_COLUMN] = GTH_TYPE_STRING_LIST;
        }
@@ -370,8 +370,8 @@ gth_file_store_get_value (GtkTreeModel *tree_model,
                g_value_set_object (value, row->file_data);
                break;
        case GTH_FILE_STORE_THUMBNAIL_COLUMN:
-               g_value_init (value, GDK_TYPE_PIXBUF);
-               g_value_set_object (value, row->thumbnail);
+               g_value_init (value, GTH_TYPE_CAIRO_SURFACE);
+               g_value_set_boxed (value, row->thumbnail);
                break;
        case GTH_FILE_STORE_IS_ICON_COLUMN:
                g_value_init (value, G_TYPE_BOOLEAN);
@@ -1350,11 +1350,11 @@ gth_file_store_get_prev_visible (GthFileStore *file_store,
 
 
 void
-gth_file_store_add (GthFileStore *file_store,
-                   GthFileData  *file,
-                   GdkPixbuf    *thumbnail,
-                   gboolean      is_icon,
-                   int           position)
+gth_file_store_add (GthFileStore    *file_store,
+                   GthFileData     *file,
+                   cairo_surface_t *thumbnail,
+                   gboolean         is_icon,
+                   int              position)
 {
        gth_file_store_queue_add (file_store, file, thumbnail, is_icon);
        gth_file_store_exec_add (file_store, position);
@@ -1362,10 +1362,10 @@ gth_file_store_add (GthFileStore *file_store,
 
 
 void
-gth_file_store_queue_add (GthFileStore *file_store,
-                         GthFileData  *file,
-                         GdkPixbuf    *thumbnail,
-                         gboolean      is_icon)
+gth_file_store_queue_add (GthFileStore    *file_store,
+                         GthFileData     *file,
+                         cairo_surface_t *thumbnail,
+                         gboolean         is_icon)
 {
        GthFileRow *row;
 
@@ -1403,9 +1403,9 @@ gth_file_store_queue_set_valist (GthFileStore *file_store,
 
        column = va_arg (var_args, int);
        while (column != -1) {
-               GthFileData   *file_data;
-               GdkPixbuf     *thumbnail;
-               GthStringList *string_list;
+               GthFileData     *file_data;
+               cairo_surface_t *thumbnail;
+               GthStringList   *string_list;
 
                switch (column) {
                case GTH_FILE_STORE_FILE_DATA_COLUMN:
@@ -1416,8 +1416,7 @@ gth_file_store_queue_set_valist (GthFileStore *file_store,
                        file_store->priv->update_filter = TRUE;
                        break;
                case GTH_FILE_STORE_THUMBNAIL_COLUMN:
-                       thumbnail = va_arg (var_args, GdkPixbuf *);
-                       g_return_if_fail (GDK_IS_PIXBUF (thumbnail));
+                       thumbnail = va_arg (var_args, cairo_surface_t *);
                        _gth_file_row_set_thumbnail (row, thumbnail);
                        row->changed = TRUE;
                        break;
diff --git a/gthumb/gth-file-store.h b/gthumb/gth-file-store.h
index b4db381..543de31 100644
--- a/gthumb/gth-file-store.h
+++ b/gthumb/gth-file-store.h
@@ -100,12 +100,12 @@ gboolean        gth_file_store_get_prev_visible  (GthFileStore         *file_sto
                                                  GtkTreeIter          *iter);
 void            gth_file_store_add               (GthFileStore         *file_store,
                                                  GthFileData          *file,
-                                                 GdkPixbuf            *thumbnail,
+                                                 cairo_surface_t      *thumbnail,
                                                  gboolean              is_icon,
                                                  int                   position);
 void            gth_file_store_queue_add         (GthFileStore         *file_store,
                                                  GthFileData          *file,
-                                                 GdkPixbuf            *thumbnail,
+                                                 cairo_surface_t      *thumbnail,
                                                  gboolean              is_icon);
 void            gth_file_store_exec_add          (GthFileStore         *file_store,
                                                  int                   position);
diff --git a/gthumb/gth-grid-view.c b/gthumb/gth-grid-view.c
index 8865e67..9d34055 100644
--- a/gthumb/gth-grid-view.c
+++ b/gthumb/gth-grid-view.c
@@ -108,7 +108,7 @@ typedef struct {
 
        guint                  ref;
        GthFileData           *file_data;
-       GdkPixbuf             *thumbnail;
+       cairo_surface_t       *thumbnail;
        gboolean               is_icon : 1;
        char                  *caption;
        gboolean               is_image : 1;
@@ -230,14 +230,14 @@ gth_grid_view_item_set_file_data (GthGridViewItem *item,
 
 static void
 gth_grid_view_item_set_thumbnail (GthGridViewItem *item,
-                                 GdkPixbuf       *thumbnail)
+                                 cairo_surface_t *thumbnail)
 {
-       _g_object_unref (item->thumbnail);
-       item->thumbnail = _g_object_ref (thumbnail);
+       cairo_surface_destroy (item->thumbnail);
+       item->thumbnail = cairo_surface_reference (thumbnail);
 
        if (item->thumbnail != NULL) {
-               item->pixbuf_area.width = gdk_pixbuf_get_width (item->thumbnail);
-               item->pixbuf_area.height = gdk_pixbuf_get_height (item->thumbnail);
+               item->pixbuf_area.width = cairo_image_surface_get_width (item->thumbnail);
+               item->pixbuf_area.height = cairo_image_surface_get_height (item->thumbnail);
        }
        else {
                item->pixbuf_area.width = 0;
@@ -312,11 +312,11 @@ gth_grid_view_item_update_caption (GthGridViewItem  *item,
 
 
 static GthGridViewItem *
-gth_grid_view_item_new (GthGridView  *grid_view,
-                       GthFileData  *file_data,
-                       GdkPixbuf    *thumbnail,
-                       gboolean      is_icon,
-                       char        **attributes_v)
+gth_grid_view_item_new (GthGridView      *grid_view,
+                       GthFileData      *file_data,
+                       cairo_surface_t  *thumbnail,
+                       gboolean          is_icon,
+                       char            **attributes_v)
 {
        GthGridViewItem *item;
 
@@ -347,7 +347,7 @@ gth_grid_view_item_unref (GthGridViewItem *item)
                return;
 
        g_free (item->caption);
-       _g_object_unref (item->thumbnail);
+       cairo_surface_destroy (item->thumbnail);
        _g_object_unref (item->file_data);
        g_free (item);
 }
@@ -1270,18 +1270,18 @@ _gth_grid_view_item_draw_thumbnail (GthGridViewItem *item,
                                    GtkStateFlags    item_state,
                                    GthGridView     *grid_view)
 {
-       GdkPixbuf             *pixbuf;
+       cairo_surface_t       *image;
        GtkStyleContext       *style_context;
        cairo_rectangle_int_t  frame_rect;
        GdkRGBA                background_color;
        GdkRGBA                lighter_color;
        GdkRGBA                darker_color;
 
-       pixbuf = item->thumbnail;
-       if (pixbuf == NULL)
+       image = item->thumbnail;
+       if (image == NULL)
                return;
 
-       g_object_ref (pixbuf);
+       cairo_surface_reference (image);
 
        cairo_save (cr);
        style_context = gtk_widget_get_style_context (widget);
@@ -1460,7 +1460,7 @@ _gth_grid_view_item_draw_thumbnail (GthGridViewItem *item,
 
        /* thumbnail */
 
-       gdk_cairo_set_source_pixbuf (cr, pixbuf, item->pixbuf_area.x, item->pixbuf_area.y);
+       cairo_set_source_surface (cr, image, item->pixbuf_area.x, item->pixbuf_area.y);
        cairo_rectangle (cr, item->pixbuf_area.x, item->pixbuf_area.y, item->pixbuf_area.width, 
item->pixbuf_area.height);
        cairo_fill (cr);
 
@@ -1480,7 +1480,7 @@ _gth_grid_view_item_draw_thumbnail (GthGridViewItem *item,
        gtk_style_context_restore (style_context);
        cairo_restore (cr);
 
-       g_object_unref (pixbuf);
+       cairo_surface_destroy (image);
 }
 
 
@@ -1538,21 +1538,25 @@ _gth_grid_view_item_draw_emblems (GthGridViewItem *item,
        emblem_offset = 0;
        emblems = (GthStringList *) g_file_info_get_attribute_object (item->file_data->info, 
GTH_FILE_ATTRIBUTE_EMBLEMS);
        for (scan = gth_string_list_get_list (emblems); scan; scan = scan->next) {
-               char      *emblem = scan->data;
-               GIcon     *icon;
-               GdkPixbuf *pixbuf;
+               char            *emblem = scan->data;
+               GIcon           *icon;
+               cairo_surface_t *image;
 
                if (grid_view->priv->icon_cache == NULL)
                        grid_view->priv->icon_cache = gth_icon_cache_new (gtk_icon_theme_get_for_screen 
(gtk_widget_get_screen (GTK_WIDGET (grid_view))), EMBLEM_SIZE);
 
                icon = g_themed_icon_new (emblem);
-               pixbuf = gth_icon_cache_get_pixbuf (grid_view->priv->icon_cache, icon);
-               if (pixbuf != NULL) {
-                       gdk_cairo_set_source_pixbuf (cr, pixbuf, item->thumbnail_area.x + emblem_offset + 1, 
item->thumbnail_area.y + 1);
-                       cairo_rectangle (cr, item->thumbnail_area.x + emblem_offset + 1, 
item->thumbnail_area.y + 1, gdk_pixbuf_get_width (pixbuf), gdk_pixbuf_get_height (pixbuf));
+               image = gth_icon_cache_get_surface (grid_view->priv->icon_cache, icon);
+               if (image != NULL) {
+                       cairo_set_source_surface (cr, image, item->thumbnail_area.x + emblem_offset + 1, 
item->thumbnail_area.y + 1);
+                       cairo_rectangle (cr,
+                                        item->thumbnail_area.x + emblem_offset + 1,
+                                        item->thumbnail_area.y + 1,
+                                        cairo_image_surface_get_width (image),
+                                        cairo_image_surface_get_height (image));
                        cairo_fill (cr);
 
-                       g_object_unref (pixbuf);
+                       cairo_surface_destroy (image);
 
                        emblem_offset += EMBLEM_SIZE + (EMBLEM_SIZE / 2);
                }
@@ -2154,7 +2158,7 @@ model_row_changed_cb (GtkTreeModel *tree_model,
        int              pos;
        GList           *link;
        GthFileData     *file_data;
-       GdkPixbuf       *thumbnail;
+       cairo_surface_t *thumbnail;
        gboolean         is_icon;
        GthGridViewItem *item;
 
@@ -2178,7 +2182,7 @@ model_row_changed_cb (GtkTreeModel *tree_model,
        _gth_grid_view_queue_relayout_from_position (self, pos);
 
        g_object_unref (file_data);
-       g_object_unref (thumbnail);
+       cairo_surface_destroy (thumbnail);
 }
 
 
@@ -2231,7 +2235,7 @@ model_row_inserted_cb (GtkTreeModel *tree_model,
 {
        GthGridView     *self = user_data;
        GthFileData     *file_data;
-       GdkPixbuf       *thumbnail;
+       cairo_surface_t *thumbnail;
        gboolean         is_icon;
        GthGridViewItem *item;
        int              pos;
@@ -2265,7 +2269,7 @@ model_row_inserted_cb (GtkTreeModel *tree_model,
        _gth_grid_view_queue_relayout_from_position (self, pos);
 
        g_object_unref (file_data);
-       g_object_unref (thumbnail);
+       cairo_surface_destroy (thumbnail);
 }
 
 
@@ -2334,7 +2338,7 @@ model_thumbnail_changed_cb (GtkTreeModel *tree_model,
        GthGridView     *self = user_data;
        int              pos;
        GList           *link;
-       GdkPixbuf       *thumbnail;
+       cairo_surface_t *thumbnail;
        gboolean         is_icon;
        GthGridViewItem *item;
 
@@ -2356,7 +2360,7 @@ model_thumbnail_changed_cb (GtkTreeModel *tree_model,
        _gth_grid_view_place_item_at (self, item, item->area.x, item->area.y);
        _gth_grid_view_queue_draw_item (self, item);
 
-       g_object_unref (thumbnail);
+       cairo_surface_destroy (thumbnail);
 }
 
 
diff --git a/gthumb/gth-icon-cache.c b/gthumb/gth-icon-cache.c
index 514c48d..1806e87 100644
--- a/gthumb/gth-icon-cache.c
+++ b/gthumb/gth-icon-cache.c
@@ -20,6 +20,8 @@
  */
 
 #include <config.h>
+#include <cairo.h>
+#include "cairo-utils.h"
 #include "glib-utils.h"
 #include "gth-icon-cache.h"
 #include "gtk-utils.h"
@@ -28,7 +30,8 @@
 struct _GthIconCache {
        GtkIconTheme *icon_theme;
        int           icon_size;
-       GHashTable   *cache;
+       GHashTable   *pixbuf_cache;
+       GHashTable   *surface_cache;
        GIcon        *fallback_icon;
 };
 
@@ -44,7 +47,8 @@ gth_icon_cache_new (GtkIconTheme *icon_theme,
        icon_cache = g_new0 (GthIconCache, 1);
        icon_cache->icon_theme = icon_theme;
        icon_cache->icon_size = icon_size;
-       icon_cache->cache = g_hash_table_new_full (g_icon_hash, (GEqualFunc) g_icon_equal, g_object_unref, 
g_object_unref);
+       icon_cache->pixbuf_cache = g_hash_table_new_full (g_icon_hash, (GEqualFunc) g_icon_equal, 
g_object_unref, g_object_unref);
+       icon_cache->surface_cache = g_hash_table_new_full (g_icon_hash, (GEqualFunc) g_icon_equal, 
g_object_unref, (GDestroyNotify) cairo_surface_destroy);
 
        return icon_cache;
 }
@@ -79,7 +83,8 @@ gth_icon_cache_free (GthIconCache *icon_cache)
 {
        if (icon_cache == NULL)
                return;
-       g_hash_table_destroy (icon_cache->cache);
+       g_hash_table_destroy (icon_cache->pixbuf_cache);
+       g_hash_table_destroy (icon_cache->surface_cache);
        if (icon_cache->fallback_icon != NULL)
                g_object_unref (icon_cache->fallback_icon);
        g_free (icon_cache);
@@ -89,8 +94,10 @@ gth_icon_cache_free (GthIconCache *icon_cache)
 void
 gth_icon_cache_clear (GthIconCache *icon_cache)
 {
-       if (icon_cache != NULL)
-               g_hash_table_remove_all (icon_cache->cache);
+       if (icon_cache == NULL)
+               return;
+       g_hash_table_remove_all (icon_cache->pixbuf_cache);
+       g_hash_table_remove_all (icon_cache->surface_cache);
 }
 
 
@@ -104,7 +111,7 @@ gth_icon_cache_get_pixbuf (GthIconCache *icon_cache,
                icon = icon_cache->fallback_icon;
 
        if (icon != NULL)
-               pixbuf = g_hash_table_lookup (icon_cache->cache, icon);
+               pixbuf = g_hash_table_lookup (icon_cache->pixbuf_cache, icon);
 
        if (pixbuf != NULL)
                return g_object_ref (pixbuf);
@@ -116,7 +123,35 @@ gth_icon_cache_get_pixbuf (GthIconCache *icon_cache,
                pixbuf = _g_icon_get_pixbuf (icon_cache->fallback_icon, icon_cache->icon_size, 
icon_cache->icon_theme);
 
        if ((icon != NULL) && (pixbuf != NULL))
-               g_hash_table_insert (icon_cache->cache, g_object_ref (icon), g_object_ref (pixbuf));
+               g_hash_table_insert (icon_cache->pixbuf_cache, g_object_ref (icon), g_object_ref (pixbuf));
 
        return pixbuf;
 }
+
+
+cairo_surface_t *
+gth_icon_cache_get_surface (GthIconCache *icon_cache,
+                           GIcon        *icon)
+{
+       cairo_surface_t *surface = NULL;
+       GdkPixbuf       *pixbuf;
+
+       if (icon == NULL)
+               icon = icon_cache->fallback_icon;
+
+       if (icon != NULL)
+               surface = g_hash_table_lookup (icon_cache->surface_cache, icon);
+
+       if (surface != NULL)
+               return cairo_surface_reference (surface);
+
+       pixbuf = gth_icon_cache_get_pixbuf (icon_cache, icon);
+       surface = _cairo_image_surface_create_from_pixbuf (pixbuf);
+
+       if ((icon != NULL) && (surface != NULL))
+               g_hash_table_insert (icon_cache->surface_cache, g_object_ref (icon), cairo_surface_reference 
(surface));
+
+       g_object_unref (pixbuf);
+
+       return surface;
+}
diff --git a/gthumb/gth-icon-cache.h b/gthumb/gth-icon-cache.h
index 2da8969..7df557b 100644
--- a/gthumb/gth-icon-cache.h
+++ b/gthumb/gth-icon-cache.h
@@ -23,21 +23,24 @@
 #define GTH_ICON_CACHE_H
 
 #include <gtk/gtk.h>
+#include <cairo.h>
 
 G_BEGIN_DECLS
 
 typedef struct _GthIconCache GthIconCache;
 
-GthIconCache * gth_icon_cache_new            (GtkIconTheme *icon_theme,
-                                             int           icon_size);
-GthIconCache * gth_icon_cache_new_for_widget (GtkWidget    *widget,
-                                             GtkIconSize   icon_size);
-void           gth_icon_cache_set_fallback   (GthIconCache *icon_cache,
-                                             GIcon        *icon);
-void           gth_icon_cache_free           (GthIconCache *icon_cache);
-void           gth_icon_cache_clear          (GthIconCache *icon_cache);
-GdkPixbuf *    gth_icon_cache_get_pixbuf     (GthIconCache *icon_cache,
-                                             GIcon        *icon);
+GthIconCache *         gth_icon_cache_new              (GtkIconTheme *icon_theme,
+                                                        int           icon_size);
+GthIconCache *         gth_icon_cache_new_for_widget   (GtkWidget    *widget,
+                                                        GtkIconSize   icon_size);
+void                   gth_icon_cache_set_fallback     (GthIconCache *icon_cache,
+                                                        GIcon        *icon);
+void                   gth_icon_cache_free             (GthIconCache *icon_cache);
+void                   gth_icon_cache_clear            (GthIconCache *icon_cache);
+GdkPixbuf *            gth_icon_cache_get_pixbuf       (GthIconCache *icon_cache,
+                                                        GIcon        *icon);
+cairo_surface_t *      gth_icon_cache_get_surface      (GthIconCache *icon_cache,
+                                                        GIcon        *icon);
 
 G_END_DECLS
 
diff --git a/gthumb/gth-thumb-loader.c b/gthumb/gth-thumb-loader.c
index f99d57a..e8638c7 100644
--- a/gthumb/gth-thumb-loader.c
+++ b/gthumb/gth-thumb-loader.c
@@ -29,6 +29,7 @@
 #define GDK_PIXBUF_ENABLE_BACKEND
 #include <gtk/gtk.h>
 #include <gdk-pixbuf/gdk-pixbuf.h>
+#include "cairo-utils.h"
 #include "gio-utils.h"
 #include "glib-utils.h"
 #define GNOME_DESKTOP_USE_UNSTABLE_API
@@ -208,9 +209,9 @@ load_cached_thumbnail (GInputStream  *istream,
                       GCancellable  *cancellable,
                       GError       **error)
 {
-       GthImage  *image = NULL;
-       char      *filename;
-       GdkPixbuf *pixbuf;
+       GthImage        *image = NULL;
+       char            *filename;
+       cairo_surface_t *surface;
 
        if (file_data == NULL) {
                if (error != NULL)
@@ -219,12 +220,13 @@ load_cached_thumbnail (GInputStream  *istream,
        }
 
        filename = g_file_get_path (file_data->file);
-       pixbuf = gdk_pixbuf_new_from_file (filename, error);
-       if (pixbuf != NULL) {
-               image = gth_image_new_for_pixbuf (pixbuf);
-               g_object_unref (pixbuf);
-       }
+       surface = cairo_image_surface_create_from_png (filename);
+       if (cairo_surface_status (surface) == CAIRO_STATUS_SUCCESS)
+               image = gth_image_new_for_surface (surface);
+       else
+               g_set_error_literal (error, G_IO_ERROR, G_IO_ERROR_FAILED, cairo_status_to_string 
(cairo_surface_status (surface)));
 
+       cairo_surface_destroy (surface);
        g_free (filename);
 
        return image;
@@ -363,8 +365,8 @@ load_data_unref (LoadData *load_data)
 
 
 typedef struct {
-       GthFileData *file_data;
-       GdkPixbuf   *pixbuf;
+       GthFileData     *file_data;
+       cairo_surface_t *image;
 } LoadResult;
 
 
@@ -372,7 +374,7 @@ static void
 load_result_unref (LoadResult *load_result)
 {
        g_object_unref (load_result->file_data);
-       _g_object_unref (load_result->pixbuf);
+       cairo_surface_destroy (load_result->image);
        g_free (load_result);
 }
 
@@ -422,14 +424,14 @@ cache_image_ready_cb (GObject      *source_object,
                      GAsyncResult *res,
                      gpointer      user_data)
 {
-       LoadData       *load_data = user_data;
-       GthThumbLoader *self = load_data->thumb_loader;
-       GthImage       *image = NULL;
-       GdkPixbuf      *pixbuf;
-       int             width;
-       int             height;
-       gboolean        modified;
-       LoadResult     *load_result;
+       LoadData        *load_data = user_data;
+       GthThumbLoader  *self = load_data->thumb_loader;
+       GthImage        *image = NULL;
+       cairo_surface_t *surface;
+       int              width;
+       int              height;
+       gboolean         modified;
+       LoadResult      *load_result;
 
        if (! gth_image_loader_load_finish (GTH_IMAGE_LOADER (source_object),
                                            res,
@@ -455,12 +457,12 @@ cache_image_ready_cb (GObject      *source_object,
        /* Thumbnail correctly loaded from the cache. Scale if the user wants
         * a different size. */
 
-       pixbuf = gth_image_get_pixbuf (image);
+       surface = gth_image_get_cairo_surface (image);
 
-       g_return_if_fail (pixbuf != NULL);
+       g_return_if_fail (surface != NULL);
 
-       width = gdk_pixbuf_get_width (pixbuf);
-       height = gdk_pixbuf_get_height (pixbuf);
+       width = cairo_image_surface_get_width (surface);
+       height = cairo_image_surface_get_height (surface);
        modified = normalize_thumb (&width,
                                    &height,
                                    self->priv->requested_size,
@@ -473,7 +475,7 @@ cache_image_ready_cb (GObject      *source_object,
 
        load_result = g_new0 (LoadResult, 1);
        load_result->file_data = g_object_ref (load_data->file_data);
-       load_result->pixbuf = pixbuf;
+       load_result->image = surface;
        g_simple_async_result_set_op_res_gpointer (load_data->simple, load_result, (GDestroyNotify) 
load_result_unref);
        g_simple_async_result_complete_in_idle (load_data->simple);
 
@@ -506,13 +508,14 @@ is_a_cache_file (const char *uri)
 
 
 static gboolean
-_gth_thumb_loader_save_to_cache (GthThumbLoader *self,
-                                GthFileData    *file_data,
-                                GdkPixbuf      *pixbuf)
+_gth_thumb_loader_save_to_cache (GthThumbLoader  *self,
+                                GthFileData     *file_data,
+                                cairo_surface_t *image)
 {
-       char  *uri;
+       char      *uri;
+       GdkPixbuf *pixbuf;
 
-       if ((self == NULL) || (pixbuf == NULL))
+       if ((self == NULL) || (image == NULL))
                return FALSE;
 
        uri = g_file_get_uri (file_data->file);
@@ -525,11 +528,17 @@ _gth_thumb_loader_save_to_cache (GthThumbLoader *self,
                return FALSE;
        }
 
+       pixbuf = _gdk_pixbuf_new_from_cairo_surface (image);
+       if (pixbuf == NULL)
+               return FALSE;
+
        gnome_desktop_thumbnail_factory_save_thumbnail (self->priv->thumb_factory,
                                                        pixbuf,
                                                        uri,
                                                        gth_file_data_get_mtime (file_data));
 
+       g_object_unref (pixbuf);
+
        return TRUE;
 }
 
@@ -537,18 +546,18 @@ _gth_thumb_loader_save_to_cache (GthThumbLoader *self,
 static void
 original_image_loaded_correctly (GthThumbLoader *self,
                                 LoadData        *load_data,
-                                GdkPixbuf       *pixbuf)
+                                cairo_surface_t *image)
 {
-       GdkPixbuf  *local_pixbuf;
-       int         width;
-       int         height;
-       gboolean    modified;
-       LoadResult *load_result;
+       cairo_surface_t *local_image;
+       int              width;
+       int              height;
+       gboolean         modified;
+       LoadResult      *load_result;
 
-       local_pixbuf = g_object_ref (pixbuf);
+       local_image = cairo_surface_reference (image);
 
-       width = gdk_pixbuf_get_width (local_pixbuf);
-       height = gdk_pixbuf_get_height (local_pixbuf);
+       width = cairo_image_surface_get_width (local_image);
+       height = cairo_image_surface_get_height (local_image);
 
        if (self->priv->save_thumbnails) {
                gboolean modified;
@@ -568,7 +577,7 @@ original_image_loaded_correctly (GthThumbLoader *self,
                        g_object_unref (tmp);
                }
 
-               _gth_thumb_loader_save_to_cache (self, load_data->file_data, local_pixbuf);
+               _gth_thumb_loader_save_to_cache (self, load_data->file_data, local_image);
        }
 
        /* Scale if the user wants a different size. */
@@ -585,11 +594,11 @@ original_image_loaded_correctly (GthThumbLoader *self,
 
        load_result = g_new0 (LoadResult, 1);
        load_result->file_data = g_object_ref (load_data->file_data);
-       load_result->pixbuf = g_object_ref (local_pixbuf);
+       load_result->image = cairo_surface_reference (local_image);
        g_simple_async_result_set_op_res_gpointer (load_data->simple, load_result, (GDestroyNotify) 
load_result_unref);
        g_simple_async_result_complete_in_idle (load_data->simple);
 
-       g_object_unref (local_pixbuf);
+       cairo_surface_destroy (local_image);
 }
 
 
@@ -698,7 +707,12 @@ watch_thumbnailer_cb (GPid     pid,
                                                                             &load_data->thumbnailer_tmpfile);
 
        if (pixbuf != NULL) {
-               original_image_loaded_correctly (self, load_data, pixbuf);
+               cairo_surface_t *surface;
+
+               surface = _cairo_image_surface_create_from_pixbuf (pixbuf);
+               original_image_loaded_correctly (self, load_data, surface);
+
+               cairo_surface_destroy (surface);
                g_object_unref (pixbuf);
        }
        else
@@ -711,11 +725,11 @@ original_image_ready_cb (GObject      *source_object,
                         GAsyncResult *res,
                         gpointer      user_data)
 {
-       LoadData       *load_data = user_data;
-       GthThumbLoader *self = load_data->thumb_loader;
-       GthImage       *image = NULL;
-       GdkPixbuf      *pixbuf = NULL;
-       GError         *error = NULL;
+       LoadData        *load_data = user_data;
+       GthThumbLoader  *self = load_data->thumb_loader;
+       GthImage        *image = NULL;
+       cairo_surface_t *surface = NULL;
+       GError          *error = NULL;
 
        if (! gth_image_loader_load_finish (GTH_IMAGE_LOADER (source_object),
                                            res,
@@ -766,10 +780,10 @@ original_image_ready_cb (GObject      *source_object,
                return;
        }
 
-       pixbuf = gth_image_get_pixbuf (image);
-       original_image_loaded_correctly (self, load_data, pixbuf);
+       surface = gth_image_get_cairo_surface (image);
+       original_image_loaded_correctly (self, load_data, surface);
 
-       g_object_unref (pixbuf);
+       cairo_surface_destroy (surface);
        g_object_unref (image);
        load_data_unref (load_data);
 }
@@ -875,10 +889,10 @@ gth_thumb_loader_load (GthThumbLoader      *self,
 
 
 gboolean
-gth_thumb_loader_load_finish (GthThumbLoader  *self,
-                             GAsyncResult    *result,
-                             GdkPixbuf      **pixbuf,
-                             GError         **error)
+gth_thumb_loader_load_finish (GthThumbLoader   *self,
+                             GAsyncResult     *result,
+                             cairo_surface_t **image,
+                             GError          **error)
 {
        GSimpleAsyncResult *simple;
        LoadResult         *load_result;
@@ -891,8 +905,8 @@ gth_thumb_loader_load_finish (GthThumbLoader  *self,
                return FALSE;
 
        load_result = g_simple_async_result_get_op_res_gpointer (simple);
-       if (pixbuf != NULL)
-               *pixbuf = _g_object_ref (load_result->pixbuf);
+       if (image != NULL)
+               *image = cairo_surface_reference (load_result->image);
 
        return TRUE;
 }
diff --git a/gthumb/gth-thumb-loader.h b/gthumb/gth-thumb-loader.h
index 56f8c21..544bf2b 100644
--- a/gthumb/gth-thumb-loader.h
+++ b/gthumb/gth-thumb-loader.h
@@ -72,7 +72,7 @@ void              gth_thumb_loader_load                 (GthThumbLoader       *s
                                                         gpointer              user_data);
 gboolean          gth_thumb_loader_load_finish          (GthThumbLoader       *self,
                                                         GAsyncResult         *res,
-                                                        GdkPixbuf           **pixbuf,
+                                                        cairo_surface_t     **image,
                                                         GError              **error);
 gboolean          gth_thumb_loader_has_valid_thumbnail  (GthThumbLoader       *self,
                                                         GthFileData          *file_data);


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]