index 62fbdf172815c5a352bbe07f8e5e7c82b0833254..31e899d8a34c703866ae9dbc40c6b51244fdb8dc 100644 (file)
#include "svg/svg.h"
#include "desktop.h"
#include "desktop-style.h"
+#include "dir-util.h"
#include "selection.h"
#include "tools-switch.h"
#include "desktop-handles.h"
#include <libnr/nr-matrix-ops.h>
#include <2geom/transforms.h>
#include "xml/repr.h"
+#include "xml/rebase-hrefs.h"
#include "style.h"
#include "document-private.h"
#include "sp-gradient.h"
#include "helper/units.h"
#include "sp-item.h"
#include "box3d.h"
+#include "persp3d.h"
#include "unit-constants.h"
#include "xml/simple-document.h"
#include "sp-filter-reference.h"
}
sp_document_done(sp_desktop_document(desktop), SP_VERB_SELECTION_RAISE,
- //TRANSLATORS: Only put the word "Raise" in the translation. Means "to raise an object" in the undo history
+ //TRANSLATORS: only translate "string" in "context|string".
+ // For more details, see http://developer.gnome.org/doc/API/2.0/glib/glib-I18N.html#Q-:CAPS
+ // "Raise" means "to raise an object" in the undo history
Q_("undo_action|Raise"));
}
return clone_with_original;
}
-
/** Apply matrix to the selection. \a set_i2d is normally true, which means objects are in the
original transform, synced with their reprs, and need to jump to the new transform in one go. A
value of set_i2d==false is only used by seltrans when it's dragging objects live (not outlines); in
that case, items are already in the new position, but the repr is in the old, and this function
then simply updates the repr from item->transform.
*/
-void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d)
+void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix const &affine, bool set_i2d, bool compensate)
{
if (selection->isEmpty())
return;
+ // For each perspective with a box in selection, check whether all boxes are selected and
+ // unlink all non-selected boxes.
+ Persp3D *persp;
+ Persp3D *transf_persp;
+ std::list<Persp3D *> plist = selection->perspList();
+ for (std::list<Persp3D *>::iterator i = plist.begin(); i != plist.end(); ++i) {
+ persp = (Persp3D *) (*i);
+
+ if (!persp3d_has_all_boxes_in_selection (persp, selection)) {
+ std::list<SPBox3D *> selboxes = selection->box3DList(persp);
+
+ // create a new perspective as a copy of the current one and link the selected boxes to it
+ transf_persp = persp3d_create_xml_element (SP_OBJECT_DOCUMENT(persp), persp->perspective_impl);
+
+ for (std::list<SPBox3D *>::iterator b = selboxes.begin(); b != selboxes.end(); ++b)
+ box3d_switch_perspectives(*b, persp, transf_persp);
+ } else {
+ transf_persp = persp;
+ }
+
+ persp3d_apply_affine_transformation(transf_persp, affine);
+ }
+
for (GSList const *l = selection->itemList(); l != NULL; l = l->next) {
SPItem *item = SP_ITEM(l->data);
@@ -1238,7 +1265,7 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
continue;
for (SPObject *use = region->firstChild() ; use ; use = SP_OBJECT_NEXT(use)) {
if (!SP_IS_USE(use)) continue;
- sp_item_write_transform(SP_USE(use), SP_OBJECT_REPR(use), item->transform.inverse(), NULL);
+ sp_item_write_transform(SP_USE(use), SP_OBJECT_REPR(use), item->transform.inverse(), NULL, compensate);
}
}
} else if (transform_clone_with_original) {
@@ -1264,30 +1291,30 @@ void sp_selection_apply_affine(Inkscape::Selection *selection, Geom::Matrix cons
if (prefs_parallel) {
Geom::Matrix move = result * clone_move * t_inv;
- sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &move);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &move, compensate);
} else if (prefs_unmoved) {
//if (SP_IS_USE(sp_use_get_original(SP_USE(item))))
// clone_move = Geom::identity();
Geom::Matrix move = result * clone_move;
- sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &t);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), move, &t, compensate);
}
} else {
// just apply the result
- sp_item_write_transform(item, SP_OBJECT_REPR(item), result, &t);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), result, &t, compensate);
}
} else {
if (set_i2d) {
sp_item_set_i2d_affine(item, sp_item_i2d_affine(item) * (Geom::Matrix)affine);
}
- sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, NULL);
+ sp_item_write_transform(item, SP_OBJECT_REPR(item), item->transform, NULL, compensate);
}
// if we're moving the actual object, not just updating the repr, we can transform the
// center by the same matrix (only necessary for non-translations)
- if (set_i2d && item->isCenterSet() && !affine.isTranslation()) {
+ if (set_i2d && item->isCenterSet() && !(affine.isTranslation() || affine.isIdentity())) {
item->setCenter(old_center * affine);
SP_OBJECT(item)->updateRepr();
}
@@ -1382,9 +1409,9 @@ sp_selection_skew_relative(Inkscape::Selection *selection, Geom::Point const &al
sp_selection_apply_affine(selection, final);
}
-void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move)
+void sp_selection_move_relative(Inkscape::Selection *selection, Geom::Point const &move, bool compensate)
{
- sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)));
+ sp_selection_apply_affine(selection, Geom::Matrix(Geom::Translate(move)), true, compensate);
}
void sp_selection_move_relative(Inkscape::Selection *selection, double dx, double dy)
g_get_current_time(&cu);
guint current = (int) (cu.tv_sec * 1000000 + cu.tv_usec) % 1024;
- // Create the filename
- gchar *filename = g_strdup_printf("%s-%s-%u.png", document->name, SP_OBJECT_REPR(items->data)->attribute("id"), current);
+ // Create the filename.
+ gchar *const basename = g_strdup_printf("%s-%s-%u.png",
+ document->name,
+ SP_OBJECT_REPR(items->data)->attribute("id"),
+ current);
// Imagemagick is known not to handle spaces in filenames, so we replace anything but letters,
// digits, and a few other chars, with "_"
- g_strcanon(filename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_');
+ g_strcanon(basename, "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_.=+~$#@^&!?", '_');
// Build the complete path by adding document base dir, if set, otherwise home dir
gchar * directory = NULL;
if (directory == NULL) {
directory = homedir_path(NULL);
}
- gchar *filepath = g_build_filename(directory, filename, NULL);
+ gchar *filepath = g_build_filename(directory, basename, NULL);
//g_print("%s\n", filepath);
if (pb) {
// Create the repr for the image
Inkscape::XML::Node * repr = xml_doc->createElement("svg:image");
- repr->setAttribute("xlink:href", filename);
- repr->setAttribute("sodipodi:absref", filepath);
+ {
+ repr->setAttribute("sodipodi:absref", filepath);
+ gchar *abs_base = Inkscape::XML::calc_abs_doc_base(document->base);
+ repr->setAttribute("xlink:href", sp_relative_path_from_path(filepath, abs_base));
+ g_free(abs_base);
+ }
if (res == PX_PER_IN) { // for default 90 dpi, snap it to pixel grid
sp_repr_set_svg_double(repr, "width", width);
sp_repr_set_svg_double(repr, "height", height);
desktop->clearWaitingCursor();
- g_free(filename);
+ g_free(basename);
g_free(filepath);
}