[evince] EvSidebarThumbnails: switch to using cairo_surface_t for images



commit 0a0d99b1c6f7d42fe37b270798b60420325fdc32
Author: Owen W. Taylor <otaylor fishsoup net>
Date:   Thu Feb 27 11:37:04 2014 -0500

    EvSidebarThumbnails: switch to using cairo_surface_t for images
    
    To support high resolution thumbnails on hi-dpi displays, we need to
    use cairo surfaces instead of using GdkPixbuf for images. In preparation
    for high resolution thumbnails, switch over to cairo_surface_t. This
    adds a GTK+ 3.10 dependency.
    
    Add new:
    ev_document_misc_render_loading_thumbnail_surface()
    ev_document_misc_render_thumbnail_surface_with_frame()
    
    To avoid converting surface => pixbuf => surface.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=723431

 configure.ac                                       |    2 +-
 .../libdocument/libevdocument-sections.txt         |    2 +
 libdocument/ev-document-misc.c                     |   85 ++++++++++++++++---
 libdocument/ev-document-misc.h                     |    9 ++
 shell/ev-sidebar-thumbnails.c                      |   49 +++++++-----
 5 files changed, 113 insertions(+), 34 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f4388ae..51a4e46 100644
--- a/configure.ac
+++ b/configure.ac
@@ -118,7 +118,7 @@ dnl Specify required versions of dependencies
 CAIRO_REQUIRED=1.10.0
 GLIB_REQUIRED=2.36.0
 LIBSECRET_REQUIRED=0.5
-GTK_REQUIRED=3.8.0
+GTK_REQUIRED=3.10.0
 NAUTILUS_REQUIRED=2.91.4
 
 AC_SUBST([GLIB_REQUIRED])
diff --git a/help/reference/libdocument/libevdocument-sections.txt 
b/help/reference/libdocument/libevdocument-sections.txt
index e2f26cf..674248e 100644
--- a/help/reference/libdocument/libevdocument-sections.txt
+++ b/help/reference/libdocument/libevdocument-sections.txt
@@ -852,6 +852,8 @@ ev_document_misc_invert_pixbuf
 ev_document_misc_format_date
 ev_document_misc_render_loading_thumbnail
 ev_document_misc_render_thumbnail_with_frame
+ev_document_misc_render_loading_thumbnail_surface
+ev_document_misc_render_thumbnail_surface_with_frame
 <SUBSECTION Deprecated>
 ev_document_misc_get_loading_thumbnail
 ev_document_misc_get_page_border_size
diff --git a/libdocument/ev-document-misc.c b/libdocument/ev-document-misc.c
index f76c15c..fdc5fbb 100644
--- a/libdocument/ev-document-misc.c
+++ b/libdocument/ev-document-misc.c
@@ -126,12 +126,13 @@ ev_document_misc_get_loading_thumbnail (int      width,
        return create_thumbnail_frame (width, height, NULL, !inverted_colors);
 }
 
