1
#define INKSCAPE_LIVEPATHEFFECT_CPP
4
* Copyright (C) Johan Engelen 2007 <j.b.c.engelen@utwente.nl>
6
* Released under GNU GPL, read the file 'COPYING' for more information
9
#include "live_effects/effect.h"
11
#include "display/display-forward.h"
12
#include "xml/node-event-vector.h"
13
#include "sp-object.h"
14
#include "attributes.h"
15
#include "message-stack.h"
19
#include <glibmm/i18n.h>
21
#include "live_effects/lpeobject.h"
22
#include "live_effects/parameter/parameter.h"
23
#include <glibmm/ustring.h>
24
#include "live_effects/n-art-bpath-2geom.h"
25
#include "display/curve.h"
30
#include <2geom/sbasis-to-bezier.h>
31
#include <2geom/matrix.h>
35
#include "live_effects/lpe-skeletalstrokes.h"
36
#include "live_effects/lpe-pathalongpath.h"
37
#include "live_effects/lpe-slant.h"
38
#include "live_effects/lpe-test-doEffect-stack.h"
39
#include "live_effects/lpe-gears.h"
40
#include "live_effects/lpe-curvestitch.h"
46
namespace LivePathEffect {
48
const Util::EnumData<EffectType> LPETypeData[INVALID_LPE] = {
49
// {constant defined in effect.h, N_("name of your effect"), "name of your effect in SVG"}
50
{PATH_ALONG_PATH, N_("Bend Path"), "bend_path"},
51
{SKELETAL_STROKES, N_("Pattern Along Path"), "skeletal"},
52
#ifdef LPE_ENABLE_TEST_EFFECTS
53
{SLANT, N_("Slant"), "slant"},
54
{DOEFFECTSTACK_TEST, N_("doEffect stack test"), "doeffectstacktest"},
56
{GEARS, N_("Gears"), "gears"},
57
{CURVE_STITCH, N_("Stitch Sub-Paths"), "curvestitching"},
59
const Util::EnumDataConverter<EffectType> LPETypeConverter(LPETypeData, INVALID_LPE);
62
Effect::New(EffectType lpenr, LivePathEffectObject *lpeobj)
64
Effect* neweffect = NULL;
66
case SKELETAL_STROKES:
67
neweffect = (Effect*) new LPESkeletalStrokes(lpeobj);
70
neweffect = (Effect*) new LPEPathAlongPath(lpeobj);
72
#ifdef LPE_ENABLE_TEST_EFFECTS
74
neweffect = (Effect*) new LPESlant(lpeobj);
76
case DOEFFECTSTACK_TEST:
77
neweffect = (Effect*) new LPEdoEffectStackTest(lpeobj);
81
neweffect = (Effect*) new LPEGears(lpeobj);
84
neweffect = (Effect*) new LPECurveStitch(lpeobj);
87
g_warning("LivePathEffect::Effect::New called with invalid patheffect type (%d)", lpenr);
93
neweffect->readallParameters(SP_OBJECT_REPR(lpeobj));
99
Effect::Effect(LivePathEffectObject *lpeobject)
112
if (lpeobj->effecttype_set && lpeobj->effecttype < INVALID_LPE)
113
return Glib::ustring( _(LPETypeConverter.get_label(lpeobj->effecttype).c_str()) );
115
return Glib::ustring( _("No effect") );
119
* Here be the doEffect function chain:
122
Effect::doEffect (SPCurve * curve)
124
NArtBpath *new_bpath = doEffect_nartbpath(SP_CURVE_BPATH(curve));
126
if (new_bpath && new_bpath != SP_CURVE_BPATH(curve)) { // FIXME, add function to SPCurve to change bpath? or a copy function?
128
g_free(curve->_bpath); //delete old bpath
130
curve->_bpath = new_bpath;
135
Effect::doEffect_nartbpath (NArtBpath * path_in)
138
std::vector<Geom::Path> orig_pathv = BPath_to_2GeomPath(path_in);
140
std::vector<Geom::Path> result_pathv = doEffect_path(orig_pathv);
142
NArtBpath *new_bpath = BPath_from_2GeomPath(result_pathv);
146
catch (std::exception & e) {
147
g_warning("Exception during LPE %s execution. \n %s", getName().c_str(), e.what());
148
SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
149
_("An exception occurred during execution of the Path Effect.") );
154
while ( path_in[ret].code != NR_END ) {
157
unsigned len = ++ret;
159
path_out = g_new(NArtBpath, len);
160
memcpy(path_out, path_in, len * sizeof(NArtBpath));
165
std::vector<Geom::Path>
166
Effect::doEffect_path (std::vector<Geom::Path> & path_in)
168
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_in;
170
for (unsigned int i=0; i < path_in.size(); i++) {
171
pwd2_in.concat( path_in[i].toPwSb() );
174
Geom::Piecewise<Geom::D2<Geom::SBasis> > pwd2_out = doEffect_pwd2(pwd2_in);
176
std::vector<Geom::Path> path_out = Geom::path_from_piecewise( pwd2_out, LPE_CONVERSION_TOLERANCE);
181
Geom::Piecewise<Geom::D2<Geom::SBasis> >
182
Effect::doEffect_pwd2 (Geom::Piecewise<Geom::D2<Geom::SBasis> > & pwd2_in)
184
g_warning("Effect has no doEffect implementation");
189
Effect::readallParameters(Inkscape::XML::Node * repr)
191
std::vector<Parameter *>::iterator it = param_vector.begin();
192
while (it != param_vector.end()) {
193
Parameter * param = *it;
194
const gchar * key = param->param_key.c_str();
195
const gchar * value = repr->attribute(key);
197
bool accepted = param->param_readSVGValue(value);
199
g_warning("Effect::readallParameters - '%s' not accepted for %s", value, key);
203
param->param_set_default();
210
/* This function does not and SHOULD NOT write to XML */
212
Effect::setParameter(const gchar * key, const gchar * new_value)
214
Parameter * param = getParameter(key);
217
bool accepted = param->param_readSVGValue(new_value);
219
g_warning("Effect::setParameter - '%s' not accepted for %s", new_value, key);
223
param->param_set_default();
229
Effect::registerParameter(Parameter * param)
231
param_vector.push_back(param);
235
* This *creates* a new widget, management of deletion should be done by the caller
238
Effect::newWidget(Gtk::Tooltips * tooltips)
240
// use manage here, because after deletion of Effect object, others might still be pointing to this widget.
241
Gtk::VBox * vbox = Gtk::manage( new Gtk::VBox() );
243
vbox->set_border_width(5);
245
std::vector<Parameter *>::iterator it = param_vector.begin();
246
while (it != param_vector.end()) {
247
Parameter * param = *it;
248
Gtk::Widget * widg = param->param_newWidget(tooltips);
249
Glib::ustring * tip = param->param_getTooltip();
251
vbox->pack_start(*widg, true, true, 2);
253
tooltips->set_tip(*widg, *tip);
260
return dynamic_cast<Gtk::Widget *>(vbox);
264
Inkscape::XML::Node *
267
return SP_OBJECT_REPR(lpeobj);
273
if (SP_OBJECT_DOCUMENT(lpeobj) == NULL) g_message("Effect::getSPDoc() returns NULL");
274
return SP_OBJECT_DOCUMENT(lpeobj);
278
Effect::getParameter(const char * key)
280
Glib::ustring stringkey(key);
282
std::vector<Parameter *>::iterator it = param_vector.begin();
283
while (it != param_vector.end()) {
284
Parameter * param = *it;
285
if ( param->param_key == key) {
296
Effect::getNextOncanvasEditableParam()
299
if (oncanvasedit_it == static_cast<int>(param_vector.size())) {
302
int old_it = oncanvasedit_it;
305
Parameter * param = param_vector[oncanvasedit_it];
306
if(param && param->oncanvas_editable) {
310
if (oncanvasedit_it == static_cast<int>(param_vector.size())) { // loop round the map
314
} while (oncanvasedit_it != old_it); // iterate until complete loop through map has been made
320
Effect::editNextParamOncanvas(SPItem * item, SPDesktop * desktop)
322
if (!desktop) return;
324
Parameter * param = getNextOncanvasEditableParam();
326
param->param_editOncanvas(item, desktop);
327
gchar *message = g_strdup_printf(_("Editing parameter <b>%s</b>."), param->param_label.c_str());
328
desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, message);
331
desktop->messageStack()->flash( Inkscape::WARNING_MESSAGE,
332
_("None of the applied path effect's parameters can be edited on-canvas.") );
336
/* This function should reset the defaults and is used for example to initialize an effect right after it has been applied to a path
337
* The nice thing about this is that this function can use knowledge of the original path and set things accordingly for example to the size or origin of the original path!
340
Effect::resetDefaults(SPItem * /*item*/)
342
// do nothing for simple effects
346
Effect::setup_nodepath(Inkscape::NodePath::Path *np)
348
np->show_helperpath = true;
349
np->helperpath_rgba = 0xff0000ff;
350
np->helperpath_width = 1.0;
354
Effect::transform_multiply(Geom::Matrix const& postmul, bool set)
356
// cycle through all parameters. Most parameters will not need transformation, but path and point params do.
357
for (std::vector<Parameter *>::iterator it = param_vector.begin(); it != param_vector.end(); it++) {
358
Parameter * param = *it;
359
param->param_transform_multiply(postmul, set);
363
} /* namespace LivePathEffect */
365
} /* namespace Inkscape */
370
c-file-style:"stroustrup"
371
c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
376
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4 :