~centralelyon2010/inkscape/imagelinks2

5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
1
/** \file
2
 * Base class for live path effect items
3
 */
4
/*
5
 * Authors:
6
 *   Johan Engelen <j.b.c.engelen@ewi.utwente.nl>
7
 *   Bastien Bouclet <bgkweb@gmail.com>
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
8
 *   Abhishek Sharma
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
9
 *
10
 * Copyright (C) 2008 authors
11
 *
12
 * Released under GNU GPL, read the file 'COPYING' for more information
13
 */
14
15
#ifdef HAVE_CONFIG_H
16
# include "config.h"
17
#endif
18
19
#include "live_effects/effect.h"
6801 by cilix42
Hide canvas text, too, when lpe-path-length is invisible
20
#include "live_effects/lpe-path_length.h"
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
21
#include "live_effects/lpeobject.h"
22
#include "live_effects/lpeobject-reference.h"
23
24
#include "sp-path.h"
25
#include "sp-item-group.h"
5503 by pjrm
fix a couple of g++-4.3 compile errors.
26
#include "streq.h"
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
27
#include "macros.h"
28
#include "attributes.h"
29
#include "sp-lpe-item.h"
30
#include "xml/repr.h"
31
#include "uri.h"
5938 by johanengelen
put exception catch block around all doEffect calls. (so in SP_LPE_ITEM)
32
#include "message-stack.h"
33
#include "inkscape.h"
34
#include "desktop.h"
6456 by cilix42
Update helperpaths live also when any of the item's LPEs is modified
35
#include "shape-editor.h"
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
36
5766 by johanengelen
LPE STACKING!
37
#include <algorithm>
38
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
39
/* LPEItem base class */
40
41
static void sp_lpe_item_class_init(SPLPEItemClass *klass);
42
static void sp_lpe_item_init(SPLPEItem *lpe_item);
43
static void sp_lpe_item_finalize(GObject *object);
44
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
45
static void sp_lpe_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
46
static void sp_lpe_item_release(SPObject *object);
47
static void sp_lpe_item_set(SPObject *object, unsigned int key, gchar const *value);
48
static void sp_lpe_item_update(SPObject *object, SPCtx *ctx, guint flags);
49
static void sp_lpe_item_modified (SPObject *object, unsigned int flags);
5884 by mental
plumb XML::Documents in everywhere
50
static Inkscape::XML::Node *sp_lpe_item_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
51
52
static void sp_lpe_item_child_added (SPObject * object, Inkscape::XML::Node * child, Inkscape::XML::Node * ref);
53
static void sp_lpe_item_remove_child (SPObject * object, Inkscape::XML::Node * child);
54
5766 by johanengelen
LPE STACKING!
55
static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
56
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
57
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
58
59
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
60
static void sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem);
5766 by johanengelen
LPE STACKING!
61
typedef std::list<std::string> HRefList;
62
static std::string patheffectlist_write_svg(PathEffectList const & list);
63
static std::string hreflist_write_svg(HRefList const & list);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
64
65
static SPItemClass *parent_class;
66
67
GType
68
sp_lpe_item_get_type()
69
{
70
    static GType lpe_item_type = 0;
71
72
    if (!lpe_item_type) {
73
        GTypeInfo lpe_item_info = {
74
            sizeof(SPLPEItemClass),
75
            NULL, NULL,
76
            (GClassInitFunc) sp_lpe_item_class_init,
77
            NULL, NULL,
78
            sizeof(SPLPEItem),
79
            16,
80
            (GInstanceInitFunc) sp_lpe_item_init,
81
            NULL,    /* value_table */
82
        };
83
        lpe_item_type = g_type_register_static(SP_TYPE_ITEM, "SPLPEItem", &lpe_item_info, (GTypeFlags)0);
84
    }
85
    return lpe_item_type;
86
}
87
88
static void
89
sp_lpe_item_class_init(SPLPEItemClass *klass)
5766 by johanengelen
LPE STACKING!
90
{
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
91
    GObjectClass *gobject_class;
92
    SPObjectClass *sp_object_class;
93
94
    gobject_class = (GObjectClass *) klass;
95
    sp_object_class = (SPObjectClass *) klass;
96
    parent_class = (SPItemClass *)g_type_class_peek_parent (klass);
97
98
    gobject_class->finalize = sp_lpe_item_finalize;
99
100
    sp_object_class->build = sp_lpe_item_build;
101
    sp_object_class->release = sp_lpe_item_release;
102
    sp_object_class->set = sp_lpe_item_set;
103
    sp_object_class->update = sp_lpe_item_update;
104
    sp_object_class->modified = sp_lpe_item_modified;
105
    sp_object_class->write = sp_lpe_item_write;
106
    sp_object_class->child_added = sp_lpe_item_child_added;
107
    sp_object_class->remove_child = sp_lpe_item_remove_child;
5766 by johanengelen
LPE STACKING!
108
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
109
    klass->update_patheffect = NULL;
110
}
111
112
static void
113
sp_lpe_item_init(SPLPEItem *lpeitem)
114
{
5766 by johanengelen
LPE STACKING!
115
    lpeitem->path_effects_enabled = 1;
116
117
    lpeitem->path_effect_list = new PathEffectList();
118
    lpeitem->current_path_effect = NULL;
119
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
120
    lpeitem->lpe_modified_connection_list = new std::list<sigc::connection>();
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
121
}
122
123
static void
124
sp_lpe_item_finalize(GObject *object)
125
{
126
    if (((GObjectClass *) (parent_class))->finalize) {
127
        (* ((GObjectClass *) (parent_class))->finalize)(object);
128
    }
129
}
130
131
/**
132
 * Reads the Inkscape::XML::Node, and initializes SPLPEItem variables.  For this to get called,
133
 * our name must be associated with a repr via "sp_object_type_register".  Best done through
134
 * sp-object-repr.cpp's repr_name_entries array.
135
 */
