]> www.fi.muni.cz Git - evince.git/commitdiff
Use cairo image surfaces instead of GDK pixbufs for drawing pages and
authorCarlos Garcia Campos <carlosgc@gnome.org>
Wed, 13 Jun 2007 08:54:53 +0000 (08:54 +0000)
committerCarlos Garcia Campos <carlosgc@src.gnome.org>
Wed, 13 Jun 2007 08:54:53 +0000 (08:54 +0000)
2007-06-13  Carlos Garcia Campos  <carlosgc@gnome.org>
* backend/dvi/dvi-document.c: (dvi_document_render),
(dvi_document_render_pixbuf), (dvi_document_document_iface_init):
* backend/impress/impress-document.c:
(imp_render_get_from_drawable), (impress_document_render_pixbuf),
(impress_document_render), (impress_document_document_iface_init),
(impress_document_thumbnails_get_thumbnail):
* backend/djvu/djvu-document-private.h:
* backend/djvu/djvu-document.c: (djvu_document_render),
(djvu_document_finalize), (djvu_document_document_iface_init),
(djvu_document_thumbnails_get_thumbnail), (djvu_document_init):
* backend/tiff/tiff-document.c: (tiff_document_render),
(tiff_document_render_pixbuf),
(tiff_document_document_iface_init):
* backend/pdf/ev-poppler.cc: (pdf_document_render),
(pdf_document_render_pixbuf), (pdf_document_document_iface_init),
(pdf_selection_render_selection):
* backend/comics/comics-document.c:
(comics_document_render_pixbuf), (comics_document_render),
(comics_document_document_iface_init):
* backend/pixbuf/pixbuf-document.c: (pixbuf_document_render),
(pixbuf_document_document_iface_init):
* libdocument/ev-document-misc.[ch]:
(ev_document_misc_surface_from_pixbuf),
(ev_document_misc_surface_rotate_and_scale):
* libdocument/ev-document.[ch]: (ev_document_render):
* libdocument/ev-selection.[ch]: (ev_selection_render_selection):
* shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info),
(move_one_job), (copy_job_to_job_info), (add_job_if_needed),
(ev_pixbuf_cache_get_surface), (new_selection_surface_needed),
(clear_selection_if_needed), (ev_pixbuf_cache_style_changed),
(ev_pixbuf_cache_get_selection_surface), (clear_job_selection):
* shell/ev-jobs.[ch]: (ev_job_render_dispose),
(render_finished_cb), (ev_job_render_run):
* shell/ev-view.c: (draw_loading_text), (draw_one_page),
(merge_selection_region):
Use cairo image surfaces instead of GDK pixbufs for drawing pages
and selections.

svn path=/trunk/; revision=2499

20 files changed:
ChangeLog
backend/comics/comics-document.c
backend/djvu/djvu-document-private.h
backend/djvu/djvu-document.c
backend/dvi/dvi-document.c
backend/impress/impress-document.c
backend/pdf/ev-poppler.cc
backend/pixbuf/pixbuf-document.c
backend/tiff/tiff-document.c
libdocument/ev-document-misc.c
libdocument/ev-document-misc.h
libdocument/ev-document.c
libdocument/ev-document.h
libdocument/ev-selection.c
libdocument/ev-selection.h
shell/ev-jobs.c
shell/ev-jobs.h
shell/ev-pixbuf-cache.c
shell/ev-pixbuf-cache.h
shell/ev-view.c

index 35fa4305f46d093767f384a57d54a4c53fa60305..ce3adcbce9192189c4edc53921b81efa1583356e 100644 (file)
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,44 @@
+2007-06-13  Carlos Garcia Campos  <carlosgc@gnome.org>
+
+       * backend/dvi/dvi-document.c: (dvi_document_render),
+       (dvi_document_render_pixbuf), (dvi_document_document_iface_init):
+       * backend/impress/impress-document.c:
+       (imp_render_get_from_drawable), (impress_document_render_pixbuf),
+       (impress_document_render), (impress_document_document_iface_init),
+       (impress_document_thumbnails_get_thumbnail):
+       * backend/djvu/djvu-document-private.h:
+       * backend/djvu/djvu-document.c: (djvu_document_render),
+       (djvu_document_finalize), (djvu_document_document_iface_init),
+       (djvu_document_thumbnails_get_thumbnail), (djvu_document_init):
+       * backend/tiff/tiff-document.c: (tiff_document_render),
+       (tiff_document_render_pixbuf),
+       (tiff_document_document_iface_init):
+       * backend/pdf/ev-poppler.cc: (pdf_document_render),
+       (pdf_document_render_pixbuf), (pdf_document_document_iface_init),
+       (pdf_selection_render_selection):
+       * backend/comics/comics-document.c:
+       (comics_document_render_pixbuf), (comics_document_render),
+       (comics_document_document_iface_init):
+       * backend/pixbuf/pixbuf-document.c: (pixbuf_document_render),
+       (pixbuf_document_document_iface_init):
+       * libdocument/ev-document-misc.[ch]:
+       (ev_document_misc_surface_from_pixbuf),
+       (ev_document_misc_surface_rotate_and_scale):
+       * libdocument/ev-document.[ch]: (ev_document_render):
+       * libdocument/ev-selection.[ch]: (ev_selection_render_selection):
+       * shell/ev-pixbuf-cache.[ch]: (dispose_cache_job_info),
+       (move_one_job), (copy_job_to_job_info), (add_job_if_needed),
+       (ev_pixbuf_cache_get_surface), (new_selection_surface_needed),
+       (clear_selection_if_needed), (ev_pixbuf_cache_style_changed),
+       (ev_pixbuf_cache_get_selection_surface), (clear_job_selection):
+       * shell/ev-jobs.[ch]: (ev_job_render_dispose),
+       (render_finished_cb), (ev_job_render_run):
+       * shell/ev-view.c: (draw_loading_text), (draw_one_page),
+       (merge_selection_region):
+
+       Use cairo image surfaces instead of GDK pixbufs for drawing pages
+       and selections.
+       
 2007-06-12  Carlos Garcia Campos  <carlosgc@gnome.org>
 
        * shell/ev-window-title.c: (ev_window_title_update):
index 64bd2b75eabaaa9f301e7db13b5a03321c1d5d75..092d8c2b3876b5caf3f5690727672978d114327e 100644 (file)
@@ -268,7 +268,7 @@ get_page_size_area_prepared_cb (GdkPixbufLoader *loader,
 }
 
 static GdkPixbuf *
-comics_document_render_pixbuf (EvDocument  *document,
+comics_document_render_pixbuf (EvDocument      *document,
                               EvRenderContext *rc)
 {
        GdkPixbufLoader *loader;
@@ -309,9 +309,24 @@ comics_document_render_pixbuf (EvDocument  *document,
                                                   360 - rc->rotation);
        g_spawn_close_pid (child_pid);
        g_object_unref (loader);
+
        return rotated_pixbuf;
 }
 
+static cairo_surface_t *
+comics_document_render (EvDocument      *document,
+                       EvRenderContext *rc)
+{
+       GdkPixbuf       *pixbuf;
+       cairo_surface_t *surface;
+
+       pixbuf = comics_document_render_pixbuf (document, rc);
+       surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+       g_object_unref (pixbuf);
+       
+       return surface;
+}
+
 static void
 render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
                                gint             width,
@@ -319,8 +334,8 @@ render_pixbuf_size_prepared_cb (GdkPixbufLoader *loader,
                                gpointer         data)
 {
        double *scale = data;
-       int w = width  * (*scale);
-       int h = height * (*scale);
+       int w = (width  * (*scale) + 0.5);
+       int h = (height * (*scale) + 0.5);
 
        gdk_pixbuf_loader_set_size (loader, w, h);
 }
@@ -371,11 +386,11 @@ comics_document_document_iface_init (EvDocumentIface *iface)
 {
        iface->load = comics_document_load;
        iface->save = comics_document_save;
-       iface->can_get_text  = comics_document_can_get_text;
-       iface->get_n_pages   = comics_document_get_n_pages;
+       iface->can_get_text = comics_document_can_get_text;
+       iface->get_n_pages = comics_document_get_n_pages;
        iface->get_page_size = comics_document_get_page_size;
-       iface->render_pixbuf = comics_document_render_pixbuf;
-       iface->get_info      = comics_document_get_info;
+       iface->render = comics_document_render;
+       iface->get_info = comics_document_get_info;
 }
 
 static void
index 37651ef7fa31e85732019982b0f92cc5ef99cbc1..3e7deedffd8ec939b7ba140ae6681b49e2e15364 100644 (file)
@@ -32,6 +32,7 @@ struct _DjvuDocument {
        ddjvu_context_t  *d_context;
        ddjvu_document_t *d_document;
        ddjvu_format_t   *d_format;
+       ddjvu_format_t   *thumbs_format;
 
        gchar            *uri;
 
index fc1ccaacd95e3c3a2ac34b007af189bad2516300..a8f04254d8fd8374f1c5190b260622ea744cde3b 100644 (file)
@@ -203,7 +203,7 @@ djvu_document_get_page_size (EvDocument   *document,
 
        while ((r = ddjvu_document_get_pageinfo(djvu_document->d_document, page, &info)) < DDJVU_JOB_OK)
                djvu_handle_events(djvu_document, TRUE);
-
+       
        if (r >= DDJVU_JOB_FAILED)
                djvu_handle_events(djvu_document, TRUE);
 
@@ -211,45 +211,57 @@ djvu_document_get_page_size (EvDocument   *document,
         *height = info.height * SCALE_FACTOR;
 }
 
-static GdkPixbuf *
-djvu_document_render_pixbuf (EvDocument  *document, 
-                            EvRenderContext *rc)
+static cairo_surface_t *
+djvu_document_render (EvDocument      *document, 
+                     EvRenderContext *rc)
 {
        DjvuDocument *djvu_document = DJVU_DOCUMENT (document);
-       GdkPixbuf *pixbuf;
-       GdkPixbuf *rotated_pixbuf;
-       
+       cairo_surface_t *surface, *rotated_surface;
+       gchar *pixels;
+       gint   rowstride;
        ddjvu_rect_t rrect;
        ddjvu_rect_t prect;
        ddjvu_page_t *d_page;
-       
        double page_width, page_height;
+       static const cairo_user_data_key_t key;
 
        d_page = ddjvu_page_create_by_pageno (djvu_document->d_document, rc->page);
        
        while (!ddjvu_page_decoding_done (d_page))
                djvu_handle_events(djvu_document, TRUE);
-       
-       page_width = ddjvu_page_get_width (d_page) * rc->scale * SCALE_FACTOR;
-       page_height = ddjvu_page_get_height (d_page) * rc->scale * SCALE_FACTOR;
 
-       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, FALSE, 8, page_width, page_height);
-
-       prect.x = 0; prect.y = 0;
-       prect.w = page_width; prect.h = page_height;
+       page_width = ddjvu_page_get_width (d_page) * rc->scale * SCALE_FACTOR + 0.5;
+       page_height = ddjvu_page_get_height (d_page) * rc->scale * SCALE_FACTOR + 0.5;
+
+       rowstride = page_width * 4;
+       pixels = (gchar *) g_malloc (page_height * rowstride);
+       surface = cairo_image_surface_create_for_data (pixels,
+                                                      CAIRO_FORMAT_ARGB32,
+                                                      page_width,
+                                                      page_height,
+                                                      rowstride);
+       cairo_surface_set_user_data (surface, &key,
+                                    pixels, (cairo_destroy_func_t)g_free);
+       prect.x = 0;
+       prect.y = 0;
+       prect.w = page_width;
+       prect.h = page_height;
        rrect = prect;
 
-       ddjvu_page_render(d_page, DDJVU_RENDER_COLOR,
-                          &prect,
-                          &rrect,
-                          djvu_document->d_format,
-                         gdk_pixbuf_get_rowstride (pixbuf),
-                          (gchar *)gdk_pixbuf_get_pixels (pixbuf));
-       
-       rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
-       g_object_unref (pixbuf);
-       
-       return rotated_pixbuf;
+       ddjvu_page_render (d_page, DDJVU_RENDER_COLOR,
+                          &prect,
+                          &rrect,
+                          djvu_document->d_format,
+                          rowstride,
+                          pixels);
+
+       rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+                                                                    page_width,
+                                                                    page_height,
+                                                                    rc->rotation);
+       cairo_surface_destroy (surface);
+
+       return rotated_surface;
 }
 
 static void
@@ -268,6 +280,7 @@ djvu_document_finalize (GObject *object)
            
        ddjvu_context_release (djvu_document->d_context);
        ddjvu_format_release (djvu_document->d_format);
+       ddjvu_format_release (djvu_document->thumbs_format);
        g_free (djvu_document->uri);
        
        G_OBJECT_CLASS (djvu_document_parent_class)->finalize (object);
@@ -329,7 +342,7 @@ djvu_document_document_iface_init (EvDocumentIface *iface)
        iface->get_text = djvu_document_get_text;
        iface->get_n_pages = djvu_document_get_n_pages;
        iface->get_page_size = djvu_document_get_page_size;
-       iface->render_pixbuf = djvu_document_render_pixbuf;
+       iface->render = djvu_document_render;
        iface->get_info = djvu_document_get_info;
 }
 
