index f6920c2a347db8bef972fcb11e306dcea7b30524..badf27ecb45caa4d93541f5e806a371f43b66fd9 100644 (file)
#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"
#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
* 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)
_("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);
}
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)));
}
/**
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);
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);
// 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();
}
// 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));
// 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();
// 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);
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);
}
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;