-static GdkPixbuf *
-ev_document_misc_render_thumbnail_frame (GtkWidget *widget,
-                                         int        width,
-                                         int        height,
-                                         gboolean   inverted_colors,
-                                         GdkPixbuf *source_pixbuf)
+static cairo_surface_t *
+ev_document_misc_render_thumbnail_frame (GtkWidget       *widget,
+                                         int              width,
+                                         int              height,
+                                         gboolean         inverted_colors,
+                                         GdkPixbuf       *source_pixbuf,
+                                         cairo_surface_t *source_surface)
 {
         GtkStyleContext *context = gtk_widget_get_style_context (widget);
         GtkStateFlags    state = gtk_widget_get_state_flags (widget);
@@ -140,7 +141,6 @@ ev_document_misc_render_thumbnail_frame (GtkWidget *widget,
         cairo_surface_t *surface;
         cairo_t         *cr;
         GtkBorder        border = {0, };
-        GdkPixbuf       *retval;
 
         if (source_pixbuf) {
                 g_return_val_if_fail (GDK_IS_PIXBUF (source_pixbuf), NULL);
@@ -164,8 +164,12 @@ ev_document_misc_render_thumbnail_frame (GtkWidget *widget,
 
         surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
                                               width_f, height_f);
+
         cr = cairo_create (surface);
-        if (source_pixbuf) {
+        if (source_surface) {
+                cairo_set_source_surface (cr, source_surface, border.left, border.top);
+                cairo_paint (cr);
+        } else if (source_pixbuf) {
                 gdk_cairo_set_source_pixbuf (cr, source_pixbuf, border.left, border.top);
                 cairo_paint (cr);
         } else {
@@ -176,10 +180,7 @@ ev_document_misc_render_thumbnail_frame (GtkWidget *widget,
 
         gtk_style_context_restore (context);
 
-        retval = gdk_pixbuf_get_from_surface (surface, 0, 0, width_f, height_f);
-        cairo_surface_destroy (surface);
-
-        return retval;
+        return surface;
 }
 
 /**
@@ -199,7 +200,34 @@ ev_document_misc_render_loading_thumbnail (GtkWidget *widget,
                                            int        height,
                                            gboolean   inverted_colors)
 {
-        return ev_document_misc_render_thumbnail_frame (widget, width, height, inverted_colors, NULL);
+        GdkPixbuf *retval;
+        cairo_surface_t *surface;
+
+        surface = ev_document_misc_render_thumbnail_frame (widget, width, height, inverted_colors, NULL, 
NULL);
+        retval = gdk_pixbuf_get_from_surface (surface, 0, 0, width, height);
+        cairo_surface_destroy (surface);
+
+        return retval;
+}
+
+/**
+ * ev_document_misc_render_loading_thumbnail_surface:
+ * @widget: a #GtkWidget to use for style information
+ * @width: the desired width
+ * @height: the desired height
+ * @inverted_colors: whether to invert colors
+ *
+ * Returns: (transfer full): a #cairo_surface_t
+ *
+ * Since: 3.14
+ */
+cairo_surface_t *
+ev_document_misc_render_loading_thumbnail_surface (GtkWidget *widget,
+                                                   int        width,
+                                                   int        height,
+                                                   gboolean   inverted_colors)
+{
+        return ev_document_misc_render_thumbnail_frame (widget, width, height, inverted_colors, NULL, NULL);
 }
 
 /**
@@ -215,7 +243,36 @@ GdkPixbuf *
 ev_document_misc_render_thumbnail_with_frame (GtkWidget *widget,
                                               GdkPixbuf *source_pixbuf)
 {
-        return ev_document_misc_render_thumbnail_frame (widget, -1, -1, FALSE, source_pixbuf);
+        GdkPixbuf *retval;
+        cairo_surface_t *surface;
+
+        surface = ev_document_misc_render_thumbnail_frame (widget, -1, -1, FALSE, source_pixbuf, NULL);
+        retval = gdk_pixbuf_get_from_surface (surface, 0, 0,
+                                              cairo_image_surface_get_width (surface),
+                                              cairo_image_surface_get_height (surface));
+        cairo_surface_destroy (surface);
+
+        return retval;
+}
+
+/**
+ * ev_document_misc_render_thumbnail_surface_with_frame:
+ * @widget: a #GtkWidget to use for style information
+ * @source_surface: a #cairo_surface_t
+ * @width: the desired width
+ * @height: the desired height
+ *
+ * Returns: (transfer full): a #cairo_surface_t
+ *
+ * Since: 3.14
+ */
+cairo_surface_t *
+ev_document_misc_render_thumbnail_surface_with_frame (GtkWidget       *widget,
+                                                      cairo_surface_t *source_surface,
+                                                      int              width,
+                                                      int              height)
+{
+        return ev_document_misc_render_thumbnail_frame (widget, width, height, FALSE, NULL, source_surface);
 }
 
 void
diff --git a/libdocument/ev-document-misc.h b/libdocument/ev-document-misc.h
index ac59682..566d594 100644
--- a/libdocument/ev-document-misc.h
+++ b/libdocument/ev-document-misc.h
@@ -50,6 +50,15 @@ GdkPixbuf *ev_document_misc_render_loading_thumbnail    (GtkWidget *widget,
 GdkPixbuf *ev_document_misc_render_thumbnail_with_frame (GtkWidget *widget,
                                                         GdkPixbuf *source_pixbuf);
 
+cairo_surface_t *ev_document_misc_render_loading_thumbnail_surface (GtkWidget *widget,
+                                                                   int        width,
+                                                                   int        height,
+                                                                   gboolean   inverted_colors);
+cairo_surface_t *ev_document_misc_render_thumbnail_surface_with_frame (GtkWidget       *widget,
+                                                                      cairo_surface_t *source_surface,
+                                                                      int              width,
+                                                                      int              height);
+
 EV_DEPRECATED
 void       ev_document_misc_get_page_border_size (gint          page_width,
                                                  gint          page_height,
diff --git a/shell/ev-sidebar-thumbnails.c b/shell/ev-sidebar-thumbnails.c
index 181e12b..d747d79 100644
--- a/shell/ev-sidebar-thumbnails.c
+++ b/shell/ev-sidebar-thumbnails.c
@@ -31,6 +31,8 @@
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 
+#include <cairo-gobject.h>
+
 #include "ev-document-misc.h"
 #include "ev-job-scheduler.h"
 #include "ev-sidebar-page.h"
@@ -80,7 +82,7 @@ struct _EvSidebarThumbnailsPrivate {
 
 enum {
        COLUMN_PAGE_STRING,
-       COLUMN_PIXBUF,
+       COLUMN_SURFACE,
        COLUMN_THUMBNAIL_SET,
        COLUMN_JOB,
        NUM_COLUMNS
@@ -371,14 +373,14 @@ ev_sidebar_thumbnails_new (void)
        return ev_sidebar_thumbnails;
 }
 
-static GdkPixbuf *
+static cairo_surface_t *
 ev_sidebar_thumbnails_get_loading_icon (EvSidebarThumbnails *sidebar_thumbnails,
                                        gint                 width,
                                        gint                 height)
 {
        EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
-       GdkPixbuf *icon;
-       gchar     *key;
+        cairo_surface_t *icon;
+       gchar           *key;
 
        key = g_strdup_printf ("%dx%d", width, height);
        icon = g_hash_table_lookup (priv->loading_icons, key);
@@ -386,8 +388,9 @@ ev_sidebar_thumbnails_get_loading_icon (EvSidebarThumbnails *sidebar_thumbnails,
                gboolean inverted_colors;
 
                inverted_colors = ev_document_model_get_inverted_colors (priv->model);
-                icon = ev_document_misc_render_loading_thumbnail (GTK_WIDGET (sidebar_thumbnails),
-                                                                  width, height, inverted_colors);
+                icon = ev_document_misc_render_loading_thumbnail_surface (GTK_WIDGET (sidebar_thumbnails),
+                                                                          width, height,
+                                                                          inverted_colors);
                g_hash_table_insert (priv->loading_icons, key, icon);
        } else {
                g_free (key);
@@ -415,7 +418,7 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
             result && start_page <= end_page;
             result = gtk_tree_model_iter_next (GTK_TREE_MODEL (priv->list_store), &iter), start_page ++) {
                EvJobThumbnail *job;
-               GdkPixbuf *loading_icon = NULL;
+               cairo_surface_t *loading_icon = NULL;
                gint width, height;
 
                gtk_tree_model_get (GTK_TREE_MODEL (priv->list_store),
@@ -444,7 +447,7 @@ clear_range (EvSidebarThumbnails *sidebar_thumbnails,
                gtk_list_store_set (priv->list_store, &iter,
                                    COLUMN_JOB, NULL,
                                    COLUMN_THUMBNAIL_SET, FALSE,
-                                   COLUMN_PIXBUF, loading_icon,
+                                   COLUMN_SURFACE, loading_icon,
                                    -1);
        }
        gtk_tree_path_free (path);
@@ -610,7 +613,7 @@ ev_sidebar_thumbnails_fill_model (EvSidebarThumbnails *sidebar_thumbnails)
        for (i = 0; i < sidebar_thumbnails->priv->n_pages; i++) {
                gchar     *page_label;
                gchar     *page_string;
-               GdkPixbuf *loading_icon = NULL;
+               cairo_surface_t *loading_icon = NULL;
                gint       width, height;
 
                page_label = ev_document_get_page_label (priv->document, i);
@@ -630,7 +633,7 @@ ev_sidebar_thumbnails_fill_model (EvSidebarThumbnails *sidebar_thumbnails)
                gtk_list_store_append (priv->list_store, &iter);
                gtk_list_store_set (priv->list_store, &iter,
                                    COLUMN_PAGE_STRING, page_string,
-                                   COLUMN_PIXBUF, loading_icon,
+                                   COLUMN_SURFACE, loading_icon,
                                    COLUMN_THUMBNAIL_SET, FALSE,
                                    -1);
                g_free (page_label);
@@ -703,7 +706,7 @@ ev_sidebar_init_tree_view (EvSidebarThumbnails *ev_sidebar_thumbnails)
                                 NULL);
        gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
                                                     NULL, renderer,
-                                                    "pixbuf", 1,
+                                                    "surface", 1,
                                                     NULL);
        gtk_tree_view_insert_column_with_attributes (GTK_TREE_VIEW (priv->tree_view), -1,
                                                     NULL, gtk_cell_renderer_text_new (),
@@ -728,7 +731,7 @@ ev_sidebar_init_icon_view (EvSidebarThumbnails *ev_sidebar_thumbnails)
                                  NULL);
         gtk_cell_layout_pack_start (GTK_CELL_LAYOUT (priv->icon_view), renderer, FALSE);
         gtk_cell_layout_set_attributes (GTK_CELL_LAYOUT (priv->icon_view),
-                                        renderer, "pixbuf", 1, NULL);
+                                        renderer, "surface", 1, NULL);
 
         renderer = g_object_new (GTK_TYPE_CELL_RENDERER_TEXT,
                                  "alignment", PANGO_ALIGN_CENTER,
@@ -765,7 +768,7 @@ ev_sidebar_thumbnails_init (EvSidebarThumbnails *ev_sidebar_thumbnails)
 
        priv->list_store = gtk_list_store_new (NUM_COLUMNS,
                                               G_TYPE_STRING,
-                                              GDK_TYPE_PIXBUF,
+                                              CAIRO_GOBJECT_TYPE_SURFACE,
                                               G_TYPE_BOOLEAN,
                                               EV_TYPE_JOB_THUMBNAIL);
 
@@ -886,22 +889,30 @@ static void
 thumbnail_job_completed_callback (EvJobThumbnail      *job,
                                  EvSidebarThumbnails *sidebar_thumbnails)
 {
+        GtkWidget                  *widget = GTK_WIDGET (sidebar_thumbnails);
        EvSidebarThumbnailsPrivate *priv = sidebar_thumbnails->priv;
        GtkTreeIter                *iter;
-        GdkPixbuf                  *pixbuf;
+        cairo_surface_t            *surface;
+        cairo_surface_t            *thumbnail;
 
-        pixbuf = ev_document_misc_render_thumbnail_with_frame (GTK_WIDGET (sidebar_thumbnails), 
job->thumbnail);
+        thumbnail = gdk_cairo_surface_create_from_pixbuf (job->thumbnail,
+                                                          1,
+                                                          gtk_widget_get_window (widget));
+        surface = ev_document_misc_render_thumbnail_surface_with_frame (widget, thumbnail,
+                                                                        gdk_pixbuf_get_width 
(job->thumbnail),
+                                                                        gdk_pixbuf_get_height 
(job->thumbnail));
+        cairo_surface_destroy (thumbnail);
 
        iter = (GtkTreeIter *) g_object_get_data (G_OBJECT (job), "tree_iter");
        if (priv->inverted_colors)
-               ev_document_misc_invert_pixbuf (pixbuf);
+               ev_document_misc_invert_surface (surface);
        gtk_list_store_set (priv->list_store,
                            iter,
-                           COLUMN_PIXBUF, pixbuf,
+                           COLUMN_SURFACE, surface,
                            COLUMN_THUMBNAIL_SET, TRUE,
                            COLUMN_JOB, NULL,
                            -1);
-        g_object_unref (pixbuf);
+        cairo_surface_destroy (surface);
 }
 
 static void
@@ -925,7 +936,7 @@ ev_sidebar_thumbnails_document_changed_cb (EvDocumentModel     *model,
        priv->loading_icons = g_hash_table_new_full (g_str_hash,
                                                     g_str_equal,
                                                     (GDestroyNotify)g_free,
-                                                    (GDestroyNotify)g_object_unref);
+                                                    (GDestroyNotify)cairo_surface_destroy);
 
        ev_sidebar_thumbnails_clear_model (sidebar_thumbnails);
        ev_sidebar_thumbnails_fill_model (sidebar_thumbnails);


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