diff options
Diffstat (limited to 'src/live_effects/lpe-clone-original.cpp')
| -rw-r--r-- | src/live_effects/lpe-clone-original.cpp | 358 |
1 files changed, 156 insertions, 202 deletions
diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 31bf0e270..15968dd56 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -5,6 +5,10 @@ */ #include "live_effects/lpe-clone-original.h" +#include "live_effects/lpe-spiro.h" +#include "live_effects/lpe-bspline.h" +#include "live_effects/lpeobject.h" +#include "live_effects/lpeobject-reference.h" #include "display/curve.h" #include "svg/path-string.h" #include "svg/svg.h" @@ -18,59 +22,50 @@ namespace Inkscape { namespace LivePathEffect { +static const Util::EnumData<Clonelpemethod> ClonelpemethodData[] = { + { CLM_NONE, N_("No shape"), "none" }, + { CLM_ORIGINALD, N_("Without LPE's"), "originald" }, + { CLM_BSPLINESPIRO, N_("With Spiro or BSpline"), "bsplinespiro" }, + { CLM_D, N_("With LPE's"), "d" } +}; +static const Util::EnumDataConverter<Clonelpemethod> CLMConverter(ClonelpemethodData, CLM_END); + LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) : Effect(lpeobject), linkeditem(_("Linked Item:"), _("Item from which to take the original data"), "linkeditem", &wr, this), - scale(_("Scale %"), _("Scale item %"), "scale", &wr, this, 100.0), - preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false), - inverse(_("Inverse clone"), _("Use LPE item as origin"), "inverse", &wr, this, false), - d(_("Clone shape -d-"), _("Clone shape -d-"), "d", &wr, this, true), - transform(_("Clone transforms"), _("Clone transforms"), "transform", &wr, this, true), - fill(_("Clone fill"), _("Clone fill"), "fill", &wr, this, false), - stroke(_("Clone stroke"), _("Clone stroke"), "stroke", &wr, this, false), - paintorder(_("Clone paint order"), _("Clone paint order"), "paintorder", &wr, this, false), - opacity(_("Clone opacity"), _("Clone opacity"), "opacity", &wr, this, false), - filter(_("Clone filter"), _("Clone filter"), "filter", &wr, this, false), + method(_("Shape linked"), _("Shape linked"), "method", CLMConverter, &wr, this, CLM_D), attributes("Attributes linked", "Attributes linked, comma separated atributes", "attributes", &wr, this,""), - style_attributes("Style attributes linked", "Style attributes linked, comma separated atributes", "style_attributes", &wr, this,""), - expanded(false), - origin(Geom::Point(0,0)) + style_attributes("Style attributes linked", "Style attributes linked, comma separated attributes like fill, filter, opacity", "style_attributes", &wr, this,""), + allow_transforms(_("Alow transforms"), _("Alow transforms"), "allow_transforms", &wr, this, true) { //0.92 compatibility const gchar * linkedpath = this->getRepr()->attribute("linkedpath"); if (linkedpath && strcmp(linkedpath, "") != 0){ this->getRepr()->setAttribute("linkeditem", linkedpath); this->getRepr()->setAttribute("linkedpath", NULL); - this->getRepr()->setAttribute("transform", "false"); + this->getRepr()->setAttribute("method", "bsplinespiro"); + this->getRepr()->setAttribute("allow_transforms", "false"); }; - + is_updating = false; + listening = false; + linked = g_strdup(this->getRepr()->attribute("linkeditem")); registerParameter(&linkeditem); - registerParameter(&scale); + registerParameter(&method); registerParameter(&attributes); registerParameter(&style_attributes); - registerParameter(&preserve_position); - registerParameter(&inverse); - registerParameter(&d); - registerParameter(&transform); - registerParameter(&fill); - registerParameter(&stroke); - registerParameter(&paintorder); - registerParameter(&opacity); - registerParameter(&filter); - scale.param_set_range(0.01, 999999.0); - scale.param_set_increments(1, 1); - scale.param_set_digits(2); + registerParameter(&allow_transforms); + prev_allow_trans = allow_transforms; + previus_method = method; + prev_affine = g_strdup(""); attributes.param_hide_canvas_text(); style_attributes.param_hide_canvas_text(); - preserve_position_changed = preserve_position; - preserve_affine = Geom::identity(); } void -LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root) +LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, const char * attributes, const char * style_attributes) { SPDocument * document = SP_ACTIVE_DOCUMENT; - if (!document) { + if (!document || !origin || !dest) { return; } if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) { @@ -79,7 +74,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for (std::vector<SPObject * >::iterator obj_it = childs.begin(); obj_it != childs.end(); ++obj_it) { SPObject *dest_child = dest->nthChild(index); - cloneAttrbutes((*obj_it), dest_child, live, attributes, style_attributes, false); + cloneAttrbutes((*obj_it), dest_child, attributes, style_attributes); index++; } } @@ -97,7 +92,7 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for ( std::vector<SPObject*>::const_iterator iter=mask_list.begin();iter!=mask_list.end();++iter) { SPObject * mask_data = *iter; SPObject * mask_dest_data = mask_list_dest[i]; - cloneAttrbutes(mask_data, mask_dest_data, live, attributes, style_attributes, false); + cloneAttrbutes(mask_data, mask_dest_data, attributes, style_attributes); i++; } } @@ -112,86 +107,60 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co for ( std::vector<SPObject*>::const_iterator iter=clippath_list.begin();iter!=clippath_list.end();++iter) { SPObject * clippath_data = *iter; SPObject * clippath_dest_data = clippath_list_dest[i]; - cloneAttrbutes(clippath_data, clippath_dest_data, live, attributes, style_attributes, false); + cloneAttrbutes(clippath_data, clippath_dest_data, attributes, style_attributes); i++; } } } gchar ** attarray = g_strsplit(attributes, ",", 0); gchar ** iter = attarray; - Geom::Affine affine_dest = Geom::identity(); - Geom::Affine affine_origin = Geom::identity(); - Geom::Affine affine_previous = Geom::identity(); - sp_svg_transform_read(SP_ITEM(dest)->getAttribute("transform"), &affine_dest); - sp_svg_transform_read(SP_ITEM(origin)->getAttribute("transform"), &affine_origin); while (*iter != NULL) { const char* attribute = (*iter); - if ( std::strcmp(attribute, "transform") == 0 ) { - if (preserve_position) { - Geom::Affine dest_affine = Geom::identity(); - if (root) { - dest_affine *= affine_origin; - if (preserve_affine == Geom::identity()) { - dest_affine *= Geom::Translate(affine_dest.translation()); - } - dest_affine *= Geom::Translate(affine_origin.translation()).inverse(); - dest_affine *= Geom::Translate(preserve_affine.translation()); - affine_previous = preserve_affine; - preserve_affine = Geom::identity(); - gchar * str = sp_svg_transform_write(dest_affine); - SP_ITEM(dest)->getRepr()->setAttribute("transform", str); - g_free(str); - } - } else { - gchar * str = sp_svg_transform_write(affine_origin); - SP_ITEM(dest)->getRepr()->setAttribute("transform", str); - g_free(str); - } - } else if ( shape_dest && shape_origin && live && (std::strcmp(attribute, "d") == 0)) { - SPCurve *c = NULL; - if (inverse) { - c = shape_origin->getCurveBeforeLPE(); - } else { - c = shape_origin->getCurve(); - } - if (c) { - Geom::PathVector c_pv = c->get_pathvector(); - Geom::OptRect orig_bbox = SP_ITEM(origin)->geometricBounds(); - Geom::OptRect dest_bbox = SP_ITEM(dest)->geometricBounds(); - if (dest_bbox && orig_bbox && root) { - Geom::Point orig_point = (*orig_bbox).corner(0); - Geom::Point dest_point = (*dest_bbox).corner(0); - if (scale != 100.0) { - double scale_affine = scale/100.0; - Geom::Scale scale = Geom::Scale(scale_affine); - c_pv *= Geom::Translate(orig_point).inverse(); - c_pv *= scale; - c_pv *= Geom::Translate(orig_point); - } - if (preserve_position) { - c_pv *= Geom::Translate(dest_point - orig_point); + if (strlen(attribute)) { + if ( shape_dest && shape_origin && (std::strcmp(attribute, "d") == 0)) { + SPCurve *c = NULL; + if (method == CLM_BSPLINESPIRO) { + c = shape_origin->getCurveBeforeLPE(); + SPLPEItem * lpe_item = SP_LPE_ITEM(origin); + if (lpe_item) { + PathEffectList lpelist = lpe_item->getEffectList(); + PathEffectList::iterator i; + for (i = lpelist.begin(); i != lpelist.end(); ++i) { + LivePathEffectObject *lpeobj = (*i)->lpeobject; + if (lpeobj) { + Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe(); + if (dynamic_cast<Inkscape::LivePathEffect::LPEBSpline *>(lpe)) { + LivePathEffect::sp_bspline_do_effect(c, 0); + } else if (dynamic_cast<Inkscape::LivePathEffect::LPESpiro *>(lpe)) { + LivePathEffect::sp_spiro_do_effect(c); + } + } + } } - } - if (inverse) { - c_pv *= i2anc_affine(origin, sp_lpe_item); + } else if(method == CLM_ORIGINALD) { + c = shape_origin->getCurveBeforeLPE(); } else { - c_pv *= i2anc_affine(dest, sp_lpe_item); + c = shape_origin->getCurve(); } - c->set_pathvector(c_pv); - if (!path_origin) { - shape_dest->setCurveInsync(c, TRUE); - gchar *str = sp_svg_write_path(c_pv); - dest->getRepr()->setAttribute(attribute, str); - g_free(str); + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + c_pv *= i2anc_affine(dest, sp_lpe_item); + c->set_pathvector(c_pv); + if (!path_origin) { + shape_dest->setCurveInsync(c, TRUE); + gchar *str = sp_svg_write_path(c_pv); + dest->getRepr()->setAttribute(attribute, str); + g_free(str); + } else { + shape_dest->setCurve(c, TRUE); + } + c->unref(); } else { - shape_dest->setCurve(c, TRUE); + dest->getRepr()->setAttribute(attribute, NULL); } - c->unref(); } else { - dest->getRepr()->setAttribute(attribute, NULL); + dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); } - } else { - dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); } iter++; } @@ -204,157 +173,142 @@ LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, co gchar ** styleiter = styleattarray; while (*styleiter != NULL) { const char* attribute = (*styleiter); - const char* origin_attribute = sp_repr_css_property(css_origin, attribute, ""); - if (!strlen(origin_attribute)) { //==0 - sp_repr_css_set_property (css_dest, attribute, NULL); - } else { - sp_repr_css_set_property (css_dest, attribute, origin_attribute); + if (strlen(attribute)) { + const char* origin_attribute = sp_repr_css_property(css_origin, attribute, ""); + if (!strlen(origin_attribute)) { //==0 + sp_repr_css_set_property (css_dest, attribute, NULL); + } else { + sp_repr_css_set_property (css_dest, attribute, origin_attribute); + } } styleiter++; } g_strfreev (styleattarray); Glib::ustring css_str; sp_repr_css_write_string(css_dest,css_str); - dest->getRepr()->setAttribute("style", css_str.c_str()); + dest->getRepr()->setAttribute("style", g_strdup(css_str.c_str())); } - void LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ + start_listening(); if (linkeditem.linksToItem()) { - linkeditem.setInverse(inverse); - if ( preserve_position_changed != preserve_position ) { - if (!preserve_position) { - sp_svg_transform_read(SP_ITEM(sp_lpe_item)->getAttribute("transform"), &preserve_affine); - } - preserve_position_changed = preserve_position; - } Glib::ustring attr = ""; - if (d) { - attr.append("d,"); - } - if (transform) { - attr.append("transform,"); + if (method != CLM_NONE) { + attr += Glib::ustring("d,"); } - attr.append(Glib::ustring(attributes.param_getSVGValue()).append(",")); + attr += Glib::ustring(attributes.param_getSVGValue()) + Glib::ustring(","); if (attr.size() && !Glib::ustring(attributes.param_getSVGValue()).size()) { attr.erase (attr.size()-1, 1); } Glib::ustring style_attr = ""; - if (fill) { - style_attr.append("fill,").append("fill-rule,"); - } - if (stroke) { - style_attr.append("stroke,").append("stroke-width,").append("stroke-linecap,").append("stroke-linejoin,"); - style_attr.append("stroke-opacity,").append("stroke-miterlimit,").append("stroke-dasharray,"); - style_attr.append("stroke-opacity,").append("stroke-dashoffset,").append("marker-start,"); - style_attr.append("marker-mid,").append("marker-end,"); + if (style_attr.size() && !Glib::ustring(style_attributes.param_getSVGValue()).size()) { + style_attr.erase (style_attr.size()-1, 1); } - if (paintorder) { - style_attr.append("paint-order,"); + style_attr += Glib::ustring(style_attributes.param_getSVGValue()) + Glib::ustring(","); + + SPItem * orig = SP_ITEM(linkeditem.getObject()); + SPItem * dest = SP_ITEM(sp_lpe_item); + Geom::OptRect o_bbox = orig->geometricBounds(); + Geom::OptRect d_bbox = dest->geometricBounds(); + gchar * id = g_strdup(orig->getId()); + if (allow_transforms && + !linkeditem.last_transform.isIdentity() && + linkeditem.last_transform.isTranslation() && + method != CLM_NONE) + { + Geom::Point expansion_dest = dest->transform.expansion(); + Geom::Point expansion_orig = orig->transform.expansion(); + dest->transform *= Geom::Scale(expansion_dest).inverse(); + dest->transform *= Geom::Scale(expansion_orig); + dest->transform *= linkeditem.last_transform.inverse(); + dest->transform *= Geom::Scale(expansion_orig).inverse(); + dest->transform *= Geom::Scale(expansion_dest); } - if (filter) { - style_attr.append("filter,"); + if ((strcmp(id, linked) != 0 || (previus_method != method && previus_method == CLM_NONE )) && + allow_transforms && + o_bbox && + d_bbox) + { + dest->transform *= Geom::Translate((*o_bbox).corner(0) - (*d_bbox).corner(0)).inverse(); } - if (opacity) { - style_attr.append("opacity,"); + cloneAttrbutes(orig, dest, g_strdup(attr.c_str()), g_strdup(style_attr.c_str())); + if (allow_transforms && + previus_method != method && + method == CLM_NONE) + { + dest->transform *= Geom::Translate((*d_bbox).corner(0) - (*o_bbox).corner(0)).inverse(); } - if (style_attr.size() && !Glib::ustring(style_attributes.param_getSVGValue()).size()) { - style_attr.erase (style_attr.size()-1, 1); - } - style_attr.append(Glib::ustring(style_attributes.param_getSVGValue()).append(",")); - SPItem * from = inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject()); - SPItem * to = !inverse ? SP_ITEM(sp_lpe_item) : SP_ITEM(linkeditem.getObject()); - cloneAttrbutes(from, to, true, g_strdup(attr.c_str()), g_strdup(style_attr.c_str()), true); - Geom::OptRect bbox = from->geometricBounds(); - if (bbox && preserve_position && origin != Geom::Point(0,0)) { - origin = (*bbox).corner(0) - origin; - to->transform *= Geom::Translate(origin); + if (!allow_transforms) { + SP_ITEM(dest)->getRepr()->setAttribute("transform", SP_ITEM(orig)->getAttribute("transform")); + } else { + SP_ITEM(dest)->getRepr()->setAttribute("transform", sp_svg_transform_write(dest->transform)); + if (prev_allow_trans == allow_transforms) { + prev_affine = g_strdup(SP_ITEM(dest)->getAttribute("transform")); + } } - bbox = from->geometricBounds(); - if (bbox && preserve_position) { - origin = (*bbox).corner(0); + + if (prev_allow_trans != allow_transforms && allow_transforms) { + SP_ITEM(dest)->getRepr()->setAttribute("transform", prev_affine); } + + linked = g_strdup(id); + g_free(id); + } else { + linked = g_strdup(""); } + previus_method = method; + prev_allow_trans = allow_transforms; } - -Gtk::Widget * -LPECloneOriginal::newWidget() +void +LPECloneOriginal::start_listening() { - // 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); - Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) ); - vbox_expander->set_border_width(0); - vbox_expander->set_spacing(2); - std::vector<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter * param = *it; - if (param->param_key == "linkedpath") { - ++it; - continue; - } - Gtk::Widget * widg = param->param_newWidget(); - Glib::ustring * tip = param->param_getTooltip(); - if (widg) { - if (param->param_key != "attributes" && - param->param_key != "style_attributes") { - vbox->pack_start(*widg, true, true, 2); - } else { - vbox_expander->pack_start(*widg, true, true, 2); - } - if (tip) { - widg->set_tooltip_text(*tip); - } else { - widg->set_tooltip_text(""); - widg->set_has_tooltip(false); - } - } - } - - ++it; + if ( !sp_lpe_item || listening ) { + return; } - expander = Gtk::manage(new Gtk::Expander(Glib::ustring(_("Show attributes override")))); - expander->add(*vbox_expander); - expander->set_expanded(expanded); - expander->property_expanded().signal_changed().connect(sigc::mem_fun(*this, &LPECloneOriginal::onExpanderChanged) ); - vbox->pack_start(*expander, true, true, 2); - return dynamic_cast<Gtk::Widget *>(vbox); + quit_listening(); + modified_connection = SP_OBJECT(sp_lpe_item)->connectModified(sigc::mem_fun(*this, &LPECloneOriginal::modified)); + listening = true; } void -LPECloneOriginal::onExpanderChanged() +LPECloneOriginal::quit_listening(void) { - expanded = expander->get_expanded(); - if(expanded) { - expander->set_label (Glib::ustring(_("Hide attributes override"))); - } else { - expander->set_label (Glib::ustring(_("Show attributes override"))); + modified_connection.disconnect(); + listening = false; +} + +void +LPECloneOriginal::modified(SPObject */*obj*/, guint /*flags*/) +{ + if ( !sp_lpe_item || is_updating) { + is_updating = false; + return; } + SP_OBJECT(this->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); + is_updating = true; } LPECloneOriginal::~LPECloneOriginal() { - + quit_listening(); + g_free(linked); + g_free(prev_affine); } void LPECloneOriginal::transform_multiply(Geom::Affine const& postmul, bool set) { - if (linkeditem.linksToItem()) { - linkeditem.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG); + if (!allow_transforms && linkeditem.linksToItem()) { + sp_lpe_item->transform *= postmul.inverse(); } } void LPECloneOriginal::doEffect (SPCurve * curve) { - if (linkeditem.linksToItem() && !inverse) { + if (linkeditem.linksToItem()) { SPShape * shape = getCurrentShape(); if(shape){ curve->set_pathvector(shape->getCurve()->get_pathvector()); |
