Inkscape
Vector Graphics Editor
cairo-renderer-pdf-out.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
2/*
3 * A quick hack to use the Cairo renderer to write out a file. This
4 * then makes 'save as...' PDF.
5 *
6 * Authors:
7 * Ted Gould <ted@gould.cx>
8 * Ulf Erikson <ulferikson@users.sf.net>
9 * Johan Engelen <goejendaagh@zonnet.nl>
10 * Jon A. Cruz <jon@joncruz.org>
11 * Abhishek Sharma
12 *
13 * Copyright (C) 2004-2010 Authors
14 *
15 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
16 */
17
18#include <cairo.h>
19#ifdef CAIRO_HAS_PDF_SURFACE
20
23#include "cairo-renderer.h"
24#include "latex-text-renderer.h"
25#include "path-chemistry.h"
26#include <print.h>
27#include "extension/system.h"
28#include "extension/print.h"
29#include "extension/db.h"
30#include "extension/output.h"
31
32#include "display/drawing.h"
33#include "display/curve.h"
34
35#include "object/sp-item.h"
36#include "object/sp-root.h"
37#include "object/sp-page.h"
38
39#include <2geom/affine.h>
40#include "page-manager.h"
41#include "document.h"
42
43#include "util/units.h"
44
45namespace Inkscape {
46namespace Extension {
47namespace Internal {
48
50{
51 bool result = true;
52
53 if (nullptr == Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer")) {
54 result = false;
55 }
56
57 return result;
58}
59
60// TODO: Make this function more generic so that it can do both PostScript and PDF; expose in the headers
61static bool
62pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, PDFOptions flags,
63 int resolution)
64{
65 if (flags.text_to_path) {
66 assert(!flags.text_to_latex);
67 // Cairo's text-to-path method has numerical precision and font matching
68 // issues (https://gitlab.com/inkscape/inkscape/-/issues/1979).
69 // We get better results by using Inkscape's Object-to-Path method.
71 }
72
73 doc->ensureUpToDate();
74
75 SPRoot *root = doc->getRoot();
76 if (!root) {
77 return false;
78 }
79
80 /* Create new drawing */
81 Inkscape::Drawing drawing;
82 unsigned dkey = SPItem::display_key_new(1);
83 drawing.setRoot(root->invoke_show(drawing, dkey, SP_ITEM_SHOW_DISPLAY));
84 drawing.setExact();
85
86 /* Create renderer and context */
87 CairoRenderer renderer;
88 CairoRenderContext ctx = renderer.createContext();
89 ctx.setPDFLevel(level);
90 ctx.setTextToPath(flags.text_to_path);
91 ctx.setOmitText(flags.text_to_latex);
93 ctx.setBitmapResolution(resolution);
94
95 bool ret = ctx.setPdfTarget(filename)
96 && renderer.setupDocument(&ctx, doc, root)
97 && renderer.renderPages(&ctx, doc, flags.stretch_to_fit);
98 if (ret) {
99 ctx.finish();
100 }
101
102 root->invoke_hide(dkey);
103 return ret;
104}
105
116void
118{
120 unsigned int ret;
121
122 ext = Inkscape::Extension::db.get("org.inkscape.output.pdf.cairorenderer");
123 if (ext == nullptr)
124 return;
125
126 int level = 0;
127 try {
128 const gchar *new_level = mod->get_param_optiongroup("PDFversion");
129 if((new_level != nullptr) && (g_ascii_strcasecmp("PDF-1.5", new_level) == 0)) {
130 level = 1;
131 }
132 }
133 catch(...) {
134 g_warning("Parameter <PDFversion> might not exist");
135 }
136
137 PDFOptions flags;
138 flags.text_to_path = false;
139 try {
140 flags.text_to_path = (strcmp(mod->get_param_optiongroup("textToPath"), "paths") == 0);
141 }
142 catch(...) {
143 g_warning("Parameter <textToPath> might not exist");
144 }
145
146 flags.text_to_latex = false;
147 try {
148 flags.text_to_latex = (strcmp(mod->get_param_optiongroup("textToPath"), "LaTeX") == 0);
149 }
150 catch(...) {
151 g_warning("Parameter <textToLaTeX> might not exist");
152 }
153
154 flags.rasterize_filters = false;
155 try {
156 flags.rasterize_filters = mod->get_param_bool("blurToBitmap");
157 }
158 catch(...) {
159 g_warning("Parameter <blurToBitmap> might not exist");
160 }
161
162 int new_bitmapResolution = 72;
163 try {
164 new_bitmapResolution = mod->get_param_int("resolution");
165 }
166 catch(...) {
167 g_warning("Parameter <resolution> might not exist");
168 }
169
170 flags.stretch_to_fit = false;
171 try {
172 flags.stretch_to_fit = (strcmp(ext->get_param_optiongroup("stretch"), "relative") == 0);
173 } catch(...) {
174 g_warning("Parameter <stretch> might not exist");
175 }
176
177 // Create PDF file
178 {
179 gchar * final_name;
180 final_name = g_strdup_printf("> %s", filename);
181 ret = pdf_render_document_to_file(doc, final_name, level, flags, new_bitmapResolution);
182 g_free(final_name);
183
184 if (!ret)
186 }
187
188 // Create LaTeX file (if requested)
189 if (flags.text_to_latex) {
190 ret = latex_render_document_text_to_file(doc, filename, true);
191
192 if (!ret)
194 }
195}
196
197#include "clear-n_.h"
198
206void
208{
209 // clang-format off
211 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
212 "<name>Portable Document Format</name>\n"
213 "<id>org.inkscape.output.pdf.cairorenderer</id>\n"
214 "<param name=\"PDFversion\" gui-text=\"" N_("Restrict to PDF version:") "\" type=\"optiongroup\" appearance=\"combo\" >\n"
215 "<option value='PDF-1.5'>" N_("PDF 1.5") "</option>\n"
216 "<option value='PDF-1.4'>" N_("PDF 1.4") "</option>\n"
217 "</param>\n"
218 "<param name=\"textToPath\" gui-text=\"" N_("Text output options:") "\" type=\"optiongroup\" appearance=\"radio\">\n"
219 "<option value=\"embed\">" N_("Embed fonts") "</option>\n"
220 "<option value=\"paths\">" N_("Convert text to paths") "</option>\n"
221 "<option value=\"LaTeX\">" N_("Omit text in PDF and create LaTeX file") "</option>\n"
222 "</param>\n"
223 "<param name=\"blurToBitmap\" gui-text=\"" N_("Rasterize filter effects") "\" type=\"bool\">true</param>\n"
224 "<param name=\"resolution\" gui-text=\"" N_("Resolution for rasterization (dpi):") "\" type=\"int\" min=\"1\" max=\"10000\">96</param>\n"
225 "<spacer size=\"10\" />"
226 "<param name=\"stretch\" gui-text=\"" N_("Rounding compensation:") "\" gui-description=\""
227 N_("Exporting to PDF rounds the document size to the next whole number in pt units. Compensation may stretch the drawing slightly (up to 0.35mm for width and/or height). When not compensating, object sizes will be preserved strictly, but this can sometimes cause white gaps along the page margins.")
228 "\" type=\"optiongroup\" appearance=\"radio\" >\n"
229 "<option value=\"relative\">" N_("Compensate for rounding (recommended)") "</option>"
230 "<option value=\"absolute\">" N_("Do not compensate") "</option>"
231 "</param><separator/>"
232 "<hbox indent=\"1\"><image>info-outline</image><spacer/><vbox><spacer/>"
233 "<label>" N_("When exporting from the Export dialog, you can choose objects to export. 'Save a copy' / 'Save as' will export all pages.") "</label>"
234 "<spacer size=\"5\" />"
235 "<label>" N_("The page bleed can be set with the Page tool.") "</label>"
236 "</vbox></hbox>"
237 "<output is_exported='true' priority='5'>\n"
238 "<extension>.pdf</extension>\n"
239 "<mimetype>application/pdf</mimetype>\n"
240 "<filetypename>PDF (*.pdf)</filetypename>\n"
241 "<filetypetooltip>PDF File</filetypetooltip>\n"
242 "</output>\n"
243 "</inkscape-extension>", std::make_unique<CairoRendererPdfOutput>());
244 // clang-format on
245
246 return;
247}
248
249} } } /* namespace Inkscape, Extension, Internal */
250
251#endif /* HAVE_CAIRO_PDF */
3x3 affine transformation matrix.
Declaration of CairoRenderContext, a class used for rendering with Cairo.
Declaration of CairoRenderer, a class used for rendering via a CairoRenderContext.
void setRoot(DrawingItem *root)
Definition: drawing.cpp:63
Extension * get(const gchar *key) const
This function looks up a Inkscape::Extension::Extension by using its unique id. It then returns a ref...
Definition: db.cpp:101
The object that is the basis for the Extension system.
Definition: extension.h:130
char const * get_param_optiongroup(char const *name, char const *alt) const
Like get_param_optiongroup but with a default on param_not_exist error.
Definition: extension.cpp:757
static void init()
A function allocate a copy of this function.
void save(Inkscape::Extension::Output *mod, SPDocument *doc, gchar const *filename) override
This function calls the output module with the filename.
bool check(Inkscape::Extension::Extension *module) override
Verify any dependencies.
bool renderPages(CairoRenderContext *ctx, SPDocument *doc, bool stretch_to_fit)
Handle multiple pages, pushing each out to cairo as needed using renderItem()
bool setupDocument(CairoRenderContext *ctx, SPDocument *doc, SPItem const *base=nullptr)
Initializes the CairoRenderContext according to the specified SPDocument.
Generic failure for an undescribed reason.
Definition: output.h:34
Typed SVG document implementation.
Definition: document.h:106
SPRoot * getRoot()
Returns our SPRoot.
Definition: document.h:205
int ensureUpToDate()
Repeatedly works on getting the document updated, since sometimes it takes more than one pass to get ...
Definition: document.cpp:1474
static unsigned int display_key_new(unsigned numkeys)
Allocates unique integer keys.
Definition: sp-item.cpp:1169
<svg> element
Definition: sp-root.h:32
A way to clear the N_ macro, which is defined as an inline function.
RootCluster root
Definition: containment.cpp:50
Css & result
SVG drawing for display.
Declaration of LaTeXTextRenderer, used for rendering the accompanying LaTeX file when exporting to PD...
int mod(int i, int l)
bool latex_render_document_text_to_file(SPDocument *doc, gchar const *filename, bool pdflatex)
This method is called by the PDF, EPS and PS output extensions.
static bool pdf_render_document_to_file(SPDocument *doc, gchar const *filename, unsigned int level, PDFOptions flags, int resolution)
DB db
This is the actual database object.
Definition: db.cpp:32
void build_from_mem(gchar const *buffer, std::unique_ptr< Implementation::Implementation > in_imp)
Create a module from a buffer holding an XML description.
Definition: system.cpp:471
CMYK to sRGB conversion routines.
void convert_text_to_curves(SPDocument *)
Convert all text in the document to path, in-place.
Some things pertinent to all visible shapes: SPItem, SPItemView, SPItemCtx.
SPPage – a page object.
SPRoot: SVG <svg> implementation.
bool stretch_to_fit
Compensate for Cairo's page size rounding to integers (in pt)?
bool rasterize_filters
Rasterize filter effects?
bool text_to_latex
Put text in a LaTeX document?