summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: afa4f5b)
raw | patch | inline | side by side (parent: afa4f5b)
author | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Thu, 4 Mar 2010 23:34:30 +0000 (00:34 +0100) | ||
committer | Krzysztof Kosiński <tweenk.pl@gmail.com> | |
Thu, 4 Mar 2010 23:34:30 +0000 (00:34 +0100) |
index 52d5f5148b540e3915a1bf1f5354ca2764dad108..b36d2e3a13478194dc50923770cd0e35373d9daa 100644 (file)
not related to the module directly. If the Repr does not include
a name and an ID the module will be left in an errored state.
*/
-Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp) : _help(NULL)
+Extension::Extension (Inkscape::XML::Node * in_repr, Implementation::Implementation * in_imp)
+ : _help(NULL)
+ , _gui(true)
{
repr = in_repr;
Inkscape::GC::anchor(in_repr);
Gtk::Widget *
Extension::autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal)
{
- if (param_visible_count() == 0) return NULL;
+ if (!_gui || param_visible_count() == 0) return NULL;
AutoGUI * agui = Gtk::manage(new AutoGUI());
index 48ca86cf780871c77fdaef8206aabecb21206ff0..6210e2eba6ea1fbcaaeae6e6c0e3c6a87d486911 100644 (file)
state_t _state; /**< Which state the Extension is currently in */
std::vector<Dependency *> _deps; /**< Dependencies for this extension */
static std::ofstream error_file; /**< This is the place where errors get reported */
+ bool _gui;
protected:
Inkscape::XML::Node *repr; /**< The XML description of the Extension */
public:
Gtk::Widget * autogui (SPDocument * doc, Inkscape::XML::Node * node, sigc::signal<void> * changeSignal = NULL);
void paramListString (std::list <std::string> & retlist);
+ void set_gui(bool s) { _gui = s; }
/* Extension editor dialog stuff */
public:
diff --git a/src/extension/input.h b/src/extension/input.h
index 55d807ce26ba30d93fe4fd54800de7e28a65614b..24cbc4896c048215684f02b8d43ea9884c93e8be 100644 (file)
--- a/src/extension/input.h
+++ b/src/extension/input.h
#ifndef INKSCAPE_EXTENSION_INPUT_H__
#define INKSCAPE_EXTENSION_INPUT_H__
+#include <exception>
#include <glib.h>
#include "extension.h"
#include "xml/repr.h"
gchar *output_extension; /**< Setting of what output extension should be used */
public:
- class open_failed {}; /**< Generic failure for an undescribed reason */
- class no_extension_found {}; /**< Failed because we couldn't find an extension to match the filename */
+ struct open_failed : public std::exception {
+ virtual ~open_failed() throw() {}
+ const char *what() const throw() { return "Open failed"; }
+ };
+ struct no_extension_found : public std::exception {
+ virtual ~no_extension_found() throw() {}
+ const char *what() const throw() { return "No suitable input extension found"; }
+ };
Input (Inkscape::XML::Node * in_repr,
Implementation::Implementation * in_imp);
diff --git a/src/extension/internal/gdkpixbuf-input.cpp b/src/extension/internal/gdkpixbuf-input.cpp
index 64a099c8a42e3c673b89b3348936c0e4050d6174..47cde4a5acbffd5cff24b3294fe70d6bee253c7a 100644 (file)
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
+#include <glib/gprintf.h>
#include "document-private.h"
#include <dir-util.h>
+#include "extension/input.h"
#include "extension/system.h"
#include "gdkpixbuf-input.h"
#include "selection-chemistry.h"
namespace Extension {
namespace Internal {
+static std::set<Glib::ustring> create_lossy_set()
+{
+ std::set<Glib::ustring> lossy;
+ lossy.insert(".jpg");
+ lossy.insert(".jpeg");
+ return lossy;
+}
+
SPDocument *
-GdkpixbufInput::open(Inkscape::Extension::Input */*mod*/, char const *uri)
+GdkpixbufInput::open(Inkscape::Extension::Input *mod, char const *uri)
{
+ bool embed = !mod->get_param_bool("link");
SPDocument *doc = NULL;
GdkPixbuf *pb = Inkscape::IO::pixbuf_new_from_file( uri, NULL );
+ static std::set<Glib::ustring> lossy = create_lossy_set();
if (pb) { /* We are readable */
+ bool is_lossy;
+ Glib::ustring mime_type, ext;
+ Glib::ustring u = uri;
+ std::size_t dotpos = u.rfind('.');
+ if (dotpos != Glib::ustring::npos) {
+ ext = u.substr(dotpos, Glib::ustring::npos);
+ }
+
+ // HACK: replace with something better based on GIO
+ if (!ext.empty() && lossy.find(ext) != lossy.end()) {
+ is_lossy = true;
+ mime_type = "image/jpeg";
+ } else {
+ is_lossy = false;
+ mime_type = "image/png";
+ }
+
doc = sp_document_new(NULL, TRUE, TRUE);
bool saved = sp_document_get_undo_sensitive(doc);
sp_document_set_undo_sensitive(doc, false); // no need to undo in this temporary document
- Inkscape::XML::Node *repr = NULL;
-
double width = gdk_pixbuf_get_width(pb);
double height = gdk_pixbuf_get_height(pb);
gchar const *str = gdk_pixbuf_get_option( pb, "Inkscape::DpiX" );
- if ( str )
- {
+ if ( str ) {
gint dpi = atoi(str);
- if ( dpi > 0 && dpi != 72 )
- {
+ if ( dpi > 0 && dpi != 72 ) {
double scale = 72.0 / (double)dpi;
width *= scale;
}
}
str = gdk_pixbuf_get_option( pb, "Inkscape::DpiY" );
- if ( str )
- {
+ if ( str ) {
gint dpi = atoi(str);
- if ( dpi > 0 && dpi != 72 )
- {
+ if ( dpi > 0 && dpi != 72 ) {
double scale = 72.0 / (double)dpi;
height *= scale;
}
}
+ // Create image node
Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
- // import as <image>
- repr = xml_doc->createElement("svg:image");
-
- // convert filename to uri
- gchar* _uri = g_filename_to_uri(uri, NULL, NULL);
- if(_uri) {
- repr->setAttribute("xlink:href", _uri);
- g_free(_uri);
+ Inkscape::XML::Node *image_node = xml_doc->createElement("svg:image");
+ sp_repr_set_svg_double(image_node, "width", width);
+ sp_repr_set_svg_double(image_node, "height", height);
+
+ if (embed) {
+ // Save pixbuf as JPEG or PNG for embedding
+ gchar *data;
+ gsize length;
+ gdk_pixbuf_save_to_buffer(pb, &data, &length, is_lossy ? "jpeg" : "png", NULL, NULL);
+
+ // Save base64 encoded data in image node
+ // this formula taken from Glib docs
+ guint needed_size = length * 4 / 3 + length * 4 / (3 * 72) + 7;
+ needed_size += 5 + 8 + mime_type.size(); // 5 bytes for data:, 8 for ;base64,
+
+ gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
+ buf_work += g_sprintf(buffer, "data:%s;base64,", mime_type.data());
+
+ gint state = 0, save = 0;
+ gsize written = 0;
+ written += g_base64_encode_step((guchar*) data, length, TRUE, buf_work, &state, &save);
+ written += g_base64_encode_close(TRUE, buf_work + written, &state, &save);
+ buf_work[written] = 0; // null terminate
+
+ image_node->setAttribute("xlink:href", buffer);
+ g_free(buffer);
} else {
- repr->setAttribute("xlink:href", uri);
+ // convert filename to uri
+ gchar* _uri = g_filename_to_uri(uri, NULL, NULL);
+ if(_uri) {
+ image_node->setAttribute("xlink:href", _uri);
+ g_free(_uri);
+ } else {
+ image_node->setAttribute("xlink:href", uri);
+ }
}
- /* impl: doc->base is currently NULL, so we can use uri for href whether it's absolute
- * or relative. The href will get rewritten by rebase_hrefs if by chance uri is relative
- * and doc gets saved to a different directory.
- *
- * We don't bother setting sodipodi:absref, as we assume it's never useful to have
- * sodipodi:absref with the same value as xlink:href, and rebase_hrefs will provide
- * sodipodi:absref values where necessary. */
-
- sp_repr_set_svg_double(repr, "width", width);
- sp_repr_set_svg_double(repr, "height", height);
-
- SP_DOCUMENT_ROOT(doc)->appendChildRepr(repr);
- Inkscape::GC::release(repr);
- gdk_pixbuf_unref(pb);
- //alter the canvas size to fit the image size
+
+ g_object_unref(pb);
+
+ // Add it to the current layer
+ SP_DOCUMENT_ROOT(doc)->appendChildRepr(image_node);
+ Inkscape::GC::release(image_node);
fit_canvas_to_drawing(doc);
// restore undo, as now this document may be shown to the user if a bitmap was opened
sp_document_set_undo_sensitive(doc, saved);
"<inkscape-extension xmlns=\"" INKSCAPE_EXTENSION_URI "\">\n"
"<name>" N_("%s GDK pixbuf Input") "</name>\n"
"<id>org.inkscape.input.gdkpixbuf.%s</id>\n"
+ "<param name=\"link\" gui-text=\""
+ N_("Link image (leave unchecked if in doubt)")
+ "\" type=\"boolean\">false</param>"
"<input>\n"
"<extension>.%s</extension>\n"
"<mimetype>%s</mimetype>\n"
diff --git a/src/interface.cpp b/src/interface.cpp
index 9c187001986ecb616ebaa5f614cd0797777706a5..cb021db18132c14c9812c4c2de3ece980e7588b1 100644 (file)
--- a/src/interface.cpp
+++ b/src/interface.cpp
#include <glib.h>
#include "inkscape-private.h"
+#include "extension/db.h"
#include "extension/effect.h"
+#include "extension/input.h"
#include "widgets/icon.h"
#include "preferences.h"
#include "path-prefix.h"
case PNG_DATA:
case JPEG_DATA:
case IMAGE_DATA: {
- Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc);
- Inkscape::XML::Node *newImage = xml_doc->createElement("svg:image");
- gchar *atom_name = gdk_atom_name(data->type);
-
- // this formula taken from Glib docs
- guint needed_size = data->length * 4 / 3 + data->length * 4 / (3 * 72) + 7;
- needed_size += 5 + 8 + strlen(atom_name); // 5 bytes for data:, 8 for ;base64,
-
- gchar *buffer = (gchar *) g_malloc(needed_size), *buf_work = buffer;
- buf_work += g_sprintf(buffer, "data:%s;base64,", atom_name);
-
- gint state = 0, save = 0;
- g_base64_encode_step(data->data, data->length, TRUE, buf_work, &state, &save);
- g_base64_encode_close(TRUE, buf_work, &state, &save);
-
- newImage->setAttribute("xlink:href", buffer);
- g_free(buffer);
-
- GError *error = NULL;
- GdkPixbufLoader *loader = gdk_pixbuf_loader_new_with_mime_type( gdk_atom_name(data->type), &error );
- if ( loader ) {
- error = NULL;
- if ( gdk_pixbuf_loader_write( loader, data->data, data->length, &error) ) {
- GdkPixbuf *pbuf = gdk_pixbuf_loader_get_pixbuf(loader);
- if ( pbuf ) {
- char tmp[1024];
- int width = gdk_pixbuf_get_width(pbuf);
- int height = gdk_pixbuf_get_height(pbuf);
- snprintf( tmp, sizeof(tmp), "%d", width );
- newImage->setAttribute("width", tmp);
-
- snprintf( tmp, sizeof(tmp), "%d", height );
- newImage->setAttribute("height", tmp);
- }
- }
- }
- g_free(atom_name);
+ const char *mime = (info == JPEG_DATA ? "image/jpeg" : "image/png");
- // Add it to the current layer
- desktop->currentLayer()->appendChildRepr(newImage);
-
- Inkscape::GC::release(newImage);
+ Inkscape::Extension::DB::InputList o;
+ Inkscape::Extension::db.get_input_list(o);
+ Inkscape::Extension::DB::InputList::const_iterator i = o.begin();
+ while (i != o.end() && strcmp( (*i)->get_mimetype(), mime ) != 0) {
+ ++i;
+ }
+ Inkscape::Extension::Extension *ext = *i;
+ bool save = ext->get_param_bool("link");
+ ext->set_param_bool("link", false);
+ ext->set_gui(false);
+
+ gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-dnd-import", NULL );
+ g_file_set_contents(filename, reinterpret_cast<gchar const *>(data->data), data->length, NULL);
+ file_import(doc, filename, ext);
+ g_free(filename);
+
+ ext->set_param_bool("link", save);
+ ext->set_gui(true);
sp_document_done( doc , SP_VERB_NONE,
_("Drop bitmap image"));
break;
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index f213160f4e2598bab6939b5f39fd40f112dbf948..99d83573097e294f88b68c4f1a227297b04c93f0 100644 (file)
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
Glib::RefPtr<Gdk::Pixbuf> img = _clipboard->wait_for_image();
if (!img) return false;
- // Very stupid hack: Write into a file, then import the file into the document.
- // To avoid using tmpfile and POSIX file handles, make the filename based on current time.
- // This wasn't my idea, I just copied this from selection-chemistry.cpp
- // and just can't think of something saner at the moment. Pasting more than
- // one image per second will overwrite the image.
- // However, I don't think anyone is able to copy a _different_ image into inkscape
- // in 1 second.
- time_t rawtime;
- char image_filename[128];
-
- time(&rawtime);
- strftime(image_filename, 128, "inkscape_pasted_image_%Y%m%d_%H%M%S.png", localtime( &rawtime ));
- /// @todo Check whether the encoding is correct here
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
- std::string save_folder = Glib::filename_from_utf8(prefs->getString("/dialogs/save_as/path"));
-
- gchar *image_path = g_build_filename(save_folder.data(), image_filename, NULL);
- img->save(image_path, "png");
- file_import(doc, image_path, NULL);
- g_free(image_path);
+ // AARGH stupid
+ Inkscape::Extension::DB::InputList o;
+ Inkscape::Extension::db.get_input_list(o);
+ Inkscape::Extension::DB::InputList::const_iterator i = o.begin();
+ while (i != o.end() && strcmp( (*i)->get_mimetype(), "image/png" ) != 0) {
+ ++i;
+ }
+ Inkscape::Extension::Extension *png = *i;
+ bool save = png->get_param_bool("link");
+ png->set_param_bool("link", false);
+ png->set_gui(false);
+
+ gchar *filename = g_build_filename( g_get_tmp_dir(), "inkscape-clipboard-import", NULL );
+ img->save(filename, "png");
+ file_import(doc, filename, png);
+ g_free(filename);
+
+ png->set_param_bool("link", save);
+ png->set_gui(true);
return true;
}