@@ -383,7 +396,7 @@ djvu_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
                    
        ddjvu_thumbnail_render (djvu_document->d_document, rc->page, 
                                &thumb_width, &thumb_height,
-                               djvu_document->d_format,
+                               djvu_document->thumbs_format,
                                gdk_pixbuf_get_rowstride (pixbuf), 
                                (gchar *)pixels);
 
@@ -417,13 +430,13 @@ djvu_document_file_exporter_format_supported (EvFileExporter      *exporter,
 
 static void
 djvu_document_file_exporter_begin (EvFileExporter      *exporter,
-                                 EvFileExporterFormat format,
-                                const char          *filename, /* for storing the temp ps file */
-                                 int                  first_page,
-                                 int                  last_page,
-                                 double               width,
-                                 double               height,
-                                 gboolean             duplex)
+                                  EvFileExporterFormat format,
+                                  const char          *filename, /* for storing the temp ps file */
+                                  int                  first_page,
+                                  int                  last_page,
+                                  double               width,
+                                  double               height,
+                                  gboolean             duplex)
 {
        DjvuDocument *djvu_document = DJVU_DOCUMENT (exporter);
        
@@ -435,7 +448,8 @@ djvu_document_file_exporter_begin (EvFileExporter      *exporter,
 }
 
 static void
-djvu_document_file_exporter_do_page (EvFileExporter *exporter, EvRenderContext *rc)
+djvu_document_file_exporter_do_page (EvFileExporter  *exporter,
+                                    EvRenderContext *rc)
 {
        DjvuDocument *djvu_document = DJVU_DOCUMENT (exporter);
        
@@ -478,9 +492,14 @@ djvu_document_file_exporter_iface_init (EvFileExporterIface *iface)
 static void
 djvu_document_init (DjvuDocument *djvu_document)
 {
+       guint masks[4] = { 0xff0000, 0xff00, 0xff, 0xff000000 };
+       
        djvu_document->d_context = ddjvu_context_create ("Evince");
-       djvu_document->d_format = ddjvu_format_create (DDJVU_FORMAT_RGB24, 0, 0);
-       ddjvu_format_set_row_order (djvu_document->d_format,1);
+       djvu_document->d_format = ddjvu_format_create (DDJVU_FORMAT_RGBMASK32, 4, masks);
+       ddjvu_format_set_row_order (djvu_document->d_format, 1);
+
+       djvu_document->thumbs_format = ddjvu_format_create (DDJVU_FORMAT_RGB24, 0, 0);
+       ddjvu_format_set_row_order (djvu_document->thumbs_format, 1);
 
        djvu_document->ps_filename = NULL;
        djvu_document->opts = g_string_new ("");
index 9abdca7105e2240a068be7f964ebb903c037eea5..445c1e0cab2df14b6dd943c1a0441ff4bfa0493b 100644 (file)
@@ -152,15 +152,14 @@ dvi_document_get_page_size (EvDocument   *document,
        return;
 }
 
-static GdkPixbuf *
-dvi_document_render_pixbuf (EvDocument  *document,
-                           EvRenderContext *rc)
+static cairo_surface_t *
+dvi_document_render (EvDocument      *document,
+                    EvRenderContext *rc)
 {
        GdkPixbuf *pixbuf;
-       GdkPixbuf *rotated_pixbuf;
-
+       cairo_surface_t *surface;
+       cairo_surface_t *rotated_surface;
        DviDocument *dvi_document = DVI_DOCUMENT(document);
-
        gint required_width, required_height;
        gint proposed_width, proposed_height;
        gint xmargin = 0, ymargin = 0;
@@ -177,8 +176,8 @@ dvi_document_render_pixbuf (EvDocument  *document,
                         (int)((dvi_document->params->hshrink - 1) / rc->scale) + 1,
                         (int)((dvi_document->params->vshrink - 1) / rc->scale) + 1);
 
-       required_width = dvi_document->base_width * rc->scale;
-       required_height = dvi_document->base_height * rc->scale;
+       required_width = dvi_document->base_width * rc->scale + 0.5;
+       required_height = dvi_document->base_height * rc->scale + 0.5;
        proposed_width = dvi_document->context->dvi_page_w * dvi_document->context->params.conv;
        proposed_height = dvi_document->context->dvi_page_h * dvi_document->context->params.vconv;
        
@@ -195,10 +194,17 @@ dvi_document_render_pixbuf (EvDocument  *document,
 
        g_mutex_unlock (dvi_context_mutex);
 
-       rotated_pixbuf = gdk_pixbuf_rotate_simple (pixbuf, 360 - rc->rotation);
+       /* FIXME: we should write a mdvi device based on cairo */
+       surface = ev_document_misc_surface_from_pixbuf (pixbuf);
        g_object_unref (pixbuf);
 
-       return rotated_pixbuf;
+       rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+                                                                    required_width,
+                                                                    required_height,
+                                                                    rc->rotation);
+       cairo_surface_destroy (surface);
+
+       return rotated_surface;
 }
 
 static void
@@ -260,7 +266,7 @@ dvi_document_document_iface_init (EvDocumentIface *iface)
        iface->can_get_text = dvi_document_can_get_text;
        iface->get_n_pages = dvi_document_get_n_pages;
        iface->get_page_size = dvi_document_get_page_size;
-       iface->render_pixbuf = dvi_document_render_pixbuf;
+       iface->render = dvi_document_render;
        iface->get_info = dvi_document_get_info;
 }
 
index 5f5982ed7fcc08b928e8012e6ec5b883cc0e5910..6251fbd25ae101cc0b4027de726e44a76542183c 100644 (file)
@@ -355,8 +355,10 @@ imp_render_get_from_drawable (ImpressDocument *impress_document)
 
   g_return_val_if_fail (page != NULL, FALSE);
 
+  ev_document_doc_mutex_lock ();
   imp_context_set_page (impress_document->ctx, page);
   imp_render (impress_document->ctx, impress_document);
+  ev_document_doc_mutex_unlock ();
 
   impress_document->pixbuf = gdk_pixbuf_get_from_drawable (NULL,
                                         GDK_DRAWABLE (impress_document->pixmap),
@@ -370,36 +372,56 @@ imp_render_get_from_drawable (ImpressDocument *impress_document)
 }
 
 static GdkPixbuf *
-impress_document_render_pixbuf (EvDocument  *document,
+impress_document_render_pixbuf (EvDocument      *document,
                                EvRenderContext *rc)
 {
   ImpressDocument *impress_document = IMPRESS_DOCUMENT (document);
-  GdkPixbuf *scaled_pixbuf;
-
-  g_return_val_if_fail (IMPRESS_IS_DOCUMENT (document), 0);
-  g_return_val_if_fail (impress_document->imp != NULL, 0);
+  GdkPixbuf       *pixbuf;
 
+  g_return_val_if_fail (IMPRESS_IS_DOCUMENT (document), NULL);
+  g_return_val_if_fail (impress_document->imp != NULL, NULL);
+  
   impress_document->pagenum = rc->page;
 
   g_mutex_lock (impress_document->mutex);
   impress_document->cond = g_cond_new ();
 
   ev_document_fc_mutex_unlock ();
+  ev_document_doc_mutex_unlock ();
   g_idle_add ((GSourceFunc) imp_render_get_from_drawable, impress_document);
   g_cond_wait (impress_document->cond, impress_document->mutex);
   g_cond_free (impress_document->cond);
+  ev_document_doc_mutex_lock ();
   ev_document_fc_mutex_lock ();
-
+  
   g_mutex_unlock (impress_document->mutex);
 
-  scaled_pixbuf = gdk_pixbuf_scale_simple (impress_document->pixbuf,
-                                          PAGE_WIDTH * rc->scale,
-                                          PAGE_HEIGHT * rc->scale,
-                                          GDK_INTERP_BILINEAR);
-  gdk_pixbuf_unref (impress_document->pixbuf);
+  pixbuf = impress_document->pixbuf;
   impress_document->pixbuf = NULL;
 
-  return scaled_pixbuf;
+  return pixbuf;
+}
+
+static cairo_surface_t *
+impress_document_render (EvDocument      *document,
+                        EvRenderContext *rc)
+{
+  GdkPixbuf *pixbuf;
+  cairo_surface_t *surface, *scaled_surface;
+
+  pixbuf = impress_document_render_pixbuf (document, rc);
+  
+  /* FIXME: impress backend should be ported to cairo */
+  surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+  g_object_unref (pixbuf);
+
+  scaled_surface = ev_document_misc_surface_rotate_and_scale (surface,
+                                                             (PAGE_WIDTH * rc->scale) + 0.5,
+                                                             (PAGE_HEIGHT * rc->scale) + 0.5,
+                                                             rc->rotation);
+  cairo_surface_destroy (surface);
+
+  return scaled_surface;
 }
 
 static void
@@ -461,7 +483,7 @@ impress_document_document_iface_init (EvDocumentIface *iface)
   iface->can_get_text = impress_document_can_get_text;
   iface->get_n_pages = impress_document_get_n_pages;
   iface->get_page_size = impress_document_get_page_size;
-  iface->render_pixbuf = impress_document_render_pixbuf;
+  iface->render = impress_document_render;
   iface->get_info = impress_document_get_info;
 }
 
@@ -470,20 +492,26 @@ impress_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
                                           EvRenderContext      *rc, 
                                           gboolean              border)
 {
-  GdkPixbuf *pixbuf = NULL;
+  GdkPixbuf *pixbuf;
+  GdkPixbuf *scaled_pixbuf;
   gdouble w, h;
 
   pixbuf = impress_document_render_pixbuf (EV_DOCUMENT (document), rc);
+  scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
+                                          (PAGE_WIDTH * rc->scale),
+                                          (PAGE_HEIGHT * rc->scale),
+                                          GDK_INTERP_BILINEAR);
+  g_object_unref (pixbuf);
 
   if (border)
     {
-      GdkPixbuf *tmp_pixbuf = pixbuf;
+      GdkPixbuf *tmp_pixbuf = scaled_pixbuf;
       
-      pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
+      scaled_pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
       g_object_unref (tmp_pixbuf);
     }
 
-  return pixbuf;
+  return scaled_pixbuf;
 }
 
 static void
