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

openSUSE Build Service is sponsored by