summaryrefslogtreecommitdiffstats
path: root/src/object
diff options
context:
space:
mode:
authorJabier Arraiza <jabier.arraiza@marker.es>2018-03-03 00:12:41 +0000
committerJabier Arraiza <jabier.arraiza@marker.es>2018-03-26 17:48:34 +0000
commit95b1c7b549605d7c6ce6623cc4cd121ed7c51a64 (patch)
tree1c38b4fe6baabbf45c55e0929516dd825f7d6847 /src/object
parentAllow building with USE_PANGO_WIN32. (diff)
downloadinkscape-95b1c7b549605d7c6ce6623cc4cd121ed7c51a64.tar.gz
inkscape-95b1c7b549605d7c6ce6623cc4cd121ed7c51a64.zip
Base LPE refactor
Diffstat (limited to 'src/object')
-rw-r--r--src/object/box3d-side.cpp25
-rw-r--r--src/object/sp-clippath.cpp6
-rw-r--r--src/object/sp-conn-end-pair.cpp4
-rw-r--r--src/object/sp-ellipse.cpp66
-rw-r--r--src/object/sp-ellipse.h4
-rw-r--r--src/object/sp-item-group.cpp72
-rw-r--r--src/object/sp-item.cpp18
-rw-r--r--src/object/sp-item.h4
-rw-r--r--src/object/sp-line.cpp2
-rw-r--r--src/object/sp-lpe-item.cpp524
-rw-r--r--src/object/sp-lpe-item.h15
-rw-r--r--src/object/sp-mask.cpp27
-rw-r--r--src/object/sp-mask.h4
-rw-r--r--src/object/sp-object.cpp1
-rw-r--r--src/object/sp-offset.cpp4
-rw-r--r--src/object/sp-path.cpp135
-rw-r--r--src/object/sp-path.h18
-rw-r--r--src/object/sp-polygon.cpp2
-rw-r--r--src/object/sp-polyline.cpp2
-rw-r--r--src/object/sp-rect.cpp6
-rw-r--r--src/object/sp-shape.cpp111
-rw-r--r--src/object/sp-shape.h13
-rw-r--r--src/object/sp-spiral.cpp52
-rw-r--r--src/object/sp-spiral.h3
-rw-r--r--src/object/sp-star.cpp51
-rw-r--r--src/object/sp-star.h3
26 files changed, 590 insertions, 582 deletions
diff --git a/src/object/box3d-side.cpp b/src/object/box3d-side.cpp
index 3eea8855c..6ecd3a1fa 100644
--- a/src/object/box3d-side.cpp
+++ b/src/object/box3d-side.cpp
@@ -192,21 +192,22 @@ void Box3DSide::set_shape() {
c->lineto(box3d_get_corner_screen(box, corners[3]));
c->closepath();
- /* Reset the this'scurve to the "original_curve"
+ /* Reset the shape's curve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- this->setCurveInsync( c, TRUE);
-
- if (hasPathEffect() && pathEffectsEnabled()) {
- SPCurve *c_lpe = c->copy();
- bool success = this->performPathEffect(c_lpe);
-
- if (success) {
- this->setCurveInsync(c_lpe, TRUE);
+ SPCurve * before = this->getCurveBeforeLPE();
+ if (before || this->hasPathEffectRecursive()) {
+ if (!before || before->get_pathvector() != c->get_pathvector()){
+ this->setCurveBeforeLPE(c);
+ this->update_patheffect(false);
+ } else {
+ this->setCurveBeforeLPE(c);
}
-
- c_lpe->unref();
+ } else {
+ this->setCurveInsync(c);
+ }
+ if (before) {
+ before->unref();
}
-
c->unref();
}
diff --git a/src/object/sp-clippath.cpp b/src/object/sp-clippath.cpp
index 4f69bd026..4afbf7e51 100644
--- a/src/object/sp-clippath.cpp
+++ b/src/object/sp-clippath.cpp
@@ -238,14 +238,12 @@ void SPClipPath::setBBox(unsigned int key, Geom::OptRect const &bbox) {
Geom::OptRect SPClipPath::geometricBounds(Geom::Affine const &transform) {
Geom::OptRect bbox;
-
for (auto& i: children) {
if (SP_IS_ITEM(&i)) {
- Geom::OptRect tmp = SP_ITEM(&i)->geometricBounds(Geom::Affine(SP_ITEM(&i)->transform) * transform);
- bbox.unionWith(tmp);
+ Geom::OptRect tmp = SP_ITEM(&i)->geometricBounds(transform);
+ bbox.unionWith(tmp);
}
}
-
return bbox;
}
diff --git a/src/object/sp-conn-end-pair.cpp b/src/object/sp-conn-end-pair.cpp
index daadd0cdd..1a0ec5d70 100644
--- a/src/object/sp-conn-end-pair.cpp
+++ b/src/object/sp-conn-end-pair.cpp
@@ -175,7 +175,7 @@ void SPConnEndPair::getAttachedItems(SPItem *h2attItem[2]) const {
void SPConnEndPair::getEndpoints(Geom::Point endPts[]) const
{
- SPCurve const *curve = _path->get_curve_reference();
+ SPCurve const *curve = _path->getCurveForEdit(true);
SPItem *h2attItem[2] = {0};
getAttachedItems(h2attItem);
Geom::Affine i2d = _path->i2doc_affine();
@@ -322,7 +322,7 @@ bool SPConnEndPair::reroutePathFromLibavoid()
return false;
}
- SPCurve *curve = _path->get_curve();
+ SPCurve *curve = _path->getCurve(true);
recreateCurve(curve, _connRef, _connCurvature);
diff --git a/src/object/sp-ellipse.cpp b/src/object/sp-ellipse.cpp
index c32e3012c..95bfd6160 100644
--- a/src/object/sp-ellipse.cpp
+++ b/src/object/sp-ellipse.cpp
@@ -18,6 +18,8 @@
#include <glibmm/i18n.h>
#include "live_effects/effect.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/lpeobject-reference.h"
#include <2geom/angle.h>
#include <2geom/circle.h>
@@ -410,7 +412,7 @@ const char *SPGenericEllipse::displayName() const
}
// Create path for rendering shape on screen
-void SPGenericEllipse::set_shape(bool force)
+void SPGenericEllipse::set_shape()
{
// std::cout << "SPGenericEllipse::set_shape: Entrance" << std::endl;
if (hasBrokenPathEffect()) {
@@ -420,7 +422,7 @@ void SPGenericEllipse::set_shape(bool force)
// unconditionally read the curve from d, if any, to preserve appearance
Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d"));
SPCurve *cold = new SPCurve(pv);
- this->setCurveInsync(cold, TRUE);
+ this->setCurveInsync(cold);
cold->unref();
}
@@ -432,7 +434,7 @@ void SPGenericEllipse::set_shape(bool force)
this->normalize();
- SPCurve *curve = NULL;
+ SPCurve *c = NULL;
// For simplicity, we use a circle with center (0, 0) and radius 1 for our calculations.
Geom::Circle circle(0, 0, 1);
@@ -465,7 +467,7 @@ void SPGenericEllipse::set_shape(bool force)
} else {
pb.flush();
}
- curve = new SPCurve(pb.peek());
+ c = new SPCurve(pb.peek());
// gchar *str = sp_svg_write_path(curve->get_pathvector());
// std::cout << " path: " << str << std::endl;
@@ -473,32 +475,25 @@ void SPGenericEllipse::set_shape(bool force)
// Stretching / moving the calculated shape to fit the actual dimensions.
Geom::Affine aff = Geom::Scale(rx.computed, ry.computed) * Geom::Translate(cx.computed, cy.computed);
- curve->transform(aff);
-
+ c->transform(aff);
+
/* Reset the shape's curve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- if(this->getCurveBeforeLPE()) {
- if(!force && this->getCurveBeforeLPE()->get_pathvector() == curve->get_pathvector()) {
- curve->unref();
- return;
+ SPCurve * before = this->getCurveBeforeLPE();
+ if (before || this->hasPathEffectRecursive()) {
+ if (!before || before->get_pathvector() != c->get_pathvector()){
+ this->setCurveBeforeLPE(c);
+ this->update_patheffect(false);
+ } else {
+ this->setCurveBeforeLPE(c);
}
+ } else {
+ this->setCurveInsync(c);
}
- this->setCurveInsync(curve, TRUE);
- this->setCurveBeforeLPE(curve);
-
- if (hasPathEffect() && pathEffectsEnabled()) {
- SPCurve *c_lpe = curve->copy();
- bool success = this->performPathEffect(c_lpe);
-
- if (success) {
- this->setCurveInsync(c_lpe, TRUE);
- }
-
- c_lpe->unref();
+ if (before) {
+ before->unref();
}
-
- curve->unref();
- // std::cout << "SPGenericEllipse::set_shape: Exit" << std::endl;
+ c->unref();
}
Geom::Affine SPGenericEllipse::set_transform(Geom::Affine const &xform)
@@ -633,25 +628,6 @@ void SPGenericEllipse::modified(guint flags)
SPShape::modified(flags);
}
-void SPGenericEllipse::update_patheffect(bool write)
-{
- this->set_shape(true);
-
- if (write) {
- Inkscape::XML::Node *repr = this->getRepr();
-
- if (this->_curve != NULL && type == SP_GENERIC_ELLIPSE_ARC) {
- gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
- repr->setAttribute("d", str);
- g_free(str);
- } else {
- repr->setAttribute("d", NULL);
- }
- }
-
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
-}
-
void SPGenericEllipse::normalize()
{
Geom::AngleInterval a(this->start, this->end, true);
@@ -698,7 +674,7 @@ void SPGenericEllipse::position_set(gdouble x, gdouble y, gdouble rx, gdouble ry
this->rx = rx;
this->ry = ry;
- Inkscape::Preferences *prefs = Inkscape::Preferences::get();
+ Inkscape::Preferences * prefs = Inkscape::Preferences::get();
// those pref values are in degrees, while we want radians
if (prefs->getDouble("/tools/shapes/arc/start", 0.0) != 0) {
diff --git a/src/object/sp-ellipse.h b/src/object/sp-ellipse.h
index a31b571d8..0aa3dd1c6 100644
--- a/src/object/sp-ellipse.h
+++ b/src/object/sp-ellipse.h
@@ -64,15 +64,13 @@ public:
virtual Inkscape::XML::Node *write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags);
virtual const char *displayName() const;
- virtual void set_shape(bool force = false);
+ virtual void set_shape();
virtual Geom::Affine set_transform(Geom::Affine const &xform);
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual void modified(unsigned int flags);
- virtual void update_patheffect(bool write);
-
/**
* @brief Makes sure that start and end lie between 0 and 2 * PI.
*/
diff --git a/src/object/sp-item-group.cpp b/src/object/sp-item-group.cpp
index 73c1dcb6c..a3fa6c6e8 100644
--- a/src/object/sp-item-group.cpp
+++ b/src/object/sp-item-group.cpp
@@ -58,7 +58,7 @@
using Inkscape::DocumentUndo;
-static void sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write);
+static void sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, Inkscape::LivePathEffect::Effect *lpe, bool write);
SPGroup::SPGroup() : SPLPEItem(),
_expanded(false),
@@ -88,7 +88,6 @@ void SPGroup::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref)
SPLPEItem::child_added(child, ref);
SPObject *last_child = this->lastChild();
-
if (last_child && last_child->getRepr() == child) {
// optimization for the common special case where the child is being added at the end
SPItem *item = dynamic_cast<SPItem *>(last_child);
@@ -121,7 +120,6 @@ void SPGroup::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref)
}
}
}
-
this->requestModified(SP_OBJECT_MODIFIED_FLAG);
}
@@ -642,13 +640,13 @@ sp_item_group_ungroup (SPGroup *group, std::vector<SPItem*> &children, bool do_d
if (item) {
item->doWriteTransform(item->transform, NULL, false);
children.insert(children.begin(),item);
+ item->requestModified(SP_OBJECT_MODIFIED_FLAG);
} else {
g_assert_not_reached();
}
Inkscape::GC::release(repr);
}
-
if (do_done) {
DocumentUndo::done(doc, SP_VERB_NONE, _("Ungroup"));
}
@@ -900,54 +898,52 @@ void SPGroup::update_patheffect(bool write) {
#ifdef GROUP_VERBOSE
g_message("sp_group_update_patheffect: %p\n", lpeitem);
#endif
-
std::vector<SPItem*> const item_list = sp_item_group_item_list(this);
for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
SPObject *sub_item = *iter;
-
- SPLPEItem *lpe_item = dynamic_cast<SPLPEItem *>(sub_item);
- if (lpe_item) {
- lpe_item->update_patheffect(write);
+ if (sub_item) {
+ SPLPEItem *lpe_item = dynamic_cast<SPLPEItem *>(sub_item);
+ if (lpe_item) {
+ lpe_item->update_patheffect(write);
+ }
}
}
+ this->resetClipPathAndMaskLPE();
if (hasPathEffect() && pathEffectsEnabled()) {
for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
{
LivePathEffectObject *lpeobj = (*it)->lpeobject;
-
- if (lpeobj && lpeobj->get_lpe()) {
- lpeobj->get_lpe()->doBeforeEffect_impl(this);
- }
- }
-
- sp_group_perform_patheffect(this, this, write);
-
- for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
- {
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
-
- if (lpeobj && lpeobj->get_lpe()) {
- lpeobj->get_lpe()->doAfterEffect(this);
+ if (lpeobj) {
+ Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
+ if (lpe) {
+ lpeobj->get_lpe()->doBeforeEffect_impl(this);
+ sp_group_perform_patheffect(this, this, lpe, write);
+ lpeobj->get_lpe()->doAfterEffect(this);
+ }
}
}
}
}
static void
-sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write)
+sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, Inkscape::LivePathEffect::Effect *lpe, bool write)
{
std::vector<SPItem*> const item_list = sp_item_group_item_list(group);
-
for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
SPObject *sub_item = *iter;
-
SPGroup *sub_group = dynamic_cast<SPGroup *>(sub_item);
if (sub_group) {
- sp_group_perform_patheffect(sub_group, top_group, write);
+ sp_group_perform_patheffect(sub_group, top_group, lpe, write);
} else {
- SPShape *sub_shape = dynamic_cast<SPShape *>(sub_item);
+ SPShape* sub_shape = dynamic_cast<SPShape *>(sub_item);
+ SPPath* sub_path = dynamic_cast<SPPath *>(sub_item);
+ SPItem* clipmaskto = dynamic_cast<SPItem *>(sub_item);
+ if (clipmaskto) {
+ top_group->applyToClipPath(clipmaskto, lpe);
+ top_group->applyToMask(clipmaskto, lpe);
+ }
if (sub_shape) {
SPCurve * c = NULL;
// If item is a SPRect, convert it to path first:
@@ -973,19 +969,16 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write)
bool success = false;
// only run LPEs when the shape has a curve defined
if (c) {
+ lpe->pathvector_before_effect = c->get_pathvector();
c->transform(i2anc_affine(sub_item, top_group));
- success = top_group->performPathEffect(c, sub_shape);
+ success = top_group->performOnePathEffect(c, sub_shape, lpe);
c->transform(i2anc_affine(sub_item, top_group).inverse());
Inkscape::XML::Node *repr = sub_item->getRepr();
if (c && success) {
- SPPath *sub_path = dynamic_cast<SPPath *>(sub_item);
- if (!sub_path) {
- sub_shape->setCurveInsync( sub_shape->getCurveBeforeLPE(), TRUE);
- sub_shape->setCurve(c, TRUE);
- sub_shape->setCurveInsync( c, TRUE);
- }
+ sub_shape->setCurveInsync(c);
+ lpe->pathvector_after_effect = c->get_pathvector();
if (write) {
- gchar *str = sp_svg_write_path(c->get_pathvector());
+ gchar *str = sp_svg_write_path(lpe->pathvector_after_effect);
repr->setAttribute("d", str);
#ifdef GROUP_VERBOSE
g_message("sp_group_perform_patheffect writes 'd' attribute");
@@ -999,7 +992,7 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write)
Geom::PathVector pv = sp_svg_read_pathv(value);
SPCurve *oldcurve = new (std::nothrow) SPCurve(pv);
if (oldcurve) {
- sub_shape->setCurve(oldcurve, TRUE);
+ sub_shape->setCurve(oldcurve);
oldcurve->unref();
}
}
@@ -1008,6 +1001,11 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *top_group, bool write)
}
}
}
+ SPItem* clipmaskto = dynamic_cast<SPItem *>(group);
+ if (clipmaskto) {
+ top_group->applyToClipPath(clipmaskto, lpe);
+ top_group->applyToMask(clipmaskto, lpe);
+ }
}
/*
diff --git a/src/object/sp-item.cpp b/src/object/sp-item.cpp
index f7a4ff672..a228d9313 100644
--- a/src/object/sp-item.cpp
+++ b/src/object/sp-item.cpp
@@ -29,7 +29,6 @@
#include "inkscape.h"
#include "desktop.h"
-
#include "gradient-chemistry.h"
#include "conn-avoid-ref.h"
#include "conditions.h"
@@ -1079,6 +1078,23 @@ bool SPItem::isFiltered() const {
return (style && style->filter.href && style->filter.href->getObject());
}
+
+SPObject* SPItem::isInMask() const {
+ SPObject* parent = this->parent;
+ while (parent && !dynamic_cast<SPMask *>(parent)) {
+ parent = parent->parent;
+ }
+ return parent;
+}
+
+SPObject* SPItem::isInClipPath() const {
+ SPObject* parent = this->parent;
+ while (parent && !dynamic_cast<SPClipPath *>(parent)) {
+ parent = parent->parent;
+ }
+ return parent;
+}
+
unsigned SPItem::display_key_new(unsigned numkeys)
{
static unsigned dkey = 0;
diff --git a/src/object/sp-item.h b/src/object/sp-item.h
index 36af02edc..88fca9779 100644
--- a/src/object/sp-item.h
+++ b/src/object/sp-item.h
@@ -290,6 +290,10 @@ public:
*/
bool isFiltered() const;
+ SPObject* isInMask() const;
+
+ SPObject* isInClipPath() const;
+
void invoke_print(SPPrintContext *ctx);
/**
diff --git a/src/object/sp-line.cpp b/src/object/sp-line.cpp
index 09ffd1f17..2ba633972 100644
--- a/src/object/sp-line.cpp
+++ b/src/object/sp-line.cpp
@@ -150,7 +150,7 @@ void SPLine::set_shape() {
c->moveto(this->x1.computed, this->y1.computed);
c->lineto(this->x2.computed, this->y2.computed);
- this->setCurveInsync(c, TRUE); // *_insync does not call update, avoiding infinite recursion when set_shape is called by update
+ this->setCurveInsync(c); // *_insync does not call update, avoiding infinite recursion when set_shape is called by update
this->setCurveBeforeLPE(c);
// LPE's cannot be applied to lines. (the result can (generally) not be represented as SPLine)
diff --git a/src/object/sp-lpe-item.cpp b/src/object/sp-lpe-item.cpp
index f3cc841fb..e0ef848af 100644
--- a/src/object/sp-lpe-item.cpp
+++ b/src/object/sp-lpe-item.cpp
@@ -41,6 +41,7 @@
#include "svg/svg.h"
#include "sp-clippath.h"
#include "sp-mask.h"
+#include "sp-rect.h"
#include "ui/tools-switch.h"
#include "ui/tools/node-tool.h"
@@ -48,9 +49,8 @@
static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
-
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
-static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths);
+static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths, bool force = false);
typedef std::list<std::string> HRefList;
static std::string patheffectlist_svg_string(PathEffectList const & list);
@@ -179,11 +179,11 @@ void SPLPEItem::update(SPCtx* ctx, unsigned int flags) {
}
void SPLPEItem::modified(unsigned int flags) {
- if (SP_IS_GROUP(this) && (flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_USER_MODIFIED_FLAG_B)) {
- sp_lpe_item_update_patheffect(this, true, true);
- }
-
-// SPItem::onModified(flags);
+ //TODO: remove if no regressions
+ //stop update when modified and make the effect update on the LPE transform method if the effect require it
+ //if (SP_IS_GROUP(this) && (flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_USER_MODIFIED_FLAG_B)) {
+ // sp_lpe_item_update_patheffect(this, true, true);
+ //}
}
Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags) {
@@ -200,113 +200,85 @@ Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape
return repr;
}
+
/**
* returns true when LPE was successful.
*/
-bool SPLPEItem::hasPathEffectOnClipOrMask() const
-{
- bool has_clipormask_lpe = false;
+bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) {
+
+ if (!curve) {
+ return false;
+ }
+
if (this->hasPathEffect() && this->pathEffectsEnabled()) {
for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
{
LivePathEffectObject *lpeobj = (*it)->lpeobject;
if (!lpeobj) {
+ /** \todo Investigate the cause of this.
+ * For example, this happens when copy pasting an object with LPE applied. Probably because the object is pasted while the effect is not yet pasted to defs, and cannot be found.
+ */
+ g_warning("SPLPEItem::performPathEffect - NULL lpeobj in list!");
return false;
}
Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
- if (!lpe) {
+ if(!performOnePathEffect(curve, current, lpe, is_clip_or_mask)) {
return false;
}
- if (lpe->isVisible()) {
- if (lpe->acceptsNumClicks() > 0 && !lpe->isReady()) {
- return false;
- }
- if (lpe->apply_to_clippath_and_mask) {
- has_clipormask_lpe = true;
- }
- }
}
}
- return has_clipormask_lpe;
-}
-
-bool SPLPEItem::hasPathEffectOnClipOrMaskRecursive() const
-{
- if (parent && SP_IS_LPE_ITEM(parent)) {
- return hasPathEffectOnClipOrMask() || SP_LPE_ITEM(parent)->hasPathEffectOnClipOrMaskRecursive();
- }
- else {
- return hasPathEffectOnClipOrMask();
- }
+ return true;
}
/**
* returns true when LPE was successful.
*/
-bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) {
-
- if (!curve) {
+bool SPLPEItem::performOnePathEffect(SPCurve *curve, SPShape *current, Inkscape::LivePathEffect::Effect *lpe, bool is_clip_or_mask) {
+ if (!lpe) {
+ /** \todo Investigate the cause of this.
+ * Not sure, but I think this can happen when an unknown effect type is specified...
+ */
+ g_warning("SPLPEItem::performPathEffect - lpeobj with invalid lpe in the stack!");
return false;
}
- bool has_clipormask_lpe = false;
- if (this->hasPathEffect() && this->pathEffectsEnabled()) {
- for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
- {
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
- if (!lpeobj) {
- /** \todo Investigate the cause of this.
- * For example, this happens when copy pasting an object with LPE applied. Probably because the object is pasted while the effect is not yet pasted to defs, and cannot be found.
- */
- g_warning("SPLPEItem::performPathEffect - NULL lpeobj in list!");
- return false;
+ if (lpe->isVisible()) {
+ if (lpe->acceptsNumClicks() > 0 && !lpe->isReady()) {
+ // if the effect expects mouse input before being applied and the input is not finished
+ // yet, we don't alter the path
+ return false;
+ }
+ //if is not clip or mask or LPE apply to clip and mask
+ if (!(is_clip_or_mask && !lpe->apply_to_clippath_and_mask)) {
+ lpe->setCurrentShape(current);
+ if (!SP_IS_GROUP(this)) {
+ lpe->pathvector_before_effect = curve->get_pathvector();
}
- Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
- if (!lpe) {
- /** \todo Investigate the cause of this.
- * Not sure, but I think this can happen when an unknown effect type is specified...
- */
- g_warning("SPLPEItem::performPathEffect - lpeobj with invalid lpe in the stack!");
- return false;
+ // To Calculate BBox on shapes and nested LPE
+ current->setCurveInsync(curve);
+ // Groups have their doBeforeEffect called elsewhere
+ if (!SP_IS_GROUP(this) && !is_clip_or_mask) {
+ lpe->doBeforeEffect_impl(this);
}
- if (lpe->isVisible()) {
- if (lpe->acceptsNumClicks() > 0 && !lpe->isReady()) {
- // if the effect expects mouse input before being applied and the input is not finished
- // yet, we don't alter the path
- return false;
- }
- if (lpe->apply_to_clippath_and_mask) {
- has_clipormask_lpe = true;
- }
- 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);
- }
- catch (std::exception & e) {
- g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what());
- if (SP_ACTIVE_DESKTOP && SP_ACTIVE_DESKTOP->messageStack()) {
- SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
- _("An exception occurred during execution of the Path Effect.") );
- }
- return false;
- }
- if (!SP_IS_GROUP(this)) {
- lpe->pathvector_after_effect = curve->get_pathvector();
- lpe->doAfterEffect(this);
- }
+ try {
+ lpe->doEffect(curve);
+ }
+
+ catch (std::exception & e) {
+ g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what());
+ if (SP_ACTIVE_DESKTOP && SP_ACTIVE_DESKTOP->messageStack()) {
+ SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
+ _("An exception occurred during execution of the Path Effect.") );
}
+ return false;
+ }
+
+
+ if (!SP_IS_GROUP(this)) {
+ // To have processed the shape to doAfterEffect
+ lpe->pathvector_after_effect = curve->get_pathvector();
+ lpe->doAfterEffect(this);
}
- }
- if(!SP_IS_GROUP(this) && !is_clip_or_mask && has_clipormask_lpe){
- this->applyToClipPath(this);
- this->applyToMask(this);
}
}
return true;
@@ -327,6 +299,7 @@ sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write)
g_message("sp_lpe_item_update_patheffect: %p\n", lpeitem);
#endif
g_return_if_fail (lpeitem != NULL);
+ g_return_if_fail (SP_IS_OBJECT (lpeitem));
g_return_if_fail (SP_IS_LPE_ITEM (lpeitem));
if (!lpeitem->pathEffectsEnabled())
@@ -346,7 +319,6 @@ sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write)
else {
top = lpeitem;
}
-
top->update_patheffect(write);
}
@@ -367,95 +339,98 @@ sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
{
g_return_if_fail(lpeitem != NULL);
- SPMask * mask = lpeitem->mask_ref->getObject();
- if(mask)
- {
- sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(mask->firstChild()));
+ SPClipPath *clip_path = SP_ITEM(lpeitem)->clip_ref->getObject();
+ if(clip_path) {
+ std::vector<SPObject*> clip_path_list = clip_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) {
+ SPLPEItem * clip_data = dynamic_cast<SPLPEItem *>(*iter);
+ sp_lpe_item_create_original_path_recursive(clip_data);
+ }
}
- SPClipPath * clip_path = lpeitem->clip_ref->getObject();
- if(clip_path)
- {
- sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()));
+
+ SPMask *mask_path = SP_ITEM(lpeitem)->mask_ref->getObject();
+ if(mask_path) {
+ std::vector<SPObject*> mask_path_list = mask_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter = mask_path_list.begin(); iter != mask_path_list.end();++iter) {
+ SPLPEItem * mask_data = dynamic_cast<SPLPEItem *>(*iter);
+ sp_lpe_item_create_original_path_recursive(mask_data);
+ }
}
if (SP_IS_GROUP(lpeitem)) {
- std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
+ std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
SPObject *subitem = *iter;
if (SP_IS_LPE_ITEM(subitem)) {
sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem));
}
}
- }
- else if (SP_IS_PATH(lpeitem)) {
- Inkscape::XML::Node *pathrepr = lpeitem->getRepr();
+ } else if (SPPath * path = dynamic_cast<SPPath *>(lpeitem)) {
+ Inkscape::XML::Node *pathrepr = path->getRepr();
if ( !pathrepr->attribute("inkscape:original-d") ) {
pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));
+ path->setCurveBeforeLPE(path->getCurve());
+ }
+ } else if (SPShape * shape = dynamic_cast<SPShape *>(lpeitem)) {
+ if (SPCurve * c_lpe = shape->getCurveBeforeLPE()) {
+ c_lpe->unref();
+ } else {
+ shape->setCurveBeforeLPE(shape->getCurve());
}
}
}
static void
-sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths)
+sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths, bool force)
{
g_return_if_fail(lpeitem != NULL);
- if (SP_IS_GROUP(lpeitem)) {
- if (!lpeitem->hasPathEffectOnClipOrMaskRecursive()) {
- SPMask * mask = lpeitem->mask_ref->getObject();
- if(mask)
- {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths);
- }
- SPClipPath * clip_path = lpeitem->clip_ref->getObject();
- if(clip_path)
- {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths);
- }
+ SPItem *item = dynamic_cast<SPItem *>(lpeitem);
+ if (!item) {
+ return;
+ }
+ SPGroup *group = dynamic_cast<SPGroup*>(lpeitem);
+ SPShape *shape = dynamic_cast<SPShape*>(lpeitem);
+ SPPath *path = dynamic_cast<SPPath *>(lpeitem);
+ SPClipPath *clip_path = item->clip_ref->getObject();
+ if(clip_path) {
+ std::vector<SPObject*> clip_path_list = clip_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) {
+ SPLPEItem* clip_data = dynamic_cast<SPLPEItem*>(*iter);
+ sp_lpe_item_cleanup_original_path_recursive(clip_data, keep_paths, shape && !shape->hasPathEffectRecursive());
}
+ }
+
+ SPMask *mask_path = item->mask_ref->getObject();
+ if(mask_path) {
+ std::vector<SPObject*> mask_path_list = mask_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter = mask_path_list.begin(); iter != mask_path_list.end();++iter) {
+ SPLPEItem* mask_data = dynamic_cast<SPLPEItem*>(*iter);
+ sp_lpe_item_cleanup_original_path_recursive(mask_data, keep_paths, shape && !shape->hasPathEffectRecursive());
+ }
+ }
+
+ if (group) {
std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
- SPObject *subitem = *iter;
- if (SP_IS_LPE_ITEM(subitem)) {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(subitem), keep_paths);
- }
+ SPLPEItem* subitem = dynamic_cast<SPLPEItem*>(*iter);
+ sp_lpe_item_cleanup_original_path_recursive(subitem, keep_paths, false);
}
- } else if (SP_IS_PATH(lpeitem)) {
+ } else if (path) {
Inkscape::XML::Node *repr = lpeitem->getRepr();
- SPMask * mask = lpeitem->mask_ref->getObject();
- if(mask) {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths);
- }
- SPClipPath * clip_path = lpeitem->clip_ref->getObject();
- if(clip_path) {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths);
- }
- mask = dynamic_cast<SPMask *>(lpeitem->parent);
- clip_path = dynamic_cast<SPClipPath *>(lpeitem->parent);
- if ((!lpeitem->hasPathEffectRecursive() && repr->attribute("inkscape:original-d")) ||
- ((mask || clip_path) && !lpeitem->hasPathEffectOnClipOrMaskRecursive() && repr->attribute("inkscape:original-d")))
+ if ((!lpeitem->hasPathEffectRecursive() || force) && repr->attribute("inkscape:original-d"))
{
if (!keep_paths) {
repr->setAttribute("d", repr->attribute("inkscape:original-d"));
}
repr->setAttribute("inkscape:original-d", NULL);
+ path->setCurveBeforeLPE(NULL);
} else {
if (!keep_paths) {
sp_lpe_item_update_patheffect(lpeitem, true, true);
}
}
- } else if (SP_IS_SHAPE(lpeitem)) {
+ } else if (shape) {
Inkscape::XML::Node *repr = lpeitem->getRepr();
- SPMask * mask = lpeitem->mask_ref->getObject();
- if(mask) {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), keep_paths);
- }
- SPClipPath * clip_path = lpeitem->clip_ref->getObject();
- if(clip_path) {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), keep_paths);
- }
- mask = dynamic_cast<SPMask *>(lpeitem->parent);
- clip_path = dynamic_cast<SPClipPath *>(lpeitem->parent);
- if ((!lpeitem->hasPathEffectRecursive() && repr->attribute("d")) ||
- ((mask || clip_path) && !lpeitem->hasPathEffectOnClipOrMaskRecursive() && repr->attribute("d")))
+ if ((!lpeitem->hasPathEffectRecursive() || force) && repr->attribute("d"))
{
if (!keep_paths) {
repr->setAttribute("d", NULL);
@@ -469,6 +444,7 @@ sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem, bool keep_paths)
sp_item_list_to_curves(items, selected, to_select, true);
}
}
+ shape->setCurveBeforeLPE(NULL);
} else {
if (!keep_paths) {
sp_lpe_item_update_patheffect(lpeitem, true, true);
@@ -515,7 +491,7 @@ void SPLPEItem::addPathEffect(std::string value, bool reset)
}
// perform this once when the effect is applied
- lpe->doOnApply(this);
+ lpe->doOnApply_impl(this);
// indicate that all necessary preparations are done and the effect can be performed
lpe->setReady();
@@ -526,16 +502,6 @@ void SPLPEItem::addPathEffect(std::string value, bool reset)
// Apply the path effect
sp_lpe_item_update_patheffect(this, true, true);
- SPMask * mask = mask_ref->getObject();
- if(mask && !hasPathEffectOnClipOrMaskRecursive())
- {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(mask->firstChild()), false);
- }
- SPClipPath * clip_path = clip_ref->getObject();
- if(clip_path && !hasPathEffectOnClipOrMaskRecursive())
- {
- sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(clip_path->firstChild()), false);
- }
//fix bug 1219324
if (SP_ACTIVE_DESKTOP ) {
Inkscape::UI::Tools::ToolBase *ec = SP_ACTIVE_DESKTOP->event_context;
@@ -678,23 +644,6 @@ bool SPLPEItem::hasBrokenPathEffect() const
}
-bool SPLPEItem::hasPathEffect() const
-{
- if (!path_effect_list || path_effect_list->empty()) {
- return false;
- }
-
- // go through the list; if some are unknown or invalid, we are not an LPE item!
- for (PathEffectList::const_iterator it = path_effect_list->begin(); it != path_effect_list->end(); ++it)
- {
- LivePathEffectObject *lpeobj = (*it)->lpeobject;
- if (!lpeobj || !lpeobj->get_lpe()) {
- return false;
- }
- }
-
- return true;
-}
bool SPLPEItem::hasPathEffectOfType(int const type, bool is_ready) const
{
@@ -718,10 +667,69 @@ bool SPLPEItem::hasPathEffectOfType(int const type, bool is_ready) const
return false;
}
+/**
+ * returns true when any LPE apply to clip or mask.
+ */
+bool SPLPEItem::hasPathEffectOnClipOrMask(SPLPEItem * shape) const
+{
+ if (shape->hasPathEffectRecursive()) {
+ return true;
+ }
+ if (!path_effect_list || path_effect_list->empty()) {
+ return false;
+ }
+
+ for (PathEffectList::iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ if (!lpeobj) {
+ continue;
+ }
+ Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
+ if (lpe->apply_to_clippath_and_mask) {
+ return true;
+ }
+ }
+ return false;
+}
+
+/**
+ * returns true when any LPE apply to clip or mask.
+ */
+bool SPLPEItem::hasPathEffectOnClipOrMaskRecursive(SPLPEItem * shape) const
+{
+ SPLPEItem * parent_lpe_item = dynamic_cast<SPLPEItem *>(parent);
+ if (parent_lpe_item) {
+ return hasPathEffectOnClipOrMask(shape) || parent_lpe_item->hasPathEffectOnClipOrMaskRecursive(shape);
+ }
+ else {
+ return hasPathEffectOnClipOrMask(shape);
+ }
+}
+
+bool SPLPEItem::hasPathEffect() const
+{
+ if (!path_effect_list || path_effect_list->empty()) {
+ return false;
+ }
+
+ // go through the list; if some are unknown or invalid, we are not an LPE item!
+ for (PathEffectList::const_iterator it = path_effect_list->begin(); it != path_effect_list->end(); ++it)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ if (!lpeobj || !lpeobj->get_lpe()) {
+ return false;
+ }
+ }
+
+ return true;
+}
+
bool SPLPEItem::hasPathEffectRecursive() const
{
- if (parent && SP_IS_LPE_ITEM(parent)) {
- return hasPathEffect() || SP_LPE_ITEM(parent)->hasPathEffectRecursive();
+ SPLPEItem * parent_lpe_item = dynamic_cast<SPLPEItem *>(parent);
+ if (parent_lpe_item) {
+ return hasPathEffect() || parent_lpe_item->hasPathEffectRecursive();
}
else {
return hasPathEffect();
@@ -729,71 +737,172 @@ bool SPLPEItem::hasPathEffectRecursive() const
}
void
-SPLPEItem::applyToClipPath(SPItem *item)
+SPLPEItem::resetClipPathAndMaskLPE(bool fromrecurse)
{
- SPClipPath *clip_path = item->clip_ref->getObject();
+ if (fromrecurse) {
+ SPGroup* group = dynamic_cast<SPGroup *>(this);
+ SPShape* shape = dynamic_cast<SPShape *>(this);
+ if (group) {
+ std::vector<SPItem*> item_list = sp_item_group_item_list(group);
+ for ( std::vector<SPItem*>::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) {
+ SPLPEItem * subitem = dynamic_cast<SPLPEItem *>(*iter2);
+ if (subitem) {
+ subitem->resetClipPathAndMaskLPE(true);
+ }
+ }
+ } else if (shape) {
+ shape->setCurveInsync( shape->getCurveForEdit());
+ if (!hasPathEffectOnClipOrMaskRecursive(shape)) {
+ shape->getRepr()->setAttribute("inkscape:original-d", NULL);
+ shape->setCurveBeforeLPE(NULL);
+ } else {
+ // make sure there is an original-d for paths!!!
+ sp_lpe_item_create_original_path_recursive(shape);
+ }
+ }
+ return;
+ }
+ SPClipPath *clip_path = this->clip_ref->getObject();
if(clip_path) {
std::vector<SPObject*> clip_path_list = clip_path->childList(true);
for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) {
- SPObject * clip_data = *iter;
- applyToClipPathOrMask(SP_ITEM(clip_data), item);
+ SPGroup* group = dynamic_cast<SPGroup *>(*iter);
+ SPShape* shape = dynamic_cast<SPShape *>(*iter);
+ if (group) {
+ std::vector<SPItem*> item_list = sp_item_group_item_list(group);
+ for ( std::vector<SPItem*>::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) {
+ SPLPEItem * subitem = dynamic_cast<SPLPEItem *>(*iter2);
+ if (subitem) {
+ subitem->resetClipPathAndMaskLPE(true);
+ }
+ }
+ } else if (shape) {
+ shape->setCurveInsync( shape->getCurveForEdit());
+ if (!hasPathEffectOnClipOrMaskRecursive(shape)) {
+ shape->getRepr()->setAttribute("inkscape:original-d", NULL);
+ shape->setCurveBeforeLPE(NULL);
+ } else {
+ // make sure there is an original-d for paths!!!
+ sp_lpe_item_create_original_path_recursive(shape);
+ }
+ }
}
}
- if(SP_IS_GROUP(item)){
- std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item));
- for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
- SPObject *subitem = *iter;
- applyToClipPath(SP_ITEM(subitem));
+ SPMask *mask = this->mask_ref->getObject();
+ if(mask) {
+ std::vector<SPObject*> mask_list = mask->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) {
+ SPGroup* group = dynamic_cast<SPGroup *>(*iter);
+ SPShape* shape = dynamic_cast<SPShape *>(*iter);
+ if (group) {
+ std::vector<SPItem*> item_list = sp_item_group_item_list(group);
+ for ( std::vector<SPItem*>::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) {
+ SPLPEItem * subitem = dynamic_cast<SPLPEItem *>(*iter2);
+ if (subitem) {
+ subitem->resetClipPathAndMaskLPE(true);
+ }
+ }
+ } else if (shape) {
+ shape->setCurveInsync( shape->getCurveForEdit());
+ if (!hasPathEffectOnClipOrMaskRecursive(shape)) {
+ shape->getRepr()->setAttribute("inkscape:original-d", NULL);
+ shape->setCurveBeforeLPE(NULL);
+ } else {
+ // make sure there is an original-d for paths!!!
+ sp_lpe_item_create_original_path_recursive(shape);
+ }
+ }
+ }
+ }
+}
+
+void
+SPLPEItem::applyToClipPath(SPItem* to, Inkscape::LivePathEffect::Effect *lpe)
+{
+ if (lpe && !lpe->apply_to_clippath_and_mask) {
+ return;
+ }
+ SPClipPath *clip_path = to->clip_ref->getObject();
+ if(clip_path) {
+ std::vector<SPObject*> clip_path_list = clip_path->childList(true);
+ for ( std::vector<SPObject*>::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) {
+ SPObject * clip_data = *iter;
+ applyToClipPathOrMask(SP_ITEM(clip_data), to, lpe);
}
}
}
void
-SPLPEItem::applyToMask(SPItem *item)
+SPLPEItem::applyToMask(SPItem* to, Inkscape::LivePathEffect::Effect *lpe)
{
- SPMask *mask = item->mask_ref->getObject();
+ if (lpe && !lpe->apply_to_clippath_and_mask) {
+ return;
+ }
+ SPMask *mask = to->mask_ref->getObject();
if(mask) {
std::vector<SPObject*> mask_list = mask->childList(true);
for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) {
SPObject * mask_data = *iter;
- applyToClipPathOrMask(SP_ITEM(mask_data), item);
- }
- }
- if(SP_IS_GROUP(item)){
- std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(item));
- for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
- SPObject *subitem = *iter;
- applyToMask(SP_ITEM(subitem));
+ applyToClipPathOrMask(SP_ITEM(mask_data), to, lpe);
}
}
}
void
-SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem *item)
+SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem* to, Inkscape::LivePathEffect::Effect *lpe)
{
- if (SP_IS_GROUP(clip_mask)) {
- std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_mask));
+ SPGroup* group = dynamic_cast<SPGroup *>(clip_mask);
+ SPShape* shape = dynamic_cast<SPShape *>(clip_mask);
+ SPLPEItem* tolpe = dynamic_cast<SPLPEItem*>(to);
+ if (group) {
+ std::vector<SPItem*> item_list = sp_item_group_item_list(group);
for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) {
SPItem *subitem = *iter;
- applyToClipPathOrMask(subitem, item);
+ applyToClipPathOrMask(subitem, to, lpe);
}
- } else if (SP_IS_SHAPE(clip_mask)) {
+ } else if (shape) {
SPCurve * c = NULL;
-
- if (SP_IS_PATH(clip_mask)) {
- c = SP_PATH(clip_mask)->get_original_curve();
+ // If item is a SPRect, convert it to path first:
+ if ( dynamic_cast<SPRect *>(shape) ) {
+ SPDesktop *desktop = SP_ACTIVE_DESKTOP;
+ if (desktop) {
+ Inkscape::Selection *sel = desktop->getSelection();
+ if ( sel && !sel->isEmpty() ) {
+ sel->clear();
+ sel->add(SP_ITEM(shape));
+ sel->toCurves();
+ SPItem* item = sel->singleItem();
+ shape = dynamic_cast<SPShape *>(item);
+ if (!shape) {
+ return;
+ }
+ sel->clear();
+ sel->add(this);
+ }
+ }
+ }
+ if (lpe) { //group
+ c = shape->getCurve();
} else {
- c = SP_SHAPE(clip_mask)->getCurve();
+ c = shape->getCurveForEdit();
}
if (c) {
bool success = false;
try {
if(SP_IS_GROUP(this)){
- c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)));
- success = this->performPathEffect(c, SP_SHAPE(clip_mask), true);
- c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse());
+ c->transform(i2anc_affine(SP_GROUP(to), SP_GROUP(this)));
+ if (lpe) {
+ success = this->performOnePathEffect(c, shape, lpe, true);
+ } else {
+ success = this->performPathEffect(c, shape, true);
+ }
+ c->transform(i2anc_affine(SP_GROUP(to), SP_GROUP(this)).inverse());
} else {
- success = this->performPathEffect(c, SP_SHAPE(clip_mask), true);
+ if (lpe) {
+ success = this->performOnePathEffect(c, shape, lpe, true);
+ } else {
+ success = this->performPathEffect(c, SP_SHAPE(clip_mask), true);
+ }
}
} catch (std::exception & e) {
g_warning("Exception during LPE execution. \n %s", e.what());
@@ -804,8 +913,8 @@ SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem *item)
success = false;
}
Inkscape::XML::Node *repr = clip_mask->getRepr();
- // This c check allow to not apply LPE if curve is NULL after performPathEffect used in clone.obgets LPE
if (success && c) {
+ shape->setCurveInsync(c);
gchar *str = sp_svg_write_path(c->get_pathvector());
repr->setAttribute("d", str);
g_free(str);
@@ -815,7 +924,7 @@ SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem *item)
Geom::PathVector pv = sp_svg_read_pathv(value);
SPCurve *oldcurve = new (std::nothrow) SPCurve(pv);
if (oldcurve) {
- SP_SHAPE(clip_mask)->setCurve(oldcurve, TRUE);
+ SP_SHAPE(clip_mask)->setCurve(oldcurve);
oldcurve->unref();
}
}
@@ -823,6 +932,7 @@ SPLPEItem::applyToClipPathOrMask(SPItem *clip_mask, SPItem *item)
if (c) {
c->unref();
}
+ shape->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
}
}
diff --git a/src/object/sp-lpe-item.h b/src/object/sp-lpe-item.h
index 82f3940c1..0e6049d4e 100644
--- a/src/object/sp-lpe-item.h
+++ b/src/object/sp-lpe-item.h
@@ -70,14 +70,14 @@ public:
virtual void update_patheffect(bool write);
- bool hasPathEffectOnClipOrMask() const;
- bool hasPathEffectOnClipOrMaskRecursive() const;
- bool performPathEffect(SPCurve *curve, SPShape *current = NULL, bool is_clip_or_mask = false);
-
+ bool performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask = false);
+ bool performOnePathEffect(SPCurve *curve, SPShape *current, Inkscape::LivePathEffect::Effect *lpe, bool is_clip_or_mask = false);
bool pathEffectsEnabled() const;
bool hasPathEffect() const;
bool hasPathEffectOfType(int const type, bool is_ready = true) const;
bool hasPathEffectRecursive() const;
+ bool hasPathEffectOnClipOrMask(SPLPEItem * shape) const;
+ bool hasPathEffectOnClipOrMaskRecursive(SPLPEItem * shape) const;
Inkscape::LivePathEffect::Effect* getPathEffectOfType(int type);
Inkscape::LivePathEffect::Effect const* getPathEffectOfType(int type) const;
bool hasBrokenPathEffect() const;
@@ -94,9 +94,10 @@ public:
void removeAllPathEffects(bool keep_paths);
void addPathEffect(std::string value, bool reset);
void addPathEffect(LivePathEffectObject * new_lpeobj);
- void applyToMask(SPItem * item);
- void applyToClipPath(SPItem * item);
- void applyToClipPathOrMask(SPItem * clip_mask, SPItem * item);
+ void resetClipPathAndMaskLPE(bool fromrecurse = false);
+ void applyToMask(SPItem* to, Inkscape::LivePathEffect::Effect *lpe = NULL);
+ void applyToClipPath(SPItem* to, Inkscape::LivePathEffect::Effect *lpe = NULL);
+ void applyToClipPathOrMask(SPItem * clip_mask, SPItem* to, Inkscape::LivePathEffect::Effect *lpe = NULL);
bool forkPathEffectsIfNecessary(unsigned int nr_of_allowed_users = 1);
void editNextParamOncanvas(SPDesktop *dt);
diff --git a/src/object/sp-mask.cpp b/src/object/sp-mask.cpp
index b65c145fc..2e764131c 100644
--- a/src/object/sp-mask.cpp
+++ b/src/object/sp-mask.cpp
@@ -115,6 +115,33 @@ void SPMask::set(unsigned int key, const gchar* value) {
}
}
+Geom::OptRect
+SPMask::geometricBounds(Geom::Affine const &transform) {
+ Geom::OptRect bbox;
+
+ for (auto& i: children) {
+ if (SP_IS_ITEM(&i)) {
+ Geom::OptRect tmp = SP_ITEM(&i)->geometricBounds(Geom::Affine(SP_ITEM(&i)->transform) * transform);
+ bbox.unionWith(tmp);
+ }
+ }
+
+ return bbox;
+}
+
+Geom::OptRect
+SPMask::visualBounds(Geom::Affine const &transform) {
+ Geom::OptRect bbox;
+ for (auto& i: children) {
+ if (SP_IS_ITEM(&i)) {
+ Geom::OptRect tmp = SP_ITEM(&i)->visualBounds(transform);
+ bbox.unionWith(tmp);
+ }
+ }
+
+ return bbox;
+}
+
void SPMask::child_added(Inkscape::XML::Node* child, Inkscape::XML::Node* ref) {
/* Invoke SPObjectGroup implementation */
SPObjectGroup::child_added(child, ref);
diff --git a/src/object/sp-mask.h b/src/object/sp-mask.h
index 02d37b82b..26e510830 100644
--- a/src/object/sp-mask.h
+++ b/src/object/sp-mask.h
@@ -47,6 +47,10 @@ public:
Inkscape::DrawingItem *sp_mask_show(Inkscape::Drawing &drawing, unsigned int key);
void sp_mask_hide(unsigned int key);
+ Geom::OptRect geometricBounds(Geom::Affine const &transform);
+
+ Geom::OptRect visualBounds(Geom::Affine const &transform) ;
+
void sp_mask_set_bbox(unsigned int key, Geom::OptRect const &bbox);
protected:
diff --git a/src/object/sp-object.cpp b/src/object/sp-object.cpp
index bc930a430..d3c429c2a 100644
--- a/src/object/sp-object.cpp
+++ b/src/object/sp-object.cpp
@@ -413,7 +413,6 @@ std::vector<SPObject*> SPObject::childList(bool add_ref, Action) {
l.push_back(&child);
}
return l;
-
}
gchar const *SPObject::label() const {
diff --git a/src/object/sp-offset.cpp b/src/object/sp-offset.cpp
index 82e0b4947..2864e88cb 100644
--- a/src/object/sp-offset.cpp
+++ b/src/object/sp-offset.cpp
@@ -361,7 +361,7 @@ void SPOffset::set_shape() {
SPCurve *c = new SPCurve(pv);
g_assert(c != NULL);
- this->setCurveInsync (c, TRUE);
+ this->setCurveInsync (c);
this->setCurveBeforeLPE(c);
c->unref();
@@ -669,7 +669,7 @@ void SPOffset::set_shape() {
SPCurve *c = new SPCurve(pv);
g_assert(c != NULL);
- this->setCurveInsync (c, TRUE);
+ this->setCurveInsync (c);
this->setCurveBeforeLPE(c);
c->unref();
diff --git a/src/object/sp-path.cpp b/src/object/sp-path.cpp
index bad843a05..3c64c09b0 100644
--- a/src/object/sp-path.cpp
+++ b/src/object/sp-path.cpp
@@ -191,13 +191,14 @@ void SPPath::set(unsigned int key, const gchar* value) {
SPCurve *curve = new SPCurve(pv);
if (curve) {
- this->set_original_curve(curve, TRUE, true);
+ this->setCurveBeforeLPE(curve);
curve->unref();
}
} else {
- this->set_original_curve(NULL, TRUE, true);
+ this->setCurveBeforeLPE(NULL);
+
}
-
+ sp_lpe_item_update_patheffect(this, true, true);
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
break;
@@ -207,11 +208,11 @@ void SPPath::set(unsigned int key, const gchar* value) {
SPCurve *curve = new SPCurve(pv);
if (curve) {
- this->setCurve(curve, TRUE);
+ this->setCurve(curve);
curve->unref();
}
} else {
- this->setCurve(NULL, TRUE);
+ this->setCurve(NULL);
}
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
@@ -361,130 +362,6 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) {
return Geom::identity();
}
-
-void SPPath::update_patheffect(bool write) {
- Inkscape::XML::Node *repr = this->getRepr();
-
-#ifdef PATH_VERBOSE
-g_message("sp_path_update_patheffect");
-#endif
-
- if (_curve_before_lpe && hasPathEffectRecursive()) {
- SPCurve *curve = _curve_before_lpe->copy();
- /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe.
- * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- this->setCurveInsync(curve, TRUE);
-
- bool success = this->performPathEffect(curve);
-
- if (success && write) {
- // could also do this->getRepr()->updateRepr(); but only the d attribute needs updating.
-#ifdef PATH_VERBOSE
-g_message("sp_path_update_patheffect writes 'd' attribute");
-#endif
- if (_curve) {
- gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
- repr->setAttribute("d", str);
- g_free(str);
- } else {
- repr->setAttribute("d", NULL);
- }
- } else if (!success) {
- // LPE was unsuccessful. Read the old '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);
- oldcurve->unref();
- }
- }
- }
-
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
- curve->unref();
- }
-}
-
-
-/**
- * Adds a original_curve to the path. If owner is specified, a reference
- * will be made, otherwise the curve will be copied into the path.
- * Any existing curve in the path will be unreferenced first.
- * This routine triggers reapplication of an effect if present
- * and also triggers a request to update the display. Does not write
- * result to XML when write=false.
- */
-void SPPath::set_original_curve (SPCurve *new_curve, unsigned int owner, bool write)
-{
- if (_curve_before_lpe) {
- _curve_before_lpe = _curve_before_lpe->unref();
- }
-
- if (new_curve) {
- if (owner) {
- _curve_before_lpe = new_curve->ref();
- } else {
- _curve_before_lpe = new_curve->copy();
- }
- }
-
- sp_lpe_item_update_patheffect(this, true, write);
- requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
-}
-
-/**
- * Return duplicate of _curve_before_lpe (if any exists) or NULL if there is no curve
- */
-SPCurve * SPPath::get_original_curve () const
-{
- if (_curve_before_lpe) {
- return _curve_before_lpe->copy();
- }
-
- return NULL;
-}
-
-/**
- * Return duplicate of edittable curve which is _curve_before_lpe if it exists or
- * shape->curve if not.
- */
-SPCurve* SPPath::get_curve_for_edit () const
-{
- if (_curve_before_lpe && hasPathEffectRecursive()) {
- return get_original_curve();
- } else {
- return getCurve();
- }
-}
-
-/**
- * Returns \c _curve_before_lpe if it is not NULL and a valid LPE is applied or
- * \c curve if not.
- */
-const SPCurve* SPPath::get_curve_reference () const
-{
- if (_curve_before_lpe && hasPathEffectRecursive()) {
- return _curve_before_lpe;
- } else {
- return _curve;
- }
-}
-
-/**
- * Returns \c _curve_before_lpe if it is not NULL and a valid LPE is applied or \c curve if not.
- * \todo should only be available to class friends!
- */
-SPCurve* SPPath::get_curve ()
-{
- if (_curve_before_lpe && hasPathEffectRecursive()) {
- return _curve_before_lpe;
- } else {
- return _curve;
- }
-}
-
/*
Local Variables:
mode:c++
diff --git a/src/object/sp-path.h b/src/object/sp-path.h
index 0530a396a..3402938a1 100644
--- a/src/object/sp-path.h
+++ b/src/object/sp-path.h
@@ -30,22 +30,11 @@ class SPCurve;
*/
class SPPath : public SPShape {
public:
- SPPath();
- virtual ~SPPath();
+ SPPath();
+ virtual ~SPPath();
int nodesInPath() const;
-
- // still in lowercase because the names should be clearer on whether curve, curve->copy or curve-ref is returned.
- void set_original_curve (SPCurve *curve, unsigned int owner, bool write);
- SPCurve* get_original_curve () const;
- SPCurve* get_curve_for_edit () const;
- const SPCurve* get_curve_reference() const;
-
-public: // should be made protected
- SPCurve* get_curve();
friend class SPConnEndPair;
-
-public:
SPConnEndPair connEndPair;
virtual void build(SPDocument *document, Inkscape::XML::Node *repr);
@@ -59,9 +48,6 @@ public:
virtual char* description() const;
virtual Geom::Affine set_transform(Geom::Affine const &transform);
virtual void convert_to_guides() const;
-
- virtual void update_patheffect(bool write);
-
private:
SPStyleSrc d_source; // Source of 'd' value, saved for output.
};
diff --git a/src/object/sp-polygon.cpp b/src/object/sp-polygon.cpp
index 14fd104b3..b2a0c1480 100644
--- a/src/object/sp-polygon.cpp
+++ b/src/object/sp-polygon.cpp
@@ -157,7 +157,7 @@ void SPPolygon::set(unsigned int key, const gchar* value) {
curve->closepath();
}
- this->setCurve(curve, TRUE);
+ this->setCurve(curve);
curve->unref();
break;
}
diff --git a/src/object/sp-polyline.cpp b/src/object/sp-polyline.cpp
index 29054f934..3be4700eb 100644
--- a/src/object/sp-polyline.cpp
+++ b/src/object/sp-polyline.cpp
@@ -91,7 +91,7 @@ void SPPolyLine::set(unsigned int key, const gchar* value) {
}
}
- this->setCurve(curve, TRUE);
+ this->setCurve(curve);
curve->unref();
break;
}
diff --git a/src/object/sp-rect.cpp b/src/object/sp-rect.cpp
index 88dad5354..f21dafd54 100644
--- a/src/object/sp-rect.cpp
+++ b/src/object/sp-rect.cpp
@@ -198,8 +198,8 @@ const char* SPRect::displayName() const {
void SPRect::set_shape() {
if ((this->height.computed < 1e-18) || (this->width.computed < 1e-18)) {
- this->setCurveInsync( NULL, TRUE);
- this->setCurveBeforeLPE( NULL );
+ this->setCurveInsync(NULL);
+ this->setCurveBeforeLPE(NULL);
return;
}
@@ -265,7 +265,7 @@ void SPRect::set_shape() {
}
c->closepath();
- this->setCurveInsync(c, true);
+ this->setCurveInsync(c);
this->setCurveBeforeLPE(c);
// LPE is not applied because result can generally not be represented as SPRect
diff --git a/src/object/sp-shape.cpp b/src/object/sp-shape.cpp
index 9edf03cbf..07416650e 100644
--- a/src/object/sp-shape.cpp
+++ b/src/object/sp-shape.cpp
@@ -37,7 +37,8 @@
#include "sp-path.h"
#include "preferences.h"
#include "attributes.h"
-
+#include "svg/svg.h"
+#include "svg/path-string.h"
#include "live_effects/lpeobject.h"
#include "helper/mathfns.h" // for triangle_area()
@@ -416,7 +417,7 @@ void SPShape::modified(unsigned int flags) {
Geom::OptRect SPShape::bbox(Geom::Affine const &transform, SPItem::BBoxType bboxtype) const {
Geom::OptRect bbox;
- if (!this->_curve) {
+ if (!this->_curve || this->_curve->get_pathvector().empty()) {
return bbox;
}
@@ -738,6 +739,38 @@ void SPShape::print(SPPrintContext* ctx) {
}
}
+void SPShape::update_patheffect(bool write)
+{
+ if (SPCurve *c_lpe = this->getCurveForEdit()) {
+ /* if a path has an lpeitem applied, then reset the curve to the _curve_before_lpe.
+ * This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
+ this->setCurveInsync(c_lpe);
+ this->resetClipPathAndMaskLPE();
+ bool success = false;
+ if (hasPathEffect() && pathEffectsEnabled()) {
+ success = this->performPathEffect(c_lpe, SP_SHAPE(this));
+ if (success) {
+ this->setCurveInsync(c_lpe);
+ this->applyToClipPath(this);
+ this->applyToMask(this);
+ }
+ }
+
+ if (write && success) {
+ Inkscape::XML::Node *repr = this->getRepr();
+ if (c_lpe != NULL) {
+ gchar *str = sp_svg_write_path(c_lpe->get_pathvector());
+ repr->setAttribute("d", str);
+ g_free(str);
+ } else {
+ repr->setAttribute("d", NULL);
+ }
+ }
+ c_lpe->unref();
+ this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
+ }
+}
+
Inkscape::DrawingItem* SPShape::show(Inkscape::Drawing &drawing, unsigned int /*key*/, unsigned int /*flags*/) {
// std::cout << "SPShape::show(): " << (getId()?getId():"null") << std::endl;
Inkscape::DrawingShape *s = new Inkscape::DrawingShape(drawing);
@@ -995,67 +1028,93 @@ void SPShape::setCurve(SPCurve *new_curve, unsigned int owner)
this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
+
/**
* Sets _curve_before_lpe to refer to the curve.
*/
void
-SPShape::setCurveBeforeLPE (SPCurve *new_curve)
+SPShape::setCurveBeforeLPE(SPCurve *new_curve, unsigned int owner)
{
if (_curve_before_lpe) {
_curve_before_lpe = _curve_before_lpe->unref();
}
if (new_curve) {
- _curve_before_lpe = new_curve->ref();
+ if (owner) {
+ _curve_before_lpe = new_curve->ref();
+ } else {
+ _curve_before_lpe = new_curve->copy();
+ }
}
}
/**
- * Return duplicate of curve (if any exists) or NULL if there is no curve
+ * Same as sp_shape_set_curve but without updating the display
*/
-SPCurve * SPShape::getCurve() const
+void SPShape::setCurveInsync(SPCurve *new_curve, unsigned int owner)
{
if (_curve) {
- return _curve->copy();
+ _curve = _curve->unref();
}
- return NULL;
+ if (new_curve) {
+ if (owner) {
+ _curve = new_curve->ref();
+ } else {
+ _curve = new_curve->copy();
+ }
+ }
}
+
/**
- * Return duplicate of curve *before* LPE (if any exists) or NULL if there is no curve
+ * Return curve (if any exists) or NULL if there is no curve
+* if owner == 0 return a copy
*/
-SPCurve * SPShape::getCurveBeforeLPE() const
+SPCurve * SPShape::getCurve(unsigned int owner) const
{
- if (hasPathEffectRecursive()) {
- if (_curve_before_lpe) {
- return this->_curve_before_lpe->copy();
- }
- } else {
- if (_curve) {
- return _curve->copy();
+ if (_curve) {
+ if(owner) {
+ return _curve;
}
+ return _curve->copy();
}
return NULL;
}
/**
- * Same as sp_shape_set_curve but without updating the display
+ * Return curve *before* LPE (if any exists) or NULL if there is no curve
+ * If force is set allow return curve_before_lpe even if not
+ * has path effect like in clips and mask
+ * if owner == 0 return a copy
*/
-void SPShape::setCurveInsync(SPCurve *new_curve, unsigned int owner)
+SPCurve * SPShape::getCurveBeforeLPE(unsigned int owner) const
{
- if (_curve) {
- _curve = _curve->unref();
- }
+ if (_curve_before_lpe) {
+ if (owner) {
+ return _curve_before_lpe;
+ }
+ return _curve_before_lpe->copy();
+ }
+ return NULL;
+}
- if (new_curve) {
+/**
+ * Return curve for edit
+ * If force is set allow return curve_before_lpe even if not
+ * has path effect like in clips and mask
+ * if owner == 0 return a copy
+ */
+SPCurve * SPShape::getCurveForEdit(unsigned int owner) const
+{
+ if (_curve_before_lpe) {
if (owner) {
- _curve = new_curve->ref();
- } else {
- _curve = new_curve->copy();
+ return _curve_before_lpe;
}
+ return _curve_before_lpe->copy();
}
+ return getCurve(owner);
}
void SPShape::snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const {
diff --git a/src/object/sp-shape.h b/src/object/sp-shape.h
index fe9d03275..be097e390 100644
--- a/src/object/sp-shape.h
+++ b/src/object/sp-shape.h
@@ -39,14 +39,16 @@ public:
SPShape();
virtual ~SPShape();
- SPCurve * getCurve () const;
- SPCurve * getCurveBeforeLPE () const;
- void setCurve (SPCurve *curve, unsigned int owner);
- void setCurveInsync (SPCurve *curve, unsigned int owner);
- void setCurveBeforeLPE (SPCurve *curve);
+ SPCurve * getCurve (unsigned int owner = FALSE) const;
+ SPCurve * getCurveBeforeLPE (unsigned int owner = FALSE) const;
+ SPCurve * getCurveForEdit (unsigned int owner = FALSE) const;
+ void setCurve (SPCurve *curve, unsigned int owner = TRUE);
+ void setCurveBeforeLPE (SPCurve *new_curve, unsigned int owner = TRUE);
+ void setCurveInsync (SPCurve *curve, unsigned int owner = TRUE);
int hasMarkers () const;
int numberOfMarkers (int type) const;
+
public: // temporarily public, until SPPath is properly classed, etc.
SPCurve *_curve_before_lpe;
SPCurve *_curve;
@@ -73,6 +75,7 @@ public:
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
virtual void set_shape();
+ virtual void update_patheffect(bool write);
};
diff --git a/src/object/sp-spiral.cpp b/src/object/sp-spiral.cpp
index a84fc6041..7a449807d 100644
--- a/src/object/sp-spiral.cpp
+++ b/src/object/sp-spiral.cpp
@@ -196,24 +196,6 @@ void SPSpiral::update(SPCtx *ctx, guint flags) {
SPShape::update(ctx, flags);
}
-void SPSpiral::update_patheffect(bool write) {
- this->set_shape(true);
-
- if (write) {
- Inkscape::XML::Node *repr = this->getRepr();
-
- if ( this->_curve != NULL ) {
- gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
- repr->setAttribute("d", str);
- g_free(str);
- } else {
- repr->setAttribute("d", NULL);
- }
- }
-
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
-}
-
const char* SPSpiral::displayName() const {
return _("Spiral");
}
@@ -310,7 +292,7 @@ void SPSpiral::fitAndDraw(SPCurve* c, double dstep, Geom::Point darray[], Geom::
g_assert (is_unit_vector (hat2));
}
-void SPSpiral::set_shape(bool force) {
+void SPSpiral::set_shape() {
if (hasBrokenPathEffect()) {
g_warning ("The spiral shape has unknown LPE on it! Convert to path to make it editable preserving the appearance; editing it as spiral will remove the bad LPE");
@@ -318,7 +300,7 @@ void SPSpiral::set_shape(bool force) {
// unconditionally read the curve from d, if any, to preserve appearance
Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d"));
SPCurve *cold = new SPCurve(pv);
- this->setCurveInsync( cold, TRUE);
+ this->setCurveInsync(cold);
this->setCurveBeforeLPE( cold );
cold->unref();
}
@@ -363,28 +345,22 @@ void SPSpiral::set_shape(bool force) {
this->fitAndDraw(c, (1.0 - t) / (SAMPLE_SIZE - 1.0), darray, hat1, hat2, &t);
}
- /* Reset the shape'scurve to the "original_curve"
+ /* Reset the shape's curve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- if(this->getCurveBeforeLPE()) {
- if(!force && this->getCurveBeforeLPE()->get_pathvector() == c->get_pathvector()) {
- c->unref();
- return;
+ SPCurve * before = this->getCurveBeforeLPE();
+ if (before || this->hasPathEffectRecursive()) {
+ if (!before || before->get_pathvector() != c->get_pathvector()){
+ this->setCurveBeforeLPE(c);
+ this->update_patheffect(false);
+ } else {
+ this->setCurveBeforeLPE(c);
}
+ } else {
+ this->setCurveInsync(c);
}
- setCurveInsync( c, TRUE);
- setCurveBeforeLPE( c );
-
- if (hasPathEffect() && pathEffectsEnabled()) {
- SPCurve *c_lpe = c->copy();
- bool success = this->performPathEffect(c_lpe);
-
- if (success) {
- this->setCurveInsync( c_lpe, TRUE);
- }
-
- c_lpe->unref();
+ if (before) {
+ before->unref();
}
-
c->unref();
}
diff --git a/src/object/sp-spiral.h b/src/object/sp-spiral.h
index ebf4c9e28..138eae914 100644
--- a/src/object/sp-spiral.h
+++ b/src/object/sp-spiral.h
@@ -70,8 +70,7 @@ public:
virtual const char* displayName() const;
virtual char* description() const;
- virtual void set_shape(bool force = false);
- virtual void update_patheffect(bool write);
+ virtual void set_shape();
private:
Geom::Point getTangent(double t) const;
diff --git a/src/object/sp-star.cpp b/src/object/sp-star.cpp
index 9844df98a..097b5d989 100644
--- a/src/object/sp-star.cpp
+++ b/src/object/sp-star.cpp
@@ -223,23 +223,6 @@ void SPStar::update(SPCtx *ctx, guint flags) {
SPShape::update(ctx, flags);
}
-void SPStar::update_patheffect(bool write) {
- this->set_shape(true);
-
- if (write) {
- Inkscape::XML::Node *repr = this->getRepr();
-
- if ( this->_curve != NULL ) {
- gchar *str = sp_svg_write_path(this->_curve->get_pathvector());
- repr->setAttribute("d", str);
- g_free(str);
- } else {
- repr->setAttribute("d", NULL);
- }
- }
-
- this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
-}
const char* SPStar::displayName() const {
if (this->flatsided == false)
@@ -364,7 +347,7 @@ sp_star_get_curvepoint (SPStar *star, SPStarPoint point, gint index, bool previ)
#define NEXT false
#define PREV true
-void SPStar::set_shape(bool force) {
+void SPStar::set_shape() {
// perhaps we should convert all our shapes into LPEs without source path
// and with knotholders for parameters, then this situation will be handled automatically
// by disabling the entire stack (including the shape LPE)
@@ -375,7 +358,7 @@ void SPStar::set_shape(bool force) {
// unconditionally read the curve from d, if any, to preserve appearance
Geom::PathVector pv = sp_svg_read_pathv(this->getRepr()->attribute("d"));
SPCurve *cold = new SPCurve(pv);
- this->setCurveInsync( cold, TRUE);
+ this->setCurveInsync(cold);
this->setCurveBeforeLPE(cold);
cold->unref();
}
@@ -445,28 +428,22 @@ void SPStar::set_shape(bool force) {
c->closepath();
- /* Reset the shape'scurve to the "original_curve"
+ /* Reset the shape's curve to the "original_curve"
* This is very important for LPEs to work properly! (the bbox might be recalculated depending on the curve in shape)*/
- if(this->getCurveBeforeLPE()) {
- if(!force && this->getCurveBeforeLPE()->get_pathvector() == c->get_pathvector()) {
- c->unref();
- return;
+ SPCurve * before = this->getCurveBeforeLPE();
+ if (before || this->hasPathEffectRecursive()) {
+ if (!before || before->get_pathvector() != c->get_pathvector()){
+ this->setCurveBeforeLPE(c);
+ this->update_patheffect(false);
+ } else {
+ this->setCurveBeforeLPE(c);
}
+ } else {
+ this->setCurveInsync(c);
}
- this->setCurveInsync( c, TRUE);
- this->setCurveBeforeLPE( c );
-
- if (hasPathEffect() && pathEffectsEnabled()) {
- SPCurve *c_lpe = c->copy();
- bool success = this->performPathEffect(c_lpe);
-
- if (success) {
- this->setCurveInsync( c_lpe, TRUE);
- }
-
- c_lpe->unref();
+ if (before) {
+ before->unref();
}
-
c->unref();
}
diff --git a/src/object/sp-star.h b/src/object/sp-star.h
index 4519de869..86f3e8ef9 100644
--- a/src/object/sp-star.h
+++ b/src/object/sp-star.h
@@ -54,8 +54,7 @@ public:
virtual char* description() const;
virtual void snappoints(std::vector<Inkscape::SnapCandidatePoint> &p, Inkscape::SnapPreferences const *snapprefs) const;
- virtual void update_patheffect(bool write);
- virtual void set_shape(bool force = false);
+ virtual void set_shape();
virtual Geom::Affine set_transform(Geom::Affine const& xform);
};