index a3549b248b55d949ce44909763c049bda84c2cd6..e3b80b450d8d93e02fc5232fe442500613c3c2d0 100644 (file)
@@ -426,12 +426,12 @@ pdf_document_get_attachments (EvDocument *document)
        return g_list_reverse (retval);
 }
 
-static GdkPixbuf *
-pdf_document_render_pixbuf (EvDocument   *document,
-                           EvRenderContext *rc)
+static cairo_surface_t *
+pdf_document_render (EvDocument      *document,
+                    EvRenderContext *rc)
 {
        PdfDocument *pdf_document;
-       GdkPixbuf *pixbuf;
+       cairo_surface_t *surface;
        double width_points, height_points;
        gint width, height;
 
@@ -448,7 +448,37 @@ pdf_document_render_pixbuf (EvDocument   *document,
                width = (int) ((width_points * rc->scale) + 0.5);
                height = (int) ((height_points * rc->scale) + 0.5);
        }
-
+       
+#ifdef HAVE_POPPLER_PAGE_RENDER
+       cairo_t *cr;
+       
+       surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                             width, height);
+       memset (cairo_image_surface_get_data (surface), 0xff,
+               cairo_image_surface_get_height (surface) *
+               cairo_image_surface_get_stride (surface));
+       
+       cr = cairo_create (surface);
+       switch (rc->rotation) {
+               case 90:
+                       cairo_translate (cr, width, 0);
+                       break;
+               case 180:
+                       cairo_translate (cr, width, height);
+                       break;
+               case 270:
+                       cairo_translate (cr, 0, height);
+                       break;
+               default:
+                       cairo_translate (cr, 0, 0);
+       }
+       cairo_scale (cr, rc->scale, rc->scale);
+       cairo_rotate (cr, rc->rotation * G_PI / 180.0);
+       poppler_page_render (POPPLER_PAGE (rc->data), cr);
+       cairo_destroy (cr);
+#else /* HAVE_POPPLER_PAGE_RENDER */
+       GdkPixbuf *pixbuf;
+       
        pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
                                 FALSE, 8,
                                 width, height);
@@ -459,9 +489,11 @@ pdf_document_render_pixbuf (EvDocument   *document,
                                       rc->scale,
                                       rc->rotation,
                                       pixbuf);
-       
-       
-       return pixbuf;
+       surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+       g_object_unref (pixbuf);
+#endif /* HAVE_POPPLER_PAGE_RENDER */
+
+       return surface;
 }
 
 /* EvDocumentSecurity */
@@ -671,7 +703,7 @@ pdf_document_document_iface_init (EvDocumentIface *iface)
        iface->get_page_label = pdf_document_get_page_label;
        iface->has_attachments = pdf_document_has_attachments;
        iface->get_attachments = pdf_document_get_attachments;
-       iface->render_pixbuf = pdf_document_render_pixbuf;
+       iface->render = pdf_document_render;
        iface->get_text = pdf_document_get_text;
        iface->can_get_text = pdf_document_can_get_text;
        iface->get_info = pdf_document_get_info;
@@ -1600,11 +1632,11 @@ pdf_document_file_exporter_iface_init (EvFileExporterIface *iface)
 static void
 pdf_selection_render_selection (EvSelection      *selection,
                                EvRenderContext  *rc,
-                               GdkPixbuf       **pixbuf,
+                               cairo_surface_t **surface,
                                EvRectangle      *points,
                                EvRectangle      *old_points,
-                               GdkColor        *text,
-                               GdkColor        *base)
+                               GdkColor         *text,
+                               GdkColor         *base)
 {
        PdfDocument *pdf_document;
        double width_points, height_points;
@@ -1613,23 +1645,54 @@ pdf_selection_render_selection (EvSelection      *selection,
        pdf_document = PDF_DOCUMENT (selection);
        set_rc_data (pdf_document, rc);
 
-       poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points);
+       poppler_page_get_size (POPPLER_PAGE (rc->data),
+                              &width_points, &height_points);
        width = (int) ((width_points * rc->scale) + 0.5);
        height = (int) ((height_points * rc->scale) + 0.5);
 
-       if (*pixbuf == NULL) {
-               * pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
-                                          TRUE, 8,
-                                          width, height);
+
+#ifdef HAVE_POPPLER_PAGE_RENDER
+       cairo_t *cr;
+
+       if (*surface == NULL) {
+               *surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                                      width, height);
+               
        }
 
+       cr = cairo_create (*surface);
+       cairo_scale (cr, rc->scale, rc->scale);
+       cairo_surface_set_device_offset (*surface, 0, 0);
+       memset (cairo_image_surface_get_data (*surface), 0x00,
+               cairo_image_surface_get_height (*surface) *
+               cairo_image_surface_get_stride (*surface));
+       poppler_page_render_selection (POPPLER_PAGE (rc->data),
+                                      cr,
+                                      (PopplerRectangle *)points,
+                                      (PopplerRectangle *)old_points,
+                                      POPPLER_SELECTION_NORMAL, /* SelectionStyle */
+                                      text,
+                                      base);
+       cairo_destroy (cr);
+#else /* HAVE_POPPLER_PAGE_RENDER */
+       GdkPixbuf *pixbuf;
+       
+       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB,
+                                TRUE, 8,
+                                width, height);
+
        poppler_page_render_selection_to_pixbuf (POPPLER_PAGE (rc->data),
-                                                rc->scale, rc->rotation, *pixbuf,
+                                                rc->scale, rc->rotation, pixbuf,
                                                 (PopplerRectangle *)points,
                                                 (PopplerRectangle *)old_points,
                                                 POPPLER_SELECTION_NORMAL, /* SelectionStyle */
                                                 text,
                                                 base);
+       if (*surface)
+               cairo_surface_destroy (*surface);
+       *surface = ev_document_misc_surface_from_pixbuf (pixbuf);
+       g_object_unref (pixbuf);
+#endif /* HAVE_POPPLER_PAGE_RENDER */
 }
 
 
@@ -1645,8 +1708,9 @@ pdf_selection_get_selection_region (EvSelection     *selection,
 
        set_rc_data (pdf_document, rc);
 
-       retval = poppler_page_get_selection_region ((PopplerPage *)rc->data, rc->scale, (PopplerRectangle *) points);
-
+       retval = poppler_page_get_selection_region ((PopplerPage *)rc->data,
+                                                   rc->scale,
+                                                   (PopplerRectangle *) points);
        return retval;
 }
 