136
static void
8422 by cilix42
Revert recent refactoring changes by johnce because they break the build, which cannot be fixed easily.
137
sp_lpe_item_build(SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
138
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
139
    object->readAttr( "inkscape:path-effect" );
5766 by johanengelen
LPE STACKING!
140
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
141
    if (((SPObjectClass *) parent_class)->build) {
142
        ((SPObjectClass *) parent_class)->build(object, document, repr);
143
    }
144
}
145
146
/**
147
 * Drops any allocated memory.
148
 */
149
static void
150
sp_lpe_item_release(SPObject *object)
151
{
6358 by buliabyak
fix crash when simplifying an lpe path: deleting the list didn't release the references, and it didn't work in _finalize anyway
152
    SPLPEItem *lpeitem = (SPLPEItem *) object;
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
153
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
154
    // disconnect all modified listeners:
155
    for (std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
156
         mod_it != lpeitem->lpe_modified_connection_list->end(); ++mod_it)
157
    {
158
        mod_it->disconnect();
159
    }
160
    delete lpeitem->lpe_modified_connection_list;
161
    lpeitem->lpe_modified_connection_list = NULL;
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
162
6358 by buliabyak
fix crash when simplifying an lpe path: deleting the list didn't release the references, and it didn't work in _finalize anyway
163
    PathEffectList::iterator it = lpeitem->path_effect_list->begin();
164
    while ( it != lpeitem->path_effect_list->end() ) {
165
        // unlink and delete all references in the list
166
        (*it)->unlink();
167
        delete *it;
168
        it = lpeitem->path_effect_list->erase(it);
169
    }
170
    // delete the list itself
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
171
    delete lpeitem->path_effect_list;
172
    lpeitem->path_effect_list = NULL;
6358 by buliabyak
fix crash when simplifying an lpe path: deleting the list didn't release the references, and it didn't work in _finalize anyway
173
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
174
    if (((SPObjectClass *) parent_class)->release)
175
        ((SPObjectClass *) parent_class)->release(object);
176
}
177
178
/**
179
 * Sets a specific value in the SPLPEItem.
180
 */
181
static void
182
sp_lpe_item_set(SPObject *object, unsigned int key, gchar const *value)
183
{
184
    SPLPEItem *lpeitem = (SPLPEItem *) object;
185
186
    switch (key) {
187
        case SP_ATTR_INKSCAPE_PATH_EFFECT:
5766 by johanengelen
LPE STACKING!
188
            {
189
                lpeitem->current_path_effect = NULL;
190
191
                // Disable the path effects while populating the LPE list
192
                 sp_lpe_item_enable_path_effects(lpeitem, false);
193
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
194
                // disconnect all modified listeners:
195
                for ( std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
196
                      mod_it != lpeitem->lpe_modified_connection_list->end();
197
                      ++mod_it)
198
                {
199
                    mod_it->disconnect();
200
                }
201
                lpeitem->lpe_modified_connection_list->clear();
5766 by johanengelen
LPE STACKING!
202
                // Clear the path effect list
203
                PathEffectList::iterator it = lpeitem->path_effect_list->begin();
204
                while ( it != lpeitem->path_effect_list->end() )
205
                {
206
                    (*it)->unlink();
207
                    delete *it;
208
                    it = lpeitem->path_effect_list->erase(it);
209
                }
210
211
                // Parse the contents of "value" to rebuild the path effect reference list
212
                if ( value ) {
213
                    std::istringstream iss(value);
214
                    std::string href;
215
                    while (std::getline(iss, href, ';'))
216
                    {
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
217
                        Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(object);
5766 by johanengelen
LPE STACKING!
218
                        try {
219
                            path_effect_ref->link(href.c_str());
6873 by johanengelen
fix crash on entering invalid lpe name in xml
220
                        } catch (Inkscape::BadURIException e) {
6891 by Ted Gould
Merge from fe-moved
221
                            g_warning("BadURIException when trying to find LPE: %s", e.what());
5766 by johanengelen
LPE STACKING!
222
                            path_effect_ref->unlink();
223
                            delete path_effect_ref;
224
                            path_effect_ref = NULL;
225
                        }
226
6891 by Ted Gould
Merge from fe-moved
227
                        lpeitem->path_effect_list->push_back(path_effect_ref);
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
228
                        if ( path_effect_ref->lpeobject && path_effect_ref->lpeobject->get_lpe() ) {
229
                            // connect modified-listener
230
                            lpeitem->lpe_modified_connection_list->push_back(
231
                                                path_effect_ref->lpeobject->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem)) );
232
                        } else {
6891 by Ted Gould
Merge from fe-moved
233
                            // something has gone wrong in finding the right patheffect.
234
                            g_warning("Unknown LPE type specified, LPE stack effectively disabled");
235
                            // keep the effect in the lpestack, so the whole stack is effectively disabled but maintained
5766 by johanengelen
LPE STACKING!
236
                        }
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
237
                    }
238
                }
5766 by johanengelen
LPE STACKING!
239
240
                sp_lpe_item_enable_path_effects(lpeitem, true);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
241
            }
