1 /*
2 * A quick hack to use the Cairo renderer to write out a file. This
3 * then makes 'save as...' PS.
4 *
5 * Authors:
6 * Ted Gould <ted@gould.cx>
7 * Ulf Erikson <ulferikson@users.sf.net>
8 * Adib Taraben <theAdib@yahoo.com>
9 * Jon A. Cruz <jon@joncruz.org>
10 * Abhishek Sharma
11 *
12 * Copyright (C) 2004-2006 Authors
13 *
14 * Released under GNU GPL, read the file 'COPYING' for more information
15 */
17 #ifdef HAVE_CONFIG_H
18 # include <config.h>
19 #endif
21 #ifdef HAVE_CAIRO_PDF
23 #include "cairo-ps-out.h"
24 #include "cairo-render-context.h"
25 #include "cairo-renderer.h"
26 #include "latex-text-renderer.h"
27 #include <print.h>
28 #include "extension/system.h"
29 #include "extension/print.h"
30 #include "extension/db.h"
31 #include "extension/output.h"
32 #include "display/nr-arena.h"
33 #include "display/nr-arena-item.h"
35 #include "display/curve.h"
36 #include "display/canvas-bpath.h"
37 #include "sp-item.h"
38 #include "style.h"
39 #include "sp-root.h"
40 #include "sp-shape.h"
42 #include "io/sys.h"
44 namespace Inkscape {
45 namespace Extension {
46 namespace Internal {
48 bool CairoPsOutput::check (Inkscape::Extension::Extension * /*module*/)
49 {
50 if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS)) {
51 return FALSE;
52 } else {
53 return TRUE;
54 }
55 }
57 bool CairoEpsOutput::check (Inkscape::Extension::Extension * /*module*/)
58 {
59 if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_EPS)) {
60 return FALSE;
61 } else {
62 return TRUE;
63 }
64 }
66 static bool
67 ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool omittext,
68 bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false)
69 {
70 doc->ensureUpToDate();
72 SPItem *base = NULL;
74 bool pageBoundingBox = TRUE;
75 if (exportId && strcmp(exportId, "")) {
76 // we want to export the given item only
77 base = SP_ITEM(doc->getObjectById(exportId));
78 pageBoundingBox = exportCanvas;
79 }
80 else {
81 // we want to export the entire document from root
82 base = SP_ITEM(doc->getRoot());
83 pageBoundingBox = !exportDrawing;
84 }
86 if (!base)
87 return false;
89 /* Create new arena */
90 NRArena *arena = NRArena::create();
91 unsigned dkey = SPItem::display_key_new(1);
92 base->invoke_show(arena, dkey, SP_ITEM_SHOW_DISPLAY);
94 /* Create renderer and context */
95 CairoRenderer *renderer = new CairoRenderer();
96 CairoRenderContext *ctx = renderer->createContext();
97 ctx->setPSLevel(level);
98 ctx->setEPS(eps);
99 ctx->setTextToPath(texttopath);
100 renderer->_omitText = omittext;
101 ctx->setFilterToBitmap(filtertobitmap);
102 ctx->setBitmapResolution(resolution);
104 bool ret = ctx->setPsTarget(filename);
105 if(ret) {
106 /* Render document */
107 ret = renderer->setupDocument(ctx, doc, pageBoundingBox, base);
108 if (ret) {
109 renderer->renderItem(ctx, base);
110 ret = ctx->finish();
111 }
112 }
114 /* Release arena */
115 base->invoke_hide(dkey);
116 nr_object_unref((NRObject *) arena);
118 renderer->destroyContext(ctx);
119 delete renderer;
121 return ret;
122 }
125 /**
126 \brief This function calls the output module with the filename
127 \param mod unused
128 \param doc Document to be saved
129 \param filename Filename to save to (probably will end in .ps)
130 */
131 void
132 CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
133 {
134 Inkscape::Extension::Extension * ext;
135 unsigned int ret;
137 ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS);
138 if (ext == NULL)
139 return;
141 const gchar *new_level = NULL;
142 int level = CAIRO_PS_LEVEL_2;
143 try {
144 new_level = mod->get_param_enum("PSlevel");
145 if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0))
146 level = CAIRO_PS_LEVEL_3;
147 } catch(...) {}
149 bool new_textToPath = FALSE;
150 try {
151 new_textToPath = mod->get_param_bool("textToPath");
152 } catch(...) {}
154 bool new_textToLaTeX = FALSE;
155 try {
156 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
157 }
158 catch(...) {
159 g_warning("Parameter <textToLaTeX> might not exist");
160 }
162 bool new_blurToBitmap = FALSE;
163 try {
164 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
165 } catch(...) {}
167 int new_bitmapResolution = 72;
168 try {
169 new_bitmapResolution = mod->get_param_int("resolution");
170 } catch(...) {}
172 bool new_areaPage = true;
173 try {
174 new_areaPage = mod->get_param_bool("areaPage");
175 } catch(...) {}
177 bool new_areaDrawing = true;
178 try {
179 new_areaDrawing = mod->get_param_bool("areaDrawing");
180 } catch(...) {}
182 const gchar *new_exportId = NULL;
183 try {
184 new_exportId = mod->get_param_string("exportId");
185 } catch(...) {}
187 // Create PS
188 {
189 gchar * final_name;
190 final_name = g_strdup_printf("> %s", filename);
191 ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage);
192 g_free(final_name);
194 if (!ret)
195 throw Inkscape::Extension::Output::save_failed();
196 }
198 // Create LaTeX file (if requested)
199 if (new_textToLaTeX) {
200 ret = latex_render_document_text_to_file(doc, filename, new_exportId, new_areaDrawing, new_areaPage, false);
202 if (!ret)
203 throw Inkscape::Extension::Output::save_failed();
204 }
205 }
208 /**
209 \brief This function calls the output module with the filename
210 \param mod unused
211 \param doc Document to be saved
212 \param filename Filename to save to (probably will end in .ps)
213 */
214 void
215 CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
216 {
217 Inkscape::Extension::Extension * ext;
218 unsigned int ret;
220 ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS);
221 if (ext == NULL)
222 return;
224 const gchar *new_level = NULL;
225 int level = CAIRO_PS_LEVEL_2;
226 try {
227 new_level = mod->get_param_enum("PSlevel");
228 if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0))
229 level = CAIRO_PS_LEVEL_3;
230 } catch(...) {}
232 bool new_textToPath = FALSE;
233 try {
234 new_textToPath = mod->get_param_bool("textToPath");
235 } catch(...) {}
237 bool new_textToLaTeX = FALSE;
238 try {
239 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
240 }
241 catch(...) {
242 g_warning("Parameter <textToLaTeX> might not exist");
243 }
245 bool new_blurToBitmap = FALSE;
246 try {
247 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
248 } catch(...) {}
250 int new_bitmapResolution = 72;
251 try {
252 new_bitmapResolution = mod->get_param_int("resolution");
253 } catch(...) {}
255 bool new_areaPage = true;
256 try {
257 new_areaPage = mod->get_param_bool("areaPage");
258 } catch(...) {}
260 bool new_areaDrawing = true;
261 try {
262 new_areaDrawing = mod->get_param_bool("areaDrawing");
263 } catch(...) {}
265 const gchar *new_exportId = NULL;
266 try {
267 new_exportId = mod->get_param_string("exportId");
268 } catch(...) {}
270 // Create EPS
271 {
272 gchar * final_name;
273 final_name = g_strdup_printf("> %s", filename);
274 ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage, true);
275 g_free(final_name);
277 if (!ret)
278 throw Inkscape::Extension::Output::save_failed();
279 }
281 // Create LaTeX file (if requested)
282 if (new_textToLaTeX) {
283 ret = latex_render_document_text_to_file(doc, filename, new_exportId, new_areaDrawing, new_areaPage, false);
285 if (!ret)
286 throw Inkscape::Extension::Output::save_failed();
287 }
288 }
291 bool
292 CairoPsOutput::textToPath(Inkscape::Extension::Print * ext)
293 {
294 return ext->get_param_bool("textToPath");
295 }
297 bool
298 CairoEpsOutput::textToPath(Inkscape::Extension::Print * ext)
299 {
300 return ext->get_param_bool("textToPath");
301 }
303 #include "clear-n_.h"
305 /**
306 \brief A function allocate a copy of this function.
308 This is the definition of Cairo PS out. This function just
309 calls the extension system with the memory allocated XML that
310 describes the data.
311 */
312 void
313 CairoPsOutput::init (void)
314 {
315 Inkscape::Extension::build_from_mem(
316 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
317 "<name>" N_("PostScript") "</name>\n"
318 "<id>" SP_MODULE_KEY_PRINT_CAIRO_PS "</id>\n"
319 "<param name=\"PSlevel\" gui-text=\"" N_("Restrict to PS level:") "\" type=\"enum\" >\n"
320 "<_item value='PS3'>" N_("PostScript level 3") "</_item>\n"
321 #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2))
322 "<_item value='PS2'>" N_("PostScript level 2") "</_item>\n"
323 #endif
324 "</param>\n"
325 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
326 "<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
327 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
328 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
329 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
330 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">true</param>\n"
331 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID:") "\" type=\"string\"></param>\n"
332 "<output>\n"
333 "<extension>.ps</extension>\n"
334 "<mimetype>image/x-postscript</mimetype>\n"
335 "<filetypename>" N_("PostScript (*.ps)") "</filetypename>\n"
336 "<filetypetooltip>" N_("PostScript File") "</filetypetooltip>\n"
337 "</output>\n"
338 "</inkscape-extension>", new CairoPsOutput());
340 return;
341 }
343 /**
344 \brief A function allocate a copy of this function.
346 This is the definition of Cairo EPS out. This function just
347 calls the extension system with the memory allocated XML that
348 describes the data.
349 */
350 void
351 CairoEpsOutput::init (void)
352 {
353 Inkscape::Extension::build_from_mem(
354 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
355 "<name>" N_("Encapsulated PostScript") "</name>\n"
356 "<id>" SP_MODULE_KEY_PRINT_CAIRO_EPS "</id>\n"
357 "<param name=\"PSlevel\" gui-text=\"" N_("Restrict to PS level:") "\" type=\"enum\" >\n"
358 "<_item value='PS3'>" N_("PostScript level 3") "</_item>\n"
359 #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2))
360 "<_item value='PS2'>" N_("PostScript level 2") "</_item>\n"
361 #endif
362 "</param>\n"
363 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
364 "<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
365 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
366 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
367 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
368 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">true</param>\n"
369 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID:") "\" type=\"string\"></param>\n"
370 "<output>\n"
371 "<extension>.eps</extension>\n"
372 "<mimetype>image/x-e-postscript</mimetype>\n"
373 "<filetypename>" N_("Encapsulated PostScript (*.eps)") "</filetypename>\n"
374 "<filetypetooltip>" N_("Encapsulated PostScript File") "</filetypetooltip>\n"
375 "</output>\n"
376 "</inkscape-extension>", new CairoEpsOutput());
378 return;
379 }
381 } } } /* namespace Inkscape, Extension, Implementation */
383 #endif /* HAVE_CAIRO_PDF */