594389c60f7f83cf6e7dba105d5c7172c0f8f2bb
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 bool ret = renderer->setTargetFile(filename);
142 if (ret) {
143 /* Render document */
144 bool ret = renderer->setupDocument(doc, pageBoundingBox, base);
145 if (ret) {
146 renderer->renderItem(base);
147 }
148 }
150 delete renderer;
152 return ret;
153 }
156 /**
157 \brief This function calls the output module with the filename
158 \param mod unused
159 \param doc Document to be saved
160 \param filename Filename to save to (probably will end in .pdf)
162 The most interesting thing that this function does is just attach
163 an '>' on the front of the filename. This is the syntax used to
164 tell the printing system to save to file.
165 */
166 void
167 CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
168 {
169 Inkscape::Extension::Extension * ext;
170 unsigned int ret;
172 ext = Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer");
173 if (ext == NULL)
174 return;
176 const gchar *new_level = NULL;
177 int level = 0;
178 try {
179 new_level = mod->get_param_enum("PDFversion");
180 // if((new_level != NULL) && (g_ascii_strcasecmp("PDF-1.x", new_level) == 0))
181 // level = 1;
182 }
183 catch(...) {
184 // g_warning("Parameter <PDFversion> might not exist");
185 }
187 bool new_textToPath = FALSE;
188 try {
189 new_textToPath = mod->get_param_bool("textToPath");
190 }
191 catch(...) {
192 g_warning("Parameter <textToPath> might not exist");
193 }
195 bool new_textToLaTeX = FALSE;
196 try {
197 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
198 }
199 catch(...) {
200 g_warning("Parameter <textToLaTeX> might not exist");
201 }
203 bool new_blurToBitmap = FALSE;
204 try {
205 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
206 }
207 catch(...) {
208 g_warning("Parameter <blurToBitmap> might not exist");
209 }
211 int new_bitmapResolution = 72;
212 try {
213 new_bitmapResolution = mod->get_param_int("resolution");
214 }
215 catch(...) {
216 g_warning("Parameter <resolution> might not exist");
217 }
219 const gchar *new_exportId = NULL;
220 try {
221 new_exportId = mod->get_param_string("exportId");
222 }
223 catch(...) {
224 g_warning("Parameter <exportId> might not exist");
225 }
227 bool new_exportDrawing = FALSE;
228 try {
229 new_exportDrawing = mod->get_param_bool("areaDrawing");
230 }
231 catch(...) {
232 g_warning("Parameter <areaDrawing> might not exist");
233 }
235 bool new_exportCanvas = FALSE;
236 try {
237 new_exportCanvas = mod->get_param_bool("areaPage");
238 }
239 catch(...) {
240 g_warning("Parameter <exportCanvas> might not exist");
241 }
243 // Create PDF file
244 {
245 gchar * final_name;
246 final_name = g_strdup_printf("> %s", filename);
247 ret = pdf_render_document_to_file(doc, final_name, level,
248 new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution,
249 new_exportId, new_exportDrawing, new_exportCanvas);
250 g_free(final_name);
252 if (!ret)
253 throw Inkscape::Extension::Output::save_failed();
254 }
256 // Create LaTeX file (if requested)
257 if (new_textToLaTeX) {
258 gchar * tex_filename;
259 //strip filename of ".pdf", do not add ".tex" here.
260 gsize n = g_str_has_suffix(filename, ".pdf") ? strlen(filename)-4 : strlen(filename);
261 tex_filename = g_strndup(filename, n);
262 ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_exportDrawing, new_exportCanvas);
263 g_free(tex_filename);
265 if (!ret)
266 throw Inkscape::Extension::Output::save_failed();
267 }
268 }
270 #include "clear-n_.h"
272 /**
273 \brief A function allocate a copy of this function.
275 This is the definition of Cairo PDF out. This function just
276 calls the extension system with the memory allocated XML that
277 describes the data.
278 */
279 void
280 CairoRendererPdfOutput::init (void)
281 {
282 Inkscape::Extension::build_from_mem(
283 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
284 "<name>Portable Document Format</name>\n"
285 "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
286 "<param name=\"PDFversion\" gui-text=\"" N_("Restrict to PDF version") "\" type=\"enum\" >\n"
287 "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
288 "</param>\n"
289 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
290 "<param name=\"textToLaTeX\" gui-text=\"" N_("Exclude text, create LaTeX file") "\" type=\"boolean\">false</param>\n"
291 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
292 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
293 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n"
294 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">false</param>\n"
295 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
296 "<output>\n"
297 "<extension>.pdf</extension>\n"
298 "<mimetype>application/pdf</mimetype>\n"
299 "<filetypename>Portable Document Format (*.pdf)</filetypename>\n"
300 "<filetypetooltip>PDF File</filetypetooltip>\n"
301 "</output>\n"
302 "</inkscape-extension>", new CairoRendererPdfOutput());
304 return;
305 }
307 } } } /* namespace Inkscape, Extension, Internal */
309 #endif /* HAVE_CAIRO_PDF */