242
            break;
243
        default:
244
            if (((SPObjectClass *) parent_class)->set) {
245
                ((SPObjectClass *) parent_class)->set(object, key, value);
246
            }
247
            break;
248
    }
249
}
250
251
/**
252
 * Receives update notifications.
253
 */
254
static void
255
sp_lpe_item_update(SPObject *object, SPCtx *ctx, guint flags)
256
{
257
    if (((SPObjectClass *) parent_class)->update) {
258
        ((SPObjectClass *) parent_class)->update(object, ctx, flags);
259
    }
6456 by cilix42
Update helperpaths live also when any of the item's LPEs is modified
260
261
    // update the helperpaths of all LPEs applied to the item
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
262
    // TODO: re-add for the new node tool
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
263
}
264
265
/**
266
 * Sets modified flag for all sub-item views.
267
 */
268
static void
269
sp_lpe_item_modified (SPObject *object, unsigned int flags)
270
{
5766 by johanengelen
LPE STACKING!
271
    if (SP_IS_GROUP(object) && (flags & SP_OBJECT_MODIFIED_FLAG) && (flags & SP_OBJECT_USER_MODIFIED_FLAG_B)) {
272
        sp_lpe_item_update_patheffect(SP_LPE_ITEM(object), true, true);
273
    }
274
275
    if (((SPObjectClass *) (parent_class))->modified) {
276
        (* ((SPObjectClass *) (parent_class))->modified) (object, flags);
277
    }
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
278
}
279
280
/**
281
 * Writes its settings to an incoming repr object, if any.
282
 */
283
static Inkscape::XML::Node *
5884 by mental
plumb XML::Documents in everywhere
284
sp_lpe_item_write(SPObject *object, Inkscape::XML::Document *xml_doc, Inkscape::XML::Node *repr, guint flags)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
285
{
286
    SPLPEItem *lpeitem = (SPLPEItem *) object;
287
8540 by johanengelen
fix bug #377958: don't write inkscape:path-effect to plain svg
288
    if (flags & SP_OBJECT_WRITE_EXT) {
289
        if ( sp_lpe_item_has_path_effect(lpeitem) ) {
290
            std::string href = patheffectlist_write_svg(*lpeitem->path_effect_list);
291
            repr->setAttribute("inkscape:path-effect", href.c_str());
292
        } else {
293
            repr->setAttribute("inkscape:path-effect", NULL);
294
        }
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
295
    }
296
297
    if (((SPObjectClass *)(parent_class))->write) {
5884 by mental
plumb XML::Documents in everywhere
298
        ((SPObjectClass *)(parent_class))->write(object, xml_doc, repr, flags);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
299
    }
300
301
    return repr;
302
}
303
6891 by Ted Gould
Merge from fe-moved
304
/**
305
 * returns true when LPE was successful.
306
 */
307
bool sp_lpe_item_perform_path_effect(SPLPEItem *lpeitem, SPCurve *curve) {
308
    if (!lpeitem) return false;
309
    if (!curve) return false;
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
310
5766 by johanengelen
LPE STACKING!
311
    if (sp_lpe_item_has_path_effect(lpeitem) && sp_lpe_item_path_effects_enabled(lpeitem)) {
312
        for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
313
        {
314
            LivePathEffectObject *lpeobj = (*it)->lpeobject;
5792 by johanengelen
fix crash, report warnings instead. trying to find real cause for this (crash on copying path with lpestack).
315
            if (!lpeobj) {
6885 by Ted Gould
From trunk
316
                /** \todo Investigate the cause of this.
317
                 * For example, this happens when copy pasting an object with LPE applied. Probably because the object is pasted while the effect is not yet pasted to defs, and cannot be found.
318
                 */
5792 by johanengelen
fix crash, report warnings instead. trying to find real cause for this (crash on copying path with lpestack).
319
                g_warning("sp_lpe_item_perform_path_effect - NULL lpeobj in list!");
6891 by Ted Gould
Merge from fe-moved
320
                return false;
5792 by johanengelen
fix crash, report warnings instead. trying to find real cause for this (crash on copying path with lpestack).
321
            }
6884 by Ted Gould
Merging from trunk
322
            Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
323
            if (!lpe) {
6885 by Ted Gould
From trunk
324
                /** \todo Investigate the cause of this.
325
                 * Not sure, but I think this can happen when an unknown effect type is specified...
326
                 */
6891 by Ted Gould
Merge from fe-moved
327
                g_warning("sp_lpe_item_perform_path_effect - lpeobj with invalid lpe in the stack!");
328
                return false;
5792 by johanengelen
fix crash, report warnings instead. trying to find real cause for this (crash on copying path with lpestack).
329
            }
5766 by johanengelen
LPE STACKING!
330
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
331
            if (lpe->isVisible()) {
6644 by cilix42
Rename acceptsNumParams() -> acceptsNumClicks() because it makes more sense
332
                if (lpe->acceptsNumClicks() > 0 && !lpe->isReady()) {
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
333
                    // if the effect expects mouse input before being applied and the input is not finished
334
                    // yet, we don't alter the path
6891 by Ted Gould
Merge from fe-moved
335
                    return false;
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
336
                }
337
5766 by johanengelen
LPE STACKING!
338
                // Groups have their doBeforeEffect called elsewhere
339
                if (!SP_IS_GROUP(lpeitem)) {
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
340
                    lpe->doBeforeEffect(lpeitem);
5766 by johanengelen
LPE STACKING!
341
                }
342
5938 by johanengelen
put exception catch block around all doEffect calls. (so in SP_LPE_ITEM)
343
                try {
344
                    lpe->doEffect(curve);
345
                }
346
                catch (std::exception & e) {
347
                    g_warning("Exception during LPE %s execution. \n %s", lpe->getName().c_str(), e.what());
6885 by Ted Gould
From trunk
348
                    if (SP_ACTIVE_DESKTOP && SP_ACTIVE_DESKTOP->messageStack()) {
349
                        SP_ACTIVE_DESKTOP->messageStack()->flash( Inkscape::WARNING_MESSAGE,
350
                                        _("An exception occurred during execution of the Path Effect.") );
351
                    }
6891 by Ted Gould
Merge from fe-moved
352
                    return false;
5938 by johanengelen
put exception catch block around all doEffect calls. (so in SP_LPE_ITEM)
353
                }
5766 by johanengelen
LPE STACKING!
354
            }
5711 by cilix42
Add checkbox for LPEs to temporarily disable them on canvas (but keep them applied to the object)
355
        }
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
356
    }
6891 by Ted Gould
Merge from fe-moved
357
358
    return true;
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
359
}
360
361
/**
362
 * Calls any registered handlers for the update_patheffect action
363
 */
364
void
5766 by johanengelen
LPE STACKING!
365
sp_lpe_item_update_patheffect (SPLPEItem *lpeitem, bool wholetree, bool write)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
366
{
367
#ifdef SHAPE_VERBOSE
368
    g_message("sp_lpe_item_update_patheffect: %p\n", lpeitem);
369
#endif
370
    g_return_if_fail (lpeitem != NULL);
371
    g_return_if_fail (SP_IS_LPE_ITEM (lpeitem));
372
5769 by bgk
Stacked LPEs should now use the right bounding box
373
    if (!sp_lpe_item_path_effects_enabled(lpeitem))
374
        return;
375
6801 by cilix42
Hide canvas text, too, when lpe-path-length is invisible
376
    // TODO: hack! this will be removed when path length measuring is reimplemented in a better way
377
    PathEffectList lpelist = sp_lpe_item_get_effect_list(lpeitem);
378
    std::list<Inkscape::LivePathEffect::LPEObjectReference *>::iterator i;
379
    for (i = lpelist.begin(); i != lpelist.end(); ++i) {
6885 by Ted Gould
From trunk
380
        if ((*i)->lpeobject) {
381
            Inkscape::LivePathEffect::Effect *lpe = (*i)->lpeobject->get_lpe();
382
            if (dynamic_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)) {
383
                if (!lpe->isVisible()) {
384
                    // we manually disable text for LPEPathLength
8846.1.1 by Krzysztof Kosiński
First GSoC node tool commit to Bazaar
385
                    // use static_cast, because we already checked for the right type above
386
                    static_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)->hideCanvasText();
6885 by Ted Gould
From trunk
387
                }
6801 by cilix42
Hide canvas text, too, when lpe-path-length is invisible
388
            }
389
        }
390
    }
391
5766 by johanengelen
LPE STACKING!
392
    SPLPEItem *top;
393
394
    if (wholetree) {
395
        SPObject *prev_parent = lpeitem;
396
        SPObject *parent = prev_parent->parent;
397
        while (parent && SP_IS_LPE_ITEM(parent) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(parent))) {
398
            prev_parent = parent;
399
            parent = prev_parent->parent;
400
        }
401
        top = SP_LPE_ITEM(prev_parent);
402
    }
403
    else {
404
        top = lpeitem;
405
    }
406
407
    if (SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (top))->update_patheffect) {
408
        SP_LPE_ITEM_CLASS (G_OBJECT_GET_CLASS (top))->update_patheffect (top, write);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
409
    }
410
}
411
412
/**
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
413
 * Gets called when any of the lpestack's lpeobject repr contents change: i.e. parameter change in any of the stacked LPEs
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
414
 */
415
static void
416
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
417
{
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
418
#ifdef SHAPE_VERBOSE
419
    g_message("lpeobject_ref_modified");
420
#endif
5766 by johanengelen
LPE STACKING!
421
    sp_lpe_item_update_patheffect (lpeitem, true, true);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
422
}
423
424
static void
425
sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem)
426
{
427
    if (SP_IS_GROUP(lpeitem)) {
428
        GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
429
        for ( GSList const *iter = item_list; iter; iter = iter->next ) {
430
            SPObject *subitem = static_cast<SPObject *>(iter->data);
431
            if (SP_IS_LPE_ITEM(subitem)) {
432
                sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(subitem));
433
            }
434
        }
435
    }
436
    else if (SP_IS_PATH(lpeitem)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
437
        Inkscape::XML::Node *pathrepr = lpeitem->getRepr();
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
438
        if ( !pathrepr->attribute("inkscape:original-d") ) {
439
            pathrepr->setAttribute("inkscape:original-d", pathrepr->attribute("d"));
440
        }
441
    }
442
}
443
444
static void
445
sp_lpe_item_cleanup_original_path_recursive(SPLPEItem *lpeitem)
446
{
447
    if (SP_IS_GROUP(lpeitem)) {
448
        GSList const *item_list = sp_item_group_item_list(SP_GROUP(lpeitem));
449
        for ( GSList const *iter = item_list; iter; iter = iter->next ) {
450
            SPObject *subitem = static_cast<SPObject *>(iter->data);
451
            if (SP_IS_LPE_ITEM(subitem)) {
452
                sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(subitem));
453
            }
454
        }
455
    }
456
    else if (SP_IS_PATH(lpeitem)) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
457
        Inkscape::XML::Node *repr = lpeitem->getRepr();
5766 by johanengelen
LPE STACKING!
458
        if (!sp_lpe_item_has_path_effect_recursive(lpeitem)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
459
                && repr->attribute("inkscape:original-d")) {
460
            repr->setAttribute("d", repr->attribute("inkscape:original-d"));
461
            repr->setAttribute("inkscape:original-d", NULL);
462
        }
463
        else {
5766 by johanengelen
LPE STACKING!
464
            sp_lpe_item_update_patheffect(lpeitem, true, true);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
465
        }
466
    }
467
}
468
5766 by johanengelen
LPE STACKING!
469
void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, gchar *value, bool reset)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
470
{
5766 by johanengelen
LPE STACKING!
471
    if (value) {
472
        // Apply the path effects here because in the casse of a group, lpe->resetDefaults
473
        // needs that all the subitems have their effects applied
474
        sp_lpe_item_update_patheffect(lpeitem, false, true);
475
476
        // Disable the path effects while preparing the new lpe
477
        sp_lpe_item_enable_path_effects(lpeitem, false);
478
479
        // Add the new reference to the list of LPE references
480
        HRefList hreflist;
481
        for (PathEffectList::const_iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
482
        {
483
            hreflist.push_back( std::string((*it)->lpeobject_href) );
5683 by bgk
Fix LPE for groups bounding box calculation by using the SPItem->getBounds method.
484
        }
5766 by johanengelen
LPE STACKING!
485
        hreflist.push_back( std::string(value) );
486
        std::string hrefs = hreflist_write_svg(hreflist);
487
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
488
        lpeitem->getRepr()->setAttribute("inkscape:path-effect", hrefs.c_str());
5766 by johanengelen
LPE STACKING!
489
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
490
        // make sure there is an original-d for paths!!!
491
        sp_lpe_item_create_original_path_recursive(lpeitem);
5766 by johanengelen
LPE STACKING!
492
493
        LivePathEffectObject *lpeobj = lpeitem->path_effect_list->back()->lpeobject;
6884 by Ted Gould
Merging from trunk
494
        if (lpeobj && lpeobj->get_lpe()) {
495
            Inkscape::LivePathEffect::Effect *lpe = lpeobj->get_lpe();
5766 by johanengelen
LPE STACKING!
496
            // Ask the path effect to reset itself if it doesn't have parameters yet
497
            if (reset) {
498
                // has to be called when all the subitems have their lpes applied
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
499
                lpe->resetDefaults(lpeitem);
500
            }
501
5905 by cilix42
whitespace
502
            // perform this once when the effect is applied
5902 by cilix42
Infrastructure in class LivePathEffect::Effect to put Inkscape into 'wait for parameter path' mode; make LPEMirrorReflect use this to let the user specify the mirroring line
503
            lpe->doOnApply(SP_LPE_ITEM(lpeitem));
504
6643 by cilix42
Remove done_pathparam_set and friends because it currently isn't used any more anyway; reimplement its intended functionality by using isReady()
505
            // indicate that all necessary preparations are done and the effect can be performed
506
            lpe->setReady();
5766 by johanengelen
LPE STACKING!
507
        }
508
509
        //Enable the path effects now that everything is ready to apply the new path effect
510
        sp_lpe_item_enable_path_effects(lpeitem, true);
511
512
        // Apply the path effect
513
        sp_lpe_item_update_patheffect(lpeitem, true, true);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
514
    }
515
}
516
5766 by johanengelen
LPE STACKING!
517
void sp_lpe_item_add_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * new_lpeobj)
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
518
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
519
    const gchar * repr_id = new_lpeobj->getRepr()->attribute("id");
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
520
    gchar *hrefstr = g_strdup_printf("#%s", repr_id);
5766 by johanengelen
LPE STACKING!
521
    sp_lpe_item_add_path_effect(lpeitem, hrefstr, false);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
522
    g_free(hrefstr);
523
}
524
5766 by johanengelen
LPE STACKING!
525
void sp_lpe_item_remove_current_path_effect(SPLPEItem *lpeitem, bool keep_paths)
526
{
527
    Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
528
    if (!lperef)
529
        return;
530
531
    PathEffectList new_list = *lpeitem->path_effect_list;
532
    new_list.remove(lperef); //current lpe ref is always our 'own' pointer from the path_effect_list
533
    std::string r = patheffectlist_write_svg(new_list);
534
8722 by scislac
Fix for 419577 by Johan
535
    if (!r.empty()) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
536
        lpeitem->getRepr()->setAttribute("inkscape:path-effect", r.c_str());
8722 by scislac
Fix for 419577 by Johan
537
    } else {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
538
        lpeitem->getRepr()->setAttribute("inkscape:path-effect", NULL);
8722 by scislac
Fix for 419577 by Johan
539
    }
