File 0001-tiff-backend-use-cairo-for-printing.patch of Package mingw32-evince
From 4e73d3cedf5975c6f943a13a3105f513bc86b8dc Mon Sep 17 00:00:00 2001
From: Hib Eris <hib@hiberis.nl>
Date: Tue, 7 Jun 2011 21:58:31 +0200
Subject: [PATCH] tiff backend: use cairo for printing
---
backend/tiff/tiff-document.c | 153 +++++++++++++++++++++++++++++++++++++++---
1 files changed, 144 insertions(+), 9 deletions(-)
diff --git a/backend/tiff/tiff-document.c b/backend/tiff/tiff-document.c
index 9c113b4..7b2e91a 100644
--- a/backend/tiff/tiff-document.c
+++ b/backend/tiff/tiff-document.c
@@ -33,8 +33,40 @@
#include "ev-document-misc.h"
#include "ev-document-thumbnails.h"
#include "ev-file-exporter.h"
+#include "ev-document-print.h"
#include "ev-file-helpers.h"
+static gpointer pool = NULL;
+static gsize poolsize = 0;
+static gboolean poolfree = TRUE;
+
+static gpointer
+try_malloc_from_pool (gsize n_bytes)
+{
+ if (!poolfree)
+ return NULL;
+
+ if (poolsize > n_bytes) {
+ poolfree = FALSE;
+ return pool;
+ }
+
+ gpointer newpool = g_try_realloc (pool, n_bytes);
+ if (newpool != NULL) {
+ pool = newpool;
+ poolsize = n_bytes;
+ poolfree = FALSE;
+ }
+ return newpool;
+}
+
+static void
+free_from_pool (gpointer mem)
+{
+ poolfree = TRUE;
+}
+
+
struct _TiffDocumentClass
{
EvDocumentClass parent_class;
@@ -55,6 +87,7 @@ typedef struct _TiffDocumentClass TiffDocumentClass;
static void tiff_document_document_thumbnails_iface_init (EvDocumentThumbnailsInterface *iface);
static void tiff_document_document_file_exporter_iface_init (EvFileExporterInterface *iface);
+static void tiff_document_document_print_iface_init (EvDocumentPrintInterface *iface);
EV_BACKEND_REGISTER_WITH_CODE (TiffDocument, tiff_document,
{
@@ -62,6 +95,9 @@ EV_BACKEND_REGISTER_WITH_CODE (TiffDocument, tiff_document,
tiff_document_document_thumbnails_iface_init);
EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_FILE_EXPORTER,
tiff_document_document_file_exporter_iface_init);
+ EV_BACKEND_IMPLEMENT_INTERFACE (EV_TYPE_DOCUMENT_PRINT,
+ tiff_document_document_print_iface_init);
+
});
static TIFFErrorHandler orig_error_handler = NULL;
@@ -230,16 +266,19 @@ tiff_document_render (EvDocument *document,
push_handlers ();
if (TIFFSetDirectory (tiff_document->tiff, rc->page->index) != 1) {
pop_handlers ();
+ g_warning("Failed to select page %d", rc->page->index);
return NULL;
}
if (!TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGEWIDTH, &width)) {
pop_handlers ();
+ g_warning("Failed to read image width");
return NULL;
}
if (! TIFFGetField (tiff_document->tiff, TIFFTAG_IMAGELENGTH, &height)) {
pop_handlers ();
+ g_warning("Failed to read image height");
return NULL;
}
@@ -252,33 +291,52 @@ tiff_document_render (EvDocument *document,
pop_handlers ();
/* Sanity check the doc */
- if (width <= 0 || height <= 0)
- return NULL;
+ if (width <= 0 || height <= 0) {
+ g_warning("Invalid width or height.");
+ return NULL;
+ }
#ifdef HAVE_CAIRO_FORMAT_STRIDE_FOR_WIDTH
rowstride = cairo_format_stride_for_width (CAIRO_FORMAT_RGB24, width);
#else
rowstride = width * 4;
#endif
- if (rowstride / 4 != width)
+ if (rowstride / 4 != width) {
+ g_warning("Overflow while rendering document.");
/* overflow, or cairo was changed in an unsupported way */
return NULL;
+ }
bytes = height * rowstride;
- if (bytes / rowstride != height)
+ if (bytes / rowstride != height) {
+ g_warning("Overflow while rendering document.");
/* overflow */
- return NULL;
+ return NULL;
+ }
- pixels = g_try_malloc (bytes);
- if (!pixels)
+ void (*pixelfree)(gpointer mem);
+ pixels = try_malloc_from_pool (bytes);
+ if (pixels) {
+ pixelfree = &free_from_pool;
+ } else {
+ pixels = g_try_malloc (bytes);
+ pixelfree = &g_free;
+ }
+ if (!pixels) {
+ g_warning("Failed to allocate memory for rendering.");
return NULL;
+ }
surface = cairo_image_surface_create_for_data (pixels,
CAIRO_FORMAT_RGB24,
width, height,
rowstride);
+ if (!surface) {
+ g_warning("Failed to create surface for rendering.");
+ return NULL;
+ }
cairo_surface_set_user_data (surface, &key,
- pixels, (cairo_destroy_func_t)g_free);
+ pixels, (cairo_destroy_func_t)*pixelfree);
TIFFReadRGBAImageOriented (tiff_document->tiff,
width, height,
@@ -436,7 +494,7 @@ tiff_document_thumbnails_get_thumbnail (EvDocumentThumbnails *document,
pixbuf = tiff_document_render_pixbuf (EV_DOCUMENT (document), rc);
- if (border) {
+ if (pixbuf && border) {
GdkPixbuf *tmp_pixbuf = pixbuf;
pixbuf = ev_document_misc_get_thumbnail_frame (-1, -1, tmp_pixbuf);
@@ -526,6 +584,83 @@ tiff_document_document_file_exporter_iface_init (EvFileExporterInterface *iface)
iface->get_capabilities = tiff_document_file_exporter_get_capabilities;
}
+/* EvDocumentPrint */
+static void
+tiff_document_print_print_page (EvDocumentPrint *document,
+ EvPage *page,
+ cairo_t *cr)
+{
+ cairo_status_t cr_status;
+
+ EvRenderContext *rc = ev_render_context_new (page, 0.0, 1.0);
+ cairo_surface_t *surface = tiff_document_render (EV_DOCUMENT (document), rc);
+ if (surface == NULL) {
+ g_warning("Failed to render document for printing.");
+ return;
+ }
+
+#if 1
+ cairo_save (cr);
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cairo_paint (cr);
+ cairo_restore (cr);
+#else
+ cairo_save (cr);
+ cr_status = cairo_status (cr);
+ if (cr_status != CAIRO_STATUS_SUCCESS)
+ g_warning("Error 1. printing page: %s.",
+ cairo_status_to_string (cr_status));
+ cairo_set_source_surface (cr, surface, 0, 0);
+ cr_status = cairo_status (cr);
+ if (cr_status != CAIRO_STATUS_SUCCESS)
+ g_warning("Error 2. printing page: %s.",
+ cairo_status_to_string (cr_status));
+ cairo_paint (cr);
+ cr_status = cairo_status (cr);
+ if (cr_status != CAIRO_STATUS_SUCCESS)
+ g_warning("Error 3. printing page: %s.",
+ cairo_status_to_string (cr_status));
+ cairo_restore (cr);
+ cr_status = cairo_status (cr);
+ if (cr_status != CAIRO_STATUS_SUCCESS)
+ g_warning("Error 4. printing page: %s.",
+ cairo_status_to_string (cr_status));
+#endif
+
+#if 0
+cairo_move_to (cr, 50.0, 75.0);
+cairo_line_to (cr, 1200.0, 75.0);
+
+cairo_move_to (cr, 50.0, 125.0);
+cairo_line_to (cr, 1200.0, 125.0);
+
+cairo_move_to (cr, 50.0, 175.0);
+cairo_line_to (cr, 1200.0, 175.0);
+
+cairo_set_line_width (cr, 30.0);
+cairo_set_line_cap (cr, CAIRO_LINE_CAP_ROUND);
+cairo_stroke (cr);
+#endif
+
+ // Hib Eris; 13/07/2011
+ // I think we should destroy 'surface' here, but it seems
+ // cairo does not handle this well:
+ // Destroying 'surface' will cause the detachment of snapshots by
+ // cairo. This will cause a _cairo_surface_snapshot_copy_on_write
+ // which can fail with an out-of-memory error for large images.
+ // The failure is not handled by cairo and not returned by
+ // cairo_surface_destroy.
+ // For now, we just uncomment it.
+ //cairo_surface_destroy (surface);
+ g_object_unref (rc);
+}
+
+static void
+tiff_document_document_print_iface_init (EvDocumentPrintInterface *iface)
+{
+ iface->print_page = tiff_document_print_print_page;
+}
+
static void
tiff_document_init (TiffDocument *tiff_document)
{
--
1.7.4.1