index c1cace00baeee607f0750b3d8f35513144533740..83d2b8ae70d47bd6075c2bca0b910132a1e49ee3 100644 (file)
@@ -101,22 +101,27 @@ pixbuf_document_get_page_size (EvDocument   *document,
        *height = gdk_pixbuf_get_height (pixbuf_document->pixbuf);
 }
 
-static GdkPixbuf*
-pixbuf_document_render_pixbuf (EvDocument      *document,
-                              EvRenderContext *rc)
+static cairo_surface_t *
+pixbuf_document_render (EvDocument      *document,
+                       EvRenderContext *rc)
 {
        PixbufDocument *pixbuf_document = PIXBUF_DOCUMENT (document);
        GdkPixbuf *scaled_pixbuf, *rotated_pixbuf;
+       cairo_surface_t *surface;
 
-       scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf_document->pixbuf,
-                                                gdk_pixbuf_get_width (pixbuf_document->pixbuf) * rc->scale,
-                                                gdk_pixbuf_get_height (pixbuf_document->pixbuf) * rc->scale,
-                                                GDK_INTERP_BILINEAR);
-
+       scaled_pixbuf = gdk_pixbuf_scale_simple (
+               pixbuf_document->pixbuf,
+               (gdk_pixbuf_get_width (pixbuf_document->pixbuf) * rc->scale) + 0.5,
+               (gdk_pixbuf_get_height (pixbuf_document->pixbuf) * rc->scale) + 0.5,
+               GDK_INTERP_BILINEAR);
+       
         rotated_pixbuf = gdk_pixbuf_rotate_simple (scaled_pixbuf, 360 - rc->rotation);
         g_object_unref (scaled_pixbuf);
 
-       return rotated_pixbuf;
+       surface = ev_document_misc_surface_from_pixbuf (rotated_pixbuf);
+       g_object_unref (rotated_pixbuf);
+
+       return surface;
 }
 
 static void
@@ -163,7 +168,7 @@ pixbuf_document_document_iface_init (EvDocumentIface *iface)
        iface->can_get_text = pixbuf_document_can_get_text;
        iface->get_n_pages = pixbuf_document_get_n_pages;
        iface->get_page_size = pixbuf_document_get_page_size;
-       iface->render_pixbuf = pixbuf_document_render_pixbuf;
+       iface->render = pixbuf_document_render;
        iface->get_info = pixbuf_document_get_info;
 }
 
index 742594729c00c6faf8825187c638231979cc7dba..8247c2a269b9751bc222f07c7447f4d7ab4d05e8 100644 (file)
@@ -201,9 +201,9 @@ tiff_document_get_page_size (EvDocument   *document,
        pop_handlers ();
 }
 
-static GdkPixbuf *
-tiff_document_render_pixbuf (EvDocument      *document,
-                            EvRenderContext *rc)
+static cairo_surface_t *
+tiff_document_render (EvDocument      *document,
+                     EvRenderContext *rc)
 {
        TiffDocument *tiff_document = TIFF_DOCUMENT (document);
        int width, height;
@@ -213,6 +213,9 @@ tiff_document_render_pixbuf (EvDocument      *document,
        GdkPixbuf *pixbuf;
        GdkPixbuf *scaled_pixbuf;
        GdkPixbuf *rotated_pixbuf;
+       cairo_surface_t *surface;
+       cairo_surface_t *rotated_surface;
+       static const cairo_user_data_key_t key;
        
        g_return_val_if_fail (TIFF_IS_DOCUMENT (document), NULL);
        g_return_val_if_fail (tiff_document->tiff != NULL, NULL);
@@ -237,6 +240,79 @@ tiff_document_render_pixbuf (EvDocument      *document,
        
        pop_handlers ();
   
+       /* Sanity check the doc */
+       if (width <= 0 || height <= 0)
+               return NULL;                
+
+       rowstride = width * 4;
+       if (rowstride / 4 != width)
+               /* overflow */
+               return NULL;                
+        
+       bytes = height * rowstride;
+       if (bytes / rowstride != height)
+               /* overflow */
+               return NULL;                
+       
+       pixels = g_try_malloc (bytes);
+       if (!pixels)
+               return NULL;
+       
+       surface = cairo_image_surface_create_for_data (pixels,
+                                                      CAIRO_FORMAT_ARGB32,
+                                                      width, height,
+                                                      rowstride);
+       cairo_surface_set_user_data (surface, &key,
+                                    pixels, (cairo_destroy_func_t)g_free);
+
+       TIFFReadRGBAImageOriented (tiff_document->tiff,
+                                  width, height,
+                                  (uint32 *)pixels,
+                                  ORIENTATION_TOPLEFT, 1);
+       pop_handlers ();
+
+       rotated_surface = ev_document_misc_surface_rotate_and_scale (surface,
+                                                                    (width * rc->scale) + 0.5,
+                                                                    (height * rc->scale * (x_res / y_res)) + 0.5,
+                                                                    rc->rotation);
+       cairo_surface_destroy (surface);
+       
+       return rotated_surface;
+}
+
+static GdkPixbuf *
+tiff_document_render_pixbuf (EvDocument      *document,
+                            EvRenderContext *rc)
+{
+       TiffDocument *tiff_document = TIFF_DOCUMENT (document);
+       int width, height;
+       float x_res, y_res;
+       gint rowstride, bytes;
+       guchar *pixels = NULL;
+       GdkPixbuf *pixbuf;
+       GdkPixbuf *scaled_pixbuf;
+       GdkPixbuf *rotated_pixbuf;
+       
+       push_handlers ();
+       if (TIFFSetDirectory (tiff_document->tiff, rc->page) != 1) {
+               pop_handlers ();
+               return NULL;
+       }
+
+       if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
+               pop_handlers ();
+               return NULL;
+       }
+
+       if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
+               pop_handlers ();
+               return NULL;
+       }
+
+       tiff_document_get_resolution (tiff_document, &x_res, &y_res);
+       
+       pop_handlers ();
+  
        /* Sanity check the doc */
        if (width <= 0 || height <= 0)
                return NULL;                
@@ -258,13 +334,12 @@ tiff_document_render_pixbuf (EvDocument      *document,
        pixbuf = gdk_pixbuf_new_from_data (pixels, GDK_COLORSPACE_RGB, TRUE, 8, 
                                           width, height, rowstride,
                                           (GdkPixbufDestroyNotify) g_free, NULL);
-       
-       pixbuf = gdk_pixbuf_new (GDK_COLORSPACE_RGB, TRUE, 8, width, height);
-       TIFFReadRGBAImageOriented (tiff_document->tiff, width, height,
-                                  (uint32 *)gdk_pixbuf_get_pixels (pixbuf),
+       TIFFReadRGBAImageOriented (tiff_document->tiff,
+                                  width, height,
+                                  (uint32 *)pixels,
                                   ORIENTATION_TOPLEFT, 1);
        pop_handlers ();
-       
+
        scaled_pixbuf = gdk_pixbuf_scale_simple (pixbuf,
                                                 width * rc->scale,
                                                 height * rc->scale * (x_res / y_res),
@@ -323,7 +398,7 @@ tiff_document_document_iface_init (EvDocumentIface *iface)
        iface->can_get_text = tiff_document_can_get_text;
        iface->get_n_pages = tiff_document_get_n_pages;
        iface->get_page_size = tiff_document_get_page_size;
-       iface->render_pixbuf = tiff_document_render_pixbuf;
+       iface->render = tiff_document_render;
        iface->get_info = tiff_document_get_info;
 }
 
index 89ff5fa8a76ff1ff14381a2608478cdb9d86db45..e8739a1ae8d073683117667c5a6823b0d1ea2ca3 100644 (file)
@@ -1,3 +1,21 @@
+/*
+ *  Copyright (c) 2007 Carlos Garcia Campos <carlosgc@gnome.org>
+ *  Copyright (C) 2000-2003 Marco Pesenti Gritti
+ *
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2, or (at your option)
+ *  any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
 
 #include "ev-document-misc.h"
 #include <string.h>
@@ -8,7 +26,6 @@
  * NULL, then it will fill the return pixbuf with the contents of
  * source_pixbuf.
  */
-
 GdkPixbuf *
 ev_document_misc_get_thumbnail_frame (int        width,
                                      int        height,
@@ -128,3 +145,77 @@ ev_document_misc_paint_one_page (GdkDrawable  *drawable,
                            border->right - border->left);
 
 }
+
+cairo_surface_t *
+ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf)
+{
+       cairo_surface_t *surface;
+       cairo_t         *cr;
+       
+       surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32,
+                                             gdk_pixbuf_get_width (pixbuf),
+                                             gdk_pixbuf_get_height (pixbuf));
+       cr = cairo_create (surface);
+       gdk_cairo_set_source_pixbuf (cr, pixbuf, 0, 0);
+       cairo_paint (cr);
+       cairo_destroy (cr);
+       
+       return surface;
+}
+
+cairo_surface_t *
+ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface,
+                                          gint             dest_width,
+                                          gint             dest_height,
+                                          gint             dest_rotation)
+{
+       cairo_surface_t *new_surface;
+       cairo_t         *cr;
+       gint             width, height;
+       gint             new_width = dest_width;
+       gint             new_height = dest_height;
+
+       width = cairo_image_surface_get_width (surface);
+       height = cairo_image_surface_get_height (surface);
+       
+       if (dest_width == width &&
+           dest_height == height &&
+           dest_rotation == 0) {
+               return cairo_surface_reference (surface);
+       }
+
+       if (dest_rotation == 90 || dest_rotation == 270) {
+               new_width = dest_height;
+               new_height = dest_width;
+       }
+
+       new_surface = cairo_surface_create_similar (surface,
+                                                   CAIRO_CONTENT_COLOR_ALPHA,
+                                                   new_width, new_height);
+
+       cr = cairo_create (new_surface);
+       switch (dest_rotation) {
+               case 90:
+                       cairo_translate (cr, new_width, 0);
+                       break;
+               case 180:
+                       cairo_translate (cr, new_width, new_height);
+                       break;
+               case 270:
+                       cairo_translate (cr, 0, new_height);
+                       break;
+               default:
+                       cairo_translate (cr, 0, 0);
+       }
+       cairo_pattern_set_filter (cairo_get_source (cr), CAIRO_FILTER_BILINEAR);
+       cairo_scale (cr,
+                    (gdouble)dest_width / width,
+                    (gdouble)dest_height / height);
+       cairo_rotate (cr, dest_rotation * G_PI / 180.0);
+       cairo_set_source_surface (cr, surface, 0, 0);
+       cairo_paint (cr);
+       cairo_destroy (cr);
+
+       return new_surface;
+}
+       
index 5d846717199a49550d1186c5f47c788342bb0f49..08607745ef06fe7b67eb7a9c84edb7119a8f1d43 100644 (file)
@@ -25,6 +25,7 @@
 
 #include <gdk-pixbuf/gdk-pixbuf.h>
 #include <gtk/gtkstyle.h>
