~ubuntu-branches/ubuntu/natty/inkscape/natty

« back to all changes in this revision

Viewing changes to src/sp-lpe-item.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Alex Valavanis
  • Date: 2010-09-12 19:44:58 UTC
  • mfrom: (1.1.12 upstream) (45.1.3 maverick)
  • Revision ID: james.westby@ubuntu.com-20100912194458-4sjwmbl7dlsrk5dc
Tags: 0.48.0-1ubuntu1
* Merge with Debian unstable (LP: #628048, LP: #401567, LP: #456248, 
  LP: #463602, LP: #591986)
* debian/control: 
  - Ubuntu maintainers
  - Promote python-lxml, python-numpy, python-uniconvertor to Recommends.
  - Demote pstoedit to Suggests (universe package).
  - Suggests ttf-dejavu instead of ttf-bitstream-vera (LP: #513319)
* debian/rules:
  - Run intltool-update on build (Ubuntu-specific).
  - Add translation domain to .desktop files (Ubuntu-specific).
* debian/dirs:
  - Add usr/share/pixmaps.  Allow inkscape.xpm installation
* drop 50-poppler-API.dpatch (now upstream)
* drop 51-paste-in-unwritable-directory.dpatch (now upstream) 

Show diffs side-by-side

added added

removed removed

Lines of Context:
33
33
#include "message-stack.h"
34
34
#include "inkscape.h"
35
35
#include "desktop.h"
36
 
#include "node-context.h"
37
36
#include "shape-editor.h"
38
37
 
39
38
#include <algorithm>
56
55
 
57
56
static void sp_lpe_item_enable_path_effects(SPLPEItem *lpeitem, bool enable);
58
57
 
59
 
static void lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem);
60
58
static void lpeobject_ref_modified(SPObject *href, guint flags, SPLPEItem *lpeitem);
61
59
 
62
60
static void sp_lpe_item_create_original_path_recursive(SPLPEItem *lpeitem);
120
118
    lpeitem->path_effect_list = new PathEffectList();
121
119
    lpeitem->current_path_effect = NULL;
122
120
 
123
 
    new (&lpeitem->lpe_modified_connection) sigc::connection();
 
121
    lpeitem->lpe_modified_connection_list = new std::list<sigc::connection>();
124
122
}
125
123
 
126
124
static void
154
152
{
155
153
    SPLPEItem *lpeitem = (SPLPEItem *) object;
156
154
 
157
 
    lpeitem->lpe_modified_connection.disconnect();
158
 
    lpeitem->lpe_modified_connection.~connection();
 
155
    // disconnect all modified listeners:
 
156
    for (std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
 
157
         mod_it != lpeitem->lpe_modified_connection_list->end(); ++mod_it)
 
158
    {
 
159
        mod_it->disconnect();
 
160
    }
 
161
    delete lpeitem->lpe_modified_connection_list;
 
162
    lpeitem->lpe_modified_connection_list = NULL;
159
163
 
160
164
    PathEffectList::iterator it = lpeitem->path_effect_list->begin();
161
165
    while ( it != lpeitem->path_effect_list->end() ) {
165
169
        it = lpeitem->path_effect_list->erase(it);
166
170
    }
167
171
    // delete the list itself
168
 
    delete SP_LPE_ITEM(object)->path_effect_list;
 
172
    delete lpeitem->path_effect_list;
 
173
    lpeitem->path_effect_list = NULL;
169
174
 
170
175
    if (((SPObjectClass *) parent_class)->release)
171
176
        ((SPObjectClass *) parent_class)->release(object);
187
192
                // Disable the path effects while populating the LPE list
188
193
                 sp_lpe_item_enable_path_effects(lpeitem, false);
189
194
 
 
195
                // disconnect all modified listeners:
 
196
                for ( std::list<sigc::connection>::iterator mod_it = lpeitem->lpe_modified_connection_list->begin();
 
197
                      mod_it != lpeitem->lpe_modified_connection_list->end();
 
198
                      ++mod_it)
 
199
                {
 
200
                    mod_it->disconnect();
 
201
                }
 
202
                lpeitem->lpe_modified_connection_list->clear();
190
203
                // Clear the path effect list
191
204
                PathEffectList::iterator it = lpeitem->path_effect_list->begin();
192
205
                while ( it != lpeitem->path_effect_list->end() )
202
215
                    std::string href;
203
216
                    while (std::getline(iss, href, ';'))
204
217
                    {
205
 
                        Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(lpeitem));
206
 
                        path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_LPE_ITEM(object)));
207
 
                        // Now do the attaching, which emits the changed signal.
208
 
                        // Fixme, it should not do this changed signal and updating before all effects are added to the path_effect_list
 
