Code

872a0234f4d4e6847fd03e14b05a150a517bebbe
[inkscape.git] / src / print.cpp
1 #define __SP_PRINT_C__
3 /** \file
4  * Frontend to printing
5  */
6 /*
7  * Author:
8  *   Lauris Kaplinski <lauris@kaplinski.com>
9  *
10  * This code is in public domain
11  */
13 #ifdef HAVE_CONFIG_H
14 # include "config.h"
15 #endif
19 #include "sp-item.h"
20 #include "extension/print.h"
21 #include "extension/system.h"
22 #include "print.h"
24 #include <unit-constants.h>
26 #ifdef HAVE_GTK_UNIX_PRINT
27 # include <gtk/gtk.h>
28 # include <glibmm/i18n.h>
29 # include <gtk/gtkprintunixdialog.h>
30 # include <unistd.h>   // close, unlink
31 # include <cstdio>
32 using std::fprintf;
33 #endif
35 #if 0
36 # include <extension/internal/ps.h>
38 # ifdef WIN32
39 #  include <extension/internal/win32.h>
40 # endif
41 #endif
43 /* Identity typedef */
45 unsigned int sp_print_bind(SPPrintContext *ctx, NR::Matrix const &transform, float opacity)
46 {
47     NRMatrix const ntransform(transform);
48     return sp_print_bind(ctx, &ntransform, opacity);
49 }
51 unsigned int
52 sp_print_bind(SPPrintContext *ctx, NRMatrix const *transform, float opacity)
53 {
54     return ctx->module->bind(transform, opacity);
55 }
57 unsigned int
58 sp_print_release(SPPrintContext *ctx)
59 {
60     return ctx->module->release();
61 }
63 unsigned int
64 sp_print_comment(SPPrintContext *ctx, char const *comment)
65 {
66     return ctx->module->comment(comment);
67 }
69 unsigned int
70 sp_print_fill(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
71               NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
72 {
73     return ctx->module->fill(bpath, ctm, style, pbox, dbox, bbox);
74 }
76 unsigned int
77 sp_print_stroke(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
78                 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
79 {
80     return ctx->module->stroke(bpath, ctm, style, pbox, dbox, bbox);
81 }
83 unsigned int
84 sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
85                           guchar *px, unsigned int w, unsigned int h, unsigned int rs,
86                           NRMatrix const *transform, SPStyle const *style)
87 {
88     return ctx->module->image(px, w, h, rs, transform, style);
89 }
91 unsigned int sp_print_text(SPPrintContext *ctx, char const *text, NR::Point p,
92                            SPStyle const *style)
93 {
94     return ctx->module->text(text, p, style);
95 }
97 #include "display/nr-arena.h"
98 #include "display/nr-arena-item.h"
100 /* UI */
102 void
103 sp_print_preview_document(SPDocument *doc)
105     Inkscape::Extension::Print *mod;
106     unsigned int ret;
108     sp_document_ensure_up_to_date(doc);
110     mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
112     ret = mod->set_preview();
114     if (ret) {
115         SPPrintContext context;
116         context.module = mod;
118         /* fixme: This has to go into module constructor somehow */
119         /* Create new arena */
120         mod->base = SP_ITEM(sp_document_root(doc));
121         mod->arena = NRArena::create();
122         mod->dkey = sp_item_display_key_new(1);
123         mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
124         /* Print document */
125         ret = mod->begin(doc);
126         sp_item_invoke_print(mod->base, &context);
127         ret = mod->finish();
128         /* Release arena */
129         sp_item_invoke_hide(mod->base, mod->dkey);
130         mod->base = NULL;
131         nr_arena_item_unref(mod->root);
132         mod->root = NULL;
133         nr_object_unref((NRObject *) mod->arena);
134         mod->arena = NULL;
135     }
137     return;
140 #ifdef HAVE_GTK_UNIX_PRINT
141 static void
142 unix_print_complete (GtkPrintJob *print_job,
143                      gpointer user_data,
144                      GError *error)
146     fprintf(stderr,"print job finished: %s\n",error ? error->message : "no error");
149 static void
150 unix_print_dialog (const gchar * ps_file, const gchar * jobname, gdouble doc_width, gdouble doc_height)
152     Glib::ustring title = _("Print");
153     title += " ";
154     title += jobname;
155     GtkWidget* dlg = gtk_print_unix_dialog_new(title.c_str(), NULL);
157     // force output system to only handle our pre-generated PS output
158     gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG(dlg),
159                                                    GTK_PRINT_CAPABILITY_GENERATE_PS);
161 /*
162  * It would be nice to merge the PrintPS::setup routine with a custom
163  * configuration dialog:
164    
165     gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
166                                           GtkWidget *child,
167                                           GtkWidget *tab_label);
168 */
170     int const response = gtk_dialog_run(GTK_DIALOG(dlg));
172     if (response == GTK_RESPONSE_OK) {
173         GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dlg));
175         if (gtk_printer_accepts_ps (printer)) {
176                         GtkPageSetup *page_setup = gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dlg));
178                         //It's important to set the right paper size here, otherwise it will 
179                         //default to letter; if for example an A4 is printed as a letter, then
180                         //part of it will be truncated even when printing on A4 paper
181                         
182                         //TODO: let the user decide upon the paper size, by enabling
183                         //the drop down widget in the printing dialog. For now, we'll simply
184                         //take the document's dimensions and communicate these to the printer
185                         //driver 
186                         
187                         GtkPaperSize *page_size = gtk_paper_size_new_custom("custom", "custom", doc_width, doc_height, GTK_UNIT_POINTS);
189                         gtk_page_setup_set_paper_size (page_setup, page_size);                                                             
190                         
191             GtkPrintJob* job = gtk_print_job_new  (jobname, printer,
192               gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dlg)),
193               page_setup);
194                         
195                         GtkPaperSize* tmp = gtk_page_setup_get_paper_size(gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dlg)));
196                         
197             GError * error = NULL;
198             if ( gtk_print_job_set_source_file (job, ps_file, &error)) {
199                 gtk_print_job_send (job, unix_print_complete, NULL, NULL);
200             }
201             else {
202                 g_warning(_("Could not set print source: %s"),error ? error->message : _("unknown error"));
203             }
204             if (error) g_error_free(error);
205         }
206         else {
207             g_warning(_("Printer '%s' does not support PS output"), gtk_printer_get_name (printer));
208         }
209     }
210     else if (response == GTK_RESPONSE_APPLY) {
211         // since we didn't include the Preview capability,
212         // this should never happen.
213         g_warning(_("Print Preview not available"));
214     }
216     gtk_widget_destroy(dlg);
218 #endif // HAVE_GTK_UNIX_PRINT
221 void
222 sp_print_document(SPDocument *doc, unsigned int direct)
224     Inkscape::Extension::Print *mod;
225     unsigned int ret;
226 #ifdef HAVE_GTK_UNIX_PRINT
227     Glib::ustring tmpfile = "";
228 #endif
230     sp_document_ensure_up_to_date(doc);
232     if (direct) {
233         mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
234     } else {
235         mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
237 #ifdef HAVE_GTK_UNIX_PRINT
238         // unix print dialog reads from the exported tempfile
239         gchar  *filename = NULL;
240         GError *error    = NULL;
241         gint tmpfd = g_file_open_tmp("inkscape-ps-XXXXXX",
242                                      &filename,
243                                      &error);
244         if (tmpfd<0) {
245             g_warning(_("Failed to create tempfile for printing: %s"),
246                       error ? error->message : _("unknown error"));
247             if (error) g_error_free(error);
248             return;
249         }
250         tmpfile = filename;
251         g_free(filename);
252         close(tmpfd);
254         Glib::ustring destination = ">" + tmpfile;
255         mod->set_param_string("destination", destination.c_str());
256 #endif
257     }
259     ret = mod->setup();
261     if (ret) {
262         SPPrintContext context;
263         context.module = mod;
265         /* fixme: This has to go into module constructor somehow */
266         /* Create new arena */
267         mod->base = SP_ITEM(sp_document_root(doc));
268         mod->arena = NRArena::create();
269         mod->dkey = sp_item_display_key_new(1);
270         mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
271         /* Print document */
272         ret = mod->begin(doc);
273         sp_item_invoke_print(mod->base, &context);
274         ret = mod->finish();
275         /* Release arena */
276         sp_item_invoke_hide(mod->base, mod->dkey);
277         mod->base = NULL;
278         nr_arena_item_unref(mod->root);
279         mod->root = NULL;
280         nr_object_unref((NRObject *) mod->arena);
281         mod->arena = NULL;
283 #ifdef HAVE_GTK_UNIX_PRINT
284         // redirect output to new print dialog
285         
286         // width and height in pt
287         gdouble width = sp_document_width(doc) * PT_PER_PX;
288         gdouble height = sp_document_height(doc) * PT_PER_PX;
289         
290         unix_print_dialog(tmpfile.c_str(),doc->name ? doc->name : _("SVG Document"), width, height);
291         unlink(tmpfile.c_str());
292         // end redirected new print dialog
293 #endif
294     }
296     return;
299 void
300 sp_print_document_to_file(SPDocument *doc, gchar const *filename)
302     Inkscape::Extension::Print *mod;
303     SPPrintContext context;
304     gchar const *oldconst;
305     gchar *oldoutput;
306     unsigned int ret;
308     sp_document_ensure_up_to_date(doc);
310     mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
311     oldconst = mod->get_param_string("destination");
312     oldoutput = g_strdup(oldconst);
313     mod->set_param_string("destination", (gchar *)filename);
315 /* Start */
316     context.module = mod;
317     /* fixme: This has to go into module constructor somehow */
318     /* Create new arena */
319     mod->base = SP_ITEM(sp_document_root(doc));
320     mod->arena = NRArena::create();
321     mod->dkey = sp_item_display_key_new(1);
322     mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
323     /* Print document */
324     ret = mod->begin(doc);
325     sp_item_invoke_print(mod->base, &context);
326     ret = mod->finish();
327     /* Release arena */
328     sp_item_invoke_hide(mod->base, mod->dkey);
329     mod->base = NULL;
330     nr_arena_item_unref(mod->root);
331     mod->root = NULL;
332     nr_object_unref((NRObject *) mod->arena);
333     mod->arena = NULL;
334 /* end */
336     mod->set_param_string("destination", oldoutput);
337     g_free(oldoutput);
339     return;
343 /*
344   Local Variables:
345   mode:c++
346   c-file-style:"stroustrup"
347   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
348   indent-tabs-mode:nil
349   fill-column:99
350   End:
351 */
352 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :