diff options
| author | Jabiertxof <jtx@jtx> | 2016-12-28 08:42:19 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx> | 2016-12-28 08:42:19 +0000 |
| commit | 50714133d92da517b5185385ea4c553408c80e54 (patch) | |
| tree | 27ecbc256d57c51e4425bb566da888b825941c10 | |
| parent | Fixes bug #1652465 on mirror and copy rotate LPE. (diff) | |
| download | inkscape-50714133d92da517b5185385ea4c553408c80e54.tar.gz inkscape-50714133d92da517b5185385ea4c553408c80e54.zip | |
First attemp working
(bzr r15356.1.1)
| -rw-r--r-- | src/live_effects/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/live_effects/effect.cpp | 10 | ||||
| -rw-r--r-- | src/live_effects/effect.h | 1 | ||||
| -rw-r--r-- | src/live_effects/lpe-clone-original.cpp | 169 | ||||
| -rw-r--r-- | src/live_effects/lpe-clone-original.h | 20 | ||||
| -rw-r--r-- | src/sp-ellipse.cpp | 13 | ||||
| -rw-r--r-- | src/sp-item-group.cpp | 37 | ||||
| -rw-r--r-- | src/sp-lpe-item.cpp | 21 | ||||
| -rw-r--r-- | src/sp-lpe-item.h | 3 | ||||
| -rw-r--r-- | src/sp-object.cpp | 14 | ||||
| -rw-r--r-- | src/sp-object.h | 3 | ||||
| -rw-r--r-- | src/sp-path.cpp | 4 | ||||
| -rw-r--r-- | src/ui/clipboard.cpp | 2 |
13 files changed, 261 insertions, 42 deletions
diff --git a/src/live_effects/CMakeLists.txt b/src/live_effects/CMakeLists.txt index 784317090..5ffccc7c0 100644 --- a/src/live_effects/CMakeLists.txt +++ b/src/live_effects/CMakeLists.txt @@ -60,6 +60,9 @@ set(live_effects_SRC parameter/array.cpp parameter/bool.cpp parameter/filletchamferpointarray.cpp + parameter/item-reference.cpp + parameter/item.cpp + parameter/originalitem.cpp parameter/originalpath.cpp parameter/originalpatharray.cpp parameter/parameter.cpp @@ -142,6 +145,9 @@ set(live_effects_SRC parameter/bool.h parameter/enum.h parameter/filletchamferpointarray.h + parameter/item.h + parameter/item-reference.h + parameter/originalitem.h parameter/originalpath.h parameter/originalpatharray.h parameter/parameter.h diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp index 5cc0d6f20..cfd393b87 100644 --- a/src/live_effects/effect.cpp +++ b/src/live_effects/effect.cpp @@ -116,7 +116,7 @@ const Util::EnumData<EffectType> LPETypeData[] = { {RULER, N_("Ruler"), "ruler"}, /* 0.91 */ {POWERSTROKE, N_("Power stroke"), "powerstroke"}, - {CLONE_ORIGINAL, N_("Clone original path"), "clone_original"}, + {CLONE_ORIGINAL, N_("Clone original"), "clone_original"}, /* 0.92 */ {SIMPLIFY, N_("Simplify"), "simplify"}, {LATTICE2, N_("Lattice Deformation 2"), "lattice2"}, @@ -457,8 +457,7 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) //printf("(SPLPEITEM*) %p\n", sp_lpe_item); SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); if(shape){ - sp_curve = shape->getCurve(); - pathvector_before_effect = sp_curve->get_pathvector(); + setSPCurve(shape->getCurve()); } doBeforeEffect(lpeitem); if (apply_to_clippath_and_mask && SP_IS_GROUP(sp_lpe_item)) { @@ -468,6 +467,11 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) update_helperpath(); } +void Effect::setSPCurve(SPCurve *curve) +{ + sp_curve = curve; + pathvector_before_effect = curve->get_pathvector(); +} /** * Effects can have a parameter path set before they are applied by accepting a nonzero number of * mouse clicks. This method activates the pen context, which waits for the specified number of diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h index 1997ff0ca..e975deb05 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -73,6 +73,7 @@ public: static int acceptsNumClicks(EffectType type); int acceptsNumClicks() const { return acceptsNumClicks(effectType()); } void doAcceptPathPreparations(SPLPEItem *lpeitem); + void setSPCurve(SPCurve *curve); /* * isReady() indicates whether all preparations which are necessary to apply the LPE are done, diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 10418a02d..be8bc9e0d 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -6,6 +6,11 @@ #include "live_effects/lpe-clone-original.h" #include "display/curve.h" +#include "svg/path-string.h" +#include "svg/svg.h" +#include <boost/algorithm/string.hpp> +#include "xml/sp-css-attr.h" + // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -14,9 +19,148 @@ namespace LivePathEffect { LPECloneOriginal::LPECloneOriginal(LivePathEffectObject *lpeobject) : Effect(lpeobject), - linked_path(_("Linked path:"), _("Path from which to take the original path data"), "linkedpath", &wr, this) + linked_item(_("Linked Item:"), _("Item from which to take the original data"), "linked_item", &wr, this), + preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false), + attributes("Attributes linked", "Attributes linked", "attributes", &wr, this,""), + style_attributes("Style attributes linked", "Style attributes linked", "style_attributes", &wr, this,"") { - registerParameter( dynamic_cast<Parameter *>(&linked_path) ); + registerParameter(&linked_item); + registerParameter(&attributes); + registerParameter(&style_attributes); + registerParameter(&preserve_position); + attributes.param_hide_canvas_text(); + style_attributes.param_hide_canvas_text(); + apply_to_clippath_and_mask = true; +} + +void +LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * first_attribute, ...) +{ + va_list args; + va_start(args, first_attribute); + SPDocument * document = SP_ACTIVE_DOCUMENT; + if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) { + std::vector< SPObject * > childs = origin->childList(true); + size_t index = 0; + 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, first_attribute, args); + index++; + } + } + SPShape * shape_origin = SP_SHAPE(origin); + SPShape * shape_dest = SP_SHAPE(dest); + for (const char* att = first_attribute; att != NULL; att = va_arg(args, const char*)) { + std::vector<std::string> elems; + boost::split(elems, att, boost::is_any_of(",")); + for (std::vector<std::string>::const_iterator atts = elems.begin(); + atts != elems.end(); ++atts) { + const char* attribute = (*atts).c_str(); + if ( std::strcmp(attribute, "transform") == 0 ) { + Geom::Affine affine_dest = Geom::identity(); + sp_svg_transform_read(SP_ITEM(dest)->getAttribute("transform"), &affine_dest); + dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); + if (preserve_position) { + Geom::Affine affine_origin = Geom::identity(); + sp_svg_transform_read(SP_ITEM(origin)->getAttribute("transform"), &affine_origin); + SP_ITEM(dest)->transform = Geom::Translate(affine_dest.translation()) * Geom::Translate(affine_origin.translation()).inverse() * affine_origin; + } + } else if ( shape_dest && shape_origin && live && (std::strcmp(attribute, "d") == 0 || std::strcmp(attribute, "inkscape:original-d") == 0)) { + SPCurve *c = NULL; + if (std::strcmp(attribute, "d") == 0) { + c = shape_origin->getCurve(); + } else { + c = shape_origin->getCurveBeforeLPE(); + } + if (c) { + Geom::PathVector c_pv = c->get_pathvector(); + if (preserve_position) { + Geom::OptRect orig_bbox = SP_ITEM(origin)->geometricBounds(); + if (orig_bbox) { + c_pv *= Geom::Translate(Geom::Point(boundingbox_X.min(), boundingbox_Y.min()) - (*orig_bbox).corner(0)); + } + } + c->set_pathvector(c_pv); + shape_dest->setCurveInsync(c, TRUE); + dest->getRepr()->setAttribute(attribute, sp_svg_write_path(c_pv)); + c->unref(); + } else { + dest->getRepr()->setAttribute(attribute, NULL); + } + } else { + dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); + } + } + } + va_end(args); +} + +void +LPECloneOriginal::cloneStyleAttrbutes(SPObject *origin, SPObject *dest, const char * first_attribute, ...) +{ + va_list args; + va_start(args, first_attribute); + + if ( SP_IS_GROUP(origin) && SP_IS_GROUP(dest) && SP_GROUP(origin)->getItemCount() == SP_GROUP(dest)->getItemCount() ) { + std::vector< SPObject * > childs = origin->childList(true); + size_t index = 0; + for (std::vector<SPObject * >::iterator obj_it = childs.begin(); + obj_it != childs.end(); ++obj_it) { + SPObject *dest_child = dest->nthChild(index); + cloneStyleAttrbutes(*obj_it, dest_child, first_attribute, args); + index++; + } + } + SPCSSAttr *css_origin = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css_origin, origin->getRepr()->attribute("style")); + SPCSSAttr *css_dest = sp_repr_css_attr_new(); + sp_repr_css_attr_add_from_string(css_dest, dest->getRepr()->attribute("style")); + for (const char* att = first_attribute; att != NULL; att = va_arg(args, const char*)) { + std::vector<std::string> elems; + boost::split(elems, att, boost::is_any_of(",")); + for (std::vector<std::string>::const_iterator atts = elems.begin(); + atts != elems.end(); ++atts) { + const char* attribute = (*atts).c_str(); + const char* origin_attribute = sp_repr_css_property(css_origin, attribute, ""); + if (origin_attribute == "") { + sp_repr_css_set_property (css_dest, attribute, NULL); + } else { + sp_repr_css_set_property (css_dest, attribute, origin_attribute); + } + } + Glib::ustring css_str; + sp_repr_css_write_string(css_dest,css_str); + dest->getRepr()->setAttribute("style", css_str.c_str()); + } + va_end(args); +} + +void +LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ + original_bbox(lpeitem); + if (linked_item.linksToItem() && sp_lpe_item) { + cloneAttrbutes(linked_item.getObject(), SP_OBJECT(sp_lpe_item), true, attributes.param_getSVGValue(), NULL); //NULL required + cloneStyleAttrbutes(linked_item.getObject(), SP_OBJECT(sp_lpe_item), style_attributes.param_getSVGValue(), NULL); //NULL required + SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); + if(shape){ + this->setSPCurve(shape->getCurve()); + } + } +} + +void +LPECloneOriginal::doOnApply(SPLPEItem const* lpeitem){ + Glib::ustring attributes_value("d,transform"); + attributes.param_setValue(attributes_value); + attributes.write_to_SVG(); + Glib::ustring style_attributes_value("opacity,border-width"); + style_attributes.param_setValue(style_attributes_value); + style_attributes.write_to_SVG(); +} + +void +LPECloneOriginal::doAfterEffect (SPLPEItem const* lpeitem){ } LPECloneOriginal::~LPECloneOriginal() @@ -26,12 +170,21 @@ LPECloneOriginal::~LPECloneOriginal() void LPECloneOriginal::doEffect (SPCurve * curve) { - if ( linked_path.linksToPath() ) { - Geom::PathVector linked_pathv = linked_path.get_pathvector(); - if ( !linked_pathv.empty() ) { - curve->set_pathvector(linked_pathv); - } - } +// std::vector<std::string> elems; +// const char * attrs = attributes.param_getSVGValue(); +// boost::split(elems, attrs, boost::is_any_of(",")); +// bool has_d = false; +// for (std::vector<std::string>::const_iterator atts = elems.begin(); +// atts != elems.end(); ++atts) { +// const char* attribute = (*atts).c_str(); +// if (std::strcmp(attribute, "d") == 0) { +// has_d = true; +// } +// } +// if (linked_item.linksToItem() && has_d) { +// curve->reset(); +// } + curve->set_pathvector(pathvector_before_effect); } } // namespace LivePathEffect diff --git a/src/live_effects/lpe-clone-original.h b/src/live_effects/lpe-clone-original.h index abf65ded8..148590695 100644 --- a/src/live_effects/lpe-clone-original.h +++ b/src/live_effects/lpe-clone-original.h @@ -10,22 +10,32 @@ */ #include "live_effects/effect.h" -#include "live_effects/parameter/originalpath.h" +#include "live_effects/parameter/originalitem.h" +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/point.h" +#include "live_effects/parameter/text.h" +#include "live_effects/lpegroupbbox.h" namespace Inkscape { namespace LivePathEffect { -class LPECloneOriginal : public Effect { +class LPECloneOriginal : public Effect, GroupBBoxEffect { public: LPECloneOriginal(LivePathEffectObject *lpeobject); virtual ~LPECloneOriginal(); virtual void doEffect (SPCurve * curve); + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual void doAfterEffect (SPLPEItem const* lpeitem); + virtual void doOnApply(SPLPEItem const* lpeitem); + void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * first_attribute, ...); + void cloneStyleAttrbutes(SPObject *origin, SPObject *dest, const char * first_attribute, ...); private: - OriginalPathParam linked_path; - -private: + OriginalItemParam linked_item; + BoolParam preserve_position; + TextParam attributes; + TextParam style_attributes; LPECloneOriginal(const LPECloneOriginal&); LPECloneOriginal& operator=(const LPECloneOriginal&); }; diff --git a/src/sp-ellipse.cpp b/src/sp-ellipse.cpp index ed1e2b504..9589d6fce 100644 --- a/src/sp-ellipse.cpp +++ b/src/sp-ellipse.cpp @@ -445,11 +445,20 @@ void SPGenericEllipse::set_shape() if (hasPathEffect() && pathEffectsEnabled()) { SPCurve *c_lpe = curve->copy(); bool success = this->performPathEffect(c_lpe); - + if (success) { this->setCurveInsync(c_lpe, TRUE); + } else { + Inkscape::XML::Node *repr = this->getRepr(); + if (gchar const * value = repr->attribute("d")) { + Geom::PathVector pv = sp_svg_read_pathv(value); + SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); + if (oldcurve) { + this->setCurveInsync(oldcurve, TRUE); + oldcurve->unref(); + } + } } - c_lpe->unref(); } diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp index 7b2507b5e..808d475c7 100644 --- a/src/sp-item-group.cpp +++ b/src/sp-item-group.cpp @@ -950,25 +950,36 @@ sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup, bool write) } else { c = subShape->getCurve(); } - + bool success = false; // only run LPEs when the shape has a curve defined if (c) { c->transform(i2anc_affine(subitem, topgroup)); - topgroup->performPathEffect(c); + success = topgroup->performPathEffect(c, subShape); c->transform(i2anc_affine(subitem, topgroup).inverse()); - subShape->setCurve(c, TRUE); - - if (write) { + if (c && success) { + subShape->setCurve(c, TRUE); + if (write) { + Inkscape::XML::Node *repr = subitem->getRepr(); + gchar *str = sp_svg_write_path(c->get_pathvector()); + repr->setAttribute("d", str); + #ifdef GROUP_VERBOSE + g_message("sp_group_perform_patheffect writes 'd' attribute"); + #endif + g_free(str); + } + c->unref(); + } else { + // LPE was unsuccesfull or doeffect stack return null. Read the old 'd'-attribute. Inkscape::XML::Node *repr = subitem->getRepr(); - gchar *str = sp_svg_write_path(c->get_pathvector()); - repr->setAttribute("d", str); -#ifdef GROUP_VERBOSE - g_message("sp_group_perform_patheffect writes 'd' attribute"); -#endif - g_free(str); + if (gchar const * value = repr->attribute("d")) { + Geom::PathVector pv = sp_svg_read_pathv(value); + SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); + if (oldcurve) { + subShape->setCurve(oldcurve, TRUE); + oldcurve->unref(); + } + } } - - c->unref(); } } } diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp index e2f61bfb5..f5c930404 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -209,7 +209,7 @@ Inkscape::XML::Node* SPLPEItem::write(Inkscape::XML::Document *xml_doc, Inkscape /** * returns true when LPE was successful. */ -bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) { +bool SPLPEItem::performPathEffect(SPCurve *curve, SPShape *current, bool is_clip_or_mask) { if (!curve) { return false; @@ -244,9 +244,11 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) { if (!SP_IS_GROUP(this)) { lpe->doBeforeEffect_impl(this); } - + if (SP_IS_GROUP(this) && current) { + lpe->setSPCurve(current->getCurve()); + } try { - lpe->doEffect(curve); + lpe->doEffect(curve); } catch (std::exception & e) { g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what()); @@ -695,10 +697,10 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item) try { if(SP_IS_GROUP(this)){ c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this))); - success = this->performPathEffect(c, true); + success = this->performPathEffect(c, SP_SHAPE(clip_mask), true); c->transform(i2anc_affine(SP_GROUP(item), SP_GROUP(this)).inverse()); } else { - success = this->performPathEffect(c, true); + success = this->performPathEffect(c, NULL, true); } } catch (std::exception & e) { g_warning("Exception during LPE execution. \n %s", e.what()); @@ -709,12 +711,13 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item) success = false; } Inkscape::XML::Node *repr = clip_mask->getRepr(); - if (success) { + // This c check allow to not apply LPE if curve is NULL after performPathEffect used in clone.obgets LPE + if (success && c) { gchar *str = sp_svg_write_path(c->get_pathvector()); repr->setAttribute("d", str); g_free(str); } else { - // LPE was unsuccesfull. Read the old 'd'-attribute. + // LPE was unsuccesfull or doeffect stack return null.. Read the old 'd'-attribute. if (gchar const * value = repr->attribute("d")) { Geom::PathVector pv = sp_svg_read_pathv(value); SPCurve *oldcurve = new (std::nothrow) SPCurve(pv); @@ -724,7 +727,9 @@ SPLPEItem::apply_to_clip_or_mask(SPItem *clip_mask, SPItem *item) } } } - c->unref(); + if (c) { + c->unref(); + } } } } diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h index 9e5cb3329..9cf868cf2 100644 --- a/src/sp-lpe-item.h +++ b/src/sp-lpe-item.h @@ -23,6 +23,7 @@ class LivePathEffectObject; class SPCurve; +class SPShape; class SPDesktop; namespace Inkscape{ @@ -69,7 +70,7 @@ public: virtual void update_patheffect(bool write); - bool performPathEffect(SPCurve *curve, bool is_clip_or_mask = false); + bool performPathEffect(SPCurve *curve, SPShape *current = NULL, bool is_clip_or_mask = false); bool pathEffectsEnabled() const; bool hasPathEffect() const; diff --git a/src/sp-object.cpp b/src/sp-object.cpp index e9c60fc7d..c2122e109 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -773,6 +773,20 @@ void SPObject::appendChild(Inkscape::XML::Node *child) { repr->appendChild(child); } +SPObject* SPObject::nthChild(unsigned index) { + g_assert(this->repr); + if (hasChildren()) { + std::vector<SPObject*> l; + unsigned counter = 0; + for (auto& child: children) { + if (counter == index) { + return &child; + } + } + } + return NULL; +} + void SPObject::addChild(Inkscape::XML::Node *child, Inkscape::XML::Node * prev) { g_assert(this->repr); diff --git a/src/sp-object.h b/src/sp-object.h index 9abbd324b..d145e966b 100644 --- a/src/sp-object.h +++ b/src/sp-object.h @@ -318,6 +318,9 @@ public: SPObject *lastChild() { return children.empty() ? nullptr : &children.back(); } SPObject const *lastChild() const { return children.empty() ? nullptr : &children.back(); } + SPObject *nthChild(unsigned index); + SPObject const *nthChild(unsigned index) const; + enum Action { ActionGeneral, ActionBBox, ActionUpdate, ActionShow }; /** diff --git a/src/sp-path.cpp b/src/sp-path.cpp index b593b7937..0a2ce4c09 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -354,9 +354,9 @@ g_message("sp_path_update_patheffect writes '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); + this->setCurveInsync(oldcurve, TRUE); + repr->setAttribute("d", value); oldcurve->unref(); } } diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp index a8e708597..42fc2fab4 100644 --- a/src/ui/clipboard.cpp +++ b/src/ui/clipboard.cpp @@ -410,6 +410,8 @@ const gchar *ClipboardManagerImpl::getFirstObjectID() strcmp(ch->name(), "svg:use") && strcmp(ch->name(), "svg:text") && strcmp(ch->name(), "svg:image") && + strcmp(ch->name(), "svg:ellipse") && + strcmp(ch->name(), "svg:circle") && strcmp(ch->name(), "svg:rect") ) { ch = ch->next(); |
