Commit 0bc827cb authored by Hartmut Kuhse's avatar Hartmut Kuhse

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.
parent 3d219b5a
......@@ -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);
......
......@@ -16,4 +16,5 @@
*/
gboolean print_draw_page (GtkPrintContext *context,
PrintData *data);
PrintData *data,
GError **error);
......@@ -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.
......
......@@ -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,
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment