summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLiam P. White <inkscapebronyat-signgmaildotcom>2014-04-02 21:18:40 +0000
committerLiam P. White <inkscapebronyat-signgmaildotcom>2014-04-02 21:18:40 +0000
commitd20b73d611b6de99e0e0697ee47a760de437ee97 (patch)
tree3069592be43d6d60466d6ba0bb418a7f5ed11bd1 /src
parentFix some stuff (diff)
downloadinkscape-d20b73d611b6de99e0e0697ee47a760de437ee97.tar.gz
inkscape-d20b73d611b6de99e0e0697ee47a760de437ee97.zip
Clean up code
(bzr r13090.1.42)
Diffstat (limited to 'src')
-rw-r--r--[-rwxr-xr-x]src/live_effects/lpe-taperstroke.cpp905
-rw-r--r--src/live_effects/lpe-taperstroke.h48
-rw-r--r--[-rwxr-xr-x]src/live_effects/pathoutlineprovider.cpp521
-rw-r--r--src/live_effects/pathoutlineprovider.h16
4 files changed, 765 insertions, 725 deletions
diff --git a/src/live_effects/lpe-taperstroke.cpp b/src/live_effects/lpe-taperstroke.cpp
index b4e43209d..97ae02e3b 100755..100644
--- a/src/live_effects/lpe-taperstroke.cpp
+++ b/src/live_effects/lpe-taperstroke.cpp
@@ -38,26 +38,27 @@ namespace Inkscape {
namespace LivePathEffect {
namespace TpS {
- class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity {
- public:
- KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual Geom::Point knot_get() const;
- };
- class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity {
- public:
- KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
- virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
- virtual Geom::Point knot_get() const;
- };
+ class KnotHolderEntityAttachBegin : public LPEKnotHolderEntity {
+ public:
+ KnotHolderEntityAttachBegin(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ };
+
+ class KnotHolderEntityAttachEnd : public LPEKnotHolderEntity {
+ public:
+ KnotHolderEntityAttachEnd(LPETaperStroke * effect) : LPEKnotHolderEntity(effect) {}
+ virtual void knot_set(Geom::Point const &p, Geom::Point const &origin, guint state);
+ virtual Geom::Point knot_get() const;
+ };
} // TpS
static const Util::EnumData<unsigned> JoinType[] = {
- {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
- {LINEJOIN_ROUND, N_("Rounded"), "round"},
- {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"},
- {LINEJOIN_POINTY, N_("Miter"), "miter"},
- {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"}
+ {LINEJOIN_STRAIGHT, N_("Beveled"), "bevel"},
+ {LINEJOIN_ROUND, N_("Rounded"), "round"},
+ {LINEJOIN_REFLECTED, N_("Reflected"), "reflected"},
+ {LINEJOIN_POINTY, N_("Miter"), "miter"},
+ {LINEJOIN_EXTRAPOLATED, N_("Extrapolated"), "extrapolated"}
};
static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeof (JoinType)/sizeof(*JoinType));
@@ -65,31 +66,30 @@ static const Util::EnumDataConverter<unsigned> JoinTypeConverter(JoinType, sizeo
LPETaperStroke::LPETaperStroke(LivePathEffectObject *lpeobject) :
Effect(lpeobject),
line_width(_("Stroke width"), _("The (non-tapered) width of the path"), "stroke_width", &wr, this, 3),
- attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2),
- attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2),
- smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5),
- join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
- miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.)
+ attach_start(_("Start offset"), _("Taper distance from path start"), "attach_start", &wr, this, 0.2),
+ attach_end(_("End offset"), _("The ending position of the taper"), "end_offset", &wr, this, 0.2),
+ smoothing(_("Taper smoothing"), _("Amount of smoothing to apply to the tapers"), "smoothing", &wr, this, 0.5),
+ join_type(_("Join type"), _("Join type for non-smooth nodes"), "jointype", JoinTypeConverter, &wr, this, LINEJOIN_EXTRAPOLATED),
+ miter_limit(_("Miter limit"), _("Limit for miter joins"), "miter_limit", &wr, this, 30.)
{
- /* uncomment the following line to have the original path displayed while the item is selected */
show_orig_path = true;
- _provides_knotholder_entities = true;
-
- attach_start.param_set_digits(3);
- attach_end.param_set_digits(3);
-
-
- registerParameter( dynamic_cast<Parameter *>(&line_width) );
- registerParameter( dynamic_cast<Parameter *>(&attach_start) );
- registerParameter( dynamic_cast<Parameter *>(&attach_end) );
- registerParameter( dynamic_cast<Parameter *>(&smoothing) );
- registerParameter( dynamic_cast<Parameter *>(&join_type) );
- registerParameter( dynamic_cast<Parameter *>(&miter_limit) );
+ _provides_knotholder_entities = true;
+
+ attach_start.param_set_digits(3);
+ attach_end.param_set_digits(3);
+
+
+ registerParameter( dynamic_cast<Parameter *>(&line_width) );
+ registerParameter( dynamic_cast<Parameter *>(&attach_start) );
+ registerParameter( dynamic_cast<Parameter *>(&attach_end) );
+ registerParameter( dynamic_cast<Parameter *>(&smoothing) );
+ registerParameter( dynamic_cast<Parameter *>(&join_type) );
+ registerParameter( dynamic_cast<Parameter *>(&miter_limit) );
}
LPETaperStroke::~LPETaperStroke()
{
-
+
}
//from LPEPowerStroke -- sets fill if stroke color because we will
@@ -97,10 +97,10 @@ LPETaperStroke::~LPETaperStroke()
void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
{
- if (SP_IS_SHAPE(lpeitem)) {
+ if (SP_IS_SHAPE(lpeitem)) {
SPLPEItem* item = const_cast<SPLPEItem*>(lpeitem);
double width = (lpeitem && lpeitem->style) ? lpeitem->style->stroke_width.computed : 1.;
-
+
SPCSSAttr *css = sp_repr_css_attr_new ();
if (lpeitem->style->stroke.isSet()) {
if (lpeitem->style->stroke.isPaintserver()) {
@@ -122,13 +122,13 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
} else {
sp_repr_css_unset_property (css, "fill");
}
-
+
sp_repr_css_set_property(css, "stroke", "none");
-
+
sp_desktop_apply_css_recursive(item, css, true);
sp_repr_css_attr_unref (css);
- line_width.param_set_value(width);
+ line_width.param_set_value(width);
} else {
g_warning("LPE Join Type can only be applied to paths (not groups).");
}
@@ -138,8 +138,10 @@ void LPETaperStroke::doOnApply(SPLPEItem const* lpeitem)
void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
{
-
- if (SP_IS_SHAPE(lpeitem)) {
+
+ if (SP_IS_SHAPE(lpeitem)) {
+ //TODO: make it getobjbyrepr instead of const_cast because this can cause
+ //undefined behavior
SPLPEItem *item = const_cast<SPLPEItem*>(lpeitem);
SPCSSAttr *css = sp_repr_css_attr_new ();
@@ -164,7 +166,7 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
sp_repr_css_unset_property (css, "stroke");
}
- Inkscape::CSSOStringStream os;
+ Inkscape::CSSOStringStream os;
os << fabs(line_width);
sp_repr_css_set_property (css, "stroke-width", os.str().c_str());
@@ -173,335 +175,347 @@ void LPETaperStroke::doOnRemove(SPLPEItem const* lpeitem)
sp_desktop_apply_css_recursive(item, css, true);
sp_repr_css_attr_unref (css);
item->updateRepr();
- }
+ }
}
//actual effect impl here
Geom::Path return_at_first_cusp (Geom::Path const & path_in, double smooth_tolerance = 0.05)
{
- Geom::Path path_out = Geom::Path();
-
- for (unsigned i = 0; i < path_in.size(); i++)
- {
- path_out.append(path_in[i]);
- if (path_in.size() == 1)
- break;
-
- //determine order of curve
- int order = Outline::bezierOrder(&path_in[i]);
-
- Geom::Point start_point;
- Geom::Point cross_point = path_in[i].finalPoint();
- Geom::Point end_point;
-
- g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint());
-
- //can you tell that the following expressions have been shaped by
- //repeated compiler errors? ;)
- switch (order)
- {
- case 3:
- start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (2);
- //major league b***f***ing
- if (are_near(start_point, cross_point, 0.0000001)) {
- start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (1);
- }
- break;
- case 2:
- //this never happens
- start_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i]))->operator[] (1);
- break;
- case 1:
- default:
- start_point = path_in[i].initialPoint();
- }
-
- order = Outline::bezierOrder(&path_in[i+1]);
-
- switch (order)
- {
- case 3:
- end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (1);
- if (are_near(end_point, cross_point, 0.0000001)) {
- end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (2);
- }
- break;
- case 2:
- end_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i+1]))->operator[] (1);
- break;
- case 1:
- default:
- end_point = path_in[i+1].finalPoint();
- }
-
- g_assert(!are_near(start_point, cross_point, 0.0000001)); //take that motherf*ckers
- g_assert(!are_near(cross_point, end_point, 0.0000001));
- g_assert(!are_near(start_point, end_point, 0.0000001));
-
- if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance))
- break;
- }
- return path_out;
+ Geom::Path path_out = Geom::Path();
+
+ for (unsigned i = 0; i < path_in.size(); i++) {
+ path_out.append(path_in[i]);
+ if (path_in.size() == 1)
+ break;
+
+ //determine order of curve
+ int order = Outline::bezierOrder(&path_in[i]);
+
+ Geom::Point start_point;
+ Geom::Point cross_point = path_in[i].finalPoint();
+ Geom::Point end_point;
+
+ g_assert(path_in[i].finalPoint() == path_in[i+1].initialPoint());
+
+ //can you tell that the following expressions have been shaped by
+ //repeated compiler errors? ;)
+ switch (order) {
+ case 3:
+ start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (2);
+ //major league b***f***ing
+ if (are_near(start_point, cross_point, 0.0000001)) {
+ start_point = (static_cast<const Geom::CubicBezier*>(&path_in[i]))->operator[] (1);
+ }
+ break;
+ case 2:
+ //this never happens
+ start_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i]))->operator[] (1);
+ break;
+ case 1:
+ default:
+ start_point = path_in[i].initialPoint();
+ }
+
+ order = Outline::bezierOrder(&path_in[i+1]);
+
+ switch (order) {
+ case 3:
+ end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (1);
+ if (are_near(end_point, cross_point, 0.0000001)) {
+ end_point = (static_cast<const Geom::CubicBezier*>(&path_in[i+1]))->operator[] (2);
+ }
+ break;
+ case 2:
+ end_point = (static_cast<const Geom::QuadraticBezier*>(&path_in[i+1]))->operator[] (1);
+ break;
+ case 1:
+ default:
+ end_point = path_in[i+1].finalPoint();
+ }
+
+ //clearly it's collinear if two occupy the same point
+ g_assert(!are_near(start_point, cross_point, 0.0000001));
+ g_assert(!are_near(cross_point, end_point, 0.0000001));
+ g_assert(!are_near(start_point, end_point, 0.0000001));
+
+ if (!are_collinear(start_point, cross_point, end_point, smooth_tolerance))
+ break;
+ }
+ return path_out;
}
Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double width);
+//references to pointers, because magic
+void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second);
Geom::PathVector LPETaperStroke::doEffect_path(Geom::PathVector const& path_in)
{
- Geom::Path first_cusp = return_at_first_cusp(path_in[0]);
- Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse());
-
- bool zeroStart = false;
- bool zeroEnd = false;
- //there is a pretty good chance that people will try to drag the knots
- //on top of each other, so block it
-
- unsigned size = path_in[0].size();
- if (size == first_cusp.size()) {
- //check to see if the knots were dragged over each other
- //if so, reset the end offset
- if ( attach_start >= (size - attach_end) ) {
- attach_end.param_set_value( size - attach_start );
- }
- }
-
- //don't ever let it be zero
- if (attach_start <= 0.00000001) {
- attach_start.param_set_value( 0.00000001 );
- zeroStart = true;
- }
- if (attach_end <= 0.00000001) {
- attach_end.param_set_value( 0.00000001 );
- zeroEnd = true;
- }
-
- //don't let it be integer
- if (double(unsigned(attach_start)) == attach_start) {
- attach_start.param_set_value(attach_start - 0.00001);
- }
- if (double(unsigned(attach_end)) == attach_end) {
- attach_end.param_set_value(attach_end - 0.00001);
- }
-
- unsigned allowed_start = first_cusp.size();
- unsigned allowed_end = last_cusp.size();
-
- //don't let the knots be farther than they are allowed to be
- if ((unsigned)attach_start >= allowed_start) {
- attach_start.param_set_value((double)allowed_start - 0.00000001);
- }
- if ((unsigned)attach_end >= allowed_end) {
- attach_end.param_set_value((double)allowed_end - 0.00000001);
- }
-
- //remember, Path::operator () means get point at time t
- start_attach_point = first_cusp(attach_start);
- end_attach_point = last_cusp(attach_end);
- Geom::PathVector pathv_out;
-
- //the following function just splits it up into three pieces.
- pathv_out = doEffect_simplePath(path_in);
-
- //now for the actual tapering. We use a Pattern Along Path method to get this done.
-
- Geom::PathVector real_pathv;
- Geom::Path real_path;
- Geom::PathVector pat_vec;
- Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2;
- Geom::Path throwaway_path;
-
- if (!zeroStart) {
- //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me)
- std::stringstream pat_str;
- pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1";
-
- pat_vec = sp_svg_read_pathv(pat_str.str().c_str());
- pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width)));
- throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0];
-
- real_path.append(throwaway_path);
- }
- //append the outside outline of the path (with direction)
- throwaway_path = Outline::PathOutsideOutline(pathv_out[1],
- -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
-
- if (!zeroStart) {
- throwaway_path.setInitial(real_path.finalPoint());
- real_path.append(throwaway_path);
- } else {
- real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
- }
-
- if (!zeroEnd) {
- //append the ending taper
- std::stringstream pat_str_1;
- pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0";
- pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str());
-
- pwd2 = Geom::Piecewise<Geom::D2<Geom::SBasis> > ();
- pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width)));
-
- throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0];
- throwaway_path.setInitial(real_path.finalPoint());
- real_path.append(throwaway_path);
- }
- //append the inside outline of the path (against direction)
- throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(),
- -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
-
- if (!zeroEnd) {
- //throwaway_path.setInitial(real_path.finalPoint());
- real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
- } else {
- real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
- }
- real_path.close();
-
- real_pathv.push_back(real_path);
-
- return real_pathv;
+ Geom::Path first_cusp = return_at_first_cusp(path_in[0]);
+ Geom::Path last_cusp = return_at_first_cusp(path_in[0].reverse());
+
+ bool zeroStart = false;
+ bool zeroEnd = false;
+ //there is a pretty good chance that people will try to drag the knots
+ //on top of each other, so block it
+
+ unsigned size = path_in[0].size();
+ if (size == first_cusp.size()) {
+ //check to see if the knots were dragged over each other
+ //if so, reset the end offset
+ if ( attach_start >= (size - attach_end) ) {
+ attach_end.param_set_value( size - attach_start );
+ }
+ }
+
+ //don't ever let it be zero
+ if (attach_start <= 0.00000001) {
+ attach_start.param_set_value( 0.00000001 );
+ zeroStart = true;
+ }
+ if (attach_end <= 0.00000001) {
+ attach_end.param_set_value( 0.00000001 );
+ zeroEnd = true;
+ }
+
+ //don't let it be integer
+ if (double(unsigned(attach_start)) == attach_start) {
+ attach_start.param_set_value(attach_start - 0.00001);
+ }
+ if (double(unsigned(attach_end)) == attach_end) {
+ attach_end.param_set_value(attach_end - 0.00001);
+ }
+
+ unsigned allowed_start = first_cusp.size();
+ unsigned allowed_end = last_cusp.size();
+
+ //don't let the knots be farther than they are allowed to be
+ if ((unsigned)attach_start >= allowed_start) {
+ attach_start.param_set_value((double)allowed_start - 0.00000001);
+ }
+ if ((unsigned)attach_end >= allowed_end) {
+ attach_end.param_set_value((double)allowed_end - 0.00000001);
+ }
+
+ //remember, Path::operator () means get point at time t
+ start_attach_point = first_cusp(attach_start);
+ end_attach_point = last_cusp(attach_end);
+ Geom::PathVector pathv_out;
+
+ //the following function just splits it up into three pieces.
+ pathv_out = doEffect_simplePath(path_in);
+
+ //now for the actual tapering. We use a Pattern Along Path method to get this done.
+
+ Geom::PathVector real_pathv;
+ Geom::Path real_path;
+ Geom::PathVector pat_vec;
+ Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2;
+ Geom::Path throwaway_path;
+
+ if (!zeroStart) {
+ //Construct the pattern (pat_str stands for pattern string) (yes, this is easier, trust me)
+ std::stringstream pat_str;
+ pat_str << "M 1,0 C " << 1 - (double)smoothing << ",0 0,0.5 0,0.5 0,0.5 " << 1 - (double)smoothing << ",1 1,1";
+
+ pat_vec = sp_svg_read_pathv(pat_str.str().c_str());
+ pwd2.concat(stretch_along(pathv_out[0].toPwSb(), pat_vec[0], -fabs(line_width)));
+ throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0];
+
+ real_path.append(throwaway_path);
+ }
+ //append the outside outline of the path (with direction)
+ throwaway_path = Outline::PathOutsideOutline(pathv_out[1],
+ -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+
+ if (!zeroStart) {
+ throwaway_path.setInitial(real_path.finalPoint());
+ real_path.append(throwaway_path);
+ } else {
+ real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
+ }
+
+ if (!zeroEnd) {
+ //append the ending taper
+ std::stringstream pat_str_1;
+ pat_str_1 << "M 0,0 0,1 C " << (double)smoothing << ",1 1,0.5 1,0.5 1,0.5 " << double(smoothing) << ",0 0,0";
+ pat_vec = sp_svg_read_pathv(pat_str_1.str().c_str());
+
+ pwd2 = Geom::Piecewise<Geom::D2<Geom::SBasis> > ();
+ pwd2.concat(stretch_along(pathv_out[2].toPwSb(), pat_vec[0], -fabs(line_width)));
+
+ throwaway_path = Geom::path_from_piecewise(pwd2, 0.001)[0];
+ throwaway_path.setInitial(real_path.finalPoint());
+ real_path.append(throwaway_path);
+ }
+ //append the inside outline of the path (against direction)
+ throwaway_path = Outline::PathOutsideOutline(pathv_out[1].reverse(),
+ -fabs(line_width), static_cast<LineJoinType>(join_type.get_value()), miter_limit);
+
+ if (!zeroEnd) {
+ //throwaway_path.setInitial(real_path.finalPoint());
+ real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
+ } else {
+ real_path.append(throwaway_path, Geom::Path::STITCH_DISCONTINUOUS);
+ }
+
+ //hmm
+ real_path.setFinal(real_path.initialPoint());
+
+ real_path.close();
+
+ real_pathv.push_back(real_path);
+
+ return real_pathv;
}
//in all cases, this should return a PathVector with three elements.
Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & path_in)
{
- unsigned size = path_in[0].size();
-
- //do subdivision and get out
- unsigned loc = (unsigned)attach_start;
- Geom::Curve * curve_start = path_in[0] [loc].duplicate();
-
- std::vector<Geom::Path> pathv_out;
- Geom::Path path_out = Geom::Path();
-
- Geom::Path trimmed_start = Geom::Path();
- Geom::Path trimmed_end = Geom::Path();
-
- for (unsigned i = 0; i < loc; i++) {
- trimmed_start.append(path_in[0] [i]);
- }
-
-
- //this is pretty annoying
- //previously I wrote a function for this but it wasted a lot of time
- //so I optimized it back into here.
- unsigned order = Outline::bezierOrder(curve_start);
- switch (order) {
- case 3: {
- Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start);
- std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide((attach_start - loc));
- trimmed_start.append(cb_pair.first); curve_start = cb_pair.second.duplicate(); //goes out of scope
- break;
- }
- case 2: {
- Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start);
- std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide((attach_start - loc));
- trimmed_start.append(qb_pair.first); curve_start = qb_pair.second.duplicate();
- break;
- }
- case 1: {
- Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start);
- std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc));
- trimmed_start.append(lb_pair.first); curve_start = lb_pair.second.duplicate();
- break;
- }
- }
-
- //special case: path is one segment long
- //special case: what if the two knots occupy the same segment?
- if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc ))
- {
- Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start);
-
- //it is just a dumb segment
- //we have to do some shifting here because the value changed when we reduced the length
- //of the previous segment.
-
- order = Outline::bezierOrder(curve_start);
- switch (order) {
- case 3: {
- Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start);
- std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t);
- trimmed_end.append(cb_pair.second); curve_start = cb_pair.first.duplicate();
- break;
- }
- case 2: {
- Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start);
- std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t);
- trimmed_end.append(qb_pair.second); curve_start = qb_pair.first.duplicate();
- break;
- }
- case 1: {
- Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start);
- std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t);
- trimmed_end.append(lb_pair.second); curve_start = lb_pair.first.duplicate();
- break;
- }
- }
-
- for (unsigned j = (size - attach_end) + 1; j < size; j++) {
- trimmed_end.append(path_in[0] [j]);
- }
-
- path_out.append(*curve_start);
- pathv_out.push_back(trimmed_start);
- pathv_out.push_back(path_out);
- pathv_out.push_back(trimmed_end);
- return pathv_out;
- }
-
- pathv_out.push_back(trimmed_start);
-
- //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute)
- path_out.append(*curve_start);
-
- for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) {
- path_out.append(path_in[0] [k]);
- }
-
- //deal with the last segment in a very similar fashion to the first
- loc = size - attach_end;
-
- Geom::Curve * curve_end = path_in[0] [loc].duplicate();
-
- Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end);
-
- order = Outline::bezierOrder(curve_end);
- switch (order) {
- case 3: {
- Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_end);
- std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t);
- trimmed_end.append(cb_pair.second); curve_end = cb_pair.first.duplicate();
- break;
- }
- case 2: {
- Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_end);
- std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t);
- trimmed_end.append(qb_pair.second); curve_end = qb_pair.first.duplicate();
- break;
- }
- case 1: {
- Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_end);
- std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t);
- trimmed_end.append(lb_pair.second); curve_end = lb_pair.first.duplicate();
- break;
- }
- }
-
- for (unsigned j = (size - attach_end) + 1; j < size; j++) {
- trimmed_end.append(path_in[0] [j]);
- }
-
- path_out.append(*curve_end);
- pathv_out.push_back(path_out);
-
- pathv_out.push_back(trimmed_end);
-
- if (curve_end) delete curve_end;
- if (curve_start) delete curve_start;
- return pathv_out;
+ unsigned size = path_in[0].size();
+
+ //do subdivision and get out
+ unsigned loc = (unsigned)attach_start;
+ Geom::Curve * curve_start = path_in[0] [loc].duplicate();
+
+ std::vector<Geom::Path> pathv_out;
+ Geom::Path path_out = Geom::Path();
+
+ Geom::Path trimmed_start = Geom::Path();
+ Geom::Path trimmed_end = Geom::Path();
+
+ for (unsigned i = 0; i < loc; i++) {
+ trimmed_start.append(path_in[0] [i]);
+ }
+
+
+ //this is pretty annoying
+ //previously I wrote a function for this but it wasted a lot of time
+ //so I optimized it back into here.
+ unsigned order = Outline::bezierOrder(curve_start);
+ switch (order) {
+ case 3: {
+ Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start);
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide((attach_start - loc));
+ trimmed_start.append(cb_pair.first);
+ curve_start = cb_pair.second.duplicate(); //goes out of scope
+ break;
+ }
+ case 2: {
+ Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start);
+ std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide((attach_start - loc));
+ trimmed_start.append(qb_pair.first);
+ curve_start = qb_pair.second.duplicate();
+ break;
+ }
+ case 1: {
+ Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start);
+ std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide((attach_start - loc));
+ trimmed_start.append(lb_pair.first);
+ curve_start = lb_pair.second.duplicate();
+ break;
+ }
+ }
+
+ //special case: path is one segment long
+ //special case: what if the two knots occupy the same segment?
+ if ((size == 1) || ( size - unsigned(attach_end) - 1 == loc )) {
+ Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_start);
+
+ //it is just a dumb segment
+ //we have to do some shifting here because the value changed when we reduced the length
+ //of the previous segment.
+
+ order = Outline::bezierOrder(curve_start);
+ switch (order) {
+ case 3: {
+ Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_start);
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t);
+ trimmed_end.append(cb_pair.second);
+ curve_start = cb_pair.first.duplicate();
+ break;
+ }
+ case 2: {
+ Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_start);
+ std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t);
+ trimmed_end.append(qb_pair.second);
+ curve_start = qb_pair.first.duplicate();
+ break;
+ }
+ case 1: {
+ Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_start);
+ std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t);
+ trimmed_end.append(lb_pair.second);
+ curve_start = lb_pair.first.duplicate();
+ break;
+ }
+ }
+
+ for (unsigned j = (size - attach_end) + 1; j < size; j++) {
+ trimmed_end.append(path_in[0] [j]);
+ }
+
+ path_out.append(*curve_start);
+ pathv_out.push_back(trimmed_start);
+ pathv_out.push_back(path_out);
+ pathv_out.push_back(trimmed_end);
+ return pathv_out;
+ }
+
+ pathv_out.push_back(trimmed_start);
+
+ //append almost all of the rest of the path, ignore the curves that the knot is past (we'll get to it in a minute)
+ path_out.append(*curve_start);
+
+ for (unsigned k = loc + 1; k < (size - unsigned(attach_end)) - 1; k++) {
+ path_out.append(path_in[0] [k]);
+ }
+
+ //deal with the last segment in a very similar fashion to the first
+ loc = size - attach_end;
+
+ Geom::Curve * curve_end = path_in[0] [loc].duplicate();
+
+ Geom::Coord t = Geom::nearest_point(end_attach_point, *curve_end);
+
+ order = Outline::bezierOrder(curve_end);
+ switch (order) {
+ case 3: {
+ Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_end);
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t);
+ trimmed_end.append(cb_pair.second);
+ curve_end = cb_pair.first.duplicate();
+ break;
+ }
+ case 2: {
+ Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_end);
+ std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t);
+ trimmed_end.append(qb_pair.second);
+ curve_end = qb_pair.first.duplicate();
+ break;
+ }
+ case 1: {
+ Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_end);
+ std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t);
+ trimmed_end.append(lb_pair.second);
+ curve_end = lb_pair.first.duplicate();
+ break;
+ }
+ }
+
+ for (unsigned j = (size - attach_end) + 1; j < size; j++) {
+ trimmed_end.append(path_in[0] [j]);
+ }
+
+ path_out.append(*curve_end);
+ pathv_out.push_back(path_out);
+
+ pathv_out.push_back(trimmed_end);
+
+ if (curve_end) delete curve_end;
+ if (curve_start) delete curve_start;
+ return pathv_out;
}
@@ -509,14 +523,14 @@ Geom::PathVector LPETaperStroke::doEffect_simplePath(Geom::PathVector const & pa
//tweaking to get it to work right in this case.
Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in, Geom::Path pattern, double prop_scale)
{
- using namespace Geom;
+ using namespace Geom;
// Don't allow empty path parameter:
if ( pattern.empty() ) {
return pwd2_in;
}
-/* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
+ /* Much credit should go to jfb and mgsloan of lib2geom development for the code below! */
Piecewise<D2<SBasis> > output;
std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pre_output;
@@ -548,7 +562,7 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<
std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > paths_in;
paths_in = split_at_discontinuities(pwd2_in);
- for (unsigned idx = 0; idx < paths_in.size(); idx++){
+ for (unsigned idx = 0; idx < paths_in.size(); idx++) {
Geom::Piecewise<Geom::D2<Geom::SBasis> > path_i = paths_in[idx];
Piecewise<SBasis> x = x0;
Piecewise<SBasis> y = y0;
@@ -556,14 +570,14 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<
uskeleton = remove_short_cuts(uskeleton,.01);
Piecewise<D2<SBasis> > n = rot90(derivative(uskeleton));
n = force_continuity(remove_short_cuts(n,.1));
-
+
int nbCopies = 0;
double scaling = 1;
nbCopies = 1;
scaling = (uskeleton.domain().extent() - toffset)/pattBndsX->extent();
double pattWidth = pattBndsX->extent() * scaling;
-
+
if (scaling != 1.0) {
x*=scaling;
}
@@ -573,20 +587,20 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<
if (prop_scale != 1.0) y *= prop_scale;
}
x += toffset;
-
+
double offs = 0;
- for (int i=0; i<nbCopies; i++){
- if (false){
+ for (int i=0; i<nbCopies; i++) {
+ if (false) {
Geom::Piecewise<Geom::D2<Geom::SBasis> > output_piece = compose(uskeleton,x+offs)+y*compose(n,x+offs);
std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > splited_output_piece = split_at_discontinuities(output_piece);
pre_output.insert(pre_output.end(), splited_output_piece.begin(), splited_output_piece.end() );
- }else{
+ } else {
output.concat(compose(uskeleton,x+offs)+y*compose(n,x+offs));
}
offs+=pattWidth;
}
}
- /*if (false){
+ /*if (false){
pre_output = fuse_nearby_ends(pre_output, fuse_tolerance);
for (unsigned i=0; i<pre_output.size(); i++){
output.concat(pre_output[i]);
@@ -598,76 +612,107 @@ Geom::Piecewise<Geom::D2<Geom::SBasis> > stretch_along(Geom::Piecewise<Geom::D2<
}
}
+void subdivideCurve(Geom::Curve * curve_in, Geom::Coord t, Geom::Curve *& val_first, Geom::Curve *& val_second)
+{
+ unsigned order = Outline::bezierOrder(curve_in);
+ switch (order) {
+ case 3: {
+ Geom::CubicBezier *cb = static_cast<Geom::CubicBezier * >(curve_in);
+ std::pair<Geom::CubicBezier, Geom::CubicBezier> cb_pair = cb->subdivide(t);
+ //trimmed_start.append(cb_pair.first);
+ val_first = cb_pair.first.duplicate();
+ val_second = cb_pair.second.duplicate();
+ break;
+ }
+ case 2: {
+ Geom::QuadraticBezier *qb = static_cast<Geom::QuadraticBezier * >(curve_in);
+ std::pair<Geom::QuadraticBezier, Geom::QuadraticBezier> qb_pair = qb->subdivide(t);
+ //trimmed_start.append(qb_pair.first);
+ val_first = qb_pair.first.duplicate();
+ val_second = qb_pair.second.duplicate();
+ break;
+ }
+ case 1: {
+ Geom::BezierCurveN<1> *lb = static_cast<Geom::BezierCurveN<1> * >(curve_in);
+ std::pair<Geom::BezierCurveN<1>, Geom::BezierCurveN<1> > lb_pair = lb->subdivide(t);
+ //trimmed_start.append(lb_pair.first);
+ val_first = lb_pair.first.duplicate();
+ val_second = lb_pair.second.duplicate();
+ break;
+ }
+ }
+}
-void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
+
+void LPETaperStroke::addKnotHolderEntities(KnotHolder *knotholder, SPDesktop *desktop, SPItem *item)
{
- {
- KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this);
- e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE );
- knotholder->add(e);
- }
- {
- KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this);
- e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
- _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE );
- knotholder->add(e);
- }
+ {
+ KnotHolderEntity *e = new TpS::KnotHolderEntityAttachBegin(this);
+ e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
+ _("Start point of the taper"), SP_KNOT_SHAPE_CIRCLE );
+ knotholder->add(e);
+ }
+ {
+ KnotHolderEntity *e = new TpS::KnotHolderEntityAttachEnd(this);
+ e->create( desktop, item, knotholder, Inkscape::CTRL_TYPE_UNKNOWN,
+ _("End point of the taper"), SP_KNOT_SHAPE_CIRCLE );
+ knotholder->add(e);
+ }
}
namespace TpS {
- void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
- {
- using namespace Geom;
-
- LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
-
- Geom::Point const s = snap_knot_position(p, state);
-
- SPCurve *curve = SP_PATH(item)->get_curve_for_edit();
- Geom::PathVector pathv = curve->get_pathvector();
- Piecewise<D2<SBasis> > pwd2;
- Geom::Path p_in = return_at_first_cusp(pathv[0]);
- pwd2.concat(p_in.toPwSb());
- std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2);
-
- double t0 = nearest_point(s, pwd_vec[0]);
- lpe->attach_start.param_set_value(t0);
-
- // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
- }
- void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
- {
- using namespace Geom;
-
- LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
-
- Geom::Point const s = snap_knot_position(p, state);
-
- SPCurve *curve = SP_PATH(item)->get_curve_for_edit();
- Geom::PathVector pathv = curve->get_pathvector();
- Piecewise<D2<SBasis> > pwd2;
- Geom::Path p_in = return_at_first_cusp(pathv[0].reverse());
- pwd2.concat(p_in.toPwSb());
- std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2);
-
- double t0 = nearest_point(s, pwd_vec[0]);
- lpe->attach_end.param_set_value(t0);
-
- // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
- }
- Geom::Point KnotHolderEntityAttachBegin::knot_get() const
- {
- LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
- return lpe->start_attach_point;
- }
- Geom::Point KnotHolderEntityAttachEnd::knot_get() const
- {
- LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
- return lpe->end_attach_point;
- }
+void KnotHolderEntityAttachBegin::knot_set(Geom::Point const &p, Geom::Point const &/*origin*/, guint state)
+{
+ using namespace Geom;
+
+ LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ SPCurve *curve = SP_PATH(item)->get_curve_for_edit();
+ Geom::PathVector pathv = curve->get_pathvector();
+ Piecewise<D2<SBasis> > pwd2;
+ Geom::Path p_in = return_at_first_cusp(pathv[0]);
+ pwd2.concat(p_in.toPwSb());
+ std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2);
+
+ double t0 = nearest_point(s, pwd_vec[0]);
+ lpe->attach_start.param_set_value(t0);
+
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+void KnotHolderEntityAttachEnd::knot_set(Geom::Point const &p, Geom::Point const& /*origin*/, guint state)
+{
+ using namespace Geom;
+
+ LPETaperStroke* lpe = dynamic_cast<LPETaperStroke *>(_effect);
+
+ Geom::Point const s = snap_knot_position(p, state);
+
+ SPCurve *curve = SP_PATH(item)->get_curve_for_edit();
+ Geom::PathVector pathv = curve->get_pathvector();
+ Piecewise<D2<SBasis> > pwd2;
+ Geom::Path p_in = return_at_first_cusp(pathv[0].reverse());
+ pwd2.concat(p_in.toPwSb());
+ std::vector<Geom::Piecewise<Geom::D2<Geom::SBasis> > > pwd_vec = split_at_discontinuities(pwd2);
+
+ double t0 = nearest_point(s, pwd_vec[0]);
+ lpe->attach_end.param_set_value(t0);
+
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), false, true);
+}
+Geom::Point KnotHolderEntityAttachBegin::knot_get() const
+{
+ LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
+ return lpe->start_attach_point;
+}
+Geom::Point KnotHolderEntityAttachEnd::knot_get() const
+{
+ LPETaperStroke const * lpe = dynamic_cast<LPETaperStroke const*> (_effect);
+ return lpe->end_attach_point;
+}
}
diff --git a/src/live_effects/lpe-taperstroke.h b/src/live_effects/lpe-taperstroke.h
index 29a56f77c..997209543 100644
--- a/src/live_effects/lpe-taperstroke.h
+++ b/src/live_effects/lpe-taperstroke.h
@@ -20,39 +20,39 @@ namespace Inkscape {
namespace LivePathEffect {
namespace TpS {
- // we need a separate namespace to avoid clashes with other LPEs
- class KnotHolderEntityAttachBegin;
- class KnotHolderEntityAttachEnd;
+// we need a separate namespace to avoid clashes with other LPEs
+class KnotHolderEntityAttachBegin;
+class KnotHolderEntityAttachEnd;
}
class LPETaperStroke : public Effect {
public:
- LPETaperStroke(LivePathEffectObject *lpeobject);
- virtual ~LPETaperStroke();
-
- virtual void doOnApply(SPLPEItem const* lpeitem);
- virtual void doOnRemove(SPLPEItem const* lpeitem);
+ LPETaperStroke(LivePathEffectObject *lpeobject);
+ virtual ~LPETaperStroke();
- virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in);
- Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in);
-
- virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
+ virtual void doOnApply(SPLPEItem const* lpeitem);
+ virtual void doOnRemove(SPLPEItem const* lpeitem);
- friend class TpS::KnotHolderEntityAttachBegin;
- friend class TpS::KnotHolderEntityAttachEnd;
+ virtual Geom::PathVector doEffect_path (Geom::PathVector const& path_in);
+ Geom::PathVector doEffect_simplePath(Geom::PathVector const& path_in);
+
+ virtual void addKnotHolderEntities(KnotHolder * knotholder, SPDesktop * desktop, SPItem * item);
+
+ friend class TpS::KnotHolderEntityAttachBegin;
+ friend class TpS::KnotHolderEntityAttachEnd;
private:
- ScalarParam line_width;
- ScalarParam attach_start;
- ScalarParam attach_end;
- ScalarParam smoothing;
- EnumParam<unsigned> join_type;
- ScalarParam miter_limit;
+ ScalarParam line_width;
+ ScalarParam attach_start;
+ ScalarParam attach_end;
+ ScalarParam smoothing;
+ EnumParam<unsigned> join_type;
+ ScalarParam miter_limit;
- Geom::Point start_attach_point;
- Geom::Point end_attach_point;
+ Geom::Point start_attach_point;
+ Geom::Point end_attach_point;
- LPETaperStroke(const LPETaperStroke&);
- LPETaperStroke& operator=(const LPETaperStroke&);
+ LPETaperStroke(const LPETaperStroke&);
+ LPETaperStroke& operator=(const LPETaperStroke&);
};
} //namespace LivePathEffect
diff --git a/src/live_effects/pathoutlineprovider.cpp b/src/live_effects/pathoutlineprovider.cpp
index 6a47285a0..ad39a7416 100755..100644
--- a/src/live_effects/pathoutlineprovider.cpp
+++ b/src/live_effects/pathoutlineprovider.cpp
@@ -9,133 +9,128 @@
#include <2geom/path-sink.h>
#include <svg/svg.h>
-namespace Geom
+namespace Geom {
+/**
+* Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
+ From MathWorld--A Wolfram Web Resource.
+ http://mathworld.wolfram.com/Circle-CircleIntersection.html
+*
+* @return 0 if no intersection
+* @return 1 if one circle is contained in the other
+* @return 2 if intersections are found (they are written to p0 and p1)
+*/
+static int circle_circle_intersection(Circle const &circle0, Circle const &circle1,
+ Point & p0, Point & p1)
+{
+ Point X0 = circle0.center();
+ double r0 = circle0.ray();
+ Point X1 = circle1.center();
+ double r1 = circle1.ray();
+
+ /* dx and dy are the vertical and horizontal distances between
+ * the circle centers.
+ */
+ Point D = X1 - X0;
+
+ /* Determine the straight-line distance between the centers. */
+ double d = L2(D);
+
+ /* Check for solvability. */
+ if (d > (r0 + r1)) {
+ /* no solution. circles do not intersect. */
+ return 0;
+ }
+ if (d <= fabs(r0 - r1)) {
+ /* no solution. one circle is contained in the other */
+ return 1;
+ }
+
+ /* 'point 2' is the point where the line through the circle
+ * intersection points crosses the line between the circle
+ * centers.
+ */
+
+ /* Determine the distance from point 0 to point 2. */
+ double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
+
+ /* Determine the coordinates of point 2. */
+ Point p2 = X0 + D * (a/d);
+
+ /* Determine the distance from point 2 to either of the
+ * intersection points.
+ */
+ double h = std::sqrt((r0*r0) - (a*a));
+
+ /* Now determine the offsets of the intersection points from
+ * point 2.
+ */
+ Point r = (h/d)*rot90(D);
+
+ /* Determine the absolute intersection points. */
+ p0 = p2 + r;
+ p1 = p2 - r;
+
+ return 2;
+}
+/**
+* Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
+* Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
+*/
+static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
{
- /**
- * Refer to: Weisstein, Eric W. "Circle-Circle Intersection."
- From MathWorld--A Wolfram Web Resource.
- http://mathworld.wolfram.com/Circle-CircleIntersection.html
- *
- * @return 0 if no intersection
- * @return 1 if one circle is contained in the other
- * @return 2 if intersections are found (they are written to p0 and p1)
- */
- static int circle_circle_intersection(Circle const &circle0, Circle const &circle1,
- Point & p0, Point & p1)
- {
- Point X0 = circle0.center();
- double r0 = circle0.ray();
- Point X1 = circle1.center();
- double r1 = circle1.ray();
-
- /* dx and dy are the vertical and horizontal distances between
- * the circle centers.
- */
- Point D = X1 - X0;
-
- /* Determine the straight-line distance between the centers. */
- double d = L2(D);
-
- /* Check for solvability. */
- if (d > (r0 + r1))
- {
- /* no solution. circles do not intersect. */
- return 0;
- }
- if (d <= fabs(r0 - r1))
- {
- /* no solution. one circle is contained in the other */
- return 1;
- }
-
- /* 'point 2' is the point where the line through the circle
- * intersection points crosses the line between the circle
- * centers.
- */
-
- /* Determine the distance from point 0 to point 2. */
- double a = ((r0*r0) - (r1*r1) + (d*d)) / (2.0 * d) ;
-
- /* Determine the coordinates of point 2. */
- Point p2 = X0 + D * (a/d);
-
- /* Determine the distance from point 2 to either of the
- * intersection points.
- */
- double h = std::sqrt((r0*r0) - (a*a));
-
- /* Now determine the offsets of the intersection points from
- * point 2.
- */
- Point r = (h/d)*rot90(D);
-
- /* Determine the absolute intersection points. */
- p0 = p2 + r;
- p1 = p2 - r;
-
- return 2;
- }
- /**
- * Find circle that touches inside of the curve, with radius matching the curvature, at time value \c t.
- * Because this method internally uses unitTangentAt, t should be smaller than 1.0 (see unitTangentAt).
- */
- static Circle touching_circle( D2<SBasis> const &curve, double t, double tol=0.01 )
- {
- D2<SBasis> dM=derivative(curve);
- if ( are_near(L2sq(dM(t)),0.) ) {
- dM=derivative(dM);
- }
- if ( are_near(L2sq(dM(t)),0.) ) { // try second time
- dM=derivative(dM);
- }
- Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
- Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
- Piecewise<SBasis> k = cross(derivative(unitv),unitv);
- k = divide(k,dMlength,tol,3);
- double curv = k(t); // note that this value is signed
-
- Geom::Point normal = unitTangentAt(curve, t).cw();
- double radius = 1/curv;
- Geom::Point center = curve(t) + radius*normal;
- return Geom::Circle(center, fabs(radius));
- }
-
- static std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
- {
- Geom::PathVector out = Geom::PathVector();
- Geom::Path temp = Geom::Path();
-
- for (unsigned path_descr = 0; path_descr < in.size(); path_descr++)
- {
- temp = Geom::Path();
- temp.append(in[path_descr]);
- out.push_back(temp);
- }
-
- return out;
- }
-
- static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
- {
- std::vector<Geom::Point> temp;
- sbasis_to_bezier(temp, sbasis_in, 4);
- return Geom::CubicBezier( temp );
- }
-
- static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
- Geom::Point const & origin_b, Geom::Point const & vector_b)
- {
- Geom::Coord denom = cross(vector_b, vector_a);
- if (!Geom::are_near(denom,0.)){
- Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
- return origin_a + t * vector_a;
- }
- return boost::none;
- }
+ D2<SBasis> dM=derivative(curve);
+ if ( are_near(L2sq(dM(t)),0.) ) {
+ dM=derivative(dM);
+ }
+ if ( are_near(L2sq(dM(t)),0.) ) { // try second time
+ dM=derivative(dM);
+ }
+ Piecewise<D2<SBasis> > unitv = unitVector(dM,tol);
+ Piecewise<SBasis> dMlength = dot(Piecewise<D2<SBasis> >(dM),unitv);
+ Piecewise<SBasis> k = cross(derivative(unitv),unitv);
+ k = divide(k,dMlength,tol,3);
+ double curv = k(t); // note that this value is signed
+
+ Geom::Point normal = unitTangentAt(curve, t).cw();
+ double radius = 1/curv;
+ Geom::Point center = curve(t) + radius*normal;
+ return Geom::Circle(center, fabs(radius));
}
-namespace Outline
+static std::vector<Geom::Path> split_at_cusps(const Geom::Path& in)
{
+ Geom::PathVector out = Geom::PathVector();
+ Geom::Path temp = Geom::Path();
+
+ for (unsigned path_descr = 0; path_descr < in.size(); path_descr++) {
+ temp = Geom::Path();
+ temp.append(in[path_descr]);
+ out.push_back(temp);
+ }
+
+ return out;
+}
+
+static Geom::CubicBezier sbasis_to_cubicbezier(Geom::D2<Geom::SBasis> const & sbasis_in)
+{
+ std::vector<Geom::Point> temp;
+ sbasis_to_bezier(temp, sbasis_in, 4);
+ return Geom::CubicBezier( temp );
+}
+
+static boost::optional<Geom::Point> intersection_point( Geom::Point const & origin_a, Geom::Point const & vector_a,
+ Geom::Point const & origin_b, Geom::Point const & vector_b)
+{
+ Geom::Coord denom = cross(vector_b, vector_a);
+ if (!Geom::are_near(denom,0.)) {
+ Geom::Coord t = (cross(origin_a,vector_b) + cross(vector_b,origin_b)) / denom;
+ return origin_a + t * vector_a;
+ }
+ return boost::none;
+}
+}
+
+namespace Outline {
typedef Geom::D2<Geom::SBasis> D2SB;
typedef Geom::Piecewise<D2SB> PWD2;
@@ -160,72 +155,70 @@ bool outside_angle (const Geom::Curve& cbc1, const Geom::Curve& cbc2)
unsigned order = bezierOrder(&cbc1);
Geom::Point start_point;
- Geom::Point cross_point = cbc1.finalPoint();
- Geom::Point end_point;
-
- //assert(cbc1.finalPoint() == cbc2.initialPoint());
- //short circuiting?
- if (cbc1.finalPoint() != cbc2.initialPoint()) {
- printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n"
- "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__);
- return false;
+ Geom::Point cross_point = cbc1.finalPoint();
+ Geom::Point end_point;
+
+ //assert(cbc1.finalPoint() == cbc2.initialPoint());
+ //short circuiting?
+ if (cbc1.finalPoint() != cbc2.initialPoint()) {
+ printf("There was an issue when asserting that one curve's end is the start of the other. Line %d, File %s\n"
+ "By default we are going to say that this is an inside join, so we cannot make a line join for it.\n", __LINE__, __FILE__);
+ return false;
+ }
+ switch (order) {
+ case 3:
+ start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (2);
+ //major league b***f***ing
+ if (are_near(start_point, cross_point, 0.0000001)) {
+ start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (1);
}
- switch (order)
- {
- case 3:
- start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (2);
- //major league b***f***ing
- if (are_near(start_point, cross_point, 0.0000001)) {
- start_point = (static_cast<const Geom::CubicBezier*>(&cbc1))->operator[] (1);
- }
- break;
- case 2:
- //this never happens
- start_point = (static_cast<const Geom::QuadraticBezier*>(&cbc1))->operator[] (1);
- break;
- case 1:
- default:
- start_point = cbc1.initialPoint();
- }
-
- order = Outline::bezierOrder(&cbc2);
-
- switch (order)
- {
- case 3:
- end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (1);
- if (are_near(end_point, cross_point, 0.0000001)) {
- end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (2);
- }
- break;
- case 2:
- end_point = (static_cast<const Geom::QuadraticBezier*>(&cbc2))->operator[] (1);
- break;
- case 1:
- default:
- end_point = cbc2.finalPoint();
- }
- //got our three points, now let's see what their clockwise angle is
-
- //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan )
- /********************************************************************
+ break;
+ case 2:
+ //this never happens
+ start_point = (static_cast<const Geom::QuadraticBezier*>(&cbc1))->operator[] (1);
+ break;
+ case 1:
+ default:
+ start_point = cbc1.initialPoint();
+ }
+
+ order = Outline::bezierOrder(&cbc2);
+
+ switch (order) {
+ case 3:
+ end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (1);
+ if (are_near(end_point, cross_point, 0.0000001)) {
+ end_point = (static_cast<const Geom::CubicBezier*>(&cbc2))->operator[] (2);
+ }
+ break;
+ case 2:
+ end_point = (static_cast<const Geom::QuadraticBezier*>(&cbc2))->operator[] (1);
+ break;
+ case 1:
+ default:
+ end_point = cbc2.finalPoint();
+ }
+ //got our three points, now let's see what their clockwise angle is
+
+ //Much credit to Wikipedia for the following ( http://en.wikipedia.org/wiki/Graham_scan )
+ /********************************************************************
# Three points are a counter-clockwise turn if ccw > 0, clockwise if
# ccw < 0, and collinear if ccw = 0 because ccw is a determinant that
# gives the signed area of the triangle formed by p1, p2 and p3.
function ccw(p1, p2, p3):
- return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
+ return (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x)
*********************************************************************/
-
+
double ccw = ( (cross_point.x() - start_point.x()) * (end_point.y() - start_point.y()) ) -
( (cross_point.y() - start_point.y()) * (end_point.x() - start_point.x()) );
if (ccw > 0) return true;
return false;
}
-void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
+void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
double miter_limit, double line_width, bool outside = false)
{
- bool lineProblem = (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc1)) || (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc2));
+ bool lineProblem = (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc1)) || (dynamic_cast<Geom::BezierCurveN<1u> *>(cbc2));
if ( outside && !lineProblem ) {
Geom::Path pth;
pth.append(*cbc1);
@@ -271,9 +264,8 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve
}
} else {
boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -284,19 +276,18 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve
}
path_builder.appendNew<Geom::LineSegment> (endPt);
}
- }
- if ( outside && lineProblem ) {
- Geom::Path pth;
+ }
+ if ( outside && lineProblem ) {
+ Geom::Path pth;
pth.append(*cbc1);
- Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.);
+ Geom::Point tang1 = Geom::unitTangentAt(Geom::reverse(pth.toPwSb()[0]), 0.);
pth = Geom::Path();
- pth.append( *cbc2 );
- Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
-
- boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ pth.append( *cbc2 );
+ Geom::Point tang2 = Geom::unitTangentAt(pth.toPwSb()[0], 0);
+
+ boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -306,13 +297,13 @@ void extrapolate_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve
}
}
path_builder.appendNew<Geom::LineSegment> (endPt);
- }
- if ( !outside ) {
- path_builder.appendNew<Geom::LineSegment> (endPt);
- }
+ }
+ if ( !outside ) {
+ path_builder.appendNew<Geom::LineSegment> (endPt);
+ }
}
-void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
+void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cbc2, Geom::Point endPt,
double miter_limit, double line_width, bool outside = false)
{
//the most important work for the reflected join is done here
@@ -320,7 +311,7 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb
//determine where we are in the path. If we're on the inside, ignore
//and just lineTo. On the outside, we'll do a little reflection magic :)
Geom::Crossings cross;
-
+
if (outside) {
Geom::Path pth;
pth.append(*cbc1);
@@ -347,9 +338,8 @@ void reflect_curves(Geom::Path& path_builder, Geom::Curve* cbc1, Geom::Curve* cb
if ( cross.empty() ) {
//curves didn't cross; default to miter
boost::optional <Geom::Point> p = intersection_point (cbc1->finalPoint(), tang1,
- cbc2->initialPoint(), tang2);
- if (p)
- {
+ cbc2->initialPoint(), tang2);
+ if (p) {
//check size of miter
Geom::Point point_on_path = cbc1->finalPoint() - rot90(tang1) * line_width;
Geom::Coord len = distance(*p, point_on_path);
@@ -388,27 +378,26 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double
// NOTE: it is important to notice the distinction between a Geom::Path and a livarot Path here!
// if you do not see "Geom::" there is a different function set!
Geom::PathVector pv = split_at_cusps(path_in);
-
+
Path to_outline;
Path outlined_result;
-
+
Geom::Path path_builder = Geom::Path(); //the path to store the result in
Geom::PathVector * path_vec; //needed because livarot returns a goddamn pointer
-
+
const unsigned k = path_in.size();
-
- for (unsigned u = 0; u < k; u+=2)
- {
+
+ for (unsigned u = 0; u < k; u+=2) {
to_outline = Path();
outlined_result = Path();
-
+
to_outline.LoadPath(pv[u], Geom::Affine(), false, false);
to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
//now a curve has been outside outlined and loaded into outlined_result
-
+
//get the Geom::Path
path_vec = outlined_result.MakePathVector();
-
+
//thing to do on the first run through
if (u == 0) {
//I could use the pv->operator[] (0) notation but that looks terrible
@@ -417,58 +406,64 @@ Geom::Path doAdvHalfOutline(const Geom::Path& path_in, double line_width, double
//get the curves ready for the operation
Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate();
Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate();
-
+
//do the reflection/extrapolation:
- if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); }
- else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] )); }
+ if (extrapolate) {
+ extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] ));
+ } else {
+ reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u - 1] [pv[u - 1].size() - 1], pv[u] [0] ));
+ }
}
-
+
path_builder.append( (*path_vec)[0] );
-
+
//outline the next segment, but don't store it yet
if (path_vec) delete path_vec;
-
+
if (u < k - 1) {
outlined_result = Path();
to_outline = Path();
-
+
to_outline.LoadPath(pv[u+1], Geom::Affine(), false, false);
to_outline.OutsideOutline(&outlined_result, line_width / 2, join_straight, butt_straight, 10);
-
+
path_vec = outlined_result.MakePathVector();
-
+
//get the curves ready for the operation
Geom::Curve * cbc1 = path_builder[path_builder.size() - 1].duplicate();
Geom::Curve * cbc2 = (*path_vec)[0] [0].duplicate();
-
+
//do the reflection/extrapolation:
- if (extrapolate) { extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); }
- else { reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
- outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] )); }
-
+ if (extrapolate) {
+ extrapolate_curves(path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] ));
+ } else {
+ reflect_curves (path_builder, cbc1, cbc2, (*path_vec)[0].initialPoint(), miter_limit, line_width,
+ outside_angle ( pv[u] [pv[u].size()-1], pv[u+1] [0] ));
+ }
+
//Now we can store it.
path_builder.append( (*path_vec)[0] );
-
+
if (cbc1) delete cbc1;
if (cbc2) delete cbc2;
if (path_vec) delete path_vec;
}
}
-
+
return path_builder;
}
-Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
+Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
ButtType butt, double miter_lim, bool extrapolate)
{
Geom::PathVector path_out;
-
+
unsigned pv_size = path_in.size();
for (unsigned i = 0; i < pv_size; i++) {
-
+
if (path_in[i].size() > 1) {
//since you've made it this far, hopefully all this is obvious :P
Geom::Path with_direction;
@@ -484,8 +479,8 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width,
newPath = Geom::path_from_piecewise(pwd2, 0.01)[0];
//fuk this
with_direction = Outline::doAdvHalfOutline( newPath, -line_width, miter_lim, extrapolate );
- against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate );
-
+ against_direction = Outline::doAdvHalfOutline( newPath.reverse(), -line_width, miter_lim, extrapolate );
+
/*if (dynamic_cast<const Geom::BezierCurveN<1u> *>(&newPath[newPath.size()])) {
//delete the 'Z'
newPath.erase_last();
@@ -497,54 +492,54 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width,
newPath.erase_last();
newPath.append(path_in[i][path_in[i].size() - 1]);
newPath.appendNew<Geom::LineSegment>(newPath.initialPoint());
- newPath.erase_last();
+ newPath.erase_last();
}*/
}
Geom::PathBuilder pb;
-
+
//add in the...do I really need to say this?
pb.moveTo(with_direction.initialPoint());
pb.append(with_direction);
-
+
//add in our line caps
if (!path_in[i].closed()) {
switch (butt) {
- case butt_straight:
- pb.lineTo(against_direction.initialPoint());
- break;
- case butt_round:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
- break;
- case butt_pointy:
- //I have ZERO idea what to do here.
- pb.lineTo(against_direction.initialPoint());
- break;
- case butt_square:
- pb.lineTo(against_direction.initialPoint());
- break;
+ case butt_straight:
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ case butt_round:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, against_direction.initialPoint() );
+ break;
+ case butt_pointy:
+ //I have ZERO idea what to do here.
+ pb.lineTo(against_direction.initialPoint());
+ break;
+ case butt_square:
+ pb.lineTo(against_direction.initialPoint());
+ break;
}
} else {
pb.moveTo(against_direction.initialPoint());
}
-
+
pb.append(against_direction);
-
+
//cap (if necessary)
if (!path_in[i].closed()) {
switch (butt) {
- case butt_straight:
- pb.lineTo(with_direction.initialPoint());
- break;
- case butt_round:
- pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
- break;
- case butt_pointy:
- //I have ZERO idea what to do here.
- pb.lineTo(with_direction.initialPoint());
- break;
- case butt_square:
- pb.lineTo(with_direction.initialPoint());
- break;
+ case butt_straight:
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ case butt_round:
+ pb.arcTo((-line_width) / 2, (-line_width) / 2, 0., true, true, with_direction.initialPoint() );
+ break;
+ case butt_pointy:
+ //I have ZERO idea what to do here.
+ pb.lineTo(with_direction.initialPoint());
+ break;
+ case butt_square:
+ pb.lineTo(with_direction.initialPoint());
+ break;
}
}
pb.flush();
@@ -554,7 +549,7 @@ Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width,
} else {
Path p = Path();
Path outlinepath = Path();
-
+
p.LoadPath(path_in[i], Geom::Affine(), false, false);
p.Outline(&outlinepath, line_width / 2, static_cast<join_typ>(join), butt, miter_lim);
Geom::PathVector *pv_p = outlinepath.MakePathVector();
diff --git a/src/live_effects/pathoutlineprovider.h b/src/live_effects/pathoutlineprovider.h
index 23cc7e2c4..27bc62d45 100644
--- a/src/live_effects/pathoutlineprovider.h
+++ b/src/live_effects/pathoutlineprovider.h
@@ -12,15 +12,15 @@ enum LineJoinType {
LINEJOIN_EXTRAPOLATED
};
-namespace Outline
+namespace Outline
{
- unsigned bezierOrder (const Geom::Curve* curve_in);
- std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtType linecap_type,
- LineJoinType linejoin_type, double miter_limit);
-
- Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
- ButtType butt, double miter_lim, bool extrapolate = false);
- Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit);
+ unsigned bezierOrder (const Geom::Curve* curve_in);
+ std::vector<Geom::Path> PathVectorOutline(std::vector<Geom::Path> const & path_in, double line_width, ButtType linecap_type,
+ LineJoinType linejoin_type, double miter_limit);
+
+ /*Geom::PathVector outlinePath(const Geom::PathVector& path_in, double line_width, LineJoinType join,
+ ButtType butt, double miter_lim, bool extrapolate = false);*/
+ Geom::Path PathOutsideOutline(Geom::Path const & path_in, double line_width, LineJoinType linejoin_type, double miter_limit);
}
#endif // _SEEN_PATH_OUTLINE_H