diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 44b737ad11c5e2e000a2d6a1b0f9edfc8afa47f6..bfc280ce6c671f6228ae3b0caa04203006d1fbe3 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(&is_visible) ); @@ -469,14 +469,14 @@ Effect::processObjects(LpeAction lpe_action) if (!document) { return; } - for (std::vector::iterator el_it = items.begin(); + for (std::vector::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 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(lpeitem); - SPShape * shape = dynamic_cast(sp_lpe_item); - setCurrentShape(shape); doOnApply(lpeitem); } void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast(lpeitem); - SPShape * shape = dynamic_cast(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(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(_("Default value: ")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("\n"); + Glib::ustring def = Glib::ustring(_("Default value: ")) + defvalue + Glib::ustring("\n"); Glib::ustring ove = Glib::ustring(_("Default value overridden: ")) + Glib::ustring(prefs->getString(pref_path)) + Glib::ustring("\n"); if (valid) { set_or_upd = _("Update"); - def = Glib::ustring(_("Default value: ")) + Glib::ustring(param->param_getDefaultSVGValue()) + Glib::ustring("\n"); + def = Glib::ustring(_("Default value: ")) + defvalue + Glib::ustring("\n"); } else { set_or_upd = _("Set"); ove = Glib::ustring(_("Default value overridden: None\n")); } - Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) + Glib::ustring(param->param_getSVGValue()); + Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) + 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("") + parameter_label->get_text () + Glib::ustring("\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(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(sigc::mem_fun(*this, &Effect::unsetDefaultParam), pref_path, tooltip, value, defvalue, parameter_label, set, unset)); - set->signal_clicked().connect(sigc::bind(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(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 (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(vbox); - vboxwidg->set_margin_bottom(10); + Gtk::Widget *vboxwidg = dynamic_cast(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(_("Default value: ")) + Glib::ustring(defvalue) + Glib::ustring("\n"); - Glib::ustring ove = Glib::ustring(_("Default value overridden: ")) + Glib::ustring(value) + Glib::ustring("\n"); - Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) + Glib::ustring(value); + Glib::ustring def = Glib::ustring(_("Default value: ")) + defvalue + Glib::ustring("\n"); + Glib::ustring ove = Glib::ustring(_("Default value overridden: ")) + value + Glib::ustring("\n"); + Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) + 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(_("Default value: ")) + Glib::ustring(defvalue) + Glib::ustring("\n"); + Glib::ustring def = Glib::ustring(_("Default value: ")) + defvalue + Glib::ustring("\n"); Glib::ustring ove = Glib::ustring(_("Default value overridden: None\n")); - Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) + Glib::ustring(value); + Glib::ustring cur = Glib::ustring(_("Current parameter value: ")) +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 d0024f8772b1edfef9b793a2791f6e9902b6e5c8..d162b8bb4da624f5eb0bf4effa4f80ff5426f4e7 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -10,6 +10,7 @@ #include #include <2geom/forward.h> #include "ui/widget/registry.h" +#include #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 items; + SPShape * current_shape; // these get stored in performPathEffects. + std::vector items; double current_zoom; std::vector 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 314ddc84c58e44382f6028bd939d4fb3df8784a1..11694249a363f44125c25dde2800fd4f5559e411 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 f007599215eb20edc73d69fb96dfaa87af1a08c1..7834ff108bf8f76a274d0a190a3063e9b429c14e 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(vbox); } @@ -164,7 +167,7 @@ void LPEBSpline::changeWeight(double weight_ammount) { SPPath *path = dynamic_cast(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 413c1889309195cea477af85575436fa0726a52a..d0ff805002fde3967dadae4d905d4aa33fde565a 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 ebcb95f0da56511cbc466dbb4140291a039fde83..6bf2a78bd31da136cd7f525c172c6ea0b1c4feb7 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::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(elemref); + if (group) { + Inkscape::XML::Node *container = xml_doc->createElement("svg:g"); + container->setAttribute("transform", prev->attribute("transform")); + std::vector const item_list = sp_item_group_item_list(group); + Inkscape::XML::Node *previous = NULL; + for ( std::vector::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 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(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 a0a3d4dc15968db20b30adcbe633a4b880f29ecb..dcbd1c45ebb60fb9175a8abb60ef716a94f90c9f 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 &hp_vec); diff --git a/src/live_effects/lpe-envelope.cpp b/src/live_effects/lpe-envelope.cpp index b50efde34592ed2abe69e722696a80b87c7901e6..0dcae51e41cbcee3c497b679485de33a839d80e0 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 > @@ -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 94a43b728a895d2b648b988d5ff814e8660f4169..59a6324e751857dc410d07047b0f25c4f38e06f0 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 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::iterator it = gchar_map_to_satellite_type.find(std::string(mode.param_getSVGValue())); + gchar * mode_str = mode.param_getSVGValue(); + std::map::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 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::iterator it = gchar_map_to_satellite_type.find(std::string(mode.param_getSVGValue())); + gchar * mode_str = mode.param_getSVGValue(); + std::map::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 f6b42cfb9280cde1a1eab9d32113a3bddd73d45c..70bc92a27fc6685835260415a42d310a537120e3 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 124a7a9c6a2c1f1ee717c6e3e0fd5f46cc40343a..df4da4590503fe4955cbe3622ec8bbf851767737 100644 --- a/src/live_effects/lpe-lattice.cpp +++ b/src/live_effects/lpe-lattice.cpp @@ -164,7 +164,7 @@ LPELattice::doEffect_pwd2 (Geom::Piecewise > 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 3eeb6e746a0190ce6903faebcf45265bb7e1575e..8c2c3ec317d6d21bd7538cbd8006287621325577 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(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 9bfa2c52e8840fe3434e8ea56dd856658f6fbbc6..cff5aec4b8d51016fd16fe0c8ea18bf84c515842 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 -#include "ui/dialog/livepatheffect-editor.h" -#include -#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 +#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 -#include - -#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 +#include +#include +#include // TODO due to internal breakage in glibmm headers, this must be last: #include @@ -46,10 +50,11 @@ using namespace Geom; namespace Inkscape { namespace LivePathEffect { + static const Util::EnumData 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 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 */ 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(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(lpeitem); - SPDocument * document = SP_ACTIVE_DOCUMENT; if (!document) { return; @@ -584,16 +608,38 @@ LPEMeasureSegments::doBeforeEffect (SPLPEItem const* lpeitem) SPShape *shape = dynamic_cast(splpeitem); if (shape) { - SPCurve * c = NULL; - - SPPath *path = dynamic_cast(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(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(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(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(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 903a5cbd27b2cc2b3426d8a3eadf0b680f029779..1b6a5a81d7c5d5fdaba80212a9394e02489ea064 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 -#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 926977a07b9c14852d8ca24a442d93f64c5edf28..1e62a98d517e666342c8e7d4b29275f49b289742 100644 --- a/src/live_effects/lpe-mirror_symmetry.cpp +++ b/src/live_effects/lpe-mirror_symmetry.cpp @@ -15,8 +15,6 @@ */ #include -#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 ModeTypeData[MT_END] = { +static const Util::EnumData 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 ModeTypeData[MT_END] = { static const Util::EnumDataConverter 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(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(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::iterator it = param_vector.begin(); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter *param = *it; + Gtk::Widget *widg = dynamic_cast(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(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::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(elemref); + if (group) { + Inkscape::XML::Node *container = xml_doc->createElement("svg:g"); + container->setAttribute("transform", prev->attribute("transform")); + std::vector const item_list = sp_item_group_item_list(group); + Inkscape::XML::Node *previous = NULL; + for ( std::vector::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 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(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 e98c83f2b8387d1ec4af61b369d585c79da98dc6..d2d04c205991a8c3e537d70cabfd16d506479689 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 &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 6e6f35f7ddc65cbee57028e1bbed12bf8164c30d..115c777d0c0d5b96f1f734a9041009de72c736ab 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(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 (_effect); SPShape const *sp_shape = dynamic_cast(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 2819094e7d4442ee12e27f344841f224e8bd44b8..afaa6b9ca57660e04e4823c31860e78b6481e65f 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 3cff83fedcc0575e29a9095b60473682c059a0df..e95cdfd4bb6d25e6e344aff93aba24c2b5352948 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(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 3484d00a5842d22e845f0ff59bda8d2665739b3c..deed40bde7be533f55b8eb26377d679d9c99c93b 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(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(vbox); } diff --git a/src/live_effects/lpe-powerclip.cpp b/src/live_effects/lpe-powerclip.cpp index 2e90abfeb5d33d0d5ad1929ea60769d8b0709ddc..60237b54efac204ea6afd6ecc6638bb3fdb44e97 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 item_list = sp_item_group_item_list(SP_GROUP(clip_data)); for ( std::vector::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 item_list = sp_item_group_item_list(SP_GROUP(clip_data)); for ( std::vector::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(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 clip_path_list = clip_path->childList(true); for ( std::vector::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 6f99d220f664c597a15bf4d86bf49354618a1f38..240a1809b3b90e90765e855b53310e87b245640f 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 947482c24ddae4abcbfaa6ad0414a8e267ca1ecd..202c97259461df5dbc2e6dd6bb08239e9774d0a5 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 6d63ffa81c5998565b52dd0fb1f612dda42e93d0..1d64e90420c0f00a283c6e1724391c1be4241877 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 e847494a2f43d62bd94f004346f7d1417db21108..e78ab99fda6deecac692cad276345007f417b6fc 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(vbox); } diff --git a/src/live_effects/lpe-show_handles.cpp b/src/live_effects/lpe-show_handles.cpp index 149425112b6a7f577517fa5a42899bfc92ce241b..35da722d0f95610eeb328f9d8b33ac008c6a6054 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 5de9816bb9609814e8b4a6dee5b3026252568a3b..e676f37a0891ddc455b534e7631e301524d735fe 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(vbox); } diff --git a/src/live_effects/lpe-transform_2pts.cpp b/src/live_effects/lpe-transform_2pts.cpp index 914d23e4bc5e37e6c0243694c2365d63fcf5d8f3..47f8864ce31b6671523dfac4cff4b4eb4bbe8ea5 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(lpeitem); SPPath *sp_path = dynamic_cast(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(lpeitem); SPPath *sp_path = dynamic_cast(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(sp_lpe_item); SPPath *sp_path = dynamic_cast(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(vbox); } diff --git a/src/live_effects/lpe-vonkoch.cpp b/src/live_effects/lpe-vonkoch.cpp index f04c243f634e19ac636057df669a81a3800c5bb7..33460aa2d74eff9ebf4a6bfd5990dfa7886da55b 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 8a42fc8b67a445845c9e212875afeb1ac8da15e5..6df6278b110917f16a8ae7ccd61f6587c9c18aa4 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(item); + if (group) { + std::vector item_list = sp_item_group_item_list(group); + for ( std::vector::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { + SPLPEItem * subitem = dynamic_cast(*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(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 7d4ac3e78c7baef7163436606fd21acfc3a5a6a4..de20138c933c207c571d3859e6f65289474a2c3f 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 c66d53266edef6aa0f32efb0b326576109060c0c..b5ee8b5cf56ba1eac8c47f013785375fba72f630 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 1a01f269be8c7c9da2a5934e7d103568476eb6e2..bfbda2bfd2c46240388e4c09cfcbbea4c061fb1e 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 ca237c0f74f9f0292762b6979266399ccfd88021..82eaa6d433bc89e5abbfba418ddb36b80c3bfc18 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 e08881f6d4009b6afe003ec2a914eccbd1c1631d..5a21f572b55f1ebb8a7b78e6bb4a107063e7908e 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 1e2c9ec50f6b9e3c341a87231ac7e4aba0bfdd52..03eb2219f545d221e0457d170504d977994adfae 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 2ac2c791a65c1b7002e5941720f2ea0d844783cf..fd850a7675c0c5af1bd241dcdab7db6b0ccadc90 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 fe2dc0c8d6aae044a83e22fe76e73ee0f3b65d46..b89485e2db063310357bae500d93445376980c33 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 b6a90671e0d8814ed8fc0adbf08c4919ab5c6898..018e1e69e939e9a0c72657485fb73ce3ba76dedd 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 caec74a8ba8137af14d119a18de41e220aef9acd..928bf29766908b82a9710b4b3bdeab39129ad8a2 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 497113e032d1672778aa28f4ce9f8c7cb51ba820..a175359f095d24edc19d2839eb574bbac9a12601 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 02075ee8e171643a8f34b6126ff298437ee54d0c..ab385daa6480c5c55617c96222c7eff8cf57d2f4 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 9b4723da3efbaf03f63b0e181a00101e0942c3d6..b811b7f2b99fd1d643a07694bf5dbe243975f451 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( 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(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(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 4afa43c6ea708a47b6bbfb81590d9f726b3d0772..23912bedbeeda671314c174ae5c5bacf88d83b04 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 7e56b2c758840e13e78b7aa901aa2a3a0c0cd922..37ae3a1d7c882bfa81eb3a29e82c9b37f7b8090d 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 e26884d6ada01530347cee56afbe8d13cb0a1f54..bb9d9a90e0b835110e098cd27d60bacc16771172 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 a010faf27cc0bffb25ba348218d46cfeccefb102..ab66e725696884970b649b447936bc92b70e61b9 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 ced93ef0dece35ac0298f3892fd6c3da90bf0051..1207a05da26a649a901a1cf4cf2bd89894874295 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 3eea8855cad220a20ba96c8d22abbde48f5efd8c..6ecd3a1fae7a71813e5760586f8eef85819e1bc8 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 4f69bd02627ad2929cf433b3ad872c3a4c05b57d..4afbf7e5103f205139c4c50b0bffaafc90f7fb30 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 daadd0cddc80b17002b338f7d6ad881b19581272..1a0ec5d70536b98b0a0d164b94487a595d1f570a 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 c32e3012c6b1f49ece2244ffd21ec268c6195e93..95bfd61606173f97aa62141c7ff9c5dbdf47b449 100644 --- a/src/object/sp-ellipse.cpp +++ b/src/object/sp-ellipse.cpp @@ -18,6 +18,8 @@ #include #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 a31b571d85645e3eb3e372b2a7ee0f48fc82418f..0aa3dd1c62ba9b80e4a65bf34adb08c8057cd186 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 &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 73c1dcb6c64d2ab7c8f29755152f66bb40b34b00..a3fa6c6e879744b1194133ef0fb64316dadf69f3 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(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 &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 const item_list = sp_item_group_item_list(this); for ( std::vector::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPObject *sub_item = *iter; - - SPLPEItem *lpe_item = dynamic_cast(sub_item); - if (lpe_item) { - lpe_item->update_patheffect(write); + if (sub_item) { + SPLPEItem *lpe_item = dynamic_cast(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 const item_list = sp_item_group_item_list(group); - for ( std::vector::const_iterator iter=item_list.begin();iter!=item_list.end();++iter) { SPObject *sub_item = *iter; - SPGroup *sub_group = dynamic_cast(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(sub_item); + SPShape* sub_shape = dynamic_cast(sub_item); + SPPath* sub_path = dynamic_cast(sub_item); + SPItem* clipmaskto = dynamic_cast(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(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(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 f7a4ff6720309b807e0c5b88c0fd2fd4b21b4529..a228d9313d61d7725d5ee61ed16a57ec0b941efc 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(parent)) { + parent = parent->parent; + } + return parent; +} + +SPObject* SPItem::isInClipPath() const { + SPObject* parent = this->parent; + while (parent && !dynamic_cast(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 36af02edc7b749308f3a2ed626672ae6ef10ccac..88fca97799aeefbdb599bf527bf70f30fd371a87 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 09ffd1f17d0c9540641ce9d0eac71f3c7983af61..2ba6339728b00f7bf3cb6c69f2ad3e289750efe9 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 f3cc841fb8cd8f055d1a68f7c8837fc896f4700e..e0ef848af00b1bad81f66d4e2fbe73b81d26e31c 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 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 clip_path_list = clip_path->childList(true); + for ( std::vector::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { + SPLPEItem * clip_data = dynamic_cast(*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 mask_path_list = mask_path->childList(true); + for ( std::vector::const_iterator iter = mask_path_list.begin(); iter != mask_path_list.end();++iter) { + SPLPEItem * mask_data = dynamic_cast(*iter); + sp_lpe_item_create_original_path_recursive(mask_data); + } } if (SP_IS_GROUP(lpeitem)) { - std::vector item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); + std::vector item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( std::vector::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(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(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(lpeitem); + if (!item) { + return; + } + SPGroup *group = dynamic_cast(lpeitem); + SPShape *shape = dynamic_cast(lpeitem); + SPPath *path = dynamic_cast(lpeitem); + SPClipPath *clip_path = item->clip_ref->getObject(); + if(clip_path) { + std::vector clip_path_list = clip_path->childList(true); + for ( std::vector::const_iterator iter=clip_path_list.begin();iter!=clip_path_list.end();++iter) { + SPLPEItem* clip_data = dynamic_cast(*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 mask_path_list = mask_path->childList(true); + for ( std::vector::const_iterator iter = mask_path_list.begin(); iter != mask_path_list.end();++iter) { + SPLPEItem* mask_data = dynamic_cast(*iter); + sp_lpe_item_cleanup_original_path_recursive(mask_data, keep_paths, shape && !shape->hasPathEffectRecursive()); + } + } + + if (group) { std::vector item_list = sp_item_group_item_list(SP_GROUP(lpeitem)); for ( std::vector::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(*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(lpeitem->parent); - clip_path = dynamic_cast(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(lpeitem->parent); - clip_path = dynamic_cast(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(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(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(this); + SPShape* shape = dynamic_cast(this); + if (group) { + std::vector item_list = sp_item_group_item_list(group); + for ( std::vector::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) { + SPLPEItem * subitem = dynamic_cast(*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 clip_path_list = clip_path->childList(true); for ( std::vector::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(*iter); + SPShape* shape = dynamic_cast(*iter); + if (group) { + std::vector item_list = sp_item_group_item_list(group); + for ( std::vector::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) { + SPLPEItem * subitem = dynamic_cast(*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 item_list = sp_item_group_item_list(SP_GROUP(item)); - for ( std::vector::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 mask_list = mask->childList(true); + for ( std::vector::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) { + SPGroup* group = dynamic_cast(*iter); + SPShape* shape = dynamic_cast(*iter); + if (group) { + std::vector item_list = sp_item_group_item_list(group); + for ( std::vector::const_iterator iter2=item_list.begin();iter2!=item_list.end();++iter2) { + SPLPEItem * subitem = dynamic_cast(*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 clip_path_list = clip_path->childList(true); + for ( std::vector::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 mask_list = mask->childList(true); for ( std::vector::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 item_list = sp_item_group_item_list(SP_GROUP(item)); - for ( std::vector::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 item_list = sp_item_group_item_list(SP_GROUP(clip_mask)); + SPGroup* group = dynamic_cast(clip_mask); + SPShape* shape = dynamic_cast(clip_mask); + SPLPEItem* tolpe = dynamic_cast(to); + if (group) { + std::vector item_list = sp_item_group_item_list(group); for ( std::vector::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(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(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 82f3940c10a46db2eae415ac264fde4587698c70..0e6049d4e6ed966471f2ac0b99b79f364427e859 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 b65c145fc2289a3157e081bf85ee71a7c61843db..2e764131c24ef50e19ad42911ee780ed42868124 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 02d37b82b0e426f757ab6cced6d31497b51272d9..26e51083008279aaea82ab48549ab4b63a4e3f17 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 bc930a43047ecd43341cc2e352c523cb93eb96e5..d3c429c2a9ada8bdb712f1bd6a4a05c96700928e 100644 --- a/src/object/sp-object.cpp +++ b/src/object/sp-object.cpp @@ -413,7 +413,6 @@ std::vector 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 82e0b49476113bfc995fc9b440694b078a592f71..2864e88cb9635782a7179394c4b80031b4f53167 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 a0c7f098d9cce5466c85d9317a235c5218b1f88b..d6a06498cdad40bcb3ad6e14da20217e4b224b8b 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); @@ -325,130 +326,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 572fd648d1d97864f579bbed06e51b102751dbf1..2d7ab4e94b7aebe0b138f1e83666b47925e7e34b 100644 --- a/src/object/sp-path.h +++ b/src/object/sp-path.h @@ -29,37 +29,24 @@ 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); - virtual void release(); - virtual void update(SPCtx* ctx, unsigned int flags); + virtual void build(SPDocument *document, Inkscape::XML::Node *repr); + virtual void release(); + virtual void update(SPCtx* ctx, unsigned int flags); - virtual void set(unsigned int key, char const* value); - virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); + virtual void set(unsigned int key, char const* value); + virtual Inkscape::XML::Node* write(Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, unsigned int flags); - virtual const char* displayName() const; - virtual char* description() const; - virtual Geom::Affine set_transform(Geom::Affine const &transform); + virtual const char* displayName() const; + 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); }; #endif // SEEN_SP_PATH_H diff --git a/src/object/sp-polygon.cpp b/src/object/sp-polygon.cpp index 14fd104b3366e506a23a79d014952ee89fba5fed..b2a0c148086a068281b9efcb1a33332d5ec492c5 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 29054f934a979fa275031b3a2b646c9b36187466..3be4700eb8328cdd5bd749e4b364091bd6e5bd38 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 88dad5354f110b5280de109f6d64fadcb467dfbf..f21dafd54f6ca599a960b3ce7272b848e2c6ed7e 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 9edf03cbfcec51aafac5bbc0bd2650bc527d5007..07416650ea616abd094943ca20381b9246729c53 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 &p, Inkscape::SnapPreferences const *snapprefs) const { diff --git a/src/object/sp-shape.h b/src/object/sp-shape.h index fe9d032755774272c3bdf944db9ecaaee2d4f8d6..be097e390a05b61841381e1d69039d973ae5b485 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 &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 a84fc60412874dcd27b4c88536930a381e390548..7a449807df7b0e945b38228efde27ab59596f0da 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 ebf4c9e28058ced6c2528742f62a6f3c5de0cb5a..138eae91494afaba9626e4474231dae95036de69 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 9844df98af3d996dc6bd9d4b0ef955d3250c1c64..097b5d9893a842d2ad3dbf2d77795fa4f5af7409 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 4519de869450c476ba64acc1cc8a09e6dd6d064e..86f3e8ef916967f6f1e2e014d994f6c98aa1e71b 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 &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 2eb471bb39bd740c29e9d59ff8d3fe3efb64259f..7d5346f317f5aa82afc0433cfc76a2a1ab5f5d34 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 ae2f63f970f61172685788fbed17a1785c29387b..622a843e4cde1e26c5ab2408ece0632f1d52e520 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(*(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 cbb51f3122e9723dceb57d00f51bec3c54fa3197..1c0cc8cb131c9701777726cc711cb269f03d3f32 100644 --- a/src/splivarot.cpp +++ b/src/splivarot.cpp @@ -2538,7 +2538,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(); } @@ -2566,7 +2566,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 7a6c51a3bf8b515121ef26616c12d037c6b2a013..68b67531ddc6127dfc538092a8d05e99885a3b8f 100644 --- a/src/style-internal.h +++ b/src/style-internal.h @@ -872,7 +872,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 ec8ae4f31b8f1582841e9037278191d5af8fad11..6cf7f807a61453e1ec2c3447a83331f248596d92 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 childs = dynamic_cast (effectwidget)->get_children(); - if (childs.size()) { - std::vector childs_default = dynamic_cast (childs[childs.size()-1])->get_children(); - if ((expander = dynamic_cast(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 childs_default = dynamic_cast (defaultswidget)->get_children(); - if ((expander = dynamic_cast(childs_default[childs_default.size()-1]))){ - expander->set_expanded(expanderopen); - } - dynamic_cast (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 5fb677f27a29da1ccfbefbb193fef8c9f3e7eba8..885f3ef40d514492d2bc9a37ebe36035ce8186c9 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(item); - if (lpe && - lpe->getCurrentLPE() && - lpe->getCurrentLPE()->isVisible() && - lpe->getCurrentLPE()->providesKnotholder()) { - knotholder = sp_lpe_knot_holder(lpe, desktop); - } else if (dynamic_cast(item)) { + if (dynamic_cast(item)) { knotholder = new RectKnotHolder(desktop, item, NULL); } else if (dynamic_cast(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(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 3a5aec056dcc519c2c78d5bfa2bdce87581bfe81..b40bec86f7dd2412637f6a8559968003b66fff2c 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 e30b2d60b9f1d9bb2d9163f453cf457eaed180c7..67bce1c98d8a38da1f95ad6abdac24f2a2d316d2 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 55e17142016c35fc49da13022db4ce8018b2a0f6..dcf0a4d4b7830e97fc8302f22d689517b4f8d12f 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(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 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 ec55ab80b2fecf5fe336f81dab82f8c3438fc9fe..20b309a98fc98d457fc7269a9516c76d51df82b0 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 26d8123940c380bc9d10935ebb5e2dfc356acdef..b57aa2fb030509370b9b1c0e2dcabdfff9d24d63 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 6e586b0e99583ebfe23bcf702d574a62b8e84ac5..d54adba89a23ff1ab11c4ad466b68e29b308328e 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 d317fa216ee60ba631941f4efcc5d8451f2950af..3988ca544f803117865cefa70723f4cea68a3fc6 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 fb9afb8daa798055f2dd7fda7095ac252e1a97b4..d2939c7209a07c6a6585437de4cc82ab7020c411 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(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(lpe)) { SPShape * shape = dynamic_cast(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; }