Code

fix pasting style after copying a text span
[inkscape.git] / src / selection-chemistry.cpp
index bd59c0aa48ae36da06ee3b91ed08db4b77d12423..badf27ecb45caa4d93541f5e806a371f43b66fd9 100644 (file)
@@ -82,6 +82,7 @@
 #include "libnr/nr-convert2geom.h"
 #include "display/curve.h"
 #include "display/canvas-bpath.h"
+#include "inkscape-private.h"
 
 // For clippath editing
 #include "tools-switch.h"
@@ -91,8 +92,8 @@
 
 #include "ui/clipboard.h"
 
-using NR::X;
-using NR::Y;
+using Geom::X;
+using Geom::Y;
 
 /* The clipboard handling is in ui/clipboard.cpp now. There are some legacy functions left here,
 because the layer manipulation code uses them. It should be rewritten specifically
@@ -102,7 +103,7 @@ for that purpose. */
  * Copies repr and its inherited css style elements, along with the accumulated transform 'full_t',
  * then prepends the copy to 'clip'.
  */
-void sp_selection_copy_one (Inkscape::XML::Node *repr, NR::Matrix full_t, GSList **clip, Inkscape::XML::Document* xml_doc)
+void sp_selection_copy_one (Inkscape::XML::Node *repr, Geom::Matrix full_t, GSList **clip, Inkscape::XML::Document* xml_doc)
 {
     Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
 
@@ -147,8 +148,8 @@ GSList *sp_selection_paste_impl (SPDocument *doc, SPObject *parent, GSList **cli
         Inkscape::XML::Node *copy = repr->duplicate(xml_doc);
 
         // premultiply the item transform by the accumulated parent transform in the paste layer
-        NR::Matrix local (sp_item_i2doc_affine(SP_ITEM(parent)));
-        if (!local.test_identity()) {
+        Geom::Matrix local (sp_item_i2doc_affine(SP_ITEM(parent)));
+        if (!local.isIdentity()) {
             gchar const *t_str = copy->attribute("transform");
             Geom::Matrix item_t (Geom::identity());
             if (t_str)
@@ -593,6 +594,36 @@ void sp_selection_ungroup(SPDesktop *desktop)
                      _("Ungroup"));
 }
 
+/** Replace all groups in the list with their member objects, recursively; returns a new list, frees old */
+GSList *
+sp_degroup_list (GSList *items)
+{
+    GSList *out = NULL;
+    bool has_groups = false;
+    for (GSList *item = items; item; item = item->next) {
+        if (!SP_IS_GROUP(item->data)) {
+            out = g_slist_prepend(out, item->data);
+        } else {
+            has_groups = true;
+            GSList *members = sp_item_group_item_list (SP_GROUP(item->data));
+            for (GSList *member = members; member; member = member->next) {
+                out = g_slist_prepend(out, member->data);
+            }
+            g_slist_free (members);
+        }
+    }
+    out = g_slist_reverse (out);
+    g_slist_free (items);
+
+    if (has_groups) { // recurse if we unwrapped a group - it may have contained others
+        out = sp_degroup_list (out);
+    }
+
+    return out;
+}
+
+/** If items in the list have a common parent, return it, otherwise return NULL */
 static SPGroup *
 sp_item_list_common_parent_group(GSList const *items)
 {
@@ -1216,9 +1247,9 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
             sp_object_read_attr (SP_OBJECT (item), "transform");
 
             // calculate the matrix we need to apply to the clone to cancel its induced transform from its original
-            Geom::Matrix parent_transform = sp_item_i2root_affine(SP_ITEM(SP_OBJECT_PARENT (item)));
-            Geom::Matrix t = parent_transform * matrix_to_desktop (matrix_from_desktop (affine, item), item) * parent_transform.inverse();
-            Geom::Matrix t_inv =parent_transform * matrix_to_desktop (matrix_from_desktop (affine.inverse(), item), item) * parent_transform.inverse();
+            Geom::Matrix parent2dt = sp_item_i2d_affine(SP_ITEM(SP_OBJECT_PARENT (item)));
+            Geom::Matrix t = parent2dt * affine * parent2dt.inverse();
+            Geom::Matrix t_inv = t.inverse();
             Geom::Matrix result = t_inv * item->transform * t;
 
             if ((prefs_parallel || prefs_unmoved) && affine.isTranslation()) {
@@ -1234,7 +1265,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
 
                 } else if (prefs_unmoved) {
                     //if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
-                    //    clone_move = NR::identity();
+                    //    clone_move = Geom::identity();
                     Geom::Matrix move = result * clone_move;
                     sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &t);
                 }
@@ -1296,7 +1327,7 @@ sp_selection_scale_absolute(Inkscape::Selection *selection,
                             y1 - y0);
     Geom::Scale const scale( newSize * Geom::Scale(bbox->dimensions()).inverse() );
     Geom::Translate const o2n(x0, y0);
-    NR::Matrix const final( p2o * scale * o2n );
+    Geom::Matrix const final( p2o * scale * o2n );
 
     sp_selection_apply_affine(selection, final);
 }
@@ -1314,8 +1345,8 @@ void sp_selection_scale_relative(Inkscape::Selection *selection, Geom::Point con
     }
 
     // FIXME: ARBITRARY LIMIT: don't try to scale above 1 Mpx, it won't display properly and will crash sooner or later anyway
-    if ( bbox->dimensions()[NR::X] * scale[Geom::X] > 1e6  ||
-         bbox->dimensions()[NR::Y] * scale[Geom::Y] > 1e6 )
+    if ( bbox->dimensions()[Geom::X] * scale[Geom::X] > 1e6  ||
+         bbox->dimensions()[Geom::Y] * scale[Geom::Y] > 1e6 )
     {
         return;
     }
@@ -1350,12 +1381,12 @@ sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &al
 
 void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move)
 {
-    sp_selection_apply_affine(selection, NR::Matrix(Geom::Translate(move)));
+    sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)));
 }
 
 void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy)
 {
-    sp_selection_apply_affine(selection, NR::Matrix(Geom::Translate(dx, dy)));
+    sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(dx, dy)));
 }
 
 /**
@@ -1369,7 +1400,7 @@ void sp_selection_rotate_90(SPDesktop *desktop, bool ccw)
         return;
 
     GSList const *l = selection->itemList();
-    Geom::Rotate const rot_90(NR::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw
+    Geom::Rotate const rot_90(Geom::Point(0, ccw ? 1 : -1)); // pos. or neg. rotation, depending on the value of ccw
     for (GSList const *l2 = l ; l2 != NULL ; l2 = l2->next) {
         SPItem *item = SP_ITEM(l2->data);
         sp_item_rotate_rel(item, rot_90);
@@ -1701,7 +1732,7 @@ void sp_selection_edit_clip_or_mask(SPDesktop * dt, bool clip)
                             tools_switch(dt, TOOLS_NODES);
                         }
 
-                        ShapeEditor * shape_editor = SP_NODE_CONTEXT( dt->event_context )->shape_editor;
+                        ShapeEditor * shape_editor = dt->event_context->shape_editor;
                         // TODO: should we set the item for nodepath or knotholder or both? seems to work with both.
                         shape_editor->set_item(SP_ITEM(child), SH_NODEPATH);
                         shape_editor->set_item(SP_ITEM(child), SH_KNOTHOLDER);
@@ -2106,7 +2137,7 @@ void sp_selection_to_marker(SPDesktop *desktop, bool apply)
     // bottommost object, after sorting
     SPObject *parent = SP_OBJECT_PARENT (items->data);
 
-    Geom::Matrix parent_transform (sp_item_i2root_affine(SP_ITEM(parent)));
+    Geom::Matrix parent_transform (sp_item_i2doc_affine(SP_ITEM(parent)));
 
     // remember the position of the first item
     gint pos = SP_OBJECT_REPR (items->data)->position();
@@ -2218,7 +2249,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
     }
 
     // calculate the transform to be applied to objects to move them to 0,0
-    Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - (r->min() + Geom::Point (0, r->dimensions()[NR::Y]));
+    Geom::Point move_p = Geom::Point(0, sp_document_height(doc)) - (r->min() + Geom::Point (0, r->dimensions()[Geom::Y]));
     move_p[Geom::Y] = -move_p[Geom::Y];
     Geom::Matrix move = Geom::Matrix (Geom::Translate (move_p));
 
@@ -2229,7 +2260,7 @@ sp_selection_tile(SPDesktop *desktop, bool apply)
     // bottommost object, after sorting
     SPObject *parent = SP_OBJECT_PARENT (items->data);
 
-    Geom::Matrix parent_transform (sp_item_i2root_affine(SP_ITEM(parent)));
+    Geom::Matrix parent_transform (sp_item_i2doc_affine(SP_ITEM(parent)));
 
     // remember the position of the first item
     gint pos = SP_OBJECT_REPR (items->data)->position();
@@ -2486,8 +2517,16 @@ sp_selection_create_bitmap_copy (SPDesktop *desktop)
     // Imagemagick is known not to handle spaces in filenames, so we replace anything but letters,
     // digits, and a few other chars, with "_"
     filename = g_strcanon (filename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_');
-    // Build the complete path by adding document->base if set
-    gchar *filepath = g_build_filename (document->base?document->base:"", filename, NULL);
+
+    // Build the complete path by adding document base dir, if set, otherwise home dir
+    gchar * directory = NULL;
+    if (SP_DOCUMENT_URI(document)) {
+        directory = g_dirname(SP_DOCUMENT_URI(document));
+    }
+    if (directory == NULL) {
+        directory = homedir_path(NULL);
+    }
+    gchar *filepath = g_build_filename (directory, filename, NULL);
 
     //g_print ("%s\n", filepath);
 
@@ -2731,7 +2770,7 @@ sp_selection_set_mask(SPDesktop *desktop, bool apply_clip_path, bool apply_to_la
         SPItem *item = reinterpret_cast<SPItem *>(i->data);
         // inverted object transform should be applied to a mask object,
         // as mask is calculated in user space (after applying transform)
-        NR::Matrix maskTransform (item->transform.inverse());
+        Geom::Matrix maskTransform (item->transform.inverse());
 
         GSList *mask_items_dup = NULL;
         for (GSList *mask_item = mask_items; NULL != mask_item; mask_item = mask_item->next) {
@@ -2841,7 +2880,7 @@ void sp_selection_unset_mask(SPDesktop *desktop, bool apply_clip_path) {
             selection->add(repr);
 
             // transform mask, so it is moved the same spot where mask was applied
-            NR::Matrix transform (mask_item->transform);
+            Geom::Matrix transform (mask_item->transform);
             transform *= (*it).second->transform;
             sp_item_write_transform(mask_item, SP_OBJECT_REPR(mask_item), transform);
         }
@@ -2899,7 +2938,7 @@ fit_canvas_to_drawing(SPDocument *doc)
 
     sp_document_ensure_up_to_date(doc);
     SPItem const *const root = SP_ITEM(doc->root);
-    Geom::OptRect const bbox(root->getBounds(sp_item_i2r_affine(root)));
+    Geom::OptRect const bbox(root->getBounds(sp_item_i2d_affine(root)));
     if (bbox) {
         doc->fitToRect(*bbox);
         return true;