1 /* GTK - The GIMP Toolkit
2 * gtkprintbackendpdf.c: Default implementation of GtkPrintBackend
3 * for printing to a file
4 * Copyright (C) 2003, Red Hat, Inc.
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the
18 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 * Boston, MA 02111-1307, USA.
25 #include <sys/types.h>
33 #include <cairo-pdf.h>
35 #include <glib/gi18n-lib.h>
37 #include "gtkprintoperation.h"
39 #include "gtkprintbackend.h"
40 #include "gtkprintbackendfile.h"
42 #include "gtkprinter.h"
43 #include "gtkprinter-private.h"
45 typedef struct _GtkPrintBackendFileClass GtkPrintBackendFileClass;
47 #define GTK_PRINT_BACKEND_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
48 #define GTK_IS_PRINT_BACKEND_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_FILE))
49 #define GTK_PRINT_BACKEND_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
51 #define _STREAM_MAX_CHUNK_SIZE 8192
53 static GType print_backend_file_type = 0;
55 struct _GtkPrintBackendFileClass
57 GtkPrintBackendClass parent_class;
60 struct _GtkPrintBackendFile
62 GtkPrintBackend parent_instance;
65 static GObjectClass *backend_parent_class;
67 static void gtk_print_backend_file_class_init (GtkPrintBackendFileClass *class);
68 static void gtk_print_backend_file_init (GtkPrintBackendFile *impl);
69 static void file_printer_get_settings_from_options (GtkPrinter *printer,
70 GtkPrinterOptionSet *options,
71 GtkPrintSettings *settings);
72 static GtkPrinterOptionSet *file_printer_get_options (GtkPrinter *printer,
73 GtkPrintSettings *settings,
74 GtkPageSetup *page_setup,
75 GtkPrintCapabilities capabilities);
76 static void file_printer_prepare_for_print (GtkPrinter *printer,
77 GtkPrintJob *print_job,
78 GtkPrintSettings *settings,
79 GtkPageSetup *page_setup);
80 static void gtk_print_backend_file_print_stream (GtkPrintBackend *print_backend,
83 GtkPrintJobCompleteFunc callback,
85 GDestroyNotify dnotify);
86 static cairo_surface_t * file_printer_create_cairo_surface (GtkPrinter *printer,
87 GtkPrintSettings *settings,
93 gtk_print_backend_file_register_type (GTypeModule *module)
95 static const GTypeInfo print_backend_file_info =
97 sizeof (GtkPrintBackendFileClass),
99 NULL, /* base_finalize */
100 (GClassInitFunc) gtk_print_backend_file_class_init,
101 NULL, /* class_finalize */
102 NULL, /* class_data */
103 sizeof (GtkPrintBackendFile),
105 (GInstanceInitFunc) gtk_print_backend_file_init,
108 print_backend_file_type = g_type_module_register_type (module,
109 GTK_TYPE_PRINT_BACKEND,
110 "GtkPrintBackendFile",
111 &print_backend_file_info, 0);
115 pb_module_init (GTypeModule *module)
117 gtk_print_backend_file_register_type (module);
121 pb_module_exit (void)
126 G_MODULE_EXPORT GtkPrintBackend *
127 pb_module_create (void)
129 return gtk_print_backend_file_new ();
133 * GtkPrintBackendFile
136 gtk_print_backend_file_get_type (void)
138 return print_backend_file_type;
142 * gtk_print_backend_file_new:
144 * Creates a new #GtkPrintBackendFile object. #GtkPrintBackendFile
145 * implements the #GtkPrintBackend interface with direct access to
146 * the filesystem using Unix/Linux API calls
148 * Return value: the new #GtkPrintBackendFile object
151 gtk_print_backend_file_new (void)
153 return g_object_new (GTK_TYPE_PRINT_BACKEND_FILE, NULL);
157 gtk_print_backend_file_class_init (GtkPrintBackendFileClass *class)
159 GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
161 backend_parent_class = g_type_class_peek_parent (class);
163 backend_class->print_stream = gtk_print_backend_file_print_stream;
164 backend_class->printer_create_cairo_surface = file_printer_create_cairo_surface;
165 backend_class->printer_get_options = file_printer_get_options;
166 backend_class->printer_get_settings_from_options = file_printer_get_settings_from_options;
167 backend_class->printer_prepare_for_print = file_printer_prepare_for_print;
170 static cairo_status_t
171 _cairo_write (void *closure,
172 const unsigned char *data,
175 gint fd = GPOINTER_TO_INT (closure);
180 written = write (fd, data, length);
184 if (errno == EAGAIN || errno == EINTR)
187 return CAIRO_STATUS_WRITE_ERROR;
194 return CAIRO_STATUS_SUCCESS;
198 static cairo_surface_t *
199 file_printer_create_cairo_surface (GtkPrinter *printer,
200 GtkPrintSettings *settings,
205 cairo_surface_t *surface;
207 surface = cairo_pdf_surface_create_for_stream (_cairo_write, GINT_TO_POINTER (cache_fd), width, height);
209 /* TODO: DPI from settings object? */
210 cairo_surface_set_fallback_resolution (surface, 300, 300);
216 GtkPrintBackend *backend;
217 GtkPrintJobCompleteFunc callback;
221 GDestroyNotify dnotify;
225 file_print_cb (GtkPrintBackendFile *print_backend,
229 _PrintStreamData *ps = (_PrintStreamData *) user_data;
231 if (ps->target_fd > 0)
232 close (ps->target_fd);
235 ps->callback (ps->job, ps->user_data, error);
238 ps->dnotify (ps->user_data);
240 gtk_print_job_set_status (ps->job,
241 (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED);
244 g_object_unref (ps->job);
250 file_write (GIOChannel *source,
254 gchar buf[_STREAM_MAX_CHUNK_SIZE];
257 _PrintStreamData *ps = (_PrintStreamData *) user_data;
262 source_fd = g_io_channel_unix_get_fd (source);
264 bytes_read = read (source_fd,
266 _STREAM_MAX_CHUNK_SIZE);
270 if (write (ps->target_fd, buf, bytes_read) == -1)
272 error = g_error_new (GTK_PRINT_ERROR,
273 GTK_PRINT_ERROR_INTERNAL_ERROR,
277 else if (bytes_read == -1)
279 error = g_error_new (GTK_PRINT_ERROR,
280 GTK_PRINT_ERROR_INTERNAL_ERROR,
284 if (bytes_read == 0 || error != NULL)
286 file_print_cb (GTK_PRINT_BACKEND_FILE (ps->backend), error, user_data);
295 gtk_print_backend_file_print_stream (GtkPrintBackend *print_backend,
298 GtkPrintJobCompleteFunc callback,
300 GDestroyNotify dnotify)
304 _PrintStreamData *ps;
305 GtkPrintSettings *settings;
306 GIOChannel *save_channel;
308 gchar *filename = NULL; /* quit gcc */
310 printer = gtk_print_job_get_printer (job);
311 settings = gtk_print_job_get_settings (job);
315 uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI);
317 filename = g_filename_from_uri (uri, NULL, NULL);
318 /* FIXME: shouldn't we error out if we get an URI we cannot handle,
319 * rather than to print to some random file somewhere?
321 if (filename == NULL)
322 filename = g_strdup_printf ("output.pdf");
324 ps = g_new0 (_PrintStreamData, 1);
325 ps->callback = callback;
326 ps->user_data = user_data;
327 ps->dnotify = dnotify;
328 ps->job = g_object_ref (job);
329 ps->backend = print_backend;
331 ps->target_fd = creat (filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
334 if (ps->target_fd == -1)
336 error = g_error_new (GTK_PRINT_ERROR,
337 GTK_PRINT_ERROR_INTERNAL_ERROR,
340 file_print_cb (GTK_PRINT_BACKEND_FILE (print_backend), error, ps);
345 save_channel = g_io_channel_unix_new (data_fd);
347 g_io_add_watch (save_channel,
348 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
349 (GIOFunc) file_write,
354 gtk_print_backend_file_init (GtkPrintBackendFile *backend)
358 printer = g_object_new (GTK_TYPE_PRINTER,
359 "name", _("Print to File"),
365 gtk_printer_set_has_details (printer, TRUE);
366 gtk_printer_set_icon_name (printer, "gtk-floppy");
367 gtk_printer_set_is_active (printer, TRUE);
369 gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
370 g_object_unref (printer);
372 gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
375 static GtkPrinterOptionSet *
376 file_printer_get_options (GtkPrinter *printer,
377 GtkPrintSettings *settings,
378 GtkPageSetup *page_setup,
379 GtkPrintCapabilities capabilities)
381 GtkPrinterOptionSet *set;
382 GtkPrinterOption *option;
384 char *n_up[] = {"1" };
386 set = gtk_printer_option_set_new ();
388 option = gtk_printer_option_new ("gtk-n-up", _("Pages Per Sheet"), GTK_PRINTER_OPTION_TYPE_PICKONE);
389 gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up),
391 gtk_printer_option_set (option, "1");
392 gtk_printer_option_set_add (set, option);
393 g_object_unref (option);
395 option = gtk_printer_option_new ("gtk-main-page-custom-input", _("File"), GTK_PRINTER_OPTION_TYPE_FILESAVE);
396 gtk_printer_option_set (option, "output.pdf");
397 option->group = g_strdup ("GtkPrintDialogExtension");
398 gtk_printer_option_set_add (set, option);
400 if (settings != NULL &&
401 (uri = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI))!= NULL)
402 gtk_printer_option_set (option, uri);
408 file_printer_get_settings_from_options (GtkPrinter *printer,
409 GtkPrinterOptionSet *options,
410 GtkPrintSettings *settings)
412 GtkPrinterOption *option;
414 option = gtk_printer_option_set_lookup (options, "gtk-main-page-custom-input");
415 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, option->value);
419 file_printer_prepare_for_print (GtkPrinter *printer,
420 GtkPrintJob *print_job,
421 GtkPrintSettings *settings,
422 GtkPageSetup *page_setup)
426 print_job->print_pages = gtk_print_settings_get_print_pages (settings);
427 print_job->page_ranges = NULL;
428 print_job->num_page_ranges = 0;
430 if (print_job->print_pages == GTK_PRINT_PAGES_RANGES)
431 print_job->page_ranges =
432 gtk_print_settings_get_page_ranges (settings,
433 &print_job->num_page_ranges);
435 print_job->collate = gtk_print_settings_get_collate (settings);
436 print_job->reverse = gtk_print_settings_get_reverse (settings);
437 print_job->num_copies = gtk_print_settings_get_n_copies (settings);
439 scale = gtk_print_settings_get_scale (settings);
441 print_job->scale = scale/100.0;
443 print_job->page_set = gtk_print_settings_get_page_set (settings);
444 print_job->rotate_to_orientation = TRUE;