summaryrefslogtreecommitdiffstats
path: root/src/live_effects
diff options
context:
space:
mode:
authorJabier Arraiza Cenoz <jabier.arraiza@marker.es>2017-01-24 08:41:37 +0000
committerjabiertxof <info@marker.es>2017-01-24 08:41:37 +0000
commit2db253e38b7ac8f00ca607ff1d69e15b61301389 (patch)
tree3177b769003d4fba36f20364720ab7cd8e3a4db3 /src/live_effects
parentfix nodes reverting back during editing (diff)
parentBug fixes (diff)
downloadinkscape-2db253e38b7ac8f00ca607ff1d69e15b61301389.tar.gz
inkscape-2db253e38b7ac8f00ca607ff1d69e15b61301389.zip
merge lp:~inkscape.dev/inkscape/rotatecopies_improvements
(bzr r15436)
Diffstat (limited to 'src/live_effects')
-rw-r--r--src/live_effects/effect.cpp88
-rw-r--r--src/live_effects/effect.h20
-rw-r--r--src/live_effects/lpe-copy_rotate.cpp306
-rw-r--r--src/live_effects/lpe-copy_rotate.h14
-rw-r--r--src/live_effects/lpe-measure-line.cpp66
-rw-r--r--src/live_effects/lpe-measure-line.h8
-rw-r--r--src/live_effects/parameter/bool.cpp3
-rw-r--r--src/live_effects/parameter/text.cpp3
8 files changed, 418 insertions, 90 deletions
diff --git a/src/live_effects/effect.cpp b/src/live_effects/effect.cpp
index 5cc0d6f20..a0ab0d41c 100644
--- a/src/live_effects/effect.cpp
+++ b/src/live_effects/effect.cpp
@@ -70,6 +70,8 @@
#include "ui/tools/node-tool.h"
#include "ui/tools-switch.h"
#include "knotholder.h"
+#include "path-chemistry.h"
+#include "xml/sp-css-attr.h"
#include "live_effects/lpeobject.h"
#include "display/curve.h"
@@ -356,6 +358,7 @@ Effect::Effect(LivePathEffectObject *lpeobject)
sp_lpe_item(NULL),
current_zoom(1),
upd_params(true),
+ sp_shape(NULL),
sp_curve(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,15 +395,15 @@ Effect::doOnApply (SPLPEItem const*/*lpeitem*/)
}
void
-Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP)
+Effect::setCurrentZoom(double cZ)
{
- selectedNodesPoints = sNP;
+ current_zoom = cZ;
}
void
-Effect::setCurrentZoom(double cZ)
+Effect::setSelectedNodePoints(std::vector<Geom::Point> sNP)
{
- current_zoom = cZ;
+ selectedNodesPoints = sNP;
}
bool
@@ -423,6 +426,74 @@ Effect::isNodePointSelected(Geom::Point const &nodePoint) const
return false;
}
+void
+Effect::processObjects(LpeAction lpe_action)
+{
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ for (std::vector<const char *>::iterator el_it = items.begin();
+ el_it != items.end(); ++el_it) {
+ const char * id = *el_it;
+ if (!id || strlen(id) == 0) {
+ return;
+ }
+ SPObject *elemref = NULL;
+ if (elemref = document->getObjectById(id)) {
+ Inkscape::XML::Node * elemnode = elemref->getRepr();
+ std::vector<SPItem*> item_list;
+ item_list.push_back(SP_ITEM(elemref));
+ std::vector<Inkscape::XML::Node*> item_to_select;
+ std::vector<SPItem*> item_selected;
+ SPCSSAttr *css;
+ Glib::ustring css_str;
+ switch (lpe_action){
+ case LPE_TO_OBJECTS:
+ if (SP_ITEM(elemref)->isHidden()) {
+ elemref->deleteObject();
+ } else {
+ if (elemnode->attribute("inkscape:path-effect")) {
+ sp_item_list_to_curves(item_list, item_selected, item_to_select);
+ }
+ elemnode->setAttribute("sodipodi:insensitive", NULL);
+ }
+ break;
+
+ case LPE_ERASE:
+ elemref->deleteObject();
+ break;
+
+ case LPE_VISIBILITY:
+ css = sp_repr_css_attr_new();
+ sp_repr_css_attr_add_from_string(css, elemref->getRepr()->attribute("style"));
+ if (!this->isVisible()/* && std::strcmp(elemref->getId(),sp_lpe_item->getId()) != 0*/) {
+ css->setAttribute("display", "none");
+ } else {
+ css->setAttribute("display", NULL);
+ }
+ sp_repr_css_write_string(css,css_str);
+ elemnode->setAttribute("style", css_str.c_str());
+ break;
+
+ default:
+ break;
+ }
+ }
+ }
+ if (lpe_action == LPE_ERASE || lpe_action == LPE_TO_OBJECTS) {
+ items.clear();
+ }
+}
+
+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();
+ }
+}
+
/**
* Is performed each time before the effect is updated.
*/
@@ -446,8 +517,12 @@ 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();*/
+ 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);
}
@@ -457,6 +532,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){
+ setCurrentShape(shape);
sp_curve = shape->getCurve();
pathvector_before_effect = sp_curve->get_pathvector();
}
diff --git a/src/live_effects/effect.h b/src/live_effects/effect.h
index 1997ff0ca..f5e41d50e 100644
--- a/src/live_effects/effect.h
+++ b/src/live_effects/effect.h
@@ -19,7 +19,7 @@
class SPDocument;
class SPDesktop;
class SPItem;
-class LivePathEffectObject;
+class LivePathEffectObject;
class SPLPEItem;
class KnotHolder;
class KnotHolderEntity;
@@ -44,6 +44,12 @@ enum LPEPathFlashType {
DEFAULT
};
+enum LpeAction {
+ LPE_ERASE = 0,
+ LPE_TO_OBJECTS,
+ LPE_VISIBILITY
+};
+
class Effect {
public:
static Effect* New(EffectType lpenr, LivePathEffectObject *lpeobj);
@@ -73,6 +79,9 @@ 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);
+ void processObjects(LpeAction lpe_action);
/*
* isReady() indicates whether all preparations which are necessary to apply the LPE are done,
@@ -125,7 +134,9 @@ public:
bool apply_to_clippath_and_mask;
bool erase_extra_objects; // set this to false allow retain extra generated objects, see measure line LPE
bool upd_params;
-
+ BoolParam is_visible;
+ SPCurve * sp_curve;
+ Geom::PathVector pathvector_before_effect;
protected:
Effect(LivePathEffectObject *lpeobject);
@@ -150,7 +161,6 @@ protected:
bool _provides_knotholder_entities;
int oncanvasedit_it;
- BoolParam is_visible;
bool show_orig_path; // set this to true in derived effects to automatically have the original
// path displayed as helperpath
@@ -164,10 +174,10 @@ protected:
bool concatenate_before_pwd2;
SPLPEItem * sp_lpe_item; // these get stored in doBeforeEffect_impl, and derived classes may do as they please with them.
+ 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.
+ std::vector<const char *> items;
double current_zoom;
std::vector<Geom::Point> selectedNodesPoints;
- SPCurve * sp_curve;
- Geom::PathVector pathvector_before_effect;
private:
bool provides_own_flash_paths; // if true, the standard flash path is suppressed
diff --git a/src/live_effects/lpe-copy_rotate.cpp b/src/live_effects/lpe-copy_rotate.cpp
index 813f25d3d..fbc7933e7 100644
--- a/src/live_effects/lpe-copy_rotate.cpp
+++ b/src/live_effects/lpe-copy_rotate.cpp
@@ -17,6 +17,13 @@
#include <2geom/sbasis-to-bezier.h>
#include <2geom/intersection-graph.h>
#include "live_effects/lpe-copy_rotate.h"
+#include "display/curve.h"
+#include "svg/path-string.h"
+#include "svg/svg.h"
+#include "style.h"
+#include "helper/geom.h"
+#include "xml/sp-css-attr.h"
+#include "path-chemistry.h"
// TODO due to internal breakage in glibmm headers, this must be last:
#include <glibmm/i18n.h>
@@ -45,9 +52,11 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
starting_angle(_("Starting angle"), _("Angle of the first copy"), "starting_angle", &wr, this, 0.0),
rotation_angle(_("Rotation angle"), _("Angle between two successive copies"), "rotation_angle", &wr, this, 60.0),
num_copies(_("Number of copies"), _("Number of copies of the original path"), "num_copies", &wr, this, 6),
+ split_gap(_("Gap on split"), _("Gap on split"), "split_gap", &wr, this, -0.001),
copies_to_360(_("360º Copies"), _("No rotation angle, fixed to 360º"), "copies_to_360", &wr, this, true),
fuse_paths(_("Kaleidoskope"), _("Kaleidoskope by helper line, use fill-rule: evenodd for best result"), "fuse_paths", &wr, this, false),
join_paths(_("Join paths"), _("Join paths, use fill-rule: evenodd for best result"), "join_paths", &wr, this, false),
+ split_items(_("Split elements"), _("Split elements, this allow gradients and other paints."), "split_items", &wr, this, false),
dist_angle_handle(100.0)
{
show_orig_path = true;
@@ -56,15 +65,21 @@ LPECopyRotate::LPECopyRotate(LivePathEffectObject *lpeobject) :
registerParameter(&copies_to_360);
registerParameter(&fuse_paths);
registerParameter(&join_paths);
+ registerParameter(&split_items);
registerParameter(&starting_angle);
registerParameter(&starting_point);
registerParameter(&rotation_angle);
registerParameter(&num_copies);
+ registerParameter(&split_gap);
registerParameter(&origin);
-
+ split_gap.param_set_range(-999999.0, 999999.0);
+ split_gap.param_set_increments(0.1, 0.1);
+ split_gap.param_set_digits(5);
+ num_copies.param_set_range(0, 999999);
num_copies.param_make_integer(true);
- num_copies.param_set_range(0, 1000);
apply_to_clippath_and_mask = true;
+ previous_num_copies = num_copies;
+ reset = false;
}
LPECopyRotate::~LPECopyRotate()
@@ -72,6 +87,207 @@ LPECopyRotate::~LPECopyRotate()
}
+void
+LPECopyRotate::doAfterEffect (SPLPEItem const* lpeitem)
+{
+ if (split_items) {
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ items.clear();
+ container = dynamic_cast<SPObject *>(sp_lpe_item->parent);
+ SPDocument * doc = SP_ACTIVE_DOCUMENT;
+ Inkscape::XML::Node *root = sp_lpe_item->document->getReprRoot();
+ Inkscape::XML::Node *root_origin = doc->getReprRoot();
+ if (root_origin != root) {
+ return;
+ }
+ if (previous_num_copies != num_copies) {
+ gint numcopies_gap = previous_num_copies - num_copies;
+ if (numcopies_gap > 0 && num_copies != 0) {
+ guint counter = num_copies - 1;
+ while (numcopies_gap > 0) {
+ const char * id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str());
+ if (!id || strlen(id) == 0) {
+ return;
+ }
+ SPObject *elemref = NULL;
+ if (elemref = document->getObjectById(id)) {
+ SP_ITEM(elemref)->setHidden(true);
+ }
+ counter++;
+ numcopies_gap--;
+ }
+ }
+ previous_num_copies = num_copies;
+ }
+ SPObject *elemref = NULL;
+ char * id = g_strdup(Glib::ustring("rotated-").append("1").append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str());
+ guint counter = 0;
+ while(elemref = document->getObjectById(id)) {
+ if (SP_ITEM(elemref)->isHidden()) {
+ items.push_back(id);
+ }
+ id = g_strdup(Glib::ustring("rotated-").append(std::to_string(counter)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str());
+ counter++;
+ }
+ g_free(id);
+ double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ Geom::Rect bbox(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ double size_divider = Geom::distance(origin,bbox) + (diagonal * 2);
+ Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider;
+ Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider;
+ Geom::Affine m = Geom::Translate(-origin) * Geom::Rotate(-(Geom::rad_from_deg(starting_angle)));
+ if (fuse_paths) {
+ size_t rest = 0;
+ for (size_t i = 1; i < num_copies; ++i) {
+ Geom::Affine r = Geom::identity();
+ Geom::Point dir = unit_vector((Geom::Point)origin - Geom::middle_point(line_start,line_end));
+ if( rest%2 == 0) {
+ r *= Geom::Rotate(Geom::Angle(dir)).inverse();
+ r *= Geom::Scale(1, -1);
+ r *= Geom::Rotate(Geom::Angle(dir));
+ }
+ Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i)));
+ Geom::Affine t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
+ if( rest%2 == 0) {
+ t = m * r * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)).inverse() * Geom::Translate(origin);
+ }
+ t *= sp_lpe_item->transform;
+ toItem(t, i-1, reset);
+ rest ++;
+ }
+ } else {
+ for (size_t i = 1; i < num_copies; ++i) {
+ Geom::Rotate rot(-(Geom::rad_from_deg(rotation_angle * i)));
+ Geom::Affine t = m * rot * Geom::Rotate(Geom::rad_from_deg(starting_angle)) * Geom::Translate(origin);
+ t *= sp_lpe_item->transform;
+ toItem(t, i - 1, reset);
+ }
+ }
+ reset = false;
+ } else {
+ processObjects(LPE_ERASE);
+ items.clear();
+ }
+
+ std::cout << previous_num_copies << "previous_num_copies\n";
+ std::cout << num_copies << "num_copies\n";
+}
+
+void
+LPECopyRotate::cloneD(SPObject *origin, SPObject *dest, bool root, bool reset)
+{
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ Inkscape::XML::Document *xml_doc = document->getReprDoc();
+ 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);
+ cloneD(*obj_it, dest_child, false, reset);
+ index++;
+ }
+ }
+ SPShape * shape = SP_SHAPE(origin);
+ SPPath * path = SP_PATH(dest);
+ if (!path && !SP_IS_GROUP(dest)) {
+ Inkscape::XML::Node *dest_node = sp_selected_item_to_curved_repr(SP_ITEM(dest), 0);
+ dest->updateRepr(xml_doc, dest_node, SP_OBJECT_WRITE_ALL);
+ path = SP_PATH(dest);
+ }
+ if (path && shape) {
+ SPCurve *c = NULL;
+ if (root) {
+ c = new SPCurve();
+ c->set_pathvector(pathvector_before_effect);
+ } else {
+ c = shape->getCurve();
+ }
+ if (c) {
+ path->setCurve(c, TRUE);
+ c->unref();
+ } else {
+ dest->getRepr()->setAttribute("d", NULL);
+ }
+ if (reset) {
+ dest->getRepr()->setAttribute("style", shape->getRepr()->attribute("style"));
+ }
+ }
+}
+
+void
+LPECopyRotate::toItem(Geom::Affine transform, size_t i, bool reset)
+{
+ SPDocument * document = SP_ACTIVE_DOCUMENT;
+ Inkscape::XML::Document *xml_doc = document->getReprDoc();
+ const char * elemref_id = g_strdup(Glib::ustring("rotated-").append(std::to_string(i)).append("-").append(sp_lpe_item->getRepr()->attribute("id")).c_str());
+ items.push_back(elemref_id);
+ SPObject *elemref= NULL;
+ Inkscape::XML::Node *phantom = NULL;
+ if (elemref = document->getObjectById(elemref_id)) {
+ phantom = elemref->getRepr();
+ } else {
+ phantom = sp_lpe_item->getRepr()->duplicate(xml_doc);
+ std::vector<const char *> attrs;
+ attrs.push_back("inkscape:path-effect");
+ attrs.push_back("inkscape:original-d");
+ attrs.push_back("sodipodi:type");
+ attrs.push_back("sodipodi:rx");
+ attrs.push_back("sodipodi:ry");
+ attrs.push_back("sodipodi:cx");
+ attrs.push_back("sodipodi:cy");
+ attrs.push_back("sodipodi:end");
+ attrs.push_back("sodipodi:start");
+ attrs.push_back("inkscape:flatsided");
+ attrs.push_back("inkscape:randomized");
+ attrs.push_back("inkscape:rounded");
+ attrs.push_back("sodipodi:arg1");
+ attrs.push_back("sodipodi:arg2");
+ attrs.push_back("sodipodi:r1");
+ attrs.push_back("sodipodi:r2");
+ attrs.push_back("sodipodi:sides");
+ attrs.push_back("inkscape:randomized");
+ attrs.push_back("sodipodi:argument");
+ attrs.push_back("sodipodi:expansion");
+ attrs.push_back("sodipodi:radius");
+ attrs.push_back("sodipodi:revolution");
+ attrs.push_back("sodipodi:t0");
+ attrs.push_back("inkscape:randomized");
+ attrs.push_back("inkscape:randomized");
+ attrs.push_back("inkscape:randomized");
+ attrs.push_back("x");
+ attrs.push_back("y");
+ attrs.push_back("rx");
+ attrs.push_back("ry");
+ attrs.push_back("width");
+ attrs.push_back("height");
+ phantom->setAttribute("id", elemref_id);
+ for(const char * attr : attrs) {
+ phantom->setAttribute(attr, NULL);
+ }
+ }
+ if (!elemref) {
+ elemref = container->appendChildRepr(phantom);
+ Inkscape::GC::release(phantom);
+ }
+ cloneD(SP_OBJECT(sp_lpe_item), elemref, true, reset);
+ elemref->getRepr()->setAttribute("transform" , sp_svg_transform_write(transform));
+ SP_ITEM(elemref)->setHidden(false);
+ if (elemref->parent != container) {
+ Inkscape::XML::Node *copy = phantom->duplicate(xml_doc);
+ copy->setAttribute("id", elemref_id);
+ container->appendChildRepr(copy);
+ Inkscape::GC::release(copy);
+ elemref->deleteObject();
+ }
+}
+
+void
+LPECopyRotate::resetStyles(){
+ reset = true;
+ doAfterEffect(sp_lpe_item);
+}
+
Gtk::Widget * LPECopyRotate::newWidget()
{
// use manage here, because after deletion of Effect object, others might
@@ -81,7 +297,15 @@ Gtk::Widget * LPECopyRotate::newWidget()
vbox->set_border_width(5);
vbox->set_homogeneous(false);
vbox->set_spacing(2);
-
+ Gtk::HBox * hbox = Gtk::manage(new Gtk::HBox(false,0));
+ Gtk::VBox * vbox_expander = Gtk::manage( new Gtk::VBox(Effect::newWidget()) );
+ vbox_expander->set_border_width(0);
+ vbox_expander->set_spacing(2);
+ Gtk::Button * reset_button = Gtk::manage(new Gtk::Button(Glib::ustring(_("Reset styles"))));
+ reset_button->signal_clicked().connect(sigc::mem_fun (*this,&LPECopyRotate::resetStyles));
+ reset_button->set_size_request(140,30);
+ vbox->pack_start(*hbox, true,true,2);
+ hbox->pack_start(*reset_button, false, false,2);
std::vector<Parameter *>::iterator it = param_vector.begin();
while (it != param_vector.end()) {
if ((*it)->widget_is_visible) {
@@ -125,11 +349,11 @@ 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);
}
+ sp_lpe_item_update_patheffect(sp_lpe_item, false, false);
}
void
@@ -140,17 +364,17 @@ LPECopyRotate::doBeforeEffect (SPLPEItem const* lpeitem)
if (copies_to_360) {
rotation_angle.param_set_value(360.0/(double)num_copies);
}
- if (fuse_paths && rotation_angle * num_copies > 360 && rotation_angle > 0) {
+ if (fuse_paths && rotation_angle * num_copies > 360.1 && rotation_angle > 0) {
num_copies.param_set_value(floor(360/rotation_angle));
}
if (fuse_paths && copies_to_360) {
- num_copies.param_set_increments(2,2);
+ num_copies.param_set_increments(2.0,10.0);
if ((int)num_copies%2 !=0) {
num_copies.param_set_value(num_copies+1);
rotation_angle.param_set_value(360.0/(double)num_copies);
}
} else {
- num_copies.param_set_increments(1,1);
+ num_copies.param_set_increments(1.0, 10.0);
}
if (dist_angle_handle < 1.0) {
@@ -352,12 +576,57 @@ LPECopyRotate::setFusion(Geom::PathVector &path_on, Geom::Path divider, double s
tmp_path.clear();
}
+Geom::PathVector
+LPECopyRotate::doEffect_path (Geom::PathVector const & path_in)
+{
+ Geom::PathVector path_out;
+ if (split_items && (fuse_paths || join_paths)) {
+ if (num_copies == 0) {
+ return path_out;
+ }
+ path_out = pathv_to_linear_and_cubic_beziers(path_in);
+ double diagonal = Geom::distance(Geom::Point(boundingbox_X.min(),boundingbox_Y.min()),Geom::Point(boundingbox_X.max(),boundingbox_Y.max()));
+ Geom::OptRect bbox = sp_lpe_item->geometricBounds();
+ double size_divider = Geom::distance(origin,bbox) + (diagonal * 2);
+ Geom::Point line_start = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(starting_angle))) * size_divider;
+ Geom::Point line_end = origin + dir * Geom::Rotate(-(Geom::rad_from_deg(rotation_angle + starting_angle))) * size_divider;
+ Geom::Path divider = Geom::Path(line_start);
+ divider.appendNew<Geom::LineSegment>((Geom::Point)origin);
+ divider.appendNew<Geom::LineSegment>(line_end);
+ divider.close();
+ Geom::PathVector triangle;
+ triangle.push_back(divider);
+ Geom::PathIntersectionGraph *pig = new Geom::PathIntersectionGraph(triangle, path_out);
+ if (pig && ! path_out.empty() && !triangle.empty()) {
+ //TODO: Here can produce a crash because some knows problems in new boolops code
+ path_out = pig->getIntersection();
+ }
+ Geom::Affine r = Geom::identity();
+ Geom::Point dir = unit_vector(Geom::middle_point(line_start,line_end) - (Geom::Point)origin);
+ Geom::Point gap = dir * split_gap;
+ r *= Geom::Translate(gap);
+ path_out *= r;
+ } else {
+ // default behavior
+ for (unsigned int i=0; i < path_in.size(); i++) {
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = path_in[i].toPwSb();
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
+ Geom::PathVector path = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
+ // add the output path vector to the already accumulated vector:
+ for (unsigned int j=0; j < path.size(); j++) {
+ path_out.push_back(path[j]);
+ }
+ }
+ }
+ return pathv_to_linear_and_cubic_beziers(path_out);
+}
+
Geom::Piecewise<Geom::D2<Geom::SBasis> >
LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
using namespace Geom;
- if (num_copies == 1 && !fuse_paths) {
+ if ((num_copies == 1 && !fuse_paths) || split_items) {
return pwd2_in;
}
@@ -373,10 +642,10 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
divider.appendNew<Geom::LineSegment>(line_end);
Piecewise<D2<SBasis> > output;
Affine pre = Translate(-origin) * Rotate(-rad_from_deg(starting_angle));
+ PathVector const original_pathv = pathv_to_linear_and_cubic_beziers(path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001));
if (fuse_paths) {
Geom::PathVector path_out;
Geom::PathVector tmp_path;
- PathVector const original_pathv = path_from_piecewise(remove_short_cuts(pwd2_in, 0.1), 0.001);
for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); path_it != original_pathv.end(); ++path_it) {
if (path_it->empty()) {
continue;
@@ -403,7 +672,7 @@ LPECopyRotate::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & p
output = paths_to_pw(path_out);
}
} else {
- Geom::PathVector output_pv = path_from_piecewise(output , 0.01);
+ Geom::PathVector output_pv;
for (int i = 0; i < num_copies; ++i) {
Rotate rot(-rad_from_deg(rotation_angle * i));
Affine t = pre * rot * Translate(origin);
@@ -449,6 +718,23 @@ LPECopyRotate::resetDefaults(SPItem const* item)
original_bbox(SP_LPE_ITEM(item));
}
+void
+LPECopyRotate::doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/)
+{
+ processObjects(LPE_VISIBILITY);
+}
+
+void
+LPECopyRotate::doOnRemove (SPLPEItem const* /*lpeitem*/)
+{
+ //unset "erase_extra_objects" hook on sp-lpe-item.cpp
+ if (!erase_extra_objects) {
+ processObjects(LPE_TO_OBJECTS);
+ return;
+ }
+ processObjects(LPE_ERASE);
+}
+
} //namespace LivePathEffect
} /* namespace Inkscape */
diff --git a/src/live_effects/lpe-copy_rotate.h b/src/live_effects/lpe-copy_rotate.h
index c2ae2daf1..dbec2e1c3 100644
--- a/src/live_effects/lpe-copy_rotate.h
+++ b/src/live_effects/lpe-copy_rotate.h
@@ -15,6 +15,8 @@
*/
#include "live_effects/effect.h"
+#include "live_effects/parameter/parameter.h"
+#include "live_effects/parameter/text.h"
#include "live_effects/parameter/point.h"
#include "live_effects/lpegroupbbox.h"
@@ -26,13 +28,20 @@ public:
LPECopyRotate(LivePathEffectObject *lpeobject);
virtual ~LPECopyRotate();
virtual void doOnApply (SPLPEItem const* lpeitem);
+ virtual Geom::PathVector doEffect_path (Geom::PathVector const & path_in);
virtual Geom::Piecewise<Geom::D2<Geom::SBasis> > doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
virtual void doBeforeEffect (SPLPEItem const* lpeitem);
+ virtual void doAfterEffect (SPLPEItem const* lpeitem);
virtual void setFusion(Geom::PathVector &path_in, Geom::Path divider, double sizeDivider);
virtual void split(Geom::PathVector &path_in, Geom::Path const &divider);
virtual void resetDefaults(SPItem const* item);
virtual void transform_multiply(Geom::Affine const& postmul, bool set);
+ virtual void doOnRemove (SPLPEItem const* /*lpeitem*/);
+ virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/);
virtual Gtk::Widget * newWidget();
+ void toItem(Geom::Affine transform, size_t i, bool reset);
+ void cloneD(SPObject *origin, SPObject *dest, bool root, bool reset);
+ void resetStyles();
protected:
virtual void addCanvasIndicators(SPLPEItem const *lpeitem, std::vector<Geom::PathVector> &hp_vec);
@@ -42,9 +51,11 @@ private:
ScalarParam starting_angle;
ScalarParam rotation_angle;
ScalarParam num_copies;
+ ScalarParam split_gap;
BoolParam copies_to_360;
BoolParam fuse_paths;
BoolParam join_paths;
+ BoolParam split_items;
Geom::Point A;
Geom::Point B;
Geom::Point dir;
@@ -52,6 +63,9 @@ private:
Geom::Point rot_pos;
Geom::Point previous_start_point;
double dist_angle_handle;
+ double previous_num_copies;
+ bool reset;
+ SPObject * container;
LPECopyRotate(const LPECopyRotate&);
LPECopyRotate& operator=(const LPECopyRotate&);
};
diff --git a/src/live_effects/lpe-measure-line.cpp b/src/live_effects/lpe-measure-line.cpp
index af2a8e919..ef87be81c 100644
--- a/src/live_effects/lpe-measure-line.cpp
+++ b/src/live_effects/lpe-measure-line.cpp
@@ -21,7 +21,9 @@
#include "svg/svg-color.h"
#include "svg/svg.h"
#include "display/curve.h"
+#include "helper/geom.h"
#include "2geom/affine.h"
+#include "path-chemistry.h"
#include "style.h"
#include "sp-root.h"
#include "sp-defs.h"
@@ -165,12 +167,6 @@ LPEMeasureLine::LPEMeasureLine(LivePathEffectObject *lpeobject) :
LPEMeasureLine::~LPEMeasureLine() {}
-void swap(Geom::Point &A, Geom::Point &B){
- Geom::Point tmp = A;
- A = B;
- B = tmp;
-}
-
void
LPEMeasureLine::createArrowMarker(const char * mode)
{
@@ -229,7 +225,7 @@ LPEMeasureLine::createArrowMarker(const char * mode)
elemref = SP_OBJECT(document->getDefs()->appendChildRepr(arrow));
Inkscape::GC::release(arrow);
}
- elements.push_back(mode);
+ items.push_back(mode);
}
void
@@ -369,7 +365,7 @@ LPEMeasureLine::createTextLabel(Geom::Point pos, double length, Geom::Coord angl
copy->setAttribute("id", id);
elemref = elemref_copy;
}
- elements.push_back(id);
+ items.push_back(id);
Geom::OptRect bounds = SP_ITEM(elemref)->bounds(SPItem::GEOMETRIC_BBOX);
if (bounds) {
anotation_width = bounds->width() * 1.4;
@@ -483,7 +479,7 @@ LPEMeasureLine::createLine(Geom::Point start,Geom::Point end, const char * id, b
elemref->deleteObject();
copy->setAttribute("id", id);
}
- elements.push_back(id);
+ items.push_back(id);
}
void
@@ -535,7 +531,7 @@ LPEMeasureLine::doBeforeEffect (SPLPEItem const* lpeitem)
sp_lpe_item->getCurrentLPE() != this){
return;
}
- elements.clear();
+ items.clear();
start_stored = start;
end_stored = end;
Geom::Point hstart = start;
@@ -680,60 +676,12 @@ LPEMeasureLine::doOnRemove (SPLPEItem const* /*lpeitem*/)
//unset "erase_extra_objects" hook on sp-lpe-item.cpp
if (!erase_extra_objects) {
processObjects(LPE_TO_OBJECTS);
- elements.clear();
+ items.clear();
return;
}
processObjects(LPE_ERASE);
}
-void
-LPEMeasureLine::processObjects(LpeAction lpe_action)
-{
- SPDocument * document = SP_ACTIVE_DOCUMENT;
- for (std::vector<const char *>::iterator el_it = elements.begin();
- el_it != elements.end(); ++el_it) {
- const char * id = *el_it;
- if (!id || strlen(id) == 0) {
- return;
- }
- SPObject *elemref = NULL;
- if (elemref = document->getObjectById(id)) {
- SPCSSAttr *css;
- Glib::ustring css_str;
- switch (lpe_action){
- case LPE_TO_OBJECTS:
- elemref->getRepr()->setAttribute("inkscape:path-effect", NULL);
- elemref->getRepr()->setAttribute("sodipodi:insensitive", NULL);
- break;
-
- case LPE_ERASE:
- if (std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) {
- elemref->deleteObject();
- }
- break;
-
- case LPE_VISIBILITY:
- css = sp_repr_css_attr_new();
- sp_repr_css_attr_add_from_string(css, elemref->getRepr()->attribute("style"));
- if (!this->isVisible() && std::strcmp(elemref->getId(),id_origin.param_getSVGValue()) != 0) {
- css->setAttribute("display", "none");
- } else {
- css->setAttribute("display", NULL);
- }
- sp_repr_css_write_string(css,css_str);
- elemref->getRepr()->setAttribute("style", css_str.c_str());
- break;
-
- default:
- break;
- }
- }
- }
- if (lpe_action == LPE_ERASE) {
- elements.clear();
- }
-}
-
Gtk::Widget *LPEMeasureLine::newWidget()
{
// use manage here, because after deletion of Effect object, others might
diff --git a/src/live_effects/lpe-measure-line.h b/src/live_effects/lpe-measure-line.h
index c69921a4d..724c0d924 100644
--- a/src/live_effects/lpe-measure-line.h
+++ b/src/live_effects/lpe-measure-line.h
@@ -35,12 +35,6 @@ enum OrientationMethod {
OM_END
};
-enum LpeAction {
- LPE_ERASE = 0,
- LPE_TO_OBJECTS,
- LPE_VISIBILITY
-};
-
class LPEMeasureLine : public Effect {
public:
LPEMeasureLine(LivePathEffectObject *lpeobject);
@@ -51,7 +45,6 @@ public:
virtual void doEffect (SPCurve * curve){}; //stop the chain
virtual void doOnVisibilityToggled(SPLPEItem const* /*lpeitem*/);
virtual Geom::PathVector doEffect_path(Geom::PathVector const &path_in);
- void processObjects(LpeAction lpe_action);
void createLine(Geom::Point start,Geom::Point end, const char * id, bool main, bool overflow, bool remove, bool arrows = false);
void createTextLabel(Geom::Point pos, double length, Geom::Coord angle, bool remove, bool valid);
void onExpanderChanged();
@@ -92,7 +85,6 @@ private:
double arrow_gap;
Geom::Point start_stored;
Geom::Point end_stored;
- std::vector<const char *> elements;
/* Geom::Affine affine_over;*/
LPEMeasureLine(const LPEMeasureLine &);
LPEMeasureLine &operator=(const LPEMeasureLine &);
diff --git a/src/live_effects/parameter/bool.cpp b/src/live_effects/parameter/bool.cpp
index af99ef362..813c06b4e 100644
--- a/src/live_effects/parameter/bool.cpp
+++ b/src/live_effects/parameter/bool.cpp
@@ -72,7 +72,7 @@ BoolParam::param_newWidget()
checkwdg->setActive(value);
checkwdg->setProgrammatically = false;
checkwdg->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change bool parameter"));
-
+ param_effect->upd_params = false;
return dynamic_cast<Gtk::Widget *> (checkwdg);
} else {
return NULL;
@@ -82,6 +82,7 @@ BoolParam::param_newWidget()
void
BoolParam::param_setValue(bool newvalue)
{
+ param_effect->upd_params = true;
value = newvalue;
}
diff --git a/src/live_effects/parameter/text.cpp b/src/live_effects/parameter/text.cpp
index 8cab68ad0..5c4cdf4c6 100644
--- a/src/live_effects/parameter/text.cpp
+++ b/src/live_effects/parameter/text.cpp
@@ -125,13 +125,14 @@ TextParam::param_newWidget()
rsu->setProgrammatically = false;
rsu->set_undo_parameters(SP_VERB_DIALOG_LIVE_PATH_EFFECT, _("Change text parameter"));
-
+ param_effect->upd_params = false;
return dynamic_cast<Gtk::Widget *> (rsu);
}
void
TextParam::param_setValue(const Glib::ustring newvalue)
{
+ param_effect->upd_params = true;
value = newvalue;
if (!_hide_canvas_text) {
sp_canvastext_set_text (canvas_text, newvalue.c_str());