diff options
| author | Marc Jeanmougin <marc@jeanmougin.fr> | 2017-12-29 10:18:01 +0000 |
|---|---|---|
| committer | Marc Jeanmougin <marc@jeanmougin.fr> | 2017-12-29 10:18:01 +0000 |
| commit | 9564781d4eef5ac13b2c4ec393171d00fbdacd1d (patch) | |
| tree | 93481b36fc6004238b6e919db03ac1680e11f096 /src/live_effects | |
| parent | remove git remnants (diff) | |
| parent | Merge branch 'master' into powerpencilII (diff) | |
| download | inkscape-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.cpp | 103 | ||||
| -rw-r--r-- | src/live_effects/lpe-powerstroke.h | 1 | ||||
| -rw-r--r-- | src/live_effects/lpeobject-reference.cpp | 6 | ||||
| -rw-r--r-- | src/live_effects/parameter/powerstrokepointarray.cpp | 54 | ||||
| -rw-r--r-- | src/live_effects/parameter/powerstrokepointarray.h | 1 |
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; |
