1 /* GTK - The GIMP Toolkit
2 * gtkprintbackendpdf.c: Default implementation of GtkPrintBackend
3 * for printing to PDF files
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.
23 #include <sys/types.h>
32 #include <cairo-pdf.h>
34 #include <glib/gi18n-lib.h>
36 #include "gtkprintoperation.h"
38 #include "gtkprintbackend.h"
39 #include "gtkprintbackendpdf.h"
41 #include "gtkprinter.h"
43 typedef struct _GtkPrintBackendPdfClass GtkPrintBackendPdfClass;
45 #define GTK_PRINT_BACKEND_PDF_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_PDF, GtkPrintBackendPdfClass))
46 #define GTK_IS_PRINT_BACKEND_PDF_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_PDF))
47 #define GTK_PRINT_BACKEND_PDF_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_PDF, GtkPrintBackendPdfClass))
49 #define _PDF_MAX_CHUNK_SIZE 8192
51 static GType print_backend_pdf_type = 0;
53 struct _GtkPrintBackendPdfClass
55 GtkPrintBackendClass parent_class;
58 struct _GtkPrintBackendPdf
60 GtkPrintBackend parent_instance;
63 static GObjectClass *backend_parent_class;
65 static void gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class);
66 static void gtk_print_backend_pdf_init (GtkPrintBackendPdf *impl);
67 static void pdf_printer_get_settings_from_options (GtkPrinter *printer,
68 GtkPrinterOptionSet *options,
69 GtkPrintSettings *settings);
70 static gboolean pdf_printer_mark_conflicts (GtkPrinter *printer,
71 GtkPrinterOptionSet *options);
72 static GtkPrinterOptionSet *pdf_printer_get_options (GtkPrinter *printer,
73 GtkPrintSettings *settings,
74 GtkPageSetup *page_setup);
75 static void pdf_printer_prepare_for_print (GtkPrinter *printer,
76 GtkPrintJob *print_job,
77 GtkPrintSettings *settings,
78 GtkPageSetup *page_setup);
79 static void pdf_printer_get_hard_margins (GtkPrinter *printer,
84 static void pdf_printer_request_details (GtkPrinter *printer);
85 static GList * pdf_printer_list_papers (GtkPrinter *printer);
86 static void gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
89 GtkPrintJobCompleteFunc callback,
91 GDestroyNotify dnotify);
92 static cairo_surface_t * pdf_printer_create_cairo_surface (GtkPrinter *printer,
98 gtk_print_backend_pdf_register_type (GTypeModule *module)
100 if (!print_backend_pdf_type)
102 static const GTypeInfo print_backend_pdf_info =
104 sizeof (GtkPrintBackendPdfClass),
105 NULL, /* base_init */
106 NULL, /* base_finalize */
107 (GClassInitFunc) gtk_print_backend_pdf_class_init,
108 NULL, /* class_finalize */
109 NULL, /* class_data */
110 sizeof (GtkPrintBackendPdf),
112 (GInstanceInitFunc) gtk_print_backend_pdf_init,
115 print_backend_pdf_type = g_type_module_register_type (module,
116 GTK_TYPE_PRINT_BACKEND,
117 "GtkPrintBackendPdf",
118 &print_backend_pdf_info, 0);
123 pb_module_init (GTypeModule *module)
125 gtk_print_backend_pdf_register_type (module);
129 pb_module_exit (void)
134 G_MODULE_EXPORT GtkPrintBackend *
135 pb_module_create (void)
137 return gtk_print_backend_pdf_new ();
144 gtk_print_backend_pdf_get_type (void)
146 return print_backend_pdf_type;
150 * gtk_print_backend_pdf_new:
152 * Creates a new #GtkPrintBackendPdf object. #GtkPrintBackendPdf
153 * implements the #GtkPrintBackend interface with direct access to
154 * the filesystem using Unix/Linux API calls
156 * Return value: the new #GtkPrintBackendPdf object
159 gtk_print_backend_pdf_new (void)
161 return g_object_new (GTK_TYPE_PRINT_BACKEND_PDF, NULL);
165 gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class)
167 GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
169 backend_parent_class = g_type_class_peek_parent (class);
171 backend_class->print_stream = gtk_print_backend_pdf_print_stream;
172 backend_class->printer_request_details = pdf_printer_request_details;
173 backend_class->printer_create_cairo_surface = pdf_printer_create_cairo_surface;
174 backend_class->printer_get_options = pdf_printer_get_options;
175 backend_class->printer_mark_conflicts = pdf_printer_mark_conflicts;
176 backend_class->printer_get_settings_from_options = pdf_printer_get_settings_from_options;
177 backend_class->printer_prepare_for_print = pdf_printer_prepare_for_print;
178 backend_class->printer_list_papers = pdf_printer_list_papers;
179 backend_class->printer_get_hard_margins = pdf_printer_get_hard_margins;
182 static cairo_status_t
183 _cairo_write (void *cache_fd_as_pointer,
184 const unsigned char *data,
187 cairo_status_t result;
189 cache_fd = GPOINTER_TO_INT (cache_fd_as_pointer);
191 result = CAIRO_STATUS_WRITE_ERROR;
193 /* write out the buffer */
194 if (write (cache_fd, data, length) != -1)
195 result = CAIRO_STATUS_SUCCESS;
201 static cairo_surface_t *
202 pdf_printer_create_cairo_surface (GtkPrinter *printer,
207 cairo_surface_t *surface;
209 surface = cairo_pdf_surface_create_for_stream (_cairo_write, GINT_TO_POINTER (cache_fd), width, height);
211 /* TODO: DPI from settings object? */
212 cairo_pdf_surface_set_dpi (surface, 300, 300);
218 GtkPrintBackend *backend;
219 GtkPrintJobCompleteFunc callback;
223 GDestroyNotify dnotify;
227 pdf_print_cb (GtkPrintBackendPdf *print_backend,
231 _PrintStreamData *ps = (_PrintStreamData *) user_data;
233 if (ps->target_fd > 0)
234 close (ps->target_fd);
237 ps->callback (ps->job, ps->user_data, error);
240 ps->dnotify (ps->user_data);
242 gtk_print_job_set_status (ps->job,
243 (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED);
246 g_object_unref (ps->job);
252 pdf_write (GIOChannel *source,
256 gchar buf[_PDF_MAX_CHUNK_SIZE];
259 _PrintStreamData *ps = (_PrintStreamData *) user_data;
264 source_fd = g_io_channel_unix_get_fd (source);
266 bytes_read = read (source_fd,
268 _PDF_MAX_CHUNK_SIZE);
274 if (write (ps->target_fd, buf, bytes_read) == -1)
276 error = g_error_new (GTK_PRINT_ERROR,
277 GTK_PRINT_ERROR_INTERNAL_ERROR,
281 else if (bytes_read == -1)
283 error = g_error_new (GTK_PRINT_ERROR,
284 GTK_PRINT_ERROR_INTERNAL_ERROR,
288 if (bytes_read == 0 || error != NULL)
290 pdf_print_cb (GTK_PRINT_BACKEND_PDF (ps->backend), error, user_data);
299 gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
302 GtkPrintJobCompleteFunc callback,
304 GDestroyNotify dnotify)
308 _PrintStreamData *ps;
309 GtkPrintSettings *settings;
310 GIOChannel *save_channel;
311 const char *filename;
313 printer = gtk_print_job_get_printer (job);
314 settings = gtk_print_job_get_settings (job);
318 filename = gtk_print_settings_get (settings, "pdf-filename");
319 if (filename == NULL)
320 filename = "output.pdf";
322 ps = g_new0 (_PrintStreamData, 1);
323 ps->callback = callback;
324 ps->user_data = user_data;
325 ps->job = g_object_ref (job);
327 ps->target_fd = creat (filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
328 ps->backend = print_backend;
330 if (ps->target_fd == -1)
332 error = g_error_new (GTK_PRINT_ERROR,
333 GTK_PRINT_ERROR_INTERNAL_ERROR,
336 pdf_print_cb (GTK_PRINT_BACKEND_PDF (print_backend),
343 save_channel = g_io_channel_unix_new (data_fd);
345 g_io_add_watch (save_channel,
346 G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
352 gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend)
356 printer = gtk_printer_new (_("Print to PDF"),
357 GTK_PRINT_BACKEND (backend),
360 gtk_printer_set_has_details (printer, TRUE);
361 gtk_printer_set_icon_name (printer, "floppy");
362 gtk_printer_set_is_active (printer, TRUE);
364 gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
365 g_object_unref (printer);
367 gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
371 pdf_printer_request_details (GtkPrinter *printer)
375 static GtkPrinterOptionSet *
376 pdf_printer_get_options (GtkPrinter *printer,
377 GtkPrintSettings *settings,
378 GtkPageSetup *page_setup)
380 GtkPrinterOptionSet *set;
381 GtkPrinterOption *option;
382 const char *filename;
383 char *n_up[] = {"1" };
385 set = gtk_printer_option_set_new ();
387 option = gtk_printer_option_new ("gtk-n-up", _("Pages Per Sheet"), GTK_PRINTER_OPTION_TYPE_PICKONE);
388 gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up),
390 gtk_printer_option_set (option, "1");
391 gtk_printer_option_set_add (set, option);
392 g_object_unref (option);
394 option = gtk_printer_option_new ("gtk-main-page-custom-input", _("File"), GTK_PRINTER_OPTION_TYPE_FILESAVE);
395 gtk_printer_option_set (option, "output.pdf");
396 option->group = g_strdup ("GtkPrintDialogExtention");
397 gtk_printer_option_set_add (set, option);
399 if (settings != NULL &&
400 (filename = gtk_print_settings_get (settings, "pdf-filename"))!= NULL)
401 gtk_printer_option_set (option, filename);
408 pdf_printer_mark_conflicts (GtkPrinter *printer,
409 GtkPrinterOptionSet *options)
415 pdf_printer_get_settings_from_options (GtkPrinter *printer,
416 GtkPrinterOptionSet *options,
417 GtkPrintSettings *settings)
419 GtkPrinterOption *option;
421 option = gtk_printer_option_set_lookup (options, "gtk-main-page-custom-input");
422 gtk_print_settings_set (settings, "pdf-filename", option->value);
426 pdf_printer_prepare_for_print (GtkPrinter *printer,
427 GtkPrintJob *print_job,
428 GtkPrintSettings *settings,
429 GtkPageSetup *page_setup)
433 print_job->print_pages = gtk_print_settings_get_print_pages (settings);
434 print_job->page_ranges = NULL;
435 print_job->num_page_ranges = 0;
437 if (print_job->print_pages == GTK_PRINT_PAGES_RANGES)
438 print_job->page_ranges =
439 gtk_print_settings_get_page_ranges (settings,
440 &print_job->num_page_ranges);
442 print_job->collate = gtk_print_settings_get_collate (settings);
443 print_job->reverse = gtk_print_settings_get_reverse (settings);
444 print_job->num_copies = gtk_print_settings_get_num_copies (settings);
446 scale = gtk_print_settings_get_scale (settings);
448 print_job->scale = scale/100.0;
450 print_job->page_set = gtk_print_settings_get_page_set (settings);
451 print_job->rotate_to_orientation = TRUE;
455 pdf_printer_get_hard_margins (GtkPrinter *printer,
468 pdf_printer_list_papers (GtkPrinter *printer)