1/* GTK - The GIMP Toolkit
2 * gtkprintbackendfile.c: Default implementation of GtkPrintBackend
3 * for printing to a file
4 * Copyright (C) 2003, Red Hat, Inc.
5 *
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.
10 *
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.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include "config.h"
21
22#include <unistd.h>
23#include <sys/types.h>
24#include <sys/stat.h>
25#include <fcntl.h>
26#include <stdlib.h>
27#include <string.h>
28
29#include <errno.h>
30#include <cairo.h>
31#include <cairo-pdf.h>
32#include <cairo-ps.h>
33#include <cairo-svg.h>
34
35#include <glib/gi18n-lib.h>
36
37#include "gtk/gtk.h"
38#include "gtk/gtkprinterprivate.h"
39
40#include "gtkprintbackendfile.h"
41
42typedef struct _GtkPrintBackendFileClass GtkPrintBackendFileClass;
43
44#define GTK_PRINT_BACKEND_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
45#define GTK_IS_PRINT_BACKEND_FILE_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), GTK_TYPE_PRINT_BACKEND_FILE))
46#define GTK_PRINT_BACKEND_FILE_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), GTK_TYPE_PRINT_BACKEND_FILE, GtkPrintBackendFileClass))
47
48#define _STREAM_MAX_CHUNK_SIZE 8192
49
50struct _GtkPrintBackendFileClass
51{
52 GtkPrintBackendClass parent_class;
53};
54
55struct _GtkPrintBackendFile
56{
57 GtkPrintBackend parent_instance;
58};
59
60typedef enum
61{
62 FORMAT_PDF,
63 FORMAT_PS,
64 FORMAT_SVG,
65 N_FORMATS
66} OutputFormat;
67
68static const char * formats[N_FORMATS] =
69{
70 "pdf",
71 "ps",
72 "svg"
73};
74
75static GObjectClass *backend_parent_class;
76
77static void file_printer_get_settings_from_options (GtkPrinter *printer,
78 GtkPrinterOptionSet *options,
79 GtkPrintSettings *settings);
80static GtkPrinterOptionSet *file_printer_get_options (GtkPrinter *printer,
81 GtkPrintSettings *settings,
82 GtkPageSetup *page_setup,
83 GtkPrintCapabilities capabilities);
84static void file_printer_prepare_for_print (GtkPrinter *printer,
85 GtkPrintJob *print_job,
86 GtkPrintSettings *settings,
87 GtkPageSetup *page_setup);
88static void gtk_print_backend_file_print_stream (GtkPrintBackend *print_backend,
89 GtkPrintJob *job,
90 GIOChannel *data_io,
91 GtkPrintJobCompleteFunc callback,
92 gpointer user_data,
93 GDestroyNotify dnotify);
94static cairo_surface_t * file_printer_create_cairo_surface (GtkPrinter *printer,
95 GtkPrintSettings *settings,
96 double width,
97 double height,
98 GIOChannel *cache_io);
99
100static GList * file_printer_list_papers (GtkPrinter *printer);
101static GtkPageSetup * file_printer_get_default_page_size (GtkPrinter *printer);
102
103G_DEFINE_DYNAMIC_TYPE(GtkPrintBackendFile, gtk_print_backend_file, GTK_TYPE_PRINT_BACKEND)
104
105void
106g_io_module_load (GIOModule *module)
107{
108 g_type_module_use (G_TYPE_MODULE (module));
109
110 gtk_print_backend_file_register_type (G_TYPE_MODULE (module));
111
112 g_io_extension_point_implement (GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
113 GTK_TYPE_PRINT_BACKEND_FILE,
114 extension_name: "file",
115 priority: 10);
116}
117
118void
119g_io_module_unload (GIOModule *module)
120{
121}
122
123char **
124g_io_module_query (void)
125{
126 char *eps[] = {
127 (char *)GTK_PRINT_BACKEND_EXTENSION_POINT_NAME,
128 NULL
129 };
130
131 return g_strdupv (str_array: eps);
132}
133
134/**
135 * gtk_print_backend_file_new:
136 *
137 * Creates a new #GtkPrintBackendFile object. #GtkPrintBackendFile
138 * implements the #GtkPrintBackend interface with direct access to
139 * the filesystem using Unix/Linux API calls
140 *
141 * Returns: the new #GtkPrintBackendFile object
142 **/
143GtkPrintBackend *
144gtk_print_backend_file_new (void)
145{
146 return g_object_new (GTK_TYPE_PRINT_BACKEND_FILE, NULL);
147}
148
149static void
150gtk_print_backend_file_class_init (GtkPrintBackendFileClass *class)
151{
152 GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
153
154 backend_parent_class = g_type_class_peek_parent (g_class: class);
155
156 backend_class->print_stream = gtk_print_backend_file_print_stream;
157 backend_class->printer_create_cairo_surface = file_printer_create_cairo_surface;
158 backend_class->printer_get_options = file_printer_get_options;
159 backend_class->printer_get_settings_from_options = file_printer_get_settings_from_options;
160 backend_class->printer_prepare_for_print = file_printer_prepare_for_print;
161 backend_class->printer_list_papers = file_printer_list_papers;
162 backend_class->printer_get_default_page_size = file_printer_get_default_page_size;
163}
164
165static void
166gtk_print_backend_file_class_finalize (GtkPrintBackendFileClass *class)
167{
168}
169
170/* return N_FORMATS if no explicit format in the settings */
171static OutputFormat
172format_from_settings (GtkPrintSettings *settings)
173{
174 const char *value;
175 int i;
176
177 if (settings == NULL)
178 return N_FORMATS;
179
180 value = gtk_print_settings_get (settings,
181 GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT);
182 if (value == NULL)
183 return N_FORMATS;
184
185 for (i = 0; i < N_FORMATS; ++i)
186 if (strcmp (s1: value, s2: formats[i]) == 0)
187 break;
188
189 g_assert (i < N_FORMATS);
190
191 return (OutputFormat) i;
192}
193
194static char *
195output_file_from_settings (GtkPrintSettings *settings,
196 const char *default_format)
197{
198 char *uri = NULL;
199
200 if (settings)
201 uri = g_strdup (str: gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_URI));
202
203 if (uri == NULL)
204 {
205 const char *extension, *basename = NULL, *output_dir = NULL;
206 char *name, *locale_name, *path;
207
208 if (default_format)
209 extension = default_format;
210 else
211 {
212 OutputFormat format;
213
214 format = format_from_settings (settings);
215 switch (format)
216 {
217 default:
218 case N_FORMATS:
219 case FORMAT_PDF:
220 extension = "pdf";
221 break;
222 case FORMAT_PS:
223 extension = "ps";
224 break;
225 case FORMAT_SVG:
226 extension = "svg";
227 break;
228 }
229 }
230
231 if (settings)
232 basename = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_BASENAME);
233 if (basename == NULL)
234 basename = _("output");
235
236 name = g_strconcat (string1: basename, ".", extension, NULL);
237
238 locale_name = g_filename_from_utf8 (utf8string: name, len: -1, NULL, NULL, NULL);
239 g_free (mem: name);
240
241 if (locale_name != NULL)
242 {
243 if (settings)
244 output_dir = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_OUTPUT_DIR);
245 if (output_dir == NULL)
246 {
247 const char *document_dir = g_get_user_special_dir (directory: G_USER_DIRECTORY_DOCUMENTS);
248
249 if (document_dir == NULL)
250 {
251 char *current_dir = g_get_current_dir ();
252 path = g_build_filename (first_element: current_dir, locale_name, NULL);
253 g_free (mem: current_dir);
254 }
255 else
256 path = g_build_filename (first_element: document_dir, locale_name, NULL);
257
258 uri = g_filename_to_uri (filename: path, NULL, NULL);
259 }
260 else
261 {
262 path = g_build_filename (first_element: output_dir, locale_name, NULL);
263 uri = g_filename_to_uri (filename: path, NULL, NULL);
264 }
265
266 g_free (mem: path);
267 g_free (mem: locale_name);
268 }
269 }
270
271 return uri;
272}
273
274static cairo_status_t
275_cairo_write (void *closure,
276 const unsigned char *data,
277 unsigned int length)
278{
279 GIOChannel *io = (GIOChannel *)closure;
280 gsize written = 0;
281 GError *error;
282
283 error = NULL;
284
285 GTK_NOTE (PRINTING,
286 g_print ("FILE Backend: Writing %u byte chunk to temp file\n", length));
287
288 while (length > 0)
289 {
290 GIOStatus status;
291
292 status = g_io_channel_write_chars (channel: io, buf: (const char *) data, count: length, bytes_written: &written, error: &error);
293
294 if (status == G_IO_STATUS_ERROR)
295 {
296 if (error != NULL)
297 {
298 GTK_NOTE (PRINTING,
299 g_print ("FILE Backend: Error writing to temp file, %s\n", error->message));
300
301 g_error_free (error);
302 }
303
304 return CAIRO_STATUS_WRITE_ERROR;
305 }
306
307 GTK_NOTE (PRINTING,
308 g_print ("FILE Backend: Wrote %zd bytes to temp file\n", written));
309
310 data += written;
311 length -= written;
312 }
313
314 return CAIRO_STATUS_SUCCESS;
315}
316
317
318static cairo_surface_t *
319file_printer_create_cairo_surface (GtkPrinter *printer,
320 GtkPrintSettings *settings,
321 double width,
322 double height,
323 GIOChannel *cache_io)
324{
325 cairo_surface_t *surface;
326 OutputFormat format;
327 const cairo_svg_version_t *versions;
328 int num_versions = 0;
329
330 format = format_from_settings (settings);
331
332 switch (format)
333 {
334 default:
335 case N_FORMATS:
336 case FORMAT_PDF:
337 surface = cairo_pdf_surface_create_for_stream (write_func: _cairo_write, closure: cache_io, width_in_points: width, height_in_points: height);
338 break;
339 case FORMAT_PS:
340 surface = cairo_ps_surface_create_for_stream (write_func: _cairo_write, closure: cache_io, width_in_points: width, height_in_points: height);
341 break;
342 case FORMAT_SVG:
343 surface = cairo_svg_surface_create_for_stream (write_func: _cairo_write, closure: cache_io, width_in_points: width, height_in_points: height);
344 cairo_svg_get_versions (versions: &versions, num_versions: &num_versions);
345 if (num_versions > 0)
346 cairo_svg_surface_restrict_to_version (surface, version: versions[num_versions - 1]);
347 break;
348 }
349
350 cairo_surface_set_fallback_resolution (surface,
351 x_pixels_per_inch: 2.0 * gtk_print_settings_get_printer_lpi (settings),
352 y_pixels_per_inch: 2.0 * gtk_print_settings_get_printer_lpi (settings));
353
354 return surface;
355}
356
357typedef struct {
358 GtkPrintBackend *backend;
359 GtkPrintJobCompleteFunc callback;
360 GtkPrintJob *job;
361 GFileOutputStream *target_io_stream;
362 gpointer user_data;
363 GDestroyNotify dnotify;
364} _PrintStreamData;
365
366static void
367file_print_cb (GtkPrintBackendFile *print_backend,
368 GError *error,
369 gpointer user_data)
370{
371 char *uri;
372
373 _PrintStreamData *ps = (_PrintStreamData *) user_data;
374 GtkRecentManager *recent_manager;
375
376 if (ps->target_io_stream != NULL)
377 (void)g_output_stream_close (G_OUTPUT_STREAM (ps->target_io_stream), NULL, NULL);
378
379 if (ps->callback)
380 ps->callback (ps->job, ps->user_data, error);
381
382 if (ps->dnotify)
383 ps->dnotify (ps->user_data);
384
385 gtk_print_job_set_status (job: ps->job,
386 status: (error != NULL)
387 ? GTK_PRINT_STATUS_FINISHED_ABORTED
388 : GTK_PRINT_STATUS_FINISHED);
389
390 recent_manager = gtk_recent_manager_get_default ();
391 uri = output_file_from_settings (settings: gtk_print_job_get_settings (job: ps->job), NULL);
392 gtk_recent_manager_add_item (manager: recent_manager, uri);
393 g_free (mem: uri);
394
395 if (ps->job)
396 g_object_unref (object: ps->job);
397
398 g_free (mem: ps);
399}
400
401static gboolean
402file_write (GIOChannel *source,
403 GIOCondition con,
404 gpointer user_data)
405{
406 char buf[_STREAM_MAX_CHUNK_SIZE];
407 gsize bytes_read;
408 GError *error;
409 GIOStatus read_status;
410 _PrintStreamData *ps = (_PrintStreamData *) user_data;
411
412 error = NULL;
413
414 read_status =
415 g_io_channel_read_chars (channel: source,
416 buf,
417 _STREAM_MAX_CHUNK_SIZE,
418 bytes_read: &bytes_read,
419 error: &error);
420
421 if (read_status != G_IO_STATUS_ERROR)
422 {
423 gsize bytes_written;
424
425 g_output_stream_write_all (G_OUTPUT_STREAM (ps->target_io_stream),
426 buffer: buf,
427 count: bytes_read,
428 bytes_written: &bytes_written,
429 NULL,
430 error: &error);
431 }
432
433 if (error != NULL || read_status == G_IO_STATUS_EOF)
434 {
435 file_print_cb (GTK_PRINT_BACKEND_FILE (ps->backend), error, user_data);
436
437 if (error != NULL)
438 {
439 GTK_NOTE (PRINTING,
440 g_print ("FILE Backend: %s\n", error->message));
441
442 g_error_free (error);
443 }
444
445 return FALSE;
446 }
447
448 GTK_NOTE (PRINTING,
449 g_print ("FILE Backend: Writing %"G_GSIZE_FORMAT" byte chunk to target file\n", bytes_read));
450
451 return TRUE;
452}
453
454static void
455gtk_print_backend_file_print_stream (GtkPrintBackend *print_backend,
456 GtkPrintJob *job,
457 GIOChannel *data_io,
458 GtkPrintJobCompleteFunc callback,
459 gpointer user_data,
460 GDestroyNotify dnotify)
461{
462 GError *internal_error = NULL;
463 _PrintStreamData *ps;
464 GtkPrintSettings *settings;
465 char *uri;
466 GFile *file = NULL;
467
468 settings = gtk_print_job_get_settings (job);
469
470 ps = g_new0 (_PrintStreamData, 1);
471 ps->callback = callback;
472 ps->user_data = user_data;
473 ps->dnotify = dnotify;
474 ps->job = g_object_ref (job);
475 ps->backend = print_backend;
476
477 internal_error = NULL;
478 uri = output_file_from_settings (settings, NULL);
479
480 if (uri == NULL)
481 goto error;
482
483 file = g_file_new_for_uri (uri);
484 ps->target_io_stream = g_file_replace (file, NULL, FALSE, flags: G_FILE_CREATE_NONE, NULL, error: &internal_error);
485
486 g_object_unref (object: file);
487 g_free (mem: uri);
488
489error:
490 if (internal_error != NULL)
491 {
492 file_print_cb (GTK_PRINT_BACKEND_FILE (print_backend),
493 error: internal_error, user_data: ps);
494
495 g_error_free (error: internal_error);
496 return;
497 }
498
499 g_io_add_watch (channel: data_io,
500 condition: G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
501 func: (GIOFunc) file_write,
502 user_data: ps);
503}
504
505static void
506gtk_print_backend_file_init (GtkPrintBackendFile *backend)
507{
508 GtkPrinter *printer;
509
510 printer = g_object_new (GTK_TYPE_PRINTER,
511 first_property_name: "name", _("Print to File"),
512 "backend", backend,
513 "is-virtual", TRUE,
514 "accepts-pdf", TRUE,
515 NULL);
516
517 gtk_printer_set_has_details (printer, TRUE);
518 gtk_printer_set_icon_name (printer, icon: "document-save");
519 gtk_printer_set_is_active (printer, TRUE);
520
521 gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
522 g_object_unref (object: printer);
523
524 gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
525}
526
527typedef struct {
528 GtkPrinter *printer;
529 GtkPrinterOptionSet *set;
530} _OutputFormatChangedData;
531
532static void
533set_printer_format_from_option_set (GtkPrinter *printer,
534 GtkPrinterOptionSet *set)
535{
536 GtkPrinterOption *format_option;
537 const char *value;
538 int i;
539
540 format_option = gtk_printer_option_set_lookup (set, name: "output-file-format");
541 if (format_option && format_option->value)
542 {
543 value = format_option->value;
544 if (value)
545 {
546 for (i = 0; i < N_FORMATS; ++i)
547 if (strcmp (s1: value, s2: formats[i]) == 0)
548 break;
549
550 g_assert (i < N_FORMATS);
551
552 switch (i)
553 {
554 case FORMAT_PDF:
555 gtk_printer_set_accepts_pdf (printer, TRUE);
556 gtk_printer_set_accepts_ps (printer, FALSE);
557 break;
558 case FORMAT_PS:
559 gtk_printer_set_accepts_pdf (printer, FALSE);
560 gtk_printer_set_accepts_ps (printer, TRUE);
561 break;
562 case FORMAT_SVG:
563 default:
564 gtk_printer_set_accepts_pdf (printer, FALSE);
565 gtk_printer_set_accepts_ps (printer, FALSE);
566 break;
567 }
568 }
569 }
570}
571
572static void
573file_printer_output_file_format_changed (GtkPrinterOption *format_option,
574 gpointer user_data)
575{
576 GtkPrinterOption *uri_option;
577 char *base = NULL;
578 _OutputFormatChangedData *data = (_OutputFormatChangedData *) user_data;
579
580 if (! format_option->value)
581 return;
582
583 uri_option = gtk_printer_option_set_lookup (set: data->set,
584 name: "gtk-main-page-custom-input");
585
586 if (uri_option && uri_option->value)
587 {
588 const char *uri = uri_option->value;
589 const char *dot = strrchr (s: uri, c: '.');
590
591 if (dot)
592 {
593 int i;
594
595 /* check if the file extension matches one of the known ones */
596 for (i = 0; i < N_FORMATS; i++)
597 if (strcmp (s1: dot + 1, s2: formats[i]) == 0)
598 break;
599
600 if (i < N_FORMATS && strcmp (s1: formats[i], s2: format_option->value))
601 {
602 /* the file extension is known but doesn't match the
603 * selected one, strip it away
604 */
605 base = g_strndup (str: uri, n: dot - uri);
606 }
607 }
608 else
609 {
610 /* there's no file extension */
611 base = g_strdup (str: uri);
612 }
613 }
614
615 if (base)
616 {
617 char *tmp = g_strdup_printf (format: "%s.%s", base, format_option->value);
618
619 gtk_printer_option_set (option: uri_option, value: tmp);
620 g_free (mem: tmp);
621 g_free (mem: base);
622 }
623
624 set_printer_format_from_option_set (printer: data->printer, set: data->set);
625}
626
627static GtkPrinterOptionSet *
628file_printer_get_options (GtkPrinter *printer,
629 GtkPrintSettings *settings,
630 GtkPageSetup *page_setup,
631 GtkPrintCapabilities capabilities)
632{
633 GtkPrinterOptionSet *set;
634 GtkPrinterOption *option;
635 const char *n_up[] = {"1", "2", "4", "6", "9", "16" };
636 const char *pages_per_sheet = NULL;
637 const char *format_names[N_FORMATS] = { N_("PDF"), N_("PostScript"), N_("SVG") };
638 const char *supported_formats[N_FORMATS];
639 const char *display_format_names[N_FORMATS];
640 int n_formats = 0;
641 OutputFormat format;
642 char *uri;
643 int current_format = 0;
644 _OutputFormatChangedData *format_changed_data;
645
646 format = format_from_settings (settings);
647
648 set = gtk_printer_option_set_new ();
649
650 option = gtk_printer_option_new (name: "gtk-n-up", _("Pages per _sheet:"), type: GTK_PRINTER_OPTION_TYPE_PICKONE);
651 gtk_printer_option_choices_from_array (option, G_N_ELEMENTS (n_up),
652 choices: n_up, choices_display: n_up /* FIXME i18n (localised digits)! */);
653 if (settings)
654 pages_per_sheet = gtk_print_settings_get (settings, GTK_PRINT_SETTINGS_NUMBER_UP);
655 if (pages_per_sheet)
656 gtk_printer_option_set (option, value: pages_per_sheet);
657 else
658 gtk_printer_option_set (option, value: "1");
659 gtk_printer_option_set_add (set, option);
660 g_object_unref (object: option);
661
662 if (capabilities & (GTK_PRINT_CAPABILITY_GENERATE_PDF | GTK_PRINT_CAPABILITY_GENERATE_PS))
663 {
664 if (capabilities & GTK_PRINT_CAPABILITY_GENERATE_PDF)
665 {
666 if (format == FORMAT_PDF || format == N_FORMATS)
667 {
668 format = FORMAT_PDF;
669 current_format = n_formats;
670 }
671 supported_formats[n_formats] = formats[FORMAT_PDF];
672 display_format_names[n_formats] = _(format_names[FORMAT_PDF]);
673 n_formats++;
674 }
675 if (capabilities & GTK_PRINT_CAPABILITY_GENERATE_PS)
676 {
677 if (format == FORMAT_PS || format == N_FORMATS)
678 current_format = n_formats;
679 supported_formats[n_formats] = formats[FORMAT_PS];
680 display_format_names[n_formats] = _(format_names[FORMAT_PS]);
681 n_formats++;
682 }
683 }
684 else
685 {
686 switch (format)
687 {
688 default:
689 case N_FORMATS:
690 case FORMAT_PDF:
691 current_format = FORMAT_PDF;
692 break;
693 case FORMAT_PS:
694 current_format = FORMAT_PS;
695 break;
696 case FORMAT_SVG:
697 current_format = FORMAT_SVG;
698 break;
699 }
700
701 for (n_formats = 0; n_formats < N_FORMATS; ++n_formats)
702 {
703 supported_formats[n_formats] = formats[n_formats];
704 display_format_names[n_formats] = _(format_names[n_formats]);
705 }
706 }
707
708 uri = output_file_from_settings (settings, default_format: supported_formats[current_format]);
709
710 option = gtk_printer_option_new (name: "gtk-main-page-custom-input", _("File"),
711 type: GTK_PRINTER_OPTION_TYPE_FILESAVE);
712 gtk_printer_option_set_activates_default (option, TRUE);
713 gtk_printer_option_set (option, value: uri);
714 g_free (mem: uri);
715 option->group = g_strdup (str: "GtkPrintDialogExtension");
716 gtk_printer_option_set_add (set, option);
717
718 if (n_formats > 1)
719 {
720 option = gtk_printer_option_new (name: "output-file-format", _("_Output format"),
721 type: GTK_PRINTER_OPTION_TYPE_ALTERNATIVE);
722 option->group = g_strdup (str: "GtkPrintDialogExtension");
723
724 gtk_printer_option_choices_from_array (option, num_choices: n_formats,
725 choices: supported_formats,
726 choices_display: display_format_names);
727 gtk_printer_option_set (option, value: supported_formats[current_format]);
728 gtk_printer_option_set_add (set, option);
729
730 set_printer_format_from_option_set (printer, set);
731 format_changed_data = g_new (_OutputFormatChangedData, 1);
732 format_changed_data->printer = printer;
733 format_changed_data->set = set;
734 g_signal_connect_data (instance: option, detailed_signal: "changed",
735 G_CALLBACK (file_printer_output_file_format_changed),
736 data: format_changed_data, destroy_data: (GClosureNotify)g_free, connect_flags: 0);
737
738 g_object_unref (object: option);
739 }
740
741 return set;
742}
743
744static void
745file_printer_get_settings_from_options (GtkPrinter *printer,
746 GtkPrinterOptionSet *options,
747 GtkPrintSettings *settings)
748{
749 GtkPrinterOption *option;
750
751 option = gtk_printer_option_set_lookup (set: options, name: "gtk-main-page-custom-input");
752 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_URI, value: option->value);
753
754 option = gtk_printer_option_set_lookup (set: options, name: "output-file-format");
755 if (option)
756 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_OUTPUT_FILE_FORMAT, value: option->value);
757
758 option = gtk_printer_option_set_lookup (set: options, name: "gtk-n-up");
759 if (option)
760 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP, value: option->value);
761
762 option = gtk_printer_option_set_lookup (set: options, name: "gtk-n-up-layout");
763 if (option)
764 gtk_print_settings_set (settings, GTK_PRINT_SETTINGS_NUMBER_UP_LAYOUT, value: option->value);
765}
766
767static void
768file_printer_prepare_for_print (GtkPrinter *printer,
769 GtkPrintJob *print_job,
770 GtkPrintSettings *settings,
771 GtkPageSetup *page_setup)
772{
773 double scale;
774 GtkPrintPages pages;
775 GtkPageRange *ranges;
776 int n_ranges;
777 OutputFormat format;
778
779 pages = gtk_print_settings_get_print_pages (settings);
780 gtk_print_job_set_pages (job: print_job, pages);
781
782 if (pages == GTK_PRINT_PAGES_RANGES)
783 ranges = gtk_print_settings_get_page_ranges (settings, num_ranges: &n_ranges);
784 else
785 {
786 ranges = NULL;
787 n_ranges = 0;
788 }
789
790 gtk_print_job_set_page_ranges (job: print_job, ranges, n_ranges);
791 gtk_print_job_set_collate (job: print_job, collate: gtk_print_settings_get_collate (settings));
792 gtk_print_job_set_reverse (job: print_job, reverse: gtk_print_settings_get_reverse (settings));
793 gtk_print_job_set_num_copies (job: print_job, num_copies: gtk_print_settings_get_n_copies (settings));
794 gtk_print_job_set_n_up (job: print_job, n_up: gtk_print_settings_get_number_up (settings));
795 gtk_print_job_set_n_up_layout (job: print_job, layout: gtk_print_settings_get_number_up_layout (settings));
796
797 scale = gtk_print_settings_get_scale (settings);
798 if (scale != 100.0)
799 gtk_print_job_set_scale (job: print_job, scale: scale / 100.0);
800
801 gtk_print_job_set_page_set (job: print_job, page_set: gtk_print_settings_get_page_set (settings));
802
803 format = format_from_settings (settings);
804 switch (format)
805 {
806 case FORMAT_PDF:
807 case N_FORMATS:
808 gtk_print_job_set_rotate (job: print_job, FALSE);
809 break;
810 default:
811 case FORMAT_PS:
812 case FORMAT_SVG:
813 gtk_print_job_set_rotate (job: print_job, TRUE);
814 break;
815 }
816}
817
818static GList *
819file_printer_list_papers (GtkPrinter *printer)
820{
821 GList *result = NULL;
822 GList *papers, *p;
823 GtkPageSetup *page_setup;
824
825 papers = gtk_paper_size_get_paper_sizes (FALSE);
826
827 for (p = papers; p; p = p->next)
828 {
829 GtkPaperSize *paper_size = p->data;
830
831 page_setup = gtk_page_setup_new ();
832 gtk_page_setup_set_paper_size (setup: page_setup, size: paper_size);
833 gtk_paper_size_free (size: paper_size);
834 result = g_list_prepend (list: result, data: page_setup);
835 }
836
837 g_list_free (list: papers);
838
839 return g_list_reverse (list: result);
840}
841
842static GtkPageSetup *
843file_printer_get_default_page_size (GtkPrinter *printer)
844{
845 GtkPageSetup *result = NULL;
846
847 return result;
848}
849

source code of gtk/modules/printbackends/gtkprintbackendfile.c