summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabiertxof <jtx@jtx>2017-01-01 14:02:26 +0000
committerJabiertxof <jtx@jtx>2017-01-01 14:02:26 +0000
commit57132e1d5f4729e2ea1abc2ef835f3962f6680b4 (patch)
tree369c9d944697c466c99a549b9456a805e0d47d76 /src
parentUpdate to trunk (diff)
parentUpdate to trunk (diff)
downloadinkscape-57132e1d5f4729e2ea1abc2ef835f3962f6680b4.tar.gz
inkscape-57132e1d5f4729e2ea1abc2ef835f3962f6680b4.zip
merge mirror improvements
(bzr r15295.1.41)
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/CMakeLists.txt6
-rw-r--r--src/live_effects/effect.cpp41
-rw-r--r--src/live_effects/effect.h8
-rw-r--r--src/live_effects/lpe-clone-original.cpp279
-rw-r--r--src/live_effects/lpe-clone-original.h23
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp1
-rw-r--r--src/live_effects/parameter/item-reference.cpp44
-rw-r--r--src/live_effects/parameter/item-reference.h56
-rw-r--r--src/live_effects/parameter/item.cpp246
-rw-r--r--src/live_effects/parameter/item.h79
-rw-r--r--src/live_effects/parameter/originalitem.cpp127
-rw-r--r--src/live_effects/parameter/originalitem.h48
-rw-r--r--src/sp-ellipse.cpp13
-rw-r--r--src/sp-item-group.cpp37
-rw-r--r--src/sp-lpe-item.cpp21
-rw-r--r--src/sp-lpe-item.h3
-rw-r--r--src/sp-object.cpp1
-rw-r--r--src/sp-path.cpp31
-rw-r--r--src/ui/clipboard.cpp2
19 files changed, 998 insertions, 68 deletions
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt
index 784317090..5ffccc7c0 100644
--- a/src/live_effects/CMakeLists.txt
+++ b/src/live_effects/CMakeLists.txt
@@ -60,6 +60,9 @@ set(live_effects_SRC
parameter/array.cpp
parameter/bool.cpp
parameter/filletchamferpointarray.cpp
+ parameter/item-reference.cpp
+ parameter/item.cpp
+ parameter/originalitem.cpp
parameter/originalpath.cpp
parameter/originalpatharray.cpp
parameter/parameter.cpp
@@ -142,6 +145,9 @@ set(live_effects_SRC
parameter/bool.h
parameter/enum.h
parameter/filletchamferpointarray.h
+ parameter/item.h
+ parameter/item-reference.h
+ parameter/originalitem.h
parameter/originalpath.h
parameter/originalpatharray.h
parameter/parameter.h
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 5cc0d6f20..81a512d23 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -116,7 +116,7 @@ const Util::EnumData<EffectType> LPETypeData[] = {
{RULER, N_("Ruler"), "ruler"},
/* 0.91 */
{POWERSTROKE, N_("Power stroke"), "powerstroke"},
- {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"},
+ {CLONE_ORIGINAL, N_("Clone original"), "clone_original"},
/* 0.92 */
{SIMPLIFY, N_("Simplify"), "simplify"},
{LATTICE2, N_("Lattice Deformation 2"), "lattice2"},
@@ -356,7 +356,7 @@ Effect::Effect(LivePathEffectObject *lpeobject)
sp_lpe_item(NULL),
current_zoom(1),
upd_params(true),
- sp_curve(NULL),
+ sp_shape(NULL),
provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden
is_ready(false) // is automatically set to false if providesOwnFlashPaths() is not overridden
{
@@ -392,9 +392,9 @@ Effect::doOnApply (SPLPEItem const*/*lpeitem*/)
}
void
-Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP)
+Effect::setSelectedNodePoints(std::vector<Geom::Point> selected_np)
{
- selectedNodesPoints = sNP;
+ selected_nodes_points = selected_np;
}
void
@@ -404,16 +404,16 @@ Effect::setCurrentZoom(double cZ)
}
bool
-Effect::isNodePointSelected(Geom::Point const &nodePoint) const
+Effect::isNodePointSelected(Geom::Point const &node_point) const
{
- if (selectedNodesPoints.size() > 0) {
+ if (selected_nodes_points.size() > 0) {
using Geom::X;
using Geom::Y;
- for (std::vector<Geom::Point>::const_iterator i = selectedNodesPoints.begin();
- i != selectedNodesPoints.end(); ++i) {
+ for (std::vector<Geom::Point>::const_iterator i = selected_nodes_points.begin();
+ i != selected_nodes_points.end(); ++i) {
Geom::Point p = *i;
Geom::Affine transformCoordinate = sp_lpe_item->i2dt_affine();
- Geom::Point p2(nodePoint[X],nodePoint[Y]);
+ Geom::Point p2(node_point[X], node_point[Y]);
p2 *= transformCoordinate;
if (Geom::are_near(p, p2, 0.01)) {
return true;
@@ -446,21 +446,24 @@ void Effect::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/)
void Effect::doOnApply_impl(SPLPEItem const* lpeitem)
{
sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
- /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve();
- pathvector_before_effect = sp_curve->get_pathvector();*/
+ SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item);
+ if(shape){
+ setCurrentShape(shape);
+ }
doOnApply(lpeitem);
}
void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
{
sp_lpe_item = const_cast<SPLPEItem *>(lpeitem);
- //printf("(SPLPEITEM*) %p\n", sp_lpe_item);
+ //Groups set shape in performPathEffect before each call to doEffect
SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item);
if(shape){
- sp_curve = shape->getCurve();
- pathvector_before_effect = sp_curve->get_pathvector();
+ setCurrentShape(shape);
}
+ //printf("(SPLPEITEM*) %p\n", sp_lpe_item);
doBeforeEffect(lpeitem);
+
if (apply_to_clippath_and_mask && SP_IS_GROUP(sp_lpe_item)) {
sp_lpe_item->apply_to_clippath(sp_lpe_item);
sp_lpe_item->apply_to_mask(sp_lpe_item);
@@ -468,6 +471,16 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem)
update_helperpath();
}
+void Effect::setCurrentShape(SPShape * shape){
+ if(shape){
+ sp_shape = shape;
+ if (!(sp_curve = sp_shape->getCurve())) {
+ // oops
+ return;
+ }
+ pathvector_before_effect = sp_curve->get_pathvector();
+ }
+}
/**
* Effects can have a parameter path set before they are applied by accepting a nonzero number of
* mouse clicks. This method activates the pen context, which waits for the specified number of
diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h
index bc56c2390..b1dc0eabb 100644
--- a/src/live_effects/effect.h
+++ b/src/live_effects/effect.h
@@ -79,7 +79,8 @@ public:
static int acceptsNumClicks(EffectType type);
int acceptsNumClicks() const { return acceptsNumClicks(effectType()); }
void doAcceptPathPreparations(SPLPEItem *lpeitem);
-
+ SPShape * getCurrentShape(){ return sp_shape; };
+ void setCurrentShape(SPShape * shape);
/*
* isReady() indicates whether all preparations which are necessary to apply the LPE are done,
* e.g., waiting for a parameter path either before the effect is created or when it needs a
@@ -169,9 +170,10 @@ protected:
// instead of normally 'splitting' the path into continuous pwd2 paths and calling doEffect_pwd2 for each.
bool concatenate_before_pwd2;
- SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
+ SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.z
+ SPShape * sp_shape; // these get stored in doBeforeEffect_impl before doEffect chain, or in performPathEffects on groups, and derived classes may do as they please with them.
double current_zoom;
- std::vector<Geom::Point> selectedNodesPoints;
+ std::vector<Geom::Point> selected_nodes_points;
SPCurve * sp_curve;
Geom::PathVector pathvector_before_effect;
private:
diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp
index 10418a02d..76cc56b8f 100644
--- a/src/live_effects/lpe-clone-original.cpp
+++ b/src/live_effects/lpe-clone-original.cpp
@@ -6,6 +6,12 @@
#include "live_effects/lpe-clone-original.h"
#include "display/curve.h"
+#include "svg/path-string.h"
+#include "svg/svg.h"
+#include "sp-clippath.h"
+#include "sp-mask.h"
+#include "xml/sp-css-attr.h"
+
// TODO due to internal breakage in glibmm headers, this must be last:
#include <glibmm/i18n.h>
@@ -14,9 +20,258 @@ namespace LivePathEffect {
LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
- linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this)
+ linked_path("LEGACY FALLBACK", "LEGACY FALLBACK", "linkedpath", &wr, this),
+ linked_item(_("Linked Item:"), _("Item from which to take the original data"), "linked_item", &wr, this),
+ scale(_("Scale %"), _("Scale item %"), "scale", &wr, this, 100.0),
+ preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false),
+ use_center(_("Relative center of element"), _("Relative center of element"), "use_center", &wr, this, true),
+ attributes("Attributes linked", "Attributes linked", "attributes", &wr, this,""),
+ style_attributes("Style attributes linked", "Style attributes linked", "style_attributes", &wr, this,"")
+{
+ registerParameter(&linked_path);
+ registerParameter(&linked_item);
+ registerParameter(&scale);
+ registerParameter(&attributes);
+ registerParameter(&style_attributes);
+ registerParameter(&preserve_position);
+ registerParameter(&use_center);
+ scale.param_set_range(0.01, 999999.0);
+ scale.param_set_increments(1, 1);
+ scale.param_set_digits(2);
+ attributes.param_hide_canvas_text();
+ style_attributes.param_hide_canvas_text();
+ preserve_position_changed = preserve_position;
+ preserve_affine = Geom::identity();
+}
+
+bool hasLinkedTransform( const char * attributes) {
+ gchar ** attarray = g_strsplit(attributes, ",", 0);
+ gchar ** iter = attarray;
+ bool has_linked_transform = false;
+ while (*iter != NULL) {
+ const char* attribute = (*iter);
+ if ( std::strcmp(attribute, "transform") == 0 ) {
+ has_linked_transform = true;
+ }
+ iter++;
+ }
+ return has_linked_transform;
+}
+
+void
+LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root)
+{
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) {
+ std::vector< SPObject * > childs = origin->childList(true);
+ size_t index = 0;
+ for (std::vector<SPObject * >::iterator obj_it = childs.begin();
+ obj_it != childs.end(); ++obj_it) {
+ SPObject *dest_child = dest->nthChild(index);
+ cloneAttrbutes((*obj_it), dest_child, live, attributes, style_attributes, false);
+ index++;
+ }
+ }
+ //Attributes
+ SPShape * shape_origin = SP_SHAPE(origin);
+ SPPath * path_origin = SP_PATH(origin);
+ SPShape * shape_dest = SP_SHAPE(dest);
+ SPMask *mask_origin = SP_ITEM(origin)->mask_ref->getObject();
+ SPMask *mask_dest = SP_ITEM(dest)->mask_ref->getObject();
+ if(mask_origin && mask_dest) {
+ std::vector<SPObject*> mask_list = mask_origin->childList(true);
+ std::vector<SPObject*> mask_list_dest = mask_dest->childList(true);
+ if (mask_list.size() == mask_list_dest.size()) {
+ size_t i = 0;
+ for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) {
+ SPObject * mask_data = *iter;
+ SPObject * mask_dest_data = mask_list_dest[i];
+ cloneAttrbutes(mask_data, mask_dest_data, live, attributes, style_attributes, false);
+ i++;
+ }
+ }
+ }
+ SPClipPath *clippath_origin = SP_ITEM(origin)->clip_ref->getObject();
+ SPClipPath *clippath_dest = SP_ITEM(dest)->clip_ref->getObject();
+ if(clippath_origin && clippath_dest) {
+ std::vector<SPObject*> clippath_list = clippath_origin->childList(true);
+ std::vector<SPObject*> clippath_list_dest = clippath_dest->childList(true);
+ if (clippath_list.size() == clippath_list_dest.size()) {
+ size_t i = 0;
+ for ( std::vector<SPObject*>::const_iterator iter=clippath_list.begin();iter!=clippath_list.end();++iter) {
+ SPObject * clippath_data = *iter;
+ SPObject * clippath_dest_data = clippath_list_dest[i];
+ cloneAttrbutes(clippath_data, clippath_dest_data, live, attributes, style_attributes, false);
+ i++;
+ }
+ }
+ }
+ gchar ** attarray = g_strsplit(attributes, ",", 0);
+ gchar ** iter = attarray;
+ Geom::Affine affine_dest = Geom::identity();
+ Geom::Affine affine_origin = Geom::identity();
+ Geom::Affine affine_previous = Geom::identity();
+ sp_svg_transform_read(SP_ITEM(dest)->getAttribute("transform"), &affine_dest);
+ sp_svg_transform_read(SP_ITEM(origin)->getAttribute("transform"), &affine_origin);
+ while (*iter != NULL) {
+ const char* attribute = (*iter);
+ if ( std::strcmp(attribute, "transform") == 0 ) {
+ if (preserve_position) {
+ Geom::Affine dest_affine = Geom::identity();
+ if (root) {
+ dest_affine *= affine_origin;
+ if (preserve_affine == Geom::identity()) {
+ dest_affine *= Geom::Translate(affine_dest.translation());
+ }
+ dest_affine *= Geom::Translate(affine_origin.translation()).inverse();
+ dest_affine *= Geom::Translate(preserve_affine.translation());
+ affine_previous = preserve_affine;
+ preserve_affine = Geom::identity();
+ SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(dest_affine));
+ }
+ } else {
+ SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(affine_origin));
+ }
+ } else if ( shape_dest && shape_origin && live && (std::strcmp(attribute, "d") == 0 || std::strcmp(attribute, "inkscape:original-d") == 0)) {
+ SPCurve *c = NULL;
+ if (std::strcmp(attribute, "d") == 0) {
+ c = shape_origin->getCurve();
+ } else {
+ c = shape_origin->getCurveBeforeLPE();
+ }
+ if (c) {
+ Geom::PathVector c_pv = c->get_pathvector();
+ Geom::OptRect orig_bbox = SP_ITEM(origin)->geometricBounds();
+ Geom::OptRect dest_bbox = SP_ITEM(dest)->geometricBounds();
+ if (dest_bbox && orig_bbox && root) {
+ Geom::Point orig_point = (*orig_bbox).corner(0);
+ Geom::Point dest_point = (*dest_bbox).corner(0);
+ if (use_center) {
+ orig_point = (*orig_bbox).midpoint();
+ dest_point = (*dest_bbox).midpoint();
+ }
+ if (scale != 100.0) {
+ double scale_affine = scale/100.0;
+ Geom::Scale scale = Geom::Scale(scale_affine);
+ c_pv *= Geom::Translate(orig_point).inverse();
+ c_pv *= scale;
+ c_pv *= Geom::Translate(orig_point);
+ }
+ if (preserve_position && hasLinkedTransform(attributes)) {
+ c_pv *= Geom::Translate(dest_point - orig_point);
+ }
+ }
+ c_pv *= i2anc_affine(dest, sp_lpe_item);
+ c->set_pathvector(c_pv);
+ if (!path_origin) {
+ shape_dest->setCurveInsync(c, TRUE);
+ dest->getRepr()->setAttribute(attribute, sp_svg_write_path(c_pv));
+ } else {
+ shape_dest->setCurve(c, TRUE);
+ }
+ c->unref();
+ } else {
+ dest->getRepr()->setAttribute(attribute, NULL);
+ }
+ } else {
+ dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute));
+ }
+ iter++;
+ }
+ g_strfreev (attarray);
+ SPCSSAttr *css_origin = sp_repr_css_attr_new();
+ sp_repr_css_attr_add_from_string(css_origin, origin->getRepr()->attribute("style"));
+ SPCSSAttr *css_dest = sp_repr_css_attr_new();
+ sp_repr_css_attr_add_from_string(css_dest, dest->getRepr()->attribute("style"));
+ gchar ** styleattarray = g_strsplit(style_attributes, ",", 0);
+ gchar ** styleiter = styleattarray;
+ while (*styleiter != NULL) {
+ const char* attribute = (*styleiter);
+ const char* origin_attribute = sp_repr_css_property(css_origin, attribute, "");
+ if (origin_attribute == "") {
+ sp_repr_css_set_property (css_dest, attribute, NULL);
+ } else {
+ sp_repr_css_set_property (css_dest, attribute, origin_attribute);
+ }
+ styleiter++;
+ }
+ g_strfreev (styleattarray);
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css_dest,css_str);
+ dest->getRepr()->setAttribute("style", css_str.c_str());
+}
+
+void
+LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){
+ original_bbox(lpeitem);
+ if (linked_path.linksToPath()) { //Legacy staff
+ Glib::ustring attributes_value("d");
+ attributes.param_setValue(attributes_value);
+ attributes.write_to_SVG();
+ Glib::ustring style_attributes_value("");
+ style_attributes.param_setValue(style_attributes_value);
+ style_attributes.write_to_SVG();
+ linked_item.param_readSVGValue(linked_path.param_getSVGValue());
+ linked_path.param_readSVGValue("");
+ }
+
+ if (linked_item.linksToItem()) {
+ if ( preserve_position_changed != preserve_position ) {
+ if (!preserve_position) {
+ sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &preserve_affine);
+ }
+ preserve_position_changed = preserve_position;
+ }
+ cloneAttrbutes(linked_item.getObject(), SP_OBJECT(sp_lpe_item), true, attributes.param_getSVGValue(), style_attributes.param_getSVGValue(), true);
+ }
+}
+
+
+Gtk::Widget *
+LPECloneOriginal::newWidget()
{
- registerParameter( dynamic_cast<Parameter *>(&linked_path) );
+ // use manage here, because after deletion of Effect object, others might
+ // still be pointing to this widget.
+ Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget()));
+ vbox->set_border_width(5);
+ vbox->set_homogeneous(false);
+ vbox->set_spacing(2);
+
+ std::vector<Parameter *>::iterator it = param_vector.begin();
+ while (it != param_vector.end()) {
+ if ((*it)->widget_is_visible) {
+ Parameter * param = *it;
+ if (param->param_key == "linkedpath") {
+ ++it;
+ continue;
+ }
+ Gtk::Widget * widg = param->param_newWidget();
+ Glib::ustring * tip = param->param_getTooltip();
+ if (widg) {
+ vbox->pack_start(*widg, true, true, 2);
+ if (tip) {
+ widg->set_tooltip_text(*tip);
+ } else {
+ widg->set_tooltip_text("");
+ widg->set_has_tooltip(false);
+ }
+ }
+ }
+
+ ++it;
+ }
+ this->upd_params = false;
+ return dynamic_cast<Gtk::Widget *>(vbox);
+}
+
+void
+LPECloneOriginal::doOnApply(SPLPEItem const* lpeitem){
+ Glib::ustring attributes_value("d,transform");
+ attributes.param_setValue(attributes_value);
+ attributes.write_to_SVG();
+ Glib::ustring style_attributes_value("opacity,stroke-width");
+ style_attributes.param_setValue(style_attributes_value);
+ style_attributes.write_to_SVG();
}
LPECloneOriginal::~LPECloneOriginal()
@@ -24,12 +279,22 @@ LPECloneOriginal::~LPECloneOriginal()
}
-void LPECloneOriginal::doEffect (SPCurve * curve)
+void
+LPECloneOriginal::transform_multiply(Geom::Affine const& postmul, bool set)
+{
+ if (linked_item.linksToItem()) {
+ bool changed = false;
+ linked_item.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ }
+}
+
+void
+LPECloneOriginal::doEffect (SPCurve * curve)
{
- if ( linked_path.linksToPath() ) {
- Geom::PathVector linked_pathv = linked_path.get_pathvector();
- if ( !linked_pathv.empty() ) {
- curve->set_pathvector(linked_pathv);
+ if (linked_item.linksToItem()) {
+ SPShape * shape = getCurrentShape();
+ if(shape){
+ curve->set_pathvector(shape->getCurve()->get_pathvector());
}
}
}
diff --git a/src/live_effects/lpe-clone-original.h b/src/live_effects/lpe-clone-original.h
index abf65ded8..064fe84b2 100644
--- a/src/live_effects/lpe-clone-original.h
+++ b/src/live_effects/lpe-clone-original.h
@@ -10,22 +10,37 @@
*/
#include "live_effects/effect.h"
+#include "live_effects/parameter/originalitem.h"
#include "live_effects/parameter/originalpath.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/point.h"
+#include "live_effects/parameter/text.h"
+#include "live_effects/lpegroupbbox.h"
namespace Inkscape {
namespace LivePathEffect {
-class LPECloneOriginal : public Effect {
+class LPECloneOriginal : public Effect, GroupBBoxEffect {
public:
LPECloneOriginal(LivePathEffectObject *lpeobject);
virtual ~LPECloneOriginal();
-
+ virtual void doOnApply(SPLPEItem const* lpeitem);
virtual void doEffect (SPCurve * curve);
+ virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+ virtual void transform_multiply(Geom::Affine const& postmul, bool set);
+ virtual Gtk::Widget * newWidget();
+ void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root);
private:
OriginalPathParam linked_path;
-
-private:
+ OriginalItemParam linked_item;
+ ScalarParam scale;
+ BoolParam preserve_position;
+ BoolParam use_center;
+ TextParam attributes;
+ TextParam style_attributes;
+ bool preserve_position_changed;
+ Geom::Affine preserve_affine;
LPECloneOriginal(const LPECloneOriginal&);
LPECloneOriginal& operator=(const LPECloneOriginal&);
};
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index 813f25d3d..250f6aa29 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -125,7 +125,6 @@ void
LPECopyRotate::transform_multiply(Geom::Affine const& postmul, bool set)
{
// cycle through all parameters. Most parameters will not need transformation, but path and point params do.
-
for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) {
Parameter * param = *it;
param->param_transform_multiply(postmul, set);
diff --git a/src/live_effects/parameter/item-reference.cpp b/src/live_effects/parameter/item-reference.cpp
new file mode 100644
index 000000000..a775d93b7
--- /dev/null
+++ b/src/live_effects/parameter/item-reference.cpp
@@ -0,0 +1,44 @@
+/*
+ * The reference corresponding to href of LPE Item parameter.
+ *
+ * Copyright (C) 2008 Johan Engelen
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information.
+ */
+
+#include "live_effects/parameter/item-reference.h"
+
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "sp-item-group.h"
+
+namespace Inkscape {
+namespace LivePathEffect {
+
+bool ItemReference::_acceptObject(SPObject * const obj) const
+{
+ if (SP_IS_SHAPE(obj) || SP_IS_TEXT(obj) || SP_IS_GROUP(obj)) {
+ /* Refuse references to lpeobject */
+ if (obj == getOwner()) {
+ return false;
+ }
+ // TODO: check whether the referred item has this LPE applied, if so: deny deny deny!
+ return URIReference::_acceptObject(obj);
+ } else {
+ return false;
+ }
+}
+
+} // namespace LivePathEffect
+} // namespace Inkscape
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/item-reference.h b/src/live_effects/parameter/item-reference.h
new file mode 100644
index 000000000..91231455a
--- /dev/null
+++ b/src/live_effects/parameter/item-reference.h
@@ -0,0 +1,56 @@
+#ifndef SEEN_LPE_ITEM_REFERENCE_H
+#define SEEN_LPE_ITEM_REFERENCE_H
+
+/*
+ * Copyright (C) 2008-2012 Authors
+ * Authors: Johan Engelen
+ * Abhishek Sharma
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information.
+ */
+
+#include <uri-references.h>
+
+class SPItem;
+namespace Inkscape {
+namespace XML { class Node; }
+
+namespace LivePathEffect {
+
+/**
+ * The reference corresponding to href of LPE ItemParam.
+ */
+class ItemReference : public Inkscape::URIReference {
+public:
+ ItemReference(SPObject *owner) : URIReference(owner) {}
+
+ SPItem *getObject() const {
+ return (SPItem *)URIReference::getObject();
+ }
+
+protected:
+ virtual bool _acceptObject(SPObject * const obj) const;
+
+private:
+ ItemReference(const ItemReference&);
+ ItemReference& operator=(const ItemReference&);
+};
+
+} // namespace LivePathEffect
+
+} // namespace Inkscape
+
+
+
+#endif /* !SEEN_LPE_PATH_REFERENCE_H */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/item.cpp b/src/live_effects/parameter/item.cpp
new file mode 100644
index 000000000..8caea4e26
--- /dev/null
+++ b/src/live_effects/parameter/item.cpp
@@ -0,0 +1,246 @@
+/*
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ * Abhishek Sharma
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "ui/widget/point.h"
+#include <glibmm/i18n.h>
+
+#include "live_effects/parameter/item.h"
+#include "live_effects/effect.h"
+#include "svg/svg.h"
+
+#include "widgets/icon.h"
+#include <gtk/gtk.h>
+#include "selection-chemistry.h"
+#include "xml/repr.h"
+#include "desktop.h"
+#include "inkscape.h"
+#include "message-stack.h"
+
+// clipboard support
+#include "ui/clipboard.h"
+// required for linking to other paths
+#include "uri.h"
+
+#include <gtkmm/button.h>
+#include <gtkmm/label.h>
+#include "ui/icon-names.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+ItemParam::ItemParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect, const gchar * default_value)
+ : Parameter(label, tip, key, wr, effect),
+ changed(true),
+ href(NULL),
+ ref( (SPObject*)effect->getLPEObj() )
+{
+ defvalue = g_strdup(default_value);
+ ref_changed_connection = ref.changedSignal().connect(sigc::mem_fun(*this, &ItemParam::ref_changed));
+}
+
+ItemParam::~ItemParam()
+{
+ remove_link();
+ g_free(defvalue);
+}
+
+void
+ItemParam::param_set_default()
+{
+ param_readSVGValue(defvalue);
+}
+
+
+void
+ItemParam::param_set_and_write_default()
+{
+ param_write_to_repr(defvalue);
+}
+
+bool
+ItemParam::param_readSVGValue(const gchar * strvalue)
+{
+ if (strvalue) {
+ remove_link();
+ if (strvalue[0] == '#') {
+ if (href)
+ g_free(href);
+ href = g_strdup(strvalue);
+ try {
+ ref.attach(Inkscape::URI(href));
+ //lp:1299948
+ SPItem* i = ref.getObject();
+ if (i) {
+ linked_modified_callback(i, SP_OBJECT_MODIFIED_FLAG);
+ } // else: document still processing new events. Repr of the linked object not created yet.
+ } catch (Inkscape::BadURIException &e) {
+ g_warning("%s", e.what());
+ ref.detach();
+ }
+ }
+ emit_changed();
+ return true;
+ }
+
+ return false;
+}
+
+gchar *
+ItemParam::param_getSVGValue() const
+{
+ return g_strdup(href);
+}
+
+Gtk::Widget *
+ItemParam::param_newWidget()
+{
+ Gtk::HBox * _widget = Gtk::manage(new Gtk::HBox());
+ Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-clone"), Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button * pButton = Gtk::manage(new Gtk::Button());
+ Gtk::Label* pLabel = Gtk::manage(new Gtk::Label(param_label));
+ static_cast<Gtk::HBox*>(_widget)->pack_start(*pLabel, true, true);
+ pLabel->set_tooltip_text(param_tooltip);
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &ItemParam::on_link_button_click));
+ static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true);
+ pButton->set_tooltip_text(_("Link to item on clipboard"));
+
+ static_cast<Gtk::HBox*>(_widget)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (_widget);
+}
+
+void
+ItemParam::emit_changed()
+{
+ changed = true;
+ signal_item_changed.emit();
+}
+
+
+void
+ItemParam::addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &hp_vec)
+{
+}
+
+
+void
+ItemParam::start_listening(SPObject * to)
+{
+ if ( to == NULL ) {
+ return;
+ }
+ linked_delete_connection = to->connectDelete(sigc::mem_fun(*this, &ItemParam::linked_delete));
+ linked_modified_connection = to->connectModified(sigc::mem_fun(*this, &ItemParam::linked_modified));
+ if (SP_IS_ITEM(to)) {
+ linked_transformed_connection = SP_ITEM(to)->connectTransformed(sigc::mem_fun(*this, &ItemParam::linked_transformed));
+ }
+ linked_modified(to, SP_OBJECT_MODIFIED_FLAG); // simulate linked_modified signal, so that path data is updated
+}
+
+void
+ItemParam::quit_listening(void)
+{
+ linked_modified_connection.disconnect();
+ linked_delete_connection.disconnect();
+ linked_transformed_connection.disconnect();
+}
+
+void
+ItemParam::ref_changed(SPObject */*old_ref*/, SPObject *new_ref)
+{
+ quit_listening();
+ if ( new_ref ) {
+ start_listening(new_ref);
+ }
+}
+
+void
+ItemParam::remove_link()
+{
+ if (href) {
+ ref.detach();
+ g_free(href);
+ href = NULL;
+ }
+}
+
+void
+ItemParam::linked_delete(SPObject */*deleted*/)
+{
+ quit_listening();
+ remove_link();
+}
+
+void ItemParam::linked_modified(SPObject *linked_obj, guint flags)
+{
+ linked_modified_callback(linked_obj, flags);
+}
+
+void ItemParam::linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item)
+{
+ linked_transformed_callback(rel_transf, moved_item);
+}
+
+void
+ItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/)
+{
+ emit_changed();
+ SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+ItemParam::on_link_button_click()
+{
+ Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get();
+ const gchar * iid = cm->getFirstObjectID();
+ if (!iid) {
+ return;
+ }
+
+ Glib::ustring itemid(iid);
+
+ if (itemid.empty()) {
+ return;
+ }
+
+ // add '#' at start to make it an uri.
+ itemid.insert(itemid.begin(), '#');
+ if ( href && strcmp(itemid.c_str(), href) == 0 ) {
+ // no change, do nothing
+ return;
+ } else {
+ // TODO:
+ // check if id really exists in document, or only in clipboard document: if only in clipboard then invalid
+ // check if linking to object to which LPE is applied (maybe delegated to PathReference
+
+ param_write_to_repr(itemid.c_str());
+ DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Link item parameter to path"));
+ }
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/item.h b/src/live_effects/parameter/item.h
new file mode 100644
index 000000000..6c719d451
--- /dev/null
+++ b/src/live_effects/parameter/item.h
@@ -0,0 +1,79 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ITEM_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ITEM_H
+
+/*
+ * Inkscape::LivePathEffectParameters
+ *
+* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include <glib.h>
+
+
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/item-reference.h"
+#include <stddef.h>
+#include <sigc++/sigc++.h>
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class ItemParam : public Parameter {
+public:
+ ItemParam ( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect,
+ const gchar * default_value = "");
+ virtual ~ItemParam();
+ virtual Gtk::Widget * param_newWidget();
+
+ virtual bool param_readSVGValue(const gchar * strvalue);
+ virtual gchar * param_getSVGValue() const;
+
+ virtual void param_set_default();
+ void param_set_and_write_default();
+ virtual void addCanvasIndicators(SPLPEItem const* lpeitem, std::vector<Geom::PathVector> &hp_vec);
+
+ sigc::signal <void> signal_item_pasted;
+ sigc::signal <void> signal_item_changed;
+ bool changed; /* this gets set whenever the path is changed (this is set to true, and then the signal_item_changed signal is emitted).
+ * the user must set it back to false if she wants to use it sensibly */
+protected:
+
+ gchar * href; // contains link to other object, e.g. "#path2428", NULL if ItemParam contains pathdata itself
+ ItemReference ref;
+ sigc::connection ref_changed_connection;
+ sigc::connection linked_delete_connection;
+ sigc::connection linked_modified_connection;
+ sigc::connection linked_transformed_connection;
+ void ref_changed(SPObject *old_ref, SPObject *new_ref);
+ void remove_link();
+ void start_listening(SPObject * to);
+ void quit_listening(void);
+ void linked_delete(SPObject *deleted);
+ void linked_modified(SPObject *linked_obj, guint flags);
+ void linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item);
+ virtual void linked_modified_callback(SPObject *linked_obj, guint flags);
+ virtual void linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/) {};
+ void on_link_button_click();
+
+ void emit_changed();
+
+ gchar * defvalue;
+
+private:
+ ItemParam(const ItemParam&);
+ ItemParam& operator=(const ItemParam&);
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/live_effects/parameter/originalitem.cpp b/src/live_effects/parameter/originalitem.cpp
new file mode 100644
index 000000000..015fa0bd4
--- /dev/null
+++ b/src/live_effects/parameter/originalitem.cpp
@@ -0,0 +1,127 @@
+/*
+ * Copyright (C) Johan Engelen 2012 <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include <gtkmm/box.h>
+#include "live_effects/parameter/originalitem.h"
+
+#include "widgets/icon.h"
+#include <glibmm/i18n.h>
+#include <gtkmm/button.h>
+#include <gtkmm/label.h>
+
+#include "uri.h"
+#include "sp-shape.h"
+#include "sp-text.h"
+#include "display/curve.h"
+#include "live_effects/effect.h"
+
+#include "inkscape.h"
+#include "desktop.h"
+#include "selection.h"
+#include "ui/icon-names.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+OriginalItemParam::OriginalItemParam( const Glib::ustring& label, const Glib::ustring& tip,
+ const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr,
+ Effect* effect)
+ : ItemParam(label, tip, key, wr, effect, "")
+{
+}
+
+OriginalItemParam::~OriginalItemParam()
+{
+
+}
+
+Gtk::Widget *
+OriginalItemParam::param_newWidget()
+{
+ Gtk::HBox *_widget = Gtk::manage(new Gtk::HBox());
+
+ { // Label
+ Gtk::Label *pLabel = Gtk::manage(new Gtk::Label(param_label));
+ static_cast<Gtk::HBox*>(_widget)->pack_start(*pLabel, true, true);
+ pLabel->set_tooltip_text(param_tooltip);
+ }
+
+ { // Paste item to link button
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-paste"), Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemParam::on_link_button_click));
+ static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true);
+ pButton->set_tooltip_text(_("Link to item"));
+ }
+
+ { // Select original button
+ Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon("edit-select-original", Inkscape::ICON_SIZE_BUTTON) );
+ Gtk::Button *pButton = Gtk::manage(new Gtk::Button());
+ pButton->set_relief(Gtk::RELIEF_NONE);
+ pIcon->show();
+ pButton->add(*pIcon);
+ pButton->show();
+ pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemParam::on_select_original_button_click));
+ static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true);
+ pButton->set_tooltip_text(_("Select original"));
+ }
+
+ static_cast<Gtk::HBox*>(_widget)->show_all_children();
+
+ return dynamic_cast<Gtk::Widget *> (_widget);
+}
+
+void
+OriginalItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/)
+{
+ emit_changed();
+ SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG);
+}
+
+void
+OriginalItemParam::linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/)
+{
+/** \todo find good way to compensate for referenced item transform, like done for normal clones.
+ * See sp-use.cpp: sp_use_move_compensate */
+}
+
+
+void
+OriginalItemParam::on_select_original_button_click()
+{
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ SPItem *original = ref.getObject();
+ if (desktop == NULL || original == NULL) {
+ return;
+ }
+ Inkscape::Selection *selection = desktop->getSelection();
+ selection->clear();
+ selection->set(original);
+}
+
+} /* namespace LivePathEffect */
+
+} /* namespace Inkscape */
+
+/*
+ Local Variables:
+ mode:c++
+ c-file-style:"stroustrup"
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
+ indent-tabs-mode:nil
+ fill-column:99
+ End:
+*/
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
diff --git a/src/live_effects/parameter/originalitem.h b/src/live_effects/parameter/originalitem.h
new file mode 100644
index 000000000..9c67571e8
--- /dev/null
+++ b/src/live_effects/parameter/originalitem.h
@@ -0,0 +1,48 @@
+#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINAL_ITEM_H
+#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINAL_ITEM_H
+
+/*
+ * Inkscape::LiveItemEffectParameters
+ *
+* Copyright (C) Johan Engelen 2012 <j.b.c.engelen@alumnus.utwente.nl>
+ *
+ * Released under GNU GPL, read the file 'COPYING' for more information
+ */
+
+#include "live_effects/parameter/item.h"
+
+namespace Inkscape {
+
+namespace LivePathEffect {
+
+class OriginalItemParam: public ItemParam {
+public:
+ OriginalItemParam ( const Glib::ustring& label,
+ const Glib::ustring& tip,
+ const Glib::ustring& key,
+ Inkscape::UI::Widget::Registry* wr,
+ Effect* effect);
+ virtual ~OriginalItemParam();
+
+ bool linksToItem() const { return (href != NULL); }
+ SPItem * getObject() const { return ref.getObject(); }
+
+ virtual Gtk::Widget * param_newWidget();
+
+protected:
+ virtual void linked_modified_callback(SPObject *linked_obj, guint flags);
+ virtual void linked_transformed_callback(Geom::Affine const *rel_transf, SPItem *moved_item);
+
+ void on_select_original_button_click();
+
+private:
+ OriginalItemParam(const OriginalItemParam&);
+ OriginalItemParam& operator=(const OriginalItemParam&);
+};
+
+
+} //namespace LivePathEffect
+
+} //namespace Inkscape
+
+#endif
diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp
index ed1e2b504..9589d6fce 100644
--- a/src/sp-ellipse.cpp
+++ b/src/sp-ellipse.cpp
@@ -445,11 +445,20 @@ void SPGenericEllipse::set_shape()
if (hasPathEffect() && pathEffectsEnabled()) {
SPCurve *c_lpe = curve->copy();
bool success = this->performPathEffect(c_lpe);
-
+
if (success) {
this->setCurveInsync(c_lpe, TRUE);
+ } else {
+ Inkscape::XML::Node *repr = this->getRepr();
+ if (gchar const * value = repr->attribute("d")) {
+ Geom::PathVector pv = sp_svg_read_pathv(value);
+ SPCurve *oldcurve = new (std::nothrow) SPCurve(pv);
+ if (oldcurve) {
+ this->setCurveInsync(oldcurve, TRUE);
+ oldcurve->unref();
+ }
+ }
}
-
c_lpe->unref();
}
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index 7b2507b5e..808d475c7 100644
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
@@ -950,25 +950,36 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write)
} else {
c = subShape->getCurve();
}
-
+ bool success = false;
// only run LPEs when the shape has a curve defined
if (c) {
c->transform(i2anc_affine(subitem, topgroup));
- topgroup->performPathEffect(c);
+ success = topgroup->performPathEffect(c, subShape);
c->transform(i2anc_affine(subitem, topgroup).inverse());
- subShape->setCurve(c, TRUE);
-
- if (write) {
+ if (c && success) {
+ subShape->setCurve(c, TRUE);
+ if (write) {
+ Inkscape::XML::Node *repr = subitem->getRepr();
+ gchar *str = sp_svg_write_path(c->get_pathvector());
+ repr->setAttribute("d", str);
+ #ifdef GROUP_VERBOSE
+ g_message("sp_group_perform_patheffect writes 'd' attribute");
+ #endif
+ g_free(str);
+ }
+ c->unref();
+ } else {
+ // LPE was unsuccesfull or doeffect stack return null. Read the old 'd'-attribute.
Inkscape::XML::Node *repr = subitem->getRepr();
- gchar *str = sp_svg_write_path(c->get_pathvector());
- repr->setAttribute("d", str);
-#ifdef GROUP_VERBOSE
- g_message("sp_group_perform_patheffect writes 'd' attribute");
-#endif
- g_free(str);
+ if (gchar const * value = repr->attribute("d")) {
+ Geom::PathVector pv = sp_svg_read_pathv(value);
+ SPCurve *oldcurve = new (std::nothrow) SPCurve(pv);
+ if (oldcurve) {
+ subShape->setCurve(oldcurve, TRUE);
+ oldcurve->unref();
+ }
+ }
}
-
- c->unref();
}
}
}
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index 98428512f..fb640c50c 100644
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
@@ -212,7 +212,7 @@ Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape
/**
* returns true when LPE was successful.
*/
-bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) {
+bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) {
if (!curve) {
return false;
@@ -244,12 +244,14 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) {
}
if (!is_clip_or_mask || (is_clip_or_mask && lpe->apply_to_clippath_and_mask)) {
// Groups have their doBeforeEffect called elsewhere
+ if (current) {
+ lpe->setCurrentShape(current);
+ }
if (!SP_IS_GROUP(this)) {
lpe->doBeforeEffect_impl(this);
}
-
try {
- lpe->doEffect(curve);
+ lpe->doEffect(curve);
}
catch (std::exception & e) {
g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what());
@@ -700,10 +702,10 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item)
try {
if(SP_IS_GROUP(this)){
c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
- success = this->performPathEffect(c, true);
+ success = this->performPathEffect(c, SP_SHAPE(clip_mask), true);
c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
} else {
- success = this->performPathEffect(c, true);
+ success = this->performPathEffect(c, SP_SHAPE(clip_mask), true);
}
} catch (std::exception & e) {
g_warning("Exception during LPE execution. \n %s", e.what());
@@ -714,12 +716,13 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item)
success = false;
}
Inkscape::XML::Node *repr = clip_mask->getRepr();
- if (success) {
+ // This c check allow to not apply LPE if curve is NULL after performPathEffect used in clone.obgets LPE
+ if (success && c) {
gchar *str = sp_svg_write_path(c->get_pathvector());
repr->setAttribute("d", str);
g_free(str);
} else {
- // LPE was unsuccesfull. Read the old 'd'-attribute.
+ // LPE was unsuccesfull or doeffect stack return null.. Read the old 'd'-attribute.
if (gchar const * value = repr->attribute("d")) {
Geom::PathVector pv = sp_svg_read_pathv(value);
SPCurve *oldcurve = new (std::nothrow) SPCurve(pv);
@@ -729,7 +732,9 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item)
}
}
}
- c->unref();
+ if (c) {
+ c->unref();
+ }
}
}
}
diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h
index db4a0c7a3..0f198c49c 100644
--- a/src/sp-lpe-item.h
+++ b/src/sp-lpe-item.h
@@ -23,6 +23,7 @@
class LivePathEffectObject;
class SPCurve;
+class SPShape;
class SPDesktop;
namespace Inkscape{
@@ -69,7 +70,7 @@ public:
virtual void update_patheffect(bool write);
- bool performPathEffect(SPCurve *curve, bool is_clip_or_mask = false);
+ bool performPathEffect(SPCurve *curve, SPShape *current = NULL, bool is_clip_or_mask = false);
bool pathEffectsEnabled() const;
bool hasPathEffect() const;
diff --git a/src/sp-object.cpp b/src/sp-object.cpp
index c2122e109..222626162 100644
--- a/src/sp-object.cpp
+++ b/src/sp-object.cpp
@@ -782,6 +782,7 @@ SPObject* SPObject::nthChild(unsigned index) {
if (counter == index) {
return &child;
}
+ counter++;
}
}
return NULL;
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index b593b7937..6c69f3463 100644
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -289,10 +289,23 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) {
if (!_curve) { // 0 nodes, nothing to transform
return Geom::identity();
}
+ // Adjust stroke
+ this->adjust_stroke(transform.descrim());
+
+ // Adjust pattern fill
+ this->adjust_pattern(transform);
+
+ // Adjust gradient fill
+ this->adjust_gradient(transform);
+
+ // Adjust LPE
+ this->adjust_livepatheffect(transform);
// Transform the original-d path if this is a valid LPE this, other else the (ordinary) path
if (_curve_before_lpe && hasPathEffectRecursive()) {
- if (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH)) {
+ if (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) ||
+ this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH))
+ {
// if path has the CLONE_ORIGINAL LPE applied, don't write the transform to the pathdata, but write it 'unoptimized'
// also if the effect is type BEND PATH to fix bug #179842
return transform;
@@ -303,18 +316,6 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) {
_curve->transform(transform);
}
- // Adjust stroke
- this->adjust_stroke(transform.descrim());
-
- // Adjust pattern fill
- this->adjust_pattern(transform);
-
- // Adjust gradient fill
- this->adjust_gradient(transform);
-
- // Adjust LPE
- this->adjust_livepatheffect(transform);
-
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG);
// nothing remains - we've written all of the transform, so return identity
@@ -354,9 +355,9 @@ g_message("sp_path_update_patheffect writes 'd' attribute");
if (gchar const * value = repr->attribute("d")) {
Geom::PathVector pv = sp_svg_read_pathv(value);
SPCurve *oldcurve = new SPCurve(pv);
-
if (oldcurve) {
- this->setCurve(oldcurve, TRUE);
+ this->setCurveInsync(oldcurve, TRUE);
+ repr->setAttribute("d", value);
oldcurve->unref();
}
}
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index a8e708597..42fc2fab4 100644
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
@@ -410,6 +410,8 @@ const gchar *ClipboardManagerImpl::getFirstObjectID()
strcmp(ch->name(), "svg:use") &&
strcmp(ch->name(), "svg:text") &&
strcmp(ch->name(), "svg:image") &&
+ strcmp(ch->name(), "svg:ellipse") &&
+ strcmp(ch->name(), "svg:circle") &&
strcmp(ch->name(), "svg:rect")
) {
ch = ch->next();