1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4 #include <glib/gprintf.h>
5 #include <glibmm/i18n.h>
6 #include "document-private.h"
7 #include <dir-util.h>
8 #include "extension/input.h"
9 #include "extension/system.h"
10 #include "gdkpixbuf-input.h"
11 #include "selection-chemistry.h"
12 #include "sp-image.h"
14 namespace Inkscape {
16 namespace IO {
17 GdkPixbuf* pixbuf_new_from_file( char const *utf8name, GError **error );
18 }
20 namespace Extension {
21 namespace Internal {
23 static std::set<Glib::ustring> create_lossy_set()
24 {
25 std::set<Glib::ustring> lossy;
26 lossy.insert(".jpg");
27 lossy.insert(".jpeg");
28 return lossy;
29 }
31 SPDocument *
32 GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
33 {
34 bool embed = (strcmp(mod->get_param_optiongroup("link"), "embed") == 0);
36 SPDocument *doc = NULL;
37 GdkPixbuf *pb = Inkscape::IO::pixbuf_new_from_file( uri, NULL );
38 static std::set<Glib::ustring> lossy = create_lossy_set();
40 if (pb) { /* We are readable */
41 bool is_lossy;
42 Glib::ustring mime_type, ext;
43 Glib::ustring u = uri;
44 std::size_t dotpos = u.rfind('.');
45 if (dotpos != Glib::ustring::npos) {
46 ext = u.substr(dotpos, Glib::ustring::npos);
47 }
49 // HACK: replace with something better based on GIO
50 if (!ext.empty() && lossy.find(ext) != lossy.end()) {
51 is_lossy = true;
52 mime_type = "image/jpeg";
53 } else {
54 is_lossy = false;
55 mime_type = "image/png";
56 }
58 doc = sp_document_new(NULL, TRUE, TRUE);
59 bool saved = sp_document_get_undo_sensitive(doc);
60 sp_document_set_undo_sensitive(doc, false); // no need to undo in this temporary document
62 double width = gdk_pixbuf_get_width(pb);
63 double height = gdk_pixbuf_get_height(pb);
64 gchar const *str = gdk_pixbuf_get_option( pb, "Inkscape::DpiX" );
65 if ( str ) {
66 gint dpi = atoi(str);
67 if ( dpi > 0 && dpi != 72 ) {
68 double scale = 72.0 / (double)dpi;
69 width *= scale;
70 }
71 }
72 str = gdk_pixbuf_get_option( pb, "Inkscape::DpiY" );
73 if ( str ) {
74 gint dpi = atoi(str);
75 if ( dpi > 0 && dpi != 72 ) {
76 double scale = 72.0 / (double)dpi;
77 height *= scale;
78 }
79 }
81 // Create image node
82 Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
83 Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image");
84 sp_repr_set_svg_double(image_node, "width", width);
85 sp_repr_set_svg_double(image_node, "height", height);
87 if (embed) {
88 sp_embed_image(image_node, pb, mime_type);
89 } else {
90 // convert filename to uri
91 gchar* _uri = g_filename_to_uri(uri, NULL, NULL);
92 if(_uri) {
93 image_node->setAttribute("xlink:href", _uri);
94 g_free(_uri);
95 } else {
96 image_node->setAttribute("xlink:href", uri);
97 }
98 }
100 g_object_unref(pb);
102 // Add it to the current layer
103 SP_DOCUMENT_ROOT(doc)->appendChildRepr(image_node);
104 Inkscape::GC::release(image_node);
105 fit_canvas_to_drawing(doc);
106 // restore undo, as now this document may be shown to the user if a bitmap was opened
107 sp_document_set_undo_sensitive(doc, saved);
108 } else {
109 printf("GdkPixbuf loader failed\n");
110 }
112 return doc;
113 }
115 #include "clear-n_.h"
117 void
118 GdkpixbufInput::init(void)
119 {
120 GSList * formatlist, * formatlisthead;
122 /* \todo I'm not sure if I need to free this list */
123 for (formatlist = formatlisthead = gdk_pixbuf_get_formats();
124 formatlist != NULL;
125 formatlist = g_slist_next(formatlist)) {
127 GdkPixbufFormat *pixformat = (GdkPixbufFormat *)formatlist->data;
129 gchar *name = gdk_pixbuf_format_get_name(pixformat);
130 gchar *description = gdk_pixbuf_format_get_description(pixformat);
131 gchar **extensions = gdk_pixbuf_format_get_extensions(pixformat);
132 gchar **mimetypes = gdk_pixbuf_format_get_mime_types(pixformat);
134 for (int i = 0; extensions[i] != NULL; i++) {
135 for (int j = 0; mimetypes[j] != NULL; j++) {
137 /* thanks but no thanks, we'll handle SVG extensions... */
138 if (strcmp(extensions[i], "svg") == 0) {
139 continue;
140 }
141 if (strcmp(extensions[i], "svgz") == 0) {
142 continue;
143 }
144 if (strcmp(extensions[i], "svg.gz") == 0) {
145 continue;
146 }
147 gchar *caption = g_strdup_printf(_("%s GDK pixbuf Input"), name);
148 gchar *xmlString = g_strdup_printf(
149 "<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
150 "<name>%s</name>\n"
151 "<id>org.inkscape.input.gdkpixbuf.%s</id>\n"
152 "<param name='link' type='optiongroup' appearance='full' _gui-text='" N_("Link or embed image:") "' >\n"
153 "<_option value='embed'>" N_("embed") "</_option>\n"
154 "<_option value='link'>" N_("link") "</_option>\n"
155 "</param>\n"
156 "<_param name='help' type='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.") "</_param>\n"
157 "<input>\n"
158 "<extension>.%s</extension>\n"
159 "<mimetype>%s</mimetype>\n"
160 "<filetypename>%s (*.%s)</filetypename>\n"
161 "<filetypetooltip>%s</filetypetooltip>\n"
162 "</input>\n"
163 "</inkscape-extension>",
164 caption,
165 extensions[i],
166 extensions[i],
167 mimetypes[j],
168 name,
169 extensions[i],
170 description
171 );
173 Inkscape::Extension::build_from_mem(xmlString, new GdkpixbufInput());
174 g_free(xmlString);
175 g_free(caption);
176 }}
178 g_free(name);
179 g_free(description);
180 g_strfreev(mimetypes);
181 g_strfreev(extensions);
182 }
184 g_slist_free(formatlisthead);
185 }
187 } } } /* namespace Inkscape, Extension, Implementation */
189 /*
190 Local Variables:
191 mode:c++
192 c-file-style:"stroustrup"
193 c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
194 indent-tabs-mode:nil
195 fill-column:99
196 End:
197 */
198 // vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 :