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



commit bf78d6a293998fec1eb5b94d3e83bd024d68cc79
Author: Hartmut Kuhse <hk_priv gmx de>
Date:   Wed Apr 16 11:31:29 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 ++++++--
 3 files changed, 66 insertions(+), 23 deletions(-)
---
diff --git a/plug-ins/print/print-draw-page.c b/plug-ins/print/print-draw-page.c
index 14de652..1bff8f9 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,28 +49,35 @@ 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;
+    }
 }
 
 
@@ -169,7 +178,8 @@ convert_from_indexeda (const guchar *src,
 }
 
 static cairo_surface_t *
-print_surface_from_drawable (gint32 drawable_ID)
+print_surface_from_drawable (gint32   drawable_ID,
+                             GError **error)
 {
   GimpDrawable    *drawable      = gimp_drawable_get (drawable_ID);
   GimpPixelRgn     region;
@@ -183,6 +193,7 @@ print_surface_from_drawable (gint32 drawable_ID)
   guint            count         = 0;
   guint            done          = 0;
   gpointer         pr;
+  cairo_status_t   status;
 
   if (gimp_drawable_is_indexed (drawable_ID))
     {
@@ -200,6 +211,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,
+                               1,
+                               0,
+                               _("Cannot handle the size (either width or height) of the Image."));
+          break;
+        default:
+          g_set_error (error,
+                       1,
+                       0,
+                       "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 155c96b..4959fa0 100644
--- a/plug-ins/print/print.c
+++ b/plug-ins/print/print.c
@@ -40,7 +40,6 @@
 #define PRINT_TEMP_PROC_NAME "file-print-gtk-page-setup-notify-temp"
 #endif
 
-
 static void        query (void);
 static void        run   (const gchar       *name,
                           gint               nparams,
@@ -369,7 +368,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),
@@ -424,11 +423,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.


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