+#include <cairo.h>
 
 G_BEGIN_DECLS
 
@@ -40,6 +41,11 @@ void       ev_document_misc_paint_one_page       (GdkDrawable  *drawable,
                                                  GdkRectangle *area,
                                                  GtkBorder    *border,
                                                  gboolean      highlight);
+cairo_surface_t *ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf);
+cairo_surface_t *ev_document_misc_surface_rotate_and_scale (cairo_surface_t *surface,
+                                                           gint             dest_width,
+                                                           gint             dest_height,
+                                                           gint             dest_rotation);
 
 G_END_DECLS
 
index a951bfa3fa83560534e113ba24ddbe38acc34112..776e4bdf4afba7c183878cb8a2a8cee1a3fb3d30 100644 (file)
@@ -230,17 +230,17 @@ ev_document_get_attachments (EvDocument *document)
        return retval;
 }
 
-GdkPixbuf *
-ev_document_render_pixbuf (EvDocument      *document,
-                          EvRenderContext *rc)
+cairo_surface_t *
+ev_document_render (EvDocument      *document,
+                   EvRenderContext *rc)
 {
        EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document);
-       GdkPixbuf *retval;
+       cairo_surface_t *retval;
 
        LOG ("ev_document_render_pixbuf");
-       g_assert (iface->render_pixbuf);
+       g_assert (iface->render);
 
-       retval = iface->render_pixbuf (document, rc);
+       retval = iface->render (document, rc);
 
        return retval;
 }
index 33b7f4d3a09b54563579769ff63fd830dc65e8a4..ce887fc6e0c3a35d360b741efa31b74ac0818914 100644 (file)
@@ -25,6 +25,7 @@
 #include <glib-object.h>
 #include <glib.h>
 #include <gdk/gdk.h>
+#include <cairo.h>
 
 #include "ev-link.h"
 #include "ev-document-info.h"
 
 G_BEGIN_DECLS
 
-#define EV_TYPE_DOCUMENT           (ev_document_get_type ())
-#define EV_DOCUMENT(o)             (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument))
-#define EV_DOCUMENT_IFACE(k)       (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface))
-#define EV_IS_DOCUMENT(o)          (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT))
-#define EV_IS_DOCUMENT_IFACE(k)            (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT))
+#define EV_TYPE_DOCUMENT            (ev_document_get_type ())
+#define EV_DOCUMENT(o)              (G_TYPE_CHECK_INSTANCE_CAST ((o), EV_TYPE_DOCUMENT, EvDocument))
+#define EV_DOCUMENT_IFACE(k)        (G_TYPE_CHECK_CLASS_CAST((k), EV_TYPE_DOCUMENT, EvDocumentIface))
+#define EV_IS_DOCUMENT(o)           (G_TYPE_CHECK_INSTANCE_TYPE ((o), EV_TYPE_DOCUMENT))
+#define EV_IS_DOCUMENT_IFACE(k)     (G_TYPE_CHECK_CLASS_TYPE ((k), EV_TYPE_DOCUMENT))
 #define EV_DOCUMENT_GET_IFACE(inst) (G_TYPE_INSTANCE_GET_INTERFACE ((inst), EV_TYPE_DOCUMENT, EvDocumentIface))
 
-typedef struct _EvDocument       EvDocument;
+typedef struct _EvDocument        EvDocument;
 typedef struct _EvDocumentIface   EvDocumentIface;
 typedef struct _EvPageCache       EvPageCache;
 typedef struct _EvPageCacheClass  EvPageCacheClass;
@@ -50,91 +51,91 @@ typedef struct _EvPageCacheClass  EvPageCacheClass;
 
 typedef enum
 {
-       EV_DOCUMENT_ERROR_INVALID,
-       EV_DOCUMENT_ERROR_ENCRYPTED
+        EV_DOCUMENT_ERROR_INVALID,
+        EV_DOCUMENT_ERROR_ENCRYPTED
 } EvDocumentError;
 
 typedef struct {
-       double x;
-       double y;
+        double x;
+        double y;
 } EvPoint;
 
 typedef struct {
-       double x1;
-       double y1;
-       double x2;
-       double y2;
+        double x1;
+        double y1;
+        double x2;
+        double y2;
 } EvRectangle;
 
 struct _EvDocumentIface
 {
-       GTypeInterface base_iface;
-
-       /* Methods  */
-       gboolean         (* load)            (EvDocument   *document,
-                                             const char   *uri,
-                                             GError      **error);
-       gboolean         (* save)            (EvDocument   *document,
-                                             const char   *uri,
-                                             GError      **error);
-       int              (* get_n_pages)     (EvDocument   *document);
-       void             (* get_page_size)   (EvDocument   *document,
-                                             int           page,
-                                             double       *width,
-                                             double       *height);
-       char           * (* get_page_label)  (EvDocument   *document,
-                                             int           page);
-       gboolean         (* can_get_text)    (EvDocument   *document);
-       char           * (* get_text)        (EvDocument   *document,
-                                             int           page,
-                                             EvRectangle  *rect);
-       gboolean         (* has_attachments) (EvDocument   *document);
-       GList          * (* get_attachments) (EvDocument   *document);
-       GdkPixbuf      * (* render_pixbuf)   (EvDocument      *document,
-                                             EvRenderContext *rc);
-       EvDocumentInfo * (* get_info)        (EvDocument   *document);
+        GTypeInterface base_iface;
+
+        /* Methods  */
+        gboolean          (* load)            (EvDocument      *document,
+                                               const char      *uri,
+                                               GError         **error);
+        gboolean          (* save)            (EvDocument      *document,
+                                               const char      *uri,
+                                               GError         **error);
+        int               (* get_n_pages)     (EvDocument      *document);
+        void              (* get_page_size)   (EvDocument      *document,
+                                               int              page,
+                                               double          *width,
+                                               double          *height);
+        char            * (* get_page_label)  (EvDocument      *document,
+                                               int              page);
+        gboolean          (* can_get_text)    (EvDocument      *document);
+        char            * (* get_text)        (EvDocument      *document,
+                                               int              page,
+                                               EvRectangle     *rect);
+        gboolean          (* has_attachments) (EvDocument      *document);
+        GList           * (* get_attachments) (EvDocument      *document);
+        cairo_surface_t * (* render)          (EvDocument      *document,
+                                               EvRenderContext *rc);
+        EvDocumentInfo *  (* get_info)        (EvDocument      *document);
 };
 
-GType          ev_document_get_type       (void);
-GQuark         ev_document_error_quark    (void);
+GType            ev_document_get_type         (void) G_GNUC_CONST;
+GQuark           ev_document_error_quark      (void);
 
 /* Document mutex */
-GMutex        *ev_document_get_doc_mutex    (void);
-void            ev_document_doc_mutex_lock   (void);
-void            ev_document_doc_mutex_unlock (void);
+GMutex          *ev_document_get_doc_mutex    (void);
+void             ev_document_doc_mutex_lock   (void);
+void             ev_document_doc_mutex_unlock (void);
 
 /* FontConfig mutex */
-GMutex         *ev_document_get_fc_mutex    (void);
-void            ev_document_fc_mutex_lock   (void);
-void            ev_document_fc_mutex_unlock (void);
-
-EvDocumentInfo *ev_document_get_info       (EvDocument     *document);
-gboolean       ev_document_load            (EvDocument     *document,
-                                            const char     *uri,
-                                            GError        **error);
-gboolean       ev_document_save            (EvDocument     *document,
-                                            const char     *uri,
-                                            GError        **error);
-int            ev_document_get_n_pages     (EvDocument     *document);
-void           ev_document_get_page_size   (EvDocument     *document,
-                                            int             page,
-                                            double         *width,
-                                            double         *height);
-char          *ev_document_get_page_label  (EvDocument     *document,
-                                            int             page);
-gboolean       ev_document_can_get_text    (EvDocument     *document);
-char          *ev_document_get_text        (EvDocument     *document,
-                                            int             page,
-                                            EvRectangle    *rect);
-gboolean        ev_document_has_attachments (EvDocument     *document);
-GList          *ev_document_get_attachments (EvDocument     *document);
-GdkPixbuf      *ev_document_render_pixbuf   (EvDocument     *document,
-                                            EvRenderContext *rc);
-
-gint            ev_rect_cmp                 (EvRectangle    *a,
-                                            EvRectangle    *b);
+GMutex          *ev_document_get_fc_mutex     (void);
+void             ev_document_fc_mutex_lock    (void);
+void             ev_document_fc_mutex_unlock  (void);
+
+EvDocumentInfo  *ev_document_get_info         (EvDocument      *document);
+gboolean         ev_document_load             (EvDocument      *document,
+                                               const char      *uri,
+                                               GError         **error);
+gboolean         ev_document_save             (EvDocument      *document,
+                                               const char      *uri,
+                                               GError         **error);
+int              ev_document_get_n_pages      (EvDocument      *document);
+void             ev_document_get_page_size    (EvDocument      *document,
+                                               int              page,
+                                               double          *width,
+                                               double          *height);
+char            *ev_document_get_page_label   (EvDocument      *document,
+                                               int              page);
+gboolean         ev_document_can_get_text     (EvDocument      *document);
+char            *ev_document_get_text         (EvDocument      *document,
+                                               int              page,
+                                               EvRectangle     *rect);
+gboolean         ev_document_has_attachments  (EvDocument      *document);
+GList           *ev_document_get_attachments  (EvDocument      *document);
+cairo_surface_t *ev_document_render           (EvDocument      *document,
+                                               EvRenderContext *rc);
+
+gint            ev_rect_cmp                   (EvRectangle    *a,
+                                               EvRectangle    *b);
 
 
 G_END_DECLS
 