218
                        Inkscape::LivePathEffect::LPEObjectReference *path_effect_ref = new Inkscape::LivePathEffect::LPEObjectReference(object);
209
219
                        try {
210
220
                            path_effect_ref->link(href.c_str());
211
221
                        } catch (Inkscape::BadURIException e) {
216
226
                        }
217
227
 
218
228
                        lpeitem->path_effect_list->push_back(path_effect_ref);
219
 
                        if ( !(path_effect_ref->lpeobject && path_effect_ref->lpeobject->get_lpe()) ) {
 
229
                        if ( path_effect_ref->lpeobject && path_effect_ref->lpeobject->get_lpe() ) {
 
230
                            // connect modified-listener
 
231
                            lpeitem->lpe_modified_connection_list->push_back(
 
232
                                                path_effect_ref->lpeobject->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem)) );
 
233
                        } else {
220
234
                            // something has gone wrong in finding the right patheffect.
221
235
                            g_warning("Unknown LPE type specified, LPE stack effectively disabled");
222
236
                            // keep the effect in the lpestack, so the whole stack is effectively disabled but maintained
246
260
    }
247
261
 
248
262
    // update the helperpaths of all LPEs applied to the item
249
 
    // TODO: is there a more canonical place for this, since we don't have instant access to the item's nodepath?
250
 
    // FIXME: this is called multiple (at least 3) times; how can we avoid this?
251
 
 
252
 
    // FIXME: ditch inkscape_active_event_context()
253
 
    SPEventContext *ec = inkscape_active_event_context();
254
 
    if (!SP_IS_NODE_CONTEXT(ec)) return;
255
 
    ShapeEditor *sh = ec->shape_editor;
256
 
    g_assert(sh);
257
 
    if (!sh->has_nodepath()) return;
258
 
 
259
 
    Inkscape::NodePath::Path *np = sh->get_nodepath();
260
 
    sp_nodepath_update_helperpaths(np);
 
263
    // TODO: re-add for the new node tool
261
264
}
262
265
 
263
266
/**
380
383
            if (dynamic_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)) {
381
384
                if (!lpe->isVisible()) {
382
385
                    // we manually disable text for LPEPathLength
383
 
                    dynamic_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)->hideCanvasText();
 
386
                    // use static_cast, because we already checked for the right type above
 
387
                    static_cast<Inkscape::LivePathEffect::LPEPathLength *>(lpe)->hideCanvasText();
384
388
                }
385
389
            }
386
390
        }
407
411
}
408
412
 
409
413
/**
410
 
 * Gets called when (re)attached to another lpeobject.
411
 
 */
412
 
static void
413
 
lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPLPEItem *lpeitem)
414
 
{
415
 
    if (old_ref) {
416
 
        sp_signal_disconnect_by_data(old_ref, lpeitem);
417
 
    }
418
 
    if ( IS_LIVEPATHEFFECT(ref) && ref != lpeitem )
419
 
    {
420
 
        lpeitem->lpe_modified_connection.disconnect();
421
 
        lpeitem->lpe_modified_connection = ref->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), lpeitem));
422
 
        lpeobject_ref_modified(ref, 0, lpeitem);
423
 
    }
424
 
}
425
 
 
426
 
/**
427
 
 * Gets called when lpeobject repr contents change: i.e. parameter change.
 
414
 * Gets called when any of the lpestack's lpeobject repr contents change: i.e. parameter change in any of the stacked LPEs
428
415
 */
429
416
static void
430
417
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPLPEItem *lpeitem)
431
418
{
 
419
#ifdef SHAPE_VERBOSE
 
420
    g_message("lpeobject_ref_modified");
 
421
#endif
432
422
    sp_lpe_item_update_patheffect (lpeitem, true, true);
433
423
}
434
424
 
753
743
 
754
744
Inkscape::LivePathEffect::LPEObjectReference* sp_lpe_item_get_current_lpereference(SPLPEItem *lpeitem)
755
745
{
756
 
    if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty())
 
746
    if (!lpeitem->current_path_effect && !lpeitem->path_effect_list->empty()) {
757
747
        sp_lpe_item_set_current_path_effect(lpeitem, lpeitem->path_effect_list->back());
 
748
    }
758
749
 
759
750
    return lpeitem->current_path_effect;
760
751
}
773
764
{
774
765
    for (PathEffectList::iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); it++) {
775
766
        if ((*it)->lpeobject_repr == lperef->lpeobject_repr) {
776
 
            lpeobject_ref_changed(NULL, (*it)->lpeobject, SP_LPE_ITEM(lpeitem)); // FIXME: explain why this is here?
777
767
            lpeitem->current_path_effect = (*it);  // current_path_effect should always be a pointer from the path_effect_list !
778
768
            return true;
779
769
        }
782
772
    return false;
783
773
}
784
774
 
