diff options
88 files changed, 1561 insertions, 1278 deletions
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 44b737ad1..bfc280ce6 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -394,9 +394,9 @@ Effect::Effect(LivePathEffectObject *lpeobject) sp_lpe_item(NULL), current_zoom(1), upd_params(true), - sp_shape(NULL), - sp_curve(NULL), + current_shape(NULL), provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden + defaultsopen(false), is_ready(false) // is automatically set to false if providesOwnFlashPaths() is not overridden { registerParameter( dynamic_cast<Parameter *>(&is_visible) ); @@ -469,14 +469,14 @@ Effect::processObjects(LpeAction lpe_action) if (!document) { return; } - for (std::vector<const char *>::iterator el_it = items.begin(); + for (std::vector<Glib::ustring>::iterator el_it = items.begin(); el_it != items.end(); ++el_it) { - const char * id = *el_it; - if (!id) { + Glib::ustring id = *el_it; + if (id.empty()) { return; } SPObject *elemref = NULL; - if ((elemref = document->getObjectById(id))) { + if ((elemref = document->getObjectById(id.c_str()))) { Inkscape::XML::Node * elemnode = elemref->getRepr(); std::vector<SPItem*> item_list; item_list.push_back(SP_ITEM(elemref)); @@ -527,17 +527,6 @@ Effect::processObjects(LpeAction lpe_action) } } -void Effect::setCurrentShape(SPShape * shape){ - if(shape){ - sp_shape = shape; - if (!(sp_curve = sp_shape->getCurveBeforeLPE())) { - // oops - return; - } - pathvector_before_effect = sp_curve->get_pathvector(); - } -} - /** * Is performed each time before the effect is updated. */ @@ -562,21 +551,13 @@ void Effect::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) void Effect::doOnApply_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); - setCurrentShape(shape); doOnApply(lpeitem); } void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); - setCurrentShape(shape); doBeforeEffect(lpeitem); - if (apply_to_clippath_and_mask && SP_IS_GROUP(sp_lpe_item)) { - sp_lpe_item->applyToClipPath(sp_lpe_item); - sp_lpe_item->applyToMask(sp_lpe_item); - } update_helperpath(); } @@ -813,6 +794,9 @@ Effect::newWidget() ++it; } + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -824,7 +808,6 @@ Effect::defaultParamSet() { // use manage here, because after deletion of Effect object, others might still be pointing to this widget. Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox() ); Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox() ); Glib::ustring effectname = (Glib::ustring)Inkscape::LivePathEffect::LPETypeConverter.get_label(effectType()); Glib::ustring effectkey = (Glib::ustring)Inkscape::LivePathEffect::LPETypeConverter.get_key(effectType()); @@ -836,27 +819,28 @@ Effect::defaultParamSet() has_params = true; Parameter * param = *it; Glib::ustring * tip = param->param_getTooltip(); - const gchar * key = param->param_key.c_str(); - const gchar * value = param->param_label.c_str(); - - Glib::ustring pref_path = (Glib::ustring)"/live_effects/" + - effectkey + - (Glib::ustring)"/" + - (Glib::ustring)key; + const gchar * key = param->param_key.c_str(); + const gchar * label = param->param_label.c_str(); + Glib::ustring value = param->param_getSVGValue(); + Glib::ustring defvalue = param->param_getDefaultSVGValue(); + Glib::ustring pref_path = "/live_effects/"; + pref_path += effectkey; + pref_path +="/"; + pref_path += key; bool valid = prefs->getEntry(pref_path).isValid(); const gchar * set_or_upd; - Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("\n"); + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + defvalue + Glib::ustring("\n"); Glib::ustring ove = Glib::ustring(_("<b>Default value overridden:</b> ")) + Glib::ustring(prefs->getString(pref_path)) + Glib::ustring("\n"); if (valid) { set_or_upd = _("Update"); - def = Glib::ustring(_("<b>Default value:</b> <s>")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("</s>\n"); + def = Glib::ustring(_("<b>Default value:</b> <s>")) + defvalue + Glib::ustring("</s>\n"); } else { set_or_upd = _("Set"); ove = Glib::ustring(_("<b>Default value overridden:</b> None\n")); } - Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(param->param_getSVGValue()); + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + value; Gtk::HBox * vbox_param = Gtk::manage( new Gtk::HBox(true) ); - Gtk::Label *parameter_label = Gtk::manage(new Gtk::Label(value, Gtk::ALIGN_START)); + Gtk::Label *parameter_label = Gtk::manage(new Gtk::Label(label, Gtk::ALIGN_START)); parameter_label->set_use_markup(true); parameter_label->set_use_underline(true); Glib::ustring tooltip = Glib::ustring("<b>") + parameter_label->get_text () + Glib::ustring("</b>\n") + param->param_tooltip + Glib::ustring("\n\n"); @@ -865,9 +849,9 @@ Effect::defaultParamSet() vbox_param->pack_start(*parameter_label, true, true, 2); Gtk::Button *set = Gtk::manage(new Gtk::Button((Glib::ustring)set_or_upd)); Gtk::Button *unset = Gtk::manage(new Gtk::Button(Glib::ustring(_("Unset")))); - unset->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, gchar *, gchar *, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::unsetDefaultParam), pref_path, tooltip, param->param_getSVGValue(), param->param_getDefaultSVGValue(), parameter_label, set, unset)); + unset->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, Glib::ustring, Glib::ustring, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::unsetDefaultParam), pref_path, tooltip, value, defvalue, parameter_label, set, unset)); - set->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, gchar *, gchar *, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::setDefaultParam), pref_path, tooltip, param->param_getSVGValue(), param->param_getDefaultSVGValue(), parameter_label, set, unset)); + set->signal_clicked().connect(sigc::bind<Glib::ustring, Glib::ustring, Glib::ustring, Glib::ustring, Gtk::Label *,Gtk::Button *, Gtk::Button *>(sigc::mem_fun(*this, &Effect::setDefaultParam), pref_path, tooltip, value, defvalue, parameter_label, set, unset)); if (!valid) { unset->set_sensitive(false); } @@ -882,11 +866,12 @@ Effect::defaultParamSet() Gtk::Expander * expander = Gtk::manage(new Gtk::Expander(tip)); expander->set_use_markup(true); expander->add(*vbox_expander); - expander->set_expanded(false); - vbox->pack_start(*dynamic_cast<Gtk::Widget *> (expander), true, true, 2); + expander->set_expanded(defaultsopen); + //expander->set_size_request(-1, 90); + expander->property_expanded().signal_changed().connect(sigc::bind<0>(sigc::mem_fun(*this, &Effect::onDefaultsExpanderChanged), expander )); if (has_params) { - Gtk::Widget *vboxwidg = dynamic_cast<Gtk::Widget *>(vbox); - vboxwidg->set_margin_bottom(10); + Gtk::Widget *vboxwidg = dynamic_cast<Gtk::Widget *>(expander); + vboxwidg->set_margin_bottom(5); vboxwidg->set_margin_top(5); return vboxwidg; } else { @@ -895,30 +880,36 @@ Effect::defaultParamSet() } void -Effect::setDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) +Effect::onDefaultsExpanderChanged(Gtk::Expander * expander) +{ + defaultsopen = expander->get_expanded(); +} + +void +Effect::setDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, Glib::ustring value, Glib::ustring defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - prefs->setString(pref_path, (Glib::ustring)value); + prefs->setString(pref_path, value); gchar * label = _("Update"); set->set_label((Glib::ustring)label); unset->set_sensitive(true); - Glib::ustring def = Glib::ustring(_("<b>Default value:</b> <s>")) + Glib::ustring(defvalue) + Glib::ustring("</s>\n"); - Glib::ustring ove = Glib::ustring(_("<b>Default value overridden:</b> ")) + Glib::ustring(value) + Glib::ustring("\n"); - Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(value); + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> <s>")) + defvalue + Glib::ustring("</s>\n"); + Glib::ustring ove = Glib::ustring(_("<b>Default value overridden:</b> ")) + value + Glib::ustring("\n"); + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + value; parameter_label->set_tooltip_markup((tooltip + def + ove + cur).c_str()); } void -Effect::unsetDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) +Effect::unsetDefaultParam(Glib::ustring pref_path, Glib::ustring tooltip, Glib::ustring value, Glib::ustring defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); prefs->remove(pref_path); gchar * label = _("Set"); set->set_label((Glib::ustring)label); unset->set_sensitive(false); - Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + Glib::ustring(defvalue) + Glib::ustring("\n"); + Glib::ustring def = Glib::ustring(_("<b>Default value:</b> ")) + defvalue + Glib::ustring("\n"); Glib::ustring ove = Glib::ustring(_("<b>Default value overridden:</b> None\n")); - Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) + Glib::ustring(value); + Glib::ustring cur = Glib::ustring(_("<b>Current parameter value:</b> ")) +value; parameter_label->set_tooltip_markup((tooltip + def + ove + cur).c_str()); } diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index d0024f877..d162b8bb4 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -10,6 +10,7 @@ #include <glibmm/ustring.h> #include <2geom/forward.h> #include "ui/widget/registry.h" +#include <gtkmm/expander.h> #include "parameter/bool.h" #include "effect-enum.h" @@ -79,8 +80,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); + SPShape * getCurrentShape() const { return current_shape; }; + void setCurrentShape(SPShape * shape) { current_shape = shape; } void processObjects(LpeAction lpe_action); /* @@ -136,7 +137,6 @@ public: bool is_load; bool upd_params; BoolParam is_visible; - SPCurve * sp_curve; Geom::PathVector pathvector_before_effect; Geom::PathVector pathvector_after_effect; protected: @@ -175,17 +175,19 @@ 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. - 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. - std::vector<const char *> items; + SPShape * current_shape; // these get stored in performPathEffects. + std::vector<Glib::ustring> items; double current_zoom; std::vector<Geom::Point> selectedNodesPoints; private: - void setDefaultParam(Glib::ustring pref_path, Glib::ustring par, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); - void unsetDefaultParam(Glib::ustring pref_path, Glib::ustring par, gchar * value, gchar * defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); + void onDefaultsExpanderChanged(Gtk::Expander * expander); + void setDefaultParam(Glib::ustring pref_path, Glib::ustring par, Glib::ustring value, Glib::ustring defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); + void unsetDefaultParam(Glib::ustring pref_path, Glib::ustring par, Glib::ustring value, Glib::ustring defvalue, Gtk::Label *parameter_label, Gtk::Button *set , Gtk::Button *unset); bool provides_own_flash_paths; // if true, the standard flash path is suppressed bool is_ready; + bool defaultsopen; Effect(const Effect&); Effect& operator=(const Effect&); diff --git a/src/live_effects/lpe-bendpath.cpp b/src/live_effects/lpe-bendpath.cpp index 314ddc84c..11694249a 100644 --- a/src/live_effects/lpe-bendpath.cpp +++ b/src/live_effects/lpe-bendpath.cpp @@ -86,9 +86,8 @@ void LPEBendPath::doBeforeEffect (SPLPEItem const* lpeitem) { // get the item bounding box - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); original_height = boundingbox_Y.max() - boundingbox_Y.min(); - SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (_knot_entity) { if (hide_knot) { helper_path.clear(); @@ -152,8 +151,7 @@ void LPEBendPath::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); Geom::Point start(boundingbox_X.min(), (boundingbox_Y.max()+boundingbox_Y.min())/2); Geom::Point end(boundingbox_X.max(), (boundingbox_Y.max()+boundingbox_Y.min())/2); @@ -171,9 +169,7 @@ LPEBendPath::resetDefaults(SPItem const* item) void LPEBendPath::transform_multiply(Geom::Affine const& postmul, bool set) { - if (sp_lpe_item) { - sp_lpe_item_update_patheffect(sp_lpe_item, false, false); - } + //block parameters be transformed because shapes with bend store transform in the element } void diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index f00759921..7834ff108 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -139,6 +139,9 @@ Gtk::Widget *LPEBSpline::newWidget() ++it; } + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -164,7 +167,7 @@ void LPEBSpline::changeWeight(double weight_ammount) { SPPath *path = dynamic_cast<SPPath *>(sp_lpe_item); if(path) { - SPCurve *curve = path->get_curve_for_edit(); + SPCurve *curve = path->getCurveForEdit(); doBSplineFromWidget(curve, weight_ammount/100.0); gchar *str = sp_svg_write_path(curve->get_pathvector()); path->getRepr()->setAttribute("inkscape:original-d", str); diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 413c18893..d0ff80500 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -124,7 +124,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, const char * if ( shape_dest && shape_origin && (std::strcmp(attribute, "d") == 0)) { SPCurve *c = NULL; if (method == CLM_BSPLINESPIRO) { - c = shape_origin->getCurveBeforeLPE(); + c = shape_origin->getCurveForEdit(); SPLPEItem * lpe_item = SP_LPE_ITEM(origin); if (lpe_item) { PathEffectList lpelist = lpe_item->getEffectList(); @@ -142,7 +142,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, const char * } } } else if(method == CLM_ORIGINALD) { - c = shape_origin->getCurveBeforeLPE(); + c = shape_origin->getCurveForEdit(); } else { c = shape_origin->getCurve(); } @@ -200,15 +200,17 @@ LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ if (method != CLM_NONE) { attr += Glib::ustring("d,"); } - attr += Glib::ustring(attributes.param_getSVGValue()) + Glib::ustring(","); - if (attr.size() && !Glib::ustring(attributes.param_getSVGValue()).size()) { + gchar * attributes_str = attributes.param_getSVGValue(); + attr += Glib::ustring(attributes_str) + Glib::ustring(","); + if (attr.size() && !Glib::ustring(attributes_str).size()) { attr.erase (attr.size()-1, 1); } + gchar * style_attributes_str = style_attributes.param_getSVGValue(); Glib::ustring style_attr = ""; - if (style_attr.size() && !Glib::ustring(style_attributes.param_getSVGValue()).size()) { + if (style_attr.size() && !Glib::ustring( style_attributes_str).size()) { style_attr.erase (style_attr.size()-1, 1); } - style_attr += Glib::ustring(style_attributes.param_getSVGValue()) + Glib::ustring(","); + style_attr += Glib::ustring( style_attributes_str) + Glib::ustring(","); SPItem * orig = SP_ITEM(linkeditem.getObject()); SPItem * dest = SP_ITEM(sp_lpe_item); @@ -257,6 +259,8 @@ LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ } linked = g_strdup(id); + g_free(style_attributes_str); + g_free(attributes_str); g_free(id); } else { linked = g_strdup(""); @@ -336,7 +340,7 @@ LPECloneOriginal::doEffect (SPCurve * curve) // if (linkeditem.linksToItem()) { // SPShape * shape = getCurrentShape(); // if(shape){ -// curve->set_pathvector(shape->getCurveBeforeLPE()->get_pathvector()); +// curve->set_pathvector(shape->getCurveForEdit()->get_pathvector()); // } // } } diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index ebcb95f0d..6bf2a78bd 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -17,6 +17,7 @@ #include <2geom/sbasis-to-bezier.h> #include <2geom/intersection-graph.h> #include "live_effects/lpe-copy_rotate.h" +#include "live_effects/lpeobject.h" #include "display/curve.h" #include "svg/path-string.h" #include "svg/svg.h" @@ -55,7 +56,6 @@ pointInTriangle(Geom::Point const &p, Geom::Point const &p1, Geom::Point const & return 0 <= t1 && t1 <= 1 && 0 <= t2 && t2 <= 1 && s <= 1; } - LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : Effect(lpeobject), method(_("Method:"), _("Rotate methods"), "method", RMConverter, &wr, this, RM_NORMAL), @@ -66,7 +66,7 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) : num_copies(_("Number of copies"), _("Number of copies of the original path"), "num_copies", &wr, this, 6), gap(_("Gap"), _("Gap"), "gap", &wr, this, -0.0001), copies_to_360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copies_to_360", &wr, this, true), - mirror_copies(_("Mirror copies"), _("Mirror between copies"), "mirror_copies", &wr, this, false), + mirror_copies(_("Mirror copies"), _("Mirror between copies"), "mirror_copies", &wr, this, true), split_items(_("Split elements"), _("Split elements, this allow gradients and other paints."), "split_items", &wr, this, false), dist_angle_handle(100.0) { @@ -129,12 +129,15 @@ LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem) if (numcopies_gap > 0 && num_copies != 0) { guint counter = num_copies - 1; while (numcopies_gap > 0) { - const char * id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); - if (!id || strlen(id) == 0) { + Glib::ustring id = Glib::ustring("rotated-"); + id += std::to_string(counter); + id += "-"; + id += this->lpeobj->getId(); + if (id.empty()) { return; } SPObject *elemref = NULL; - if ((elemref = document->getObjectById(id))) { + if (elemref = document->getObjectById(id.c_str())) { SP_ITEM(elemref)->setHidden(true); } counter++; @@ -144,10 +147,14 @@ LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem) previous_num_copies = num_copies; } SPObject *elemref = NULL; - const char * id = g_strdup(Glib::ustring("rotated-").append("0").append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); guint counter = 0; - while((elemref = document->getObjectById(id))) { - id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); + Glib::ustring id = "rotated-0-"; + id += this->lpeobj->getId(); + while((elemref = document->getObjectById(id.c_str()))) { + id = Glib::ustring("rotated-"); + id += std::to_string(counter); + id += "-"; + id += this->lpeobj->getId(); if (SP_ITEM(elemref)->isHidden()) { items.push_back(id); } @@ -184,7 +191,7 @@ LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem) } void -LPECopyRotate::cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bool root, bool reset) +LPECopyRotate::cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bool reset) { SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { @@ -197,30 +204,29 @@ LPECopyRotate::cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bo for (std::vector<SPObject * >::iterator obj_it = childs.begin(); obj_it != childs.end(); ++obj_it) { SPObject *dest_child = dest->nthChild(index); - cloneD(*obj_it, dest_child, transform, false, reset); + cloneD(*obj_it, dest_child, transform, reset); index++; } + return; } SPShape * shape = SP_SHAPE(orig); - if (shape && !SP_IS_PATH(dest)) { + SPPath * path = SP_PATH(dest); + if (shape && !path) { const char * id = dest->getId(); Inkscape::XML::Node *dest_node = sp_selected_item_to_curved_repr(SP_ITEM(dest), 0); dest->updateRepr(xml_doc, dest_node, SP_OBJECT_WRITE_ALL); dest->getRepr()->setAttribute("d", id); + path = SP_PATH(dest); } - if (SP_IS_PATH(dest) && shape) { - SPCurve *c = NULL; - if (root) { - c = new SPCurve(); - c->set_pathvector(pathvector_after_effect); - } else { - c = shape->getCurve(); - } + if (path && shape) { + SPCurve *c = shape->getCurve(); if (c) { - SP_PATH(dest)->setCurve(c, TRUE); + gchar *str = sp_svg_write_path(c->get_pathvector()); + path->getRepr()->setAttribute("d", str); + g_free(str); c->unref(); } else { - dest->getRepr()->setAttribute("d", NULL); + path->getRepr()->setAttribute("d", NULL); } if (reset) { dest->getRepr()->setAttribute("style", shape->getRepr()->attribute("style")); @@ -228,6 +234,33 @@ LPECopyRotate::cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bo } } +Inkscape::XML::Node * +LPECopyRotate::createPathBase(SPObject *elemref) { + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return NULL; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Node *prev = elemref->getRepr(); + SPGroup *group = dynamic_cast<SPGroup *>(elemref); + if (group) { + Inkscape::XML::Node *container = xml_doc->createElement("svg:g"); + container->setAttribute("transform", prev->attribute("transform")); + std::vector<SPItem*> const item_list = sp_item_group_item_list(group); + Inkscape::XML::Node *previous = NULL; + for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPObject *sub_item = *iter; + Inkscape::XML::Node *resultnode = createPathBase(sub_item); + container->addChild(resultnode, previous); + previous = resultnode; + } + return container; + } + Inkscape::XML::Node *resultnode = xml_doc->createElement("svg:path"); + resultnode->setAttribute("transform", prev->attribute("transform")); + return resultnode; +} + void LPECopyRotate::toItem(Geom::Affine transform, size_t i, bool reset) { @@ -236,64 +269,32 @@ LPECopyRotate::toItem(Geom::Affine transform, size_t i, bool reset) return; } Inkscape::XML::Document *xml_doc = document->getReprDoc(); - const char * elemref_id = g_strdup(Glib::ustring("rotated-").append(std::to_string(i)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str()); + Glib::ustring elemref_id = Glib::ustring("rotated-"); + elemref_id += std::to_string(i); + elemref_id += "-"; + elemref_id += this->lpeobj->getId(); items.push_back(elemref_id); SPObject *elemref= NULL; Inkscape::XML::Node *phantom = NULL; - if ((elemref = document->getObjectById(elemref_id))) { + if (elemref = document->getObjectById(elemref_id.c_str())) { phantom = elemref->getRepr(); } else { - phantom = sp_lpe_item->getRepr()->duplicate(xml_doc); - std::vector<const char *> attrs; - attrs.push_back("inkscape:path-effect"); - attrs.push_back("inkscape:original-d"); - attrs.push_back("sodipodi:type"); - attrs.push_back("sodipodi:rx"); - attrs.push_back("sodipodi:ry"); - attrs.push_back("sodipodi:cx"); - attrs.push_back("sodipodi:cy"); - attrs.push_back("sodipodi:end"); - attrs.push_back("sodipodi:start"); - attrs.push_back("inkscape:flatsided"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:rounded"); - attrs.push_back("sodipodi:arg1"); - attrs.push_back("sodipodi:arg2"); - attrs.push_back("sodipodi:r1"); - attrs.push_back("sodipodi:r2"); - attrs.push_back("sodipodi:sides"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("sodipodi:argument"); - attrs.push_back("sodipodi:expansion"); - attrs.push_back("sodipodi:radius"); - attrs.push_back("sodipodi:revolution"); - attrs.push_back("sodipodi:t0"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("x"); - attrs.push_back("y"); - attrs.push_back("rx"); - attrs.push_back("ry"); - attrs.push_back("width"); - attrs.push_back("height"); - phantom->setAttribute("id", elemref_id); - for(const char * attr : attrs) { - phantom->setAttribute(attr, NULL); - } + phantom = createPathBase(sp_lpe_item); + phantom->setAttribute("id", elemref_id.c_str()); + reset = true; } if (!elemref) { elemref = container->appendChildRepr(phantom); Inkscape::GC::release(phantom); } - cloneD(SP_OBJECT(sp_lpe_item), elemref, transform, true, reset); + cloneD(SP_OBJECT(sp_lpe_item), elemref, transform, reset); gchar *str = sp_svg_transform_write(transform); elemref->getRepr()->setAttribute("transform" , str); g_free(str); SP_ITEM(elemref)->setHidden(false); if (elemref->parent != container) { Inkscape::XML::Node *copy = phantom->duplicate(xml_doc); - copy->setAttribute("id", elemref_id); + copy->setAttribute("id", elemref_id.c_str()); container->appendChildRepr(copy); Inkscape::GC::release(copy); elemref->deleteObject(); @@ -340,6 +341,9 @@ Gtk::Widget * LPECopyRotate::newWidget() reset_button->set_size_request(110,20); vbox->pack_start(*hbox, true,true,2); hbox->pack_start(*reset_button, false, false,2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -348,7 +352,7 @@ void LPECopyRotate::doOnApply(SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); A = Point(boundingbox_X.min(), boundingbox_Y.middle()); B = Point(boundingbox_X.middle(), boundingbox_Y.middle()); @@ -375,7 +379,7 @@ void LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); if (copies_to_360 && num_copies > 2) { rotation_angle.param_set_value(360.0/(double)num_copies); } @@ -711,7 +715,7 @@ void LPECopyRotate::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); } void diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h index a0a3d4dc1..dcbd1c45e 100644 --- a/src/live_effects/lpe-copy_rotate.h +++ b/src/live_effects/lpe-copy_rotate.h @@ -48,7 +48,8 @@ public: virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); virtual Gtk::Widget * newWidget(); void toItem(Geom::Affine transform, size_t i, bool reset); - void cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bool root, bool reset); + void cloneD(SPObject *orig, SPObject *dest, Geom::Affine transform, bool reset); + Inkscape::XML::Node * createPathBase(SPObject *elemref); void resetStyles(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); diff --git a/src/live_effects/lpe-envelope.cpp b/src/live_effects/lpe-envelope.cpp index b50efde34..0dcae51e4 100644 --- a/src/live_effects/lpe-envelope.cpp +++ b/src/live_effects/lpe-envelope.cpp @@ -42,7 +42,7 @@ void LPEEnvelope::doBeforeEffect (SPLPEItem const* lpeitem) { // get the item bounding box - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); } Geom::Piecewise<Geom::D2<Geom::SBasis> > @@ -218,7 +218,7 @@ LPEEnvelope::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); Geom::Point Up_Left(boundingbox_X.min(), boundingbox_Y.min()); Geom::Point Up_Right(boundingbox_X.max(), boundingbox_Y.min()); diff --git a/src/live_effects/lpe-fillet-chamfer.cpp b/src/live_effects/lpe-fillet-chamfer.cpp index 94a43b728..59a6324e7 100644 --- a/src/live_effects/lpe-fillet-chamfer.cpp +++ b/src/live_effects/lpe-fillet-chamfer.cpp @@ -111,7 +111,9 @@ void LPEFilletChamfer::doOnApply(SPLPEItem const *lpeItem) SatelliteType satellite_type = FILLET; std::map<std::string, SatelliteType> gchar_map_to_satellite_type = boost::assign::map_list_of("F", FILLET)("IF", INVERSE_FILLET)("C", CHAMFER)("IC", INVERSE_CHAMFER)("KO", INVALID_SATELLITE); - std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(mode.param_getSVGValue())); + gchar * mode_str = mode.param_getSVGValue(); + std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(mode_str)); + g_free(mode_str); if (it != gchar_map_to_satellite_type.end()) { satellite_type = it->second; } @@ -250,7 +252,9 @@ Gtk::Widget *LPEFilletChamfer::newWidget() vbox->pack_start(*fillet_container, true, true, 2); vbox->pack_start(*chamfer_container, true, true, 2); - + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return vbox; } @@ -320,14 +324,14 @@ void LPEFilletChamfer::setSelected(PathVectorSatellites *_pathvector_satellites) void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) { - if (sp_curve) { + if (!pathvector_before_effect.empty()) { //fillet chamfer specific calls satellites_param.setUseDistance(use_knot_distance); satellites_param.setCurrentZoom(current_zoom); //mandatory call satellites_param.setEffectType(effectType()); - Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(sp_curve->get_pathvector()); - //if are different sizes call to recalculate + Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(pathvector_before_effect); + //if are diferent sizes call to recalculate //TODO: Update the satellite data in paths modified, Satellites satellites = satellites_param.data(); if (satellites.empty()) { @@ -338,7 +342,6 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) size_t number_nodes = pathv.nodes().size(); size_t previous_number_nodes = _pathvector_satellites->getTotalSatellites(); if (number_nodes != previous_number_nodes) { - Geom::PathVector const pathv = pathv_to_linear_and_cubic_beziers(sp_curve->get_pathvector()); Satellites satellites; double power = radius; if (!flexible) { @@ -350,7 +353,9 @@ void LPEFilletChamfer::doBeforeEffect(SPLPEItem const *lpeItem) SatelliteType satellite_type = FILLET; std::map<std::string, SatelliteType> gchar_map_to_satellite_type = boost::assign::map_list_of("F", FILLET)("IF", INVERSE_FILLET)("C", CHAMFER)("IC", INVERSE_CHAMFER)("KO", INVALID_SATELLITE); - std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(mode.param_getSVGValue())); + gchar * mode_str = mode.param_getSVGValue(); + std::map<std::string, SatelliteType>::iterator it = gchar_map_to_satellite_type.find(std::string(mode_str)); + g_free(mode_str); if (it != gchar_map_to_satellite_type.end()) { satellite_type = it->second; } diff --git a/src/live_effects/lpe-interpolate.cpp b/src/live_effects/lpe-interpolate.cpp index f6b42cfb9..70bc92a27 100644 --- a/src/live_effects/lpe-interpolate.cpp +++ b/src/live_effects/lpe-interpolate.cpp @@ -104,7 +104,7 @@ LPEInterpolate::resetDefaults(SPItem const* item) if (!SP_IS_PATH(item)) return; - SPCurve const *crv = SP_PATH(item)->get_curve_reference(); + SPCurve const *crv = SP_PATH(item)->getCurveForEdit(true); Geom::PathVector const &pathv = crv->get_pathvector(); if ( (pathv.size() < 2) ) return; diff --git a/src/live_effects/lpe-lattice.cpp b/src/live_effects/lpe-lattice.cpp index 124a7a9c6..df4da4590 100644 --- a/src/live_effects/lpe-lattice.cpp +++ b/src/live_effects/lpe-lattice.cpp @@ -164,7 +164,7 @@ LPELattice::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2 void LPELattice::doBeforeEffect (SPLPEItem const* lpeitem) { - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); } void @@ -172,7 +172,7 @@ LPELattice::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - original_bbox(SP_LPE_ITEM(item), false); + original_bbox(SP_LPE_ITEM(item), false, true); // place the 16 control points grid_point0[Geom::X] = boundingbox_X.min(); diff --git a/src/live_effects/lpe-lattice2.cpp b/src/live_effects/lpe-lattice2.cpp index 3eeb6e746..8c2c3ec31 100644 --- a/src/live_effects/lpe-lattice2.cpp +++ b/src/live_effects/lpe-lattice2.cpp @@ -268,6 +268,9 @@ LPELattice2::newWidget() expander->set_expanded(expanded); vbox->pack_start(*expander, true, true, 2); expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPELattice2::onExpanderChanged) ); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -327,7 +330,7 @@ LPELattice2::horizontal(PointParam ¶m_one, PointParam ¶m_two, Geom::Line void LPELattice2::doBeforeEffect (SPLPEItem const* lpeitem) { - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); setDefaults(); Geom::Line vert(grid_point_8x9.param_get_default(),grid_point_10x11.param_get_default()); Geom::Line horiz(grid_point_24x26.param_get_default(),grid_point_25x27.param_get_default()); @@ -551,7 +554,7 @@ void LPELattice2::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); setDefaults(); resetGrid(); } diff --git a/src/live_effects/lpe-measure-segments.cpp b/src/live_effects/lpe-measure-segments.cpp index 9bfa2c52e..cff5aec4b 100644 --- a/src/live_effects/lpe-measure-segments.cpp +++ b/src/live_effects/lpe-measure-segments.cpp @@ -8,36 +8,40 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ -#include "live_effects/lpe-measure-segments.h" -#include "live_effects/lpeobject.h" -#include <pangomm/fontdescription.h> -#include "ui/dialog/livepatheffect-editor.h" -#include <libnrtype/font-lister.h> -#include "inkscape.h" -#include "xml/node.h" -#include "xml/sp-css-attr.h" -#include "preferences.h" -#include "util/units.h" -#include "svg/svg-length.h" -#include "svg/svg-color.h" -#include "svg/stringstream.h" -#include "svg/svg.h" + +#include <gtkmm.h> +#include "2geom/affine.h" +#include "2geom/angle.h" +#include "2geom/point.h" +#include "2geom/ray.h" #include "display/curve.h" #include "helper/geom.h" -#include "2geom/affine.h" -#include "path-chemistry.h" -#include "document.h" -#include "document-undo.h" -#include <iomanip> -#include <cmath> - -#include "object/sp-root.h" +#include "live_effects/lpe-measure-segments.h" #include "object/sp-defs.h" #include "object/sp-item.h" -#include "object/sp-shape.h" #include "object/sp-path.h" +#include "object/sp-root.h" +#include "object/sp-shape.h" #include "object/sp-star.h" #include "object/sp-spiral.h" +#include "svg/stringstream.h" +#include "svg/svg.h" +#include "svg/svg-color.h" +#include "svg/svg-length.h" +#include "util/units.h" +#include "xml/node.h" +#include "xml/sp-css-attr.h" + +#include "document.h" +#include "document-undo.h" +#include "inkscape.h" +#include "preferences.h" +#include "path-chemistry.h" + +#include <cmath> +#include <iomanip> +#include <libnrtype/font-lister.h> +#include <pangomm/fontdescription.h> // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -46,10 +50,11 @@ using namespace Geom; namespace Inkscape { namespace LivePathEffect { + static const Util::EnumData<OrientationMethod> OrientationMethodData[] = { - { OM_HORIZONTAL, N_("Horizontal"), "horizontal" }, - { OM_VERTICAL, N_("Vertical"), "vertical" }, - { OM_PARALLEL, N_("Parallel"), "parallel" } + { OM_HORIZONTAL , N_("Horizontal"), "horizontal" }, + { OM_VERTICAL , N_("Vertical") , "vertical" }, + { OM_PARALLEL , N_("Parallel") , "parallel" } }; static const Util::EnumDataConverter<OrientationMethod> OMConverter(OrientationMethodData, OM_END); @@ -102,7 +107,6 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : registerParameter(&rotate_anotation); registerParameter(&hide_back); registerParameter(&message); - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); Glib::ustring format_value = prefs->getString("/live_effects/measure-line/format"); @@ -140,21 +144,26 @@ LPEMeasureSegments::LPEMeasureSegments(LivePathEffectObject *lpeobject) : helpline_overlap.param_set_increments(1, 1); helpline_overlap.param_set_digits(2); star_ellipse_fix = Geom::identity(); - message.param_set_min_height(95); + locale_base = strdup(setlocale(LC_NUMERIC, NULL)); + message.param_set_min_height(85); + previous_size = 0; } -LPEMeasureSegments::~LPEMeasureSegments() {} +LPEMeasureSegments::~LPEMeasureSegments() { + doOnRemove(NULL); +} void -LPEMeasureSegments::createArrowMarker(const char * mode) +LPEMeasureSegments::createArrowMarker(Glib::ustring mode) { SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; } + Glib::ustring lpobjid = this->lpeobj->getId(); + Glib::ustring itemid = sp_lpe_item->getId(); Glib::ustring style; gchar c[32]; - unsigned const rgb24 = coloropacity.get_value() >> 8; sprintf(c, "#%06x", rgb24); style = Glib::ustring("fill:") + Glib::ustring(c); Inkscape::SVGOStringStream os; @@ -163,7 +172,7 @@ LPEMeasureSegments::createArrowMarker(const char * mode) Inkscape::XML::Document *xml_doc = document->getReprDoc(); SPObject *elemref = NULL; Inkscape::XML::Node *arrow = NULL; - if ((elemref = document->getObjectById(mode))) { + if ((elemref = document->getObjectById(mode.c_str()))) { Inkscape::XML::Node *arrow= elemref->getRepr(); if (arrow) { arrow->setAttribute("sodipodi:insensitive", "true"); @@ -176,9 +185,13 @@ LPEMeasureSegments::createArrowMarker(const char * mode) } } else { arrow = xml_doc->createElement("svg:marker"); - arrow->setAttribute("id", mode); - arrow->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-arrows-marker")).c_str()); - arrow->setAttribute("inkscape:stockid", mode); + arrow->setAttribute("id", mode.c_str()); + Glib::ustring classarrow = itemid; + classarrow += " "; + classarrow += lpobjid; + classarrow += " measure-arrows-marker"; + arrow->setAttribute("class", classarrow.c_str()); + arrow->setAttribute("inkscape:stockid", mode.c_str()); arrow->setAttribute("orient", "auto"); arrow->setAttribute("refX", "0.0"); arrow->setAttribute("refY", "0.0"); @@ -186,17 +199,22 @@ LPEMeasureSegments::createArrowMarker(const char * mode) arrow->setAttribute("sodipodi:insensitive", "true"); /* Create <path> */ Inkscape::XML::Node *arrow_path = xml_doc->createElement("svg:path"); - if (std::strcmp(mode, "ArrowDIN-start") == 0) { + if (std::strcmp(mode.c_str(), "ArrowDIN-start") == 0) { arrow_path->setAttribute("d", "M -8,0 8,-2.11 8,2.11 z"); - } else if (std::strcmp(mode, "ArrowDIN-end") == 0) { + } else if (std::strcmp(mode.c_str(), "ArrowDIN-end") == 0) { arrow_path->setAttribute("d", "M 8,0 -8,2.11 -8,-2.11 z"); - } else if (std::strcmp(mode, "ArrowDINout-start") == 0) { + } else if (std::strcmp(mode.c_str(), "ArrowDINout-start") == 0) { arrow_path->setAttribute("d", "M 0,0 -16,2.11 -16,0.5 -26,0.5 -26,-0.5 -16,-0.5 -16,-2.11 z"); } else { arrow_path->setAttribute("d", "M 0,0 16,-2.11 16,-0.5 26,-0.5 26,0.5 16,0.5 16,2.11 z"); } - arrow_path->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-arrows")).c_str()); - arrow_path->setAttribute("id", Glib::ustring(mode).append("_path").c_str()); + Glib::ustring classarrowpath = itemid; + classarrowpath += " "; + classarrowpath += lpobjid; + classarrowpath += " measure-arrows"; + arrow_path->setAttribute("class", classarrowpath.c_str()); + Glib::ustring arrowpath = mode + Glib::ustring("_path"); + arrow_path->setAttribute("id", arrowpath.c_str()); arrow_path->setAttribute("style", style.c_str()); arrow->addChild(arrow_path, NULL); Inkscape::GC::release(arrow_path); @@ -216,72 +234,48 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng Inkscape::XML::Document *xml_doc = document->getReprDoc(); Inkscape::XML::Node *rtext = NULL; double doc_w = document->getRoot()->width.value; - Geom::Scale scale = document->getDocumentScale(); - SPNamedView *nv = sp_document_namedview(document, NULL); - Glib::ustring display_unit = nv->display_units->abbr; - if (display_unit.empty()) { - display_unit = "px"; - } - //only check constrain viewbox on X - doc_scale = Inkscape::Util::Quantity::convert( scale[Geom::X], "px", nv->display_units ); - if( doc_scale > 0 ) { - doc_scale= 1.0/doc_scale; - } else { - doc_scale = 1.0; - } - const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); + + Glib::ustring lpobjid = this->lpeobj->getId(); + Glib::ustring itemid = sp_lpe_item->getId(); + Glib::ustring id = Glib::ustring("text-on-"); + id += Glib::ustring::format(counter); + id += "-"; + id += lpobjid; SPObject *elemref = NULL; Inkscape::XML::Node *rtspan = NULL; - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - return; - } + elemref = document->getObjectById(id.c_str()); + + if (elemref) { rtext = elemref->getRepr(); sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); rtext->setAttribute("sodipodi:insensitive", "true"); rtext->setAttribute("transform", NULL); } else { - if (remove) { - return; - } rtext = xml_doc->createElement("svg:text"); rtext->setAttribute("xml:space", "preserve"); - rtext->setAttribute("id", id); - rtext->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-labels")).c_str()); + rtext->setAttribute("id", id.c_str()); + Glib::ustring classlabel = itemid; + classlabel += " "; + classlabel += lpobjid; + classlabel += " measure-labels"; + rtext->setAttribute("class", classlabel.c_str()); rtext->setAttribute("sodipodi:insensitive", "true"); sp_repr_set_svg_double(rtext, "x", pos[Geom::X]); sp_repr_set_svg_double(rtext, "y", pos[Geom::Y]); rtspan = xml_doc->createElement("svg:tspan"); rtspan->setAttribute("sodipodi:role", "line"); } - gchar * transform; - Geom::Affine affine = Geom::Affine(Geom::Translate(pos).inverse()); - angle = std::fmod(angle, 2*M_PI); - if (angle < 0) angle += 2*M_PI; - if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { - angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); - if (angle < 0) angle += 2*M_PI; - } - affine *= Geom::Rotate(angle); - affine *= Geom::Translate(pos); - if (rotate_anotation) { - transform = sp_svg_transform_write(affine); - } else { - transform = NULL; - } - rtext->setAttribute("transform", transform); - g_free(transform); SPCSSAttr *css = sp_repr_css_attr_new(); Inkscape::FontLister *fontlister = Inkscape::FontLister::get_instance(); - fontlister->fill_css(css, Glib::ustring(fontbutton.param_getSVGValue())); + gchar * fontbutton_str = fontbutton.param_getSVGValue(); + fontlister->fill_css(css, Glib::ustring(fontbutton_str)); + g_free(fontbutton_str); std::stringstream font_size; - font_size.imbue(std::locale::classic()); + setlocale (LC_NUMERIC, "C"); font_size << fontsize << "pt"; - + setlocale (LC_NUMERIC, locale_base); gchar c[32]; - unsigned const rgb24 = coloropacity.get_value() >> 8; sprintf(c, "#%06x", rgb24); sp_repr_css_set_property (css, "fill",c); Inkscape::SVGOStringStream os; @@ -291,10 +285,14 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng rtspan = rtext->firstChild(); } sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); + if (remove) { + sp_repr_css_set_property (css, "display","hidden"); + } + sp_repr_css_set_property (css, "font-size",font_size.str().c_str()); Glib::ustring css_str; sp_repr_css_write_string(css,css_str); rtext->setAttribute("style", css_str.c_str()); - rtspan->setAttribute("style", NULL); + rtspan->setAttribute("style", css_str.c_str()); rtspan->setAttribute("transform", NULL); sp_repr_css_attr_unref (css); if (!elemref) { @@ -302,7 +300,6 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng Inkscape::GC::release(rtspan); } length = Inkscape::Util::Quantity::convert(length / doc_scale, display_unit.c_str(), unit.get_abbreviation()); - char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); if (local_locale) { setlocale (LC_NUMERIC, ""); } else { @@ -310,9 +307,10 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng } gchar length_str[64]; g_snprintf(length_str, 64, "%.*f", (int)precision, length); - setlocale (LC_NUMERIC, oldlocale); - g_free (oldlocale); - Glib::ustring label_value(format.param_getSVGValue()); + setlocale (LC_NUMERIC, locale_base); + gchar * format_str = format.param_getSVGValue(); + Glib::ustring label_value(format_str); + g_free(format_str); size_t s = label_value.find(Glib::ustring("{measure}"),0); if(s < label_value.length()) { label_value.replace(s,s+9,length_str); @@ -341,26 +339,53 @@ LPEMeasureSegments::createTextLabel(Geom::Point pos, size_t counter, double leng Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); Inkscape::GC::release(copy); - elemref->deleteObject(); - copy->setAttribute("id", id); + sp_object_ref(elemref, 0 ); + elemref->deleteObject(true); + sp_object_unref(elemref); + copy->setAttribute("id", id.c_str()); elemref = elemref_copy; } - items.push_back(id); + SP_ITEM(elemref)->updateRepr(); Geom::OptRect bounds = SP_ITEM(elemref)->bounds(SPItem::GEOMETRIC_BBOX); if (bounds) { anotation_width = bounds->width() * 1.15; + rtspan->setAttribute("style", NULL); } + gchar * transform; + if (rotate_anotation) { + Geom::Affine affine = Geom::Affine(Geom::Translate(pos).inverse()); + angle = std::fmod(angle, 2*M_PI); + if (angle < 0) angle += 2*M_PI; + if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { + angle = std::fmod(angle + rad_from_deg(180), 2*M_PI); + if (angle < 0) angle += 2*M_PI; + } + affine *= Geom::Rotate(angle); + affine *= Geom::Translate(pos); + transform = sp_svg_transform_write(affine); + } else { + transform = NULL; + } + rtext->setAttribute("transform", transform); + g_free(transform); } void -LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool remove, bool arrows) +LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, Glib::ustring name, size_t counter, bool main, bool remove, bool arrows) { SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; } + Glib::ustring lpobjid = this->lpeobj->getId(); + Glib::ustring itemid = sp_lpe_item->getId(); + Glib::ustring id = name; + id += Glib::ustring::format(counter); + id += "-"; + id += lpobjid; + Inkscape::XML::Document *xml_doc = document->getReprDoc(); - SPObject *elemref = NULL; + SPObject *elemref = document->getObjectById(id.c_str()); Inkscape::XML::Node *line = NULL; if (!main) { Geom::Ray ray(start, end); @@ -369,25 +394,13 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i end = end + Point::polar(angle, helpline_overlap ); } Geom::PathVector line_pathv; - + + double k = (Geom::distance(start,end)/2.0) - (anotation_width/10.0) - (anotation_width/2.0); if (main && std::abs(text_top_bottom) < fontsize/1.5 && - hide_back) + hide_back && + k > 0) { - double k = 0; - if (flip_side) { - k = (Geom::distance(start,end)/2.0) + arrow_gap - (anotation_width/2.0); - } else { - k = (Geom::distance(start,end)/2.0) - arrow_gap - (anotation_width/2.0); - } - if (Geom::distance(start,end) < anotation_width){ - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - } - return; - } - } //k = std::max(k , arrow_gap -1); Geom::Ray ray(end, start); Geom::Coord angle = ray.angle(); @@ -403,11 +416,7 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i line_path.appendNew<Geom::LineSegment>(end); line_pathv.push_back(line_path); } - if ((elemref = document->getObjectById(id))) { - if (remove) { - elemref->deleteObject(); - return; - } + if (elemref) { line = elemref->getRepr(); gchar * line_str = sp_svg_write_path( line_pathv ); @@ -415,46 +424,59 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i line->setAttribute("transform", NULL); g_free(line_str); } else { - if (remove) { - return; - } line = xml_doc->createElement("svg:path"); - line->setAttribute("id", id); + line->setAttribute("id", id.c_str()); if (main) { - line->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-DIM-lines measure-lines")).c_str()); + Glib::ustring classlinedim = itemid; + classlinedim += " "; + classlinedim += lpobjid; + classlinedim += " measure-DIM-lines measure-lines"; + line->setAttribute("class", classlinedim.c_str()); } else { - line->setAttribute("class", (Glib::ustring(sp_lpe_item->getId()) + Glib::ustring(" ") + Glib::ustring(this->lpeobj->getId()) + Glib::ustring(" measure-helper-lines measure-lines")).c_str()); + Glib::ustring classlinehelper = itemid; + classlinehelper += " "; + classlinehelper += lpobjid; + classlinehelper += " measure-helper-lines measure-lines"; + line->setAttribute("class", classlinehelper.c_str()); } gchar * line_str = sp_svg_write_path( line_pathv ); line->setAttribute("d" , line_str); g_free(line_str); } + line->setAttribute("sodipodi:insensitive", "true"); line_pathv.clear(); Glib::ustring style; + if (remove) { + style ="display:none;"; + } if (main) { line->setAttribute("inkscape:label", "dinline"); if (arrows_outside) { - style = style + Glib::ustring("marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);"); + style += "marker-start:url(#ArrowDINout-start);marker-end:url(#ArrowDINout-end);"; } else { - style = style + Glib::ustring("marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);"); + style += "marker-start:url(#ArrowDIN-start);marker-end:url(#ArrowDIN-end);"; } } else { line->setAttribute("inkscape:label", "dinhelpline"); } std::stringstream stroke_w; - stroke_w.imbue(std::locale::classic()); + setlocale (LC_NUMERIC, "C"); + double stroke_width = Inkscape::Util::Quantity::convert(line_width / doc_scale, "mm", display_unit.c_str()); stroke_w << stroke_width; - style = style + Glib::ustring("stroke-width:" + stroke_w.str()); + setlocale (LC_NUMERIC, locale_base); + style += "stroke-width:"; + style += stroke_w.str(); gchar c[32]; - unsigned const rgb24 = coloropacity.get_value() >> 8; sprintf(c, "#%06x", rgb24); - style = style + Glib::ustring(";stroke:") + Glib::ustring(c); + style += ";stroke:"; + style += Glib::ustring(c); Inkscape::SVGOStringStream os; os << SP_RGBA32_A_F(coloropacity.get_value()); - style = style + Glib::ustring(";stroke-opacity:") + Glib::ustring(os.str()); + style += ";stroke-opacity:"; + style += os.str(); SPCSSAttr *css = sp_repr_css_attr_new(); sp_repr_css_attr_add_from_string(css, style.c_str()); Glib::ustring css_str; @@ -468,10 +490,11 @@ LPEMeasureSegments::createLine(Geom::Point start,Geom::Point end, const char * i Inkscape::XML::Node *copy = old_repr->duplicate(xml_doc); SPObject * elemref_copy = sp_lpe_item->parent->appendChildRepr(copy); Inkscape::GC::release(copy); - elemref->deleteObject(); - copy->setAttribute("id", id); + sp_object_ref(elemref, 0 ); + elemref->deleteObject(true); + sp_object_unref(elemref); + copy->setAttribute("id", id.c_str()); } - items.push_back(id); } void @@ -534,7 +557,9 @@ LPEMeasureSegments::doOnApply(SPLPEItem const* lpeitem) bool LPEMeasureSegments::hasMeassure (size_t i) { - std::string listsegments(std::string(blacklist.param_getSVGValue()) + std::string(",")); + gchar * blacklist_str = blacklist.param_getSVGValue(); + std::string listsegments(std::string(blacklist_str) + std::string(",")); + g_free(blacklist_str); listsegments.erase(std::remove(listsegments.begin(), listsegments.end(), ' '), listsegments.end()); size_t s = listsegments.find(std::to_string(i) + std::string(","),0); if(s < listsegments.length()) { @@ -571,7 +596,6 @@ void LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) { SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); - SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; @@ -584,16 +608,38 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) SPShape *shape = dynamic_cast<SPShape *>(splpeitem); if (shape) { - SPCurve * c = NULL; - - SPPath *path = dynamic_cast<SPPath *>(shape); - if (path) { - c = path->get_original_curve(); + //only check constrain viewbox on X + Geom::Scale scaledoc = document->getDocumentScale(); + SPNamedView *nv = sp_document_namedview(document, NULL); + display_unit = nv->display_units->abbr; + if (display_unit.empty()) { + display_unit = "px"; + } + doc_scale = Inkscape::Util::Quantity::convert( scaledoc[Geom::X], "px", display_unit.c_str() ); + if( doc_scale > 0 ) { + doc_scale= 1.0/doc_scale; } else { - c = shape->getCurve(); + doc_scale = 1.0; + } + unsigned const color = coloropacity.get_value() >> 8; + bool colorchanged = false; + if (color != rgb24) { + colorchanged = true; } - Geom::Point start_stored; - Geom::Point end_stored; + rgb24 = color; + SPCurve * c = NULL; + gchar * fontbutton_str = fontbutton.param_getSVGValue(); + Glib::ustring fontdesc_ustring = Glib::ustring(fontbutton_str); + Pango::FontDescription fontdesc(fontdesc_ustring); + fontsize = fontdesc.get_size()/(double)Pango::SCALE; + fontsize *= document->getRoot()->c2p.inverse().expansionX(); + g_free(fontbutton_str); + fontsize *= document->getRoot()->c2p.inverse().expansionX(); + c = shape->getCurve(); + Geom::Point prev_stored = Geom::Point(0,0); + Geom::Point start_stored = Geom::Point(0,0); + Geom::Point end_stored = Geom::Point(0,0); + Geom::Point next_stored = Geom::Point(0,0); Geom::Affine affinetransform = i2anc_affine(SP_OBJECT(lpeitem->parent), SP_OBJECT(document->getRoot())); Geom::PathVector pathvector = pathv_to_linear_and_cubic_beziers(c->get_pathvector()); c->unref(); @@ -605,55 +651,137 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) } else { pathvector *= writed_transform; } - if ((Glib::ustring(format.param_getSVGValue()).empty())) { + gchar * format_str = format.param_getSVGValue(); + if (Glib::ustring(format_str).empty()) { format.param_setValue(Glib::ustring("{measure}{unit}")); } + g_free(format_str); size_t ncurves = pathvector.curveCount(); items.clear(); double start_angle_cross = 0; double end_angle_cross = 0; - size_t counter = -1; + gint counter = -1; + Glib::ustring lpobjid = this->lpeobj->getId(); + bool previous_fix_overlaps = true; for (size_t i = 0; i < pathvector.size(); i++) { for (size_t j = 0; j < pathvector[i].size(); j++) { counter++; - if(hasMeassure(counter + 1)) { - Geom::Point prev = Geom::Point(0,0); - if (j == 0 && pathvector[i].closed()) { - prev = pathvector.pointAt(pathvector[i].size() - 1); - } else if (j != 0) { - prev = pathvector[i].pointAt(j - 1); + gint fix_overlaps_degree = fix_overlaps; + Geom::Point prev = Geom::Point(0,0); + if (j == 0 && pathvector[i].closed()) { + prev = pathvector.pointAt(pathvector[i].size() - 1); + } else if (j != 0) { + prev = pathvector[i].pointAt(j - 1); + } + Geom::Point start = pathvector[i].pointAt(j); + Geom::Point end = pathvector[i].pointAt(j + 1); + Geom::Point next = Geom::Point(0,0); + if(pathvector[i].closed() && pathvector[i].size() == j+1){ + end = pathvector[i].pointAt(0); + next = pathvector[i].pointAt(1); + } else if (pathvector[i].size() > j + 1) { + next = pathvector[i].pointAt(j+2); + } + if(hasMeassure(counter) && !Geom::are_near(start, end)) { + Glib::ustring idprev = Glib::ustring("infoline-on-start-"); + idprev += Glib::ustring::format(counter-1); + idprev += "-"; + idprev += lpobjid; + SPObject *elemref = NULL; + if (elemref = document->getObjectById(idprev.c_str())) { + SPPath* path = dynamic_cast<SPPath *>(elemref); + if (path) { + SPCurve* prevcurve = path->getCurve(); + if (prevcurve) { + prev_stored = *prevcurve->first_point(); + } + prevcurve->unref(); + } } - Geom::Point start = pathvector[i].pointAt(j); - Geom::Point end = pathvector[i].pointAt(j + 1); - Geom::Point next = Geom::Point(0,0); - if(pathvector[i].closed() && pathvector[i].size() == j+1){ - end = pathvector[i].pointAt(0); - next = pathvector[i].pointAt(1); - } else if (pathvector[i].size() > j + 1) { - next = pathvector[i].pointAt(j+2); + Glib::ustring idstart = Glib::ustring("infoline-on-start-"); + idstart += Glib::ustring::format(counter); + idstart += "-"; + idstart += lpobjid; + elemref = NULL; + if (elemref = document->getObjectById(idstart.c_str())) { + SPPath* path = dynamic_cast<SPPath *>(elemref); + if (path) { + SPCurve* startcurve = path->getCurve(); + if (startcurve) { + start_stored = *startcurve->first_point(); + } + startcurve->unref(); + } } - const char * idstart = Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str(); - SPObject *elemref = NULL; - if ((elemref = document->getObjectById(idstart))) { - start_stored = *SP_PATH(elemref)->get_curve()->first_point(); + Glib::ustring idend = Glib::ustring("infoline-on-end-"); + idend += Glib::ustring::format(counter); + idend += "-"; + idend += lpobjid; + elemref = NULL; + if (elemref = document->getObjectById(idend.c_str())) { + SPPath* path = dynamic_cast<SPPath *>(elemref); + if (path) { + SPCurve* endcurve = path->getCurve(); + if (endcurve) { + end_stored = *endcurve->first_point(); + } + endcurve->unref(); + } } - const char * idend = Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str(); + Glib::ustring idnext = Glib::ustring("infoline-on-start-"); + idnext += Glib::ustring::format(counter+1); + idnext += "-"; + idnext += lpobjid; elemref = NULL; - if ((elemref = document->getObjectById(idend))) { - end_stored = *SP_PATH(elemref)->get_curve()->first_point(); + if (elemref = document->getObjectById(idnext.c_str())) { + SPPath* path = dynamic_cast<SPPath *>(elemref); + if (path) { + SPCurve* nextcurve = path->getCurve(); + if (nextcurve) { + next_stored = *nextcurve->first_point(); + } + nextcurve->unref(); + } } - if (Geom::are_near(start, start_stored, 0.01) && - Geom::are_near(end, end_stored, 0.01)) + Glib::ustring infoline_on_start = "infoline-on-start-"; + infoline_on_start += Glib::ustring::format(counter); + infoline_on_start += "-"; + infoline_on_start += lpobjid; + items.push_back(infoline_on_start); + Glib::ustring infoline_on_end = "infoline-on-end-"; + infoline_on_end += Glib::ustring::format(counter); + infoline_on_end += "-"; + infoline_on_end += lpobjid; + items.push_back(infoline_on_end); + Glib::ustring infoline = "infoline-"; + infoline += Glib::ustring::format(counter); + infoline += "-"; + infoline += lpobjid; + items.push_back(infoline); + Glib::ustring texton = "text-on-"; + texton += Glib::ustring::format(counter); + texton += "-"; + texton += lpobjid; + items.push_back(texton); + if (arrows_outside) { + items.push_back(Glib::ustring("ArrowDINout-start")); + items.push_back(Glib::ustring("ArrowDINout-end")); + } else { + items.push_back(Glib::ustring("ArrowDIN-start")); + items.push_back(Glib::ustring("ArrowDIN-end")); + } + if ((Geom::are_near(prev, prev_stored, 0.01) && Geom::are_near(next, next_stored, 0.01) || + fix_overlaps_degree == 180) && + Geom::are_near(start, start_stored, 0.01) && + Geom::are_near(end, end_stored, 0.01) && + !this->upd_params && + !colorchanged) { continue; } Geom::Point hstart = start; Geom::Point hend = end; bool remove = false; - if (Geom::are_near(hstart, hend)) { - remove = true; - } - if (orientation == OM_VERTICAL) { Coord xpos = std::max(hstart[Geom::X],hend[Geom::X]); if (flip_side) { @@ -682,16 +810,23 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) if (Geom::are_near(hstart[Geom::X], hend[Geom::X])) { remove = true; } - } else if (fix_overlaps != 180) { - start_angle_cross = getAngle( start, prev, end, flip_side, fix_overlaps); + } else if (fix_overlaps_degree != 180) { + start_angle_cross = getAngle( start, prev, end, flip_side, fix_overlaps_degree); if (prev == Geom::Point(0,0)) { start_angle_cross = 0; } - end_angle_cross = getAngle(end, start, next, flip_side, fix_overlaps); + end_angle_cross = getAngle(end, start, next, flip_side, fix_overlaps_degree); if (next == Geom::Point(0,0)) { end_angle_cross = 0; } } + if (remove) { + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-start-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-end-"), counter, true, true, true); + createTextLabel(Geom::Point(), counter, 0, 0, true, true); + continue; + } Geom::Ray ray(hstart,hend); Geom::Coord angle = ray.angle(); if (flip_side) { @@ -708,36 +843,42 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) start_angle_cross *= -1; //turn *= -1; } - if (fix_overlaps != 180 && start_angle_cross != 0) { - double position_turned = position / sin(start_angle_cross/2.0); - hstart = hstart - Point::polar(angle_cross - (start_angle_cross/2.0) - turn, position_turned); + double position_turned_start = position / sin(start_angle_cross/2.0); + double length = Geom::distance(start,end); + if (fix_overlaps_degree != 180 && + start_angle_cross != 0 && + position_turned_start < length && + previous_fix_overlaps) + { + hstart = hstart - Point::polar(angle_cross - (start_angle_cross/2.0) - turn, position_turned_start); } else { hstart = hstart - Point::polar(angle_cross, position); } - createLine(start, hstart, g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, remove); - - if (fix_overlaps != 180 && end_angle_cross != 0) { - double position_turned = position / sin(end_angle_cross/2.0); - hend = hend - Point::polar(angle_cross + (end_angle_cross/2.0) + turn, position_turned); + createLine(start, hstart, Glib::ustring("infoline-on-start-"), counter, false, false); + double position_turned_end = position / sin(end_angle_cross/2.0); + double endlength = Geom::distance(end,next); + if (fix_overlaps_degree != 180 && + end_angle_cross != 0 && + position_turned_end < length && + position_turned_end < endlength) + { + hend = hend - Point::polar(angle_cross + (end_angle_cross/2.0) + turn, position_turned_end); + previous_fix_overlaps = true; } else { hend = hend - Point::polar(angle_cross, position); + previous_fix_overlaps = false; } - double length = Geom::distance(hstart,hend) * scale; + length = Geom::distance(start,end) * scale; Geom::Point pos = Geom::middle_point(hstart,hend); if (arrows_outside) { - createArrowMarker("ArrowDINout-start"); - createArrowMarker("ArrowDINout-end"); + createArrowMarker(Glib::ustring("ArrowDINout-start")); + createArrowMarker(Glib::ustring("ArrowDINout-end")); } else { - createArrowMarker("ArrowDIN-start"); - createArrowMarker("ArrowDIN-end"); + createArrowMarker(Glib::ustring("ArrowDIN-start")); + createArrowMarker(Glib::ustring("ArrowDIN-end")); } - //We get the font size to offset the text to the middle - Pango::FontDescription fontdesc(Glib::ustring(fontbutton.param_getSVGValue())); - fontsize = fontdesc.get_size()/(double)Pango::SCALE; - fontsize *= document->getRoot()->c2p.inverse().expansionX(); - if (angle >= rad_from_deg(90) && angle < rad_from_deg(270)) { - pos = pos - Point::polar(angle_cross, text_top_bottom + (fontsize/2.5)); + pos = pos - Point::polar(angle_cross, text_top_bottom + (fontsize/2.5)); } else { pos = pos + Point::polar(angle_cross, text_top_bottom + (fontsize/2.5)); } @@ -753,55 +894,42 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) } else { createTextLabel(pos, counter, length, angle, remove, true); } - const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); arrow_gap = 8 * Inkscape::Util::Quantity::convert(line_width / doc_scale, "mm", display_unit.c_str()); SPCSSAttr *css = sp_repr_css_attr_new(); - char *oldlocale = g_strdup (setlocale(LC_NUMERIC, NULL)); setlocale (LC_NUMERIC, "C"); double width_line = atof(sp_repr_css_property(css,"stroke-width","-1")); - setlocale (LC_NUMERIC, oldlocale); - g_free (oldlocale); + setlocale (LC_NUMERIC, locale_base); if (width_line > -0.0001) { arrow_gap = 8 * Inkscape::Util::Quantity::convert(width_line/ doc_scale, "mm", display_unit.c_str()); } if(flip_side) { arrow_gap *= -1; } - createLine(end, hend, g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), false, remove); + createLine(end, hend, Glib::ustring("infoline-on-end-"), counter, false, false); if (!arrows_outside) { hstart = hstart + Point::polar(angle, arrow_gap); hend = hend - Point::polar(angle, arrow_gap ); } - if ((anotation_width/2) < Geom::distance(hstart,hend)/2.0) { - createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, remove, true); + if ((anotation_width/2.0) + arrow_gap < Geom::distance(hstart,hend)/2.0) { + createLine(hstart, hend, Glib::ustring("infoline-"), counter, true, false, true); } else { - createLine(hstart, hend, g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); + createLine(hstart, hend, Glib::ustring("infoline-"), counter, true, true, true); } } else { - const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - createLine(Geom::Point(),Geom::Point(), downline, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - SPObject *elemref = NULL; - if ((elemref = document->getObjectById(id))) { - elemref->deleteObject(); - } + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-start-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-end-"), counter, true, true, true); + createTextLabel(Geom::Point(), counter, 0, 0, true, true); } } } - for (size_t k = ncurves; k <= previous_size; k++) { - const char * downline = g_strdup(Glib::ustring("downline-").append(Glib::ustring::format(counter) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - createLine(Geom::Point(),Geom::Point(), downline, true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-start-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - createLine(Geom::Point(), Geom::Point(), g_strdup(Glib::ustring("infoline-on-end-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()), true, true, true); - const char * id = g_strdup(Glib::ustring("text-on-").append(Glib::ustring::format(k) + Glib::ustring("-")).append(this->getRepr()->attribute("id")).c_str()); - SPObject *elemref = NULL; - if ((elemref = document->getObjectById(id))) { - elemref->deleteObject(); + if (previous_size) { + for (size_t counter = ncurves; counter < previous_size; counter++) { + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-start-"), counter, true, true, true); + createLine(Geom::Point(), Geom::Point(), Glib::ustring("infoline-on-end-"), counter, true, true, true); + createTextLabel(Geom::Point(), counter, 0, 0, true, true); } } previous_size = ncurves; @@ -837,12 +965,6 @@ LPEMeasureSegments::transform_multiply(Geom::Affine const& postmul, bool set) } } -Geom::PathVector -LPEMeasureSegments::doEffect_path(Geom::PathVector const &path_in) -{ - return path_in; -} - }; //namespace LivePathEffect }; /* namespace Inkscape */ diff --git a/src/live_effects/lpe-measure-segments.h b/src/live_effects/lpe-measure-segments.h index 903a5cbd2..1b6a5a81d 100644 --- a/src/live_effects/lpe-measure-segments.h +++ b/src/live_effects/lpe-measure-segments.h @@ -11,19 +11,16 @@ */ #include "live_effects/effect.h" -#include "ui/dialog/styledialog.h" - +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" +#include "live_effects/parameter/bool.h" +#include "live_effects/parameter/colorpicker.h" #include "live_effects/parameter/enum.h" #include "live_effects/parameter/fontbutton.h" +#include "live_effects/parameter/message.h" #include "live_effects/parameter/text.h" #include "live_effects/parameter/unit.h" -#include "live_effects/parameter/bool.h" -#include "live_effects/parameter/colorpicker.h" -#include "live_effects/parameter/message.h" -#include <libnrtype/font-lister.h> -#include <2geom/angle.h> -#include <2geom/ray.h> -#include <2geom/point.h> + namespace Inkscape { namespace LivePathEffect { @@ -39,16 +36,15 @@ class LPEMeasureSegments : public Effect { public: LPEMeasureSegments(LivePathEffectObject *lpeobject); virtual ~LPEMeasureSegments(); - virtual void doBeforeEffect (SPLPEItem const* lpeitem); virtual void doOnApply(SPLPEItem const* lpeitem); - virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); - virtual void doEffect (SPCurve * curve){}; //stop the chain + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual void doOnRemove(SPLPEItem const* /*lpeitem*/); + virtual void doEffect(SPCurve * curve){}; //stop the chain virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); virtual void transform_multiply(Geom::Affine const& postmul, bool set); - virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in); - void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool remove, bool arrows = false); + void createLine(Geom::Point start,Geom::Point end, Glib::ustring name, size_t counter, bool main, bool remove, bool arrows = false); void createTextLabel(Geom::Point pos, size_t counter, double length, Geom::Coord angle, bool remove, bool valid); - void createArrowMarker(const char * mode); + void createArrowMarker(Glib::ustring mode); bool hasMeassure (size_t i); private: UnitParam unit; @@ -78,7 +74,9 @@ private: double fontsize; double anotation_width; double previous_size; + unsigned rgb24; double arrow_gap; + gchar const* locale_base; Geom::Affine star_ellipse_fix; LPEMeasureSegments(const LPEMeasureSegments &); LPEMeasureSegments &operator=(const LPEMeasureSegments &); diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp index 926977a07..1e62a98d5 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -15,8 +15,6 @@ */ #include <gtkmm.h> -#include "live_effects/lpeobject.h" -#include "live_effects/lpeobject-reference.h" #include "live_effects/lpe-mirror_symmetry.h" #include "display/curve.h" #include "svg/path-string.h" @@ -41,7 +39,7 @@ namespace Inkscape { namespace LivePathEffect { -static const Util::EnumData<ModeType> ModeTypeData[MT_END] = { +static const Util::EnumData<ModeType> ModeTypeData[] = { { MT_V, N_("Vertical Page Center"), "vertical" }, { MT_H, N_("Horizontal Page Center"), "horizontal" }, { MT_FREE, N_("Free from reflection line"), "free" }, @@ -51,6 +49,7 @@ static const Util::EnumData<ModeType> ModeTypeData[MT_END] = { static const Util::EnumDataConverter<ModeType> MTConverter(ModeTypeData, MT_END); + LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : Effect(lpeobject), mode(_("Mode"), _("Symmetry move mode"), "mode", MTConverter, &wr, this, MT_FREE), @@ -61,8 +60,7 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : split_items(_("Split elements"), _("Split elements, this allow gradients and other paints."), "split_items", &wr, this, false), start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, _("Adjust start of mirroring")), end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, _("Adjust end of mirroring")), - center_point(_("Center mirror line"), _("Center mirror line"), "center_point", &wr, this, _("Adjust center of mirroring")), - id_origin("id origin", "store the id of the first LPEItem", "id_origin", &wr, this,"") + center_point(_("Center mirror line"), _("Center mirror line"), "center_point", &wr, this, _("Adjust center of mirroring")) { show_orig_path = true; registerParameter(&mode); @@ -74,15 +72,13 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) : registerParameter(&start_point); registerParameter(&end_point); registerParameter(¢er_point); - registerParameter(&id_origin); - id_origin.param_hide_canvas_text(); split_gap.param_set_range(-999999.0, 999999.0); split_gap.param_set_increments(0.1, 0.1); split_gap.param_set_digits(5); apply_to_clippath_and_mask = true; previous_center = Geom::Point(0,0); - id_origin.param_widget_is_visible(false); center_point.param_widget_is_visible(false); + reset = false; } LPEMirrorSymmetry::~LPEMirrorSymmetry() @@ -97,30 +93,71 @@ LPEMirrorSymmetry::doAfterEffect (SPLPEItem const* lpeitem) if (!document) { return; } + container = dynamic_cast<SPObject *>(sp_lpe_item->parent); + Inkscape::XML::Node *root = sp_lpe_item->document->getReprRoot(); + Inkscape::XML::Node *root_origin = document->getReprRoot(); + if (root_origin != root) { + return; + } + if (split_items && !discard_orig_path) { - container = dynamic_cast<SPObject *>(sp_lpe_item->parent); - Inkscape::XML::Node *root = sp_lpe_item->document->getReprRoot(); - Inkscape::XML::Node *root_origin = document->getReprRoot(); - if (root_origin != root) { - return; - } Geom::Line ls((Geom::Point)start_point, (Geom::Point)end_point); Geom::Affine m = Geom::reflection (ls.vector(), (Geom::Point)start_point); m = m * sp_lpe_item->transform; - toMirror(m); + toMirror(m, reset); + reset = false; } else { processObjects(LPE_ERASE); items.clear(); } } +Gtk::Widget * +LPEMirrorSymmetry::newWidget() +{ + // 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; + Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(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; + } + Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0)); + Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset styles")))); + reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPEMirrorSymmetry::resetStyles)); + reset_button->set_size_request(110,20); + vbox->pack_start(*hbox, true,true,2); + hbox->pack_start(*reset_button, false, false,2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } + return dynamic_cast<Gtk::Widget *>(vbox); +} + void LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) { - using namespace Geom; - original_bbox(lpeitem); - //center_point->param_set_liveupdate(false); + original_bbox(lpeitem, false, true); Point point_a(boundingbox_X.max(), boundingbox_Y.min()); Point point_b(boundingbox_X.max(), boundingbox_Y.max()); if (mode == MT_Y) { @@ -140,7 +177,7 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) } if ( mode == MT_X || mode == MT_Y ) { if (!are_near(previous_center, (Geom::Point)center_point, 0.01)) { - center_point.param_setValue(Geom::middle_point(point_a, point_b), true); + center_point.param_setValue(Geom::middle_point(point_a, point_b)); end_point.param_setValue(point_b); start_point.param_setValue(point_a); } else { @@ -163,10 +200,12 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) } else if ( mode == MT_FREE) { if (are_near(previous_center, (Geom::Point)center_point, 0.01)) { center_point.param_setValue(Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point)); + } else { Geom::Point trans = center_point - Geom::middle_point((Geom::Point)start_point, (Geom::Point)end_point); start_point.param_setValue(start_point * trans); end_point.param_setValue(end_point * trans); + } } else if ( mode == MT_V){ SPDocument * document = SP_ACTIVE_DOCUMENT; @@ -193,7 +232,7 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem) } void -LPEMirrorSymmetry::cloneD(SPObject *orig, SPObject *dest, bool live, bool root) +LPEMirrorSymmetry::cloneD(SPObject *orig, SPObject *dest, bool reset) { SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { @@ -206,108 +245,99 @@ LPEMirrorSymmetry::cloneD(SPObject *orig, SPObject *dest, bool live, bool root) for (std::vector<SPObject * >::iterator obj_it = childs.begin(); obj_it != childs.end(); ++obj_it) { SPObject *dest_child = dest->nthChild(index); - cloneD(*obj_it, dest_child, live, false); + cloneD(*obj_it, dest_child, reset); index++; } + return; } SPShape * shape = SP_SHAPE(orig); SPPath * path = SP_PATH(dest); - if (shape && !path) { - Inkscape::XML::Node *dest_node = sp_selected_item_to_curved_repr(SP_ITEM(dest), 0); - dest->updateRepr(xml_doc, dest_node, SP_OBJECT_WRITE_ALL); - path = SP_PATH(dest); - } if (path && shape) { - if ( live) { - SPCurve *c = NULL; - if (root) { - c = new SPCurve(); - c->set_pathvector(pathvector_after_effect); - } else { - c = shape->getCurve(); - } - if (c) { - path->setCurve(c, TRUE); - c->unref(); - } else { - dest->getRepr()->setAttribute("d", NULL); - } + SPCurve *c = shape->getCurve(); + if (c) { + gchar *str = sp_svg_write_path(c->get_pathvector()); + dest->getRepr()->setAttribute("d", str); + g_free(str); + c->unref(); } else { - dest->getRepr()->setAttribute("d", orig->getRepr()->attribute("d")); + dest->getRepr()->setAttribute("d", NULL); + } + if (reset) { + dest->getRepr()->setAttribute("style", shape->getRepr()->attribute("style")); + } + } +} + +Inkscape::XML::Node * +LPEMirrorSymmetry::createPathBase(SPObject *elemref) { + SPDocument * document = SP_ACTIVE_DOCUMENT; + if (!document) { + return NULL; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Inkscape::XML::Node *prev = elemref->getRepr(); + SPGroup *group = dynamic_cast<SPGroup *>(elemref); + if (group) { + Inkscape::XML::Node *container = xml_doc->createElement("svg:g"); + container->setAttribute("transform", prev->attribute("transform")); + std::vector<SPItem*> const item_list = sp_item_group_item_list(group); + Inkscape::XML::Node *previous = NULL; + for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPObject *sub_item = *iter; + Inkscape::XML::Node *resultnode = createPathBase(sub_item); + container->addChild(resultnode, previous); + previous = resultnode; } + return container; } + Inkscape::XML::Node *resultnode = xml_doc->createElement("svg:path"); + resultnode->setAttribute("transform", prev->attribute("transform")); + return resultnode; } void -LPEMirrorSymmetry::toMirror(Geom::Affine transform) +LPEMirrorSymmetry::toMirror(Geom::Affine transform, bool reset) { SPDocument * document = SP_ACTIVE_DOCUMENT; - if (document) { - Inkscape::XML::Document *xml_doc = document->getReprDoc(); - const char * id_origin_char = id_origin.param_getSVGValue(); - const char * elemref_id = g_strdup(Glib::ustring("mirror-").append(id_origin_char).c_str()); - items.clear(); - items.push_back(elemref_id); - SPObject *elemref= NULL; - Inkscape::XML::Node *phantom = NULL; - if ((elemref = document->getObjectById(elemref_id))) { - phantom = elemref->getRepr(); - } else { - phantom = sp_lpe_item->getRepr()->duplicate(xml_doc); - std::vector<const char *> attrs; - attrs.push_back("inkscape:path-effect"); - attrs.push_back("inkscape:original-d"); - attrs.push_back("sodipodi:type"); - attrs.push_back("sodipodi:rx"); - attrs.push_back("sodipodi:ry"); - attrs.push_back("sodipodi:cx"); - attrs.push_back("sodipodi:cy"); - attrs.push_back("sodipodi:end"); - attrs.push_back("sodipodi:start"); - attrs.push_back("inkscape:flatsided"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:rounded"); - attrs.push_back("sodipodi:arg1"); - attrs.push_back("sodipodi:arg2"); - attrs.push_back("sodipodi:r1"); - attrs.push_back("sodipodi:r2"); - attrs.push_back("sodipodi:sides"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("sodipodi:argument"); - attrs.push_back("sodipodi:expansion"); - attrs.push_back("sodipodi:radius"); - attrs.push_back("sodipodi:revolution"); - attrs.push_back("sodipodi:t0"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("inkscape:randomized"); - attrs.push_back("x"); - attrs.push_back("y"); - attrs.push_back("rx"); - attrs.push_back("ry"); - attrs.push_back("width"); - attrs.push_back("height"); - for(const char * attr : attrs) { - phantom->setAttribute(attr, NULL); - } - } - phantom->setAttribute("id", elemref_id); - if (!elemref) { - elemref = container->appendChildRepr(phantom); - Inkscape::GC::release(phantom); - } - cloneD(SP_OBJECT(sp_lpe_item), elemref, true, true); - gchar *str = sp_svg_transform_write(transform); - elemref->getRepr()->setAttribute("transform" , str); - g_free(str); - if (elemref->parent != container) { - Inkscape::XML::Node *copy = phantom->duplicate(xml_doc); - copy->setAttribute("id", elemref_id); - container->appendChildRepr(copy); - Inkscape::GC::release(copy); - elemref->deleteObject(); - } + if (!document) { + return; + } + Inkscape::XML::Document *xml_doc = document->getReprDoc(); + Glib::ustring elemref_id = Glib::ustring("mirror-"); + elemref_id += this->lpeobj->getId(); + items.clear(); + items.push_back(elemref_id); + SPObject *elemref = NULL; + Inkscape::XML::Node *phantom = NULL; + if (elemref = document->getObjectById(elemref_id.c_str())) { + phantom = elemref->getRepr(); + } else { + phantom = createPathBase(sp_lpe_item); + phantom->setAttribute("id", elemref_id.c_str()); + reset = true; + } + if (!elemref) { + elemref = container->appendChildRepr(phantom); + Inkscape::GC::release(phantom); } + cloneD(SP_OBJECT(sp_lpe_item), elemref, reset); + gchar *str = sp_svg_transform_write(transform); + elemref->getRepr()->setAttribute("transform" , str); + g_free(str); + if (elemref->parent != container) { + Inkscape::XML::Node *copy = phantom->duplicate(xml_doc); + copy->setAttribute("id", elemref_id); + container->appendChildRepr(copy); + Inkscape::GC::release(copy); + elemref->deleteObject(); + } +} + + +void +LPEMirrorSymmetry::resetStyles(){ + reset = true; + doAfterEffect(sp_lpe_item); } //TODO: Migrate the tree next function to effect.cpp/h to avoid duplication @@ -345,7 +375,7 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); Point point_a(boundingbox_X.max(), boundingbox_Y.min()); Point point_b(boundingbox_X.max(), boundingbox_Y.max()); @@ -357,10 +387,6 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem) center_point.param_setValue(point_c); previous_center = center_point; SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); - if (!lpeitem->hasPathEffectOfType(this->effectType(), false) ){ //first applied not ready yet - id_origin.param_setValue(lpeitem->getRepr()->attribute("id")); - id_origin.write_to_SVG(); - } } diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h index e98c83f2b..d2d04c205 100644 --- a/src/live_effects/lpe-mirror_symmetry.h +++ b/src/live_effects/lpe-mirror_symmetry.h @@ -17,6 +17,8 @@ */ #include "live_effects/effect.h" +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" #include "live_effects/parameter/parameter.h" #include "live_effects/parameter/text.h" #include "live_effects/parameter/point.h" @@ -46,9 +48,11 @@ public: virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in); virtual void doOnRemove (SPLPEItem const* /*lpeitem*/); virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/); - void toMirror(Geom::Affine transform); - // void cloneAttrbutes(Inkscape::XML::Node * origin, Inkscape::XML::Node * dest, const char * first_attribute, ...); - void cloneD(SPObject *orig, SPObject *dest, bool live, bool root); + virtual Gtk::Widget * newWidget(); + void toMirror(Geom::Affine transform, bool reset); + void cloneD(SPObject *orig, SPObject *dest, bool reset); + Inkscape::XML::Node * createPathBase(SPObject *elemref); + void resetStyles(); protected: virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec); @@ -63,9 +67,9 @@ private: PointParam start_point; PointParam end_point; PointParam center_point; - TextParam id_origin; Geom::Point previous_center; SPObject * container; + bool reset; LPEMirrorSymmetry(const LPEMirrorSymmetry&); LPEMirrorSymmetry& operator=(const LPEMirrorSymmetry&); }; diff --git a/src/live_effects/lpe-patternalongpath.cpp b/src/live_effects/lpe-patternalongpath.cpp index 6e6f35f7d..115c777d0 100644 --- a/src/live_effects/lpe-patternalongpath.cpp +++ b/src/live_effects/lpe-patternalongpath.cpp @@ -316,7 +316,7 @@ KnotHolderEntityWidthPatternAlongPath::knot_set(Geom::Point const &p, Geom::Poin Geom::Point const s = snap_knot_position(p, state); SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item)); if (sp_shape) { - SPCurve *curve_before = sp_shape->getCurveBeforeLPE(); + SPCurve *curve_before = sp_shape->getCurveForEdit(); if (curve_before) { Geom::Path const *path_in = curve_before->first_path(); Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); @@ -349,7 +349,7 @@ KnotHolderEntityWidthPatternAlongPath::knot_get() const LPEPatternAlongPath *lpe = dynamic_cast<LPEPatternAlongPath *> (_effect); SPShape const *sp_shape = dynamic_cast<SPShape const *>(SP_LPE_ITEM(item)); if (sp_shape) { - SPCurve *curve_before = sp_shape->getCurveBeforeLPE(); + SPCurve *curve_before = sp_shape->getCurveForEdit(); if (curve_before) { Geom::Path const *path_in = curve_before->first_path(); Geom::Point ptA = path_in->pointAt(Geom::PathTime(0, 0.0)); diff --git a/src/live_effects/lpe-perp_bisector.cpp b/src/live_effects/lpe-perp_bisector.cpp index 2819094e7..afaa6b9ca 100644 --- a/src/live_effects/lpe-perp_bisector.cpp +++ b/src/live_effects/lpe-perp_bisector.cpp @@ -113,7 +113,7 @@ LPEPerpBisector::doOnApply (SPLPEItem const*/*lpeitem*/) { /* make the path a straight line */ /** - SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()? + SPCurve* curve = sp_path_getCurveForEdit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()? Geom::Point A(curve->first_point()); Geom::Point B(curve->last_point()); @@ -121,7 +121,7 @@ LPEPerpBisector::doOnApply (SPLPEItem const*/*lpeitem*/) SPCurve *c = new SPCurve(); c->moveto(A); c->lineto(B); - // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work? + // TODO: Why doesn't sp_path_set_curve_before_LPE(SP_PATH(lpeitem), c, TRUE, true) work? SP_PATH(lpeitem)->original_curve = c->ref(); c->unref(); **/ diff --git a/src/live_effects/lpe-perspective-envelope.cpp b/src/live_effects/lpe-perspective-envelope.cpp index 3cff83fed..e95cdfd4b 100644 --- a/src/live_effects/lpe-perspective-envelope.cpp +++ b/src/live_effects/lpe-perspective-envelope.cpp @@ -414,6 +414,9 @@ LPEPerspectiveEnvelope::newWidget() reset_button->set_size_request(140,30); vbox->pack_start(*hbox, true,true,2); hbox->pack_start(*reset_button, false, false,2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -462,7 +465,7 @@ LPEPerspectiveEnvelope::horizontal(PointParam ¶m_one, PointParam ¶m_two, void LPEPerspectiveEnvelope::doBeforeEffect (SPLPEItem const* lpeitem) { - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); Geom::Line vert(Geom::Point(boundingbox_X.middle(),boundingbox_Y.max()), Geom::Point(boundingbox_X.middle(), boundingbox_Y.min())); Geom::Line horiz(Geom::Point(boundingbox_X.min(),boundingbox_Y.middle()), Geom::Point(boundingbox_X.max(), boundingbox_Y.middle())); if(vertical_mirror) { @@ -503,7 +506,7 @@ void LPEPerspectiveEnvelope::resetDefaults(SPItem const* item) { Effect::resetDefaults(item); - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); setDefaults(); resetGrid(); } diff --git a/src/live_effects/lpe-perspective_path.cpp b/src/live_effects/lpe-perspective_path.cpp index 3484d00a5..deed40bde 100644 --- a/src/live_effects/lpe-perspective_path.cpp +++ b/src/live_effects/lpe-perspective_path.cpp @@ -255,6 +255,9 @@ LPEPerspectivePath::newWidget() Gtk::Widget* apply3DWidget = dynamic_cast<Gtk::Widget *>(apply3D); apply3DWidget->set_tooltip_text("Refresh perspective"); vbox->pack_start(*apply3DWidget, true, true,2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } diff --git a/src/live_effects/lpe-powerclip.cpp b/src/live_effects/lpe-powerclip.cpp index 2e90abfeb..60237b54e 100644 --- a/src/live_effects/lpe-powerclip.cpp +++ b/src/live_effects/lpe-powerclip.cpp @@ -44,11 +44,12 @@ LPEPowerClip::~LPEPowerClip() {} void LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ SPObject * clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); + gchar * uri_str = uri.param_getSVGValue(); if(hide_clip && clip_path) { SP_ITEM(sp_lpe_item)->clip_ref->detach(); - } else if (!hide_clip && !clip_path && uri.param_getSVGValue()) { + } else if (!hide_clip && !clip_path && uri_str) { try { - SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri_str)); } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); SP_ITEM(sp_lpe_item)->clip_ref->detach(); @@ -62,9 +63,10 @@ LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ if(!bbox) { return; } - if (uri.param_getSVGValue()) { + uri_str = uri.param_getSVGValue(); + if (uri_str) { try { - SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + SP_ITEM(sp_lpe_item)->clip_ref->attach(Inkscape::URI(uri_str)); } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); SP_ITEM(sp_lpe_item)->clip_ref->detach(); @@ -72,6 +74,7 @@ LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ } else { SP_ITEM(sp_lpe_item)->clip_ref->detach(); } + g_free(uri_str); Geom::Rect bboxrect = (*bbox); bboxrect.expandBy(1); Geom::Point topleft = bboxrect.corner(0); @@ -125,7 +128,7 @@ LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ Geom::PathVector c_pv = c->get_pathvector(); c_pv *= affine; c->set_pathvector(c_pv); - SP_SHAPE(clip_to_path)->setCurve(c, TRUE); + SP_SHAPE(clip_to_path)->setCurve(c); c->unref(); } @@ -144,28 +147,38 @@ LPEPowerClip::doBeforeEffect (SPLPEItem const* lpeitem){ Inkscape::GC::release(clip_path_node); clip_to_path->emitModified(SP_OBJECT_MODIFIED_CASCADE); } - if( is_inverse.param_getSVGValue() == (Glib::ustring)"false" && inverse && isVisible()) { + gchar * is_inverse_str = is_inverse.param_getSVGValue(); + if(!strcmp(is_inverse_str,"false") && inverse && isVisible()) { if (clip_to_path) { addInverse(SP_ITEM(clip_to_path)); } else { addInverse(SP_ITEM(clip_data)); } - } else if(is_inverse.param_getSVGValue() == (Glib::ustring)"true" && !inverse && isVisible()) { + } else if(!strcmp(is_inverse_str,"true") && !inverse && isVisible()) { if (clip_to_path) { removeInverse(SP_ITEM(clip_to_path)); } else { removeInverse(SP_ITEM(clip_data)); } - } else if (inverse && !is_visible && is_inverse.param_getSVGValue() == (Glib::ustring)"true"){ + } else if (inverse && !is_visible && is_inverse_str == (Glib::ustring)"true"){ removeInverse(SP_ITEM(clip_data)); } + g_free(is_inverse_str); } } } void +LPEPowerClip::doAfterEffect (SPLPEItem const* lpeitem){ + if (!hide_clip && flatten && isVisible()) { + SP_ITEM(sp_lpe_item)->clip_ref->detach(); + } +} + +void LPEPowerClip::addInverse (SPItem * clip_data){ - if(is_inverse.param_getSVGValue() == (Glib::ustring)"false") { + gchar * is_inverse_str = is_inverse.param_getSVGValue(); + if(!strcmp(is_inverse_str,"false")) { if (SP_IS_GROUP(clip_data)) { std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_data)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { @@ -185,9 +198,12 @@ LPEPowerClip::addInverse (SPItem * clip_data){ } c_pv.push_back(clip_box); c->set_pathvector(c_pv); - SP_SHAPE(clip_data)->setCurve(c, TRUE); + SP_SHAPE(clip_data)->setCurve(c); c->unref(); - is_inverse.param_setValue((Glib::ustring)"true", true); + gchar * is_inverse_str = is_inverse.param_getSVGValue(); + if (strcmp(is_inverse_str, "true") != 0) { + is_inverse.param_setValue((Glib::ustring)"true", true); + } SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop) { if (tools_isactive(desktop, TOOLS_NODES)) { @@ -202,11 +218,13 @@ LPEPowerClip::addInverse (SPItem * clip_data){ } } } + g_free(is_inverse_str); } void LPEPowerClip::removeInverse (SPItem * clip_data){ - if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + gchar * is_inverse_str = is_inverse.param_getSVGValue(); + if(!strcmp(is_inverse_str,"true")) { if (SP_IS_GROUP(clip_data)) { std::vector<SPItem*> item_list = sp_item_group_item_list(SP_GROUP(clip_data)); for ( std::vector<SPItem*>::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { @@ -222,9 +240,12 @@ LPEPowerClip::removeInverse (SPItem * clip_data){ c_pv.pop_back(); } c->set_pathvector(c_pv); - SP_SHAPE(clip_data)->setCurve(c, TRUE); + SP_SHAPE(clip_data)->setCurve(c); c->unref(); - is_inverse.param_setValue((Glib::ustring)"false", true); + gchar * is_inverse_str = is_inverse.param_getSVGValue(); + if (strcmp(is_inverse_str, "false") != 0) { + is_inverse.param_setValue((Glib::ustring)"false", true); + } SPDesktop *desktop = SP_ACTIVE_DESKTOP; if (desktop) { if (tools_isactive(desktop, TOOLS_NODES)) { @@ -239,6 +260,7 @@ LPEPowerClip::removeInverse (SPItem * clip_data){ } } } + g_free(is_inverse_str); } void @@ -281,6 +303,9 @@ LPEPowerClip::newWidget() topaths_button->set_size_request(220,30); hbox->pack_start(*topaths_button, false, false,2); vbox->pack_start(*hbox, true,true,2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } @@ -290,13 +315,15 @@ LPEPowerClip::doOnRemove (SPLPEItem const* /*lpeitem*/) SPClipPath *clip_path = SP_ITEM(sp_lpe_item)->clip_ref->getObject(); if(!keep_paths) { if(clip_path) { + gchar * is_inverse_str = is_inverse.param_getSVGValue(); 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; - if(is_inverse.param_getSVGValue() == (Glib::ustring)"true") { + if(!strcmp(is_inverse_str,"true")) { removeInverse(SP_ITEM(clip_data)); } } + g_free(is_inverse_str); } } else { if (flatten && clip_path) { @@ -317,7 +344,6 @@ LPEPowerClip::doEffect_path(Geom::PathVector const & path_in){ flattenClip(SP_ITEM(clip_data), path_out); } } - SP_ITEM(sp_lpe_item)->clip_ref->detach(); } return path_out; } diff --git a/src/live_effects/lpe-powerclip.h b/src/live_effects/lpe-powerclip.h index 6f99d220f..240a1809b 100644 --- a/src/live_effects/lpe-powerclip.h +++ b/src/live_effects/lpe-powerclip.h @@ -23,6 +23,7 @@ public: virtual Gtk::Widget * newWidget(); //virtual void transform_multiply(Geom::Affine const& postmul, bool set); virtual void doOnVisibilityToggled(SPLPEItem const* lpeitem); + virtual void doAfterEffect (SPLPEItem const* lpeitem); void addInverse (SPItem * clip_data); void removeInverse (SPItem * clip_data); void flattenClip(SPItem * clip_data, Geom::PathVector &path_in); diff --git a/src/live_effects/lpe-powermask.cpp b/src/live_effects/lpe-powermask.cpp index 947482c24..202c97259 100644 --- a/src/live_effects/lpe-powermask.cpp +++ b/src/live_effects/lpe-powermask.cpp @@ -50,13 +50,14 @@ LPEPowerMask::~LPEPowerMask() {} void LPEPowerMask::doBeforeEffect (SPLPEItem const* lpeitem){ - //To avoid close of color dialog and better performance on change color + //To avoid close of color dialog and better performance on change color SPObject * mask = SP_ITEM(sp_lpe_item)->mask_ref->getObject(); + gchar * uri_str = uri.param_getSVGValue(); if(hide_mask && mask) { SP_ITEM(sp_lpe_item)->mask_ref->detach(); - } else if (!hide_mask && !mask && uri.param_getSVGValue()) { + } else if (!hide_mask && !mask && uri_str) { try { - SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri_str)); } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); SP_ITEM(sp_lpe_item)->mask_ref->detach(); @@ -72,11 +73,13 @@ LPEPowerMask::doBeforeEffect (SPLPEItem const* lpeitem){ SP_ITEM(sp_lpe_item)->mask_ref->detach(); Geom::OptRect bbox = sp_lpe_item->visualBounds(); if(!bbox) { + g_free(uri_str); return; } - if (uri.param_getSVGValue()) { + uri_str = uri.param_getSVGValue(); + if (uri_str) { try { - SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri.param_getSVGValue())); + SP_ITEM(sp_lpe_item)->mask_ref->attach(Inkscape::URI(uri_str)); } catch (Inkscape::BadURIException &e) { g_warning("%s", e.what()); SP_ITEM(sp_lpe_item)->mask_ref->detach(); @@ -99,6 +102,7 @@ LPEPowerMask::doBeforeEffect (SPLPEItem const* lpeitem){ setMask(); } } + g_free(uri_str); } void diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp index 6d63ffa81..1d64e9042 100644 --- a/src/live_effects/lpe-powerstroke.cpp +++ b/src/live_effects/lpe-powerstroke.cpp @@ -170,13 +170,13 @@ LPEPowerStroke::LPEPowerStroke(LivePathEffectObject *lpeobject) : Effect(lpeobject), offset_points(_("Offset points"), _("Offset points"), "offset_points", &wr, this), sort_points(_("Sort points"), _("Sort offset points according to their time value along the curve"), "sort_points", &wr, this, true), - interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CUBICBEZIER), + interpolator_type(_("Interpolator type:"), _("Determines which kind of interpolator will be used to interpolate between stroke width along the path"), "interpolator_type", InterpolatorTypeConverter, &wr, this, Geom::Interpolate::INTERP_CENTRIPETAL_CATMULLROM), interpolator_beta(_("Smoothness:"), _("Sets the smoothness for the CubicBezierJohan interpolator; 0 = linear interpolation, 1 = smooth"), "interpolator_beta", &wr, this, 0.2), scale_width(_("Width scale:"), _("Width scale all points"), "scale_width", &wr, this, 1.0), - start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT), - linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_EXTRP_MITER_ARC), + start_linecap_type(_("Start cap:"), _("Determines the shape of the path's start"), "start_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ZERO_WIDTH), + linejoin_type(_("Join:"), _("Determines the shape of the path's corners"), "linejoin_type", LineJoinTypeConverter, &wr, this, LINEJOIN_ROUND), miter_limit(_("Miter limit:"), _("Maximum length of the miter (in units of stroke width)"), "miter_limit", &wr, this, 4.), - end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_BUTT) + end_linecap_type(_("End cap:"), _("Determines the shape of the path's end"), "end_linecap_type", LineCapTypeConverter, &wr, this, LINECAP_ZERO_WIDTH) { show_orig_path = true; diff --git a/src/live_effects/lpe-roughen.cpp b/src/live_effects/lpe-roughen.cpp index e847494a2..e78ab99fd 100644 --- a/src/live_effects/lpe-roughen.cpp +++ b/src/live_effects/lpe-roughen.cpp @@ -163,6 +163,9 @@ Gtk::Widget *LPERoughen::newWidget() } ++it; } + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp index 149425112..35da722d0 100644 --- a/src/live_effects/lpe-show_handles.cpp +++ b/src/live_effects/lpe-show_handles.cpp @@ -95,7 +95,7 @@ Geom::PathVector LPEShowHandles::doEffect_path (Geom::PathVector const & path_in outline_path.clear(); } if (original_d) { - SPCurve * shape_curve = sp_shape->getCurveBeforeLPE(); + SPCurve * shape_curve = current_shape->getCurveForEdit(); if (shape_curve) { Geom::PathVector original_curve = shape_curve->get_pathvector(); if(original_path) { diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp index 5de9816bb..e676f37a0 100644 --- a/src/live_effects/lpe-simplify.cpp +++ b/src/live_effects/lpe-simplify.cpp @@ -115,6 +115,9 @@ LPESimplify::newWidget() ++it; } vbox->pack_start(*buttons,true, true, 2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } diff --git a/src/live_effects/lpe-transform_2pts.cpp b/src/live_effects/lpe-transform_2pts.cpp index 914d23e4b..47f8864ce 100644 --- a/src/live_effects/lpe-transform_2pts.cpp +++ b/src/live_effects/lpe-transform_2pts.cpp @@ -89,13 +89,13 @@ void LPETransform2Pts::doOnApply(SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); point_a = Point(boundingbox_X.min(), boundingbox_Y.middle()); point_b = Point(boundingbox_X.max(), boundingbox_Y.middle()); SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem); if (sp_path) { - pathvector = sp_path->get_original_curve()->get_pathvector(); + pathvector = sp_path->getCurveForEdit()->get_pathvector(); } if(!pathvector.empty()) { point_a = pathvector.initialPoint(); @@ -120,14 +120,14 @@ void LPETransform2Pts::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); point_a = Point(boundingbox_X.min(), boundingbox_Y.middle()); point_b = Point(boundingbox_X.max(), boundingbox_Y.middle()); SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem); SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem); if (sp_path) { - pathvector = sp_path->get_original_curve()->get_pathvector(); + pathvector = sp_path->getCurveForEdit()->get_pathvector(); } if(from_original_width_toggler != from_original_width) { from_original_width_toggler = from_original_width; @@ -183,7 +183,7 @@ LPETransform2Pts::updateIndex() SPLPEItem * splpeitem = const_cast<SPLPEItem *>(sp_lpe_item); SPPath *sp_path = dynamic_cast<SPPath *>(splpeitem); if (sp_path) { - pathvector = sp_path->get_original_curve()->get_pathvector(); + pathvector = sp_path->getCurveForEdit()->get_pathvector(); } if(pathvector.empty()) { return; @@ -362,6 +362,9 @@ Gtk::Widget *LPETransform2Pts::newWidget() vbox->pack_start(*button2, true, true, 2); vbox->pack_start(*button3, true, true, 2); vbox->pack_start(*button4, true, true, 2); + if(Gtk::Widget* widg = defaultParamSet()) { + vbox->pack_start(*widg, true, true, 2); + } return dynamic_cast<Gtk::Widget *>(vbox); } diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp index f04c243f6..33460aa2d 100644 --- a/src/live_effects/lpe-vonkoch.cpp +++ b/src/live_effects/lpe-vonkoch.cpp @@ -239,7 +239,7 @@ void LPEVonKoch::doBeforeEffect (SPLPEItem const* lpeitem) { using namespace Geom; - original_bbox(lpeitem); + original_bbox(lpeitem, false, true); Geom::PathVector paths = ref_path.get_pathvector(); Geom::Point A,B; @@ -269,7 +269,7 @@ LPEVonKoch::resetDefaults(SPItem const* item) Effect::resetDefaults(item); using namespace Geom; - original_bbox(SP_LPE_ITEM(item)); + original_bbox(SP_LPE_ITEM(item), false, true); Point A,B; A[Geom::X] = boundingbox_X.min(); diff --git a/src/live_effects/lpegroupbbox.cpp b/src/live_effects/lpegroupbbox.cpp index 8a42fc8b6..6df6278b1 100644 --- a/src/live_effects/lpegroupbbox.cpp +++ b/src/live_effects/lpegroupbbox.cpp @@ -5,8 +5,13 @@ * Released under GNU GPL, read the file 'COPYING' for more information */ +#include "document.h" #include "live_effects/lpegroupbbox.h" - +#include "object/sp-clippath.h" +#include "object/sp-mask.h" +#include "object/sp-root.h" +#include "object/sp-shape.h" +#include "object/sp-item-group.h" #include "object/sp-lpe-item.h" namespace Inkscape { @@ -22,7 +27,32 @@ namespace LivePathEffect { * or of the transformed lpeitem (\c absolute = \c true) using sp_item_i2doc_affine. * @post Updated values of boundingbox_X and boundingbox_Y. These intervals are set to empty intervals when the precondition is not met. */ -void GroupBBoxEffect::original_bbox(SPLPEItem const* lpeitem, bool absolute) + +Geom::OptRect +GroupBBoxEffect::clip_mask_bbox(SPLPEItem *item, Geom::Affine transform) +{ + Geom::OptRect bbox; + Geom::Affine affine = transform * item->transform; + SPClipPath * clip_path = item->clip_ref->getObject(); + if(clip_path) { + bbox.unionWith(clip_path->geometricBounds(affine)); + } + SPMask * mask_path = item->mask_ref->getObject(); + if(mask_path) { + bbox.unionWith(mask_path->visualBounds(affine)); + } + SPGroup * group = dynamic_cast<SPGroup *>(item); + 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) { + SPLPEItem * subitem = dynamic_cast<SPLPEItem *>(*iter); + bbox.unionWith(clip_mask_bbox(subitem, affine)); + } + } + return bbox; +} + +void GroupBBoxEffect::original_bbox(SPLPEItem const* lpeitem, bool absolute, bool clip_mask) { // Get item bounding box Geom::Affine transform; @@ -32,8 +62,12 @@ void GroupBBoxEffect::original_bbox(SPLPEItem const* lpeitem, bool absolute) else { transform = Geom::identity(); } - + Geom::OptRect bbox = lpeitem->geometricBounds(transform); + if (clip_mask) { + SPLPEItem * item = const_cast<SPLPEItem *>(lpeitem); + bbox.unionWith(clip_mask_bbox(item, transform * item->transform.inverse())); + } if (bbox) { boundingbox_X = (*bbox)[Geom::X]; boundingbox_Y = (*bbox)[Geom::Y]; diff --git a/src/live_effects/lpegroupbbox.h b/src/live_effects/lpegroupbbox.h index 7d4ac3e78..de20138c9 100644 --- a/src/live_effects/lpegroupbbox.h +++ b/src/live_effects/lpegroupbbox.h @@ -18,12 +18,13 @@ namespace LivePathEffect { class GroupBBoxEffect { protected: - // Bounding box of the item the path effect is applied on + // Bounding box of the item the path effect is applied on Geom::Interval boundingbox_X; Geom::Interval boundingbox_Y; - //This sets boundingbox_X and boundingbox_Y - void original_bbox(SPLPEItem const* lpeitem, bool absolute = false); + //This sets boundingbox_X and boundingbox_Y + Geom::OptRect clip_mask_bbox(SPLPEItem * item, Geom::Affine transform); + void original_bbox(SPLPEItem const* lpeitem, bool absolute = false, bool clip_mask = false); }; }; //namespace LivePathEffect diff --git a/src/live_effects/parameter/array.h b/src/live_effects/parameter/array.h index c66d53266..b5ee8b5cf 100644 --- a/src/live_effects/parameter/array.h +++ b/src/live_effects/parameter/array.h @@ -64,8 +64,7 @@ public: virtual gchar * param_getSVGValue() const { Inkscape::SVGOStringStream os; writesvg(os, _vector); - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } virtual gchar * param_getDefaultSVGValue() const { diff --git a/src/live_effects/parameter/bool.cpp b/src/live_effects/parameter/bool.cpp index 1a01f269b..bfbda2bfd 100644 --- a/src/live_effects/parameter/bool.cpp +++ b/src/live_effects/parameter/bool.cpp @@ -57,15 +57,13 @@ BoolParam::param_readSVGValue(const gchar * strvalue) gchar * BoolParam::param_getSVGValue() const { - gchar * str = g_strdup(value ? "true" : "false"); - return str; + return g_strdup(value ? "true" : "false"); } gchar * BoolParam::param_getDefaultSVGValue() const { - gchar * str = g_strdup(defvalue ? "true" : "false"); - return str; + return g_strdup(defvalue ? "true" : "false"); } Gtk::Widget * diff --git a/src/live_effects/parameter/enum.h b/src/live_effects/parameter/enum.h index ca237c0f7..82eaa6d43 100644 --- a/src/live_effects/parameter/enum.h +++ b/src/live_effects/parameter/enum.h @@ -61,13 +61,11 @@ public: return true; }; gchar * param_getSVGValue() const { - gchar * str = g_strdup( enumdataconv->get_key(value).c_str() ); - return str; + return g_strdup( enumdataconv->get_key(value).c_str() ); }; gchar * param_getDefaultSVGValue() const { - gchar * str = g_strdup( enumdataconv->get_key(defvalue).c_str() ); - return str; + return g_strdup( enumdataconv->get_key(defvalue).c_str() ); }; E get_value() const { diff --git a/src/live_effects/parameter/hidden.cpp b/src/live_effects/parameter/hidden.cpp index e08881f6d..5a21f572b 100644 --- a/src/live_effects/parameter/hidden.cpp +++ b/src/live_effects/parameter/hidden.cpp @@ -55,8 +55,7 @@ HiddenParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << value; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -64,8 +63,7 @@ HiddenParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } Gtk::Widget * diff --git a/src/live_effects/parameter/message.cpp b/src/live_effects/parameter/message.cpp index 1e2c9ec50..03eb2219f 100644 --- a/src/live_effects/parameter/message.cpp +++ b/src/live_effects/parameter/message.cpp @@ -17,8 +17,8 @@ MessageParam::MessageParam( const Glib::ustring& label, const Glib::ustring& tip const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, Effect* effect, const gchar * default_message ) : Parameter(label, tip, key, wr, effect), - message(g_strdup(default_message)), - defmessage(g_strdup(default_message)) + message(default_message), + defmessage(default_message) { _label = NULL; _min_height = -1; @@ -33,7 +33,7 @@ MessageParam::param_set_default() void MessageParam::param_update_default(const gchar * default_message) { - defmessage = g_strdup(default_message); + defmessage = default_message; } bool @@ -46,13 +46,13 @@ MessageParam::param_readSVGValue(const gchar * strvalue) gchar * MessageParam::param_getSVGValue() const { - return message; + return g_strdup(message); } gchar * MessageParam::param_getDefaultSVGValue() const { - return defmessage; + return g_strdup(defmessage); } void @@ -106,7 +106,7 @@ MessageParam::param_setValue(const gchar * strvalue) if (strcmp(strvalue, message) != 0) { param_effect->upd_params = true; } - message = g_strdup(strvalue); + message = strvalue; } diff --git a/src/live_effects/parameter/message.h b/src/live_effects/parameter/message.h index 2ac2c791a..fd850a767 100644 --- a/src/live_effects/parameter/message.h +++ b/src/live_effects/parameter/message.h @@ -41,8 +41,8 @@ private: int _min_height; MessageParam(const MessageParam&); MessageParam& operator=(const MessageParam&); - gchar * message; - gchar * defmessage; + const gchar * message; + const gchar * defmessage; }; } //namespace LivePathEffect diff --git a/src/live_effects/parameter/originalitemarray.cpp b/src/live_effects/parameter/originalitemarray.cpp index fe2dc0c8d..b89485e2d 100644 --- a/src/live_effects/parameter/originalitemarray.cpp +++ b/src/live_effects/parameter/originalitemarray.cpp @@ -438,8 +438,7 @@ gchar * OriginalItemArrayParam::param_getSVGValue() const } os << (*iter)->href << "," << ((*iter)->actived ? "1" : "0"); } - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * OriginalItemArrayParam::param_getDefaultSVGValue() const diff --git a/src/live_effects/parameter/originalpath.cpp b/src/live_effects/parameter/originalpath.cpp index b6a90671e..018e1e69e 100644 --- a/src/live_effects/parameter/originalpath.cpp +++ b/src/live_effects/parameter/originalpath.cpp @@ -93,7 +93,7 @@ OriginalPathParam::linked_modified_callback(SPObject *linked_obj, guint /*flags* SPCurve *curve = NULL; if (SP_IS_SHAPE(linked_obj)) { if (_from_original_d) { - curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + curve = SP_SHAPE(linked_obj)->getCurveForEdit(); } else { curve = SP_SHAPE(linked_obj)->getCurve(); } diff --git a/src/live_effects/parameter/originalpatharray.cpp b/src/live_effects/parameter/originalpatharray.cpp index caec74a8b..928bf2976 100644 --- a/src/live_effects/parameter/originalpatharray.cpp +++ b/src/live_effects/parameter/originalpatharray.cpp @@ -428,9 +428,9 @@ void OriginalPathArrayParam::setPathVector(SPObject *linked_obj, guint /*flags*/ if (SP_IS_SHAPE(linked_obj)) { SPLPEItem * lpe_item = SP_LPE_ITEM(linked_obj); if (_from_original_d) { - curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + curve = SP_SHAPE(linked_obj)->getCurveForEdit(); } else if (_allow_only_bspline_spiro && lpe_item && lpe_item->hasPathEffect()){ - curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + curve = SP_SHAPE(linked_obj)->getCurveForEdit(); PathEffectList lpelist = lpe_item->getEffectList(); PathEffectList::iterator i; for (i = lpelist.begin(); i != lpelist.end(); ++i) { @@ -524,13 +524,12 @@ gchar * OriginalPathArrayParam::param_getSVGValue() const } os << (*iter)->href << "," << ((*iter)->reversed ? "1" : "0") << "," << ((*iter)->visibled ? "1" : "0"); } - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * OriginalPathArrayParam::param_getDefaultSVGValue() const { - return ""; + return g_strdup(""); } void OriginalPathArrayParam::update() diff --git a/src/live_effects/parameter/parameter.cpp b/src/live_effects/parameter/parameter.cpp index 497113e03..a175359f0 100644 --- a/src/live_effects/parameter/parameter.cpp +++ b/src/live_effects/parameter/parameter.cpp @@ -91,8 +91,7 @@ ScalarParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << value; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -100,8 +99,7 @@ ScalarParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } void @@ -129,6 +127,9 @@ ScalarParam::param_update_default(const gchar * default_value) void ScalarParam::param_set_value(gdouble val) { + if (value != val) { + param_effect->upd_params = true; + } value = val; if (integer) value = round(value); diff --git a/src/live_effects/parameter/path.cpp b/src/live_effects/parameter/path.cpp index 02075ee8e..ab385daa6 100644 --- a/src/live_effects/parameter/path.cpp +++ b/src/live_effects/parameter/path.cpp @@ -460,7 +460,7 @@ PathParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) SPCurve *curve = NULL; if (SP_IS_SHAPE(linked_obj)) { if (_from_original_d) { - curve = SP_SHAPE(linked_obj)->getCurveBeforeLPE(); + curve = SP_SHAPE(linked_obj)->getCurveForEdit(); } else { curve = SP_SHAPE(linked_obj)->getCurve(); } diff --git a/src/live_effects/parameter/point.cpp b/src/live_effects/parameter/point.cpp index 9b4723da3..b811b7f2b 100644 --- a/src/live_effects/parameter/point.cpp +++ b/src/live_effects/parameter/point.cpp @@ -128,8 +128,7 @@ PointParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << *dynamic_cast<Geom::Point const *>( this ); - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -137,8 +136,7 @@ PointParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } void @@ -212,10 +210,10 @@ PointParamKnotHolderEntity::knot_set(Geom::Point const &p, Geom::Point const &or s = A; } } - pparam->param_setValue(s); - SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item); - if(splpeitem && this->pparam->liveupdate){ - sp_lpe_item_update_patheffect(splpeitem, true, true); + if(this->pparam->liveupdate){ + pparam->param_setValue(s, true); + } else { + pparam->param_setValue(s); } } @@ -231,10 +229,7 @@ PointParamKnotHolderEntity::knot_click(guint state) if (state & GDK_CONTROL_MASK) { if (state & GDK_MOD1_MASK) { this->pparam->param_set_default(); - SPLPEItem * splpeitem = dynamic_cast<SPLPEItem *>(item); - if(splpeitem){ - sp_lpe_item_update_patheffect(splpeitem, true, true); - } + pparam->param_setValue(*pparam,true); } } } diff --git a/src/live_effects/parameter/random.cpp b/src/live_effects/parameter/random.cpp index 4afa43c6e..23912bedb 100644 --- a/src/live_effects/parameter/random.cpp +++ b/src/live_effects/parameter/random.cpp @@ -67,8 +67,7 @@ RandomParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << value << ';' << startseed; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -76,8 +75,7 @@ RandomParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue << ';' << defseed; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } void diff --git a/src/live_effects/parameter/text.cpp b/src/live_effects/parameter/text.cpp index 7e56b2c75..37ae3a1d7 100644 --- a/src/live_effects/parameter/text.cpp +++ b/src/live_effects/parameter/text.cpp @@ -112,8 +112,7 @@ TextParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << value; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -121,8 +120,7 @@ TextParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } void diff --git a/src/live_effects/parameter/togglebutton.cpp b/src/live_effects/parameter/togglebutton.cpp index e26884d6a..bb9d9a90e 100644 --- a/src/live_effects/parameter/togglebutton.cpp +++ b/src/live_effects/parameter/togglebutton.cpp @@ -55,15 +55,13 @@ ToggleButtonParam::param_readSVGValue(const gchar * strvalue) gchar * ToggleButtonParam::param_getSVGValue() const { - gchar * str = g_strdup(value ? "true" : "false"); - return str; + return g_strdup(value ? "true" : "false"); } gchar * ToggleButtonParam::param_getDefaultSVGValue() const { - gchar * str = g_strdup(defvalue ? "true" : "false"); - return str; + return g_strdup(defvalue ? "true" : "false"); } void diff --git a/src/live_effects/parameter/transformedpoint.cpp b/src/live_effects/parameter/transformedpoint.cpp index a010faf27..ab66e7256 100644 --- a/src/live_effects/parameter/transformedpoint.cpp +++ b/src/live_effects/parameter/transformedpoint.cpp @@ -78,8 +78,7 @@ TransformedPointParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << origin << " , " << vector; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -87,8 +86,7 @@ TransformedPointParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } void diff --git a/src/live_effects/parameter/vector.cpp b/src/live_effects/parameter/vector.cpp index ced93ef0d..1207a05da 100644 --- a/src/live_effects/parameter/vector.cpp +++ b/src/live_effects/parameter/vector.cpp @@ -97,8 +97,7 @@ VectorParam::param_getSVGValue() const { Inkscape::SVGOStringStream os; os << origin << " , " << vector; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } gchar * @@ -106,8 +105,7 @@ VectorParam::param_getDefaultSVGValue() const { Inkscape::SVGOStringStream os; os << defvalue; - gchar * str = g_strdup(os.str().c_str()); - return str; + return g_strdup(os.str().c_str()); } Gtk::Widget * 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); }; diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp index 2eb471bb3..7d5346f31 100644 --- a/src/path-chemistry.cpp +++ b/src/path-chemistry.cpp @@ -123,7 +123,7 @@ ObjectSet::combine(bool skip_undo) did = true; } - SPCurve *c = path->get_curve_for_edit(); + SPCurve *c = path->getCurveForEdit(); if (first == NULL) { // this is the topmost path first = item; parent = first->getRepr()->parent(); @@ -225,7 +225,7 @@ ObjectSet::breakApart(bool skip_undo) continue; } - SPCurve *curve = path->get_curve_for_edit(); + SPCurve *curve = path->getCurveForEdit(); if (curve == NULL) { continue; } @@ -650,7 +650,7 @@ ObjectSet::pathReverse() did = true; - SPCurve *rcurve = path->get_curve_reference()->create_reverse(); + SPCurve *rcurve = path->getCurveForEdit(true)->create_reverse(); gchar *str = sp_svg_write_path(rcurve->get_pathvector()); if ( path->hasPathEffectRecursive() ) { diff --git a/src/selection-chemistry.cpp b/src/selection-chemistry.cpp index ae2f63f97..622a843e4 100644 --- a/src/selection-chemistry.cpp +++ b/src/selection-chemistry.cpp @@ -771,10 +771,6 @@ Inkscape::XML::Node* ObjectSet::group() { group->setPosition(topmost + 1); set(doc->getObjectByRepr(group)); - SPLPEItem *lpeitem = dynamic_cast<SPLPEItem*>(*(items().begin())); - if (lpeitem) { - sp_lpe_item_update_patheffect(lpeitem, true, true); - } DocumentUndo::done(doc, SP_VERB_SELECTION_GROUP, C_("Verb", "Group")); @@ -4155,9 +4151,14 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { for (auto& child: obj->children) { // Collect all clipped paths and masks within a single group Inkscape::XML::Node *copy = child.getRepr()->duplicate(xml_doc); - if(copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) - { + if (copy->attribute("inkscape:original-d") && copy->attribute("inkscape:path-effect")) { copy->setAttribute("d", copy->attribute("inkscape:original-d")); + } else if (copy->attribute("inkscape:original-d")) { + copy->setAttribute("d", copy->attribute("inkscape:original-d")); + copy->setAttribute("inkscape:original-d", NULL); + } else if (!copy->attribute("inkscape:path-effect") && !SP_IS_PATH(&child)) { + copy->setAttribute("d", NULL); + copy->setAttribute("inkscape:original-d", NULL); } items_to_move.push_back(copy); } @@ -4204,7 +4205,6 @@ void ObjectSet::unsetMask(const bool apply_clip_path, const bool skip_undo) { // rebuild selection addList(items_to_select); - if (!skip_undo) { if (apply_clip_path) { DocumentUndo::done(doc, SP_VERB_OBJECT_UNSET_CLIPPATH, _("Release clipping path")); diff --git a/src/splivarot.cpp b/src/splivarot.cpp index 62d67469d..2a4ac9c34 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -2545,7 +2545,7 @@ SPCurve* curve_for_item(SPItem *item) SPCurve *curve = NULL; if (SP_IS_SHAPE(item)) { if (SP_IS_PATH(item)) { - curve = SP_PATH(item)->get_curve_for_edit(); + curve = SP_PATH(item)->getCurveForEdit(); } else { curve = SP_SHAPE(item)->getCurve(); } @@ -2573,7 +2573,7 @@ SPCurve* curve_for_item_before_LPE(SPItem *item) SPCurve *curve = NULL; if (SP_IS_SHAPE(item)) { - curve = SP_SHAPE(item)->getCurveBeforeLPE(); + curve = SP_SHAPE(item)->getCurveForEdit(); } else if (SP_IS_TEXT(item) || SP_IS_FLOWTEXT(item)) { diff --git a/src/style-internal.h b/src/style-internal.h index 2d49daad0..a0f31a6f0 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -875,7 +875,7 @@ public: } bool isNone() const { - return (paintOrigin == SP_CSS_PAINT_ORIGIN_NORMAL) && !colorSet && !isPaintserver(); + return !colorSet && !isPaintserver() && (paintOrigin == SP_CSS_PAINT_ORIGIN_NORMAL); } // TODO refine bool isColor() const { diff --git a/src/ui/dialog/livepatheffect-editor.cpp b/src/ui/dialog/livepatheffect-editor.cpp index ec8ae4f31..6cf7f807a 100644 --- a/src/ui/dialog/livepatheffect-editor.cpp +++ b/src/ui/dialog/livepatheffect-editor.cpp @@ -42,6 +42,7 @@ #include "object/sp-text.h" #include "ui/icon-names.h" +#include "ui/tools/node-tool.h" #include "ui/widget/imagetoggler.h" namespace Inkscape { @@ -205,42 +206,16 @@ LivePathEffectEditor::showParams(LivePathEffect::Effect& effect) lpe_changed = false; return; } - bool expanderopen = false; - Gtk::Widget * defaultswidget = effect.defaultParamSet(); - if (effectwidget) { - if (defaultswidget) { - Gtk::Expander * expander = NULL; - std::vector<Gtk::Widget *> childs = dynamic_cast<Gtk::Box *> (effectwidget)->get_children(); - if (childs.size()) { - std::vector<Gtk::Widget *> childs_default = dynamic_cast<Gtk::Box *> (childs[childs.size()-1])->get_children(); - if ((expander = dynamic_cast<Gtk::Expander *>(childs_default[childs_default.size()-1]))){ - expanderopen = expander->get_expanded(); - } - } - } effectcontrol_vbox.remove(*effectwidget); delete effectwidget; effectwidget = NULL; } - + effectwidget = effect.newWidget(); effectcontrol_frame.set_label(effect.getName()); + effectcontrol_vbox.pack_start(*effectwidget, true, true); - effectwidget = effect.newWidget(); - if (effectwidget) { - - if (defaultswidget) { - Gtk::Expander * expander = NULL; - std::vector<Gtk::Widget *> childs_default = dynamic_cast<Gtk::Box *> (defaultswidget)->get_children(); - if ((expander = dynamic_cast<Gtk::Expander *>(childs_default[childs_default.size()-1]))){ - expander->set_expanded(expanderopen); - } - dynamic_cast<Gtk::Box *> (effectwidget)->pack_start(*defaultswidget, true, true); - } - effectcontrol_vbox.pack_start(*effectwidget, true, true); - } button_remove.show(); - status_label.hide(); effectcontrol_frame.show(); effectcontrol_vbox.show_all_children(); @@ -254,7 +229,7 @@ LivePathEffectEditor::selectInList(LivePathEffect::Effect* effect) { Gtk::TreeNodeChildren chi = effectlist_view.get_model()->children(); for (Gtk::TreeIter ci = chi.begin() ; ci != chi.end(); ci++) { - if (ci->get_value(columns.lperef)->lpeobject->get_lpe() == effect) + if (ci->get_value(columns.lperef)->lpeobject->get_lpe() == effect && effectlist_view.get_selection()) effectlist_view.get_selection()->select(ci); } } @@ -580,6 +555,16 @@ void LivePathEffectEditor::on_effect_selection_changed() if (effect) { lpe_changed = true; showParams(*effect); + //To reload knots and helper paths + Inkscape::Selection *sel = _getSelection(); + if ( sel && !sel->isEmpty() ) { + SPItem *item = sel->singleItem(); + if (item) { + sel->clear(); + sel->add(item); + Inkscape::UI::Tools::sp_update_helperpath(); + } + } } } } diff --git a/src/ui/shape-editor-knotholders.cpp b/src/ui/shape-editor-knotholders.cpp index 5fb677f27..885f3ef40 100644 --- a/src/ui/shape-editor-knotholders.cpp +++ b/src/ui/shape-editor-knotholders.cpp @@ -107,13 +107,7 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop) { KnotHolder *knotholder = NULL; - SPLPEItem *lpe = dynamic_cast<SPLPEItem *>(item); - if (lpe && - lpe->getCurrentLPE() && - lpe->getCurrentLPE()->isVisible() && - lpe->getCurrentLPE()->providesKnotholder()) { - knotholder = sp_lpe_knot_holder(lpe, desktop); - } else if (dynamic_cast<SPRect *>(item)) { + if (dynamic_cast<SPRect *>(item)) { knotholder = new RectKnotHolder(desktop, item, NULL); } else if (dynamic_cast<SPBox3D *>(item)) { knotholder = new Box3DKnotHolder(desktop, item, NULL); @@ -139,6 +133,20 @@ KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop) return knotholder; } +KnotHolder *createLPEKnotHolder(SPItem *item, SPDesktop *desktop) +{ + KnotHolder *knotholder = NULL; + + SPLPEItem *lpe = dynamic_cast<SPLPEItem *>(item); + if (lpe && + lpe->getCurrentLPE() && + lpe->getCurrentLPE()->isVisible() && + lpe->getCurrentLPE()->providesKnotholder()) { + knotholder = sp_lpe_knot_holder(lpe, desktop); + } + return knotholder; +} + } } // namespace Inkscape diff --git a/src/ui/shape-editor.cpp b/src/ui/shape-editor.cpp index 3a5aec056..b40bec86f 100644 --- a/src/ui/shape-editor.cpp +++ b/src/ui/shape-editor.cpp @@ -29,13 +29,16 @@ namespace Inkscape { namespace UI { KnotHolder *createKnotHolder(SPItem *item, SPDesktop *desktop); +KnotHolder *createLPEKnotHolder(SPItem *item, SPDesktop *desktop); bool ShapeEditor::_blockSetItem = false; ShapeEditor::ShapeEditor(SPDesktop *dt, Geom::Affine edit_transform) : desktop(dt), knotholder(nullptr), + lpeknotholder(nullptr), knotholder_listener_attached_for(nullptr), + lpeknotholder_listener_attached_for(nullptr), _edit_transform(edit_transform) { } @@ -58,25 +61,43 @@ void ShapeEditor::unset_item(bool keep_knotholder) { this->knotholder = NULL; } } + if (this->lpeknotholder) { + Inkscape::XML::Node *old_repr = this->lpeknotholder->repr; + if (old_repr && old_repr == lpeknotholder_listener_attached_for) { + sp_repr_remove_listener_by_data(old_repr, this); + Inkscape::GC::release(old_repr); + lpeknotholder_listener_attached_for = NULL; + } + + if (!keep_knotholder) { + delete this->lpeknotholder; + this->lpeknotholder = NULL; + } + } } bool ShapeEditor::has_knotholder() { - return this->knotholder != NULL; + return this->knotholder != NULL || this->lpeknotholder != NULL; } void ShapeEditor::update_knotholder() { if (this->knotholder) this->knotholder->update_knots(); + if (this->lpeknotholder) + this->lpeknotholder->update_knots(); } bool ShapeEditor::has_local_change() { - return (this->knotholder && this->knotholder->local_change != 0); + return (this->knotholder && this->knotholder->local_change != 0) || (this->lpeknotholder && this->lpeknotholder->local_change != 0); } void ShapeEditor::decrement_local_change() { if (this->knotholder) { this->knotholder->local_change = FALSE; } + if (this->lpeknotholder) { + this->lpeknotholder->local_change = FALSE; + } } void ShapeEditor::event_attr_changed(Inkscape::XML::Node * node, gchar const *name, gchar const *, gchar const *, bool, void *data) @@ -123,6 +144,10 @@ void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) { // only recreate knotholder if none is present this->knotholder = createKnotHolder(item, desktop); } + if (!this->lpeknotholder) { + // only recreate knotholder if none is present + this->lpeknotholder = createLPEKnotHolder(item, desktop); + } if (this->knotholder) { this->knotholder->setEditTransform(_edit_transform); this->knotholder->update_knots(); @@ -134,6 +159,17 @@ void ShapeEditor::set_item(SPItem *item, bool keep_knotholder) { knotholder_listener_attached_for = repr; } } + if (this->lpeknotholder) { + this->lpeknotholder->setEditTransform(_edit_transform); + this->lpeknotholder->update_knots(); + // setting new listener + repr = this->lpeknotholder->repr; + if (repr != lpeknotholder_listener_attached_for) { + Inkscape::GC::anchor(repr); + sp_repr_add_listener(repr, &shapeeditor_repr_events, this); + lpeknotholder_listener_attached_for = repr; + } + } } } @@ -145,6 +181,9 @@ void ShapeEditor::reset_item(bool keep_knotholder) if (knotholder) { SPObject *obj = desktop->getDocument()->getObjectByRepr(knotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject. set_item(SP_ITEM(obj), keep_knotholder); + } else if (lpeknotholder) { + SPObject *obj = desktop->getDocument()->getObjectByRepr(lpeknotholder_listener_attached_for); /// note that it is not certain that this is an SPItem; it could be a LivePathEffectObject. + set_item(SP_ITEM(obj), keep_knotholder); } } @@ -155,7 +194,9 @@ bool ShapeEditor::knot_mouseover() const { if (this->knotholder) { return knotholder->knot_mouseover(); } - + if (this->lpeknotholder) { + return lpeknotholder->knot_mouseover(); + } return false; } diff --git a/src/ui/shape-editor.h b/src/ui/shape-editor.h index e30b2d60b..67bce1c98 100644 --- a/src/ui/shape-editor.h +++ b/src/ui/shape-editor.h @@ -36,6 +36,7 @@ public: bool knot_mouseover() const; KnotHolder *knotholder; + KnotHolder *lpeknotholder; bool has_knotholder(); static void blockSetItem(bool b) { _blockSetItem = b; } // kludge static void event_attr_changed(Inkscape::XML::Node * /*repr*/, char const *name, char const * /*old_value*/, @@ -46,6 +47,7 @@ private: SPDesktop *desktop; Inkscape::XML::Node *knotholder_listener_attached_for; + Inkscape::XML::Node *lpeknotholder_listener_attached_for; Geom::Affine _edit_transform; }; diff --git a/src/ui/tool/path-manipulator.cpp b/src/ui/tool/path-manipulator.cpp index 55e171420..dcf0a4d4b 100644 --- a/src/ui/tool/path-manipulator.cpp +++ b/src/ui/tool/path-manipulator.cpp @@ -190,7 +190,7 @@ void PathManipulator::writeXML() { if (!_live_outline) _updateOutline(); - if (!_live_objects) + if (_live_objects) _setGeometry(); if (!_path) return; @@ -1152,6 +1152,9 @@ void PathManipulator::_createControlPointsFromGeometry() ++i; } } + if (pathv.empty()) { + return; + } _spcurve->set_pathvector(pathv); pathv *= (_edit_transform * _i2d_transform); @@ -1358,6 +1361,23 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE) } builder.flush(); Geom::PathVector pathv = builder.peek() * (_edit_transform * _i2d_transform).inverse(); + for (Geom::PathVector::iterator i = pathv.begin(); i != pathv.end(); ) { + // NOTE: this utilizes the fact that Geom::PathVector is an std::vector. + // When we erase an element, the next one slides into position, + // so we do not increment the iterator even though it is theoretically invalidated. + if (i->empty()) { + i = pathv.erase(i); + } else { + ++i; + } + } + if (pathv.empty()) { + return; + } + + if (_spcurve->get_pathvector() == pathv) { + return; + } _spcurve->set_pathvector(pathv); if (alert_LPE) { /// \todo note that _path can be an Inkscape::LivePathEffect::Effect* too, kind of confusing, rework member naming? @@ -1371,7 +1391,6 @@ void PathManipulator::_createGeometryFromControlPoints(bool alert_LPE) } } } - if (_live_outline) _updateOutline(); if (_live_objects) @@ -1465,7 +1484,7 @@ void PathManipulator::_getGeometry() } } else { _spcurve->unref(); - _spcurve = _path->get_curve_for_edit(); + _spcurve = _path->getCurveForEdit(); // never allow NULL to sneak in here! if (_spcurve == NULL) { _spcurve = new SPCurve(); @@ -1477,7 +1496,6 @@ void PathManipulator::_getGeometry() void PathManipulator::_setGeometry() { using namespace Inkscape::LivePathEffect; - if (!_lpe_key.empty()) { // copied from nodepath.cpp // NOTE: if we are editing an LPE param, _path is not actually an SPPath, it is @@ -1485,17 +1503,22 @@ void PathManipulator::_setGeometry() Effect *lpe = LIVEPATHEFFECT(_path)->get_lpe(); if (lpe) { PathParam *pathparam = dynamic_cast<PathParam *>(lpe->getParameter(_lpe_key.data())); + if (pathparam->get_pathvector() == _spcurve->get_pathvector()) { + return; //False we dont update LPE + } pathparam->set_new_value(_spcurve->get_pathvector(), false); LIVEPATHEFFECT(_path)->requestModified(SP_OBJECT_MODIFIED_FLAG); } } else { + // return true to leave the decission on empty to the caller. + // Maybe the path become empty and we want to update to empty if (empty()) return; - if (SPCurve * original = _path->get_original_curve()){ + if (SPCurve * original = _path->getCurveBeforeLPE()){ if(!_spcurve->is_equal(original)) { - _path->set_original_curve(_spcurve, false, false); + _path->setCurveBeforeLPE(_spcurve); delete original; } - } else if(!_spcurve->is_equal(_path->get_curve())) { + } else if(!_spcurve->is_equal(_path->getCurve(true))) { _path->setCurve(_spcurve, false); } } @@ -1658,7 +1681,6 @@ Geom::Coord PathManipulator::_updateDragPoint(Geom::Point const &evp) Geom::Affine to_desktop = _edit_transform * _i2d_transform; Geom::PathVector pv = _spcurve->get_pathvector(); - boost::optional<Geom::PathVectorTime> pvp = pv.nearestTime(_desktop->w2d(evp) * to_desktop.inverse()); if (!pvp) return dist; diff --git a/src/ui/tools/connector-tool.cpp b/src/ui/tools/connector-tool.cpp index ec55ab80b..20b309a98 100644 --- a/src/ui/tools/connector-tool.cpp +++ b/src/ui/tools/connector-tool.cpp @@ -617,7 +617,7 @@ bool ConnectorTool::_handleMotionNotify(GdkEventMotion const &mevent) Geom::Affine i2d ( (this->clickeditem)->i2dt_affine() ); Geom::Affine d2i = i2d.inverse(); SPPath *path = SP_PATH(this->clickeditem); - SPCurve *curve = path->get_curve(); + SPCurve *curve = path->getCurve(true); if (this->clickedhandle == this->endpt_handle[0]) { Geom::Point o = this->endpt_handle[1]->pos; curve->stretch_endpoints(p * d2i, o * d2i); @@ -628,7 +628,7 @@ bool ConnectorTool::_handleMotionNotify(GdkEventMotion const &mevent) sp_conn_reroute_path_immediate(path); // Copy this to the temporary visible path - this->red_curve = path->get_curve_for_edit(); + this->red_curve = path->getCurveForEdit(); this->red_curve->transform(i2d); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(this->red_bpath), this->red_curve, true); @@ -1041,7 +1041,7 @@ static gboolean endpt_handler(SPKnot */*knot*/, GdkEvent *event, ConnectorTool * } // Show the red path for dragging. - cc->red_curve = SP_PATH(cc->clickeditem)->get_curve_for_edit(); + cc->red_curve = SP_PATH(cc->clickeditem)->getCurveForEdit(); Geom::Affine i2d = (cc->clickeditem)->i2dt_affine(); cc->red_curve->transform(i2d); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(cc->red_bpath), cc->red_curve, true); @@ -1135,7 +1135,7 @@ void ConnectorTool::cc_set_active_conn(SPItem *item) { g_assert( SP_IS_PATH(item) ); - const SPCurve *curve = SP_PATH(item)->get_curve_reference(); + const SPCurve *curve = SP_PATH(item)->getCurveForEdit(true); Geom::Affine i2dt = item->i2dt_affine(); if (this->active_conn == item) { @@ -1275,7 +1275,7 @@ static bool cc_item_is_shape(SPItem *item) bool cc_item_is_connector(SPItem *item) { if (SP_IS_PATH(item)) { - bool closed = SP_PATH(item)->get_curve_reference()->is_closed(); + bool closed = SP_PATH(item)->getCurveForEdit(true)->is_closed(); if (SP_PATH(item)->connEndPair.isAutoRoutingConn() && !closed) { // To be considered a connector, an object must be a non-closed // path that is marked with a "inkscape:connector-type" attribute. diff --git a/src/ui/tools/freehand-base.cpp b/src/ui/tools/freehand-base.cpp index 26d812394..b57aa2fb0 100644 --- a/src/ui/tools/freehand-base.cpp +++ b/src/ui/tools/freehand-base.cpp @@ -645,7 +645,7 @@ static void spdc_attach_selection(FreehandBase *dc, Inkscape::Selection */*sel*/ // Curve list // We keep it in desktop coordinates to eliminate calculation errors - SPCurve *norm = SP_PATH(item)->get_curve_for_edit(); + SPCurve *norm = SP_PATH(item)->getCurveForEdit(); norm->transform((dc->white_item)->i2dt_affine()); g_return_if_fail( norm != NULL ); dc->white_curves = norm->split(); diff --git a/src/ui/tools/node-tool.cpp b/src/ui/tools/node-tool.cpp index 6e586b0e9..d54adba89 100644 --- a/src/ui/tools/node-tool.cpp +++ b/src/ui/tools/node-tool.cpp @@ -533,7 +533,7 @@ bool NodeTool::root_handler(GdkEvent* event) { } this->flashed_item = over_item; - SPCurve *c = SP_SHAPE(over_item)->getCurveBeforeLPE(); + SPCurve *c = SP_SHAPE(over_item)->getCurveForEdit(); if (!c) { break; // break out when curve doesn't exist diff --git a/src/ui/widget/selected-style.cpp b/src/ui/widget/selected-style.cpp index d317fa216..3988ca544 100644 --- a/src/ui/widget/selected-style.cpp +++ b/src/ui/widget/selected-style.cpp @@ -109,7 +109,7 @@ typedef enum { // code, those warnings are actually desired. They say "Hey! Fix this". We // definitely don't want to hide/ignore them. --JonCruz static const GtkTargetEntry ui_drop_target_entries [] = { - {"application/x-color", 0, APP_X_COLOR} + {g_strdup("application/x-color"), 0, APP_X_COLOR} }; static guint nui_drop_target_entries = G_N_ELEMENTS(ui_drop_target_entries); diff --git a/src/widgets/pencil-toolbar.cpp b/src/widgets/pencil-toolbar.cpp index fb9afb8da..d2939c720 100644 --- a/src/widgets/pencil-toolbar.cpp +++ b/src/widgets/pencil-toolbar.cpp @@ -320,7 +320,7 @@ static void sp_flatten_spiro_bspline(GtkWidget * /*widget*/, GObject *obj) { SPShape * shape = dynamic_cast<SPShape *>(lpeitem); if(shape){ - SPCurve * c = shape->getCurveBeforeLPE(); + SPCurve * c = shape->getCurveForEdit(); lpe->doEffect(c); lpeitem->setCurrentPathEffect(*i); if (lpelist.size() > 1){ @@ -328,7 +328,7 @@ static void sp_flatten_spiro_bspline(GtkWidget * /*widget*/, GObject *obj) shape->setCurveBeforeLPE(c); } else { lpeitem->removeCurrentPathEffect(false); - shape->setCurve(c,0); + shape->setCurve(c, false); } break; } @@ -361,7 +361,7 @@ static void sp_simplify_flatten(GtkWidget * /*widget*/, GObject *obj) if (dynamic_cast<Inkscape::LivePathEffect::LPESimplify *>(lpe)) { SPShape * shape = dynamic_cast<SPShape *>(lpeitem); if(shape){ - SPCurve * c = shape->getCurveBeforeLPE(); + SPCurve * c = shape->getCurveForEdit(); lpe->doEffect(c); lpeitem->setCurrentPathEffect(*i); if (lpelist.size() > 1){ @@ -369,7 +369,7 @@ static void sp_simplify_flatten(GtkWidget * /*widget*/, GObject *obj) shape->setCurveBeforeLPE(c); } else { lpeitem->removeCurrentPathEffect(false); - shape->setCurve(c,0); + shape->setCurve(c, false); } break; } |