5766 by johanengelen
LPE STACKING!
540
541
    if (!keep_paths) {
542
        sp_lpe_item_cleanup_original_path_recursive(lpeitem);
543
    }
544
}
545
546
void sp_lpe_item_remove_all_path_effects(SPLPEItem *lpeitem, bool keep_paths)
547
{
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
548
    lpeitem->getRepr()->setAttribute("inkscape:path-effect", NULL);
5766 by johanengelen
LPE STACKING!
549
550
    if (!keep_paths) {
551
        sp_lpe_item_cleanup_original_path_recursive(lpeitem);
552
    }
553
}
554
555
void sp_lpe_item_down_current_path_effect(SPLPEItem *lpeitem)
556
{
557
    Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
558
    if (!lperef)
559
        return;
560
561
    PathEffectList new_list = *lpeitem->path_effect_list;
562
    PathEffectList::iterator cur_it = find( new_list.begin(), new_list.end(), lperef );
563
    if (cur_it != new_list.end()) {
564
        PathEffectList::iterator down_it = cur_it;
565
        down_it++;
566
        if (down_it != new_list.end()) { // perhaps current effect is already last effect
567
            std::iter_swap(cur_it, down_it);
568
        }
569
    }
570
    std::string r = patheffectlist_write_svg(new_list);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
571
    lpeitem->getRepr()->setAttribute("inkscape:path-effect", r.c_str());
5766 by johanengelen
LPE STACKING!
572
573
    sp_lpe_item_cleanup_original_path_recursive(lpeitem);
574
}
575
576
void sp_lpe_item_up_current_path_effect(SPLPEItem *lpeitem)
577
{
578
    Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
579
    if (!lperef)
580
        return;
581
582
    PathEffectList new_list = *lpeitem->path_effect_list;
583
    PathEffectList::iterator cur_it = find( new_list.begin(), new_list.end(), lperef );
584
    if (cur_it != new_list.end() && cur_it != new_list.begin()) {
585
        PathEffectList::iterator up_it = cur_it;
586
        up_it--;
587
        std::iter_swap(cur_it, up_it);
588
    }
589
    std::string r = patheffectlist_write_svg(new_list);
590
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
591
    lpeitem->getRepr()->setAttribute("inkscape:path-effect", r.c_str());
5766 by johanengelen
LPE STACKING!
592
593
    sp_lpe_item_cleanup_original_path_recursive(lpeitem);
594
}
595
8520 by buliabyak
fix rendering of testcase errorhandling-nosuchlpe.svg: make sure shapes do not calculate the curve if they have a broken lpe, instead reading it directly from d= and issuing a warning
596
/** used for shapes so they can see if they should also disable shape calculation and read from d= */
597
bool sp_lpe_item_has_broken_path_effect(SPLPEItem *lpeitem)
598
{
599
    if (lpeitem->path_effect_list->empty())
600
        return false;
601
602
    // go through the list; if some are unknown or invalid, return true
603
    PathEffectList effect_list =  sp_lpe_item_get_effect_list(lpeitem);
604
    for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
605
    {
606
        LivePathEffectObject *lpeobj = (*it)->lpeobject;
607
        if (!lpeobj || !lpeobj->get_lpe())
608
            return true;
609
    }
610
611
    return false;
612
}
613
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
614
615
bool sp_lpe_item_has_path_effect(SPLPEItem *lpeitem)
616
{
7566 by buliabyak
sp_lpe_item_has_path_effect now returns false if one of the effects in the stack is invalid or unsupported, in which case LPE stack is disabled
617
    if (lpeitem->path_effect_list->empty())
618
        return false;
619
620
    // go through the list; if some are unknown or invalid, we are not an LPE item!
621
    PathEffectList effect_list =  sp_lpe_item_get_effect_list(lpeitem);
622
    for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
623
    {
624
        LivePathEffectObject *lpeobj = (*it)->lpeobject;
625
        if (!lpeobj || !lpeobj->get_lpe())
626
            return false;
627
    }
628
629
    return true;
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
630
}
631
632
bool sp_lpe_item_has_path_effect_recursive(SPLPEItem *lpeitem)
633
{
634
    SPObject *parent = lpeitem->parent;
635
    if (parent && SP_IS_LPE_ITEM(parent)) {
636
        return sp_lpe_item_has_path_effect(lpeitem) || sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(parent));
637
    }
638
    else {
639
        return sp_lpe_item_has_path_effect(lpeitem);
640
    }