785
 
void sp_lpe_item_replace_path_effect(SPLPEItem *lpeitem, LivePathEffectObject * old_lpeobj,
786
 
                                        LivePathEffectObject * new_lpeobj)
 
775
/**
 
776
 * Writes a new "inkscape:path-effect" string to xml, where the old_lpeobjects are substituted by the new ones.
 
777
 *  Note that this method messes up the item's \c PathEffectList.
 
778
 */
 
779
void SPLPEItem::replacePathEffects( std::vector<LivePathEffectObject const *> const old_lpeobjs,
 
780
                                    std::vector<LivePathEffectObject const *> const new_lpeobjs )
787
781
{
788
782
    HRefList hreflist;
789
 
    for (PathEffectList::const_iterator it = lpeitem->path_effect_list->begin(); it != lpeitem->path_effect_list->end(); ++it)
 
783
    for (PathEffectList::const_iterator it = this->path_effect_list->begin(); it != this->path_effect_list->end(); ++it)
790
784
    {
791
 
        if ((*it)->lpeobject == old_lpeobj) {
792
 
            const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
 
785
        LivePathEffectObject const * current_lpeobj = (*it)->lpeobject;
 
786
        std::vector<LivePathEffectObject const *>::const_iterator found_it(std::find(old_lpeobjs.begin(), old_lpeobjs.end(), current_lpeobj));
 
787
        if ( found_it != old_lpeobjs.end() ) {
 
788
            std::vector<LivePathEffectObject const *>::difference_type found_index = std::distance (old_lpeobjs.begin(), found_it);
 
789
            const gchar * repr_id = SP_OBJECT_REPR(new_lpeobjs[found_index])->attribute("id");
793
790
            gchar *hrefstr = g_strdup_printf("#%s", repr_id);
794
791
            hreflist.push_back( std::string(hrefstr) );
795
792
            g_free(hrefstr);
799
796
        }
800
797
    }
801
798
    std::string r = hreflist_write_svg(hreflist);
802
 
    SP_OBJECT_REPR(lpeitem)->setAttribute("inkscape:path-effect", r.c_str());
 
799
    SP_OBJECT_REPR(this)->setAttribute("inkscape:path-effect", r.c_str());
 
800
}
 
801
 
 
802
/**
 
803
 *  Check all effects in the stack if they are used by other items, and fork them if so.
 
804
 *  It is not recommended to fork the effects by yourself calling LivePathEffectObject::fork_private_if_necessary,
 
805
 *  use this method instead.
 
806
 *  Returns true if one or more effects were forked; returns false if nothing was done.
 
807
 */
 
808
bool sp_lpe_item_fork_path_effects_if_necessary(SPLPEItem *lpeitem, unsigned int nr_of_allowed_users)
 
809
{
 
810
    bool forked = false;
 
811
 
 
812
    if ( sp_lpe_item_has_path_effect(lpeitem) ) {
 
813
        // If one of the path effects is used by 2 or more items, fork it
 
814
        // so that each object has its own independent copy of the effect.
 
815
        // Note: replacing path effects messes up the path effect list
 
816
 
 
817
        // Clones of the LPEItem will increase the refcount of the lpeobjects.
 
818
        // Therefore, nr_of_allowed_users should be increased with the number of clones (i.e. refs to the lpeitem)
 
819
        nr_of_allowed_users += SP_OBJECT(lpeitem)->hrefcount;
 
820
 
 
821
        std::vector<LivePathEffectObject const *> old_lpeobjs, new_lpeobjs;
 
822
        PathEffectList effect_list =  sp_lpe_item_get_effect_list(lpeitem);
 
823
        for (PathEffectList::iterator it = effect_list.begin(); it != effect_list.end(); it++)
 
824
        {
 
825
            LivePathEffectObject *lpeobj = (*it)->lpeobject;
 
826
            if (lpeobj) {
 
827
                LivePathEffectObject *forked_lpeobj = lpeobj->fork_private_if_necessary(nr_of_allowed_users);
 
828
                if (forked_lpeobj != lpeobj) {
 
829
                    forked = true;
 
830
                    old_lpeobjs.push_back(lpeobj);
 
831
                    new_lpeobjs.push_back(forked_lpeobj);
 
832
                }
 
833
            }
 
834
        }
 
835
 
 
836
        if (forked) {
 
837
            lpeitem->replacePathEffects(old_lpeobjs, new_lpeobjs);
 
838
        }
 
839
    }
 
840
 
 
841
    return forked;
803
842
}
804
843
 
805
844
// Enable or disable the path effects of the item.