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 *
10 * Copyright (C) 2004-2006 Authors
11 *
12 * Released under GNU GPL, read the file 'COPYING' for more information
13 */
15 #ifdef HAVE_CONFIG_H
16 # include <config.h>
17 #endif
19 #ifdef HAVE_CAIRO_PDF
21 #include "cairo-ps-out.h"
22 #include "cairo-render-context.h"
23 #include "cairo-renderer.h"
24 #include "latex-text-renderer.h"
25 #include <print.h>
26 #include "extension/system.h"
27 #include "extension/print.h"
28 #include "extension/db.h"
29 #include "extension/output.h"
30 #include "display/nr-arena.h"
31 #include "display/nr-arena-item.h"
33 #include "display/curve.h"
34 #include "display/canvas-bpath.h"
35 #include "sp-item.h"
36 #include "style.h"
37 #include "sp-root.h"
38 #include "sp-shape.h"
40 #include "io/sys.h"
42 namespace Inkscape {
43 namespace Extension {
44 namespace Internal {
46 bool CairoPsOutput::check (Inkscape::Extension::Extension * /*module*/)
47 {
48 if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS)) {
49 return FALSE;
50 } else {
51 return TRUE;
52 }
53 }
55 bool CairoEpsOutput::check (Inkscape::Extension::Extension * /*module*/)
56 {
57 if (NULL == Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_EPS)) {
58 return FALSE;
59 } else {
60 return TRUE;
61 }
62 }
64 static bool
65 ps_print_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, bool texttopath, bool omittext,
66 bool filtertobitmap, int resolution, const gchar * const exportId, bool exportDrawing, bool exportCanvas, bool eps = false)
67 {
68 sp_document_ensure_up_to_date(doc);
70 SPItem *base = NULL;
72 bool pageBoundingBox = TRUE;
73 if (exportId && strcmp(exportId, "")) {
74 // we want to export the given item only
75 base = SP_ITEM(doc->getObjectById(exportId));
76 pageBoundingBox = exportCanvas;
77 }
78 else {
79 // we want to export the entire document from root
80 base = SP_ITEM(sp_document_root(doc));
81 pageBoundingBox = !exportDrawing;
82 }
84 if (!base)
85 return false;
87 /* Create new arena */
88 NRArena *arena = NRArena::create();
89 unsigned dkey = sp_item_display_key_new(1);
90 sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
92 /* Create renderer and context */
93 CairoRenderer *renderer = new CairoRenderer();
94 CairoRenderContext *ctx = renderer->createContext();
95 ctx->setPSLevel(level);
96 ctx->setEPS(eps);
97 ctx->setTextToPath(texttopath);
98 renderer->_omitText = omittext;
99 ctx->setFilterToBitmap(filtertobitmap);
100 ctx->setBitmapResolution(resolution);
102 bool ret = ctx->setPsTarget(filename);
103 if(ret) {
104 /* Render document */
105 ret = renderer->setupDocument(ctx, doc, pageBoundingBox, base);
106 if (ret) {
107 renderer->renderItem(ctx, base);
108 ret = ctx->finish();
109 }
110 }
112 /* Release arena */
113 sp_item_invoke_hide(base, dkey);
114 nr_object_unref((NRObject *) arena);
116 renderer->destroyContext(ctx);
117 delete renderer;
119 return ret;
120 }
123 /**
124 \brief This function calls the output module with the filename
125 \param mod unused
126 \param doc Document to be saved
127 \param filename Filename to save to (probably will end in .ps)
128 */
129 void
130 CairoPsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
131 {
132 Inkscape::Extension::Extension * ext;
133 unsigned int ret;
135 ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS);
136 if (ext == NULL)
137 return;
139 const gchar *new_level = NULL;
140 int level = CAIRO_PS_LEVEL_2;
141 try {
142 new_level = mod->get_param_enum("PSlevel");
143 if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0))
144 level = CAIRO_PS_LEVEL_3;
145 } catch(...) {}
147 bool new_textToPath = FALSE;
148 try {
149 new_textToPath = mod->get_param_bool("textToPath");
150 } catch(...) {}
152 bool new_textToLaTeX = FALSE;
153 try {
154 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
155 }
156 catch(...) {
157 g_warning("Parameter <textToLaTeX> might not exist");
158 }
160 bool new_blurToBitmap = FALSE;
161 try {
162 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
163 } catch(...) {}
165 int new_bitmapResolution = 72;
166 try {
167 new_bitmapResolution = mod->get_param_int("resolution");
168 } catch(...) {}
170 bool new_areaPage = true;
171 try {
172 new_areaPage = mod->get_param_bool("areaPage");
173 } catch(...) {}
175 bool new_areaDrawing = true;
176 try {
177 new_areaDrawing = mod->get_param_bool("areaDrawing");
178 } catch(...) {}
180 const gchar *new_exportId = NULL;
181 try {
182 new_exportId = mod->get_param_string("exportId");
183 } catch(...) {}
185 // Create PS
186 {
187 gchar * final_name;
188 final_name = g_strdup_printf("> %s", filename);
189 ret = ps_print_document_to_file(doc, final_name, level, new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution, new_exportId, new_areaDrawing, new_areaPage);
190 g_free(final_name);
192 if (!ret)
193 throw Inkscape::Extension::Output::save_failed();
194 }
196 // Create LaTeX file (if requested)
197 if (new_textToLaTeX) {
198 gchar * tex_filename;
199 //strip filename of ".ps", do not add ".tex" here.
200 gsize n = g_str_has_suffix(filename, ".ps") ? strlen(filename)-3 : strlen(filename);
201 tex_filename = g_strndup(filename, n);
202 ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage);
203 g_free(tex_filename);
205 if (!ret)
206 throw Inkscape::Extension::Output::save_failed();
207 }
208 }
211 /**
212 \brief This function calls the output module with the filename
213 \param mod unused
214 \param doc Document to be saved
215 \param filename Filename to save to (probably will end in .ps)
216 */
217 void
218 CairoEpsOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
219 {
220 Inkscape::Extension::Extension * ext;
221 unsigned int ret;
223 ext = Inkscape::Extension::db.get(SP_MODULE_KEY_PRINT_CAIRO_PS);
224 if (ext == NULL)
225 return;
227 const gchar *new_level = NULL;
228 int level = CAIRO_PS_LEVEL_2;
229 try {
230 new_level = mod->get_param_enum("PSlevel");
231 if((new_level != NULL) && !(g_ascii_strcasecmp("PS3", new_level) == 0))
232 level = CAIRO_PS_LEVEL_3;
233 } catch(...) {}
235 bool new_textToPath = FALSE;
236 try {
237 new_textToPath = mod->get_param_bool("textToPath");
238 } catch(...) {}
240 bool new_textToLaTeX = FALSE;
241 try {
242 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
243 }
244 catch(...) {
245 g_warning("Parameter <textToLaTeX> might not exist");
246 }
248 bool new_blurToBitmap = FALSE;
249 try {
250 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
251 } catch(...) {}
253 int new_bitmapResolution = 72;
254 try {
255 new_bitmapResolution = mod->get_param_int("resolution");
256 } catch(...) {}
258 bool new_areaPage = true;
259 try {
260 new_areaPage = mod->get_param_bool("areaPage");
261 } catch(...) {}
263 bool new_areaDrawing = true;
264 try {
265 new_areaDrawing = mod->get_param_bool("areaDrawing");
266 } catch(...) {}
268 const gchar *new_exportId = NULL;
269 try {
270 new_exportId = mod->get_param_string("exportId");
271 } catch(...) {}
273 // Create EPS
274 {
275 gchar * final_name;
276 final_name = g_strdup_printf("> %s", filename);
277 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);
278 g_free(final_name);
280 if (!ret)
281 throw Inkscape::Extension::Output::save_failed();
282 }
284 // Create LaTeX file (if requested)
285 if (new_textToLaTeX) {
286 gchar * tex_filename;
287 //strip filename of ".eps", do not add ".tex" here.
288 gsize n = g_str_has_suffix(filename, ".eps") ? strlen(filename)-4 : strlen(filename);
289 tex_filename = g_strndup(filename, n);
290 ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_areaDrawing, new_areaPage);
291 g_free(tex_filename);
293 if (!ret)
294 throw Inkscape::Extension::Output::save_failed();
295 }
296 }
299 bool
300 CairoPsOutput::textToPath(Inkscape::Extension::Print * ext)
301 {
302 return ext->get_param_bool("textToPath");
303 }
305 bool
306 CairoEpsOutput::textToPath(Inkscape::Extension::Print * ext)
307 {
308 return ext->get_param_bool("textToPath");
309 }
311 #include "clear-n_.h"
313 /**
314 \brief A function allocate a copy of this function.
316 This is the definition of Cairo PS out. This function just
317 calls the extension system with the memory allocated XML that
318 describes the data.
319 */
320 void
321 CairoPsOutput::init (void)
322 {
323 Inkscape::Extension::build_from_mem(
324 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
325 "<name>" N_("PostScript") "</name>\n"
326 "<id>" SP_MODULE_KEY_PRINT_CAIRO_PS "</id>\n"
327 "<param name=\"PSlevel\" gui-text=\"" N_("Restrict to PS level") "\" type=\"enum\" >\n"
328 "<_item value='PS3'>" N_("PostScript level 3") "</_item>\n"
329 #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2))
330 "<_item value='PS2'>" N_("PostScript level 2") "</_item>\n"
331 #endif
332 "</param>\n"
333 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
334 "<param name=\"textToLaTeX\" gui-text=\"" N_("PS+LaTeX: Omit text in PS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
335 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
336 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
337 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
338 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">true</param>\n"
339 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
340 "<output>\n"
341 "<extension>.ps</extension>\n"
342 "<mimetype>image/x-postscript</mimetype>\n"
343 "<filetypename>" N_("PostScript (*.ps)") "</filetypename>\n"
344 "<filetypetooltip>" N_("PostScript File") "</filetypetooltip>\n"
345 "</output>\n"
346 "</inkscape-extension>", new CairoPsOutput());
348 return;
349 }
351 /**
352 \brief A function allocate a copy of this function.
354 This is the definition of Cairo EPS out. This function just
355 calls the extension system with the memory allocated XML that
356 describes the data.
357 */
358 void
359 CairoEpsOutput::init (void)
360 {
361 Inkscape::Extension::build_from_mem(
362 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
363 "<name>" N_("Encapsulated PostScript") "</name>\n"
364 "<id>" SP_MODULE_KEY_PRINT_CAIRO_EPS "</id>\n"
365 "<param name=\"PSlevel\" gui-text=\"" N_("Restrict to PS level") "\" type=\"enum\" >\n"
366 "<_item value='PS3'>" N_("PostScript level 3") "</_item>\n"
367 #if (CAIRO_VERSION >= CAIRO_VERSION_ENCODE(1, 5, 2))
368 "<_item value='PS2'>" N_("PostScript level 2") "</_item>\n"
369 #endif
370 "</param>\n"
371 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
372 "<param name=\"textToLaTeX\" gui-text=\"" N_("EPS+LaTeX: Omit text in EPS, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
373 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
374 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
375 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">true</param>\n"
376 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">true</param>\n"
377 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
378 "<output>\n"
379 "<extension>.eps</extension>\n"
380 "<mimetype>image/x-e-postscript</mimetype>\n"
381 "<filetypename>" N_("Encapsulated PostScript (*.eps)") "</filetypename>\n"
382 "<filetypetooltip>" N_("Encapsulated PostScript File") "</filetypetooltip>\n"
383 "</output>\n"
384 "</inkscape-extension>", new CairoEpsOutput());
386 return;
387 }
389 } } } /* namespace Inkscape, Extension, Implementation */
391 #endif /* HAVE_CAIRO_PDF */