Code

BUG 322116, PDF export does not use the highest quality for rasterized filter
[inkscape.git] / src / extension / internal / cairo-renderer-pdf-out.cpp
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;
74     
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;
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)
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();
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)
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;
236 } } }  /* namespace Inkscape, Extension, Internal */
238 #endif /* HAVE_CAIRO_PDF */