641
}
642
6322 by cilix42
New LPE FreehandShape derived from PatternAlongPath (for the shapes in pen/pencil context); don't apply shapes each time the selection changes; new functions to test for specific LPE type and if a path can accept a new shape
643
Inkscape::LivePathEffect::Effect*
644
sp_lpe_item_has_path_effect_of_type(SPLPEItem *lpeitem, int type)
645
{
646
    std::list<Inkscape::LivePathEffect::LPEObjectReference *>::iterator i;
647
    for (i = lpeitem->path_effect_list->begin(); i != lpeitem->path_effect_list->end(); ++i) {
6884 by Ted Gould
Merging from trunk
648
        Inkscape::LivePathEffect::Effect* lpe = (*i)->lpeobject->get_lpe();
649
        if (lpe && (lpe->effectType() == type)) {
650
            return lpe;
6322 by cilix42
New LPE FreehandShape derived from PatternAlongPath (for the shapes in pen/pencil context); don't apply shapes each time the selection changes; new functions to test for specific LPE type and if a path can accept a new shape
651
        }
652
    }
653
    return NULL;
654
}
655
656
/* Return false if the item is not a path or already has a shape applied */
657
bool sp_lpe_item_can_accept_freehand_shape(SPLPEItem *lpeitem)
658
{
659
    if (!SP_IS_PATH(lpeitem))
660
        return false;
661
662
    if (sp_lpe_item_has_path_effect_of_type(lpeitem, Inkscape::LivePathEffect::FREEHAND_SHAPE))
663
        return false;
664
665
    return true;
666
}
667
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
668
void sp_lpe_item_edit_next_param_oncanvas(SPLPEItem *lpeitem, SPDesktop *dt)
669
{
5766 by johanengelen
LPE STACKING!
670
    Inkscape::LivePathEffect::LPEObjectReference *lperef = sp_lpe_item_get_current_lpereference(lpeitem);
6884 by Ted Gould
Merging from trunk
671
    if (lperef && lperef->lpeobject && lperef->lpeobject->get_lpe()) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
672
        lperef->lpeobject->get_lpe()->editNextParamOncanvas(lpeitem, dt);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
673
    }
674
}
675
676
static void
677
sp_lpe_item_child_added (SPObject *object, Inkscape::XML::Node *child, Inkscape::XML::Node *ref)
678
{
679
    if (((SPObjectClass *) (parent_class))->child_added)
680
        (* ((SPObjectClass *) (parent_class))->child_added) (object, child, ref);
5766 by johanengelen
LPE STACKING!
681
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
682
    if (SP_IS_LPE_ITEM(object) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(object))) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
683
        SPObject *ochild = object->get_child_by_repr(child);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
684
        if ( ochild && SP_IS_LPE_ITEM(ochild) ) {
685
            sp_lpe_item_create_original_path_recursive(SP_LPE_ITEM(ochild));
686
        }
687
    }
688
}
689
690
static void
691
sp_lpe_item_remove_child (SPObject * object, Inkscape::XML::Node * child)
692
{
693
    if (SP_IS_LPE_ITEM(object) && sp_lpe_item_has_path_effect_recursive(SP_LPE_ITEM(object))) {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
694
        SPObject *ochild = object->get_child_by_repr(child);
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
695
        if ( ochild && SP_IS_LPE_ITEM(ochild) ) {
696
            sp_lpe_item_cleanup_original_path_recursive(SP_LPE_ITEM(ochild));
697
        }
698
    }
699
700
    if (((SPObjectClass *) (parent_class))->remove_child)
701
        (* ((SPObjectClass *) (parent_class))->remove_child) (object, child);
702
}
703
5766 by johanengelen
LPE STACKING!
704
static std::string patheffectlist_write_svg(PathEffectList const & list)
705
{
706
    HRefList hreflist;
707
    for (PathEffectList::const_iterator it = list.begin(); it != list.end(); ++it)
708
    {
709
        hreflist.push_back( std::string((*it)->lpeobject_href) );
710
    }
711
    return hreflist_write_svg(hreflist);
712
}
713
714
/**
715
 *  THE function that should be used to generate any patheffectlist string.
716
 * one of the methods to change the effect list:
717
 *  - create temporary href list
718
 *  - populate the templist with the effects from the old list that you want to have and their order
719
 *  - call this function with temp list as param
720
 */
721
static std::string hreflist_write_svg(HRefList const & list)
722
{
723
    std::string r;
724
    bool semicolon_first = false;
725
    for (HRefList::const_iterator it = list.begin(); it != list.end(); ++it)
726
    {
727
        if (semicolon_first) {
728
            r += ';';
729
        }
730
        semicolon_first = true;
731
732
        r += (*it);
733
    }
734
    return r;
735
}
736
737
// Return a copy of the effect list
738
PathEffectList sp_lpe_item_get_effect_list(SPLPEItem *lpeitem)
739
{
740
    return *lpeitem->path_effect_list;
741
}
742
743
Inkscape::LivePathEffect::LPEObjectReference* sp_lpe_item_get_current_lpereference(SPLPEItem *lpeitem)
744
{
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
745
    if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty()) {
5766 by johanengelen
LPE STACKING!
746
        sp_lpe_item_set_current_path_effect(lpeitem, lpeitem->path_effect_list->back());
8839 by johanengelen
work on the lpe group undo bug. it's not solved, but i think LPE code does everything correct now. I think now it's the interplay between undo-system and LPE that bugs.
747
    }
5766 by johanengelen
LPE STACKING!
748
749
    return lpeitem->current_path_effect;
750
}
751
752
Inkscape::LivePathEffect::Effect* sp_lpe_item_get_current_lpe(SPLPEItem *lpeitem)
753
{
754
    Inkscape::LivePathEffect::LPEObjectReference* lperef = sp_lpe_item_get_current_lpereference(lpeitem);
755
756
    if (lperef && lperef->lpeobject)
6884 by Ted Gould
Merging from trunk
757
        return lperef->lpeobject->get_lpe();
5766 by johanengelen
LPE STACKING!
758
    else
759
        return NULL;
760
}
761
762
bool sp_lpe_item_set_current_path_effect(SPLPEItem *lpeitem, Inkscape::LivePathEffect::LPEObjectReference* lperef)
763
{
764
    for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++) {
765
        if ((*it)->lpeobject_repr == lperef->lpeobject_repr) {
766
            lpeitem->current_path_effect = (*it);  // current_path_effect should always be a pointer from the path_effect_list !
767
            return true;
768
        }
769
    }
