summaryrefslogtreecommitdiffstats
path: root/src/trace/trace.cpp
diff options
context:
space:
mode:
authorMenTaLguY <mental@rydia.net>2006-01-16 02:36:01 +0000
committermental <mental@users.sourceforge.net>2006-01-16 02:36:01 +0000
commit179fa413b047bede6e32109e2ce82437c5fb8d34 (patch)
treea5a6ac2c1708bd02288fbd8edb2ff500ff2e0916 /src/trace/trace.cpp
downloadinkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.tar.gz
inkscape-179fa413b047bede6e32109e2ce82437c5fb8d34.zip
moving trunk for module inkscape
(bzr r1)
Diffstat (limited to 'src/trace/trace.cpp')
-rw-r--r--src/trace/trace.cpp322
1 files changed, 322 insertions, 0 deletions
diff --git a/src/trace/trace.cpp b/src/trace/trace.cpp
new file mode 100644
index 000000000..5431b4416
--- /dev/null
+++ b/src/trace/trace.cpp
@@ -0,0 +1,322 @@
+/*
+ * A generic interface for plugging different
+ * autotracers into Inkscape.
+ *
+ * Authors:
+ * Bob Jamison <rjamison@titan.com>
+ *
+ * Copyright (C) 2004 Bob Jamison
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+
+
+#include "trace/potrace/inkscape-potrace.h"
+
+#include <inkscape.h>
+#include <desktop-handles.h>
+#include <document.h>
+#include "message-stack.h"
+#include <glibmm/i18n.h>
+#include <selection.h>
+#include <xml/repr.h>
+#include "sp-item.h"
+#include "sp-image.h"
+
+namespace Inkscape {
+
+namespace Trace {
+
+/**
+ *
+ */
+SPImage *
+Tracer::getSelectedSPImage()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop)
+ {
+ g_warning("Trace: No active desktop\n");
+ return NULL;
+ }
+
+ Inkscape::Selection *sel = SP_DT_SELECTION(desktop);
+ if (!sel)
+ {
+ char *msg = _("Select an <b>image</b> to trace");
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ return NULL;
+ }
+
+ SPItem *item = sel->singleItem();
+ if (!item)
+ {
+ char *msg = _("Select an <b>image</b> to trace"); //same as above
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ return NULL;
+ }
+
+ if (!SP_IS_IMAGE(item))
+ {
+ char *msg = _("Select an <b>image</b> to trace");
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ return NULL;
+ }
+
+ selectedItem = item;
+
+ SPImage *img = SP_IMAGE(item);
+
+ return img;
+
+}
+
+
+
+/**
+ *
+ */
+GdkPixbuf *
+Tracer::getSelectedImage()
+{
+
+ SPImage *img = getSelectedSPImage();
+ if (!img)
+ return NULL;
+
+ GdkPixbuf *pixbuf = img->pixbuf;
+
+ return pixbuf;
+
+}
+
+
+
+//#########################################################################
+//# T R A C E
+//#########################################################################
+
+
+/**
+ * Threaded method that does single bitmap--->path conversion
+ */
+void Tracer::traceThread()
+{
+ //## Remember. NEVER leave this method without setting
+ //## engine back to NULL
+
+ //## Prepare our kill flag. We will watch this later to
+ //## see if the main thread wants us to stop
+ keepGoing = true;
+
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (!desktop)
+ {
+ g_warning("Trace: No active desktop\n");
+ return;
+ }
+
+ Inkscape::Selection *selection = SP_DT_SELECTION (desktop);
+
+ if (!SP_ACTIVE_DOCUMENT)
+ {
+ char *msg = _("Trace: No active document");
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ engine = NULL;
+ return;
+ }
+ SPDocument *doc = SP_ACTIVE_DOCUMENT;
+ sp_document_ensure_up_to_date(doc);
+
+
+ SPImage *img = getSelectedSPImage();
+ if (!img || !selectedItem)
+ {
+ engine = NULL;
+ return;
+ }
+
+ GdkPixbuf *pixbuf = img->pixbuf;
+
+ if (!pixbuf)
+ {
+ char *msg = _("Trace: Image has no bitmap data");
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, msg);
+ //g_warning(msg);
+ engine = NULL;
+ return;
+ }
+
+ int nrPaths;
+ TracingEngineResult *results = engine->trace(pixbuf, &nrPaths);
+ //printf("nrPaths:%d\n", nrPaths);
+
+ //### Check if we should stop
+ if (!keepGoing || !results || nrPaths<1)
+ {
+ engine = NULL;
+ return;
+ }
+
+ //### Get pointers to the <image> and its parent
+ Inkscape::XML::Node *imgRepr = SP_OBJECT(img)->repr;
+ Inkscape::XML::Node *par = sp_repr_parent(imgRepr);
+
+ //### Get some information for the new transform()
+ double x = 0.0;
+ double y = 0.0;
+ double width = 0.0;
+ double height = 0.0;
+ double dval = 0.0;
+
+ if (sp_repr_get_double(imgRepr, "x", &dval))
+ x = dval;
+ if (sp_repr_get_double(imgRepr, "y", &dval))
+ y = dval;
+
+ if (sp_repr_get_double(imgRepr, "width", &dval))
+ width = dval;
+ if (sp_repr_get_double(imgRepr, "height", &dval))
+ height = dval;
+
+ NR::Matrix trans(NR::translate(x, y));
+
+ double iwidth = (double)gdk_pixbuf_get_width(pixbuf);
+ double iheight = (double)gdk_pixbuf_get_height(pixbuf);
+
+ double iwscale = width / iwidth;
+ double ihscale = height / iheight;
+
+ NR::Matrix scal(NR::scale(iwscale, ihscale));
+
+ //# Convolve scale, translation, and the original transform
+ NR::Matrix tf(scal);
+ tf *= trans;
+ tf *= selectedItem->transform;
+
+
+ //#OK. Now let's start making new nodes
+
+ Inkscape::XML::Node *groupRepr = NULL;
+
+ //# if more than 1, make a <g>roup of <path>s
+ if (nrPaths > 1)
+ {
+ groupRepr = sp_repr_new("svg:g");
+ par->addChild(groupRepr, imgRepr);
+ }
+
+ long totalNodeCount = 0L;
+
+ for (TracingEngineResult *result=results ;
+ result ; result=result->next)
+ {
+ totalNodeCount += result->getNodeCount();
+
+ Inkscape::XML::Node *pathRepr = sp_repr_new("svg:path");
+ pathRepr->setAttribute("style", result->getStyle());
+ pathRepr->setAttribute("d", result->getPathData());
+
+ if (nrPaths > 1)
+ groupRepr->addChild(pathRepr, NULL);
+ else
+ par->addChild(pathRepr, imgRepr);
+
+ //### Apply the transform from the image to the new shape
+ SPObject *reprobj = doc->getObjectByRepr(pathRepr);
+ if (reprobj)
+ {
+ SPItem *newItem = SP_ITEM(reprobj);
+ sp_item_write_transform(newItem, pathRepr, tf, NULL);
+ }
+ if (nrPaths == 1)
+ {
+ selection->clear();
+ selection->add(pathRepr);
+ }
+ Inkscape::GC::release(pathRepr);
+ }
+
+
+ delete results;
+
+ // If we have a group, then focus on, then forget it
+ if (nrPaths > 1)
+ {
+ selection->clear();
+ selection->add(groupRepr);
+ Inkscape::GC::release(groupRepr);
+ }
+
+ //## inform the document, so we can undo
+ sp_document_done(doc);
+
+ engine = NULL;
+
+ char *msg = g_strdup_printf(_("Trace: Done. %ld nodes created"), totalNodeCount);
+ SP_DT_MSGSTACK(desktop)->flash(Inkscape::NORMAL_MESSAGE, msg);
+ g_free(msg);
+
+}
+
+/**
+ * Main tracing method
+ */
+void Tracer::trace(TracingEngine *theEngine)
+{
+ //Check if we are already running
+ if (engine)
+ return;
+
+ engine = theEngine;
+
+#if HAVE_THREADS
+ //Ensure that thread support is running
+ if (!Glib::thread_supported())
+ Glib::thread_init();
+
+ //Create our thread and run it
+ Glib::Thread::create(
+ sigc::mem_fun(*this, &Tracer::traceThread), false);
+#else
+ traceThread();
+#endif
+
+}
+
+
+
+
+
+/**
+ * Abort the thread that is executing trace()
+ */
+void Tracer::abort()
+{
+
+ //## Inform Trace's working thread
+ keepGoing = false;
+
+ if (engine)
+ {
+ engine->abort();
+ }
+
+}
+
+
+
+} // namespace Trace
+
+} // namespace Inkscape
+
+
+//#########################################################################
+//# E N D O F F I L E
+//#########################################################################
+