summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorJabiertxof <jtx@jtx>2016-12-03 22:49:17 +0000
committerJabiertxof <jtx@jtx>2016-12-03 22:49:17 +0000
commit4d33b96eb8c47f5aef22f795dd199ba04b734784 (patch)
tree2f131732027685db6a7e71fe612832a5d1ff6144 /src
parentFix a typo (diff)
downloadinkscape-4d33b96eb8c47f5aef22f795dd199ba04b734784.tar.gz
inkscape-4d33b96eb8c47f5aef22f795dd199ba04b734784.zip
Start coding
(bzr r15295.1.1)
Diffstat (limited to 'src')
-rw-r--r--src/live_effects/lpe-mirror_symmetry.cpp201
-rw-r--r--src/live_effects/lpe-mirror_symmetry.h14
2 files changed, 200 insertions, 15 deletions
diff --git a/src/live_effects/lpe-mirror_symmetry.cpp b/src/live_effects/lpe-mirror_symmetry.cpp
index 4deb29d8f..e62dbbca9 100644
--- a/src/live_effects/lpe-mirror_symmetry.cpp
+++ b/src/live_effects/lpe-mirror_symmetry.cpp
@@ -14,12 +14,18 @@
* Released under GNU GPL, read the file 'COPYING' for more information
*/
#include "live_effects/lpe-mirror_symmetry.h"
-#include <display/curve.h>
-#include <svg/path-string.h>
+#include "display/curve.h"
+#include "svg/path-string.h"
+#include "svg/svg.h"
+#include "sp-defs.h"
#include "helper/geom.h"
-#include <2geom/path-intersection.h>
+#include "2geom/path-intersection.h"
+#include "2geom/affine.h"
+#include "uri.h"
+#include "uri-references.h"
#include "knotholder.h"
// TODO due to internal breakage in glibmm headers, this must be last:
+#include <glibmm/i18n.h>
namespace Inkscape {
namespace LivePathEffect {
@@ -34,6 +40,9 @@ static const Util::EnumData<ModeType> ModeTypeData[MT_END] = {
static const Util::EnumDataConverter<ModeType>
MTConverter(ModeTypeData, MT_END);
+std::vector<Glib::ustring> ms_elements;
+SPObject * ms_container;
+
namespace MS {
class KnotHolderEntityCenterMirrorSymmetry : public LPEKnotHolderEntity {
@@ -65,6 +74,9 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) :
discard_orig_path(_("Discard original path?"), _("Check this to only keep the mirrored part of the path"), "discard_orig_path", &wr, this, false),
fuse_paths(_("Fuse paths"), _("Fuse original and the reflection into a single path"), "fuse_paths", &wr, this, false),
oposite_fuse(_("Opposite fuse"), _("Picks the other side of the mirror as the original"), "oposite_fuse", &wr, this, false),
+ split(_("Split elements"), _("Split elements, this allow gradients and other paints"), "split", &wr, this, false),
+ split_sensitive(_("Make split selectable"), _("Allow select splited elements"), "split", &wr, this, false),
+ split_style(_("Make splits with style"), _("Allow Change colors to split"), "split", &wr, this, false),
start_point(_("Start mirror line"), _("Start mirror line"), "start_point", &wr, this, "Adjust the start of mirroring"),
end_point(_("End mirror line"), _("End mirror line"), "end_point", &wr, this, "Adjust end of mirroring")
{
@@ -73,6 +85,9 @@ LPEMirrorSymmetry::LPEMirrorSymmetry(LivePathEffectObject *lpeobject) :
registerParameter( &discard_orig_path);
registerParameter( &fuse_paths);
registerParameter( &oposite_fuse);
+ registerParameter( &split);
+ registerParameter( &split_sensitive);
+ registerParameter( &split_style);
registerParameter( &start_point);
registerParameter( &end_point);
apply_to_clippath_and_mask = true;
@@ -142,8 +157,155 @@ LPEMirrorSymmetry::doBeforeEffect (SPLPEItem const* lpeitem)
}
}
previous_center = center_point;
+ if (split) {
+ SPLPEItem * splpeitem = const_cast<SPLPEItem *>(lpeitem);
+ ms_container = dynamic_cast<SPObject *>(splpeitem->parent);
+ SPDocument * doc = SP_ACTIVE_DOCUMENT;
+ Inkscape::XML::Node *root = splpeitem->document->getReprRoot();
+ Inkscape::XML::Node *root_origin = doc->getReprRoot();
+ if (root_origin != root) {
+ return;
+ }
+ Geom::Point point_a(line_separation.initialPoint());
+ Geom::Point point_b(line_separation.finalPoint());
+
+ Geom::Translate m1(point_a[0], point_a[1]);
+ double hyp = Geom::distance(point_a, point_b);
+ double cos = 0;
+ double sin = 0;
+ if (hyp > 0) {
+ cos = (point_b[0] - point_a[0]) / hyp;
+ sin = (point_b[1] - point_a[1]) / hyp;
+ }
+ Geom::Affine m2(cos, -sin, sin, cos, 0.0, 0.0);
+ Geom::Scale sca(1.0, -1.0);
+
+ Geom::Affine m = m1.inverse() * m2;
+ m = m * sca;
+ m = m * m2.inverse();
+ m = m * m1;
+ createPhantom(splpeitem , (Glib::ustring) "origin-clon-", split_style);
+ createClone(splpeitem , m, (Glib::ustring) "clon-");
+ }
+}
+
+void
+LPEMirrorSymmetry::createPhantom(SPLPEItem *origin, Glib::ustring id, bool styling)
+{
+ if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) {
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ id = id + (Glib::ustring)this->getRepr()->attribute("id");
+ Inkscape::URI SVGElem_uri(((Glib::ustring)"#" + id).c_str());
+ Inkscape::URIReference* SVGElemRef = new Inkscape::URIReference(desktop->doc());
+ SVGElemRef->attach(SVGElem_uri);
+ SPObject *elemref = NULL;
+ Inkscape::XML::Node *phantom = origin->getRepr()->duplicate(xml_doc);
+ if (elemref = SVGElemRef->getObject()) {
+ elemref->deleteObject();
+ }
+ if (styling) {
+ SPCSSAttr *css = sp_repr_css_attr_new();
+ sp_repr_css_set_property (css, "fill", NULL);
+ sp_repr_css_set_property (css, "stroke",NULL);
+ Glib::ustring css_str;
+ sp_repr_css_write_string(css,css_str);
+ sp_repr_css_change_recursive (phantom, css, css_str.c_str());
+ }
+ phantom->setAttribute("id", id);
+ phantom->setAttribute("inkscape:path-effect", NULL);
+ SP_OBJECT(desktop->getDocument()->getDefs()->appendChildRepr(phantom));
+ Inkscape::GC::release(phantom);
+ ms_elements.push_back(id);
+ }
+}
+
+void
+LPEMirrorSymmetry::createClone(SPLPEItem *origin, Geom::Affine transform, Glib::ustring id)
+{
+ if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) {
+ Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
+ id = id + (Glib::ustring)this->getRepr()->attribute("id");
+ Inkscape::URI SVGElem_uri(((Glib::ustring)"#" + id).c_str());
+ Inkscape::URIReference* SVGElemRef = new Inkscape::URIReference(desktop->doc());
+ SVGElemRef->attach(SVGElem_uri);
+ SPObject *elemref = NULL;
+ Inkscape::XML::Node *use = NULL;
+ use = xml_doc->createElement("svg:use");
+ use->setAttribute("transform" , sp_svg_transform_write(transform));
+ use->setAttribute("xlink:href", ((Glib::ustring)"#origin-" + id).c_str());
+ use->setAttribute("width", "100%");
+ use->setAttribute("height", "100%");
+ use->setAttribute("id", id);
+ use->setAttribute("x", "0");
+ use->setAttribute("y", "0");
+ if (split_sensitive) {
+ use->setAttribute("sodipodi:insensitive" , "false");
+ } else {
+ use->setAttribute("sodipodi:insensitive" , "true");
+ }
+ if (elemref) {
+ elemref->deleteObject();
+ }
+ elemref = ms_container->appendChildRepr(use);
+ Inkscape::GC::release(use);
+ ms_elements.push_back(id);
+ }
+}
+
+
+void
+LPEMirrorSymmetry::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/)
+{
+ processObjects(LPE_VISIBILITY);
+}
+
+void
+LPEMirrorSymmetry::doOnRemove (SPLPEItem const* /*lpeitem*/)
+{
+ if (!erase_extra_objects) {
+ processObjects(LPE_TO_OBJECTS);
+ ms_elements.clear();
+ return;
+ }
+ processObjects(LPE_ERASE);
}
+void
+LPEMirrorSymmetry::processObjects(LpeAction lpe_action)
+{
+ if (SPDesktop *desktop = SP_ACTIVE_DESKTOP) {
+ for (std::vector<Glib::ustring>::iterator el_it = ms_elements.begin();
+ el_it != ms_elements.end();++el_it) {
+ Glib::ustring id = *el_it;
+ Inkscape::URI SVGElem_uri(((Glib::ustring)"#" + id).c_str());
+ Inkscape::URIReference* SVGElemRef = new Inkscape::URIReference(desktop->doc());
+ SVGElemRef->attach(SVGElem_uri);
+ SPObject *elemref = NULL;
+ if (elemref = SVGElemRef->getObject()) {
+ switch (lpe_action){
+ case LPE_TO_OBJECTS:
+ elemref->getRepr()->setAttribute("sodipodi:insensitive", NULL);
+ break;
+ case LPE_ERASE:
+ elemref->deleteObject();
+ break;
+ default: //LPE_VISIBILITY
+ if (!this->isVisible()) {
+ elemref->getRepr()->setAttribute("style", "display:none");
+ } else {
+ elemref->getRepr()->setAttribute("style", NULL);
+ }
+ break;
+ }
+ }
+ }
+ if (lpe_action == LPE_ERASE) {
+ ms_elements.clear();
+ }
+ }
+}
+
+
void
LPEMirrorSymmetry::transform_multiply(Geom::Affine const& postmul, bool set)
{
@@ -178,6 +340,9 @@ LPEMirrorSymmetry::doOnApply (SPLPEItem const* lpeitem)
Geom::PathVector
LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
{
+ if (split && !fuse_paths) {
+ return path_in;
+ }
Geom::PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_in);
Geom::PathVector path_out;
@@ -204,7 +369,7 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
m = m * m2.inverse();
m = m * m1;
- if (fuse_paths && !discard_orig_path) {
+ if (fuse_paths && (!discard_orig_path || split )) {
for (Geom::PathVector::const_iterator path_it = original_pathv.begin();
path_it != original_pathv.end(); ++path_it)
{
@@ -255,11 +420,15 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
}
if (position == 1) {
Geom::Path mirror = portion.reversed() * m;
- mirror.setInitial(portion.finalPoint());
- portion.append(mirror);
- if(i!=0) {
- portion.setFinal(portion.initialPoint());
+ if (split) {
portion.close();
+ } else {
+ mirror.setInitial(portion.finalPoint());
+ portion.append(mirror);
+ if(i!=0) {
+ portion.setFinal(portion.initialPoint());
+ portion.close();
+ }
}
tmp_path.push_back(portion);
}
@@ -277,10 +446,14 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
Geom::Path portion = original.portion(time_start, original.size());
if (!portion.empty()) {
portion = portion.reversed();
- Geom::Path mirror = portion.reversed() * m;
- mirror.setInitial(portion.finalPoint());
- portion.append(mirror);
- portion = portion.reversed();
+ if (split) {
+
+ } else {
+ Geom::Path mirror = portion.reversed() * m;
+ mirror.setInitial(portion.finalPoint());
+ portion.append(mirror);
+ portion = portion.reversed();
+ }
if (!original.closed()) {
tmp_path.push_back(portion);
} else {
@@ -304,9 +477,7 @@ LPEMirrorSymmetry::doEffect_path (Geom::PathVector const & path_in)
path_out.insert(path_out.end(), tmp_path.begin(), tmp_path.end());
tmp_path.clear();
}
- }
-
- if (!fuse_paths || discard_orig_path) {
+ } else if (!fuse_paths || discard_orig_path) {
for (size_t i = 0; i < original_pathv.size(); ++i) {
path_out.push_back(original_pathv[i] * m);
}
diff --git a/src/live_effects/lpe-mirror_symmetry.h b/src/live_effects/lpe-mirror_symmetry.h
index 7ec4029e0..70c82e330 100644
--- a/src/live_effects/lpe-mirror_symmetry.h
+++ b/src/live_effects/lpe-mirror_symmetry.h
@@ -31,6 +31,12 @@ namespace MS {
class KnotHolderEntityCenterMirrorSymmetry;
}
+enum LpeAction {
+ LPE_ERASE = 0,
+ LPE_TO_OBJECTS,
+ LPE_VISIBILITY
+};
+
enum ModeType {
MT_V,
MT_H,
@@ -48,8 +54,13 @@ public:
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
virtual void transform_multiply(Geom::Affine const& postmul, bool set);
virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
+ virtual void doOnRemove (SPLPEItem const* /*lpeitem*/);
+ virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/);
+ void processObjects(LpeAction lpe_action);
/* the knotholder entity classes must be declared friends */
friend class MS::KnotHolderEntityCenterMirrorSymmetry;
+ void createPhantom(SPLPEItem *origin, Glib::ustring id, bool styling);
+ void createClone(SPLPEItem *origin, Geom::Affine transform, Glib::ustring id);
void addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item);
protected:
@@ -60,6 +71,9 @@ private:
BoolParam discard_orig_path;
BoolParam fuse_paths;
BoolParam oposite_fuse;
+ BoolParam split;
+ BoolParam split_sensitive;
+ BoolParam split_style;
PointParam start_point;
PointParam end_point;
Geom::Line line_separation;