summaryrefslogtreecommitdiffstats
path: root/src/live_effects
diff options
context:
space:
mode:
authorMarc Jeanmougin <marc@jeanmougin.fr>2017-12-29 10:18:01 +0000
committerMarc Jeanmougin <marc@jeanmougin.fr>2017-12-29 10:18:01 +0000
commit9564781d4eef5ac13b2c4ec393171d00fbdacd1d (patch)
tree93481b36fc6004238b6e919db03ac1680e11f096 /src/live_effects
parentremove git remnants (diff)
parentMerge branch 'master' into powerpencilII (diff)
downloadinkscape-9564781d4eef5ac13b2c4ec393171d00fbdacd1d.tar.gz
inkscape-9564781d4eef5ac13b2c4ec393171d00fbdacd1d.zip
Merge branch 'master' of gitlab.com:inkscape/inkscape
Diffstat (limited to 'src/live_effects')
-rw-r--r--src/live_effects/lpe-powerstroke.cpp103
-rw-r--r--src/live_effects/lpe-powerstroke.h1
-rw-r--r--src/live_effects/lpeobject-reference.cpp6
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.cpp54
-rw-r--r--src/live_effects/parameter/powerstrokepointarray.h1
5 files changed, 108 insertions, 57 deletions
diff --git a/src/live_effects/lpe-powerstroke.cpp b/src/live_effects/lpe-powerstroke.cpp
index 51c8451a5..4e937c1e4 100644
--- a/src/live_effects/lpe-powerstroke.cpp
+++ b/src/live_effects/lpe-powerstroke.cpp
@@ -97,10 +97,13 @@ static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.0
if ( are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) ) { // try second time
dM=derivative(dM);
}
- if ( are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) ) { // admit defeat
+ if ( dM.isZero(tol) || (are_near(L2sq(dM(t)),0.) && (dM[0].size() > 1) && (dM[1].size() > 1) )) { // admit defeat
return Geom::Circle(Geom::Point(0., 0.), 0.);
}
Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ if (unitv.empty()) { // admit defeat
+ return Geom::Circle(Geom::Point(0., 0.), 0.);
+ }
Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
Piecewise<SBasis> k = cross(derivative(unitv),unitv);
k = divide(k,dMlength,tol,3);
@@ -322,7 +325,7 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::
/* per definition, each discontinuity should be fixed with a join-ending, as defined by linejoin_type
*/
Geom::PathBuilder pb;
- if (B.size() == 0) {
+ if (B.empty()) {
return pb.peek().front();
}
@@ -555,7 +558,6 @@ static Geom::Path path_from_piecewise_fix_cusps( Geom::Piecewise<Geom::D2<Geom::
return pb.peek().front();
}
-
Geom::PathVector
LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
{
@@ -567,11 +569,18 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
}
Geom::PathVector pathv = pathv_to_linear_and_cubic_beziers(path_in);
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in = pathv[0].toPwSb();
+ if (pwd2_in.empty()) {
+ return path_in;
+ }
Piecewise<D2<SBasis> > der = derivative(pwd2_in);
- Piecewise<D2<SBasis> > n = unitVector(der,0.0001);
- if (!n.size() || !pwd2_in.size() || !n.size()) {
+ if (der.empty()) {
+ return path_in;
+ }
+ Piecewise<D2<SBasis> > n = unitVector(der,0.00001);
+ if (n.empty()) {
return path_in;
}
+
n = rot90(n);
offset_points.set_pwd2(pwd2_in, n);
@@ -590,12 +599,33 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
if (sort_points) {
sort(ts.begin(), ts.end(), compare_offsets);
}
+ // create stroke path where points (x,y) := (t, offset)
+ Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
+ if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) {
+ johan->setBeta(interpolator_beta);
+ }
+ if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(interpolator)) {
+ smooth->setBeta(interpolator_beta);
+ }
if (pathv[0].closed()) {
- // add extra points for interpolation between first and last point
- Point first_point = ts.front();
- Point last_point = ts.back();
- ts.insert(ts.begin(), last_point - Point(pwd2_in.domain().extent() ,0));
- ts.push_back( first_point + Point(pwd2_in.domain().extent() ,0) );
+ std::vector<Geom::Point> ts_close;
+ //we have only one knot or overwrite before
+ Geom::Point start = Geom::Point( pwd2_in.domain().min(), ts.front()[Geom::Y]);
+ Geom::Point end = Geom::Point( pwd2_in.domain().max(), ts.front()[Geom::Y]);
+ if (ts.size() > 1) {
+ ts_close.push_back(ts[ts.size()-2]);
+ ts_close.push_back(ts.back());
+ ts_close.push_back(ts.front());
+ ts_close.push_back(ts[1]);
+ Geom::Path closepath = interpolator->interpolateToPath(ts_close);
+ start = closepath.pointAt(Geom::nearest_time(Geom::Point( pwd2_in.domain().min(),0), closepath));
+ start[Geom::X] = pwd2_in.domain().min();
+ end = start;
+ end[Geom::X] = pwd2_in.domain().max();
+ }
+ ts.insert(ts.begin(), start );
+ ts.push_back( end );
+ ts_close.clear();
} else {
// add width data for first and last point on the path
// depending on cap type, these first and last points have width zero or take the width from the closest width point.
@@ -612,14 +642,7 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
for (std::size_t i = 0, e = ts.size(); i < e; ++i) {
ts[i][Geom::X] *= xcoord_scaling;
}
- // create stroke path where points (x,y) := (t, offset)
- Geom::Interpolate::Interpolator *interpolator = Geom::Interpolate::Interpolator::create(static_cast<Geom::Interpolate::InterpolatorType>(interpolator_type.get_value()));
- if (Geom::Interpolate::CubicBezierJohan *johan = dynamic_cast<Geom::Interpolate::CubicBezierJohan*>(interpolator)) {
- johan->setBeta(interpolator_beta);
- }
- if (Geom::Interpolate::CubicBezierSmooth *smooth = dynamic_cast<Geom::Interpolate::CubicBezierSmooth*>(interpolator)) {
- smooth->setBeta(interpolator_beta);
- }
+
Geom::Path strokepath = interpolator->interpolateToPath(ts);
delete interpolator;
@@ -639,7 +662,9 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
}
LineJoinType jointype = static_cast<LineJoinType>(linejoin_type.get_value());
-
+ if (x.empty() || y.empty()) {
+ return path_in;
+ }
Piecewise<D2<SBasis> > pwd2_out = compose(pwd2_in,x) + y*compose(n,x);
Piecewise<D2<SBasis> > mirrorpath = reverse( compose(pwd2_in,x) - y*compose(n,x));
@@ -659,31 +684,31 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
case LINECAP_PEAK:
{
Geom::Point end_deriv = -unitTangentAt( reverse(pwd2_in.segs.back()), 0.);
- double radius = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue());
- Geom::Point midpoint = 0.5*(pwd2_out.lastValue() + mirrorpath.firstValue()) + radius*end_deriv;
+ double radius = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint());
+ Geom::Point midpoint = 0.5*(fixed_path.finalPoint() + fixed_mirrorpath.initialPoint()) + radius*end_deriv;
fixed_path.appendNew<LineSegment>(midpoint);
- fixed_path.appendNew<LineSegment>(mirrorpath.firstValue());
+ fixed_path.appendNew<LineSegment>(fixed_mirrorpath.initialPoint());
break;
}
case LINECAP_SQUARE:
{
Geom::Point end_deriv = -unitTangentAt( reverse(pwd2_in.segs.back()), 0.);
- double radius = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue());
- fixed_path.appendNew<LineSegment>( pwd2_out.lastValue() + radius*end_deriv );
- fixed_path.appendNew<LineSegment>( mirrorpath.firstValue() + radius*end_deriv );
- fixed_path.appendNew<LineSegment>( mirrorpath.firstValue() );
+ double radius = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint());
+ fixed_path.appendNew<LineSegment>( fixed_path.finalPoint() + radius*end_deriv );
+ fixed_path.appendNew<LineSegment>( fixed_mirrorpath.initialPoint() + radius*end_deriv );
+ fixed_path.appendNew<LineSegment>( fixed_mirrorpath.initialPoint() );
break;
}
case LINECAP_BUTT:
{
- fixed_path.appendNew<LineSegment>( mirrorpath.firstValue() );
+ fixed_path.appendNew<LineSegment>( fixed_mirrorpath.initialPoint() );
break;
}
case LINECAP_ROUND:
default:
{
- double radius1 = 0.5 * distance(pwd2_out.lastValue(), mirrorpath.firstValue());
- fixed_path.appendNew<EllipticalArc>( radius1, radius1, M_PI/2., false, y.lastValue() < 0, mirrorpath.firstValue() );
+ double radius1 = 0.5 * distance(fixed_path.finalPoint(), fixed_mirrorpath.initialPoint());
+ fixed_path.appendNew<EllipticalArc>( radius1, radius1, M_PI/2., false, y.lastValue() < 0, fixed_mirrorpath.initialPoint() );
break;
}
}
@@ -696,31 +721,31 @@ LPEPowerStroke::doEffect_path (Geom::PathVector const & path_in)
case LINECAP_PEAK:
{
Geom::Point start_deriv = unitTangentAt( pwd2_in.segs.front(), 0.);
- double radius = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue());
- Geom::Point midpoint = 0.5*(mirrorpath.lastValue() + pwd2_out.firstValue()) - radius*start_deriv;
+ double radius = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint());
+ Geom::Point midpoint = 0.5*(fixed_mirrorpath.finalPoint() + fixed_path.initialPoint()) - radius*start_deriv;
fixed_path.appendNew<LineSegment>( midpoint );
- fixed_path.appendNew<LineSegment>( pwd2_out.firstValue() );
+ fixed_path.appendNew<LineSegment>( fixed_path.initialPoint() );
break;
}
case LINECAP_SQUARE:
{
Geom::Point start_deriv = unitTangentAt( pwd2_in.segs.front(), 0.);
- double radius = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue());
- fixed_path.appendNew<LineSegment>( mirrorpath.lastValue() - radius*start_deriv );
- fixed_path.appendNew<LineSegment>( pwd2_out.firstValue() - radius*start_deriv );
- fixed_path.appendNew<LineSegment>( pwd2_out.firstValue() );
+ double radius = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint());
+ fixed_path.appendNew<LineSegment>( fixed_mirrorpath.finalPoint() - radius*start_deriv );
+ fixed_path.appendNew<LineSegment>( fixed_path.initialPoint() - radius*start_deriv );
+ fixed_path.appendNew<LineSegment>( fixed_path.initialPoint() );
break;
}
case LINECAP_BUTT:
{
- fixed_path.appendNew<LineSegment>( pwd2_out.firstValue() );
+ fixed_path.appendNew<LineSegment>( fixed_path.initialPoint() );
break;
}
case LINECAP_ROUND:
default:
{
- double radius2 = 0.5 * distance(pwd2_out.firstValue(), mirrorpath.lastValue());
- fixed_path.appendNew<EllipticalArc>( radius2, radius2, M_PI/2., false, y.firstValue() < 0, pwd2_out.firstValue() );
+ double radius2 = 0.5 * distance(fixed_path.initialPoint(), fixed_mirrorpath.finalPoint());
+ fixed_path.appendNew<EllipticalArc>( radius2, radius2, M_PI/2., false, y.firstValue() < 0, fixed_path.initialPoint() );
break;
}
}
diff --git a/src/live_effects/lpe-powerstroke.h b/src/live_effects/lpe-powerstroke.h
index 4a0eda75a..19696ac57 100644
--- a/src/live_effects/lpe-powerstroke.h
+++ b/src/live_effects/lpe-powerstroke.h
@@ -45,7 +45,6 @@ private:
EnumParam<unsigned> linejoin_type;
ScalarParam miter_limit;
EnumParam<unsigned> end_linecap_type;
-
LPEPowerStroke(const LPEPowerStroke&);
LPEPowerStroke& operator=(const LPEPowerStroke&);
};
diff --git a/src/live_effects/lpeobject-reference.cpp b/src/live_effects/lpeobject-reference.cpp
index 83cd6623c..89df843e8 100644
--- a/src/live_effects/lpeobject-reference.cpp
+++ b/src/live_effects/lpeobject-reference.cpp
@@ -76,8 +76,10 @@ LPEObjectReference::link(const char *to)
void
LPEObjectReference::unlink(void)
{
- g_free(lpeobject_href);
- lpeobject_href = NULL;
+ if (lpeobject_href) {
+ g_free(lpeobject_href);
+ lpeobject_href = NULL;
+ }
detach();
}
diff --git a/src/live_effects/parameter/powerstrokepointarray.cpp b/src/live_effects/parameter/powerstrokepointarray.cpp
index bc06e42ca..64c772602 100644
--- a/src/live_effects/parameter/powerstrokepointarray.cpp
+++ b/src/live_effects/parameter/powerstrokepointarray.cpp
@@ -89,6 +89,31 @@ PowerStrokePointArrayParam::recalculate_controlpoints_for_new_pwd2(Geom::Piecewi
}
}
+/** call this method to recalculate the controlpoints when path is reversed.*/
+std::vector<Geom::Point>
+PowerStrokePointArrayParam::reverse_controlpoints(bool write)
+{
+ std::vector<Geom::Point> controlpoints;
+ if (!last_pwd2.empty()) {
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in_reverse = reverse(last_pwd2);
+ for (unsigned int i = 0; i < _vector.size(); ++i) {
+ Geom::Point control_pos = last_pwd2.valueAt(_vector[i][Geom::X]);
+ double new_pos = Geom::nearest_time(control_pos, pwd2_in_reverse);
+ controlpoints.push_back(Geom::Point(new_pos,_vector[i][Geom::Y]));
+ _vector[i][Geom::X] = new_pos;
+ }
+ if (write) {
+ write_to_SVG();
+ _vector.clear();
+ _vector = controlpoints;
+ controlpoints.clear();
+ write_to_SVG();
+ return _vector;
+ }
+ }
+ return controlpoints;
+}
+
float PowerStrokePointArrayParam::median_width()
{
size_t size = _vector.size();
@@ -205,22 +230,21 @@ PowerStrokePointArrayParamKnotHolderEntity::knot_click(guint state)
if (state & GDK_MOD1_MASK) {
// delete the clicked knot
std::vector<Geom::Point> & vec = _pparam->_vector;
- vec.erase(vec.begin() + _index);
- _pparam->param_set_and_write_new_value(vec);
-
- // remove knot from knotholder
- parent_holder->entity.remove(this);
- // shift knots down one index
- for(std::list<KnotHolderEntity *>::iterator ent = parent_holder->entity.begin(); ent != parent_holder->entity.end(); ++ent) {
- PowerStrokePointArrayParamKnotHolderEntity *pspa_ent = dynamic_cast<PowerStrokePointArrayParamKnotHolderEntity *>(*ent);
- if ( pspa_ent && pspa_ent->_pparam == this->_pparam ) { // check if the knotentity belongs to this powerstrokepointarray parameter
- if (pspa_ent->_index > this->_index) {
- --pspa_ent->_index;
+ if (vec.size() > 1) { //Force dont remove last knot
+ vec.erase(vec.begin() + _index);
+ _pparam->param_set_and_write_new_value(vec);
+ // shift knots down one index
+ for(std::list<KnotHolderEntity *>::iterator ent = parent_holder->entity.begin(); ent != parent_holder->entity.end(); ++ent) {
+ PowerStrokePointArrayParamKnotHolderEntity *pspa_ent = dynamic_cast<PowerStrokePointArrayParamKnotHolderEntity *>(*ent);
+ if ( pspa_ent && pspa_ent->_pparam == this->_pparam ) { // check if the knotentity belongs to this powerstrokepointarray parameter
+ if (pspa_ent->_index > this->_index) {
+ --pspa_ent->_index;
+ }
}
- }
- };
- // delete self and return
- delete this;
+ };
+ // temporary hide, when knotholder were recreated it finaly drop
+ this->knot->hide();
+ }
return;
} else {
// add a knot to XML
diff --git a/src/live_effects/parameter/powerstrokepointarray.h b/src/live_effects/parameter/powerstrokepointarray.h
index 621d3b969..a1d4db3ca 100644
--- a/src/live_effects/parameter/powerstrokepointarray.h
+++ b/src/live_effects/parameter/powerstrokepointarray.h
@@ -47,6 +47,7 @@ public:
Geom::Piecewise<Geom::D2<Geom::SBasis> > const & get_pwd2_normal() const { return last_pwd2_normal; }
void recalculate_controlpoints_for_new_pwd2(Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in);
+ std::vector<Geom::Point> reverse_controlpoints(bool write);
void set_scale_width(double scale_width){_scale_width = scale_width;};
double _scale_width;
friend class PowerStrokePointArrayParamKnotHolderEntity;