summary | shortlog | log | commit | commitdiff | tree
raw | patch | inline | side by side (parent: d10f8bb)
raw | patch | inline | side by side (parent: d10f8bb)
author | johanengelen <johanengelen@users.sourceforge.net> | |
Fri, 30 May 2008 20:36:13 +0000 (20:36 +0000) | ||
committer | johanengelen <johanengelen@users.sourceforge.net> | |
Fri, 30 May 2008 20:36:13 +0000 (20:36 +0000) |
(many thanks to the french students who made this.)
25 files changed:
index 28d54d87c79ee045f91f994e00803a0f8842536b..7d3221357ffd78978c028a1eef17b65dd339f0ca 100644 (file)
lpe-curvestitch.cpp
lpe-curvestitch.h
lpe-envelope.cpp
-lpe-envelope.h
lpe-gears.cpp
lpe-gears.h
lpegroupbbox.cpp
lpegroupbbox.h
lpe-knot.cpp
lpe-knot.h
+lpe-lattice.cpp
lpeobject.cpp
lpeobject.h
lpeobject-reference.cpp
spiro.h
)
+
index 4629a4d02c60f98bc418d2db51a4a3218843aeda..ea49aa269a4334661aa70f333e3dc46b86c995f9 100644 (file)
live_effects/lpe-gears.h \
live_effects/lpe-test-doEffect-stack.cpp \
live_effects/lpe-test-doEffect-stack.h \
+ live_effects/lpe-lattice.cpp \
+ live_effects/lpe-lattice.h \
+ live_effects/lpe-envelope.cpp \
+ live_effects/lpe-envelope.h \
live_effects/lpe-spiro.cpp \
live_effects/lpe-spiro.h \
+ live_effects/lpe-tangent_to_curve.cpp \
+ live_effects/lpe-tangent_to_curve.h \
+ live_effects/lpe-perp_bisector.cpp \
+ live_effects/lpe-perp_bisector.h \
live_effects/spiro.h \
live_effects/spiro.cpp \
live_effects/bezctx.h \
live_effects/lpe-circle_with_radius.cpp \
live_effects/lpe-circle_with_radius.h \
live_effects/lpe-perspective_path.cpp \
- live_effects/lpe-perspective_path.h \
- live_effects/lpe-envelope.cpp \
- live_effects/lpe-envelope.h \
- live_effects/lpe-perp_bisector.cpp \
- live_effects/lpe-perp_bisector.h \
- live_effects/lpe-tangent_to_curve.cpp \
- live_effects/lpe-tangent_to_curve.h
+ live_effects/lpe-perspective_path.h
+
index 906955575599d13fac395f6764148d2b7d9cc9c8..f968ec5c086e2436857300062319b754acb46f77 100644 (file)
#include "live_effects/lpe-circle_with_radius.h"
#include "live_effects/lpe-perspective_path.h"
#include "live_effects/lpe-spiro.h"
-#include "live_effects/lpe-constructgrid.h"
+#include "live_effects/lpe-lattice.h"
#include "live_effects/lpe-envelope.h"
+#include "live_effects/lpe-constructgrid.h"
#include "live_effects/lpe-perp_bisector.h"
#include "live_effects/lpe-tangent_to_curve.h"
// end of includes
{DOEFFECTSTACK_TEST, N_("doEffect stack test"), "doeffectstacktest"},
#endif
{GEARS, N_("Gears"), "gears"},
- {CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"},
+ {CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"},
{CIRCLE_WITH_RADIUS, N_("Circle (center+radius)"), "circle_with_radius"},
{PERSPECTIVE_PATH, N_("Perspective path"), "perspective_path"},
{SPIRO, N_("Spiro spline"), "spiro"},
- {CONSTRUCT_GRID, N_("Construct grid"), "construct_grid"},
+ {LATTICE, N_("Lattice Deformation"), "lattice"},
{ENVELOPE, N_("Envelope Deformation"), "envelope"},
+ {CONSTRUCT_GRID, N_("Construct grid"), "construct_grid"},
{PERP_BISECTOR, N_("Perpendicular bisector"), "perp_bisector"},
- {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"},
+ {TANGENT_TO_CURVE, N_("Tangent to curve"), "tangent_to_curve"}
};
const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, INVALID_LPE);
case CURVE_STITCH:
neweffect = static_cast<Effect*> ( new LPECurveStitch(lpeobj) );
break;
+ case LATTICE:
+ neweffect = static_cast<Effect*> ( new LPELattice(lpeobj) );
+ break;
+ case ENVELOPE:
+ neweffect = static_cast<Effect*> ( new LPEEnvelope(lpeobj) );
+ break;
case CIRCLE_WITH_RADIUS:
neweffect = static_cast<Effect*> ( new LPECircleWithRadius(lpeobj) );
break;
case CONSTRUCT_GRID:
neweffect = static_cast<Effect*> ( new LPEConstructGrid(lpeobj) );
break;
- case ENVELOPE:
- neweffect = static_cast<Effect*> ( new LPEEnvelope(lpeobj) );
- break;
case PERP_BISECTOR:
neweffect = static_cast<Effect*> ( new LPEPerpBisector(lpeobj) );
break;
index 1255595d0522fa8804cf9679f08a0c435c1af6cf..d5a49d71ed8235e4195d87b9eed11a8940b7dd7d 100644 (file)
CIRCLE_WITH_RADIUS,
PERSPECTIVE_PATH,
SPIRO,
- CONSTRUCT_GRID,
+ LATTICE,
ENVELOPE,
+ CONSTRUCT_GRID,
PERP_BISECTOR,
TANGENT_TO_CURVE,
INVALID_LPE // This must be last
index 6b9fbbb97eaedb8712735680e297f884ffdb487c..282ea82706f44738eaa1d974fde3367564afdfd8 100644 (file)
prop_scale.param_set_increments(0.01, 0.10);
concatenate_before_pwd2 = true;
-
- groupSpecialBehavior = false;
}
LPEBendPath::~LPEBendPath()
void
LPEBendPath::doBeforeEffect (SPLPEItem *lpeitem)
{
- if(SP_IS_GROUP(lpeitem))
- {
- groupSpecialBehavior = true;
-
- original_bbox(lpeitem);
- }
+ // get the item bounding box
+ original_bbox(lpeitem);
}
Geom::Piecewise<Geom::D2<Geom::SBasis> >
@@ -105,11 +99,6 @@ LPEBendPath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd
Piecewise<SBasis> y = vertical_pattern.get_value() ? Piecewise<SBasis>(patternd2[0]) : Piecewise<SBasis>(patternd2[1]);
//We use the group bounding box size or the path bbox size to translate well x and y
- if(groupSpecialBehavior == false)
- {
- boundingbox_X = bounds_exact(x);
- boundingbox_Y = bounds_exact(y);
- }
x-= vertical_pattern.get_value() ? boundingbox_Y.min() : boundingbox_X.min();
y-= vertical_pattern.get_value() ? boundingbox_X.middle() : boundingbox_Y.middle();
index e05112de9fc1da46c2759413a873c620f34648c0..1d3a9861ef8793e5307b87496232acf0616c14b8 100644 (file)
BoolParam scale_y_rel;
BoolParam vertical_pattern;
- bool groupSpecialBehavior;
-
void on_pattern_pasted();
LPEBendPath(const LPEBendPath&);
index b31ad669635c1aeb7cc86b49b2f3c174c92f3047..52a21fbaf48edfc6ad2b98d71573ecdfa9573d4d 100644 (file)
-#define INKSCAPE_LPE_PERP_BISECTOR_CPP
-/** \file
- * LPE <perp_bisector> implementation.
- */
-/*
- * Authors:
- * Maximilian Albert
- * Johan Engelen
- *
- * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
- * Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com>
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "live_effects/lpe-perp_bisector.h"
-#include "display/curve.h"
-#include <libnr/n-art-bpath.h>
-#include "sp-path.h"
-#include "line-geometry.h"
-
-#include <2geom/path.h>
-
-namespace Inkscape {
-namespace LivePathEffect {
-
-/* FIXME: We should arguably make these member functions of LPEPerpBisector.
- Is there an easy way to register member functions with knotholder?
- */
-NR::Point bisector_left_end_get(SPItem *item) {
- Inkscape::LivePathEffect::LPEPerpBisector *lpe =
- (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return NR::Point(lpe->C);
-}
-
-NR::Point bisector_right_end_get(SPItem *item) {
- Inkscape::LivePathEffect::LPEPerpBisector *lpe =
- (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return NR::Point(lpe->D);
-}
-
-void
-bisector_end_set(SPItem *item, NR::Point const &p, bool left) {
- Inkscape::LivePathEffect::LPEPerpBisector *lpe =
- (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- double lambda = Geom::nearest_point(p.to_2geom(), lpe->M, lpe->perp_dir);
- if (left) {
- lpe->C = lpe->M + lpe->perp_dir * lambda;
- lpe->length_left.param_set_value(lambda);
- } else {
- lpe->D = lpe->M + lpe->perp_dir * lambda;
- lpe->length_right.param_set_value(-lambda);
- }
-
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
-
-void
-bisector_left_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
- bisector_end_set(item, p);
-}
-
-void
-bisector_right_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
- bisector_end_set(item, p, false);
-}
-
-NR::Point path_start_get(SPItem *item) {
- Inkscape::LivePathEffect::LPEPerpBisector *lpe =
- (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return NR::Point(lpe->A);
-}
-
-NR::Point path_end_get(SPItem *item) {
- Inkscape::LivePathEffect::LPEPerpBisector *lpe =
- (Inkscape::LivePathEffect::LPEPerpBisector *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return NR::Point(lpe->B);
-}
-
-void
-path_set_start_end(SPItem *item, NR::Point const &p, bool start) {
- SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(item)); // TODO: Should we use sp_shape_get_curve()?
- NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(item)));
-
- Geom::Point A, B;
- if (start) {
- A = p.to_2geom();
- B = (curve->last_point()).to_2geom();
- } else {
- A = (curve->first_point()).to_2geom();
- B = (p.to_2geom());
- }
-
- SPCurve *c = new SPCurve();
- c->moveto(A);
- c->lineto(B);
- sp_path_set_original_curve(SP_PATH(item), c, TRUE, true);
- c->unref();
-}
-
-void path_start_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
- path_set_start_end(item, p);
-}
-
-void path_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {
- path_set_start_end(item, p, false);
-}
-
-LPEPerpBisector::LPEPerpBisector(LivePathEffectObject *lpeobject) :
- Effect(lpeobject),
- length_left(_("Length left"), _("Specifies the left end of the bisector"), "length-left", &wr, this, 200),
- length_right(_("Length right"), _("Specifies the right end of the bisector"), "length-right", &wr, this, 200),
- A(0,0), B(0,0), M(0,0), C(0,0), D(0,0), perp_dir(0,0)
-{
- // register all your parameters here, so Inkscape knows which parameters this effect has:
- registerParameter( dynamic_cast<Parameter *>(&length_left) );
- registerParameter( dynamic_cast<Parameter *>(&length_right) );
-
- registerKnotHolderHandle(path_start_set, path_start_get);
- registerKnotHolderHandle(path_end_set, path_end_get);
- registerKnotHolderHandle(bisector_left_end_set, bisector_left_end_get);
- registerKnotHolderHandle(bisector_right_end_set, bisector_right_end_get);
-}
-
-LPEPerpBisector::~LPEPerpBisector()
-{
-}
-
-void
-LPEPerpBisector::doOnApply (SPLPEItem *lpeitem)
-{
- /* make the path a straight line */
- SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?
-
- Geom::Point A((curve->first_point()).to_2geom());
- Geom::Point B((curve->last_point()).to_2geom());
-
- SPCurve *c = new SPCurve();
- c->moveto(A);
- c->lineto(B);
- // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?
- SP_PATH(lpeitem)->original_curve = c->ref();
- c->unref();
-}
-
-
-Geom::Piecewise<Geom::D2<Geom::SBasis> >
-LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
-{
- using namespace Geom;
-
- Piecewise<D2<SBasis> > output;
-
- A = pwd2_in.firstValue();
- B = pwd2_in.lastValue();
- M = (A + B)/2;
-
- perp_dir = unit_vector((B - A).ccw());
-
- C = M + perp_dir * length_left;
- D = M - perp_dir * length_right;
-
- output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
-
- return output;
-}
-
-/* ######################## */
-
-} //namespace LivePathEffect
-} /* namespace Inkscape */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+#define INKSCAPE_LPE_PERP_BISECTOR_CPP\r
+/** \file\r
+ * LPE <perp_bisector> implementation.\r
+ */\r
+/*\r
+ * Authors:\r
+ * Maximilian Albert\r
+ * Johan Engelen\r
+ *\r
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>\r
+ * Copyright (C) Maximilin Albert 2008 <maximilian.albert@gmail.com>\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#include "live_effects/lpe-perp_bisector.h"\r
+#include "display/curve.h"\r
+#include <libnr/n-art-bpath.h>\r
+#include "sp-path.h"\r
+#include "line-geometry.h"\r
+#include "sp-lpe-item.h"\r
+#include <2geom/path.h>\r
+\r
+namespace Inkscape {\r
+namespace LivePathEffect {\r
+\r
+/* FIXME: We should make these member functions of LPEPerpBisector.\r
+ Is there an easy way to register member functions with knotholder?\r
+ KNOWN BUG: Because of the above, this effect does not work well when in an LPE stack\r
+ */\r
+NR::Point bisector_left_end_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPEPerpBisector *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return NR::Point(lpe->C);\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+NR::Point bisector_right_end_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPEPerpBisector *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return NR::Point(lpe->D);\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+void\r
+bisector_end_set(SPItem *item, NR::Point const &p, bool left) {\r
+ Inkscape::LivePathEffect::LPEPerpBisector *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (!lpe)\r
+ return;\r
+\r
+ double lambda = Geom::nearest_point(p.to_2geom(), lpe->M, lpe->perp_dir);\r
+ if (left) {\r
+ lpe->C = lpe->M + lpe->perp_dir * lambda;\r
+ lpe->length_left.param_set_value(lambda);\r
+ } else {\r
+ lpe->D = lpe->M + lpe->perp_dir * lambda;\r
+ lpe->length_right.param_set_value(-lambda);\r
+ }\r
+\r
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.\r
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);\r
+}\r
+\r
+void\r
+bisector_left_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {\r
+ bisector_end_set(item, p);\r
+}\r
+\r
+void\r
+bisector_right_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {\r
+ bisector_end_set(item, p, false);\r
+}\r
+\r
+NR::Point path_start_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPEPerpBisector *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return NR::Point(lpe->A);\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+NR::Point path_end_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPEPerpBisector *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPEPerpBisector *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return NR::Point(lpe->B);\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+void\r
+path_set_start_end(SPItem *item, NR::Point const &p, bool start) {\r
+ SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(item)); // TODO: Should we use sp_shape_get_curve()?\r
+ NR::Matrix const i2d (sp_item_i2d_affine (SP_ITEM(item)));\r
+\r
+ Geom::Point A, B;\r
+ if (start) {\r
+ A = p.to_2geom();\r
+ B = (curve->last_point()).to_2geom();\r
+ } else {\r
+ A = (curve->first_point()).to_2geom();\r
+ B = (p.to_2geom());\r
+ }\r
+\r
+ SPCurve *c = new SPCurve();\r
+ c->moveto(A);\r
+ c->lineto(B);\r
+ sp_path_set_original_curve(SP_PATH(item), c, TRUE, true);\r
+ c->unref();\r
+}\r
+\r
+void path_start_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {\r
+ path_set_start_end(item, p);\r
+}\r
+\r
+void path_end_set(SPItem *item, NR::Point const &p, NR::Point const &/*origin*/, guint /*state*/) {\r
+ path_set_start_end(item, p, false);\r
+}\r
+\r
+LPEPerpBisector::LPEPerpBisector(LivePathEffectObject *lpeobject) :\r
+ Effect(lpeobject),\r
+ length_left(_("Length left"), _("Specifies the left end of the bisector"), "length-left", &wr, this, 200),\r
+ length_right(_("Length right"), _("Specifies the right end of the bisector"), "length-right", &wr, this, 200),\r
+ A(0,0), B(0,0), M(0,0), C(0,0), D(0,0), perp_dir(0,0)\r
+{\r
+ // register all your parameters here, so Inkscape knows which parameters this effect has:\r
+ registerParameter( dynamic_cast<Parameter *>(&length_left) );\r
+ registerParameter( dynamic_cast<Parameter *>(&length_right) );\r
+\r
+ registerKnotHolderHandle(path_start_set, path_start_get);\r
+ registerKnotHolderHandle(path_end_set, path_end_get);\r
+ registerKnotHolderHandle(bisector_left_end_set, bisector_left_end_get);\r
+ registerKnotHolderHandle(bisector_right_end_set, bisector_right_end_get);\r
+}\r
+\r
+LPEPerpBisector::~LPEPerpBisector()\r
+{\r
+}\r
+\r
+void\r
+LPEPerpBisector::doOnApply (SPLPEItem *lpeitem)\r
+{\r
+ /* make the path a straight line */\r
+ SPCurve* curve = sp_path_get_curve_for_edit (SP_PATH(lpeitem)); // TODO: Should we use sp_shape_get_curve()?\r
+\r
+ Geom::Point A((curve->first_point()).to_2geom());\r
+ Geom::Point B((curve->last_point()).to_2geom());\r
+\r
+ SPCurve *c = new SPCurve();\r
+ c->moveto(A);\r
+ c->lineto(B);\r
+ // TODO: Why doesn't sp_path_set_original_curve(SP_PATH(lpeitem), c, TRUE, true) work?\r
+ SP_PATH(lpeitem)->original_curve = c->ref();\r
+ c->unref();\r
+}\r
+\r
+\r
+Geom::Piecewise<Geom::D2<Geom::SBasis> >\r
+LPEPerpBisector::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)\r
+{\r
+ using namespace Geom;\r
+\r
+ Piecewise<D2<SBasis> > output;\r
+\r
+ A = pwd2_in.firstValue();\r
+ B = pwd2_in.lastValue();\r
+ M = (A + B)/2;\r
+\r
+ perp_dir = unit_vector((B - A).ccw());\r
+\r
+ C = M + perp_dir * length_left;\r
+ D = M - perp_dir * length_right;\r
+\r
+ output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));\r
+\r
+ return output;\r
+}\r
+\r
+/* ######################## */\r
+\r
+} //namespace LivePathEffect\r
+} /* namespace Inkscape */\r
+\r
+/*\r
+ Local Variables:\r
+ mode:c++\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
index 57bc458a945da28f879206e0b0b566866c170199..cf6d1cecd91ce583f588ed013239abd98d840196 100644 (file)
Proj::TransfMat3x4 pmat = persp->tmat;
pmat.copy_tmat(tmat);
-
- groupSpecialBehavior = false;
}
LPEPerspectivePath::~LPEPerspectivePath()
void
LPEPerspectivePath::doBeforeEffect (SPLPEItem *lpeitem)
{
- if(SP_IS_GROUP(lpeitem))
- {
- groupSpecialBehavior = true;
- original_bbox(lpeitem);
- }
+ original_bbox(lpeitem, true);
}
-
Geom::Piecewise<Geom::D2<Geom::SBasis> >
LPEPerspectivePath::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
{
D2<Piecewise<SBasis> > B = make_cuts_independant(path_a_pw);
Piecewise<SBasis> preimage[4];
- if(!groupSpecialBehavior)
- {
- boundingbox_X = bounds_fast(pwd2_in)[0];
- boundingbox_Y = bounds_fast(pwd2_in)[1];
- }
-
Geom::Point orig = Geom::Point(uses_plane_xy ? boundingbox_X.max() : boundingbox_X.min(),
boundingbox_Y.middle());
+
//Geom::Point orig = Geom::Point(bounds_X.min(), bounds_Y.middle());
//orig = Geom::Point(orig[X], sp_document_height(inkscape_active_document()) - orig[Y]);
index a2f451e6558d412e0348a2cae18f75ac6b984c9e..02dcf23258b1156fc1884bb28c02bd203f4054b2 100644 (file)
std::vector<Geom::Point> handles;
double tmat[3][4];
-
- bool groupSpecialBehavior;
};
} //namespace LivePathEffect
index 65948837fc3fb745f3738c5e0af9689e6cd6208f..6293ba2334b259bb2f5bf7a001a9073caaaa3d62 100644 (file)
-#define INKSCAPE_LPE_TANGENT_TO_CURVE_CPP
-/** \file
- * Implementation of tangent-to-curve LPE.
- */
-
-/*
- * Authors:
- * Johan Engelen
- * Maximilian Albert
- *
- * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
- * Copyright (C) Maximilian Albert 2008 <maximilian.albert@gmail.com>
- *
- * Released under GNU GPL, read the file 'COPYING' for more information
- */
-
-#include "live_effects/lpe-tangent_to_curve.h"
-// FIXME: The following are only needed to convert the path's SPCurve* to pwd2.
-// There must be a more convenient way to achieve this.
-#include "sp-path.h"
-#include "display/curve.h"
-#include "libnr/n-art-bpath-2geom.h"
-
-#include <2geom/path.h>
-#include <2geom/transforms.h>
-
-namespace Inkscape {
-namespace LivePathEffect {
-
-/* FIXME: We should arguably make these member functions of LPETangentToCurve.
- Is there an easy way to register member functions with knotholder?
- */
-NR::Point attach_pt_get(SPItem *item) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return lpe->ptA;
-}
-
-void attach_pt_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- using namespace Geom;
-
- // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.
- SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(item));
- const NArtBpath *bpath = curve->get_bpath();
- Piecewise<D2<SBasis> > pwd2;
- std::vector<Geom::Path> pathv = BPath_to_2GeomPath(bpath);
- for (unsigned int i=0; i < pathv.size(); i++) {
- pwd2.concat(pathv[i].toPwSb());
- }
-
- double t0 = nearest_point(p.to_2geom(), pwd2);
- lpe->t_attach.param_set_value(t0);
-
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
-
-NR::Point left_end_get(SPItem *item) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return lpe->C;
-}
-
-NR::Point right_end_get(SPItem *item) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- return lpe->D;
-}
-
-void left_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);
- lpe->length_left.param_set_value(-lambda);
-
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
-
-void right_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {
- Inkscape::LivePathEffect::LPETangentToCurve *lpe =
- (Inkscape::LivePathEffect::LPETangentToCurve *) sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
-
- double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);
- lpe->length_right.param_set_value(lambda);
-
- sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true);
-}
-
-LPETangentToCurve::LPETangentToCurve(LivePathEffectObject *lpeobject) :
- Effect(lpeobject),
- t_attach(_("Location along curve"), _("Location of the point of attachment along the curve (between 0.0 and number-of-segments)"), "t_attach", &wr, this, 0.5),
- length_left(_("Length left"), _("Specifies the left end of the tangent"), "length-left", &wr, this, 150),
- length_right(_("Length right"), _("Specifies the right end of the tangent"), "length-right", &wr, this, 150),
- angle(_("Angle"), _("Additional angle between tangent and curve"), "angle", &wr, this, 0.0)
-{
- registerParameter( dynamic_cast<Parameter *>(&t_attach) );
- registerParameter( dynamic_cast<Parameter *>(&length_left) );
- registerParameter( dynamic_cast<Parameter *>(&length_right) );
- registerParameter( dynamic_cast<Parameter *>(&angle) );
- registerKnotHolderHandle(attach_pt_set, attach_pt_get);
- registerKnotHolderHandle(left_end_set, left_end_get);
- registerKnotHolderHandle(right_end_set, right_end_get);
-}
-
-LPETangentToCurve::~LPETangentToCurve()
-{
-}
-
-Geom::Piecewise<Geom::D2<Geom::SBasis> >
-LPETangentToCurve::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)
-{
- using namespace Geom;
- Piecewise<D2<SBasis> > output;
-
- ptA = pwd2_in.valueAt(t_attach);
- derivA = unit_vector(derivative(pwd2_in).valueAt(t_attach));
-
- // TODO: Why are positive angles measured clockwise, not counterclockwise?
- Geom::Rotate rot(Geom::Rotate::from_degrees(-angle));
- derivA = derivA * rot;
-
- C = ptA - derivA * length_left;
- D = ptA + derivA * length_right;
-
- output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));
-
- return output;
-}
-
-} //namespace LivePathEffect
-} /* namespace Inkscape */
-
-/*
- Local Variables:
- mode:c++
- c-file-style:"stroustrup"
- c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
- indent-tabs-mode:nil
- fill-column:99
- End:
-*/
-// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :
+#define INKSCAPE_LPE_TANGENT_TO_CURVE_CPP\r
+/** \file\r
+ * Implementation of tangent-to-curve LPE.\r
+ */\r
+\r
+/*\r
+ * Authors:\r
+ * Johan Engelen\r
+ * Maximilian Albert\r
+ *\r
+ * Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>\r
+ * Copyright (C) Maximilian Albert 2008 <maximilian.albert@gmail.com>\r
+ *\r
+ * Released under GNU GPL, read the file 'COPYING' for more information\r
+ */\r
+\r
+#include "live_effects/lpe-tangent_to_curve.h"\r
+// FIXME: The following are only needed to convert the path's SPCurve* to pwd2.\r
+// There must be a more convenient way to achieve this.\r
+#include "sp-path.h"\r
+#include "display/curve.h"\r
+#include "libnr/n-art-bpath-2geom.h"\r
+\r
+#include <2geom/path.h>\r
+#include <2geom/transforms.h>\r
+\r
+namespace Inkscape {\r
+namespace LivePathEffect {\r
+\r
+/* FIXME: We should make these member functions of LPETangentToCurve.\r
+ Is there an easy way to register member functions with knotholder?\r
+ KNOWN BUG: Because of the above, this effect does not work well when in an LPE stack\r
+*/\r
+NR::Point attach_pt_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return lpe->ptA;\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+void attach_pt_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (!lpe)\r
+ return;\r
+\r
+ using namespace Geom;\r
+\r
+ // FIXME: There must be a better way of converting the path's SPCurve* to pwd2.\r
+ SPCurve *curve = sp_path_get_curve_for_edit (SP_PATH(item));\r
+ const NArtBpath *bpath = curve->get_bpath();\r
+ Piecewise<D2<SBasis> > pwd2;\r
+ std::vector<Geom::Path> pathv = BPath_to_2GeomPath(bpath);\r
+ for (unsigned int i=0; i < pathv.size(); i++) {\r
+ pwd2.concat(pathv[i].toPwSb());\r
+ }\r
+\r
+ double t0 = nearest_point(p.to_2geom(), pwd2);\r
+ lpe->t_attach.param_set_value(t0);\r
+\r
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.\r
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);\r
+}\r
+\r
+NR::Point left_end_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return lpe->C;\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+NR::Point right_end_get(SPItem *item) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (lpe)\r
+ return lpe->D;\r
+ else\r
+ return NR::Point(0,0);\r
+}\r
+\r
+void left_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (!lpe)\r
+ return;\r
+\r
+ double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);\r
+ lpe->length_left.param_set_value(-lambda);\r
+\r
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.\r
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);\r
+}\r
+\r
+void right_end_set(SPItem *item, NR::Point const &p, NR::Point const &origin, guint state) {\r
+ Inkscape::LivePathEffect::LPETangentToCurve *lpe =\r
+ dynamic_cast<Inkscape::LivePathEffect::LPETangentToCurve *> (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)));\r
+\r
+ if (!lpe)\r
+ return;\r
+\r
+ double lambda = Geom::nearest_point(p.to_2geom(), lpe->ptA, lpe->derivA);\r
+ lpe->length_right.param_set_value(lambda);\r
+\r
+ // FIXME: this should not directly ask for updating the item. It should write to SVG, which triggers updating.\r
+ sp_lpe_item_update_patheffect (SP_LPE_ITEM(item), true, true);\r
+}\r
+\r
+LPETangentToCurve::LPETangentToCurve(LivePathEffectObject *lpeobject) :\r
+ Effect(lpeobject),\r
+ t_attach(_("Location along curve"), _("Location of the point of attachment along the curve (between 0.0 and number-of-segments)"), "t_attach", &wr, this, 0.5),\r
+ length_left(_("Length left"), _("Specifies the left end of the tangent"), "length-left", &wr, this, 150),\r
+ length_right(_("Length right"), _("Specifies the right end of the tangent"), "length-right", &wr, this, 150),\r
+ angle(_("Angle"), _("Additional angle between tangent and curve"), "angle", &wr, this, 0.0)\r
+{\r
+ registerParameter( dynamic_cast<Parameter *>(&t_attach) );\r
+ registerParameter( dynamic_cast<Parameter *>(&length_left) );\r
+ registerParameter( dynamic_cast<Parameter *>(&length_right) );\r
+ registerParameter( dynamic_cast<Parameter *>(&angle) );\r
+ registerKnotHolderHandle(attach_pt_set, attach_pt_get);\r
+ registerKnotHolderHandle(left_end_set, left_end_get);\r
+ registerKnotHolderHandle(right_end_set, right_end_get);\r
+}\r
+\r
+LPETangentToCurve::~LPETangentToCurve()\r
+{\r
+}\r
+\r
+Geom::Piecewise<Geom::D2<Geom::SBasis> >\r
+LPETangentToCurve::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > const & pwd2_in)\r
+{\r
+ using namespace Geom;\r
+ Piecewise<D2<SBasis> > output;\r
+\r
+ ptA = pwd2_in.valueAt(t_attach);\r
+ derivA = unit_vector(derivative(pwd2_in).valueAt(t_attach));\r
+\r
+ // TODO: Why are positive angles measured clockwise, not counterclockwise?\r
+ Geom::Rotate rot(Geom::Rotate::from_degrees(-angle));\r
+ derivA = derivA * rot;\r
+\r
+ C = ptA - derivA * length_left;\r
+ D = ptA + derivA * length_right;\r
+\r
+ output = Piecewise<D2<SBasis> >(D2<SBasis>(Linear(C[X], D[X]), Linear(C[Y], D[Y])));\r
+\r
+ return output;\r
+}\r
+\r
+} //namespace LivePathEffect\r
+} /* namespace Inkscape */\r
+\r
+/*\r
+ Local Variables:\r
+ mode:c++\r
+ c-file-style:"stroustrup"\r
+ c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))\r
+ indent-tabs-mode:nil\r
+ fill-column:99\r
+ End:\r
+*/\r
+// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :\r
index 34005e79199fa17ffcc5cb1cdcf910bb792ded4d..8a8dd94da0c18381263c8b053ddec28ece2b6845 100644 (file)
}
void
-LPEObjectReference::link(char *to)
+LPEObjectReference::link(const char *to)
{
if ( to == NULL ) {
quit_listening();
index 6a2f75327c9b7dd66ac8552e63b3569b0951a6cf..e5f7556f1668d138b899344c475c0ffc715caa07 100644 (file)
sigc::connection _delete_connection;
sigc::connection _changed_connection;
- void link(char* to);
+ void link(const char* to);
void unlink(void);
void start_listening(LivePathEffectObject* to);
void quit_listening(void);
diff --git a/src/nodepath.cpp b/src/nodepath.cpp
index ff442fd702aad76cfa8ba8f524b26e137e57311f..e827f9fb07dafa522d5c39433d58eefd700fa48c 100644 (file)
--- a/src/nodepath.cpp
+++ b/src/nodepath.cpp
#include <cstring>
#include <string>
#include "live_effects/lpeobject.h"
+#include "live_effects/effect.h"
#include "live_effects/parameter/parameter.h"
#include "util/mathfns.h"
#include "display/snap-indicator.h"
if ( sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(np->object)) ) {
np->repr_key = g_strdup("inkscape:original-d");
- LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(SP_LPE_ITEM(np->object));
- if (lpeobj && lpeobj->lpe) {
- lpeobj->lpe->setup_nodepath(np);
+ Inkscape::LivePathEffect::Effect* lpe = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(np->object));
+ if (lpe) {
+ lpe->setup_nodepath(np);
}
} else {
np->repr_key = g_strdup("d");
diff --git a/src/object-edit.cpp b/src/object-edit.cpp
index 091c997348abc04b930e8173ddd435b50037d93f..ecd6227f42cc781088b11d48e13a978098ba230b 100644 (file)
--- a/src/object-edit.cpp
+++ b/src/object-edit.cpp
{
SPKnotHolder *knot_holder = sp_knot_holder_new(desktop, item, NULL);
- Inkscape::LivePathEffect::Effect *effect = sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item));
- effect->addHandles(knot_holder);
+ Inkscape::LivePathEffect::Effect *effect = sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item));
+ if (!effect) {
+ g_error("sp_lpe_knot_holder: logical error, this method cannot be called with item having an LPE");
+ } else {
+ effect->addHandles(knot_holder);
+ }
return knot_holder;
}
SPKnotHolder *
sp_item_knot_holder(SPItem *item, SPDesktop *desktop)
{
- if (sp_lpe_item_has_path_effect(SP_LPE_ITEM(item)) &&
- sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item))->isVisible() &&
- sp_lpe_item_get_livepatheffect(SP_LPE_ITEM(item))->providesKnotholder()) {
+ if (sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item)) &&
+ sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item))->isVisible() &&
+ sp_lpe_item_get_current_lpe(SP_LPE_ITEM(item))->providesKnotholder()) {
return sp_lpe_knot_holder(item, desktop);
- } else
- if (SP_IS_RECT(item)) {
+ } else if (SP_IS_RECT(item)) {
return sp_rect_knot_holder(item, desktop);
} else if (SP_IS_BOX3D(item)) {
return box3d_knot_holder(item, desktop);
diff --git a/src/path-chemistry.cpp b/src/path-chemistry.cpp
index 5b57e326efb52a0f6b357aac3e7adbb54d33f286..996ae3fd5203afc8521730305ee0fb363620766f 100644 (file)
--- a/src/path-chemistry.cpp
+++ b/src/path-chemistry.cpp
@@ -368,7 +368,7 @@ sp_item_list_to_curves(const GSList *items, GSList **selected, GSList **to_selec
}
if (SP_IS_GROUP(item)) {
- sp_lpe_item_remove_path_effect(SP_LPE_ITEM(item), true);
+ sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(item), true);
GSList *item_list = sp_item_group_item_list(SP_GROUP(item));
GSList *item_to_select = NULL;
index 0f89464411e395c9a6235bdd24fd5d1b80b54418..9c826c949a8ad38706e8f6341213dcd697a102c8 100644 (file)
void sp_selection_remove_livepatheffect_impl(SPItem *item)
{
if ( item && SP_IS_LPE_ITEM(item) ) {
- sp_lpe_item_remove_path_effect(SP_LPE_ITEM(item), false);
+ sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(item), false);
}
}
diff --git a/src/shape-editor.cpp b/src/shape-editor.cpp
index 40e92e0dd0033565fa7b314b5e1e6f2481348db7..1d60671aad089cf5d0595e740504b6122e4b5b3e 100644 (file)
--- a/src/shape-editor.cpp
+++ b/src/shape-editor.cpp
if (item) {
SPLPEItem *lpeitem = SP_LPE_ITEM(item);
- if (!sp_lpe_item_has_path_effect(lpeitem) ||
- !sp_lpe_item_get_livepatheffect(lpeitem)->isVisible() ||
- !sp_lpe_item_get_livepatheffect(lpeitem)->providesKnotholder()) {
+ if (!sp_lpe_item_get_current_lpe(lpeitem) || // if returns NULL, the whole expression evaluates to true and C++ will not call the otherwise crashing 2 functions below
+ !sp_lpe_item_get_current_lpe(lpeitem)->isVisible() ||
+ !sp_lpe_item_get_current_lpe(lpeitem)->providesKnotholder()) {
// only create nodepath if the item either doesn't have an LPE
// or the LPE is invisible or it doesn't provide a knotholder itself
this->nodepath =
diff --git a/src/sp-item-group.cpp b/src/sp-item-group.cpp
index acdf8aa36628914359d6e401d532b3ec0592fd3d..20efd8fe72c76e4c370d84f51eb9e015b1ab8bdb 100644 (file)
--- a/src/sp-item-group.cpp
+++ b/src/sp-item-group.cpp
#include <string>
#include "display/nr-arena-group.h"
+#include "display/curve.h"
#include "libnr/nr-matrix-ops.h"
#include "libnr/nr-matrix-fns.h"
#include "xml/repr.h"
#include "inkscape.h"
#include "desktop-handles.h"
#include "selection.h"
+#include "live_effects/lpeobject.h"
+#include "live_effects/lpeobject-reference.h"
static void sp_group_class_init (SPGroupClass *klass);
static void sp_group_init (SPGroup *group);
static void sp_group_snappoints (SPItem const *item, SnapPointsIter p);
static void sp_group_update_patheffect(SPLPEItem *lpeitem, bool write);
+static void sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup);
static SPLPEItemClass * parent_class;
static void
sp_group_modified (SPObject *object, guint flags)
{
+ if (((SPObjectClass *) (parent_class))->modified)
+ ((SPObjectClass *) (parent_class))->modified (object, flags);
+
SP_GROUP(object)->group->onModified(flags);
}
gitem = SP_ITEM(group);
}
- sp_lpe_item_remove_path_effect(SP_LPE_ITEM(group), false);
+ sp_lpe_item_remove_all_path_effects(SP_LPE_ITEM(group), false);
/* Step 1 - generate lists of children objects */
GSList *items = NULL;
}
static void
-sp_group_update_patheffect (SPLPEItem *lpeitem, bool /*write*/)
+sp_group_update_patheffect (SPLPEItem *lpeitem, bool write)
{
#ifdef GROUP_VERBOSE
g_message("sp_group_update_patheffect: %p\n", lpeitem);
for ( GSList const *iter = item_list; iter; iter = iter->next ) {
SPObject *subitem = static_cast<SPObject *>(iter->data);
if (SP_IS_LPE_ITEM(subitem)) {
- sp_lpe_item_update_patheffect(SP_LPE_ITEM(subitem), true);
+ if (SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (subitem))->update_patheffect) {
+ SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (subitem))->update_patheffect (SP_LPE_ITEM(subitem), write);
+ }
+ }
+ }
+
+ if (sp_lpe_item_has_path_effect(lpeitem) && sp_lpe_item_path_effects_enabled(lpeitem)) {
+ for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ lpeobj->lpe->doBeforeEffect(lpeitem);
}
+
+ sp_group_perform_patheffect(SP_GROUP(lpeitem), SP_GROUP(lpeitem));
}
}
+static void
+sp_group_perform_patheffect(SPGroup *group, SPGroup *topgroup)
+{
+ GSList const *item_list = sp_item_group_item_list(SP_GROUP(group));
+ for ( GSList const *iter = item_list; iter; iter = iter->next ) {
+ SPObject *subitem = static_cast<SPObject *>(iter->data);
+ if (SP_IS_GROUP(subitem)) {
+ sp_group_perform_patheffect(SP_GROUP(subitem), topgroup);
+ } else if (SP_IS_SHAPE(subitem)) {
+ SPCurve * c = sp_shape_get_curve(SP_SHAPE(subitem));
+ sp_lpe_item_perform_path_effect(SP_LPE_ITEM(topgroup), c);
+ sp_shape_set_curve(SP_SHAPE(subitem), c, TRUE);
+
+ Inkscape::XML::Node *repr = SP_OBJECT_REPR(subitem);
+
+ NArtBpath *abp = c->first_bpath();
+ if (abp) {
+ gchar *str = sp_svg_write_path(abp);
+ repr->setAttribute("d", str);
+ g_free(str);
+ } else {
+ repr->setAttribute("d", "");
+ }
+
+ c->unref();
+ }
+ }
+}
/*
Local Variables:
diff --git a/src/sp-item.cpp b/src/sp-item.cpp
index 0ab8566eb9479e369760d50616807107da370c23..be6be4f63895e3decb6e28799070726c8dce2b84 100644 (file)
--- a/src/sp-item.cpp
+++ b/src/sp-item.cpp
#include "live_effects/lpeobject.h"
#include "live_effects/effect.h"
+#include "live_effects/lpeobject-reference.h"
#define noSP_ITEM_DEBUG_IDLE
@@ -1296,15 +1297,21 @@ sp_item_adjust_livepatheffect (SPItem *item, NR::Matrix const &postmul, bool set
SPLPEItem *lpeitem = SP_LPE_ITEM (item);
if ( sp_lpe_item_has_path_effect(lpeitem) ) {
- LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
- LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary();
- if (new_lpeobj != lpeobj) {
- sp_lpe_item_set_path_effect(lpeitem, new_lpeobj);
- }
-
- Inkscape::LivePathEffect::Effect * effect = sp_lpe_item_get_livepatheffect(lpeitem);
- if (effect) {
- effect->transform_multiply (to_2geom(postmul), set);
+ PathEffectList effect_list = sp_lpe_item_get_effect_list(lpeitem);
+ for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
+ {
+ // If the path effect is used by 2 or more items, fork it
+ // so that each object has its own independent copy of the effect
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+ LivePathEffectObject *new_lpeobj = lpeobj->fork_private_if_necessary();
+ if (new_lpeobj != lpeobj) {
+ sp_lpe_item_replace_path_effect(lpeitem, lpeobj, new_lpeobj);
+ }
+
+ if (lpeobj->lpe) {
+ Inkscape::LivePathEffect::Effect * effect = lpeobj->lpe;
+ effect->transform_multiply(to_2geom(postmul), set);
+ }
}
}
}
diff --git a/src/sp-lpe-item.cpp b/src/sp-lpe-item.cpp
index f16b455ddf33fe3d8c1a4efb283aa5bef57e853b..12473f770d5848601e55cdf55d1ab7a2f37deb26 100644 (file)
--- a/src/sp-lpe-item.cpp
+++ b/src/sp-lpe-item.cpp
#include "xml/repr.h"
#include "uri.h"
+#include <algorithm>
+
/* LPEItem base class */
static void sp_lpe_item_class_init(SPLPEItemClass *klass);
@@ -46,11 +48,16 @@ static Inkscape::XML::Node *sp_lpe_item_write(SPObject *object, Inkscape::XML::N
static void sp_lpe_item_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
static void sp_lpe_item_remove_child (SPObject * object, Inkscape::XML::Node * child);
+static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
+
static void lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem);
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem);
+typedef std::list<std::string> HRefList;
+static std::string patheffectlist_write_svg(PathEffectList const & list);
+static std::string hreflist_write_svg(HRefList const & list);
static SPItemClass *parent_class;
static void
sp_lpe_item_class_init(SPLPEItemClass *klass)
-{
+{
GObjectClass *gobject_class;
SPObjectClass *sp_object_class;
sp_object_class->write = sp_lpe_item_write;
sp_object_class->child_added = sp_lpe_item_child_added;
sp_object_class->remove_child = sp_lpe_item_remove_child;
-
+
klass->update_patheffect = NULL;
}
static void
sp_lpe_item_init(SPLPEItem *lpeitem)
{
- lpeitem->path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(lpeitem));
+ lpeitem->path_effects_enabled = 1;
+
+ lpeitem->path_effect_list = new PathEffectList();
+ lpeitem->current_path_effect = NULL;
+
new (&lpeitem->lpe_modified_connection) sigc::connection();
}
if (((GObjectClass *) (parent_class))->finalize) {
(* ((GObjectClass *) (parent_class))->finalize)(object);
}
+
+ delete SP_LPE_ITEM(object)->path_effect_list;
}
/**
static void
sp_lpe_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
{
- SP_LPE_ITEM(object)->path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_LPE_ITEM(object)));
-
sp_object_read_attr(object, "inkscape:path-effect");
-
+
if (((SPObjectClass *) parent_class)->build) {
((SPObjectClass *) parent_class)->build(object, document, repr);
}
SPLPEItem *lpeitem;
lpeitem = (SPLPEItem *) object;
- lpeitem->path_effect_ref->detach();
-
lpeitem->lpe_modified_connection.disconnect();
lpeitem->lpe_modified_connection.~connection();
switch (key) {
case SP_ATTR_INKSCAPE_PATH_EFFECT:
- if ( value && lpeitem->path_effect_ref->lpeobject_href
- && streq(value, lpeitem->path_effect_ref->lpeobject_href) ) {
- /* No change, do nothing. */
- } else {
- if (value) {
- // Now do the attaching, which emits the changed signal.
- try {
- lpeitem->path_effect_ref->link((gchar*)value);
- } catch (Inkscape::BadURIException &e) {
- g_warning("%s", e.what());
- lpeitem->path_effect_ref->detach();
+ {
+ lpeitem->current_path_effect = NULL;
+
+ // Disable the path effects while populating the LPE list
+ sp_lpe_item_enable_path_effects(lpeitem, false);
+
+ // Clear the path effect list
+ PathEffectList::iterator it = lpeitem->path_effect_list->begin();
+ while ( it != lpeitem->path_effect_list->end() )
+ {
+ (*it)->unlink();
+ delete *it;
+ it = lpeitem->path_effect_list->erase(it);
+ }
+
+ // Parse the contents of "value" to rebuild the path effect reference list
+ if ( value ) {
+ std::istringstream iss(value);
+ std::string href;
+ while (std::getline(iss, href, ';'))
+ {
+ Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref;
+ path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(lpeitem));
+ path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_LPE_ITEM(object)));
+ // Now do the attaching, which emits the changed signal.
+ // Fixme, it should not do this changed signal and updating before all effects are added to the path_effect_list
+ try {
+ path_effect_ref->link(href.c_str());
+ } catch (Inkscape::BadURIException &e) {
+ g_warning("BadURIException: %s", e.what());
+ path_effect_ref->unlink();
+ delete path_effect_ref;
+ path_effect_ref = NULL;
+ }
+
+ if (path_effect_ref) {
+ lpeitem->path_effect_list->push_back(path_effect_ref);
+ }
}
- } else {
- // Detach, which emits the changed signal.
- lpeitem->path_effect_ref->detach();
}
+
+ sp_lpe_item_enable_path_effects(lpeitem, true);
}
break;
default:
static void
sp_lpe_item_modified (SPObject *object, unsigned int flags)
{
- if (((SPObjectClass *) (parent_class))->modified) {
- (* ((SPObjectClass *) (parent_class))->modified) (object, flags);
- }
+
+ if (SP_IS_GROUP(object) && (flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_USER_MODIFIED_FLAG_B)) {
+ sp_lpe_item_update_patheffect(SP_LPE_ITEM(object), true, true);
+ }
+
+ if (((SPObjectClass *) (parent_class))->modified) {
+ (* ((SPObjectClass *) (parent_class))->modified) (object, flags);
+ }
}
/**
SPLPEItem *lpeitem = (SPLPEItem *) object;
if ( sp_lpe_item_has_path_effect(lpeitem) ) {
- repr->setAttribute("inkscape:path-effect", lpeitem->path_effect_ref->lpeobject_href);
+ std::string href = patheffectlist_write_svg(*lpeitem->path_effect_list);
+ repr->setAttribute("inkscape:path-effect", href.c_str());
} else {
repr->setAttribute("inkscape:path-effect", NULL);
}
return repr;
}
-
-LivePathEffectObject *
-sp_lpe_item_get_livepatheffectobject(SPLPEItem *lpeitem) {
- if (!lpeitem) return NULL;
-
- if (sp_lpe_item_has_path_effect(lpeitem)) {
- return lpeitem->path_effect_ref->lpeobject;
- } else {
- return NULL;
- }
-}
-
-Inkscape::LivePathEffect::Effect *
-sp_lpe_item_get_livepatheffect(SPLPEItem *lpeitem) {
- if (!lpeitem) return NULL;
-
- LivePathEffectObject * lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
- if (lpeobj)
- return lpeobj->lpe;
- else
- return NULL;
-}
-
void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve) {
if (!lpeitem) return;
if (!curve) return;
- if (sp_lpe_item_has_path_effect(lpeitem)) {
- LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
- if (lpeobj->lpe->isVisible()) {
- lpeobj->lpe->doBeforeEffect(lpeitem);
- lpeobj->lpe->doEffect(curve);
+ if (sp_lpe_item_has_path_effect(lpeitem) && sp_lpe_item_path_effects_enabled(lpeitem)) {
+ for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
+ {
+ LivePathEffectObject *lpeobj = (*it)->lpeobject;
+
+ if (lpeobj->lpe->isVisible()) {
+ // Groups have their doBeforeEffect called elsewhere
+ if (!SP_IS_GROUP(lpeitem)) {
+ lpeobj->lpe->doBeforeEffect(lpeitem);
+ }
+
+ lpeobj->lpe->doEffect(curve);
+ }
}
}
-
- SPObject *parent = lpeitem->parent;
- if (parent && SP_IS_LPE_ITEM(parent))
- sp_lpe_item_perform_path_effect(SP_LPE_ITEM(parent), curve);
}
/**
* Calls any registered handlers for the update_patheffect action
*/
void
-sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool write)
+sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write)
{
#ifdef SHAPE_VERBOSE
g_message("sp_lpe_item_update_patheffect: %p\n", lpeitem);
g_return_if_fail (lpeitem != NULL);
g_return_if_fail (SP_IS_LPE_ITEM (lpeitem));
- if (SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (lpeitem))->update_patheffect) {
- SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (lpeitem))->update_patheffect (lpeitem, write);
+ SPLPEItem *top;
+
+ if (wholetree) {
+ SPObject *prev_parent = lpeitem;
+ SPObject *parent = prev_parent->parent;
+ while (parent && SP_IS_LPE_ITEM(parent) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(parent))) {
+ prev_parent = parent;
+ parent = prev_parent->parent;
+ }
+ top = SP_LPE_ITEM(prev_parent);
+ }
+ else {
+ top = lpeitem;
+ }
+
+ if (SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (top))->update_patheffect) {
+ SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (top))->update_patheffect (top, write);
}
}
static void
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
{
- sp_lpe_item_update_patheffect (lpeitem, true);
+ sp_lpe_item_update_patheffect (lpeitem, true, true);
}
static void
}
else if (SP_IS_PATH(lpeitem)) {
Inkscape::XML::Node *repr = SP_OBJECT_REPR(lpeitem);
- if (!sp_lpe_item_has_path_effect_recursive(lpeitem)
+ if (!sp_lpe_item_has_path_effect_recursive(lpeitem)
&& repr->attribute("inkscape:original-d")) {
repr->setAttribute("d", repr->attribute("inkscape:original-d"));
repr->setAttribute("inkscape:original-d", NULL);
}
else {
- sp_lpe_item_update_patheffect(lpeitem, true);
+ sp_lpe_item_update_patheffect(lpeitem, true, true);
}
}
}
-void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset)
+void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset)
{
- if (!value) {
- sp_lpe_item_remove_path_effect(lpeitem, false);
- } else {
- SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", value);
-
- // Ask the path effect to reset itself if it doesn't have parameters yet
- if (lpeitem->path_effect_ref) {
- LivePathEffectObject *lpeobj = lpeitem->path_effect_ref->lpeobject;
- if (lpeobj && lpeobj->lpe) {
- if(reset) {
- // has to be called when all the subitems have their lpes applied
- lpeobj->lpe->resetDefaults(lpeitem);
- }
- // perform this once when the effect is applied
- lpeobj->lpe->doOnApply(SP_LPE_ITEM(lpeitem));
- }
+ if (value) {
+ // Apply the path effects here because in the casse of a group, lpe->resetDefaults
+ // needs that all the subitems have their effects applied
+ sp_lpe_item_update_patheffect(lpeitem, false, true);
+
+ // Disable the path effects while preparing the new lpe
+ sp_lpe_item_enable_path_effects(lpeitem, false);
+
+ // Add the new reference to the list of LPE references
+ HRefList hreflist;
+ for (PathEffectList::const_iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
+ {
+ hreflist.push_back( std::string((*it)->lpeobject_href) );
}
-
+ hreflist.push_back( std::string(value) );
+ std::string hrefs = hreflist_write_svg(hreflist);
+
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", hrefs.c_str());
+
// make sure there is an original-d for paths!!!
sp_lpe_item_create_original_path_recursive(lpeitem);
+
+ LivePathEffectObject *lpeobj = lpeitem->path_effect_list->back()->lpeobject;
+ if (lpeobj && lpeobj->lpe) {
+ // Ask the path effect to reset itself if it doesn't have parameters yet
+ if (reset) {
+ // has to be called when all the subitems have their lpes applied
+ lpeobj->lpe->resetDefaults(lpeitem);
+ }
+ }
+
+ //Enable the path effects now that everything is ready to apply the new path effect
+ sp_lpe_item_enable_path_effects(lpeitem, true);
+
+ // Apply the path effect
+ sp_lpe_item_update_patheffect(lpeitem, true, true);
}
}
-void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj)
+void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj)
{
const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
gchar *hrefstr = g_strdup_printf("#%s", repr_id);
- sp_lpe_item_set_path_effect(lpeitem, hrefstr, false);
+ sp_lpe_item_add_path_effect(lpeitem, hrefstr, false);
g_free(hrefstr);
}
-void sp_lpe_item_remove_path_effect(SPLPEItem *lpeitem, bool keep_paths)
+void sp_lpe_item_remove_current_path_effect(SPLPEItem *lpeitem, bool keep_paths)
{
- Inkscape::XML::Node *repr = SP_OBJECT_REPR(lpeitem);
- repr->setAttribute("inkscape:path-effect", NULL);
-
+ Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+ if (!lperef)
+ return;
+
+ PathEffectList new_list = *lpeitem->path_effect_list;
+ new_list.remove(lperef); //current lpe ref is always our 'own' pointer from the path_effect_list
+ std::string r = patheffectlist_write_svg(new_list);
+
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
+
if (!keep_paths) {
sp_lpe_item_cleanup_original_path_recursive(lpeitem);
}
}
+void sp_lpe_item_remove_all_path_effects(SPLPEItem *lpeitem, bool keep_paths)
+{
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", NULL);
+
+ if (!keep_paths) {
+ sp_lpe_item_cleanup_original_path_recursive(lpeitem);
+ }
+}
+
+void sp_lpe_item_down_current_path_effect(SPLPEItem *lpeitem)
+{
+ Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+ if (!lperef)
+ return;
+
+ PathEffectList new_list = *lpeitem->path_effect_list;
+ PathEffectList::iterator cur_it = find( new_list.begin(), new_list.end(), lperef );
+ if (cur_it != new_list.end()) {
+ PathEffectList::iterator down_it = cur_it;
+ down_it++;
+ if (down_it != new_list.end()) { // perhaps current effect is already last effect
+ std::iter_swap(cur_it, down_it);
+ }
+ }
+ std::string r = patheffectlist_write_svg(new_list);
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
+
+ sp_lpe_item_cleanup_original_path_recursive(lpeitem);
+}
+
+void sp_lpe_item_up_current_path_effect(SPLPEItem *lpeitem)
+{
+ Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+ if (!lperef)
+ return;
+
+ PathEffectList new_list = *lpeitem->path_effect_list;
+ PathEffectList::iterator cur_it = find( new_list.begin(), new_list.end(), lperef );
+ if (cur_it != new_list.end() && cur_it != new_list.begin()) {
+ PathEffectList::iterator up_it = cur_it;
+ up_it--;
+ std::iter_swap(cur_it, up_it);
+ }
+ std::string r = patheffectlist_write_svg(new_list);
+
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
+
+ sp_lpe_item_cleanup_original_path_recursive(lpeitem);
+}
+
+
bool sp_lpe_item_has_path_effect(SPLPEItem *lpeitem)
{
- return lpeitem->path_effect_ref && lpeitem->path_effect_ref->lpeobject;
+ return !lpeitem->path_effect_list->empty();
}
bool sp_lpe_item_has_path_effect_recursive(SPLPEItem *lpeitem)
void sp_lpe_item_edit_next_param_oncanvas(SPLPEItem *lpeitem, SPDesktop *dt)
{
- LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
- if (lpeobj && lpeobj->lpe) {
- lpeobj->lpe->editNextParamOncanvas(SP_ITEM(lpeitem), dt);
+ Inkscape::LivePathEffect::LPEObjectReference *lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+ if (lperef && lperef->lpeobject && lperef->lpeobject->lpe) {
+ lperef->lpeobject->lpe->editNextParamOncanvas(SP_ITEM(lpeitem), dt);
}
}
@@ -428,7 +539,7 @@ sp_lpe_item_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape:
{
if (((SPObjectClass *) (parent_class))->child_added)
(* ((SPObjectClass *) (parent_class))->child_added) (object, child, ref);
-
+
if (SP_IS_LPE_ITEM(object) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(object))) {
SPObject *ochild = sp_object_get_child_by_repr(object, child);
if ( ochild && SP_IS_LPE_ITEM(ochild) ) {
(* ((SPObjectClass *) (parent_class))->remove_child) (object, child);
}
+static std::string patheffectlist_write_svg(PathEffectList const & list)
+{
+ HRefList hreflist;
+ for (PathEffectList::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ hreflist.push_back( std::string((*it)->lpeobject_href) );
+ }
+ return hreflist_write_svg(hreflist);
+}
+
+/**
+ * THE function that should be used to generate any patheffectlist string.
+ * one of the methods to change the effect list:
+ * - create temporary href list
+ * - populate the templist with the effects from the old list that you want to have and their order
+ * - call this function with temp list as param
+ */
+static std::string hreflist_write_svg(HRefList const & list)
+{
+ std::string r;
+ bool semicolon_first = false;
+ for (HRefList::const_iterator it = list.begin(); it != list.end(); ++it)
+ {
+ if (semicolon_first) {
+ r += ';';
+ }
+ semicolon_first = true;
+
+ r += (*it);
+ }
+ return r;
+}
+
+// Return a copy of the effect list
+PathEffectList sp_lpe_item_get_effect_list(SPLPEItem *lpeitem)
+{
+ return *lpeitem->path_effect_list;
+}
+
+Inkscape::LivePathEffect::LPEObjectReference* sp_lpe_item_get_current_lpereference(SPLPEItem *lpeitem)
+{
+ if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty())
+ sp_lpe_item_set_current_path_effect(lpeitem, lpeitem->path_effect_list->back());
+
+ return lpeitem->current_path_effect;
+}
+
+Inkscape::LivePathEffect::Effect* sp_lpe_item_get_current_lpe(SPLPEItem *lpeitem)
+{
+ Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+
+ if (lperef && lperef->lpeobject)
+ return lperef->lpeobject->lpe;
+ else
+ return NULL;
+}
+
+bool sp_lpe_item_set_current_path_effect(SPLPEItem *lpeitem, Inkscape::LivePathEffect::LPEObjectReference* lperef)
+{
+ for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++) {
+ if ((*it)->lpeobject_repr == lperef->lpeobject_repr) {
+ lpeobject_ref_changed(NULL, (*it)->lpeobject, SP_LPE_ITEM(lpeitem)); // FIXME: explain why this is here?
+ lpeitem->current_path_effect = (*it); // current_path_effect should always be a pointer from the path_effect_list !
+ return true;
+ }
+ }
+
+ return false;
+}
+
+void sp_lpe_item_replace_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * old_lpeobj,
+ LivePathEffectObject * new_lpeobj)
+{
+ HRefList hreflist;
+ for (PathEffectList::const_iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
+ {
+ if ((*it)->lpeobject == old_lpeobj) {
+ const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
+ gchar *hrefstr = g_strdup_printf("#%s", repr_id);
+ hreflist.push_back( std::string(hrefstr) );
+ g_free(hrefstr);
+ }
+ else {
+ hreflist.push_back( std::string((*it)->lpeobject_href) );
+ }
+ }
+ std::string r = hreflist_write_svg(hreflist);
+ SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
+}
+
+// Enable or disable the path effects of the item.
+// The counter allows nested calls
+static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable)
+{
+ if (enable) {
+ lpeitem->path_effects_enabled++;
+ }
+ else {
+ lpeitem->path_effects_enabled--;
+ }
+}
+
+// Are the path effects enabled on this item ?
+bool sp_lpe_item_path_effects_enabled(SPLPEItem *lpeitem)
+{
+ return lpeitem->path_effects_enabled > 0;
+}
+
/*
Local Variables:
mode:c++
diff --git a/src/sp-lpe-item.h b/src/sp-lpe-item.h
index 7d85bb2be854a934ccfea298a8b8cbc6c9c58995..3aba7b8a7a4aa16de87c5ae5a16e8c7e709bb819 100644 (file)
--- a/src/sp-lpe-item.h
+++ b/src/sp-lpe-item.h
#include "sp-item.h"
#include "display/display-forward.h"
+#include <list>
+
#define SP_TYPE_LPE_ITEM (sp_lpe_item_get_type())
#define SP_LPE_ITEM(o) (G_TYPE_CHECK_INSTANCE_CAST((o), SP_TYPE_LPE_ITEM, SPLPEItem))
#define SP_LPE_ITEM_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), SP_TYPE_LPE_ITEM, SPLPEItemClass))
};
};
+typedef std::list<Inkscape::LivePathEffect::LPEObjectReference *> PathEffectList;
+
struct SPLPEItem : public SPItem {
- Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref;
+ int path_effects_enabled;
+
+ PathEffectList* path_effect_list;
+ Inkscape::LivePathEffect::LPEObjectReference* current_path_effect;
+
sigc::connection lpe_modified_connection;
};
GType sp_lpe_item_get_type();
-LivePathEffectObject * sp_lpe_item_get_livepatheffectobject(SPLPEItem *lpeitem);
-Inkscape::LivePathEffect::Effect * sp_lpe_item_get_livepatheffect(SPLPEItem *lpeitem);
-void sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool write);
+void sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write);
void sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve);
-void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset);
-void sp_lpe_item_set_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj);
-void sp_lpe_item_remove_path_effect(SPLPEItem *lpeitem, bool keep_paths);
+void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset);
+void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj);
+void sp_lpe_item_replace_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * old_lpeobj,
+ LivePathEffectObject * new_lpeobj);
+void sp_lpe_item_remove_all_path_effects(SPLPEItem *lpeitem, bool keep_paths);
+void sp_lpe_item_remove_current_path_effect(SPLPEItem *lpeitem, bool keep_paths);
+void sp_lpe_item_down_current_path_effect(SPLPEItem *lpeitem);
+void sp_lpe_item_up_current_path_effect(SPLPEItem *lpeitem);
bool sp_lpe_item_has_path_effect(SPLPEItem *lpeitem);
bool sp_lpe_item_has_path_effect_recursive(SPLPEItem *lpeitem);
void sp_lpe_item_edit_next_param_oncanvas(SPLPEItem *lpeitem, SPDesktop *dt);
+PathEffectList sp_lpe_item_get_effect_list(SPLPEItem *lpeitem);
+Inkscape::LivePathEffect::LPEObjectReference* sp_lpe_item_get_current_lpereference(SPLPEItem *lpeitem);
+Inkscape::LivePathEffect::Effect* sp_lpe_item_get_current_lpe(SPLPEItem *lpeitem);
+bool sp_lpe_item_set_current_path_effect(SPLPEItem *lpeitem, Inkscape::LivePathEffect::LPEObjectReference* lperef);
+bool sp_lpe_item_path_effects_enabled(SPLPEItem *lpeitem);
#endif /* !SP_LPE_ITEM_H_SEEN */
diff --git a/src/sp-path.cpp b/src/sp-path.cpp
index 4654b1b131645bcc78902b33b7588730347813d4..b2e26efa03a91e7b36fad69b85acb3643d195b8f 100644 (file)
--- a/src/sp-path.cpp
+++ b/src/sp-path.cpp
@@ -464,7 +464,7 @@ sp_path_set_original_curve (SPPath *path, SPCurve *curve, unsigned int owner, bo
path->original_curve = curve->copy();
}
}
- sp_path_update_patheffect(path, write);
+ sp_lpe_item_update_patheffect(path, true, write);
SP_OBJECT(path)->requestDisplayUpdate(SP_OBJECT_MODIFIED_FLAG);
}
diff --git a/src/ui/clipboard.cpp b/src/ui/clipboard.cpp
index fff6e3b097af9cf9cff0008b5fcea2ea61355b6d..2d38f5ccd227909ed44b289618749aa962f99972 100644 (file)
--- a/src/ui/clipboard.cpp
+++ b/src/ui/clipboard.cpp
#include "sp-textpath.h"
#include "sp-rect.h"
#include "live_effects/lpeobject.h"
+#include "live_effects/lpeobject-reference.h"
#include "live_effects/parameter/path.h"
#include "svg/svg.h" // for sp_svg_transform_write, used in _copySelection
#include "svg/css-ostringstream.h" // used in _parseColor
}
}
// For lpe items, copy liveeffect if applicable
+ // TODO: copy the whole effect stack. now it only copies current selected effect
if (SP_IS_LPE_ITEM(item)) {
SPLPEItem *lpeitem = SP_LPE_ITEM (item);
if (sp_lpe_item_has_path_effect(lpeitem)) {
- _copyNode(SP_OBJECT_REPR(SP_OBJECT(sp_lpe_item_get_livepatheffectobject(lpeitem))), _doc, _defs);
+ Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
+ if (lperef && lperef->lpeobject) {
+ _copyNode(SP_OBJECT_REPR(SP_OBJECT(lperef->lpeobject)), _doc, _defs);
+ }
}
}
// For 3D boxes, copy perspectives
if (!obj) return;
// if the effect is not used by anyone, we might as well take it
LivePathEffectObject *lpeobj = LIVEPATHEFFECT(obj)->fork_private_if_necessary(1);
- sp_lpe_item_set_path_effect(lpeitem, lpeobj);
+ sp_lpe_item_add_path_effect(lpeitem, lpeobj);
}
}
index 43cdb726cd002078a636861f99e1b78c799cb321..c92d015f53f1e67e41b7e66c3a942405ca00557c 100644 (file)
#include "sp-item-group.h"
#include "sp-path.h"
#include "sp-rect.h"
+#include "sp-lpe-item.h"
#include "path-chemistry.h"
#include "live_effects/effect.h"
#include "live_effects/lpeobject.h"
#include "document-private.h"
#include "xml/node.h"
#include "xml/document.h"
+#include <gtkmm/stock.h>
+#include <gtkmm/toolbar.h>
+
+#include "live_effects/lpeobject-reference.h"
namespace Inkscape {
class Application;
@@ -59,38 +64,88 @@ static void lpeeditor_selection_changed (Inkscape::Selection * selection, gpoint
LivePathEffectEditor::LivePathEffectEditor()
: UI::Widget::Panel("", "dialogs.livepatheffect", SP_VERB_DIALOG_LIVE_PATH_EFFECT),
combo_effecttype(Inkscape::LivePathEffect::LPETypeConverter),
- button_apply(_("_Apply"), _("Apply chosen effect to selection")),
- button_remove(_("_Remove"), _("Remove effect from selection")),
effectwidget(NULL),
explain_label("", Gtk::ALIGN_CENTER),
effectapplication_frame(_("Apply new effect")),
effectcontrol_frame(_("Current effect")),
- current_desktop(NULL)
+ effectlist_frame(_("Effect list")),
+ button_up(Gtk::Stock::GO_UP),
+ button_down(Gtk::Stock::GO_DOWN),
+ button_apply(Gtk::Stock::ADD),
+ button_remove(Gtk::Stock::REMOVE),
+ current_desktop(NULL),
+ current_lpeitem(NULL)
{
Gtk::Box *contents = _getContents();
contents->set_spacing(4);
+ //Add the TreeView, inside a ScrolledWindow, with the button underneath:
+ scrolled_window.add(effectlist_view);
+ //Only show the scrollbars when they are necessary:
+ scrolled_window.set_policy(Gtk::POLICY_AUTOMATIC, Gtk::POLICY_AUTOMATIC);
+
effectapplication_hbox.set_spacing(4);
effectcontrol_vbox.set_spacing(4);
+ effectlist_vbox.set_spacing(4);
effectapplication_hbox.pack_start(combo_effecttype, true, true);
effectapplication_hbox.pack_start(button_apply, true, true);
effectapplication_frame.add(effectapplication_hbox);
+ effectlist_vbox.pack_start(scrolled_window, Gtk::PACK_EXPAND_WIDGET);
+ effectlist_vbox.pack_end(toolbar, Gtk::PACK_SHRINK);
+ // effectlist_vbox.pack_end(button_hbox, Gtk::PACK_SHRINK);
+ effectlist_frame.add(effectlist_vbox);
+
effectcontrol_vbox.pack_start(explain_label, true, true);
- effectcontrol_vbox.pack_end(button_remove, true, true);
effectcontrol_frame.add(effectcontrol_vbox);
+ // button_hbox.pack_start(button_up, true, true);
+ // button_hbox.pack_start(button_down, true, true);
+ // button_hbox.pack_end(button_remove, true, true);
+ toolbar.set_toolbar_style(Gtk::TOOLBAR_ICONS);
+ // Add toolbar items to toolbar
+ toolbar.append(button_up);
+ toolbar.append(button_down);
+ toolbar.append(button_remove);
+
+
+ // Add toolbar
+ //add_toolbar(toolbar);
+ toolbar.show_all(); //Show the toolbar and all its child widgets.
+
+
+ //Create the Tree model:
+ effectlist_store = Gtk::ListStore::create(columns);
+ effectlist_view.set_model(effectlist_store);
+
+ effectlist_view.set_rules_hint();
+ effectlist_view.set_headers_clickable(true);
+ effectlist_view.set_headers_visible(true);
+
+ // Handle tree selections
+ effectlist_selection = effectlist_view.get_selection();
+ effectlist_selection->signal_changed().connect( sigc::mem_fun(*this, &LivePathEffectEditor::on_effect_selection_changed) );
+
+ effectlist_view.set_headers_visible(false);
+ //Add the TreeView's view columns:
+ effectlist_view.append_column("Effect", columns.col_name);
+
+
contents->pack_start(effectapplication_frame, false, false);
+ contents->pack_start(effectlist_frame, true, true);
contents->pack_start(effectcontrol_frame, false, false);
// connect callback functions to buttons
button_apply.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onApply));
button_remove.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onRemove));
+ button_up.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onUp));
+ button_down.signal_clicked().connect(sigc::mem_fun(*this, &LivePathEffectEditor::onDown));
+
show_all_children();
- button_remove.hide();
+ //button_remove.hide();
}
LivePathEffectEditor::~LivePathEffectEditor()
}
explain_label.set_label(str);
- button_remove.hide();
+ //button_remove.hide();
// fixme: do resizing of dialog ?
}
combo_effecttype.set_sensitive(sensitive);
button_apply.set_sensitive(sensitive);
button_remove.set_sensitive(sensitive);
+ effectlist_view.set_sensitive(sensitive);
+ button_up.set_sensitive(sensitive);
+ button_down.set_sensitive(sensitive);
}
+
void
LivePathEffectEditor::onSelectionChanged(Inkscape::Selection *sel)
{
+ effectlist_store->clear();
+ current_lpeitem = NULL;
+
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
if ( item ) {
if ( SP_IS_LPE_ITEM(item) ) {
SPLPEItem *lpeitem = SP_LPE_ITEM(item);
- LivePathEffectObject *lpeobj = sp_lpe_item_get_livepatheffectobject(lpeitem);
+
+ effect_list_update(lpeitem);
+
+ current_lpeitem = lpeitem;
+
set_sensitize_all(true);
- if (lpeobj) {
- if (lpeobj->lpe) {
- showParams(lpeobj->lpe);
+ if ( sp_lpe_item_has_path_effect(lpeitem) ) {
+ Inkscape::LivePathEffect::Effect *lpe = sp_lpe_item_get_current_lpe(lpeitem);
+ if (lpe) {
+ showParams(lpe);
} else {
showText(_("Unknown effect is applied"));
}
}
}
+void
+LivePathEffectEditor::effect_list_update(SPLPEItem *lpeitem)
+{
+ effectlist_store->clear();
+
+ PathEffectList effectlist = sp_lpe_item_get_effect_list(lpeitem);
+ PathEffectList::iterator it;
+ for( it = effectlist.begin() ; it!=effectlist.end(); it++ )
+ {
+ Gtk::TreeModel::Row row = *(effectlist_store->append());
+ row[columns.col_name] = (*it)->lpeobject->lpe->getName();
+ row[columns.lperef] = *it;
+ }
+}
+
+
void
LivePathEffectEditor::setDesktop(SPDesktop *desktop)
{
Inkscape::GC::release(repr);
gchar *href = g_strdup_printf("#%s", repr_id);
- sp_lpe_item_set_path_effect(SP_LPE_ITEM(item), href, true);
+ sp_lpe_item_add_path_effect(SP_LPE_ITEM(item), href, true);
g_free(href);
sp_document_done(doc, SP_VERB_DIALOG_LIVE_PATH_EFFECT,
if ( sel && !sel->isEmpty() ) {
SPItem *item = sel->singleItem();
if ( item && SP_IS_LPE_ITEM(item) ) {
- sp_lpe_item_remove_path_effect(SP_LPE_ITEM(item), false);
- showText(_("No effect applied"));
- button_remove.set_sensitive(false);
+ sp_lpe_item_remove_current_path_effect(SP_LPE_ITEM(item), false);
+
+ sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Remove path effect") );
+
+ effect_list_update(SP_LPE_ITEM(item));
+ }
+ }
+}
+
+void LivePathEffectEditor::onUp()
+{
+ Inkscape::Selection *sel = _getSelection();
+ if ( sel && !sel->isEmpty() ) {
+ SPItem *item = sel->singleItem();
+ if ( item && SP_IS_LPE_ITEM(item) ) {
+
+ sp_lpe_item_up_current_path_effect(SP_LPE_ITEM(item));
+
+ sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
+ _("Remove path effect") );
+
+ effect_list_update(SP_LPE_ITEM(item));
+ }
+ }
+
+}
+
+void LivePathEffectEditor::onDown()
+{
+ Inkscape::Selection *sel = _getSelection();
+ if ( sel && !sel->isEmpty() ) {
+ SPItem *item = sel->singleItem();
+ if ( item && SP_IS_LPE_ITEM(item) ) {
+
+ sp_lpe_item_down_current_path_effect(SP_LPE_ITEM(item));
+
sp_document_done ( sp_desktop_document (current_desktop), SP_VERB_DIALOG_LIVE_PATH_EFFECT,
_("Remove path effect") );
+
+ effect_list_update(SP_LPE_ITEM(item));
}
}
}
+void LivePathEffectEditor::on_effect_selection_changed()
+{
+ Glib::RefPtr<Gtk::TreeSelection> sel = effectlist_view.get_selection();
+ if (sel->count_selected_rows () == 0)
+ return;
+
+ Gtk::TreeModel::iterator it = sel->get_selected();
+ LivePathEffect::LPEObjectReference * lperef = (*it)[columns.lperef];
+
+ if (lperef && current_lpeitem) {
+ sp_lpe_item_set_current_path_effect(current_lpeitem, lperef);
+ showParams(lperef->lpeobject->lpe);
+ }
+}
+
+
} // namespace Dialog
} // namespace UI
} // namespace Inkscape
index dc96fc313761230f75efc9eba01d5eb9b2d4ed6b..e2c7da3220bc6bb2421dcc38ea6bc68245e1cfaa 100644 (file)
#include <gtkmm/tooltips.h>
#include "ui/widget/combo-enums.h"
#include "live_effects/effect.h"
+#include "live_effects/lpeobject-reference.h"
+#include <gtkmm/liststore.h>
+#include <gtkmm/treeview.h>
+#include <gtkmm/scrolledwindow.h>
+#include <gtkmm/buttonbox.h>
+#include <gtkmm/toolbar.h>
+
class SPDesktop;
static LivePathEffectEditor &getInstance() { return *new LivePathEffectEditor(); }
void onSelectionChanged(Inkscape::Selection *sel);
+ virtual void on_effect_selection_changed();
void setDesktop(SPDesktop *desktop);
private:
void showParams(LivePathEffect::Effect* effect);
void showText(Glib::ustring const &str);
+ // void add_entry(const char* name );
+ void effect_list_update(SPLPEItem *lpeitem);
+
// callback methods for buttons on grids page.
void onApply();
void onRemove();
+ void onUp();
+ void onDown();
+
+ class ModelColumns : public Gtk::TreeModel::ColumnRecord
+ {
+ public:
+ ModelColumns()
+ {
+ add(col_name);
+ add(lperef);
+ }
+
+ Gtk::TreeModelColumn<Glib::ustring> col_name;
+ Gtk::TreeModelColumn<LivePathEffect::LPEObjectReference *> lperef;
+ };
+
Inkscape::UI::Widget::ComboBoxEnum<LivePathEffect::EffectType> combo_effecttype;
- Inkscape::UI::Widget::Button button_apply;
- Inkscape::UI::Widget::Button button_remove;
+
Gtk::Widget * effectwidget;
Gtk::Label explain_label;
Gtk::Frame effectapplication_frame;
Gtk::Frame effectcontrol_frame;
+ Gtk::Frame effectlist_frame;
Gtk::HBox effectapplication_hbox;
Gtk::VBox effectcontrol_vbox;
+ Gtk::VBox effectlist_vbox;
Gtk::Tooltips tooltips;
+ ModelColumns columns;
+ Gtk::ScrolledWindow scrolled_window;
+ Gtk::TreeView effectlist_view;
+ Glib::RefPtr<Gtk::ListStore> effectlist_store;
+ Glib::RefPtr<Gtk::TreeSelection> effectlist_selection;
+
+ Gtk::Toolbar toolbar;
+ Gtk::ToolButton button_up;
+ Gtk::ToolButton button_down;
+ Gtk::Button button_apply;
+ Gtk::ToolButton button_remove;
+ /*Gtk::HButtonBox button_hbox;
+ Gtk::Button button_up;
+ Gtk::Button button_down;
+ Gtk::Button button_apply;
+ Gtk::Button button_remove;*/
SPDesktop * current_desktop;
+
+ SPLPEItem * current_lpeitem;
LivePathEffectEditor(LivePathEffectEditor const &d);
LivePathEffectEditor& operator=(LivePathEffectEditor const &d);