]> Pileus Git - ~andy/gtk/blob - modules/printbackends/pdf/gtkprintbackendpdf.c
Added new symbols
[~andy/gtk] / modules / printbackends / pdf / gtkprintbackendpdf.c
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.
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, write to the
18  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19  * Boston, MA 02111-1307, USA.
20  */
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 <config.h>
30 #include <errno.h>
31 #include <cairo.h>
32 #include <cairo-pdf.h>
33
34 #include <glib/gi18n-lib.h>
35
36 #include "gtkprintoperation.h"
37
38 #include "gtkprintbackend.h"
39 #include "gtkprintbackendpdf.h"
40
41 #include "gtkprinter.h"
42
43 typedef struct _GtkPrintBackendPdfClass GtkPrintBackendPdfClass;
44
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))
48
49 #define _PDF_MAX_CHUNK_SIZE 8192
50
51 static GType print_backend_pdf_type = 0;
52
53 struct _GtkPrintBackendPdfClass
54 {
55   GtkPrintBackendClass parent_class;
56 };
57
58 struct _GtkPrintBackendPdf
59 {
60   GtkPrintBackend parent_instance;
61 };
62
63 static GObjectClass *backend_parent_class;
64
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,
80                                                                    double                  *top,
81                                                                    double                  *bottom,
82                                                                    double                  *left,
83                                                                    double                  *right);
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,
87                                                                    GtkPrintJob             *job,
88                                                                    gint                     data_fd,
89                                                                    GtkPrintJobCompleteFunc  callback,
90                                                                    gpointer                 user_data,
91                                                                    GDestroyNotify           dnotify);
92 static cairo_surface_t *    pdf_printer_create_cairo_surface      (GtkPrinter              *printer,
93                                                                    gdouble                  width,
94                                                                    gdouble                  height,
95                                                                    gint                     cache_fd);
96
97 static void
98 gtk_print_backend_pdf_register_type (GTypeModule *module)
99 {
100   if (!print_backend_pdf_type)
101     {
102       static const GTypeInfo print_backend_pdf_info =
103       {
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),
111         0,              /* n_preallocs */
112         (GInstanceInitFunc) gtk_print_backend_pdf_init,
113       };
114
115       print_backend_pdf_type = g_type_module_register_type (module,
116                                                             GTK_TYPE_PRINT_BACKEND,
117                                                             "GtkPrintBackendPdf",
118                                                             &print_backend_pdf_info, 0);
119     }
120 }
121
122 G_MODULE_EXPORT void 
123 pb_module_init (GTypeModule *module)
124 {
125   gtk_print_backend_pdf_register_type (module);
126 }
127
128 G_MODULE_EXPORT void 
129 pb_module_exit (void)
130 {
131
132 }
133   
134 G_MODULE_EXPORT GtkPrintBackend * 
135 pb_module_create (void)
136 {
137   return gtk_print_backend_pdf_new ();
138 }
139
140 /*
141  * GtkPrintBackendPdf
142  */
143 GType
144 gtk_print_backend_pdf_get_type (void)
145 {
146   return print_backend_pdf_type;
147 }
148
149 /**
150  * gtk_print_backend_pdf_new:
151  *
152  * Creates a new #GtkPrintBackendPdf object. #GtkPrintBackendPdf
153  * implements the #GtkPrintBackend interface with direct access to
154  * the filesystem using Unix/Linux API calls
155  *
156  * Return value: the new #GtkPrintBackendPdf object
157  **/
158 GtkPrintBackend *
159 gtk_print_backend_pdf_new (void)
160 {
161   return g_object_new (GTK_TYPE_PRINT_BACKEND_PDF, NULL);
162 }
163
164 static void
165 gtk_print_backend_pdf_class_init (GtkPrintBackendPdfClass *class)
166 {
167   GtkPrintBackendClass *backend_class = GTK_PRINT_BACKEND_CLASS (class);
168
169   backend_parent_class = g_type_class_peek_parent (class);
170
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;
180 }
181
182 static cairo_status_t
183 _cairo_write (void *cache_fd_as_pointer,
184               const unsigned char *data,
185               unsigned int         length)
186 {
187   cairo_status_t result;
188   gint cache_fd;
189   cache_fd = GPOINTER_TO_INT (cache_fd_as_pointer);
190   
191   result = CAIRO_STATUS_WRITE_ERROR;
192   
193   /* write out the buffer */
194   if (write (cache_fd, data, length) != -1)
195       result = CAIRO_STATUS_SUCCESS;
196    
197   return result;
198 }
199
200
201 static cairo_surface_t *
202 pdf_printer_create_cairo_surface (GtkPrinter *printer,
203                                    gdouble width, 
204                                    gdouble height,
205                                    gint cache_fd)
206 {
207   cairo_surface_t *surface;
208   
209   surface = cairo_pdf_surface_create_for_stream  (_cairo_write, GINT_TO_POINTER (cache_fd), width, height);
210
211   /* TODO: DPI from settings object? */
212   cairo_pdf_surface_set_dpi (surface, 300, 300);
213
214   return surface;
215 }
216
217 typedef struct {
218   GtkPrintBackend *backend;
219   GtkPrintJobCompleteFunc callback;
220   GtkPrintJob *job;
221   gint target_fd;
222   gpointer user_data;
223   GDestroyNotify dnotify;
224 } _PrintStreamData;
225
226 static void
227 pdf_print_cb (GtkPrintBackendPdf *print_backend,
228               GError *error,
229               gpointer user_data)
230 {
231   _PrintStreamData *ps = (_PrintStreamData *) user_data;
232
233   if (ps->target_fd > 0)
234     close (ps->target_fd);
235
236   if (ps->callback)
237     ps->callback (ps->job, ps->user_data, error);
238
239   if (ps->dnotify)
240     ps->dnotify (ps->user_data);
241
242   gtk_print_job_set_status (ps->job,
243                             (error != NULL)?GTK_PRINT_STATUS_FINISHED_ABORTED:GTK_PRINT_STATUS_FINISHED);
244
245   if (ps->job)
246     g_object_unref (ps->job);
247  
248   g_free (ps);
249 }
250
251 static gboolean
252 pdf_write (GIOChannel *source,
253            GIOCondition con,
254            gpointer user_data)
255 {
256   gchar buf[_PDF_MAX_CHUNK_SIZE];
257   gsize bytes_read;
258   GError *error;
259   _PrintStreamData *ps = (_PrintStreamData *) user_data;
260   gint source_fd;
261
262   error = NULL;
263
264   source_fd = g_io_channel_unix_get_fd (source);
265
266   bytes_read = read (source_fd,
267                      buf,
268                      _PDF_MAX_CHUNK_SIZE);
269
270    
271
272   if (bytes_read > 0)
273     {
274       if (write (ps->target_fd, buf, bytes_read) == -1)
275         {
276           error = g_error_new (GTK_PRINT_ERROR,
277                            GTK_PRINT_ERROR_INTERNAL_ERROR, 
278                            g_strerror (errno));
279         }
280     }
281   else if (bytes_read == -1)
282     {
283       error = g_error_new (GTK_PRINT_ERROR,
284                            GTK_PRINT_ERROR_INTERNAL_ERROR, 
285                            g_strerror (errno));
286     }
287
288   if (bytes_read == 0 || error != NULL)
289     {
290       pdf_print_cb (GTK_PRINT_BACKEND_PDF (ps->backend), error, user_data);
291
292       return FALSE;
293     }
294
295   return TRUE;
296 }
297
298 static void
299 gtk_print_backend_pdf_print_stream (GtkPrintBackend *print_backend,
300                                     GtkPrintJob *job,
301                                     gint data_fd,
302                                     GtkPrintJobCompleteFunc callback,
303                                     gpointer user_data,
304                                     GDestroyNotify dnotify)
305 {
306   GError *error;
307   GtkPrinter *printer;
308   _PrintStreamData *ps;
309   GtkPrintSettings *settings;
310   GIOChannel *save_channel;  
311   const char *filename;
312
313   printer = gtk_print_job_get_printer (job);
314   settings = gtk_print_job_get_settings (job);
315
316   error = NULL;
317
318   filename = gtk_print_settings_get (settings, "pdf-filename");
319   if (filename == NULL)
320     filename = "output.pdf";
321   
322   ps = g_new0 (_PrintStreamData, 1);
323   ps->callback = callback;
324   ps->user_data = user_data;
325   ps->job = g_object_ref (job);
326
327   ps->target_fd = creat (filename, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP | S_IROTH);
328   ps->backend = print_backend;
329
330   if (ps->target_fd == -1)
331     {
332       error = g_error_new (GTK_PRINT_ERROR,
333                            GTK_PRINT_ERROR_INTERNAL_ERROR, 
334                            g_strerror (errno));
335
336       pdf_print_cb (GTK_PRINT_BACKEND_PDF (print_backend),
337                     error,
338                     ps);
339
340       return;
341     }
342   
343   save_channel = g_io_channel_unix_new (data_fd);
344
345   g_io_add_watch (save_channel, 
346                   G_IO_IN | G_IO_PRI | G_IO_ERR | G_IO_HUP,
347                   (GIOFunc) pdf_write,
348                   ps);
349 }
350
351 static void
352 gtk_print_backend_pdf_init (GtkPrintBackendPdf *backend)
353 {
354   GtkPrinter *printer;
355   
356   printer = gtk_printer_new (_("Print to PDF"),
357                              GTK_PRINT_BACKEND (backend),
358                              TRUE); 
359
360   gtk_printer_set_has_details (printer, TRUE);
361   gtk_printer_set_icon_name (printer, "floppy");
362   gtk_printer_set_is_active (printer, TRUE);
363
364   gtk_print_backend_add_printer (GTK_PRINT_BACKEND (backend), printer);
365   g_object_unref (printer);
366
367   gtk_print_backend_set_list_done (GTK_PRINT_BACKEND (backend));
368 }
369
370 static void
371 pdf_printer_request_details (GtkPrinter *printer)
372 {
373 }
374
375 static GtkPrinterOptionSet *
376 pdf_printer_get_options (GtkPrinter *printer,
377                          GtkPrintSettings *settings,
378                          GtkPageSetup *page_setup)
379 {
380   GtkPrinterOptionSet *set;
381   GtkPrinterOption *option;
382   const char *filename;
383   char *n_up[] = {"1" };
384
385   set = gtk_printer_option_set_new ();
386
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),
389                                          n_up, n_up);
390   gtk_printer_option_set (option, "1");
391   gtk_printer_option_set_add (set, option);
392   g_object_unref (option);
393
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);
398
399   if (settings != NULL &&
400       (filename = gtk_print_settings_get (settings, "pdf-filename"))!= NULL)
401     gtk_printer_option_set (option, filename);
402
403   return set;
404 }
405
406
407 static gboolean
408 pdf_printer_mark_conflicts  (GtkPrinter          *printer,
409                              GtkPrinterOptionSet *options)
410 {
411   return FALSE;
412 }
413
414 static void
415 pdf_printer_get_settings_from_options (GtkPrinter *printer,
416                                        GtkPrinterOptionSet *options,
417                                        GtkPrintSettings *settings)
418 {
419   GtkPrinterOption *option;
420
421   option = gtk_printer_option_set_lookup (options, "gtk-main-page-custom-input");
422   gtk_print_settings_set (settings, "pdf-filename", option->value);
423 }
424
425 static void
426 pdf_printer_prepare_for_print (GtkPrinter *printer,
427                                GtkPrintJob *print_job,
428                                GtkPrintSettings *settings,
429                                GtkPageSetup *page_setup)
430 {
431   double scale;
432
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;
436   
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);
441   
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);
445
446   scale = gtk_print_settings_get_scale (settings);
447   if (scale != 100.0)
448     print_job->scale = scale/100.0;
449
450   print_job->page_set = gtk_print_settings_get_page_set (settings);
451   print_job->rotate_to_orientation = TRUE;
452 }
453
454 static void
455 pdf_printer_get_hard_margins (GtkPrinter *printer,
456                               double *top,
457                               double *bottom,
458                               double *left,
459                               double *right)
460 {
461   *top = 0;
462   *bottom = 0;
463   *left = 0;
464   *right = 0;
465 }
466
467 static GList *
468 pdf_printer_list_papers (GtkPrinter *printer)
469 {
470   return NULL;
471 }