diff options
| author | Jabiertxof <jtx@jtx> | 2017-01-01 14:02:26 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx> | 2017-01-01 14:02:26 +0000 |
| commit | 57132e1d5f4729e2ea1abc2ef835f3962f6680b4 (patch) | |
| tree | 369c9d944697c466c99a549b9456a805e0d47d76 /src | |
| parent | Update to trunk (diff) | |
| parent | Update to trunk (diff) | |
| download | inkscape-57132e1d5f4729e2ea1abc2ef835f3962f6680b4.tar.gz inkscape-57132e1d5f4729e2ea1abc2ef835f3962f6680b4.zip | |
merge mirror improvements
(bzr r15295.1.41)
Diffstat (limited to 'src')
| -rw-r--r-- | src/live_effects/CMakeLists.txt | 6 | ||||
| -rw-r--r-- | src/live_effects/effect.cpp | 41 | ||||
| -rw-r--r-- | src/live_effects/effect.h | 8 | ||||
| -rw-r--r-- | src/live_effects/lpe-clone-original.cpp | 279 | ||||
| -rw-r--r-- | src/live_effects/lpe-clone-original.h | 23 | ||||
| -rw-r--r-- | src/live_effects/lpe-copy_rotate.cpp | 1 | ||||
| -rw-r--r-- | src/live_effects/parameter/item-reference.cpp | 44 | ||||
| -rw-r--r-- | src/live_effects/parameter/item-reference.h | 56 | ||||
| -rw-r--r-- | src/live_effects/parameter/item.cpp | 246 | ||||
| -rw-r--r-- | src/live_effects/parameter/item.h | 79 | ||||
| -rw-r--r-- | src/live_effects/parameter/originalitem.cpp | 127 | ||||
| -rw-r--r-- | src/live_effects/parameter/originalitem.h | 48 | ||||
| -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 | 1 | ||||
| -rw-r--r-- | src/sp-path.cpp | 31 | ||||
| -rw-r--r-- | src/ui/clipboard.cpp | 2 |
19 files changed, 998 insertions, 68 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..81a512d23 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"}, @@ -356,7 +356,7 @@ Effect::Effect(LivePathEffectObject *lpeobject) sp_lpe_item(NULL), current_zoom(1), upd_params(true), - sp_curve(NULL), + sp_shape(NULL), provides_own_flash_paths(true), // is automatically set to false if providesOwnFlashPaths() is not overridden is_ready(false) // is automatically set to false if providesOwnFlashPaths() is not overridden { @@ -392,9 +392,9 @@ Effect::doOnApply (SPLPEItem const*/*lpeitem*/) } void -Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP) +Effect::setSelectedNodePoints(std::vector<Geom::Point> selected_np) { - selectedNodesPoints = sNP; + selected_nodes_points = selected_np; } void @@ -404,16 +404,16 @@ Effect::setCurrentZoom(double cZ) } bool -Effect::isNodePointSelected(Geom::Point const &nodePoint) const +Effect::isNodePointSelected(Geom::Point const &node_point) const { - if (selectedNodesPoints.size() > 0) { + if (selected_nodes_points.size() > 0) { using Geom::X; using Geom::Y; - for (std::vector<Geom::Point>::const_iterator i = selectedNodesPoints.begin(); - i != selectedNodesPoints.end(); ++i) { + for (std::vector<Geom::Point>::const_iterator i = selected_nodes_points.begin(); + i != selected_nodes_points.end(); ++i) { Geom::Point p = *i; Geom::Affine transformCoordinate = sp_lpe_item->i2dt_affine(); - Geom::Point p2(nodePoint[X],nodePoint[Y]); + Geom::Point p2(node_point[X], node_point[Y]); p2 *= transformCoordinate; if (Geom::are_near(p, p2, 0.01)) { return true; @@ -446,21 +446,24 @@ void Effect::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/) void Effect::doOnApply_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - /*sp_curve = SP_SHAPE(sp_lpe_item)->getCurve(); - pathvector_before_effect = sp_curve->get_pathvector();*/ + SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); + if(shape){ + setCurrentShape(shape); + } doOnApply(lpeitem); } void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) { sp_lpe_item = const_cast<SPLPEItem *>(lpeitem); - //printf("(SPLPEITEM*) %p\n", sp_lpe_item); + //Groups set shape in performPathEffect before each call to doEffect SPShape * shape = dynamic_cast<SPShape *>(sp_lpe_item); if(shape){ - sp_curve = shape->getCurve(); - pathvector_before_effect = sp_curve->get_pathvector(); + setCurrentShape(shape); } + //printf("(SPLPEITEM*) %p\n", sp_lpe_item); doBeforeEffect(lpeitem); + if (apply_to_clippath_and_mask && SP_IS_GROUP(sp_lpe_item)) { sp_lpe_item->apply_to_clippath(sp_lpe_item); sp_lpe_item->apply_to_mask(sp_lpe_item); @@ -468,6 +471,16 @@ void Effect::doBeforeEffect_impl(SPLPEItem const* lpeitem) update_helperpath(); } +void Effect::setCurrentShape(SPShape * shape){ + if(shape){ + sp_shape = shape; + if (!(sp_curve = sp_shape->getCurve())) { + // oops + return; + } + pathvector_before_effect = sp_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 bc56c2390..b1dc0eabb 100644 --- a/src/live_effects/effect.h +++ b/src/live_effects/effect.h @@ -79,7 +79,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); /* * isReady() indicates whether all preparations which are necessary to apply the LPE are done, * e.g., waiting for a parameter path either before the effect is created or when it needs a @@ -169,9 +170,10 @@ 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. + SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.z + 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. double current_zoom; - std::vector<Geom::Point> selectedNodesPoints; + std::vector<Geom::Point> selected_nodes_points; SPCurve * sp_curve; Geom::PathVector pathvector_before_effect; private: diff --git a/src/live_effects/lpe-clone-original.cpp b/src/live_effects/lpe-clone-original.cpp index 10418a02d..76cc56b8f 100644 --- a/src/live_effects/lpe-clone-original.cpp +++ b/src/live_effects/lpe-clone-original.cpp @@ -6,6 +6,12 @@ #include "live_effects/lpe-clone-original.h" #include "display/curve.h" +#include "svg/path-string.h" +#include "svg/svg.h" +#include "sp-clippath.h" +#include "sp-mask.h" +#include "xml/sp-css-attr.h" + // TODO due to internal breakage in glibmm headers, this must be last: #include <glibmm/i18n.h> @@ -14,9 +20,258 @@ 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_path("LEGACY FALLBACK", "LEGACY FALLBACK", "linkedpath", &wr, this), + linked_item(_("Linked Item:"), _("Item from which to take the original data"), "linked_item", &wr, this), + scale(_("Scale %"), _("Scale item %"), "scale", &wr, this, 100.0), + preserve_position(_("Preserve position"), _("Preserve position"), "preserve_position", &wr, this, false), + use_center(_("Relative center of element"), _("Relative center of element"), "use_center", &wr, this, true), + attributes("Attributes linked", "Attributes linked", "attributes", &wr, this,""), + style_attributes("Style attributes linked", "Style attributes linked", "style_attributes", &wr, this,"") +{ + registerParameter(&linked_path); + registerParameter(&linked_item); + registerParameter(&scale); + registerParameter(&attributes); + registerParameter(&style_attributes); + registerParameter(&preserve_position); + registerParameter(&use_center); + scale.param_set_range(0.01, 999999.0); + scale.param_set_increments(1, 1); + scale.param_set_digits(2); + attributes.param_hide_canvas_text(); + style_attributes.param_hide_canvas_text(); + preserve_position_changed = preserve_position; + preserve_affine = Geom::identity(); +} + +bool hasLinkedTransform( const char * attributes) { + gchar ** attarray = g_strsplit(attributes, ",", 0); + gchar ** iter = attarray; + bool has_linked_transform = false; + while (*iter != NULL) { + const char* attribute = (*iter); + if ( std::strcmp(attribute, "transform") == 0 ) { + has_linked_transform = true; + } + iter++; + } + return has_linked_transform; +} + +void +LPECloneOriginal::cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root) +{ + 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, attributes, style_attributes, false); + index++; + } + } + //Attributes + SPShape * shape_origin = SP_SHAPE(origin); + SPPath * path_origin = SP_PATH(origin); + SPShape * shape_dest = SP_SHAPE(dest); + SPMask *mask_origin = SP_ITEM(origin)->mask_ref->getObject(); + SPMask *mask_dest = SP_ITEM(dest)->mask_ref->getObject(); + if(mask_origin && mask_dest) { + std::vector<SPObject*> mask_list = mask_origin->childList(true); + std::vector<SPObject*> mask_list_dest = mask_dest->childList(true); + if (mask_list.size() == mask_list_dest.size()) { + size_t i = 0; + 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); + i++; + } + } + } + SPClipPath *clippath_origin = SP_ITEM(origin)->clip_ref->getObject(); + SPClipPath *clippath_dest = SP_ITEM(dest)->clip_ref->getObject(); + if(clippath_origin && clippath_dest) { + std::vector<SPObject*> clippath_list = clippath_origin->childList(true); + std::vector<SPObject*> clippath_list_dest = clippath_dest->childList(true); + if (clippath_list.size() == clippath_list_dest.size()) { + size_t i = 0; + 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); + 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(); + SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(dest_affine)); + } + } else { + SP_ITEM(dest)->getRepr()->setAttribute("transform",sp_svg_transform_write(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(); + 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 (use_center) { + orig_point = (*orig_bbox).midpoint(); + dest_point = (*dest_bbox).midpoint(); + } + 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 && hasLinkedTransform(attributes)) { + c_pv *= Geom::Translate(dest_point - orig_point); + } + } + c_pv *= i2anc_affine(dest, sp_lpe_item); + c->set_pathvector(c_pv); + if (!path_origin) { + shape_dest->setCurveInsync(c, TRUE); + dest->getRepr()->setAttribute(attribute, sp_svg_write_path(c_pv)); + } else { + shape_dest->setCurve(c, TRUE); + } + c->unref(); + } else { + dest->getRepr()->setAttribute(attribute, NULL); + } + } else { + dest->getRepr()->setAttribute(attribute, origin->getRepr()->attribute(attribute)); + } + iter++; + } + g_strfreev (attarray); + 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")); + gchar ** styleattarray = g_strsplit(style_attributes, ",", 0); + gchar ** styleiter = styleattarray; + while (*styleiter != NULL) { + const char* attribute = (*styleiter); + 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); + } + 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()); +} + +void +LPECloneOriginal::doBeforeEffect (SPLPEItem const* lpeitem){ + original_bbox(lpeitem); + if (linked_path.linksToPath()) { //Legacy staff + Glib::ustring attributes_value("d"); + attributes.param_setValue(attributes_value); + attributes.write_to_SVG(); + Glib::ustring style_attributes_value(""); + style_attributes.param_setValue(style_attributes_value); + style_attributes.write_to_SVG(); + linked_item.param_readSVGValue(linked_path.param_getSVGValue()); + linked_path.param_readSVGValue(""); + } + + if (linked_item.linksToItem()) { + 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; + } + cloneAttrbutes(linked_item.getObject(), SP_OBJECT(sp_lpe_item), true, attributes.param_getSVGValue(), style_attributes.param_getSVGValue(), true); + } +} + + +Gtk::Widget * +LPECloneOriginal::newWidget() { - registerParameter( dynamic_cast<Parameter *>(&linked_path) ); + // use manage here, because after deletion of Effect object, others might + // still be pointing to this widget. + Gtk::VBox *vbox = Gtk::manage(new Gtk::VBox(Effect::newWidget())); + vbox->set_border_width(5); + vbox->set_homogeneous(false); + vbox->set_spacing(2); + + std::vector<Parameter *>::iterator it = param_vector.begin(); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter * param = *it; + if (param->param_key == "linkedpath") { + ++it; + continue; + } + Gtk::Widget * widg = 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; + } + this->upd_params = false; + return dynamic_cast<Gtk::Widget *>(vbox); +} + +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,stroke-width"); + style_attributes.param_setValue(style_attributes_value); + style_attributes.write_to_SVG(); } LPECloneOriginal::~LPECloneOriginal() @@ -24,12 +279,22 @@ LPECloneOriginal::~LPECloneOriginal() } -void LPECloneOriginal::doEffect (SPCurve * curve) +void +LPECloneOriginal::transform_multiply(Geom::Affine const& postmul, bool set) +{ + if (linked_item.linksToItem()) { + bool changed = false; + linked_item.getObject()->requestModified(SP_OBJECT_MODIFIED_FLAG); + } +} + +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); + if (linked_item.linksToItem()) { + SPShape * shape = getCurrentShape(); + if(shape){ + curve->set_pathvector(shape->getCurve()->get_pathvector()); } } } diff --git a/src/live_effects/lpe-clone-original.h b/src/live_effects/lpe-clone-original.h index abf65ded8..064fe84b2 100644 --- a/src/live_effects/lpe-clone-original.h +++ b/src/live_effects/lpe-clone-original.h @@ -10,22 +10,37 @@ */ #include "live_effects/effect.h" +#include "live_effects/parameter/originalitem.h" #include "live_effects/parameter/originalpath.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 doOnApply(SPLPEItem const* lpeitem); virtual void doEffect (SPCurve * curve); + virtual void doBeforeEffect (SPLPEItem const* lpeitem); + virtual void transform_multiply(Geom::Affine const& postmul, bool set); + virtual Gtk::Widget * newWidget(); + void cloneAttrbutes(SPObject *origin, SPObject *dest, bool live, const char * attributes, const char * style_attributes, bool root); private: OriginalPathParam linked_path; - -private: + OriginalItemParam linked_item; + ScalarParam scale; + BoolParam preserve_position; + BoolParam use_center; + TextParam attributes; + TextParam style_attributes; + bool preserve_position_changed; + Geom::Affine preserve_affine; LPECloneOriginal(const LPECloneOriginal&); LPECloneOriginal& operator=(const LPECloneOriginal&); }; diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp index 813f25d3d..250f6aa29 100644 --- a/src/live_effects/lpe-copy_rotate.cpp +++ b/src/live_effects/lpe-copy_rotate.cpp @@ -125,7 +125,6 @@ void LPECopyRotate::transform_multiply(Geom::Affine const& postmul, bool set) { // cycle through all parameters. Most parameters will not need transformation, but path and point params do. - for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); ++it) { Parameter * param = *it; param->param_transform_multiply(postmul, set); diff --git a/src/live_effects/parameter/item-reference.cpp b/src/live_effects/parameter/item-reference.cpp new file mode 100644 index 000000000..a775d93b7 --- /dev/null +++ b/src/live_effects/parameter/item-reference.cpp @@ -0,0 +1,44 @@ +/* + * The reference corresponding to href of LPE Item parameter. + * + * Copyright (C) 2008 Johan Engelen + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include "live_effects/parameter/item-reference.h" + +#include "sp-shape.h" +#include "sp-text.h" +#include "sp-item-group.h" + +namespace Inkscape { +namespace LivePathEffect { + +bool ItemReference::_acceptObject(SPObject * const obj) const +{ + if (SP_IS_SHAPE(obj) || SP_IS_TEXT(obj) || SP_IS_GROUP(obj)) { + /* Refuse references to lpeobject */ + if (obj == getOwner()) { + return false; + } + // TODO: check whether the referred item has this LPE applied, if so: deny deny deny! + return URIReference::_acceptObject(obj); + } else { + return false; + } +} + +} // namespace LivePathEffect +} // namespace Inkscape + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/item-reference.h b/src/live_effects/parameter/item-reference.h new file mode 100644 index 000000000..91231455a --- /dev/null +++ b/src/live_effects/parameter/item-reference.h @@ -0,0 +1,56 @@ +#ifndef SEEN_LPE_ITEM_REFERENCE_H +#define SEEN_LPE_ITEM_REFERENCE_H + +/* + * Copyright (C) 2008-2012 Authors + * Authors: Johan Engelen + * Abhishek Sharma + * + * Released under GNU GPL, read the file 'COPYING' for more information. + */ + +#include <uri-references.h> + +class SPItem; +namespace Inkscape { +namespace XML { class Node; } + +namespace LivePathEffect { + +/** + * The reference corresponding to href of LPE ItemParam. + */ +class ItemReference : public Inkscape::URIReference { +public: + ItemReference(SPObject *owner) : URIReference(owner) {} + + SPItem *getObject() const { + return (SPItem *)URIReference::getObject(); + } + +protected: + virtual bool _acceptObject(SPObject * const obj) const; + +private: + ItemReference(const ItemReference&); + ItemReference& operator=(const ItemReference&); +}; + +} // namespace LivePathEffect + +} // namespace Inkscape + + + +#endif /* !SEEN_LPE_PATH_REFERENCE_H */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/item.cpp b/src/live_effects/parameter/item.cpp new file mode 100644 index 000000000..8caea4e26 --- /dev/null +++ b/src/live_effects/parameter/item.cpp @@ -0,0 +1,246 @@ +/* + * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl> + * Abhishek Sharma + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "ui/widget/point.h" +#include <glibmm/i18n.h> + +#include "live_effects/parameter/item.h" +#include "live_effects/effect.h" +#include "svg/svg.h" + +#include "widgets/icon.h" +#include <gtk/gtk.h> +#include "selection-chemistry.h" +#include "xml/repr.h" +#include "desktop.h" +#include "inkscape.h" +#include "message-stack.h" + +// clipboard support +#include "ui/clipboard.h" +// required for linking to other paths +#include "uri.h" + +#include <gtkmm/button.h> +#include <gtkmm/label.h> +#include "ui/icon-names.h" + +namespace Inkscape { + +namespace LivePathEffect { + +ItemParam::ItemParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect, const gchar * default_value) + : Parameter(label, tip, key, wr, effect), + changed(true), + href(NULL), + ref( (SPObject*)effect->getLPEObj() ) +{ + defvalue = g_strdup(default_value); + ref_changed_connection = ref.changedSignal().connect(sigc::mem_fun(*this, &ItemParam::ref_changed)); +} + +ItemParam::~ItemParam() +{ + remove_link(); + g_free(defvalue); +} + +void +ItemParam::param_set_default() +{ + param_readSVGValue(defvalue); +} + + +void +ItemParam::param_set_and_write_default() +{ + param_write_to_repr(defvalue); +} + +bool +ItemParam::param_readSVGValue(const gchar * strvalue) +{ + if (strvalue) { + remove_link(); + if (strvalue[0] == '#') { + if (href) + g_free(href); + href = g_strdup(strvalue); + try { + ref.attach(Inkscape::URI(href)); + //lp:1299948 + SPItem* i = ref.getObject(); + if (i) { + linked_modified_callback(i, SP_OBJECT_MODIFIED_FLAG); + } // else: document still processing new events. Repr of the linked object not created yet. + } catch (Inkscape::BadURIException &e) { + g_warning("%s", e.what()); + ref.detach(); + } + } + emit_changed(); + return true; + } + + return false; +} + +gchar * +ItemParam::param_getSVGValue() const +{ + return g_strdup(href); +} + +Gtk::Widget * +ItemParam::param_newWidget() +{ + Gtk::HBox * _widget = Gtk::manage(new Gtk::HBox()); + Gtk::Widget* pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-clone"), Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button * pButton = Gtk::manage(new Gtk::Button()); + Gtk::Label* pLabel = Gtk::manage(new Gtk::Label(param_label)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pLabel, true, true); + pLabel->set_tooltip_text(param_tooltip); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &ItemParam::on_link_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Link to item on clipboard")); + + static_cast<Gtk::HBox*>(_widget)->show_all_children(); + + return dynamic_cast<Gtk::Widget *> (_widget); +} + +void +ItemParam::emit_changed() +{ + changed = true; + signal_item_changed.emit(); +} + + +void +ItemParam::addCanvasIndicators(SPLPEItem const*/*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) +{ +} + + +void +ItemParam::start_listening(SPObject * to) +{ + if ( to == NULL ) { + return; + } + linked_delete_connection = to->connectDelete(sigc::mem_fun(*this, &ItemParam::linked_delete)); + linked_modified_connection = to->connectModified(sigc::mem_fun(*this, &ItemParam::linked_modified)); + if (SP_IS_ITEM(to)) { + linked_transformed_connection = SP_ITEM(to)->connectTransformed(sigc::mem_fun(*this, &ItemParam::linked_transformed)); + } + linked_modified(to, SP_OBJECT_MODIFIED_FLAG); // simulate linked_modified signal, so that path data is updated +} + +void +ItemParam::quit_listening(void) +{ + linked_modified_connection.disconnect(); + linked_delete_connection.disconnect(); + linked_transformed_connection.disconnect(); +} + +void +ItemParam::ref_changed(SPObject */*old_ref*/, SPObject *new_ref) +{ + quit_listening(); + if ( new_ref ) { + start_listening(new_ref); + } +} + +void +ItemParam::remove_link() +{ + if (href) { + ref.detach(); + g_free(href); + href = NULL; + } +} + +void +ItemParam::linked_delete(SPObject */*deleted*/) +{ + quit_listening(); + remove_link(); +} + +void ItemParam::linked_modified(SPObject *linked_obj, guint flags) +{ + linked_modified_callback(linked_obj, flags); +} + +void ItemParam::linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item) +{ + linked_transformed_callback(rel_transf, moved_item); +} + +void +ItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) +{ + emit_changed(); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + +void +ItemParam::on_link_button_click() +{ + Inkscape::UI::ClipboardManager *cm = Inkscape::UI::ClipboardManager::get(); + const gchar * iid = cm->getFirstObjectID(); + if (!iid) { + return; + } + + Glib::ustring itemid(iid); + + if (itemid.empty()) { + return; + } + + // add '#' at start to make it an uri. + itemid.insert(itemid.begin(), '#'); + if ( href && strcmp(itemid.c_str(), href) == 0 ) { + // no change, do nothing + return; + } else { + // TODO: + // check if id really exists in document, or only in clipboard document: if only in clipboard then invalid + // check if linking to object to which LPE is applied (maybe delegated to PathReference + + param_write_to_repr(itemid.c_str()); + DocumentUndo::done(param_effect->getSPDoc(), SP_VERB_DIALOG_LIVE_PATH_EFFECT, + _("Link item parameter to path")); + } +} + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/item.h b/src/live_effects/parameter/item.h new file mode 100644 index 000000000..6c719d451 --- /dev/null +++ b/src/live_effects/parameter/item.h @@ -0,0 +1,79 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ITEM_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ITEM_H + +/* + * Inkscape::LivePathEffectParameters + * +* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include <glib.h> + + +#include "live_effects/parameter/parameter.h" +#include "live_effects/parameter/item-reference.h" +#include <stddef.h> +#include <sigc++/sigc++.h> + +namespace Inkscape { + +namespace LivePathEffect { + +class ItemParam : public Parameter { +public: + ItemParam ( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect, + const gchar * default_value = ""); + virtual ~ItemParam(); + virtual Gtk::Widget * param_newWidget(); + + virtual bool param_readSVGValue(const gchar * strvalue); + virtual gchar * param_getSVGValue() const; + + virtual void param_set_default(); + void param_set_and_write_default(); + virtual void addCanvasIndicators(SPLPEItem const* lpeitem, std::vector<Geom::PathVector> &hp_vec); + + sigc::signal <void> signal_item_pasted; + sigc::signal <void> signal_item_changed; + bool changed; /* this gets set whenever the path is changed (this is set to true, and then the signal_item_changed signal is emitted). + * the user must set it back to false if she wants to use it sensibly */ +protected: + + gchar * href; // contains link to other object, e.g. "#path2428", NULL if ItemParam contains pathdata itself + ItemReference ref; + sigc::connection ref_changed_connection; + sigc::connection linked_delete_connection; + sigc::connection linked_modified_connection; + sigc::connection linked_transformed_connection; + void ref_changed(SPObject *old_ref, SPObject *new_ref); + void remove_link(); + void start_listening(SPObject * to); + void quit_listening(void); + void linked_delete(SPObject *deleted); + void linked_modified(SPObject *linked_obj, guint flags); + void linked_transformed(Geom::Affine const *rel_transf, SPItem *moved_item); + virtual void linked_modified_callback(SPObject *linked_obj, guint flags); + virtual void linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/) {}; + void on_link_button_click(); + + void emit_changed(); + + gchar * defvalue; + +private: + ItemParam(const ItemParam&); + ItemParam& operator=(const ItemParam&); +}; + + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif diff --git a/src/live_effects/parameter/originalitem.cpp b/src/live_effects/parameter/originalitem.cpp new file mode 100644 index 000000000..015fa0bd4 --- /dev/null +++ b/src/live_effects/parameter/originalitem.cpp @@ -0,0 +1,127 @@ +/* + * Copyright (C) Johan Engelen 2012 <j.b.c.engelen@alumnus.utwente.nl> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <gtkmm/box.h> +#include "live_effects/parameter/originalitem.h" + +#include "widgets/icon.h" +#include <glibmm/i18n.h> +#include <gtkmm/button.h> +#include <gtkmm/label.h> + +#include "uri.h" +#include "sp-shape.h" +#include "sp-text.h" +#include "display/curve.h" +#include "live_effects/effect.h" + +#include "inkscape.h" +#include "desktop.h" +#include "selection.h" +#include "ui/icon-names.h" + +namespace Inkscape { + +namespace LivePathEffect { + +OriginalItemParam::OriginalItemParam( const Glib::ustring& label, const Glib::ustring& tip, + const Glib::ustring& key, Inkscape::UI::Widget::Registry* wr, + Effect* effect) + : ItemParam(label, tip, key, wr, effect, "") +{ +} + +OriginalItemParam::~OriginalItemParam() +{ + +} + +Gtk::Widget * +OriginalItemParam::param_newWidget() +{ + Gtk::HBox *_widget = Gtk::manage(new Gtk::HBox()); + + { // Label + Gtk::Label *pLabel = Gtk::manage(new Gtk::Label(param_label)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pLabel, true, true); + pLabel->set_tooltip_text(param_tooltip); + } + + { // Paste item to link button + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon( INKSCAPE_ICON("edit-paste"), Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemParam::on_link_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Link to item")); + } + + { // Select original button + Gtk::Widget *pIcon = Gtk::manage( sp_icon_get_icon("edit-select-original", Inkscape::ICON_SIZE_BUTTON) ); + Gtk::Button *pButton = Gtk::manage(new Gtk::Button()); + pButton->set_relief(Gtk::RELIEF_NONE); + pIcon->show(); + pButton->add(*pIcon); + pButton->show(); + pButton->signal_clicked().connect(sigc::mem_fun(*this, &OriginalItemParam::on_select_original_button_click)); + static_cast<Gtk::HBox*>(_widget)->pack_start(*pButton, true, true); + pButton->set_tooltip_text(_("Select original")); + } + + static_cast<Gtk::HBox*>(_widget)->show_all_children(); + + return dynamic_cast<Gtk::Widget *> (_widget); +} + +void +OriginalItemParam::linked_modified_callback(SPObject *linked_obj, guint /*flags*/) +{ + emit_changed(); + SP_OBJECT(param_effect->getLPEObj())->requestModified(SP_OBJECT_MODIFIED_FLAG); +} + +void +OriginalItemParam::linked_transformed_callback(Geom::Affine const * /*rel_transf*/, SPItem * /*moved_item*/) +{ +/** \todo find good way to compensate for referenced item transform, like done for normal clones. + * See sp-use.cpp: sp_use_move_compensate */ +} + + +void +OriginalItemParam::on_select_original_button_click() +{ + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + SPItem *original = ref.getObject(); + if (desktop == NULL || original == NULL) { + return; + } + Inkscape::Selection *selection = desktop->getSelection(); + selection->clear(); + selection->set(original); +} + +} /* namespace LivePathEffect */ + +} /* namespace Inkscape */ + +/* + Local Variables: + mode:c++ + c-file-style:"stroustrup" + c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +)) + indent-tabs-mode:nil + fill-column:99 + End: +*/ +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 : diff --git a/src/live_effects/parameter/originalitem.h b/src/live_effects/parameter/originalitem.h new file mode 100644 index 000000000..9c67571e8 --- /dev/null +++ b/src/live_effects/parameter/originalitem.h @@ -0,0 +1,48 @@ +#ifndef INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINAL_ITEM_H +#define INKSCAPE_LIVEPATHEFFECT_PARAMETER_ORIGINAL_ITEM_H + +/* + * Inkscape::LiveItemEffectParameters + * +* Copyright (C) Johan Engelen 2012 <j.b.c.engelen@alumnus.utwente.nl> + * + * Released under GNU GPL, read the file 'COPYING' for more information + */ + +#include "live_effects/parameter/item.h" + +namespace Inkscape { + +namespace LivePathEffect { + +class OriginalItemParam: public ItemParam { +public: + OriginalItemParam ( const Glib::ustring& label, + const Glib::ustring& tip, + const Glib::ustring& key, + Inkscape::UI::Widget::Registry* wr, + Effect* effect); + virtual ~OriginalItemParam(); + + bool linksToItem() const { return (href != NULL); } + SPItem * getObject() const { return ref.getObject(); } + + virtual Gtk::Widget * param_newWidget(); + +protected: + virtual void linked_modified_callback(SPObject *linked_obj, guint flags); + virtual void linked_transformed_callback(Geom::Affine const *rel_transf, SPItem *moved_item); + + void on_select_original_button_click(); + +private: + OriginalItemParam(const OriginalItemParam&); + OriginalItemParam& operator=(const OriginalItemParam&); +}; + + +} //namespace LivePathEffect + +} //namespace Inkscape + +#endif 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 98428512f..fb640c50c 100644 --- a/src/sp-lpe-item.cpp +++ b/src/sp-lpe-item.cpp @@ -212,7 +212,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,12 +244,14 @@ bool SPLPEItem::performPathEffect(SPCurve *curve, bool is_clip_or_mask) { } 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); + lpe->doEffect(curve); } catch (std::exception & e) { g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what()); @@ -700,10 +702,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, SP_SHAPE(clip_mask), true); } } catch (std::exception & e) { g_warning("Exception during LPE execution. \n %s", e.what()); @@ -714,12 +716,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); @@ -729,7 +732,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 db4a0c7a3..0f198c49c 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 c2122e109..222626162 100644 --- a/src/sp-object.cpp +++ b/src/sp-object.cpp @@ -782,6 +782,7 @@ SPObject* SPObject::nthChild(unsigned index) { if (counter == index) { return &child; } + counter++; } } return NULL; diff --git a/src/sp-path.cpp b/src/sp-path.cpp index b593b7937..6c69f3463 100644 --- a/src/sp-path.cpp +++ b/src/sp-path.cpp @@ -289,10 +289,23 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) { if (!_curve) { // 0 nodes, nothing to transform return Geom::identity(); } + // Adjust stroke + this->adjust_stroke(transform.descrim()); + + // Adjust pattern fill + this->adjust_pattern(transform); + + // Adjust gradient fill + this->adjust_gradient(transform); + + // Adjust LPE + this->adjust_livepatheffect(transform); // Transform the original-d path if this is a valid LPE this, other else the (ordinary) path if (_curve_before_lpe && hasPathEffectRecursive()) { - if (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH)) { + if (this->hasPathEffectOfType(Inkscape::LivePathEffect::CLONE_ORIGINAL) || + this->hasPathEffectOfType(Inkscape::LivePathEffect::BEND_PATH)) + { // if path has the CLONE_ORIGINAL LPE applied, don't write the transform to the pathdata, but write it 'unoptimized' // also if the effect is type BEND PATH to fix bug #179842 return transform; @@ -303,18 +316,6 @@ Geom::Affine SPPath::set_transform(Geom::Affine const &transform) { _curve->transform(transform); } - // Adjust stroke - this->adjust_stroke(transform.descrim()); - - // Adjust pattern fill - this->adjust_pattern(transform); - - // Adjust gradient fill - this->adjust_gradient(transform); - - // Adjust LPE - this->adjust_livepatheffect(transform); - this->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_STYLE_MODIFIED_FLAG); // nothing remains - we've written all of the transform, so return identity @@ -354,9 +355,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(); |
