Inkscape
Vector Graphics Editor
Loading...
Searching...
No Matches
gdkpixbuf-input.cpp
Go to the documentation of this file.
1// SPDX-License-Identifier: GPL-2.0-or-later
/*
5 * Authors: see git history
6 *
7 * Copyright (C) 2018 Authors
8 * Released under GNU GPL v2+, read the file 'COPYING' for more information.
9 */
10
11#include <gdk-pixbuf/gdk-pixbuf.h>
12#include <gdkmm/pixbuf.h>
13#include <gdkmm/pixbufformat.h>
14#include <glib/gprintf.h>
15#include <glibmm/i18n.h>
16
17#include "document.h"
18#include "document-undo.h"
19#include "gdkpixbuf-input.h"
20#include "image-resolution.h"
21#include "preferences.h"
22#include "selection-chemistry.h"
23
24#include "display/cairo-utils.h"
25
26#include "extension/input.h"
27#include "extension/system.h"
28
29#include "object/sp-image.h"
30#include "object/sp-root.h"
31
32#include "util/units.h"
33
35
36std::unique_ptr<SPDocument> GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri, bool)
37{
38 // Determine whether the image should be embedded
40 bool ask = prefs->getBool( "/dialogs/import/ask");
41 bool forcexdpi = prefs->getBool( "/dialogs/import/forcexdpi");
42 Glib::ustring link = prefs->getString("/dialogs/import/link");
43 Glib::ustring scale = prefs->getString("/dialogs/import/scale");
44
45 // If we asked about import preferences, get values and update preferences.
46 if (ask) {
47 ask = !mod->get_param_bool("do_not_ask");
48 forcexdpi = (strcmp(mod->get_param_optiongroup("dpi"), "from_default") == 0);
49 link = mod->get_param_optiongroup("link");
50 scale = mod->get_param_optiongroup("scale");
51
52 prefs->setBool( "/dialogs/import/ask", ask );
53 prefs->setBool( "/dialogs/import/forcexdpi", forcexdpi);
54 prefs->setString("/dialogs/import/link", link );
55 prefs->setString("/dialogs/import/scale", scale );
56 }
57
58 bool embed = (link == "embed");
59
60 std::unique_ptr<SPDocument> doc;
61 std::unique_ptr<Inkscape::Pixbuf> pb(Inkscape::Pixbuf::create_from_file(uri));
62
63 // TODO: the pixbuf is created again from the base64-encoded attribute in SPImage.
64 // Find a way to create the pixbuf only once.
65
66 if (pb) {
67 doc = SPDocument::createNewDoc(nullptr, true, true);
68 DocumentUndo::ScopedInsensitive _no_undo(doc.get());
69
70 double width = pb->width();
71 double height = pb->height();
72 double defaultxdpi = prefs->getDouble("/dialogs/import/defaultxdpi/value", Inkscape::Util::Quantity::convert(1, "in", "px"));
73
74 double xscale = 1;
75 double yscale = 1;
76
77 if (!forcexdpi) {
78 auto ir = ImageResolution{uri};
79 if (ir.ok()) {
80 xscale = 960.0 / std::round(10.0 * ir.x()); // round-off to 0.1 dpi
81 yscale = 960.0 / std::round(10.0 * ir.y());
82 // prevent crash on image with too small dpi (bug 1479193)
83 if (ir.x() <= .05)
84 xscale = 960.0;
85 if (ir.y() <= .05)
86 yscale = 960.0;
87 }
88 } else {
89 xscale = 96.0 / defaultxdpi;
90 yscale = 96.0 / defaultxdpi;
91 }
92
93 width *= xscale;
94 height *= yscale;
95
96 // Create image node
97 Inkscape::XML::Document *xml_doc = doc->getReprDoc();
98 Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image");
99 image_node->setAttributeSvgDouble("width", width);
100 image_node->setAttributeSvgDouble("height", height);
101
102 // Set default value as we honor "preserveAspectRatio".
103 image_node->setAttribute("preserveAspectRatio", "none");
104
105 // This is actually 'image-rendering'.
106 if( scale.compare( "auto" ) != 0 ) {
108 sp_repr_css_set_property(css, "image-rendering", scale.c_str());
109 sp_repr_css_set(image_node, css, "style");
111 }
112
113 if (embed) {
114 sp_embed_image(image_node, pb.get());
115 } else {
116 // convert filename to uri
117 gchar* _uri = g_filename_to_uri(uri, nullptr, nullptr);
118 if(_uri) {
119 image_node->setAttribute("xlink:href", _uri);
120 g_free(_uri);
121 } else {
122 image_node->setAttribute("xlink:href", uri);
123 }
124 }
125
126 // Add it to the current layer
127 Inkscape::XML::Node *layer_node = xml_doc->createElement("svg:g");
128 layer_node->setAttribute("inkscape:groupmode", "layer");
129 layer_node->setAttribute("inkscape:label", "Image");
130 doc->getRoot()->appendChildRepr(layer_node);
131 layer_node->appendChild(image_node);
132 Inkscape::GC::release(image_node);
133 Inkscape::GC::release(layer_node);
134 fit_canvas_to_drawing(doc.get());
135
136 // Set viewBox if it doesn't exist
137 if (!doc->getRoot()->viewBox_set) {
138 // std::cerr << "Viewbox not set, setting" << std::endl;
139 doc->setViewBox(Geom::Rect::from_xywh(0, 0, doc->getWidth().value(doc->getDisplayUnit()), doc->getHeight().value(doc->getDisplayUnit())));
140 }
141 } else {
142 printf("GdkPixbuf loader failed\n");
143 }
144
145 return doc;
146}
147
148#include "clear-n_.h"
149
150void
152{
153 static std::vector< Gdk::PixbufFormat > formatlist = Gdk::Pixbuf::get_formats();
154 for (auto i: formatlist) {
155 GdkPixbufFormat *pixformat = i.gobj();
156
157 gchar *name = gdk_pixbuf_format_get_name(pixformat);
158 gchar *description = gdk_pixbuf_format_get_description(pixformat);
159 gchar **extensions = gdk_pixbuf_format_get_extensions(pixformat);
160 gchar **mimetypes = gdk_pixbuf_format_get_mime_types(pixformat);
161
162 for (int i = 0; extensions[i] != nullptr; i++) {
163 for (int j = 0; mimetypes[j] != nullptr; j++) {
164
165 /* thanks but no thanks, we'll handle SVG extensions... */
166 if (strcmp(extensions[i], "svg") == 0) {
167 continue;
168 }
169 if (strcmp(extensions[i], "svgz") == 0) {
170 continue;
171 }
172 if (strcmp(extensions[i], "svg.gz") == 0) {
173 continue;
174 }
175 gchar *caption = g_strdup_printf(_("%s bitmap image import"), name);
176
177 // clang-format off
178 gchar *xmlString = g_strdup_printf(
179 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
180 "<name>%s</name>\n"
181 "<id>org.inkscape.input.gdkpixbuf.%s</id>\n"
182
183 "<param name='link' type='optiongroup' gui-text='" N_("Image Import Type:") "' gui-description='" N_("Embed results in stand-alone, larger SVG files. Link references a file outside this SVG document and all files must be moved together.") "' >\n"
184 "<option value='embed' >" N_("Embed") "</option>\n"
185 // TRANSLATORS: Image is displayed, and stored as a link or embedded
186 "<option value='link' >" N_("Link") "</option>\n"
187 "</param>\n"
188
189 "<param name='dpi' type='optiongroup' gui-text='" N_("Image DPI:") "' gui-description='" N_("Take information from file or use default bitmap import resolution as defined in the preferences.") "' >\n"
190 "<option value='from_file' >" N_("From file") "</option>\n"
191 "<option value='from_default' >" N_("Default import resolution") "</option>\n"
192 "</param>\n"
193
194 "<param name='scale' type='optiongroup' gui-text='" N_("Image Rendering Mode:") "' gui-description='" N_("When an image is upscaled, apply smoothing or keep blocky (pixelated). (Will not work in all browsers.)") "' >\n"
195 "<option value='auto' >" N_("None (auto)") "</option>\n"
196 "<option value='optimizeQuality' >" N_("Smooth (optimizeQuality)") "</option>\n"
197 "<option value='optimizeSpeed' >" N_("Blocky (optimizeSpeed)") "</option>\n"
198 "</param>\n"
199
200 "<param name=\"do_not_ask\" gui-description='" N_("Hide the dialog next time and always apply the same actions.") "' gui-text=\"" N_("Don't ask again") "\" type=\"bool\" >false</param>\n"
201 "<input>\n"
202 "<extension>.%s</extension>\n"
203 "<mimetype>%s</mimetype>\n"
204 "<filetypename>%s (*.%s)</filetypename>\n"
205 "<filetypetooltip>%s</filetypetooltip>\n"
206 "</input>\n"
207 "</inkscape-extension>",
208 caption,
209 extensions[i],
210 extensions[i],
211 mimetypes[j],
212 name,
213 extensions[i],
214 description
215 );
216 // clang-format off
217
218 Inkscape::Extension::build_from_mem(xmlString, std::make_unique<GdkpixbufInput>());
219 g_free(xmlString);
220 g_free(caption);
221 }}
222
223 g_free(name);
224 g_free(description);
225 g_strfreev(mimetypes);
226 g_strfreev(extensions);
227 }
228}
229
230} // namespace Inkscape::Extension::Internal
231
232/*
233 Local Variables:
234 mode:c++
235 c-file-style:"stroustrup"
236 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
237 indent-tabs-mode:nil
238 fill-column:99
239 End:
240*/
241// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :
double scale
Definition aa.cpp:228
Cairo integration helpers.
static CRect from_xywh(Coord x, Coord y, Coord w, Coord h)
Create rectangle from origin and dimensions.
RAII-style mechanism for creating a temporary undo-insensitive context.
std::unique_ptr< SPDocument > open(Inkscape::Extension::Input *mod, char const *uri, bool is_importing) override
Open a file.
static Pixbuf * create_from_file(std::string const &fn, double svgddpi=0)
Preference storage class.
Definition preferences.h:61
bool getBool(Glib::ustring const &pref_path, bool def=false)
Retrieve a Boolean value.
double getDouble(Glib::ustring const &pref_path, double def=0.0, Glib::ustring const &unit="")
Retrieve a floating point value.
Glib::ustring getString(Glib::ustring const &pref_path, Glib::ustring const &def="")
Retrieve an UTF-8 string.
static Preferences * get()
Access the singleton Preferences object.
void setString(Glib::ustring const &pref_path, Glib::ustring const &value)
Set an UTF-8 string value.
void setBool(Glib::ustring const &pref_path, bool value)
Set a Boolean value.
static double convert(double from_dist, Unit const *from, Unit const *to)
Convert distances.
Definition units.cpp:588
Interface for refcounted XML nodes.
Definition node.h:80
virtual void appendChild(Node *child)=0
Append a node as the last child of this node.
void setAttribute(Util::const_char_ptr key, Util::const_char_ptr value)
Change an attribute of this node.
Definition node.cpp:25
bool setAttributeSvgDouble(Util::const_char_ptr key, double val)
For attributes where an exponent is allowed.
Definition node.cpp:111
static std::unique_ptr< SPDocument > createNewDoc(char const *filename, bool keepalive, bool make_new=false, SPDocument *parent=nullptr)
Fetches document from filename, or creates new, if NULL; public document appears in document list.
Definition document.cpp:659
A way to clear the N_ macro, which is defined as an inline function.
std::shared_ptr< Css const > css
TODO: insert short description here.
TODO: insert short description here.
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:459
static R & release(R &r)
Decrements the reference count of a anchored object.
Singleton class to access the preferences file in a convenient way.
SPCSSAttr * sp_repr_css_attr_new()
Creates an empty SPCSSAttr (a class for manipulating CSS style properties).
Definition repr-css.cpp:67
void sp_repr_css_set(Node *repr, SPCSSAttr *css, gchar const *attr)
Sets an attribute (e.g.
Definition repr-css.cpp:264
void sp_repr_css_attr_unref(SPCSSAttr *css)
Unreferences an SPCSSAttr (will be garbage collected if no references remain).
Definition repr-css.cpp:76
void sp_repr_css_set_property(SPCSSAttr *css, gchar const *name, gchar const *value)
Set a style property to a new value (e.g.
Definition repr-css.cpp:190
bool fit_canvas_to_drawing(SPDocument *doc, bool with_margins)
void sp_embed_image(Inkscape::XML::Node *image_node, Inkscape::Pixbuf *pb)
Definition sp-image.cpp:716
SVG <image> implementation.
SPRoot: SVG <svg> implementation.
Interface for XML documents.
Definition document.h:43
virtual Node * createElement(char const *name)=0
double height
double width
Glib::ustring name
Definition toolbars.cpp:55