From b5d3bcd190a8b4c95613eeb82e2b768b08b693ce Mon Sep 17 00:00:00 2001 From: Jabiertxo Arraiza Cenoz Date: Wed, 13 Sep 2017 17:10:44 +0200 Subject: Fixes for clone original LPE --- src/live_effects/lpe-fill-between-many.cpp | 122 ++++++++++++++++++----- src/live_effects/lpe-fill-between-many.h | 16 ++- src/live_effects/parameter/originalpatharray.cpp | 35 ++++--- src/live_effects/parameter/originalpatharray.h | 7 +- src/selection-chemistry.cpp | 6 +- src/sp-path.cpp | 1 + 6 files changed, 137 insertions(+), 50 deletions(-) (limited to 'src') diff --git a/src/live_effects/lpe-fill-between-many.cpp b/src/live_effects/lpe-fill-between-many.cpp index 8b5cb9b95..e380ca2dd 100644 --- a/src/live_effects/lpe-fill-between-many.cpp +++ b/src/live_effects/lpe-fill-between-many.cpp @@ -6,10 +6,14 @@ #include "live_effects/lpe-fill-between-many.h" - +#include "live_effects/lpeobject.h" +#include "xml/node.h" #include "display/curve.h" +#include "inkscape.h" +#include "selection.h" #include "sp-shape.h" #include "sp-text.h" +#include "sp-defs.h" #include "svg/svg.h" // TODO due to internal breakage in glibmm headers, this must be last: #include @@ -17,25 +21,31 @@ namespace Inkscape { namespace LivePathEffect { +static const Util::EnumData FilllpemethodData[] = { + { FLM_NONE, N_("Without LPE"), "none" }, + { FLM_PARTIAL, N_("Spiro/BSpline"), "partial" }, + { FLM_ALL, N_("All LPE"), "all" } +}; +static const Util::EnumDataConverter FLMConverter(FilllpemethodData, FLM_END); + LPEFillBetweenMany::LPEFillBetweenMany(LivePathEffectObject *lpeobject) : Effect(lpeobject), linked_paths(_("Linked path:"), _("Paths from which to take the original path data"), "linkedpaths", &wr, this), - original_visible(_("Original path visible"), _("Original path visibled"), "original_visible", &wr, this, true), - original_reversed(_("Original path reversed"), _("Reverse original path"), "original_reversed", &wr, this, false), + method(_("LPE's on linked:"), _("LPE's on linked"), "method", FLMConverter, &wr, this, FLM_PARTIAL), fuse(_("Fuse coincident points"), _("Fuse coincident points"), "fuse", &wr, this, false), allow_transforms(_("Allow transforms"), _("Allow transforms"), "allow_transforms", &wr, this, false), join(_("Join subpaths"), _("Join subpaths"), "join", &wr, this, true), - close(_("Close"), _("Close path"), "close", &wr, this, true) + close(_("Close"), _("Close path"), "close", &wr, this, true), + applied("Store the first apply", "", "applied", &wr, this, "false", false) { registerParameter(&linked_paths); - registerParameter(&original_visible); - registerParameter(&original_reversed); + registerParameter(&method); registerParameter(&fuse); registerParameter(&allow_transforms); registerParameter(&join); registerParameter(&close); - transformmultiply = false; - linked_paths.allowOnlyBsplineSpiro(true); + registerParameter(&applied); + previous_method = FLM_END; } LPEFillBetweenMany::~LPEFillBetweenMany() @@ -43,17 +53,70 @@ LPEFillBetweenMany::~LPEFillBetweenMany() } +void LPEFillBetweenMany::doOnApply (SPLPEItem const* lpeitem) +{ + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return; + } + SPLPEItem *lpe_item = const_cast(lpeitem); + SPObject * parent = lpe_item->parent; + if (lpe_item) { + SPShape *shape = dynamic_cast(lpe_item); + if (shape) { + Inkscape::SVGOStringStream os; + if (strcmp(this->lpeobj->getRepr()->attribute("applied"), "false") == 0) { + os << '#' << SP_ITEM(lpe_item)->getId() << ",0,1"; + + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + // create the LPE + Inkscape::XML::Node *lpe_repr = xml_doc->createElement("inkscape:path-effect"); + { + lpe_repr->setAttribute("effect", "fill_between_many"); + lpe_repr->setAttribute("linkedpaths", os.str()); + lpe_repr->setAttribute("applied", "true"); + lpe_repr->setAttribute("method", "partial"); + lpe_repr->setAttribute("allow_transforms", "false"); + document->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to and assigns the 'id' attribute + } + std::string lpe_id_href = std::string("#") + lpe_repr->attribute("id"); + Inkscape::GC::release(lpe_repr); + Inkscape::XML::Node *clone = xml_doc->createElement("svg:path"); + { + clone->setAttribute("d", "M 0 0", false); + // add the new clone to the top of the original's parent + parent->appendChildRepr(clone); + SPObject *clone_obj = document->getObjectById(clone->attribute("id")); + SPLPEItem *clone_lpeitem = dynamic_cast(clone_obj); + if (clone_lpeitem) { + clone_lpeitem->addPathEffect(lpe_id_href, false); + } + } + Inkscape::Selection * sel = SP_ACTIVE_DESKTOP->getSelection(); + sel->set(clone); + Inkscape::GC::release(clone); + lpe_item->removeCurrentPathEffect(false); + } + } + } +} + void LPEFillBetweenMany::doEffect (SPCurve * curve) { - Geom::PathVector res_pathv; - SPItem * firstObj = NULL; - if (original_visible) { - Geom::PathVector original = curve->get_pathvector(); - if (original_reversed) { - original = original.reversed(); + if (previous_method != method) { + if (method == FLM_PARTIAL) { + linked_paths.allowOnlyBsplineSpiro(true); + linked_paths.setFromOriginalD(false); + } else if(method == FLM_NONE) { + linked_paths.allowOnlyBsplineSpiro(false); + linked_paths.setFromOriginalD(true); + } else { + linked_paths.allowOnlyBsplineSpiro(false); + linked_paths.setFromOriginalD(false); } - res_pathv = original; + previous_method = method; } + Geom::PathVector res_pathv; for (std::vector::iterator iter = linked_paths._vector.begin(); iter != linked_paths._vector.end(); ++iter) { SPObject *obj; if ((*iter)->ref.isAttached() && (obj = (*iter)->ref.getObject()) && SP_IS_ITEM(obj) && !(*iter)->_pathvector.empty() && (*iter)->visibled) { @@ -65,36 +128,43 @@ void LPEFillBetweenMany::doEffect (SPCurve * curve) } if (!res_pathv.empty() && join) { - linked_path = linked_path * SP_ITEM(obj)->getRelativeTransform(firstObj); if (!are_near(res_pathv.front().finalPoint(), linked_path.initialPoint(), 0.01) || !fuse) { res_pathv.front().appendNew(linked_path.initialPoint()); } else { linked_path.setInitial(res_pathv.front().finalPoint()); } + if(!allow_transforms) { + Geom::Affine affine = Geom::identity(); + sp_svg_transform_read(SP_ITEM(obj)->getAttribute("transform"), &affine); + linked_path *= affine; + } res_pathv.front().append(linked_path); } else { - firstObj = SP_ITEM(obj); if (close && !join) { linked_path.close(); } + if(!allow_transforms) { + Geom::Affine affine = Geom::identity(); + sp_svg_transform_read(SP_ITEM(obj)->getAttribute("transform"), &affine); + linked_path *= affine; + } res_pathv.push_back(linked_path); } } } + + if(!allow_transforms && sp_lpe_item) { + SP_ITEM(sp_lpe_item)->transform = Geom::identity(); + } + if (!res_pathv.empty() && close) { res_pathv.front().close(); } + if (res_pathv.empty()) { res_pathv = curve->get_pathvector(); } - if(!allow_transforms && !transformmultiply) { - Geom::Affine affine = Geom::identity(); - sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &affine); - res_pathv *= affine.inverse(); - } - if(transformmultiply) { - transformmultiply = false; - } + curve->set_pathvector(res_pathv); } @@ -103,8 +173,6 @@ LPEFillBetweenMany::transform_multiply(Geom::Affine const& postmul, bool set) { if(!allow_transforms && sp_lpe_item) { SP_ITEM(sp_lpe_item)->transform *= postmul.inverse(); - transformmultiply = true; - sp_lpe_item_update_patheffect(sp_lpe_item, false, false); } } diff --git a/src/live_effects/lpe-fill-between-many.h b/src/live_effects/lpe-fill-between-many.h index 5bea53aba..da3a532bf 100644 --- a/src/live_effects/lpe-fill-between-many.h +++ b/src/live_effects/lpe-fill-between-many.h @@ -10,27 +10,37 @@ */ #include "live_effects/effect.h" +#include "live_effects/parameter/enum.h" #include "live_effects/parameter/originalpatharray.h" +#include "live_effects/parameter/hidden.h" namespace Inkscape { namespace LivePathEffect { +enum Filllpemethod { + FLM_NONE, + FLM_PARTIAL, + FLM_ALL, + FLM_END +}; + class LPEFillBetweenMany : public Effect { public: LPEFillBetweenMany(LivePathEffectObject *lpeobject); virtual ~LPEFillBetweenMany(); + virtual void doOnApply (SPLPEItem const* lpeitem); virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual void doEffect (SPCurve * curve); private: OriginalPathArrayParam linked_paths; - BoolParam original_visible; - BoolParam original_reversed; + EnumParam method; BoolParam fuse; BoolParam allow_transforms; BoolParam join; BoolParam close; - bool transformmultiply; + HiddenParam applied; + Filllpemethod previous_method; private: LPEFillBetweenMany(const LPEFillBetweenMany&); LPEFillBetweenMany& operator=(const LPEFillBetweenMany&); diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp index 13bd23634..0b1eb4802 100644 --- a/src/live_effects/parameter/originalpatharray.cpp +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -326,28 +326,25 @@ OriginalPathArrayParam::on_link_button_click() if (pathsid.empty()) { return; } + bool foundOne = false; Inkscape::SVGOStringStream os; + for (std::vector::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + if (foundOne) { + os << "|"; + } else { + foundOne = true; + } + os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0") << "," << ((*iter)->visibled ? "1" : "0"); + } for (auto i=pathsid.begin();i!=pathsid.end();++i) { Glib::ustring pathid = *i; // add '#' at start to make it an uri. pathid.insert(pathid.begin(), '#'); - bool foundOne = false; - for (std::vector::const_iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { - if (foundOne) { - os << "|"; - } else { - foundOne = true; - } - os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0") << "," << ((*iter)->visibled ? "1" : "0"); - } - + if (foundOne) { os << "|"; } - os << pathid.c_str() << ",0"; - if (*i != *(--pathsid.end())) { - os << "|"; - } + os << pathid.c_str() << ",0,1"; } param_write_to_repr(os.str().c_str()); DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, @@ -363,7 +360,7 @@ void OriginalPathArrayParam::unlink(PathAndDirectionAndVisible* to) if (to->href) { g_free(to->href); to->href = NULL; - } + } } void OriginalPathArrayParam::remove_link(PathAndDirectionAndVisible* to) @@ -528,6 +525,14 @@ gchar * OriginalPathArrayParam::param_getSVGValue() const return str; } +void OriginalPathArrayParam::update() +{ + for (std::vector::iterator iter = _vector.begin(); iter != _vector.end(); ++iter) { + SPObject *linked_obj = (*iter)->ref.getObject(); + linked_modified(linked_obj, SP_OBJECT_MODIFIED_FLAG, *iter); + } +} + } /* namespace LivePathEffect */ } /* namespace Inkscape */ diff --git a/src/live_effects/parameter/originalpatharray.h b/src/live_effects/parameter/originalpatharray.h index 51810a5cf..cffa2911f 100644 --- a/src/live_effects/parameter/originalpatharray.h +++ b/src/live_effects/parameter/originalpatharray.h @@ -72,11 +72,11 @@ public: virtual void param_editOncanvas(SPItem * /*item*/, SPDesktop * /*dt*/) {}; /** Disable the canvas indicators of parent class by overriding this method */ virtual void addCanvasIndicators(SPLPEItem const* /*lpeitem*/, std::vector & /*hp_vec*/) {}; - void setFromOriginalD(bool from_original_d){ _from_original_d = from_original_d; }; - void allowOnlyBsplineSpiro(bool allow_only_bspline_spiro){ _allow_only_bspline_spiro = allow_only_bspline_spiro; }; + void setFromOriginalD(bool from_original_d){ _from_original_d = from_original_d; update();}; + void allowOnlyBsplineSpiro(bool allow_only_bspline_spiro){ _allow_only_bspline_spiro = allow_only_bspline_spiro; update();}; std::vector _vector; - + protected: bool _updateLink(const Gtk::TreeIter& iter, PathAndDirectionAndVisible* pd); bool _selectIndex(const Gtk::TreeIter& iter, int* i); @@ -108,6 +108,7 @@ protected: private: bool _from_original_d; bool _allow_only_bspline_spiro; + void update(); OriginalPathArrayParam(const OriginalPathArrayParam&); OriginalPathArrayParam& operator=(const OriginalPathArrayParam&); }; diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index f23a49500..9764563f1 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -2915,7 +2915,7 @@ void ObjectSet::cloneOriginal() } /** -* This creates a new path, applies the Original Path LPE, and has it refer to the selection. +* This applies the Fill Between Many LPE, and has it refer to the selection. */ void ObjectSet::cloneOriginalPathLPE(bool allow_transforms) { @@ -2942,7 +2942,9 @@ void ObjectSet::cloneOriginalPathLPE(bool allow_transforms) { lpe_repr->setAttribute("effect", "fill_between_many"); lpe_repr->setAttribute("linkedpaths", os.str()); - lpe_repr->setAttribute("original_visible", "false"); + lpe_repr->setAttribute("applied", "true"); + gchar const *method_str = allow_transforms ? "all" : "partial"; + lpe_repr->setAttribute("method", method_str); gchar const *allow_transforms_str = allow_transforms ? "true" : "false"; lpe_repr->setAttribute("allow_transforms", allow_transforms_str); document()->getDefs()->getRepr()->addChild(lpe_repr, NULL); // adds to and assigns the 'id' attribute diff --git a/src/sp-path.cpp b/src/sp-path.cpp index bb76eb73f..0cf2a5f3e 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -299,6 +299,7 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) { // if path has this 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 this->adjust_livepatheffect(transform); + this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); return transform; } else { _curve_before_lpe->transform(transform); -- cgit v1.2.3