Index: backend/ev-document-misc.c =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document-misc.c,v retrieving revision 1.7 diff -u -u -r1.7 ev-document-misc.c --- backend/ev-document-misc.c 24 Feb 2006 19:13:39 -0000 1.7 +++ backend/ev-document-misc.c 6 Dec 2006 17:21:44 -0000 @@ -139,3 +139,20 @@ 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; +} Index: backend/ev-document-misc.h =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document-misc.h,v retrieving revision 1.5 diff -u -u -r1.5 ev-document-misc.h --- backend/ev-document-misc.h 24 Feb 2006 19:13:39 -0000 1.5 +++ backend/ev-document-misc.h 6 Dec 2006 17:21:44 -0000 @@ -25,6 +25,7 @@ #include #include +#include G_BEGIN_DECLS @@ -41,6 +42,7 @@ GdkRectangle *area, GtkBorder *border, gboolean highlight); +cairo_surface_t *ev_document_misc_surface_from_pixbuf (GdkPixbuf *pixbuf); G_END_DECLS Index: backend/ev-document.c =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.c,v retrieving revision 1.36 diff -u -u -r1.36 ev-document.c --- backend/ev-document.c 8 Oct 2006 12:35:39 -0000 1.36 +++ backend/ev-document.c 6 Dec 2006 17:21:44 -0000 @@ -210,6 +210,20 @@ return retval; } +cairo_surface_t * +ev_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + EvDocumentIface *iface = EV_DOCUMENT_GET_IFACE (document); + cairo_surface_t *retval = NULL; + + LOG ("ev_document_render_surface"); + if (iface->render_surface) + retval = iface->render_surface (document, rc); + + return retval; +} + GdkPixbuf * ev_document_render_pixbuf (EvDocument *document, EvRenderContext *rc) Index: backend/ev-document.h =================================================================== RCS file: /cvs/gnome/evince/backend/ev-document.h,v retrieving revision 1.34 diff -u -u -r1.34 ev-document.h --- backend/ev-document.h 2 May 2006 19:02:45 -0000 1.34 +++ backend/ev-document.h 6 Dec 2006 17:21:44 -0000 @@ -25,6 +25,7 @@ #include #include #include +#include #include "ev-link.h" #include "ev-document-info.h" @@ -71,61 +72,65 @@ 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); + 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_surface) (EvDocument *document, + EvRenderContext *rc); GdkPixbuf * (* render_pixbuf) (EvDocument *document, EvRenderContext *rc); - EvDocumentInfo * (* get_info) (EvDocument *document); + EvDocumentInfo * (* get_info) (EvDocument *document); }; -GType ev_document_get_type (void); -GQuark ev_document_error_quark (void); -GMutex *ev_document_get_doc_mutex (void); -void ev_document_doc_mutex_lock (void); -void ev_document_doc_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); +GType ev_document_get_type (void); +GQuark ev_document_error_quark (void); +GMutex *ev_document_get_doc_mutex (void); +void ev_document_doc_mutex_lock (void); +void ev_document_doc_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_surface (EvDocument *document, + EvRenderContext *rc); +GdkPixbuf *ev_document_render_pixbuf (EvDocument *document, + EvRenderContext *rc); -gint ev_rect_cmp (EvRectangle *a, - EvRectangle *b); +gint ev_rect_cmp (EvRectangle *a, + EvRectangle *b); G_END_DECLS Index: djvu/djvu-document.c =================================================================== RCS file: /cvs/gnome/evince/djvu/djvu-document.c,v retrieving revision 1.16 diff -u -u -r1.16 djvu-document.c --- djvu/djvu-document.c 3 Dec 2006 15:54:22 -0000 1.16 +++ djvu/djvu-document.c 6 Dec 2006 17:21:44 -0000 @@ -202,6 +202,21 @@ return rotated_pixbuf; } +static cairo_surface_t * +djvu_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + DjvuDocument *djvu_document = DJVU_DOCUMENT (document); + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + + pixbuf = djvu_document_render_pixbuf (document, rc); + surface = ev_document_misc_surface_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return surface; +} + static void djvu_document_finalize (GObject *object) { @@ -274,6 +289,7 @@ 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_surface = djvu_document_render_surface; iface->get_info = djvu_document_get_info; } Index: dvi/dvi-document.c =================================================================== RCS file: /cvs/gnome/evince/dvi/dvi-document.c,v retrieving revision 1.13 diff -u -u -r1.13 dvi-document.c --- dvi/dvi-document.c 16 Nov 2006 15:58:36 -0000 1.13 +++ dvi/dvi-document.c 6 Dec 2006 17:21:44 -0000 @@ -202,6 +202,20 @@ return rotated_pixbuf; } +static cairo_surface_t * +dvi_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + + pixbuf = dvi_document_render_pixbuf (document, rc); + surface = ev_document_misc_surface_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return surface; +} + static void dvi_document_finalize (GObject *object) { @@ -262,6 +276,7 @@ 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_surface = dvi_document_render_surface; iface->get_info = dvi_document_get_info; } Index: impress/impress-document.c =================================================================== RCS file: /cvs/gnome/evince/impress/impress-document.c,v retrieving revision 1.1 diff -u -u -r1.1 impress-document.c --- impress/impress-document.c 10 Jul 2006 21:03:38 -0000 1.1 +++ impress/impress-document.c 6 Dec 2006 17:21:44 -0000 @@ -392,6 +392,21 @@ return scaled_pixbuf; } +static cairo_surface_t * +impress_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + ImpressDocument *impress_document = IMPRESS_DOCUMENT (document); + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + + pixbuf = impress_document_render_pixbuf (document, rc); + surface = ev_document_misc_surface_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return surface; +} + static void impress_document_finalize (GObject *object) { @@ -442,6 +457,7 @@ 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_surface = impress_document_render_surface; iface->get_info = impress_document_get_info; } Index: pdf/ev-poppler.cc =================================================================== RCS file: /cvs/gnome/evince/pdf/ev-poppler.cc,v retrieving revision 1.74 diff -u -u -r1.74 ev-poppler.cc --- pdf/ev-poppler.cc 4 Dec 2006 11:53:24 -0000 1.74 +++ pdf/ev-poppler.cc 6 Dec 2006 17:21:45 -0000 @@ -413,7 +413,7 @@ } static GdkPixbuf * -pdf_document_render_pixbuf (EvDocument *document, +pdf_document_render_pixbuf (EvDocument *document, EvRenderContext *rc) { PdfDocument *pdf_document; @@ -450,6 +450,71 @@ return pixbuf; } +#ifdef HAVE_POPPLER_PAGE_RENDER +static cairo_surface_t * +pdf_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + PdfDocument *pdf_document; + cairo_surface_t *surface; + double width_points, height_points; + gint width, height; + cairo_t *cr; + + pdf_document = PDF_DOCUMENT (document); + + set_rc_data (pdf_document, rc); + + poppler_page_get_size (POPPLER_PAGE (rc->data), &width_points, &height_points); + + if (rc->rotation == 90 || rc->rotation == 270) { + width = (int) ((height_points * rc->scale) + 0.5); + height = (int) ((width_points * rc->scale) + 0.5); + } else { + width = (int) ((width_points * rc->scale) + 0.5); + height = (int) ((height_points * rc->scale) + 0.5); + } + + surface = cairo_image_surface_create (CAIRO_FORMAT_ARGB32, + width, height); + 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 * M_PI / 180.0); + poppler_page_render (POPPLER_PAGE (rc->data), cr); + cairo_destroy (cr); + + return surface; +} +#else +static cairo_surface_t * +pdf_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + GdkPixbuf *pixbuf; + cairo_surface_t *surface; + + pixbuf = pdf_document_render_pixbuf (document, rc); + surface = ev_document_misc_surface_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return surface; +} +#endif /* HAVE_POPPLER_PAGE_RENDER */ + + /* EvDocumentSecurity */ static gboolean @@ -657,6 +722,7 @@ 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_surface = pdf_document_render_surface; iface->render_pixbuf = pdf_document_render_pixbuf; iface->get_text = pdf_document_get_text; iface->can_get_text = pdf_document_can_get_text; Index: shell/ev-jobs.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.c,v retrieving revision 1.25 diff -u -u -r1.25 ev-jobs.c --- shell/ev-jobs.c 3 Dec 2006 20:35:45 -0000 1.25 +++ shell/ev-jobs.c 6 Dec 2006 17:21:45 -0000 @@ -3,6 +3,7 @@ #include "ev-document-thumbnails.h" #include "ev-document-links.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,11 +121,11 @@ 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) { g_object_unref (job->rc); job->rc = NULL; @@ -297,8 +298,9 @@ g_signal_handlers_disconnect_by_func (EV_JOB (job)->document, render_finished_cb, job); + 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)); } @@ -316,7 +318,7 @@ g_signal_connect (EV_JOB (job)->document, "render_finished", G_CALLBACK (render_finished_cb), job); } else { - job->pixbuf = ev_document_render_pixbuf (EV_JOB (job)->document, job->rc); + job->surface = ev_document_render_surface (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: shell/ev-jobs.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-jobs.h,v retrieving revision 1.18 diff -u -u -r1.18 ev-jobs.h --- shell/ev-jobs.h 3 Dec 2006 20:35:45 -0000 1.18 +++ shell/ev-jobs.h 6 Dec 2006 17:21:45 -0000 @@ -121,7 +121,7 @@ EvRenderContext *rc; gint target_width; gint target_height; - GdkPixbuf *pixbuf; + cairo_surface_t *surface; GList *link_mapping; GdkRegion *text_mapping; Index: shell/ev-pixbuf-cache.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.c,v retrieving revision 1.23 diff -u -u -r1.23 ev-pixbuf-cache.c --- shell/ev-pixbuf-cache.c 27 Aug 2006 20:06:18 -0000 1.23 +++ shell/ev-pixbuf-cache.c 6 Dec 2006 17:21:45 -0000 @@ -9,7 +9,7 @@ EvRenderContext *rc; /* Data we get from rendering */ - GdkPixbuf *pixbuf; + cairo_surface_t *surface; GList *link_mapping; GdkRegion *text_mapping; @@ -144,9 +144,9 @@ 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); @@ -310,7 +310,7 @@ *target_page = *job_info; job_info->job = NULL; - job_info->pixbuf = NULL; + job_info->surface = NULL; job_info->link_mapping = NULL; if (new_priority != priority && target_page->job) { @@ -318,8 +318,6 @@ } } - - static void ev_pixbuf_cache_update_range (EvPixbufCache *pixbuf_cache, gint start_page, @@ -399,10 +397,11 @@ 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); + if (job_render->surface) + job_info->surface = cairo_surface_reference (job_render->surface); if (job_info->rc) { g_object_unref (G_OBJECT (job_info->rc)); @@ -421,7 +420,6 @@ job_info->text_mapping = job_render->text_mapping; } - if (job_render->include_selection) { if (job_info->selection) { @@ -447,7 +445,6 @@ g_object_unref (G_OBJECT (job_info->job)); job_info->job = NULL; } - } static CacheJobInfo* @@ -537,9 +534,9 @@ 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 */ @@ -652,9 +649,9 @@ 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; @@ -668,7 +665,7 @@ copy_job_to_job_info (EV_JOB_RENDER (job_info->job), job_info, pixbuf_cache); } - return job_info->pixbuf; + return job_info->surface; } GList * Index: shell/ev-pixbuf-cache.h =================================================================== RCS file: /cvs/gnome/evince/shell/ev-pixbuf-cache.h,v retrieving revision 1.9 diff -u -u -r1.9 ev-pixbuf-cache.h --- shell/ev-pixbuf-cache.h 6 Aug 2005 05:13:20 -0000 1.9 +++ shell/ev-pixbuf-cache.h 6 Dec 2006 17:21:45 -0000 @@ -57,7 +57,7 @@ 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); Index: shell/ev-view.c =================================================================== RCS file: /cvs/gnome/evince/shell/ev-view.c,v retrieving revision 1.213 diff -u -u -r1.213 ev-view.c --- shell/ev-view.c 27 Oct 2006 09:51:45 -0000 1.213 +++ shell/ev-view.c 6 Dec 2006 17:21:46 -0000 @@ -2277,7 +2277,6 @@ gboolean *page_ready) { gint width, height; - GdkPixbuf *current_pixbuf; GdkRectangle overlap; GdkRectangle real_page_area; EvViewSelection *selection; @@ -2310,29 +2309,26 @@ if (gdk_rectangle_intersect (&real_page_area, expose_area, &overlap)) { GdkPixbuf *selection_pixbuf = NULL; - GdkPixbuf *scaled_image; GdkPixbuf *scaled_selection; + gboolean scaled = FALSE; + gint swidth, sheight; + cairo_t *cr; + cairo_surface_t *surface; - current_pixbuf = ev_pixbuf_cache_get_pixbuf (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) + surface = ev_pixbuf_cache_get_surface (view->pixbuf_cache, page); + if (surface && 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 (surface) { + swidth = cairo_image_surface_get_width (surface); + sheight = cairo_image_surface_get_height (surface); + + if (width != swidth || height != sheight) + scaled = TRUE; + } if (selection_pixbuf == NULL) scaled_selection = NULL; @@ -2346,23 +2342,30 @@ 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); + if (surface) { + cr = gdk_cairo_create (GTK_WIDGET(view)->window); + + if (scaled) { + cairo_scale (cr, + (gdouble)width / swidth, + (gdouble)height / sheight); + } + + cairo_surface_set_device_offset (surface, + overlap.x - real_page_area.x, + overlap.y - real_page_area.y); + + cairo_set_source_surface (cr, surface, overlap.x, overlap.y); + cairo_paint (cr); + + cairo_destroy (cr); } else { draw_loading_text (view, &real_page_area, expose_area); *page_ready = FALSE; } + if (scaled_selection) { gdk_draw_pixbuf (GTK_WIDGET(view)->window, @@ -2376,6 +2379,7 @@ 0, 0); g_object_unref (scaled_selection); } + } } Index: tiff/tiff-document.c =================================================================== RCS file: /cvs/gnome/evince/tiff/tiff-document.c,v retrieving revision 1.17 diff -u -u -r1.17 tiff-document.c --- tiff/tiff-document.c 3 Dec 2006 20:35:46 -0000 1.17 +++ tiff/tiff-document.c 6 Dec 2006 17:21:46 -0000 @@ -269,6 +269,21 @@ return rotated_pixbuf; } +static cairo_surface_t * +tiff_document_render_surface (EvDocument *document, + EvRenderContext *rc) +{ + TiffDocument *tiff_document = TIFF_DOCUMENT (document); + cairo_surface_t *surface; + GdkPixbuf *pixbuf; + + pixbuf = tiff_document_render_pixbuf (document, rc); + surface = ev_document_misc_surface_from_pixbuf (pixbuf); + g_object_unref (pixbuf); + + return surface; +} + static void tiff_document_finalize (GObject *object) { @@ -316,6 +331,7 @@ 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_surface = tiff_document_render_surface; iface->get_info = tiff_document_get_info; }