summaryrefslogtreecommitdiffstats
path: root/src/live_effects/lpe-clone-original.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/live_effects/lpe-clone-original.cpp')
-rw-r--r--src/live_effects/lpe-clone-original.cpp358
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());