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 <print.h>
24 #include "extension/system.h"
25 #include "extension/print.h"
26 #include "extension/db.h"
27 #include "extension/output.h"
28 #include "display/nr-arena.h"
29 #include "display/nr-arena-item.h"
31 #include "display/curve.h"
32 #include "display/canvas-bpath.h"
33 #include "sp-item.h"
34 #include "sp-root.h"
36 namespace Inkscape {
37 namespace Extension {
38 namespace Internal {
40 bool
41 CairoRendererPdfOutput::check (Inkscape::Extension::Extension * module)
42 {
43 if (NULL == Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer"))
44 return FALSE;
46 return TRUE;
47 }
49 static bool
50 pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level,
51 bool texttopath, bool filtertobitmap, int resolution,
52 const gchar * const exportId, bool exportDrawing, bool exportCanvas)
53 {
54 sp_document_ensure_up_to_date(doc);
56 /* Start */
58 SPItem *base = NULL;
60 bool pageBoundingBox = TRUE;
61 if (exportId && strcmp(exportId, "")) {
62 // we want to export the given item only
63 base = SP_ITEM(doc->getObjectById(exportId));
64 pageBoundingBox = exportCanvas;
65 }
66 else {
67 // we want to export the entire document from root
68 base = SP_ITEM(sp_document_root(doc));
69 pageBoundingBox = !exportDrawing;
70 }
72 if (!base)
73 return false;
75 /* Create new arena */
76 NRArena *arena = NRArena::create();
77 nr_arena_set_renderoffscreen (arena);
78 unsigned dkey = sp_item_display_key_new(1);
79 sp_item_invoke_show(base, arena, dkey, SP_ITEM_SHOW_DISPLAY);
81 /* Create renderer and context */
82 CairoRenderer *renderer = new CairoRenderer();
83 CairoRenderContext *ctx = renderer->createContext();
84 ctx->setPDFLevel(level);
85 ctx->setTextToPath(texttopath);
86 ctx->setFilterToBitmap(filtertobitmap);
87 ctx->setBitmapResolution(resolution);
89 bool ret = ctx->setPdfTarget (filename);
90 if(ret) {
91 /* Render document */
92 ret = renderer->setupDocument(ctx, doc, pageBoundingBox, base);
93 if (ret) {
94 renderer->renderItem(ctx, base);
95 ret = ctx->finish();
96 }
97 }
99 /* Release arena */
100 sp_item_invoke_hide(base, dkey);
101 nr_object_unref((NRObject *) arena);
103 renderer->destroyContext(ctx);
104 delete renderer;
106 return ret;
107 }
110 /**
111 \brief This function calls the output module with the filename
112 \param mod unused
113 \param doc Document to be saved
114 \param filename Filename to save to (probably will end in .pdf)
116 The most interesting thing that this function does is just attach
117 an '>' on the front of the filename. This is the syntax used to
118 tell the printing system to save to file.
119 */
120 void
121 CairoRendererPdfOutput::save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename)
122 {
123 Inkscape::Extension::Extension * ext;
124 unsigned int ret;
126 ext = Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer");
127 if (ext == NULL)
128 return;
130 const gchar *new_level = NULL;
131 int level = 0;
132 try {
133 new_level = mod->get_param_enum("PDFversion");
134 // if((new_level != NULL) && (g_ascii_strcasecmp("PDF-1.x", new_level) == 0))
135 // level = 1;
136 }
137 catch(...) {
138 // g_warning("Parameter <PDFversion> might not exist");
139 }
141 bool new_textToPath = FALSE;
142 try {
143 new_textToPath = mod->get_param_bool("textToPath");
144 }
145 catch(...) {
146 g_warning("Parameter <textToPath> might not exist");
147 }
149 bool new_blurToBitmap = FALSE;
150 try {
151 new_blurToBitmap = mod->get_param_bool("blurToBitmap");
152 }
153 catch(...) {
154 g_warning("Parameter <blurToBitmap> might not exist");
155 }
157 int new_bitmapResolution = 72;
158 try {
159 new_bitmapResolution = mod->get_param_int("resolution");
160 }
161 catch(...) {
162 g_warning("Parameter <resolution> might not exist");
163 }
165 const gchar *new_exportId = NULL;
166 try {
167 new_exportId = mod->get_param_string("exportId");
168 }
169 catch(...) {
170 g_warning("Parameter <exportId> might not exist");
171 }
173 bool new_exportDrawing = FALSE;
174 try {
175 new_exportDrawing = mod->get_param_bool("areaDrawing");
176 }
177 catch(...) {
178 g_warning("Parameter <areaDrawing> might not exist");
179 }
181 bool new_exportCanvas = FALSE;
182 try {
183 new_exportCanvas = mod->get_param_bool("areaCanvas");
184 }
185 catch(...) {
186 g_warning("Parameter <exportCanvas> might not exist");
187 }
189 gchar * final_name;
190 final_name = g_strdup_printf("> %s", filename);
191 ret = pdf_render_document_to_file(doc, final_name, level,
192 new_textToPath, new_blurToBitmap, new_bitmapResolution,
193 new_exportId, new_exportDrawing, new_exportCanvas);
194 g_free(final_name);
196 if (!ret)
197 throw Inkscape::Extension::Output::save_failed();
198 }
200 #include "clear-n_.h"
202 /**
203 \brief A function allocate a copy of this function.
205 This is the definition of Cairo PDF out. This function just
206 calls the extension system with the memory allocated XML that
207 describes the data.
208 */
209 void
210 CairoRendererPdfOutput::init (void)
211 {
212 Inkscape::Extension::build_from_mem(
213 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
214 "<name>Portable Document Format</name>\n"
215 "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
216 "<param name=\"PDFversion\" gui-text=\"" N_("Restrict to PDF version") "\" type=\"enum\" >\n"
217 "<_item value='PDF14'>" N_("PDF 1.4") "</_item>\n"
218 "</param>\n"
219 "<param name=\"textToPath\" gui-text=\"" N_("Convert texts to paths") "\" type=\"boolean\">false</param>\n"
220 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"boolean\">true</param>\n"
221 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi)") "\" type=\"int\" min=\"1\" max=\"10000\">90</param>\n"
222 "<param name=\"areaDrawing\" gui-text=\"" N_("Export drawing, not page") "\" type=\"boolean\">false</param>\n"
223 "<param name=\"areaCanvas\" gui-text=\"" N_("Export canvas") "\" type=\"boolean\">false</param>\n"
224 "<param name=\"exportId\" gui-text=\"" N_("Limit export to the object with ID") "\" type=\"string\"></param>\n"
225 "<output>\n"
226 "<extension>.pdf</extension>\n"
227 "<mimetype>application/pdf</mimetype>\n"
228 "<filetypename>Portable Document Format (*.pdf)</filetypename>\n"
229 "<filetypetooltip>PDF File</filetypetooltip>\n"
230 "</output>\n"
231 "</inkscape-extension>", new CairoRendererPdfOutput());
233 return;
234 }
236 } } } /* namespace Inkscape, Extension, Internal */
238 #endif /* HAVE_CAIRO_PDF */