[gimp] Bug 725576 - GIMP crashes on printing large TIFF files Cairo surface creating is limited to 32768. P



commit 0bc827cb69e611eb7c59a0a02acf9b33aa0edd5c
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Wed Apr 16 11:15:35 2014 +0200

    Bug 725576 - GIMP crashes on printing large TIFF files
    Cairo surface creating is limited to 32768.
    Printing is refused for images bigger than 32768 either width,
    height or both.

 plug-ins/print/print-draw-page.c |   70 ++++++++++++++++++++++++++++----------
 plug-ins/print/print-draw-page.h |    3 +-
 plug-ins/print/print.c           |   16 +++++++--
 plug-ins/print/print.h           |    9 +++++
 4 files changed, 76 insertions(+), 22 deletions(-)
---
diff --git a/plug-ins/print/print-draw-page.c b/plug-ins/print/print-draw-page.c
index cc46507..bb0734e 100644
--- a/plug-ins/print/print-draw-page.c
+++ b/plug-ins/print/print-draw-page.c
@@ -28,7 +28,8 @@
 #include "libgimp/stdplugins-intl.h"
 
 
-static cairo_surface_t * print_surface_from_drawable (gint32  drawable_ID);
+static cairo_surface_t * print_surface_from_drawable (gint32        drawable_ID,
+                                                      GError      **error);
 
 static void              print_draw_crop_marks       (GtkPrintContext *context,
                                                       gdouble          x,
@@ -38,7 +39,8 @@ static void              print_draw_crop_marks       (GtkPrintContext *context,
 
 gboolean
 print_draw_page (GtkPrintContext *context,
-                 PrintData       *data)
+                 PrintData       *data,
+                 GError         **error)
 {
   cairo_t         *cr = gtk_print_context_get_cairo_context (context);
   cairo_surface_t *surface;
@@ -47,36 +49,45 @@ print_draw_page (GtkPrintContext *context,
   gdouble          scale_x;
   gdouble          scale_y;
 
-  surface = print_surface_from_drawable (data->drawable_id);
+  surface = print_surface_from_drawable (data->drawable_id, error);
 
-  width  = cairo_image_surface_get_width (surface);
-  height = cairo_image_surface_get_height (surface);
+  if (surface)
+    {
+      width  = cairo_image_surface_get_width (surface);
+      height = cairo_image_surface_get_height (surface);
 
-  scale_x = gtk_print_context_get_dpi_x (context) / data->xres;
-  scale_y = gtk_print_context_get_dpi_y (context) / data->yres;
+      scale_x = gtk_print_context_get_dpi_x (context) / data->xres;
+      scale_y = gtk_print_context_get_dpi_y (context) / data->yres;
 
-  cairo_translate (cr, data->offset_x, data->offset_y);
+      cairo_translate (cr, data->offset_x, data->offset_y);
 
-  if (data->draw_crop_marks)
-    print_draw_crop_marks (context,
-                           0, 0, width * scale_x, height * scale_y);
+      if (data->draw_crop_marks)
+        print_draw_crop_marks (context,
+                               0, 0, width * scale_x, height * scale_y);
 
-  cairo_scale (cr, scale_x, scale_y);
-  cairo_rectangle (cr, 0, 0, width, height);
-  cairo_set_source_surface (cr, surface, 0, 0);
-  cairo_fill (cr);
+      cairo_scale (cr, scale_x, scale_y);
+      cairo_rectangle (cr, 0, 0, width, height);
+      cairo_set_source_surface (cr, surface, 0, 0);
+      cairo_fill (cr);
 
-  cairo_surface_destroy (surface);
+      cairo_surface_destroy (surface);
 
-  return TRUE;
+      return TRUE;
+    }
+  else
+    {
+      return FALSE;
+    }
 }
 
 static cairo_surface_t *
-print_surface_from_drawable (gint32 drawable_ID)
+print_surface_from_drawable (gint32   drawable_ID,
+                             GError **error)
 {
   GeglBuffer         *buffer   = gimp_drawable_get_buffer (drawable_ID);
   const Babl         *format;
   cairo_surface_t    *surface;
+  cairo_status_t      status;
   const gint          width    = gimp_drawable_width  (drawable_ID);
   const gint          height   = gimp_drawable_height (drawable_ID);
   GeglBufferIterator *iter;
@@ -95,6 +106,29 @@ print_surface_from_drawable (gint32 drawable_ID)
                                         CAIRO_FORMAT_RGB24,
                                         width, height);
 
+  status = cairo_surface_status (surface);
+  if (status != CAIRO_STATUS_SUCCESS)
+    {
+      switch (status)
+        {
+        case CAIRO_STATUS_INVALID_SIZE:
+          g_set_error_literal (error,
+                               GIMP_PLUGIN_PRINT_ERROR,
+                               GIMP_PLUGIN_PRINT_ERROR_FAILED,
+                               _("Cannot handle the size (either width or height) of the Image."));
+          break;
+        default:
+          g_set_error (error,
+                       GIMP_PLUGIN_PRINT_ERROR,
+                       GIMP_PLUGIN_PRINT_ERROR_FAILED,
+                       "Cairo error: %s",
+                       cairo_status_to_string (status));
+          break;
+        }
+
+      return NULL;
+    }
+
   pixels = cairo_image_surface_get_data (surface);
   stride = cairo_image_surface_get_stride (surface);
 
diff --git a/plug-ins/print/print-draw-page.h b/plug-ins/print/print-draw-page.h
index 238c33a..00ff557 100644
--- a/plug-ins/print/print-draw-page.h
+++ b/plug-ins/print/print-draw-page.h
@@ -16,4 +16,5 @@
  */
 
 gboolean print_draw_page (GtkPrintContext *context,
-                          PrintData       *data);
+                          PrintData       *data,
+                          GError         **error);
diff --git a/plug-ins/print/print.c b/plug-ins/print/print.c
index 4362b46..ab07590 100644
--- a/plug-ins/print/print.c
+++ b/plug-ins/print/print.c
@@ -40,6 +40,7 @@
 #define PRINT_TEMP_PROC_NAME "file-print-gtk-page-setup-notify-temp"
 #endif
 
+G_DEFINE_QUARK (gimp-plugin-print-error-quark, gimp_plugin_print_error)
 
 static void        query (void);
 static void        run   (const gchar       *name,
@@ -368,7 +369,7 @@ print_show_error (const gchar *message)
   dialog = gtk_message_dialog_new (NULL, 0,
                                    GTK_MESSAGE_ERROR,
                                    GTK_BUTTONS_OK,
-                                  "%s",
+                                                          "%s",
                                    _("An error occurred while trying to print:"));
 
   gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
@@ -423,11 +424,20 @@ draw_page (GtkPrintOperation *operation,
            gint               page_nr,
            PrintData         *data)
 {
-  print_draw_page (context, data);
+  GError *error = NULL;
 
-  gimp_progress_update (1.0);
+  if (print_draw_page (context, data, &error))
+    {
+      gimp_progress_update (1.0);
+    }
+  else
+    {
+      print_show_error (error->message);
+      g_error_free (error);
+    }
 }
 
+
 /*
  * This callback creates a "custom" widget that gets inserted into the
  * print operation dialog.
diff --git a/plug-ins/print/print.h b/plug-ins/print/print.h
index 2e2cfcd..3236a5b 100644
--- a/plug-ins/print/print.h
+++ b/plug-ins/print/print.h
@@ -20,6 +20,15 @@
 #define EMBED_PAGE_SETUP 1
 #endif
 
+#define GIMP_PLUGIN_PRINT_ERROR gimp_plugin_print_error_quark ()
+
+typedef enum
+{
+  GIMP_PLUGIN_PRINT_ERROR_FAILED
+} GimpPluginPrintError;
+
+GQuark gimp_plugin_print_error_quark (void);
+
 typedef enum
 {
   CENTER_NONE         = 0,


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]