1 /*
2 * A quick hack to use the Cairo renderer to write out a file. This
3 * then makes 'save as...' PDF.
4 *
5 * Authors:
6 * Ted Gould <ted@gould.cx>
7 * Ulf Erikson <ulferikson@users.sf.net>
8 *
9 * Copyright (C) 2004-2006 Authors
10 *
11 * Released under GNU GPL, read the file 'COPYING' for more information
12 */
14 #ifdef HAVE_CONFIG_H
15 # include <config.h>
16 #endif
18 #ifdef HAVE_CAIRO_PDF
20 #include "cairo-renderer-pdf-out.h"
21 #include "cairo-render-context.h"
22 #include "cairo-renderer.h"
23 #include "pdflatex-renderer.h"
24 #include <print.h>
25 #include "extension/system.h"
26 #include "extension/print.h"
27 #include "extension/db.h"
28 #include "extension/output.h"
29 #include "display/nr-arena.h"
30 #include "display/nr-arena-item.h"
32 #include "display/curve.h"
33 #include "display/canvas-bpath.h"
34 #include "sp-item.h"
35 #include "sp-root.h"
37 #include <2geom/matrix.h>
39 namespace Inkscape {
40 namespace Extension {
41 namespace Internal {
43 bool
44 CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module)
45 {
46 if (NULL == Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer"))
47 return FALSE;
49 return TRUE;
50 }
52 static bool
53 pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level,
54 bool texttopath, bool omittext, bool filtertobitmap, int resolution,
55 const gchar * const exportId, bool exportDrawing, bool exportCanvas)
56 {
57 sp_document_ensure_up_to_date(doc);
59 /* Start */
61 SPItem *base = NULL;
63 bool pageBoundingBox = TRUE;
64 if (exportId && strcmp(exportId, "")) {
65 // we want to export the given item only
66 base = SP_ITEM(doc->getObjectById(exportId));
67 pageBoundingBox = exportCanvas;
68 }
69 else {
70 // we want to export the entire document from root
71 base = SP_ITEM(sp_document_root(doc));
72 pageBoundingBox = !exportDrawing;
73 }
75 if (!base)
76 return false;
78 /* Create new arena */
79 NRArena *arena = NRArena::create();
80 nr_arena_set_renderoffscreen (arena);
81 unsigned dkey = sp_item_display_key_new(1);
82 sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
84 /* Create renderer and context */
85 CairoRenderer *renderer = new CairoRenderer();
86 CairoRenderContext *ctx = renderer->createContext();
87 ctx->setPDFLevel(level);
88 ctx->setTextToPath(texttopath);
89 renderer->_omitText = omittext;
90 ctx->setFilterToBitmap(filtertobitmap);
91 ctx->setBitmapResolution(resolution);
93 bool ret = ctx->setPdfTarget (filename);
94 if(ret) {
95 /* Render document */
96 ret = renderer->setupDocument(ctx, doc, pageBoundingBox, base);
97 if (ret) {
98 renderer->renderItem(ctx, base);
99 ret = ctx->finish();
100 }
101 }
103 /* Release arena */
104 sp_item_invoke_hide(base, dkey);
105 nr_object_unref((NRObject *) arena);
107 renderer->destroyContext(ctx);
108 delete renderer;
110 return ret;
111 }
113 static bool
114 latex_render_document_text_to_file( SPDocument *doc, gchar const *filename,
115 const gchar * const exportId, bool exportDrawing, bool exportCanvas)
116 {
117 sp_document_ensure_up_to_date(doc);
119 /* Start */
121 SPItem *base = NULL;
123 bool pageBoundingBox = true;
124 if (exportId && strcmp(exportId, "")) {
125 // we want to export the given item only
126 base = SP_ITEM(doc->getObjectById(exportId));
127 pageBoundingBox = exportCanvas;
128 }
129 else {
130 // we want to export the entire document from root
131 base = SP_ITEM(sp_document_root(doc));
132 pageBoundingBox = !exportDrawing;
133 }
135 if (!base)
136 return false;
138 /* Create renderer */
139 PDFLaTeXRenderer *renderer = new PDFLaTeXRenderer();
141 /* Render document */
142 bool ret = renderer->setupDocument(doc, pageBoundingBox, base);
143 if (ret) {
144 renderer->renderItem(base);
145 }
147 delete renderer;
149 return ret;
150 }
153 /**
154 \brief This function calls the output module with the filename
155 \param mod unused
156 \param doc Document to be saved
157 \param filename Filename to save to (probably will end in .pdf)
159 The most interesting thing that this function does is just attach
160 an '>' on the front of the filename. This is the syntax used to
161 tell the printing system to save to file.
162 */
163 void
164 CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
165 {
166 Inkscape::Extension::Extension * ext;
167 unsigned int ret;
169 ext = Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer");
170 if (ext == NULL)
171 return;
173 const gchar *new_level = NULL;
174 int level = 0;
175 try {
176 new_level = mod->get_param_enum("PDFversion");
177 // if((new_level != NULL) && (g_ascii_strcasecmp("PDF-1.x", new_level) == 0))
178 // level = 1;
179 }
180 catch(...) {
181 // g_warning("Parameter <PDFversion> might not exist");
182 }
184 bool new_textToPath = FALSE;
185 try {
186 new_textToPath = mod->get_param_bool("textToPath");
187 }
188 catch(...) {
189 g_warning("Parameter <textToPath> might not exist");
190 }
192 bool new_textToLaTeX = FALSE;
193 try {
194 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
195 }
196 catch(...) {
197 g_warning("Parameter <textToLaTeX> might not exist");
198 }
200 bool new_blurToBitmap = FALSE;
201 try {
202 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
203 }
204 catch(...) {
205 g_warning("Parameter <blurToBitmap> might not exist");
206 }
208 int new_bitmapResolution = 72;
209 try {
210 new_bitmapResolution = mod->get_param_int("resolution");
211 }
212 catch(...) {
213 g_warning("Parameter <resolution> might not exist");
214 }
216 const gchar *new_exportId = NULL;
217 try {
218 new_exportId = mod->get_param_string("exportId");
219 }
220 catch(...) {
221 g_warning("Parameter <exportId> might not exist");
222 }
224 bool new_exportDrawing = FALSE;
225 try {
226 new_exportDrawing = mod->get_param_bool("areaDrawing");
227 }
228 catch(...) {
229 g_warning("Parameter <areaDrawing> might not exist");
230 }
232 bool new_exportCanvas = FALSE;
233 try {
234 new_exportCanvas = mod->get_param_bool("areaPage");
235 }
236 catch(...) {
237 g_warning("Parameter <exportCanvas> might not exist");
238 }
240 // Create PDF file
241 {
242 gchar * final_name;
243 final_name = g_strdup_printf("> %s", filename);
244 ret = pdf_render_document_to_file(doc, final_name, level,
245 new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution,
246 new_exportId, new_exportDrawing, new_exportCanvas);
247 g_free(final_name);
249 if (!ret)
250 throw Inkscape::Extension::Output::save_failed();
251 }
253 // Create LaTeX file (if requested)
254 if (new_textToLaTeX) {
255 gchar * tex_filename;
256 tex_filename = g_strdup_printf("%s.tex", filename);
257 ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_exportDrawing, new_exportCanvas);
258 g_free(tex_filename);
260 if (!ret)
261 throw Inkscape::Extension::Output::save_failed();
262 }
263 }
265 #include "clear-n_.h"
267 /**
268 \brief A function allocate a copy of this function.
270 This is the definition of Cairo PDF out. This function just
271 calls the extension system with the memory allocated XML that
272 describes the data.
273 */
274 void
275 CairoRendererPdfOutput::init (void)
276 {
277 Inkscape::Extension::build_from_mem(
278 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
279 "<name>Portable Document Format</name>\n"
280 "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
281 "<param name=\"PDFversion\" gui-text=\"" N_("Restrict to PDF version") "\" type=\"enum\" >\n"
282 "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
283 "</param>\n"
284 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
285 "<param name=\"textToLaTeX\" gui-text=\"" N_("Exclude text, create LaTeX file") "\" type=\"boolean\">false</param>\n"
286 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
287 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
288 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n"
289 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">false</param>\n"
290 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
291 "<output>\n"
292 "<extension>.pdf</extension>\n"
293 "<mimetype>application/pdf</mimetype>\n"
294 "<filetypename>Portable Document Format (*.pdf)</filetypename>\n"
295 "<filetypetooltip>PDF File</filetypetooltip>\n"
296 "</output>\n"
297 "</inkscape-extension>", new CairoRendererPdfOutput());
299 return;
300 }
302 } } } /* namespace Inkscape, Extension, Internal */
304 #endif /* HAVE_CAIRO_PDF */