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
40 # ifdef WITH_GNOME_PRINT
41 # include <extension/internal/gnome.h>
42 # endif
43 #endif
45 /* Identity typedef */
47 unsigned int sp_print_bind(SPPrintContext *ctx, NR::Matrix const &transform, float opacity)
48 {
49 NRMatrix const ntransform(transform);
50 return sp_print_bind(ctx, &ntransform, opacity);
51 }
53 unsigned int
54 sp_print_bind(SPPrintContext *ctx, NRMatrix const *transform, float opacity)
55 {
56 return ctx->module->bind(transform, opacity);
57 }
59 unsigned int
60 sp_print_release(SPPrintContext *ctx)
61 {
62 return ctx->module->release();
63 }
65 unsigned int
66 sp_print_comment(SPPrintContext *ctx, char const *comment)
67 {
68 return ctx->module->comment(comment);
69 }
71 unsigned int
72 sp_print_fill(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
73 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
74 {
75 return ctx->module->fill(bpath, ctm, style, pbox, dbox, bbox);
76 }
78 unsigned int
79 sp_print_stroke(SPPrintContext *ctx, NRBPath const *bpath, NRMatrix const *ctm, SPStyle const *style,
80 NRRect const *pbox, NRRect const *dbox, NRRect const *bbox)
81 {
82 return ctx->module->stroke(bpath, ctm, style, pbox, dbox, bbox);
83 }
85 unsigned int
86 sp_print_image_R8G8B8A8_N(SPPrintContext *ctx,
87 guchar *px, unsigned int w, unsigned int h, unsigned int rs,
88 NRMatrix const *transform, SPStyle const *style)
89 {
90 return ctx->module->image(px, w, h, rs, transform, style);
91 }
93 unsigned int sp_print_text(SPPrintContext *ctx, char const *text, NR::Point p,
94 SPStyle const *style)
95 {
96 return ctx->module->text(text, p, style);
97 }
99 #include "display/nr-arena.h"
100 #include "display/nr-arena-item.h"
102 /* UI */
104 void
105 sp_print_preview_document(SPDocument *doc)
106 {
107 Inkscape::Extension::Print *mod;
108 unsigned int ret;
110 sp_document_ensure_up_to_date(doc);
112 mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
114 ret = mod->set_preview();
116 if (ret) {
117 SPPrintContext context;
118 context.module = mod;
120 /* fixme: This has to go into module constructor somehow */
121 /* Create new arena */
122 mod->base = SP_ITEM(sp_document_root(doc));
123 mod->arena = NRArena::create();
124 mod->dkey = sp_item_display_key_new(1);
125 mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
126 /* Print document */
127 ret = mod->begin(doc);
128 sp_item_invoke_print(mod->base, &context);
129 ret = mod->finish();
130 /* Release arena */
131 sp_item_invoke_hide(mod->base, mod->dkey);
132 mod->base = NULL;
133 nr_arena_item_unref(mod->root);
134 mod->root = NULL;
135 nr_object_unref((NRObject *) mod->arena);
136 mod->arena = NULL;
137 }
139 return;
140 }
142 #ifdef HAVE_GTK_UNIX_PRINT
143 static void
144 unix_print_complete (GtkPrintJob *print_job,
145 gpointer user_data,
146 GError *error)
147 {
148 fprintf(stderr,"print job finished: %s\n",error ? error->message : "no error");
149 }
151 static void
152 unix_print_dialog (const gchar * ps_file, const gchar * jobname)
153 {
154 Glib::ustring title = _("Print");
155 title += " ";
156 title += jobname;
157 GtkWidget* dlg = gtk_print_unix_dialog_new(title.c_str(), NULL);
159 // force output system to only handle our pre-generated PS output
160 gtk_print_unix_dialog_set_manual_capabilities (GTK_PRINT_UNIX_DIALOG(dlg),
161 GTK_PRINT_CAPABILITY_GENERATE_PS);
163 /*
164 * It would be nice to merge the PrintPS::setup routine with a custom
165 * configuration dialog:
167 gtk_print_unix_dialog_add_custom_tab (GtkPrintUnixDialog *dialog,
168 GtkWidget *child,
169 GtkWidget *tab_label);
170 */
172 int const response = gtk_dialog_run(GTK_DIALOG(dlg));
174 if (response == GTK_RESPONSE_OK) {
175 GtkPrinter* printer = gtk_print_unix_dialog_get_selected_printer(GTK_PRINT_UNIX_DIALOG(dlg));
177 if (gtk_printer_accepts_ps (printer)) {
178 GtkPrintJob* job = gtk_print_job_new (jobname, printer,
179 gtk_print_unix_dialog_get_settings(GTK_PRINT_UNIX_DIALOG(dlg)),
180 gtk_print_unix_dialog_get_page_setup(GTK_PRINT_UNIX_DIALOG(dlg)));
183 GError * error = NULL;
184 if ( gtk_print_job_set_source_file (job, ps_file, &error)) {
185 gtk_print_job_send (job, unix_print_complete, NULL, NULL);
186 }
187 else {
188 g_warning(_("Could not set print source: %s"),error ? error->message : _("unknown error"));
189 }
190 if (error) g_error_free(error);
191 }
192 else {
193 g_warning(_("Printer '%s' does not support PS output"), gtk_printer_get_name (printer));
194 }
195 }
196 else if (response == GTK_RESPONSE_APPLY) {
197 // since we didn't include the Preview capability,
198 // this should never happen.
199 g_warning(_("Print Preview not available"));
200 }
202 gtk_widget_destroy(dlg);
203 }
204 #endif // HAVE_GTK_UNIX_PRINT
207 void
208 sp_print_document(SPDocument *doc, unsigned int direct)
209 {
210 Inkscape::Extension::Print *mod;
211 unsigned int ret;
212 #ifdef HAVE_GTK_UNIX_PRINT
213 Glib::ustring tmpfile = "";
214 #endif
216 sp_document_ensure_up_to_date(doc);
218 if (direct) {
219 mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
220 } else {
221 mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_DEFAULT);
223 #ifdef HAVE_GTK_UNIX_PRINT
224 // unix print dialog reads from the exported tempfile
225 gchar *filename = NULL;
226 GError *error = NULL;
227 gint tmpfd = g_file_open_tmp("inkscape-ps-XXXXXX",
228 &filename,
229 &error);
230 if (tmpfd<0) {
231 g_warning(_("Failed to create tempfile for printing: %s"),
232 error ? error->message : _("unknown error"));
233 if (error) g_error_free(error);
234 return;
235 }
236 tmpfile = filename;
237 g_free(filename);
238 close(tmpfd);
240 Glib::ustring destination = ">" + tmpfile;
241 mod->set_param_string("destination", destination.c_str());
242 #endif
243 }
245 ret = mod->setup();
247 if (ret) {
248 SPPrintContext context;
249 context.module = mod;
251 /* fixme: This has to go into module constructor somehow */
252 /* Create new arena */
253 mod->base = SP_ITEM(sp_document_root(doc));
254 mod->arena = NRArena::create();
255 mod->dkey = sp_item_display_key_new(1);
256 mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
257 /* Print document */
258 ret = mod->begin(doc);
259 sp_item_invoke_print(mod->base, &context);
260 ret = mod->finish();
261 /* Release arena */
262 sp_item_invoke_hide(mod->base, mod->dkey);
263 mod->base = NULL;
264 nr_arena_item_unref(mod->root);
265 mod->root = NULL;
266 nr_object_unref((NRObject *) mod->arena);
267 mod->arena = NULL;
269 #ifdef HAVE_GTK_UNIX_PRINT
270 // redirect output to new print dialog
271 unix_print_dialog(tmpfile.c_str(),doc->name ? doc->name : _("SVG Document"));
272 unlink(tmpfile.c_str());
273 // end redirected new print dialog
274 #endif
275 }
277 return;
278 }
280 void
281 sp_print_document_to_file(SPDocument *doc, gchar const *filename)
282 {
283 Inkscape::Extension::Print *mod;
284 SPPrintContext context;
285 gchar const *oldconst;
286 gchar *oldoutput;
287 unsigned int ret;
289 sp_document_ensure_up_to_date(doc);
291 mod = Inkscape::Extension::get_print(SP_MODULE_KEY_PRINT_PS);
292 oldconst = mod->get_param_string("destination");
293 oldoutput = g_strdup(oldconst);
294 mod->set_param_string("destination", (gchar *)filename);
296 /* Start */
297 context.module = mod;
298 /* fixme: This has to go into module constructor somehow */
299 /* Create new arena */
300 mod->base = SP_ITEM(sp_document_root(doc));
301 mod->arena = NRArena::create();
302 mod->dkey = sp_item_display_key_new(1);
303 mod->root = sp_item_invoke_show(mod->base, mod->arena, mod->dkey, SP_ITEM_SHOW_DISPLAY);
304 /* Print document */
305 ret = mod->begin(doc);
306 sp_item_invoke_print(mod->base, &context);
307 ret = mod->finish();
308 /* Release arena */
309 sp_item_invoke_hide(mod->base, mod->dkey);
310 mod->base = NULL;
311 nr_arena_item_unref(mod->root);
312 mod->root = NULL;
313 nr_object_unref((NRObject *) mod->arena);
314 mod->arena = NULL;
315 /* end */
317 mod->set_param_string("destination", oldoutput);
318 g_free(oldoutput);
320 return;
321 }
324 /*
325 Local Variables:
326 mode:c++
327 c-file-style:"stroustrup"
328 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
329 indent-tabs-mode:nil
330 fill-column:99
331 End:
332 */
333 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :