diff --git a/src/extension/internal/bitmap/imagemagick.cpp b/src/extension/internal/bitmap/imagemagick.cpp
index 83650aaa788b84c2640544e0d0b0677974a0ddb5..e907612fdaa093098e27d6f361e7976d7aa7a26e 100644 (file)
* Released under GNU GPL, read the file 'COPYING' for more information
*/
+#include <libintl.h>
+
#include <gtkmm/box.h>
#include <gtkmm/adjustment.h>
#include <gtkmm/spinbutton.h>
+#include <gtkmm.h>
#include <glib/gstdio.h>
namespace Internal {
namespace Bitmap {
-bool
-ImageMagick::load(Inkscape::Extension::Extension *module)
+class ImageMagickDocCache: public Inkscape::Extension::Implementation::ImplementationDocumentCache {
+ friend class ImageMagick;
+private:
+ void readImage(char const *xlink, Magick::Image *image);
+protected:
+ Inkscape::XML::Node** _nodes;
+
+ Magick::Image** _images;
+ int _imageCount;
+ char** _caches;
+ unsigned* _cacheLengths;
+
+ const char** _originals;
+public:
+ ImageMagickDocCache(Inkscape::UI::View::View * view);
+ ~ImageMagickDocCache ( );
+};
+
+ImageMagickDocCache::ImageMagickDocCache(Inkscape::UI::View::View * view) :
+ Inkscape::Extension::Implementation::ImplementationDocumentCache(view),
+ _nodes(NULL),
+ _images(NULL),
+ _imageCount(0),
+ _caches(NULL),
+ _cacheLengths(NULL),
+ _originals(NULL)
{
- _loaded = FALSE;
- return TRUE;
-}
+ SPDesktop *desktop = (SPDesktop*)view;
+ const GSList *selectedReprList = desktop->selection->reprList();
+ int selectCount = g_slist_length((GSList *)selectedReprList);
+
+ // Init the data-holders
+ _nodes = new Inkscape::XML::Node*[selectCount];
+ _originals = new const char*[selectCount];
+ _caches = new char*[selectCount];
+ _cacheLengths = new unsigned int[selectCount];
+ _images = new Magick::Image*[selectCount];
+ _imageCount = 0;
+
+ // Loop through selected nodes
+ for (; selectedReprList != NULL; selectedReprList = g_slist_next(selectedReprList))
+ {
+ Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(selectedReprList->data);
+ if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image"))
+ {
+ _nodes[_imageCount] = node;
+ char const *xlink = node->attribute("xlink:href");
-void
-ImageMagick::commitDocument(void) {
- _loaded = FALSE;
-}
+ _originals[_imageCount] = xlink;
+ _caches[_imageCount] = "";
+ _cacheLengths[_imageCount] = 0;
+ _images[_imageCount] = new Magick::Image();
+ readImage(xlink, _images[_imageCount]);
-void
-ImageMagick::cancelDocument(void) {
- for (int i = 0; i < _imageCount; i++) {
- _nodes[i]->setAttribute("xlink:href", _originals[i], true);
+ _imageCount++;
+ }
}
-
- _loaded = FALSE;
+}
+
+ImageMagickDocCache::~ImageMagickDocCache ( ) {
+ if (_nodes)
+ delete _nodes;
+ if (_originals)
+ delete _originals;
+ if (_caches)
+ delete _caches;
+ if (_cacheLengths)
+ delete _cacheLengths;
+ if (_images)
+ delete _images;
+
+ return;
}
void
-ImageMagick::readImage(const char *xlink, Magick::Image *image)
+ImageMagickDocCache::readImage(const char *xlink, Magick::Image *image)
{
- // Find if the xlink:href is base64 data, i.e. if the image is embedded
- char *search = strndup(xlink, 30);
+ // Find if the xlink:href is base64 data, i.e. if the image is embedded
+ char *search = (char *) g_strndup(xlink, 30);
if (strstr(search, "base64") != (char*)NULL) {
// 7 = strlen("base64") + strlen(",")
- char* pureBase64 = strstr(xlink, "base64") + 7;
+ const char* pureBase64 = strstr(xlink, "base64") + 7;
Magick::Blob blob;
blob.base64(pureBase64);
image->read(blob);
}
else {
- image->read(xlink);
+ const gchar *path = xlink;
+ if (strncmp (xlink,"file:", 5) == 0) {
+ path = g_filename_from_uri(xlink, NULL, NULL);
+ }
+
+ try {
+ image->read(path);
+ } catch (...) {}
}
+ g_free(search);
+}
+
+bool
+ImageMagick::load(Inkscape::Extension::Extension */*module*/)
+{
+ return true;
+}
+
+Inkscape::Extension::Implementation::ImplementationDocumentCache *
+ImageMagick::newDocCache (Inkscape::Extension::Extension * /*ext*/, Inkscape::UI::View::View * view) {
+ return new ImageMagickDocCache(view);
}
void
-ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document)
+ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::View *document, Inkscape::Extension::Implementation::ImplementationDocumentCache * docCache)
{
refreshParameters(module);
-
- if (!_loaded)
- {
- SPDesktop *desktop = (SPDesktop*)document;
- const GSList *selectedReprList = desktop->selection->reprList();
- int selectCount = g_slist_length((GSList *)selectedReprList);
-
- // Init the data-holders
- _nodes = new Inkscape::XML::Node*[selectCount];
- _originals = new const char*[selectCount];
- _images = new Magick::Image[selectCount];
- _imageCount = 0;
-
- // Loop through selected nodes
- for (; selectedReprList != NULL; selectedReprList = g_slist_next(selectedReprList))
- {
- Inkscape::XML::Node *node = reinterpret_cast<Inkscape::XML::Node *>(selectedReprList->data);
- if (!strcmp(node->name(), "image") || !strcmp(node->name(), "svg:image"))
- {
- _nodes[_imageCount] = node;
- char const *xlink = node->attribute("xlink:href");
-
- _originals[_imageCount] = xlink;
-
- readImage(xlink, &_images[_imageCount]);
-
- _imageCount++;
- }
- }
-
- _loaded = 1;
+
+ if (docCache == NULL) { // should never happen
+ docCache = newDocCache(module, document);
+ }
+ ImageMagickDocCache * dc = dynamic_cast<ImageMagickDocCache *>(docCache);
+ if (dc == NULL) { // should really never happen
+ printf("AHHHHHHHHH!!!!!");
+ exit(1);
}
- for (int i = 0; i < _imageCount; i++)
+ for (int i = 0; i < dc->_imageCount; i++)
{
try
{
- Magick::Image effectedImage = _images[i];
+ Magick::Image effectedImage = *dc->_images[i]; // make a copy
applyEffect(&effectedImage);
- Magick::Blob blob;
- effectedImage.write(&blob);
-
- std::string raw_string = blob.base64();
- const int raw_len = raw_string.length();
- const char *raw = raw_string.c_str();
- const char *raw_i = raw;
-
- int formatted_len = (int)(raw_len / 76.0 * 78.0) + 100;
- char *formatted = new char[formatted_len];
- char *formatted_i = formatted;
- // data:image/png;base64,
- formatted_i = stpcpy(formatted_i, "data:image/");
- formatted_i = stpcpy(formatted_i, effectedImage.magick().c_str());
- formatted_i = stpcpy(formatted_i, ";base64, \n");
- while (strnlen(raw_i, 80) > 76)
- {
- formatted_i = stpncpy(formatted_i, raw_i, 76);
- formatted_i = stpcpy(formatted_i, "\n");
- raw_i += 76;
- }
- if (strlen(raw_i) > 0)
- {
- formatted_i = stpcpy(formatted_i, raw_i);
- formatted_i = stpcpy(formatted_i, "\n");
- }
-
- formatted_i = stpcpy(formatted_i, "\0");
-
- _nodes[i]->setAttribute("xlink:href", formatted, true);
+ Magick::Blob *blob = new Magick::Blob();
+ effectedImage.write(blob);
+
+ std::string raw_string = blob->base64();
+ const int raw_len = raw_string.length();
+ const char *raw_i = raw_string.c_str();
+
+ unsigned new_len = (int)(raw_len * (77.0 / 76.0) + 100);
+ if (new_len > dc->_cacheLengths[i]) {
+ dc->_cacheLengths[i] = (int)(new_len * 1.2);
+ dc->_caches[i] = new char[dc->_cacheLengths[i]];
+ }
+ char *formatted_i = dc->_caches[i];
+ const char *src;
+
+ for (src = "data:image/"; *src; )
+ *formatted_i++ = *src++;
+ for (src = effectedImage.magick().c_str(); *src ; )
+ *formatted_i++ = *src++;
+ for (src = ";base64, \n" ; *src; )
+ *formatted_i++ = *src++;
+
+ int col = 0;
+ while (*raw_i) {
+ *formatted_i++ = *raw_i++;
+ if (col++ > 76) {
+ *formatted_i++ = '\n';
+ col = 0;
+ }
+ }
+ if (col) {
+ *formatted_i++ = '\n';
+ }
+ *formatted_i = '\0';
+
+ dc->_nodes[i]->setAttribute("xlink:href", dc->_caches[i], true);
+ dc->_nodes[i]->setAttribute("sodipodi:absref", NULL, true);
}
catch (Magick::Exception &error_) {
printf("Caught exception: %s \n", error_.what());
}
+
+ //while(Gtk::Main::events_pending()) {
+ // Gtk::Main::iteration();
+ //}
}
}
@@ -156,7 +219,7 @@ ImageMagick::effect (Inkscape::Extension::Effect *module, Inkscape::UI::View::Vi
Uses AutoGUI for creating the GUI.
*/
Gtk::Widget *
-ImageMagick::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view, sigc::signal<void> * changeSignal)
+ImageMagick::prefs_effect(Inkscape::Extension::Effect *module, Inkscape::UI::View::View * view, sigc::signal<void> * changeSignal, Inkscape::Extension::Implementation::ImplementationDocumentCache * /*docCache*/)
{
SPDocument * current_document = view->doc();