770
771
    return false;
772
}
773
9012.1.407 by Johan Engelen
fix bug when forking LPE stack
774
/**
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
775
 * Writes a new "inkscape:path-effect" string to xml, where the old_lpeobjects are substituted by the new ones.
9012.1.407 by Johan Engelen
fix bug when forking LPE stack
776
 *  Note that this method messes up the item's \c PathEffectList.
777
 */
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
778
void SPLPEItem::replacePathEffects( std::vector<LivePathEffectObject const *> const old_lpeobjs,
779
                                    std::vector<LivePathEffectObject const *> const new_lpeobjs )
5766 by johanengelen
LPE STACKING!
780
{
781
    HRefList hreflist;
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
782
    for (PathEffectList::const_iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
5766 by johanengelen
LPE STACKING!
783
    {
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
784
        LivePathEffectObject const * current_lpeobj = (*it)->lpeobject;
785
        std::vector<LivePathEffectObject const *>::const_iterator found_it(std::find(old_lpeobjs.begin(), old_lpeobjs.end(), current_lpeobj));
786
        if ( found_it != old_lpeobjs.end() ) {
787
            std::vector<LivePathEffectObject const *>::difference_type found_index = std::distance (old_lpeobjs.begin(), found_it);
788
            const gchar * repr_id = new_lpeobjs[found_index]->getRepr()->attribute("id");
5766 by johanengelen
LPE STACKING!
789
            gchar *hrefstr = g_strdup_printf("#%s", repr_id);
790
            hreflist.push_back( std::string(hrefstr) );
791
            g_free(hrefstr);
792
        }
793
        else {
794
            hreflist.push_back( std::string((*it)->lpeobject_href) );
795
        }
796
    }
797
    std::string r = hreflist_write_svg(hreflist);
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
798
    this->getRepr()->setAttribute("inkscape:path-effect", r.c_str());
5766 by johanengelen
LPE STACKING!
799
}
800
9012.1.419 by Johan Engelen
better fix for lpe stack forking
801
/**
802
 *  Check all effects in the stack if they are used by other items, and fork them if so.
803
 *  It is not recommended to fork the effects by yourself calling LivePathEffectObject::fork_private_if_necessary,
804
 *  use this method instead.
805
 *  Returns true if one or more effects were forked; returns false if nothing was done.
806
 */
807
bool sp_lpe_item_fork_path_effects_if_necessary(SPLPEItem *lpeitem, unsigned int nr_of_allowed_users)
808
{
809
    bool forked = false;
810
811
    if ( sp_lpe_item_has_path_effect(lpeitem) ) {
812
        // If one of the path effects is used by 2 or more items, fork it
813
        // so that each object has its own independent copy of the effect.
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
814
        // Note: replacing path effects messes up the path effect list
815
816
        // Clones of the LPEItem will increase the refcount of the lpeobjects.
817
        // Therefore, nr_of_allowed_users should be increased with the number of clones (i.e. refs to the lpeitem)
818
        nr_of_allowed_users += lpeitem->hrefcount;
819
820
        std::vector<LivePathEffectObject const *> old_lpeobjs, new_lpeobjs;
821
        PathEffectList effect_list =  sp_lpe_item_get_effect_list(lpeitem);
822
        for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
823
        {
824
            LivePathEffectObject *lpeobj = (*it)->lpeobject;
825
            if (lpeobj) {
826
                LivePathEffectObject *forked_lpeobj = lpeobj->fork_private_if_necessary(nr_of_allowed_users);
827
                if (forked_lpeobj != lpeobj) {
828
                    forked = true;
829
                    old_lpeobjs.push_back(lpeobj);
830
                    new_lpeobjs.push_back(forked_lpeobj);
9012.1.419 by Johan Engelen
better fix for lpe stack forking
831
                }
832
            }
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
833
        }
834
835
        if (forked) {
836
            lpeitem->replacePathEffects(old_lpeobjs, new_lpeobjs);
837
        }
9012.1.419 by Johan Engelen
better fix for lpe stack forking
838
    }
839
840
    return forked;
841
}
842
5766 by johanengelen
LPE STACKING!
843
// Enable or disable the path effects of the item.
844
// The counter allows nested calls
845
static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable)
846
{
847
    if (enable) {
848
        lpeitem->path_effects_enabled++;
849
    }
850
    else {
851
        lpeitem->path_effects_enabled--;
852
    }
853
}
854
855
// Are the path effects enabled on this item ?
856
bool sp_lpe_item_path_effects_enabled(SPLPEItem *lpeitem)
857
{
858
    return lpeitem->path_effects_enabled > 0;
859
}
860
5227 by pjrm
svn propset svn:eol-style native *.[ch] *.cpp (including buildtool.cpp, packaging/macosx/native-gtk/*, src/dom/**).
861
/*
862
  Local Variables:
863
  mode:c++
864
  c-file-style:"stroustrup"
865
  c-file-offsets:((innamespace . 0)(inline-open . 0)(case-label . +))
866
  indent-tabs-mode:nil
867
  fill-column:99
868
  End:
869
*/
9020 by JazzyNico
Code refactoring and merging with trunk (revision 10599).
870
// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :