From 217797d63b2d3b1c9a7a0511af1bbf3d99f0d482 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Campos Date: Wed, 13 Jun 2007 08:54:53 +0000 Subject: Use cairo image surfaces instead of GDK pixbufs for drawing pages and 2007-06-13 Carlos Garcia Campos * 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 --- (limited to 'backend') 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; } -- cgit v0.9.1