1dcfbdf1d746d94e0ff5772505e380f7d5786f70
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 * Johan Engelen <goejendaagh@zonnet.nl>
9 *
10 * Copyright (C) 2004-2010 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-renderer-pdf-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 "sp-root.h"
38 #include <2geom/matrix.h>
40 namespace Inkscape {
41 namespace Extension {
42 namespace Internal {
44 bool
45 CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module)
46 {
47 if (NULL == Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer"))
48 return FALSE;
50 return TRUE;
51 }
53 static bool
54 pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level,
55 bool texttopath, bool omittext, bool filtertobitmap, int resolution,
56 const gchar * const exportId, bool exportDrawing, bool exportCanvas)
57 {
58 sp_document_ensure_up_to_date(doc);
60 /* Start */
62 SPItem *base = NULL;
64 bool pageBoundingBox = TRUE;
65 if (exportId && strcmp(exportId, "")) {
66 // we want to export the given item only
67 base = SP_ITEM(doc->getObjectById(exportId));
68 pageBoundingBox = exportCanvas;
69 }
70 else {
71 // we want to export the entire document from root
72 base = SP_ITEM(sp_document_root(doc));
73 pageBoundingBox = !exportDrawing;
74 }
76 if (!base)
77 return false;
79 /* Create new arena */
80 NRArena *arena = NRArena::create();
81 nr_arena_set_renderoffscreen (arena);
82 unsigned dkey = sp_item_display_key_new(1);
83 sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
85 /* Create renderer and context */
86 CairoRenderer *renderer = new CairoRenderer();
87 CairoRenderContext *ctx = renderer->createContext();
88 ctx->setPDFLevel(level);
89 ctx->setTextToPath(texttopath);
90 renderer->_omitText = omittext;
91 ctx->setFilterToBitmap(filtertobitmap);
92 ctx->setBitmapResolution(resolution);
94 bool ret = ctx->setPdfTarget (filename);
95 if(ret) {
96 /* Render document */
97 ret = renderer->setupDocument(ctx, doc, pageBoundingBox, base);
98 if (ret) {
99 renderer->renderItem(ctx, base);
100 ret = ctx->finish();
101 }
102 }
104 /* Release arena */
105 sp_item_invoke_hide(base, dkey);
106 nr_object_unref((NRObject *) arena);
108 renderer->destroyContext(ctx);
109 delete renderer;
111 return ret;
112 }
114 /**
115 \brief This function calls the output module with the filename
116 \param mod unused
117 \param doc Document to be saved
118 \param filename Filename to save to (probably will end in .pdf)
120 The most interesting thing that this function does is just attach
121 an '>' on the front of the filename. This is the syntax used to
122 tell the printing system to save to file.
123 */
124 void
125 CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
126 {
127 Inkscape::Extension::Extension * ext;
128 unsigned int ret;
130 ext = Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer");
131 if (ext == NULL)
132 return;
134 const gchar *new_level = NULL;
135 int level = 0;
136 try {
137 new_level = mod->get_param_enum("PDFversion");
138 // if((new_level != NULL) && (g_ascii_strcasecmp("PDF-1.x", new_level) == 0))
139 // level = 1;
140 }
141 catch(...) {
142 // g_warning("Parameter <PDFversion> might not exist");
143 }
145 bool new_textToPath = FALSE;
146 try {
147 new_textToPath = mod->get_param_bool("textToPath");
148 }
149 catch(...) {
150 g_warning("Parameter <textToPath> might not exist");
151 }
153 bool new_textToLaTeX = FALSE;
154 try {
155 new_textToLaTeX = mod->get_param_bool("textToLaTeX");
156 }
157 catch(...) {
158 g_warning("Parameter <textToLaTeX> might not exist");
159 }
161 bool new_blurToBitmap = FALSE;
162 try {
163 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
164 }
165 catch(...) {
166 g_warning("Parameter <blurToBitmap> might not exist");
167 }
169 int new_bitmapResolution = 72;
170 try {
171 new_bitmapResolution = mod->get_param_int("resolution");
172 }
173 catch(...) {
174 g_warning("Parameter <resolution> might not exist");
175 }
177 const gchar *new_exportId = NULL;
178 try {
179 new_exportId = mod->get_param_string("exportId");
180 }
181 catch(...) {
182 g_warning("Parameter <exportId> might not exist");
183 }
185 bool new_exportDrawing = FALSE;
186 try {
187 new_exportDrawing = mod->get_param_bool("areaDrawing");
188 }
189 catch(...) {
190 g_warning("Parameter <areaDrawing> might not exist");
191 }
193 bool new_exportCanvas = FALSE;
194 try {
195 new_exportCanvas = mod->get_param_bool("areaPage");
196 }
197 catch(...) {
198 g_warning("Parameter <exportCanvas> might not exist");
199 }
201 // Create PDF file
202 {
203 gchar * final_name;
204 final_name = g_strdup_printf("> %s", filename);
205 ret = pdf_render_document_to_file(doc, final_name, level,
206 new_textToPath, new_textToLaTeX, new_blurToBitmap, new_bitmapResolution,
207 new_exportId, new_exportDrawing, new_exportCanvas);
208 g_free(final_name);
210 if (!ret)
211 throw Inkscape::Extension::Output::save_failed();
212 }
214 // Create LaTeX file (if requested)
215 if (new_textToLaTeX) {
216 gchar * tex_filename;
217 //strip filename of ".pdf", do not add ".tex" here.
218 gsize n = g_str_has_suffix(filename, ".pdf") ? strlen(filename)-4 : strlen(filename);
219 tex_filename = g_strndup(filename, n);
220 ret = latex_render_document_text_to_file(doc, tex_filename, new_exportId, new_exportDrawing, new_exportCanvas);
221 g_free(tex_filename);
223 if (!ret)
224 throw Inkscape::Extension::Output::save_failed();
225 }
226 }
228 #include "clear-n_.h"
230 /**
231 \brief A function allocate a copy of this function.
233 This is the definition of Cairo PDF out. This function just
234 calls the extension system with the memory allocated XML that
235 describes the data.
236 */
237 void
238 CairoRendererPdfOutput::init (void)
239 {
240 Inkscape::Extension::build_from_mem(
241 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
242 "<name>Portable Document Format</name>\n"
243 "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
244 "<param name=\"PDFversion\" gui-text=\"" N_("Restrict to PDF version") "\" type=\"enum\" >\n"
245 "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
246 "</param>\n"
247 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
248 "<param name=\"textToLaTeX\" gui-text=\"" N_("PDF+LaTeX: Omit text in PDF, and create LaTeX file") "\" type=\"boolean\">false</param>\n"
249 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
250 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
251 "<param name=\"areaDrawing\" gui-text=\"" N_("Export area is drawing") "\" type=\"boolean\">false</param>\n"
252 "<param name=\"areaPage\" gui-text=\"" N_("Export area is page") "\" type=\"boolean\">false</param>\n"
253 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
254 "<output>\n"
255 "<extension>.pdf</extension>\n"
256 "<mimetype>application/pdf</mimetype>\n"
257 "<filetypename>Portable Document Format (*.pdf)</filetypename>\n"
258 "<filetypetooltip>PDF File</filetypetooltip>\n"
259 "</output>\n"
260 "</inkscape-extension>", new CairoRendererPdfOutput());
262 return;
263 }
265 } } } /* namespace Inkscape, Extension, Internal */
267 #endif /* HAVE_CAIRO_PDF */