-#endif
+#endif /* EV_DOCUMENT_H */
index 2aa45a7cafbd86710695389202ad107a6fead542..f7aee2f79045c68ac2b4f273b85fd819e8f22ef2 100644 (file)
@@ -59,7 +59,7 @@ ev_selection_base_init (gpointer g_class)
 void
 ev_selection_render_selection (EvSelection      *selection,
                               EvRenderContext  *rc,
-                              GdkPixbuf       **pixbuf,
+                              cairo_surface_t **surface,
                               EvRectangle      *points,
                               EvRectangle      *old_points,
                               GdkColor        *text,
@@ -68,7 +68,7 @@ ev_selection_render_selection (EvSelection      *selection,
        EvSelectionIface *iface = EV_SELECTION_GET_IFACE (selection);
 
        iface->render_selection (selection, rc,
-                                pixbuf,
+                                surface,
                                 points, old_points,
                                 text, base);
 }
index d0816040b16380c0f81bdae5b300dcdf6127dfbc..5ba9776d734d1f4f249bd347ead007085f713f8b 100644 (file)
@@ -45,7 +45,7 @@ struct _EvSelectionIface
 
        void        (* render_selection)     (EvSelection      *selection,
                                              EvRenderContext  *rc,
-                                             GdkPixbuf       **pixbuf,
+                                             cairo_surface_t **surface,
                                              EvRectangle      *points,
                                              EvRectangle      *old_points,
                                              GdkColor        *text,
@@ -60,7 +60,7 @@ struct _EvSelectionIface
 GType      ev_selection_get_type             (void);
 void       ev_selection_render_selection     (EvSelection      *selection,
                                              EvRenderContext  *rc,
-                                             GdkPixbuf       **pixbuf,
+                                             cairo_surface_t **surface,
                                              EvRectangle      *points,
                                              EvRectangle      *old_points,
                                              GdkColor         *text,
index 6ad4dfcaa876e5a4f64ed7e59c9ecaf20809883b..d9cdac8ae33c20e751c184e4c199d8d936ce2a9d 100644 (file)
@@ -4,6 +4,7 @@
 #include "ev-document-links.h"
 #include "ev-document-images.h"
 #include "ev-document-factory.h"
+#include "ev-document-misc.h"
 #include "ev-file-helpers.h"
 #include "ev-document-fonts.h"
 #include "ev-selection.h"
@@ -120,9 +121,9 @@ ev_job_render_dispose (GObject *object)
 
        job = EV_JOB_RENDER (object);
 
-       if (job->pixbuf) {
-               g_object_unref (job->pixbuf);
-               job->pixbuf = NULL;
+       if (job->surface) {
+               cairo_surface_destroy (job->surface);
+               job->surface = NULL;
        }
 
        if (job->rc) {
@@ -131,7 +132,7 @@ ev_job_render_dispose (GObject *object)
        }
 
        if (job->selection) {
-               g_object_unref (job->selection);
+               cairo_surface_destroy (job->selection);
                job->selection = NULL;
        }
 
@@ -299,13 +300,16 @@ ev_job_render_new (EvDocument      *document,
 }
 
 static void
-render_finished_cb (EvDocument *document, GdkPixbuf *pixbuf, EvJobRender *job)
+render_finished_cb (EvDocument      *document,
+                   GdkPixbuf       *pixbuf,
+                   EvJobRender     *job)
 {
        g_signal_handlers_disconnect_by_func (EV_JOB (job)->document,
                                              render_finished_cb, job);
 
+       /* FIXME: ps backend should be ported to cairo */
+       job->surface = ev_document_misc_surface_from_pixbuf (pixbuf);
        EV_JOB (job)->finished = TRUE;
-       job->pixbuf = g_object_ref (pixbuf);
        ev_job_finished (EV_JOB (job));
 }
 
@@ -325,7 +329,7 @@ ev_job_render_run (EvJobRender *job)
        } else {
                ev_document_fc_mutex_lock ();
                
-               job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, job->rc);
+               job->surface = ev_document_render (EV_JOB (job)->document, job->rc);
                if (job->include_links && EV_IS_DOCUMENT_LINKS (EV_JOB (job)->document))
                        job->link_mapping =
                                ev_document_links_get_links (EV_DOCUMENT_LINKS (EV_JOB (job)->document),
index 1f210ece96ab99aa7ee728f3f5780d449531a029..fc681d371a2ec43d3eead18ab954d4f8b51bb562 100644 (file)
@@ -121,13 +121,13 @@ struct _EvJobRender
        EvRenderContext *rc;
        gint target_width;
        gint target_height;
-       GdkPixbuf *pixbuf;
+       cairo_surface_t *surface;
 
        GList *link_mapping;
        GdkRegion *text_mapping;
        GList *image_mapping;
 
-       GdkPixbuf *selection;
+       cairo_surface_t *selection;
        GdkRegion *selection_region;
        EvRectangle selection_points;
        GdkColor base;
index 777e0147c508a9586b3e1417b3a52e451de5b9bd..2c815c099c181c4b92cffcfdd89af095e403c88b 100644 (file)
@@ -11,7 +11,7 @@ typedef struct _CacheJobInfo
        EvRenderContext *rc;
 
        /* Data we get from rendering */
-       GdkPixbuf *pixbuf;
+       cairo_surface_t *surface;
        GList *link_mapping;
        GList *image_mapping;
        GdkRegion *text_mapping;
@@ -23,7 +23,7 @@ typedef struct _CacheJobInfo
        EvRectangle target_points;
        gboolean    points_set;
        
-       GdkPixbuf *selection;
+       cairo_surface_t *selection;
        GdkRegion *selection_region;
 } CacheJobInfo;
 
@@ -74,10 +74,10 @@ static CacheJobInfo *find_job_cache             (EvPixbufCache      *pixbuf_cach
 static void          copy_job_to_job_info       (EvJobRender        *job_render,
                                                 CacheJobInfo       *job_info,
                                                 EvPixbufCache      *pixbuf_cache);
-static gboolean      new_selection_pixbuf_needed(EvPixbufCache      *pixbuf_cache,
-                                                CacheJobInfo       *job_info,
-                                                gint                page,
-                                                gfloat              scale);
+static gboolean      new_selection_surface_needed(EvPixbufCache      *pixbuf_cache,
+                                                 CacheJobInfo       *job_info,
+                                                 gint                page,
+                                                 gfloat              scale);
 
 
 /* These are used for iterating through the prev and next arrays */
@@ -149,9 +149,9 @@ dispose_cache_job_info (CacheJobInfo *job_info,
                g_object_unref (G_OBJECT (job_info->job));
                job_info->job = NULL;
        }
-       if (job_info->pixbuf) {
-               g_object_unref (G_OBJECT (job_info->pixbuf));
-               job_info->pixbuf = NULL;
+       if (job_info->surface) {
+               cairo_surface_destroy (job_info->surface);
+               job_info->surface = NULL;
        }
        if (job_info->link_mapping) {
                ev_link_mapping_free (job_info->link_mapping);
@@ -166,7 +166,7 @@ dispose_cache_job_info (CacheJobInfo *job_info,
                job_info->text_mapping = NULL;
        }
        if (job_info->selection) {
-               g_object_unref (G_OBJECT (job_info->selection));
+               cairo_surface_destroy (job_info->selection);
                job_info->selection = NULL;
        }
        if (job_info->selection_region) {
@@ -321,7 +321,7 @@ move_one_job (CacheJobInfo  *job_info,
 
        *target_page = *job_info;
        job_info->job = NULL;
-       job_info->pixbuf = NULL;
+       job_info->surface = NULL;
        job_info->link_mapping = NULL;
        job_info->image_mapping = NULL;
 
@@ -411,10 +411,10 @@ copy_job_to_job_info (EvJobRender   *job_render,
 
        job_info->points_set = FALSE;
 
-       if (job_info->pixbuf) {
-               g_object_unref (G_OBJECT (job_info->pixbuf));
+       if (job_info->surface) {
+               cairo_surface_destroy (job_info->surface);
        }
-       job_info->pixbuf = g_object_ref (job_render->pixbuf);
+       job_info->surface = cairo_surface_reference (job_render->surface);
 
        if (job_info->rc) {
                g_object_unref (G_OBJECT (job_info->rc));
@@ -441,7 +441,7 @@ copy_job_to_job_info (EvJobRender   *job_render,
 
        if (job_render->include_selection) {
                if (job_info->selection) {
-                       g_object_unref (G_OBJECT (job_info->selection));
+                       cairo_surface_destroy (job_info->selection);
                        job_info->selection = NULL;
                }
                if (job_info->selection_region) {
@@ -451,7 +451,7 @@ copy_job_to_job_info (EvJobRender   *job_render,
                
                job_info->selection_points = job_render->selection_points;
                job_info->selection_region = gdk_region_copy (job_render->selection_region);
-               job_info->selection = g_object_ref (job_render->selection);
+               job_info->selection = cairo_surface_reference (job_render->selection);
                g_assert (job_info->selection_points.x1 >= 0);
                job_info->points_set = TRUE;
        }
@@ -554,9 +554,9 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
        ev_page_cache_get_size (page_cache, page, rotation,
                                scale, &width, &height);
 
-       if (job_info->pixbuf &&
-           gdk_pixbuf_get_width (job_info->pixbuf) == width &&
-           gdk_pixbuf_get_height (job_info->pixbuf) == height)
+       if (job_info->surface &&
+           cairo_image_surface_get_width (job_info->surface) == width &&
+           cairo_image_surface_get_height (job_info->surface) == height)
                return;
 
        /* make a new job now */
@@ -575,7 +575,7 @@ add_job_if_needed (EvPixbufCache *pixbuf_cache,
                include_images = TRUE;
        if (job_info->text_mapping == NULL)
                include_text = TRUE;
-       if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) {
+       if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
                include_selection = TRUE;
        }
 
@@ -672,9 +672,9 @@ ev_pixbuf_cache_set_page_range (EvPixbufCache  *pixbuf_cache,
        ev_pixbuf_cache_add_jobs_if_needed (pixbuf_cache, rotation, scale);
 }
 
-GdkPixbuf *
-ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache,
-                           gint           page)
+cairo_surface_t *
+ev_pixbuf_cache_get_surface (EvPixbufCache *pixbuf_cache,
+                            gint           page)
 {
        CacheJobInfo *job_info;
 
@@ -688,7 +688,7 @@ ev_pixbuf_cache_get_pixbuf (EvPixbufCache *pixbuf_cache,
                copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache);
        }
 
-       return job_info->pixbuf;
+       return job_info->surface;
 }
 
 GList *
@@ -733,26 +733,32 @@ ev_pixbuf_cache_get_image_mapping (EvPixbufCache *pixbuf_cache,
 }
 
 static gboolean
-new_selection_pixbuf_needed (EvPixbufCache *pixbuf_cache,
+new_selection_surface_needed (EvPixbufCache *pixbuf_cache,
                             CacheJobInfo  *job_info,
                             gint           page,
                             gfloat         scale)
 {
        EvPageCache *page_cache;
-       gint width, height;
 
        if (job_info->selection) {
+               gint width, height;
+               gint selection_width, selection_height;
+               
                page_cache = ev_page_cache_get (pixbuf_cache->document);
-               ev_page_cache_get_size (page_cache, page, job_info->rc->rotation,
+               ev_page_cache_get_size (page_cache, page,
+                                       job_info->rc->rotation,
                                        scale, &width, &height);
+
+               selection_width = cairo_image_surface_get_width (job_info->selection);
+               selection_height = cairo_image_surface_get_height (job_info->selection);
                
-               if (width != gdk_pixbuf_get_width (job_info->selection) ||
-                   height != gdk_pixbuf_get_height (job_info->selection))
+               if (width != selection_width || height != selection_height)
                        return TRUE;
        } else {
                if (job_info->points_set)
                        return TRUE;
        }
+       
        return FALSE;
 }
 
@@ -762,9 +768,9 @@ clear_selection_if_needed (EvPixbufCache *pixbuf_cache,
                           gint           page,
                           gfloat         scale)
 {
-       if (new_selection_pixbuf_needed (pixbuf_cache, job_info, page, scale)) {
+       if (new_selection_surface_needed (pixbuf_cache, job_info, page, scale)) {
                if (job_info->selection)
-                       g_object_unref (job_info->selection);
+                       cairo_surface_destroy (job_info->selection);
                job_info->selection = NULL;
                job_info->selection_points.x1 = -1;
        }
@@ -818,13 +824,13 @@ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache)
 
                job_info = pixbuf_cache->prev_job + i;
                if (job_info->selection) {
-                       g_object_unref (G_OBJECT (job_info->selection));
+                       cairo_surface_destroy (job_info->selection);
                        job_info->selection = NULL;
                }
 
                job_info = pixbuf_cache->next_job + i;
                if (job_info->selection) {
-                       g_object_unref (G_OBJECT (job_info->selection));
+                       cairo_surface_destroy (job_info->selection);
                        job_info->selection = NULL;
                }
        }
@@ -834,17 +840,17 @@ ev_pixbuf_cache_style_changed (EvPixbufCache *pixbuf_cache)
 
                job_info = pixbuf_cache->job_list + i;
                if (job_info->selection) {
-                       g_object_unref (G_OBJECT (job_info->selection));
+                       cairo_surface_destroy (job_info->selection);
                        job_info->selection = NULL;
                }
        }
 }
 
-GdkPixbuf *
-ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache  *pixbuf_cache,
-                                     gint            page,
-                                     gfloat          scale,
-                                     GdkRegion     **region)
+cairo_surface_t *
+ev_pixbuf_cache_get_selection_surface (EvPixbufCache  *pixbuf_cache,
+                                      gint            page,
+                                      gfloat          scale,
+                                      GdkRegion     **region)
 {
        CacheJobInfo *job_info;
 
@@ -932,7 +938,7 @@ clear_job_selection (CacheJobInfo *job_info)
        job_info->selection_points.x1 = -1;
 
        if (job_info->selection) {
-               g_object_unref (job_info->selection);
+               cairo_surface_destroy (job_info->selection);
                job_info->selection = NULL;
        }
 }
index 6f96dc18f91efe633c673ec380c8da3b62cc30f6..79e0810a0f2956486f8ef6215f05acd6e5934393 100644 (file)
@@ -57,7 +57,7 @@ void           ev_pixbuf_cache_set_page_range       (EvPixbufCache *pixbuf_cache
                                                     gint           rotation,
                                                     gfloat         scale,
                                                     GList          *selection_list);
-GdkPixbuf     *ev_pixbuf_cache_get_pixbuf           (EvPixbufCache *pixbuf_cache,
+cairo_surface_t *ev_pixbuf_cache_get_surface        (EvPixbufCache *pixbuf_cache,
                                                     gint           page);
 GList         *ev_pixbuf_cache_get_link_mapping     (EvPixbufCache *pixbuf_cache,
                                                     gint           page);
@@ -69,10 +69,10 @@ void           ev_pixbuf_cache_clear                (EvPixbufCache *pixbuf_cache
 void           ev_pixbuf_cache_style_changed        (EvPixbufCache *pixbuf_cache);
 
 /* Selection */
-GdkPixbuf     *ev_pixbuf_cache_get_selection_pixbuf (EvPixbufCache *pixbuf_cache,
-                                                    gint           page,
-                                                    gfloat         scale,
-                                                    GdkRegion     **region);
+cairo_surface_t *ev_pixbuf_cache_get_selection_surface (EvPixbufCache *pixbuf_cache,
+                                                       gint           page,
+                                                       gfloat         scale,
+                                                       GdkRegion     **region);
 void           ev_pixbuf_cache_set_selection_list   (EvPixbufCache *pixbuf_cache,
                                                     GList         *selection_list);
 GList         *ev_pixbuf_cache_get_selection_list   (EvPixbufCache *pixbuf_cache);
index bcf3374e2592bd6fae556394abd203e6d3c1cf10..ba69b27cb7bda5022d7f39150d36a42eea145707 100644 (file)
@@ -2003,6 +2003,9 @@ ev_view_button_press_event (GtkWidget      *widget,
                                        view->selection_info.in_drag = TRUE;
                                } else {
                                        clear_selection (view);
+                                       
+                                       view->selection_info.start.x = event->x + view->scroll_x;
+                                       view->selection_info.start.y = event->y + view->scroll_y;
                                }
                                
                                gtk_widget_queue_draw (widget);
@@ -2015,10 +2018,10 @@ ev_view_button_press_event (GtkWidget      *widget,
 
                                view->image_dnd_info.start.x = event->x + view->scroll_x;
                                view->image_dnd_info.start.y = event->y + view->scroll_y;
+                       } else {
+                               view->selection_info.start.x = event->x + view->scroll_x;
+                               view->selection_info.start.y = event->y + view->scroll_y;
                        }
-
-                       view->selection_info.start.x = event->x + view->scroll_x;
-                       view->selection_info.start.y = event->y + view->scroll_y;
                }                       
                        return TRUE;
                case 2:
@@ -2773,8 +2776,6 @@ highlight_find_results (EvView *view, int page)
        EvDocumentFind *find;
        int i, results = 0;
 
-       g_return_if_fail (EV_IS_DOCUMENT_FIND (view->document));
-
        find = EV_DOCUMENT_FIND (view->document);
 
        results = ev_document_find_get_n_results (find, page);
@@ -2804,7 +2805,7 @@ draw_loading_text (EvView       *view,
 {
        cairo_t *cr;
        gint     width, height;
-       
+
        /* Don't annoy users with loading messages during presentations.
         * FIXME: Temporary "workaround" for
         * http://bugzilla.gnome.org/show_bug.cgi?id=320352 */
@@ -2812,17 +2813,15 @@ draw_loading_text (EvView       *view,
                return;
 
        if (!view->loading_text) {
-               const gchar *loading_text;
+               const gchar *loading_text = _("Loading...");
                PangoLayout *layout;
                PangoFontDescription *font_desc;
                PangoRectangle logical_rect;
-               gdouble real_scale;
                gint target_width;
-               
-               loading_text = _("Loading..."); 
+               gdouble real_scale;
 
                ev_document_fc_mutex_lock ();
-               
+
                layout = gtk_widget_create_pango_layout (GTK_WIDGET (view), loading_text);
                
                font_desc = pango_font_description_new ();
@@ -2831,8 +2830,7 @@ draw_loading_text (EvView       *view,
                pango_font_description_set_size (font_desc, 10 * PANGO_SCALE);
                pango_layout_set_font_description (layout, font_desc);
                pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
-               
-               /* Make sure we fit the middle of the page */
+
                target_width = MAX (page_area->width / 2, 1);
                real_scale = ((double)target_width / (double) logical_rect.width) * (PANGO_SCALE * 10);
                pango_font_description_set_size (font_desc, (int)real_scale);
@@ -2860,39 +2858,30 @@ draw_loading_text (EvView       *view,
        height = (page_area->height - cairo_image_surface_get_height (view->loading_text)) / 2;
        
        cr = gdk_cairo_create (GTK_WIDGET (view)->window);
-       cairo_set_source_surface (cr, view->loading_text,
-                                 page_area->x + width,
-                                 page_area->y + height);
+       cairo_translate (cr,
+                        page_area->x + width,
+                        page_area->y + height);
+       cairo_set_source_surface (cr, view->loading_text, 0, 0);
        cairo_paint (cr);
        cairo_destroy (cr);
 }
 
 static void
-draw_one_page (EvView          *view,
-              gint             page,
-              GdkRectangle    *page_area,
-              GtkBorder       *border,
-              GdkRectangle    *expose_area,
-              gboolean        *page_ready)
+draw_one_page (EvView       *view,
+              gint          page,
+              GdkRectangle *page_area,
+              GtkBorder    *border,
+              GdkRectangle *expose_area,
+              gboolean     *page_ready)
 {
-       gint width, height;
-       GdkPixbuf *current_pixbuf;
        GdkRectangle overlap;
        GdkRectangle real_page_area;
-       EvViewSelection *selection;
-       gint current_page;
 
        g_assert (view->document);
 
        if (! gdk_rectangle_intersect (page_area, expose_area, &overlap))
                return;
-       
-       current_page = ev_page_cache_get_current_page (view->page_cache);
-       selection = find_selection_for_page (view, page);
-       ev_page_cache_get_size (view->page_cache,
-                               page, view->rotation,
-                               view->scale,
-                               &width, &height);
+
        /* Render the document itself */
        real_page_area = *page_area;
 
@@ -2903,80 +2892,100 @@ draw_one_page (EvView          *view,
        *page_ready = TRUE;
 
        if (!view->presentation) {
-               ev_document_misc_paint_one_page (GTK_WIDGET(view)->window,
+               gint current_page;
+
+               current_page = ev_page_cache_get_current_page (view->page_cache);
+               ev_document_misc_paint_one_page (GTK_WIDGET (view)->window,
                                                 GTK_WIDGET (view),
                                                 page_area, border, 
                                                 page == current_page);
        }
 
        if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) {
-               GdkPixbuf *selection_pixbuf = NULL;
-               GdkPixbuf *scaled_image;
-               GdkPixbuf *scaled_selection;
+               gint             width, height;
+               gint             page_width, page_height;
+               cairo_surface_t *page_surface = NULL;
+               gint             selection_width, selection_height;
+               cairo_surface_t *selection_surface = NULL;
+               cairo_t         *cr = NULL;
 
-               current_pixbuf = ev_pixbuf_cache_get_pixbuf (view->pixbuf_cache, page);
+               page_surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page);
 
-               /* Get the selection pixbuf iff we have something to draw */
-               if (current_pixbuf && view->selection_mode == EV_VIEW_SELECTION_TEXT && selection)
-                       selection_pixbuf = ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
-                                                                                page,
-                                                                                view->scale,
-                                                                                NULL);
-
-               if (current_pixbuf == NULL)
-                       scaled_image = NULL;
-               else if (width == gdk_pixbuf_get_width (current_pixbuf) &&
-                        height == gdk_pixbuf_get_height (current_pixbuf))
-                       scaled_image = g_object_ref (current_pixbuf);
-               else
-                       /* FIXME: We don't want to scale the whole area, just the right
-                        * area of it */
-                       scaled_image = gdk_pixbuf_scale_simple (current_pixbuf,
-                                                               width, height,
-                                                               GDK_INTERP_NEAREST);
-
-               if (selection_pixbuf == NULL)
-                       scaled_selection = NULL;
-               else if (width == gdk_pixbuf_get_width (selection_pixbuf) &&
-                        height == gdk_pixbuf_get_height (selection_pixbuf))
-                       scaled_selection = g_object_ref (selection_pixbuf);
-               else
-                       /* FIXME: We don't want to scale the whole area, just the right
-                        * area of it */
-                       scaled_selection = gdk_pixbuf_scale_simple (selection_pixbuf,
-                                                                   width, height,
-                                                                   GDK_INTERP_NEAREST);
-
-               if (scaled_image) {
-                       gdk_draw_pixbuf (GTK_WIDGET(view)->window,
-                                        GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL],
-                                        scaled_image,
-                                        overlap.x - real_page_area.x,
-                                        overlap.y - real_page_area.y,
-                                        overlap.x, overlap.y,
-                                        overlap.width, overlap.height,
-                                        GDK_RGB_DITHER_NORMAL,
-                                        0, 0);
-                       g_object_unref (scaled_image);
-               } else {
+               if (!page_surface) {
                        draw_loading_text (view,
                                           &real_page_area,
                                           expose_area);
                        *page_ready = FALSE;
+
+                       return;
+               }
+
+               ev_page_cache_get_size (view->page_cache,
+                                       page, view->rotation,
+                                       view->scale,
+                                       &width, &height);
+
+               cr = gdk_cairo_create (GTK_WIDGET (view)->window);
+               
+               cairo_save (cr);
+               
+               page_width = cairo_image_surface_get_width (page_surface);
+               page_height = cairo_image_surface_get_height (page_surface);
+
+               cairo_translate (cr, overlap.x, overlap.y);
+               
+               if (width != page_width || height != page_height) {
+                       cairo_pattern_set_filter (cairo_get_source (cr),
+                                                 CAIRO_FILTER_FAST);
+                       cairo_scale (cr,
+                                    (gdouble)width / page_width,
+                                    (gdouble)height / page_height);
                }
 
-               if (scaled_selection) {
-                       gdk_draw_pixbuf (GTK_WIDGET(view)->window,
-                                        GTK_WIDGET (view)->style->fg_gc[GTK_STATE_NORMAL],
-                                        scaled_selection,
-                                        overlap.x - real_page_area.x,
-                                        overlap.y - real_page_area.y,
-                                        overlap.x, overlap.y,
-                                        overlap.width, overlap.height,
-                                        GDK_RGB_DITHER_NORMAL,
-                                        0, 0);
-                       g_object_unref (scaled_selection);
+               cairo_surface_set_device_offset (page_surface,
+                                                overlap.x - real_page_area.x,
+                                                overlap.y - real_page_area.y);
+
+               cairo_set_source_surface (cr, page_surface, 0, 0);
+               cairo_paint (cr);
+
+               cairo_restore (cr);
+               
+               /* Get the selection pixbuf iff we have something to draw */
+               if (find_selection_for_page (view, page) &&
+                   view->selection_mode == EV_VIEW_SELECTION_TEXT) {
+                       selection_surface =
+                               ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
+                                                                      page,
+                                                                      view->scale,
+                                                                      NULL);
+               }
+
+               if (!selection_surface) {
+                       cairo_destroy (cr);
+                       return;
                }
+
+               selection_width = cairo_image_surface_get_width (selection_surface);
+               selection_height = cairo_image_surface_get_height (selection_surface);
+
+               cairo_translate (cr, overlap.x, overlap.y);
+
+               if (width != selection_width || height != selection_height) {
+                       cairo_pattern_set_filter (cairo_get_source (cr),
+                                                 CAIRO_FILTER_FAST);
+                       cairo_scale (cr,
+                                    (gdouble)width / selection_width,
+                                    (gdouble)height / selection_height);
+               }
+
+               cairo_surface_set_device_offset (selection_surface,
+                                                overlap.x - real_page_area.x,
+                                                overlap.y - real_page_area.y);
+
+               cairo_set_source_surface (cr, selection_surface, 0, 0);
+               cairo_paint (cr);
+               cairo_destroy (cr);
        }
 }
 
@@ -3569,7 +3578,7 @@ ev_view_set_zoom (EvView   *view,
                cairo_surface_destroy (view->loading_text);
                view->loading_text = NULL;
        }
-       
+
        view->scale = scale;
        view->pending_resize = TRUE;
 
@@ -4453,8 +4462,6 @@ compute_new_selection_text (EvView   *view,
 
        }
 
-
-
        /* Now create a list of EvViewSelection's for the affected
         * pages.  This could be an empty list, a list of just one
         * page or a number of pages.*/
@@ -4561,10 +4568,12 @@ merge_selection_region (EvView *view,
                 * region too. */
                if (new_sel) {
                        GdkRegion *tmp_region = NULL;
-                       ev_pixbuf_cache_get_selection_pixbuf (view->pixbuf_cache,
-                                                             cur_page,
-                                                             view->scale,
-                                                             &tmp_region);
+
+                       ev_pixbuf_cache_get_selection_surface (view->pixbuf_cache,
+                                                              cur_page,
+                                                              view->scale,
+                                                              &tmp_region);
+
                        if (tmp_region) {
                                new_sel->covered_region = gdk_region_copy (tmp_region);
                        }
@@ -4572,8 +4581,7 @@ merge_selection_region (EvView *view,
 
                /* Now we figure out what needs redrawing */
                if (old_sel && new_sel) {
-                       if (old_sel->covered_region &&
-                           new_sel->covered_region) {
+                       if (old_sel->covered_region && new_sel->covered_region) {
                                /* We only want to redraw the areas that have
                                 * changed, so we xor the old and new regions
                                 * and redraw if it's different */
@@ -4605,6 +4613,12 @@ merge_selection_region (EvView *view,
                        GdkRectangle page_area;
                        GtkBorder border;
 
+                       /* I don't know why but the region is smaller
+                        * than expected. This hack fixes it, I guess
+                        * 10 pixels more won't hurt
+                        */
+                       gdk_region_shrink (region, -5, -5);
+
                        get_page_extents (view, cur_page, &page_area, &border);
                        gdk_region_offset (region,
                                           page_area.x + border.left - view->scroll_x,