diff options
| author | Jabier Arraiza Cenoz <jabier.arraiza@marker.es> | 2015-08-21 21:54:57 +0000 |
|---|---|---|
| committer | Jabiertxof <jtx@jtx.marker.es> | 2015-08-21 21:54:57 +0000 |
| commit | 584f35dcc621f5877732cf310c310570c021c31d (patch) | |
| tree | 6dd2b5612d3a41949ca87828c7cf27713e059675 /src/live_effects | |
| parent | Not sure about this changes :( (diff) | |
| parent | indentation and whitespace fixes (diff) | |
| download | inkscape-584f35dcc621f5877732cf310c310570c021c31d.tar.gz inkscape-584f35dcc621f5877732cf310c310570c021c31d.zip | |
update to trunk
(bzr r13645.1.108)
Diffstat (limited to 'src/live_effects')
| -rw-r--r-- | src/live_effects/lpe-angle_bisector.cpp | 2 | ||||
| -rw-r--r-- | src/live_effects/lpe-bendpath.h | 3 | ||||
| -rw-r--r-- | src/live_effects/lpe-bspline.cpp | 240 | ||||
| -rw-r--r-- | src/live_effects/lpe-bspline.h | 13 | ||||
| -rw-r--r-- | src/live_effects/lpe-simplify.cpp | 1 | ||||
| -rw-r--r-- | src/live_effects/lpe-spiro.cpp | 16 | ||||
| -rw-r--r-- | src/live_effects/lpe-spiro.h | 2 | ||||
| -rw-r--r-- | src/live_effects/spiro-converters.cpp | 32 | ||||
| -rw-r--r-- | src/live_effects/spiro-converters.h | 24 | ||||
| -rw-r--r-- | src/live_effects/spiro.cpp | 15 |
10 files changed, 164 insertions, 184 deletions
diff --git a/src/live_effects/lpe-angle_bisector.cpp b/src/live_effects/lpe-angle_bisector.cpp index 95a81c763..900d29e3a 100644 --- a/src/live_effects/lpe-angle_bisector.cpp +++ b/src/live_effects/lpe-angle_bisector.cpp @@ -38,7 +38,7 @@ public: virtual Geom::Point knot_get() const; }; -} // namespace TtC +} // namespace AB LPEAngleBisector::LPEAngleBisector(LivePathEffectObject *lpeobject) : Effect(lpeobject), diff --git a/src/live_effects/lpe-bendpath.h b/src/live_effects/lpe-bendpath.h index 16b8c6137..0871d532e 100644 --- a/src/live_effects/lpe-bendpath.h +++ b/src/live_effects/lpe-bendpath.h @@ -39,9 +39,8 @@ public: virtual void resetDefaults(SPItem const* item); - -private: PathParam bend_path; +private: ScalarParam prop_scale; BoolParam scale_y_rel; BoolParam vertical_pattern; diff --git a/src/live_effects/lpe-bspline.cpp b/src/live_effects/lpe-bspline.cpp index c2a2d080e..019584943 100644 --- a/src/live_effects/lpe-bspline.cpp +++ b/src/live_effects/lpe-bspline.cpp @@ -16,10 +16,12 @@ namespace Inkscape { namespace LivePathEffect { -const double HANDLE_CUBIC_GAP = 0.01; +const double HANDLE_CUBIC_GAP = 0.001; const double NO_POWER = 0.0; const double DEFAULT_START_POWER = 0.3334; const double DEFAULT_END_POWER = 0.6667; +Geom::PathVector hp; +void sp_bspline_drawHandle(Geom::Point p, double helper_size); LPEBSpline::LPEBSpline(LivePathEffectObject *lpeobject) : Effect(lpeobject), @@ -67,15 +69,115 @@ void LPEBSpline::doOnApply(SPLPEItem const* lpeitem) } } +void +LPEBSpline::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) +{ + hp_vec.push_back(hp); +} + +Gtk::Widget *LPEBSpline::newWidget() +{ + // 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); + std::vector<Parameter *>::iterator it = param_vector.begin(); + while (it != param_vector.end()) { + if ((*it)->widget_is_visible) { + Parameter *param = *it; + Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); + if (param->param_key == "weight") { + Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0)); + Gtk::Button *default_weight = + Gtk::manage(new Gtk::Button(Glib::ustring(_("Default weight")))); + default_weight->signal_clicked() + .connect(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight)); + buttons->pack_start(*default_weight, true, true, 2); + Gtk::Button *make_cusp = + Gtk::manage(new Gtk::Button(Glib::ustring(_("Make cusp")))); + make_cusp->signal_clicked() + .connect(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp)); + buttons->pack_start(*make_cusp, true, true, 2); + vbox->pack_start(*buttons, true, true, 2); + } + if (param->param_key == "weight" || param->param_key == "steps") { + Inkscape::UI::Widget::Scalar *widg_registered = + Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); + widg_registered->signal_value_changed() + .connect(sigc::mem_fun(*this, &LPEBSpline::toWeight)); + widg = dynamic_cast<Gtk::Widget *>(widg_registered); + if (widg) { + Gtk::HBox * hbox_weight_steps = dynamic_cast<Gtk::HBox *>(widg); + std::vector< Gtk::Widget* > childList = hbox_weight_steps->get_children(); + Gtk::Entry* entry_widget = dynamic_cast<Gtk::Entry *>(childList[1]); + entry_widget->set_width_chars(6); + } + } + if (param->param_key == "only_selected") { + Gtk::CheckButton *widg_registered = + Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); + widg = dynamic_cast<Gtk::Widget *>(widg_registered); + } + if (param->param_key == "ignore_cusp") { + Gtk::CheckButton *widg_registered = + Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); + widg = dynamic_cast<Gtk::Widget *>(widg_registered); + } + 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; + } + return dynamic_cast<Gtk::Widget *>(vbox); +} + +void LPEBSpline::toDefaultWeight() +{ + changeWeight(DEFAULT_START_POWER); +} + +void LPEBSpline::toMakeCusp() +{ + changeWeight(NO_POWER); +} + +void LPEBSpline::toWeight() +{ + changeWeight(weight); +} + +void LPEBSpline::changeWeight(double weight_ammount) +{ + SPPath *path = dynamic_cast<SPPath *>(sp_lpe_item); + if(path) { + SPCurve *curve = path->get_curve_for_edit(); + doBSplineFromWidget(curve, weight_ammount); + gchar *str = sp_svg_write_path(curve->get_pathvector()); + path->getRepr()->setAttribute("inkscape:original-d", str); + } +} + void LPEBSpline::doEffect(SPCurve *curve) { + sp_bspline_do_effect(curve, helper_size); +} +void sp_bspline_do_effect(SPCurve *curve, double helper_size) +{ if (curve->get_segment_count() < 1) { return; } - // Make copy of old path as it is changed during processing Geom::PathVector const original_pathv = curve->get_pathvector(); - curve->reset(); Inkscape::Preferences *prefs = Inkscape::Preferences::get(); for (Geom::PathVector::const_iterator path_it = original_pathv.begin(); @@ -99,20 +201,6 @@ void LPEBSpline::doEffect(SPCurve *curve) Geom::D2<Geom::SBasis> sbasis_out; Geom::D2<Geom::SBasis> sbasis_helper; Geom::CubicBezier const *cubic = NULL; - if (path_it->closed()) { - // if the path is closed, maybe we have to stop a bit earlier because the - // closing line segment has zerolength. - const Geom::Curve &closingline = - path_it->back_closed(); // the closing line segment is always of type - // Geom::LineSegment. - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - // closingline.isDegenerate() did not work, because it only checks for - // *exact* zero length, which goes wrong for relative coordinates and - // rounding errors... - // the closing line segment has zero-length. So stop before that one! - curve_endit = path_it->end_open(); - } - } curve_n->moveto(curve_it1->initialPoint()); while (curve_it1 != curve_endit) { SPCurve *in = new SPCurve(); @@ -209,12 +297,11 @@ void LPEBSpline::doEffect(SPCurve *curve) curve_n->curveto(point_at1, point_at2, node); } if(!are_near(node,curve_it1->finalPoint()) && helper_size > 0.0) { - drawHandle(node, helper_size); + sp_bspline_drawHandle(node, helper_size); } ++curve_it1; ++curve_it2; } - //y cerramos la curva if (path_it->closed()) { curve_n->closepath_current(); } @@ -228,8 +315,8 @@ void LPEBSpline::doEffect(SPCurve *curve) } } -void -LPEBSpline::drawHandle(Geom::Point p, double helper_size) + +void sp_bspline_drawHandle(Geom::Point p, double helper_size) { char const * svgd = "M 1,0.5 A 0.5,0.5 0 0 1 0.5,1 0.5,0.5 0 0 1 0,0.5 0.5,0.5 0 0 1 0.5,0 0.5,0.5 0 0 1 1,0.5 Z"; Geom::PathVector pathv = sp_svg_read_pathv(svgd); @@ -240,103 +327,6 @@ LPEBSpline::drawHandle(Geom::Point p, double helper_size) hp.push_back(pathv[0]); } -void -LPEBSpline::addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec) -{ - hp_vec.push_back(hp); -} -Gtk::Widget *LPEBSpline::newWidget() -{ - // 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); - std::vector<Parameter *>::iterator it = param_vector.begin(); - while (it != param_vector.end()) { - if ((*it)->widget_is_visible) { - Parameter *param = *it; - Gtk::Widget *widg = dynamic_cast<Gtk::Widget *>(param->param_newWidget()); - if (param->param_key == "weight") { - Gtk::HBox * buttons = Gtk::manage(new Gtk::HBox(true,0)); - Gtk::Button *default_weight = - Gtk::manage(new Gtk::Button(Glib::ustring(_("Default weight")))); - default_weight->signal_clicked() - .connect(sigc::mem_fun(*this, &LPEBSpline::toDefaultWeight)); - buttons->pack_start(*default_weight, true, true, 2); - Gtk::Button *make_cusp = - Gtk::manage(new Gtk::Button(Glib::ustring(_("Make cusp")))); - make_cusp->signal_clicked() - .connect(sigc::mem_fun(*this, &LPEBSpline::toMakeCusp)); - buttons->pack_start(*make_cusp, true, true, 2); - vbox->pack_start(*buttons, true, true, 2); - } - if (param->param_key == "weight" || param->param_key == "steps") { - Inkscape::UI::Widget::Scalar *widg_registered = - Gtk::manage(dynamic_cast<Inkscape::UI::Widget::Scalar *>(widg)); - widg_registered->signal_value_changed() - .connect(sigc::mem_fun(*this, &LPEBSpline::toWeight)); - widg = dynamic_cast<Gtk::Widget *>(widg_registered); - if (widg) { - Gtk::HBox * hbox_weight_steps = dynamic_cast<Gtk::HBox *>(widg); - std::vector< Gtk::Widget* > childList = hbox_weight_steps->get_children(); - Gtk::Entry* entry_widget = dynamic_cast<Gtk::Entry *>(childList[1]); - entry_widget->set_width_chars(6); - } - } - if (param->param_key == "only_selected") { - Gtk::CheckButton *widg_registered = - Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); - widg = dynamic_cast<Gtk::Widget *>(widg_registered); - } - if (param->param_key == "ignore_cusp") { - Gtk::CheckButton *widg_registered = - Gtk::manage(dynamic_cast<Gtk::CheckButton *>(widg)); - widg = dynamic_cast<Gtk::Widget *>(widg_registered); - } - 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; - } - return dynamic_cast<Gtk::Widget *>(vbox); -} - -void LPEBSpline::toDefaultWeight() -{ - changeWeight(DEFAULT_START_POWER); -} - -void LPEBSpline::toMakeCusp() -{ - changeWeight(NO_POWER); -} - -void LPEBSpline::toWeight() -{ - changeWeight(weight); -} - -void LPEBSpline::changeWeight(double weight_ammount) -{ - SPPath *path = dynamic_cast<SPPath *>(sp_lpe_item); - if(path) { - SPCurve *curve = path->get_curve_for_edit(); - doBSplineFromWidget(curve, weight_ammount); - gchar *str = sp_svg_write_path(curve->get_pathvector()); - path->getRepr()->setAttribute("inkscape:original-d", str); - } -} - void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weight_ammount) { using Geom::X; @@ -366,20 +356,6 @@ void LPEBSpline::doBSplineFromWidget(SPCurve *curve, double weight_ammount) Geom::D2<Geom::SBasis> sbasis_in; Geom::D2<Geom::SBasis> sbasis_out; Geom::CubicBezier const *cubic = NULL; - if (path_it->closed()) { - // if the path is closed, maybe we have to stop a bit earlier because the - // closing line segment has zerolength. - const Geom::Curve &closingline = - path_it->back_closed(); // the closing line segment is always of type - // Geom::LineSegment. - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - // closingline.isDegenerate() did not work, because it only checks for - // *exact* zero length, which goes wrong for relative coordinates and - // rounding errors... - // the closing line segment has zero-length. So stop before that one! - curve_endit = path_it->end_open(); - } - } curve_n->moveto(curve_it1->initialPoint()); while (curve_it1 != curve_endit) { SPCurve *in = new SPCurve(); diff --git a/src/live_effects/lpe-bspline.h b/src/live_effects/lpe-bspline.h index fc0f66353..033e85cf0 100644 --- a/src/live_effects/lpe-bspline.h +++ b/src/live_effects/lpe-bspline.h @@ -25,14 +25,13 @@ public: virtual void doOnApply(SPLPEItem const* lpeitem); virtual void doEffect(SPCurve *curve); virtual void doBeforeEffect (SPLPEItem const* lpeitem); - void drawHandle(Geom::Point p, double radiusHelperNodes); - virtual void doBSplineFromWidget(SPCurve *curve, double value); + void doBSplineFromWidget(SPCurve *curve, double value); void addCanvasIndicators(SPLPEItem const */*lpeitem*/, std::vector<Geom::PathVector> &hp_vec); virtual Gtk::Widget *newWidget(); - virtual void changeWeight(double weightValue); - virtual void toDefaultWeight(); - virtual void toMakeCusp(); - virtual void toWeight(); + void changeWeight(double weightValue); + void toDefaultWeight(); + void toMakeCusp(); + void toWeight(); // TODO make this private ScalarParam steps; @@ -42,12 +41,12 @@ private: BoolParam ignore_cusp; BoolParam only_selected; ScalarParam weight; - Geom::PathVector hp; LPEBSpline(const LPEBSpline &); LPEBSpline &operator=(const LPEBSpline &); }; +void sp_bspline_do_effect(SPCurve *curve, double helper_size); } //namespace LivePathEffect } //namespace Inkscape diff --git a/src/live_effects/lpe-simplify.cpp b/src/live_effects/lpe-simplify.cpp index 265192a17..f6842a030 100644 --- a/src/live_effects/lpe-simplify.cpp +++ b/src/live_effects/lpe-simplify.cpp @@ -82,6 +82,7 @@ LPESimplify::newWidget() { // 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); diff --git a/src/live_effects/lpe-spiro.cpp b/src/live_effects/lpe-spiro.cpp index eefd25c7d..0d42596b2 100644 --- a/src/live_effects/lpe-spiro.cpp +++ b/src/live_effects/lpe-spiro.cpp @@ -37,6 +37,10 @@ LPESpiro::~LPESpiro() void LPESpiro::doEffect(SPCurve * curve) { + sp_spiro_do_effect(curve); +} + +void sp_spiro_do_effect(SPCurve *curve){ using Geom::X; using Geom::Y; @@ -54,7 +58,7 @@ LPESpiro::doEffect(SPCurve * curve) // start of path { - Geom::Point p = path_it->front().pointAt(0); + Geom::Point p = path_it->initialPoint(); path[ip].x = p[X]; path[ip].y = p[Y]; path[ip].ty = '{' ; // for closed paths, this is overwritten @@ -64,17 +68,7 @@ LPESpiro::doEffect(SPCurve * curve) // midpoints Geom::Path::const_iterator curve_it1 = path_it->begin(); // incoming curve Geom::Path::const_iterator curve_it2 = ++(path_it->begin()); // outgoing curve - Geom::Path::const_iterator curve_endit = path_it->end_default(); // this determines when the loop has to stop - if (path_it->closed()) { - // if the path is closed, maybe we have to stop a bit earlier because the closing line segment has zerolength. - const Geom::Curve &closingline = path_it->back_closed(); // the closing line segment is always of type Geom::LineSegment. - if (are_near(closingline.initialPoint(), closingline.finalPoint())) { - // closingline.isDegenerate() did not work, because it only checks for *exact* zero length, which goes wrong for relative coordinates and rounding errors... - // the closing line segment has zero-length. So stop before that one! - curve_endit = path_it->end_open(); - } - } while ( curve_it2 != curve_endit ) { diff --git a/src/live_effects/lpe-spiro.h b/src/live_effects/lpe-spiro.h index edce42280..c8aba53d9 100644 --- a/src/live_effects/lpe-spiro.h +++ b/src/live_effects/lpe-spiro.h @@ -27,6 +27,8 @@ private: LPESpiro& operator=(const LPESpiro&); }; +void sp_spiro_do_effect(SPCurve *curve); + }; //namespace LivePathEffect }; //namespace Inkscape diff --git a/src/live_effects/spiro-converters.cpp b/src/live_effects/spiro-converters.cpp index f116d5256..ee214704c 100644 --- a/src/live_effects/spiro-converters.cpp +++ b/src/live_effects/spiro-converters.cpp @@ -21,43 +21,49 @@ namespace Spiro {
void
-ConverterSPCurve::moveto(double x, double y, bool is_open)
+ConverterSPCurve::moveto(double x, double y)
{
if ( IS_FINITE(x) && IS_FINITE(y) ) {
_curve.moveto(x, y);
- if (!is_open) {
- _curve.closepath();
- }
} else {
SPIRO_G_MESSAGE("Spiro: moveto not finite");
}
}
void
-ConverterSPCurve::lineto(double x, double y)
+ConverterSPCurve::lineto(double x, double y, bool close_last)
{
if ( IS_FINITE(x) && IS_FINITE(y) ) {
_curve.lineto(x, y);
+ if (close_last) {
+ _curve.closepath();
+ }
} else {
SPIRO_G_MESSAGE("Spiro: lineto not finite");
}
}
void
-ConverterSPCurve::quadto(double xm, double ym, double x3, double y3)
+ConverterSPCurve::quadto(double xm, double ym, double x3, double y3, bool close_last)
{
if ( IS_FINITE(xm) && IS_FINITE(ym) && IS_FINITE(x3) && IS_FINITE(y3) ) {
_curve.quadto(xm, ym, x3, y3);
+ if (close_last) {
+ _curve.closepath();
+ }
} else {
SPIRO_G_MESSAGE("Spiro: quadto not finite");
}
}
void
-ConverterSPCurve::curveto(double x1, double y1, double x2, double y2, double x3, double y3)
+ConverterSPCurve::curveto(double x1, double y1, double x2, double y2, double x3, double y3, bool close_last)
{
if ( IS_FINITE(x1) && IS_FINITE(y1) && IS_FINITE(x2) && IS_FINITE(y2) ) {
_curve.curveto(x1, y1, x2, y2, x3, y3);
+ if (close_last) {
+ _curve.closepath();
+ }
} else {
SPIRO_G_MESSAGE("Spiro: curveto not finite");
}
@@ -71,41 +77,43 @@ ConverterPath::ConverterPath(Geom::Path &path) }
void
-ConverterPath::moveto(double x, double y, bool is_open)
+ConverterPath::moveto(double x, double y)
{
if ( IS_FINITE(x) && IS_FINITE(y) ) {
_path.start(Geom::Point(x, y));
- _path.close(!is_open);
} else {
SPIRO_G_MESSAGE("spiro moveto not finite");
}
}
void
-ConverterPath::lineto(double x, double y)
+ConverterPath::lineto(double x, double y, bool close_last)
{
if ( IS_FINITE(x) && IS_FINITE(y) ) {
_path.appendNew<Geom::LineSegment>( Geom::Point(x, y) );
+ _path.close(close_last);
} else {
SPIRO_G_MESSAGE("spiro lineto not finite");
}
}
void
-ConverterPath::quadto(double xm, double ym, double x3, double y3)
+ConverterPath::quadto(double xm, double ym, double x3, double y3, bool close_last)
{
if ( IS_FINITE(xm) && IS_FINITE(ym) && IS_FINITE(x3) && IS_FINITE(y3) ) {
_path.appendNew<Geom::QuadraticBezier>(Geom::Point(xm, ym), Geom::Point(x3, y3));
+ _path.close(close_last);
} else {
SPIRO_G_MESSAGE("spiro quadto not finite");
}
}
void
-ConverterPath::curveto(double x1, double y1, double x2, double y2, double x3, double y3)
+ConverterPath::curveto(double x1, double y1, double x2, double y2, double x3, double y3, bool close_last)
{
if ( IS_FINITE(x1) && IS_FINITE(y1) && IS_FINITE(x2) && IS_FINITE(y2) ) {
_path.appendNew<Geom::CubicBezier>(Geom::Point(x1, y1), Geom::Point(x2, y2), Geom::Point(x3, y3));
+ _path.close(close_last);
} else {
SPIRO_G_MESSAGE("spiro curveto not finite");
}
diff --git a/src/live_effects/spiro-converters.h b/src/live_effects/spiro-converters.h index 90855d2d6..6182a5dcd 100644 --- a/src/live_effects/spiro-converters.h +++ b/src/live_effects/spiro-converters.h @@ -11,10 +11,10 @@ public: ConverterBase() {}; virtual ~ConverterBase() {}; - virtual void moveto(double x, double y, bool is_open) = 0; - virtual void lineto(double x, double y) = 0; - virtual void quadto(double x1, double y1, double x2, double y2) = 0; - virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3) = 0; + virtual void moveto(double x, double y) = 0; + virtual void lineto(double x, double y, bool close_last) = 0; + virtual void quadto(double x1, double y1, double x2, double y2, bool close_last) = 0; + virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3, bool close_last) = 0; }; @@ -27,10 +27,10 @@ public: : _curve(curve) {} - virtual void moveto(double x, double y, bool is_open); - virtual void lineto(double x, double y); - virtual void quadto(double x1, double y1, double x2, double y2); - virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3); + virtual void moveto(double x, double y); + virtual void lineto(double x, double y, bool close_last); + virtual void quadto(double x1, double y1, double x2, double y2, bool close_last); + virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3, bool close_last); private: SPCurve &_curve; @@ -47,10 +47,10 @@ class ConverterPath : public ConverterBase { public: ConverterPath(Geom::Path &path); - virtual void moveto(double x, double y, bool is_open); - virtual void lineto(double x, double y); - virtual void quadto(double x1, double y1, double x2, double y2); - virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3); + virtual void moveto(double x, double y); + virtual void lineto(double x, double y, bool close_last); + virtual void quadto(double x1, double y1, double x2, double y2, bool close_last); + virtual void curveto(double x1, double y1, double x2, double y2, double x3, double y3, bool close_last); private: Geom::Path &_path; diff --git a/src/live_effects/spiro.cpp b/src/live_effects/spiro.cpp index 46e53a0da..0ac2815bf 100644 --- a/src/live_effects/spiro.cpp +++ b/src/live_effects/spiro.cpp @@ -847,13 +847,13 @@ solve_spiro(spiro_seg *s, const int nseg) static void spiro_seg_to_otherpath(const double ks[4], double x0, double y0, double x1, double y1, - ConverterBase &bc, int depth) + ConverterBase &bc, int depth, bool close_last) { double bend = fabs(ks[0]) + fabs(.5 * ks[1]) + fabs(.125 * ks[2]) + fabs((1./48) * ks[3]); if (!(bend > 1e-8)) { - bc.lineto(x1, y1); + bc.lineto(x1, y1, close_last); } else { double seg_ch = hypot(x1 - x0, y1 - y0); double seg_th = atan2(y1 - y0, x1 - x0); @@ -876,7 +876,7 @@ spiro_seg_to_otherpath(const double ks[4], vl = (scale * (1./3)) * sin(th_even - th_odd); ur = (scale * (1./3)) * cos(th_even + th_odd); vr = (scale * (1./3)) * sin(th_even + th_odd); - bc.curveto(x0 + ul, y0 + vl, x1 - ur, y1 - vr, x1, y1); + bc.curveto(x0 + ul, y0 + vl, x1 - ur, y1 - vr, x1, y1, close_last); } else { /* subdivide */ double ksub[4]; @@ -895,11 +895,11 @@ spiro_seg_to_otherpath(const double ks[4], integrate_spiro(ksub, xysub); xmid = x0 + cth * xysub[0] - sth * xysub[1]; ymid = y0 + cth * xysub[1] + sth * xysub[0]; - spiro_seg_to_otherpath(ksub, x0, y0, xmid, ymid, bc, depth + 1); + spiro_seg_to_otherpath(ksub, x0, y0, xmid, ymid, bc, depth + 1, false); ksub[0] += .25 * ks[1] + (1./384) * ks[3]; ksub[1] += .125 * ks[2]; ksub[2] += (1./16) * ks[3]; - spiro_seg_to_otherpath(ksub, xmid, ymid, x1, y1, bc, depth + 1); + spiro_seg_to_otherpath(ksub, xmid, ymid, x1, y1, bc, depth + 1, close_last); } } } @@ -933,9 +933,10 @@ spiro_to_otherpath(const spiro_seg *s, int n, ConverterBase &bc) double y1 = s[i + 1].y; if (i == 0) { - bc.moveto(x0, y0, s[0].ty == '{'); + bc.moveto(x0, y0); } - spiro_seg_to_otherpath(s[i].ks, x0, y0, x1, y1, bc, 0); + // on the last segment, set the 'close_last' flag if path is closed + spiro_seg_to_otherpath(s[i].ks, x0, y0, x1, y1, bc, 0, (nsegs == n) && (i == n - 1)); } } |
