Code

r16619@tres: ted | 2007-09-18 21:09:29 -0700
[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 #ifdef HAVE_GTK_UNIX_PRINT
25 # include <gtk/gtk.h>
26 # include <glibmm/i18n.h>
27 # include <gtk/gtkprintunixdialog.h>
28 # include <unistd.h>   // close, unlink
29 # include <cstdio>
30 using std::fprintf;
31 #endif
33 #if 0
34 # include <extension/internal/ps.h>
36 # ifdef WIN32
37 #  include <extension/internal/win32.h>
38 # endif
39 #endif
41 /* Identity typedef */
43 unsigned int sp_print_bind(SPPrintContext *ctx, NR::Matrix const &transform, float opacity)
44 {
45     NRMatrix const ntransform(transform);
46     return sp_print_bind(ctx, &ntransform, opacity);
47 }
49 unsigned int
50 sp_print_bind(SPPrintContext *ctx, NRMatrix const *transform, float opacity)
51 {
52     return ctx->module->bind(transform, opacity);
53 }
55 unsigned int
56 sp_print_release(SPPrintContext *ctx)
57 {
58     return ctx->module->release();
59 }
61 unsigned int
62 sp_print_comment(SPPrintContext *ctx, char const *comment)
63 {
64     return ctx->module->comment(comment);
65 }
67 unsigned int
68 sp_print_fill(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
69               NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
70 {
71     return ctx->module->fill(bpath, ctm, style, pbox, dbox, bbox);
72 }
74 unsigned int
75 sp_print_stroke(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
76                 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
77 {
78     return ctx->module->stroke(bpath, ctm, style, pbox, dbox, bbox);
79 }
81 unsigned int
82 sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
83                           guchar *px, unsigned int w, unsigned int h, unsigned int rs,
84                           NRMatrix const *transform, SPStyle const *style)
85 {
86     return ctx->module->image(px, w, h, rs, transform, style);
87 }
89 unsigned int sp_print_text(SPPrintContext *ctx, char const *text, NR::Point p,
90                            SPStyle const *style)
91 {
92     return ctx->module->text(text, p, style);
93 }
95 #include "display/nr-arena.h"
96 #include "display/nr-arena-item.h"
98 /* UI */
100 void
101 sp_print_preview_document(SPDocument *doc)
103     Inkscape::Extension::Print *mod;
104     unsigned int ret;
106     sp_document_ensure_up_to_date(doc);
108     mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
110     ret = mod->set_preview();
112     if (ret) {
113         SPPrintContext context;
114         context.module = mod;
116         /* fixme: This has to go into module constructor somehow */
117         /* Create new arena */
118         mod->base = SP_ITEM(sp_document_root(doc));
119         mod->arena = NRArena::create();
120         mod->dkey = sp_item_display_key_new(1);
121         mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
122         /* Print document */
123         ret = mod->begin(doc);
124         sp_item_invoke_print(mod->base, &context);
125         ret = mod->finish();
126         /* Release arena */
127         sp_item_invoke_hide(mod->base, mod->dkey);
128         mod->base = NULL;
129         nr_arena_item_unref(mod->root);
130         mod->root = NULL;
131         nr_object_unref((NRObject *) mod->arena);
132         mod->arena = NULL;
133     }
135     return;
138 #ifdef HAVE_GTK_UNIX_PRINT
139 static void
140 unix_print_complete (GtkPrintJob *print_job,
141                      gpointer user_data,
142                      GError *error)
144     fprintf(stderr,"print job finished: %s\n",error ? error->message : "no error");
147 static void
148 unix_print_dialog (const gchar * ps_file, const gchar * jobname)
150     Glib::ustring title = _("Print");
151     title += " ";
152     title += jobname;
153     GtkWidget* dlg = gtk_print_unix_dialog_new(title.c_str(), NULL);
155     // force output system to only handle our pre-generated PS output
156     gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG(dlg),
157                                                    GTK_PRINT_CAPABILITY_GENERATE_PS);
159 /*
160  * It would be nice to merge the PrintPS::setup routine with a custom
161  * configuration dialog:
162    
163     gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
164                                           GtkWidget *child,
165                                           GtkWidget *tab_label);
166 */
168     int const response = gtk_dialog_run(GTK_DIALOG(dlg));
170     if (response == GTK_RESPONSE_OK) {
171         GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dlg));
173         if (gtk_printer_accepts_ps (printer)) {
174             GtkPrintJob* job = gtk_print_job_new  (jobname, printer,
175               gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dlg)),
176               gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dlg)));
179             GError * error = NULL;
180             if ( gtk_print_job_set_source_file (job, ps_file, &error)) {
181                 gtk_print_job_send (job, unix_print_complete, NULL, NULL);
182             }
183             else {
184                 g_warning(_("Could not set print source: %s"),error ? error->message : _("unknown error"));
185             }
186             if (error) g_error_free(error);
187         }
188         else {
189             g_warning(_("Printer '%s' does not support PS output"), gtk_printer_get_name (printer));
190         }
191     }
192     else if (response == GTK_RESPONSE_APPLY) {
193         // since we didn't include the Preview capability,
194         // this should never happen.
195         g_warning(_("Print Preview not available"));
196     }
198     gtk_widget_destroy(dlg);
200 #endif // HAVE_GTK_UNIX_PRINT
203 void
204 sp_print_document(SPDocument *doc, unsigned int direct)
206     Inkscape::Extension::Print *mod;
207     unsigned int ret;
208 #ifdef HAVE_GTK_UNIX_PRINT
209     Glib::ustring tmpfile = "";
210 #endif
212     sp_document_ensure_up_to_date(doc);
214     if (direct) {
215         mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
216     } else {
217         mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
219 #ifdef HAVE_GTK_UNIX_PRINT
220         // unix print dialog reads from the exported tempfile
221         gchar  *filename = NULL;
222         GError *error    = NULL;
223         gint tmpfd = g_file_open_tmp("inkscape-ps-XXXXXX",
224                                      &filename,
225                                      &error);
226         if (tmpfd<0) {
227             g_warning(_("Failed to create tempfile for printing: %s"),
228                       error ? error->message : _("unknown error"));
229             if (error) g_error_free(error);
230             return;
231         }
232         tmpfile = filename;
233         g_free(filename);
234         close(tmpfd);
236         Glib::ustring destination = ">" + tmpfile;
237         mod->set_param_string("destination", destination.c_str());
238 #endif
239     }
241     ret = mod->setup();
243     if (ret) {
244         SPPrintContext context;
245         context.module = mod;
247         /* fixme: This has to go into module constructor somehow */
248         /* Create new arena */
249         mod->base = SP_ITEM(sp_document_root(doc));
250         mod->arena = NRArena::create();
251         mod->dkey = sp_item_display_key_new(1);
252         mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
253         /* Print document */
254         ret = mod->begin(doc);
255         sp_item_invoke_print(mod->base, &context);
256         ret = mod->finish();
257         /* Release arena */
258         sp_item_invoke_hide(mod->base, mod->dkey);
259         mod->base = NULL;
260         nr_arena_item_unref(mod->root);
261         mod->root = NULL;
262         nr_object_unref((NRObject *) mod->arena);
263         mod->arena = NULL;
265 #ifdef HAVE_GTK_UNIX_PRINT
266         // redirect output to new print dialog
267         unix_print_dialog(tmpfile.c_str(),doc->name ? doc->name : _("SVG Document"));
268         unlink(tmpfile.c_str());
269         // end redirected new print dialog
270 #endif
271     }
273     return;
276 void
277 sp_print_document_to_file(SPDocument *doc, gchar const *filename)
279     Inkscape::Extension::Print *mod;
280     SPPrintContext context;
281     gchar const *oldconst;
282     gchar *oldoutput;
283     unsigned int ret;
285     sp_document_ensure_up_to_date(doc);
287     mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
288     oldconst = mod->get_param_string("destination");
289     oldoutput = g_strdup(oldconst);
290     mod->set_param_string("destination", (gchar *)filename);
292 /* Start */
293     context.module = mod;
294     /* fixme: This has to go into module constructor somehow */
295     /* Create new arena */
296     mod->base = SP_ITEM(sp_document_root(doc));
297     mod->arena = NRArena::create();
298     mod->dkey = sp_item_display_key_new(1);
299     mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
300     /* Print document */
301     ret = mod->begin(doc);
302     sp_item_invoke_print(mod->base, &context);
303     ret = mod->finish();
304     /* Release arena */
305     sp_item_invoke_hide(mod->base, mod->dkey);
306     mod->base = NULL;
307     nr_arena_item_unref(mod->root);
308     mod->root = NULL;
309     nr_object_unref((NRObject *) mod->arena);
310     mod->arena = NULL;
311 /* end */
313     mod->set_param_string("destination", oldoutput);
314     g_free(oldoutput);
316     return;
320 /*
321   Local Variables:
322   mode:c++
323   c-file-style:"stroustrup"
324   c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
325   indent-tabs-mode:nil
326   fill-column:99
327   End:
328 */
329 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :