Code

Fix bug #1077600 -> correct mirroring and no drifting of origin
[inkscape.git] / src / path-chemistry.cpp
index 663cd6da4031b2542dac0399a274f1f3beabe924..9a8eb3e9237b16ed1318d8aa5cca929b9ce2270b 100644 (file)
@@ -19,6 +19,7 @@
 #include "xml/repr.h"
 #include "svg/svg.h"
 #include "display/curve.h"
+#include <glib/gmem.h>
 #include <glibmm/i18n.h>
 #include "sp-path.h"
 #include "sp-text.h"
@@ -27,6 +28,7 @@
 #include "text-editing.h"
 #include "style.h"
 #include "inkscape.h"
+#include "desktop.h"
 #include "document.h"
 #include "message-stack.h"
 #include "selection.h"
@@ -48,18 +50,18 @@ sp_selected_path_combine(void)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
     GSList *items = (GSList *) selection->itemList();
 
     if (g_slist_length(items) < 2) {
-        SP_DT_MSGSTACK(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>at least two objects</b> to combine."));
+        sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>at least two objects</b> to combine."));
         return;
     }
 
     for (GSList *i = items; i != NULL; i = i->next) {
         SPItem *item = (SPItem *) i->data;
         if (!SP_IS_SHAPE(item) && !SP_IS_TEXT(item)) {
-            SP_DT_MSGSTACK(desktop)->flash(Inkscape::WARNING_MESSAGE, _("At least one of the objects is <b>not a path</b>, cannot combine."));
+            sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("At least one of the objects is <b>not a path</b>, cannot combine."));
             return;
         }
     }
@@ -67,7 +69,7 @@ sp_selected_path_combine(void)
     Inkscape::XML::Node *parent = SP_OBJECT_REPR((SPItem *) items->data)->parent();
     for (GSList *i = items; i != NULL; i = i->next) {
         if ( SP_OBJECT_REPR((SPItem *) i->data)->parent() != parent ) {
-            SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, _("You cannot combine objects from <b>different groups</b> or <b>layers</b>."));
+            sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("You cannot combine objects from <b>different groups</b> or <b>layers</b>."));
             return;
         }
     }
@@ -95,10 +97,10 @@ sp_selected_path_combine(void)
         SPPath *path = (SPPath *) i->data;
         SPCurve *c = sp_shape_get_curve(SP_SHAPE(path));
 
-        NArtBpath *abp = nr_artpath_affine(c->bpath, SP_ITEM(path)->transform);
+        NArtBpath *abp = nr_artpath_affine(SP_CURVE_BPATH(c), SP_ITEM(path)->transform);
         sp_curve_unref(c);
         gchar *str = sp_svg_write_path(abp);
-        nr_free(abp);
+        g_free(abp);
 
         dstring = g_string_append(dstring, str);
         g_free(str);
@@ -117,7 +119,8 @@ sp_selected_path_combine(void)
 
     g_slist_free(items);
 
-    Inkscape::XML::Node *repr = sp_repr_new("svg:path");
+    Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
 
     // restore id
     repr->setAttribute("id", id);
@@ -134,7 +137,8 @@ sp_selected_path_combine(void)
     // move to the position of the topmost, reduced by the number of deleted items
     repr->setPosition(topmost > 0 ? topmost + 1 : 0);
 
-    sp_document_done(SP_DT_DOCUMENT(desktop));
+    sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_COMBINE, 
+                         _("Combine"));
 
     selection->set(repr);
 
@@ -146,10 +150,10 @@ sp_selected_path_break_apart(void)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
-        SP_DT_MSGSTACK(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to break apart."));
+        sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to break apart."));
         return;
     }
 
@@ -178,7 +182,7 @@ sp_selected_path_break_apart(void)
 
         gchar *style = g_strdup(SP_OBJECT(item)->repr->attribute("style"));
 
-        NArtBpath *abp = nr_artpath_affine(curve->bpath, (SP_ITEM(path))->transform);
+        NArtBpath *abp = nr_artpath_affine(SP_CURVE_BPATH(curve), (SP_ITEM(path))->transform);
 
         sp_curve_unref(curve);
 
@@ -192,13 +196,14 @@ sp_selected_path_break_apart(void)
 
         sp_curve_unref(curve);
 
-        for (GSList *l = g_slist_reverse(list); l != NULL; l = l->next) {
+        GSList *reprs = NULL;
+        for (GSList *l = list; l != NULL; l = l->next) {
             curve = (SPCurve *) l->data;
 
-            Inkscape::XML::Node *repr = sp_repr_new("svg:path");
+            Inkscape::XML::Node *repr = parent->document()->createElement("svg:path");
             repr->setAttribute("style", style);
 
-            gchar *str = sp_svg_write_path(curve->bpath);
+            gchar *str = sp_svg_write_path(SP_CURVE_BPATH(curve));
             repr->setAttribute("d", str);
             g_free(str);
 
@@ -212,20 +217,24 @@ sp_selected_path_break_apart(void)
             if (l == list)
                 repr->setAttribute("id", id);
 
-            selection->add(repr);
+            reprs = g_slist_prepend (reprs, repr);
 
             Inkscape::GC::release(repr);
         }
 
+        selection->setReprList(reprs);
+
+        g_slist_free(reprs);
         g_slist_free(list);
         g_free(style);
 
     }
 
     if (did) {
-        sp_document_done(SP_DT_DOCUMENT(desktop));
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_BREAK_APART, 
+                         _("Break apart"));
     } else {
-        SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to break apart in the selection."));
+        sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No path(s)</b> to break apart in the selection."));
         return;
     }
 }
@@ -242,11 +251,11 @@ sp_selected_path_to_curves0(gboolean interactive, guint32 text_grouping_policy)
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
 
     if (selection->isEmpty()) {
         if (interactive)
-            SP_DT_MSGSTACK(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to path."));
+            sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>object(s)</b> to convert to path."));
         return;
     }
 
@@ -289,9 +298,10 @@ sp_selected_path_to_curves0(gboolean interactive, guint32 text_grouping_policy)
 
     if (interactive) {
         if (did) {
-            sp_document_done(SP_DT_DOCUMENT(desktop));
+            sp_document_done(sp_desktop_document(desktop), SP_VERB_OBJECT_TO_CURVE, 
+                             _("Object to path"));
         } else {
-            SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No objects</b> to convert to path in the selection."));
+            sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No objects</b> to convert to path in the selection."));
             return;
         }
     }
@@ -313,7 +323,8 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 text_grouping_policy)
     if (!curve)
         return NULL;
 
-    Inkscape::XML::Node *repr = sp_repr_new("svg:path");
+    Inkscape::XML::Document *xml_doc = SP_OBJECT_REPR(item)->document();
+    Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
     /* Transformation */
     repr->setAttribute("transform", SP_OBJECT_REPR(item)->attribute("transform"));
     /* Style */
@@ -321,12 +332,23 @@ sp_selected_item_to_curved_repr(SPItem *item, guint32 text_grouping_policy)
                                                  SP_OBJECT_STYLE(SP_OBJECT_PARENT(item)));
     repr->setAttribute("style", style_str);
     g_free(style_str);
+
+    /* Mask */
+    gchar *mask_str = (gchar *) SP_OBJECT_REPR(item)->attribute("mask");
+    if ( mask_str )
+        repr->setAttribute("mask", mask_str);
+
+    /* Clip path */
+    gchar *clip_path_str = (gchar *) SP_OBJECT_REPR(item)->attribute("clip-path");
+    if ( clip_path_str )
+        repr->setAttribute("clip-path", clip_path_str);
+
     /* Rotation center */
     sp_repr_set_attr(repr, "inkscape:transform-center-x", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-x"));
     sp_repr_set_attr(repr, "inkscape:transform-center-y", SP_OBJECT_REPR(item)->attribute("inkscape:transform-center-y"));
 
     /* Definition */
-    gchar *def_str = sp_svg_write_path(curve->bpath);
+    gchar *def_str = sp_svg_write_path(SP_CURVE_BPATH(curve));
     repr->setAttribute("d", def_str);
     g_free(def_str);
     sp_curve_unref(curve);
@@ -338,11 +360,11 @@ sp_selected_path_reverse()
 {
     SPDesktop *desktop = SP_ACTIVE_DESKTOP;
 
-    Inkscape::Selection *selection = SP_DT_SELECTION(desktop);
+    Inkscape::Selection *selection = sp_desktop_selection(desktop);
     GSList *items = (GSList *) selection->itemList();
 
     if (!items) {
-        SP_DT_MSGSTACK(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to reverse."));
+        sp_desktop_message_stack(desktop)->flash(Inkscape::WARNING_MESSAGE, _("Select <b>path(s)</b> to reverse."));
         return;
     }
 
@@ -358,7 +380,7 @@ sp_selected_path_reverse()
 
         SPCurve *rcurve = sp_curve_reverse(shape->curve);
 
-        gchar *str = sp_svg_write_path(rcurve->bpath);
+        gchar *str = sp_svg_write_path(SP_CURVE_BPATH(rcurve));
         SP_OBJECT_REPR(shape)->setAttribute("d", str);
         g_free(str);
 
@@ -366,9 +388,10 @@ sp_selected_path_reverse()
     }
 
     if (did) {
-        sp_document_done(SP_DT_DOCUMENT(desktop));
+        sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_REVERSE,
+                         _("Reverse path"));
     } else {
-        SP_DT_MSGSTACK(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No paths</b> to reverse in the selection."));
+        sp_desktop_message_stack(desktop)->flash(Inkscape::ERROR_MESSAGE, _("<b>No paths</b> to reverse in the selection."));
     }
 }