Web   ·   Wiki   ·   Activities   ·   Blog   ·   Lists   ·   Chat   ·   Meeting   ·   Bugs   ·   Git   ·   Translate   ·   Archive   ·   People   ·   Donate
summaryrefslogtreecommitdiffstats
path: root/backend
diff options
context:
space:
mode:
authorCarlos Garcia Campos <carlosgc@gnome.org>2007-06-13 08:54:53 (GMT)
committer Carlos Garcia Campos <carlosgc@src.gnome.org>2007-06-13 08:54:53 (GMT)
commit217797d63b2d3b1c9a7a0511af1bbf3d99f0d482 (patch)
tree7984c3b1bb57f723eb57c81f6ab4121b55e69510 /backend
parent83005d76d55eea57772ea2dc7224e45f856725be (diff)
Use cairo image surfaces instead of GDK pixbufs for drawing pages and
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
Diffstat (limited to 'backend')
-rw-r--r--backend/comics/comics-document.c29
-rw-r--r--backend/djvu/djvu-document-private.h1
-rw-r--r--backend/djvu/djvu-document.c95
-rw-r--r--backend/dvi/dvi-document.c28
-rw-r--r--backend/impress/impress-document.c62
-rw-r--r--backend/pdf/ev-poppler.cc104
-rw-r--r--backend/pixbuf/pixbuf-document.c25
-rw-r--r--backend/tiff/tiff-document.c93
8 files changed, 325 insertions, 112 deletions
diff --git a/backend/comics/comics-document.c b/backend/comics/comics-document.c
index 64bd2b7..092d8c2 100644
--- a/backend/comics/comics-document.c
+++ b/backend/comics/comics-document.c
@@ -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
diff --git a/backend/djvu/djvu-document-private.h b/backend/djvu/djvu-document-private.h
index 37651ef..3e7deed 100644
--- a/backend/djvu/djvu-document-private.h
+++ b/backend/djvu/djvu-document-private.h
@@ -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;
diff --git a/backend/djvu/djvu-document.c b/backend/djvu/djvu-document.c
index fc1ccaa..a8f0425 100644
--- a/backend/djvu/djvu-document.c
+++ b/backend/djvu/djvu-document.c
@@ -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 ("");
diff --git a/backend/dvi/dvi-document.c b/backend/dvi/dvi-document.c
index 9abdca7..445c1e0 100644
--- a/backend/dvi/dvi-document.c
+++ b/backend/dvi/dvi-document.c
@@ -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;
}
diff --git a/backend/impress/impress-document.c b/backend/impress/impress-document.c
index 5f5982e..6251fbd 100644
--- a/backend/impress/impress-document.c
+++ b/backend/impress/impress-document.c
@@ -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
diff --git a/backend/pdf/ev-poppler.cc b/backend/pdf/ev-poppler.cc
index a3549b2..e3b80b4 100644
--- a/backend/pdf/ev-poppler.cc
+++ b/backend/pdf/ev-poppler.cc
@@ -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;
}
diff --git a/backend/pixbuf/pixbuf-document.c b/backend/pixbuf/pixbuf-document.c
index c1cace0..83d2b8a 100644
--- a/backend/pixbuf/pixbuf-document.c
+++ b/backend/pixbuf/pixbuf-document.c
@@ -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;
}
diff --git a/backend/tiff/tiff-document.c b/backend/tiff/tiff-document.c
index 7425947..8247c2a 100644
--- a/backend/tiff/tiff-document.c
+++ b/backend/tiff/tiff-document.c
@@ -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);
@@ -255,16 +258,88 @@ tiff_document_render_pixbuf (EvDocument *document,
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;
+
+ 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;
+
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;
}