From 82b78fb84295ba3d512191725b8d4b27859772c3 Mon Sep 17 00:00:00 2001 From: Johan Engelen Date: Sat, 15 May 2010 01:08:45 +0200 Subject: [PATCH] fix bug when forking LPE stack --- src/live_effects/lpeobject.cpp | 9 ++++---- src/sp-item.cpp | 38 +++++++++++++++++++++++----------- src/sp-lpe-item.cpp | 3 +++ 3 files changed, 34 insertions(+), 16 deletions(-) diff --git a/src/live_effects/lpeobject.cpp b/src/live_effects/lpeobject.cpp index ec0dee0be..be5d618f2 100644 --- a/src/live_effects/lpeobject.cpp +++ b/src/live_effects/lpeobject.cpp @@ -252,11 +252,12 @@ LivePathEffectObject::fork_private_if_necessary(unsigned int nr_of_allowed_users if (SP_OBJECT_HREFCOUNT(this) > nr_of_allowed_users) { SPDocument *doc = SP_OBJECT_DOCUMENT(this); Inkscape::XML::Document *xml_doc = sp_document_repr_doc(doc); + Inkscape::XML::Node *dup_repr = SP_OBJECT_REPR (this)->duplicate(xml_doc); - Inkscape::XML::Node *repr = SP_OBJECT_REPR (this)->duplicate(xml_doc); - SP_OBJECT_REPR (SP_DOCUMENT_DEFS (doc))->addChild(repr, NULL); - LivePathEffectObject *lpeobj_new = (LivePathEffectObject *) doc->getObjectByRepr(repr); - Inkscape::GC::release(repr); + SP_OBJECT_REPR (SP_DOCUMENT_DEFS (doc))->addChild(dup_repr, NULL); + LivePathEffectObject *lpeobj_new = LIVEPATHEFFECT( doc->getObjectByRepr(dup_repr) ); + + Inkscape::GC::release(dup_repr); return lpeobj_new; } return this; diff --git a/src/sp-item.cpp b/src/sp-item.cpp index c4411e47d..d6f68fc74 100644 --- a/src/sp-item.cpp +++ b/src/sp-item.cpp @@ -1377,22 +1377,36 @@ sp_item_adjust_livepatheffect (SPItem *item, Geom::Matrix const &postmul, bool s SPLPEItem *lpeitem = SP_LPE_ITEM (item); if ( sp_lpe_item_has_path_effect(lpeitem) ) { + // If one of the path effects is used by 2 or more items, fork it + // so that each object has its own independent copy of the effect. + // Forking messes up the path effect list, so after each fork, + // reload the list and recheck if more forking is required. + bool forked = false; + do { + forked = false; + PathEffectList effect_list = sp_lpe_item_get_effect_list(lpeitem); + for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++) + { + LivePathEffectObject *lpeobj = (*it)->lpeobject; + if (lpeobj) { + LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary(); + if (new_lpeobj != lpeobj) { + sp_lpe_item_replace_path_effect(lpeitem, lpeobj, new_lpeobj); + forked = true; + break; // forked, so break the for-loop and recheck + } + } + } + } while (forked); + + // now that all LPEs are forked_if_necessary, we can apply the transform PathEffectList effect_list = sp_lpe_item_get_effect_list(lpeitem); for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++) { - // If the path effect is used by 2 or more items, fork it - // so that each object has its own independent copy of the effect LivePathEffectObject *lpeobj = (*it)->lpeobject; - if (lpeobj) { - LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary(); - if (new_lpeobj != lpeobj) { - sp_lpe_item_replace_path_effect(lpeitem, lpeobj, new_lpeobj); - } - - if (lpeobj->get_lpe()) { - Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe(); - effect->transform_multiply(postmul, set); - } + if (lpeobj && lpeobj->get_lpe()) { + Inkscape::LivePathEffect::Effect * effect = lpeobj->get_lpe(); + effect->transform_multiply(postmul, set); } } } diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index 1bb500dd2..740690887 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -772,6 +772,9 @@ bool sp_lpe_item_set_current_path_effect(SPLPEItem *lpeitem, Inkscape::LivePathE return false; } +/** + * Note that this method messes up the item's \c PathEffectList. + */ void sp_lpe_item_replace_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * old_lpeobj, LivePathEffectObject * new_lpeobj) { -- 2.30.2