~valavanisalex/ubuntu/oneiric/inkscape/inkscape_0.48.1-2ubuntu4

« back to all changes in this revision

Viewing changes to src/sp-shape.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Kees Cook, Kees Cook, Ted Gould
  • Date: 2008-02-10 14:20:16 UTC
  • mfrom: (1.1.6 upstream)
  • Revision ID: james.westby@ubuntu.com-20080210142016-vcnb2zqyhszu0xvb
Tags: 0.46~pre1-0ubuntu1
[ Kees Cook ]
* debian/control:
  - add libgtkspell-dev build-dep to gain GtkSpell features (LP: #183547).
  - update Standards version (no changes needed).
  - add Vcs and Homepage fields.
  - switch to new python-lxml dep.
* debian/{control,rules}: switch from dpatch to quilt for more sanity.
* debian/patches/20_fix_glib_and_gxx43_ftbfs.patch:
  - merged against upstream fixes.
  - added additional fixes for newly written code.
* debian/rules: enable parallel building.

[ Ted Gould ]
* Updating POTFILES.in to make it so things build correctly.
* debian/control:
  - add ImageMagick++ and libboost-dev to build-deps

Show diffs side-by-side

added added

removed removed

Lines of Context:
9
9
 * Copyright (C) 1999-2002 Lauris Kaplinski
10
10
 * Copyright (C) 2000-2001 Ximian, Inc.
11
11
 * Copyright (C) 2004 John Cliff
 
12
 * Copyright (C) 2007-2008 Johan Engelen
12
13
 *
13
14
 * Released under GNU GPL, read the file 'COPYING' for more information
14
15
 */
35
36
#include "marker.h"
36
37
#include "sp-path.h"
37
38
#include "prefs-utils.h"
 
39
#include "attributes.h"
 
40
 
 
41
#include "live_effects/effect.h"
 
42
#include "live_effects/lpeobject.h"
 
43
#include "live_effects/lpeobject-reference.h"
 
44
#include "uri.h"
 
45
#include "extract-uri.h"
 
46
#include "uri-references.h"
 
47
#include "bad-uri-exception.h"
 
48
#include "xml/repr.h"
 
49
 
 
50
#include "util/mathfns.h" // for triangle_area()
38
51
 
39
52
#define noSHAPE_VERBOSE
40
53
 
45
58
static void sp_shape_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr);
46
59
static void sp_shape_release (SPObject *object);
47
60
 
 
61
static void sp_shape_set(SPObject *object, unsigned key, gchar const *value);
48
62
static void sp_shape_update (SPObject *object, SPCtx *ctx, unsigned int flags);
49
63
static void sp_shape_modified (SPObject *object, unsigned int flags);
 
64
static Inkscape::XML::Node *sp_shape_write(SPObject *object, Inkscape::XML::Node *repr, guint flags);
50
65
 
51
66
static void sp_shape_bbox(SPItem const *item, NRRect *bbox, NR::Matrix const &transform, unsigned const flags);
52
67
void sp_shape_print (SPItem * item, SPPrintContext * ctx);
56
71
 
57
72
static void sp_shape_update_marker_view (SPShape *shape, NRArenaItem *ai);
58
73
 
 
74
static void lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPShape *shape);
 
75
static void lpeobject_ref_modified(SPObject *href, guint flags, SPShape *shape);
 
76
 
59
77
static SPItemClass *parent_class;
60
78
 
61
79
/**
88
106
static void
89
107
sp_shape_class_init (SPShapeClass *klass)
90
108
{
91
 
        GObjectClass *gobject_class;
 
109
    GObjectClass *gobject_class;
92
110
        SPObjectClass *sp_object_class;
93
111
        SPItemClass * item_class;
94
112
        SPPathClass * path_class;
95
113
 
96
 
        gobject_class = (GObjectClass *) klass;
 
114
    gobject_class = (GObjectClass *) klass;
97
115
        sp_object_class = (SPObjectClass *) klass;
98
116
        item_class = (SPItemClass *) klass;
99
117
        path_class = (SPPathClass *) klass;
100
118
 
101
119
        parent_class = (SPItemClass *)g_type_class_peek_parent (klass);
102
120
 
103
 
        gobject_class->finalize = sp_shape_finalize;
 
121
    gobject_class->finalize = sp_shape_finalize;
104
122
 
105
123
        sp_object_class->build = sp_shape_build;
106
124
        sp_object_class->release = sp_shape_release;
 
125
    sp_object_class->set = sp_shape_set;
107
126
        sp_object_class->update = sp_shape_update;
108
127
        sp_object_class->modified = sp_shape_modified;
 
128
    sp_object_class->write = sp_shape_write;
109
129
 
110
130
        item_class->bbox = sp_shape_bbox;
111
131
        item_class->print = sp_shape_print;
112
132
        item_class->show = sp_shape_show;
113
133
        item_class->hide = sp_shape_hide;
114
 
        item_class->snappoints = sp_shape_snappoints;
 
134
    item_class->snappoints = sp_shape_snappoints;
 
135
 
 
136
    klass->set_shape = NULL;
 
137
    klass->update_patheffect = NULL;
115
138
}
116
139
 
117
140
/**
120
143
static void
121
144
sp_shape_init (SPShape *shape)
122
145
{
 
146
    shape->path_effect_href = NULL;
 
147
    shape->path_effect_ref  = new Inkscape::LivePathEffect::LPEObjectReference(SP_OBJECT(shape));
 
148
        new (&shape->lpe_modified_connection) sigc::connection();
 
149
 
123
150
    for ( int i = 0 ; i < SP_MARKER_LOC_QTY ; i++ ) {
124
151
        new (&shape->release_connect[i]) sigc::connection();
125
152
        new (&shape->modified_connect[i]) sigc::connection();
146
173
/**
147
174
 * Virtual build callback for SPMarker.
148
175
 *
149
 
 * This is to be invoked immediately after creation of an SPShape.  This is 
150
 
 * just a stub.
 
176
 * This is to be invoked immediately after creation of an SPShape.
151
177
 *
152
178
 * \see sp_object_build()
153
179
 */
154
180
static void
155
181
sp_shape_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
156
182
{
157
 
        if (((SPObjectClass *) (parent_class))->build) {
158
 
          (*((SPObjectClass *) (parent_class))->build) (object, document, repr);
159
 
        }
 
183
    SP_SHAPE(object)->path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_SHAPE(object)));
 
184
 
 
185
    sp_object_read_attr(object, "inkscape:path-effect");
 
186
 
 
187
    if (((SPObjectClass *) (parent_class))->build) {
 
188
       (*((SPObjectClass *) (parent_class))->build) (object, document, repr);
 
189
    }
160
190
}
161
191
 
162
192
/**
193
223
                shape->curve = sp_curve_unref (shape->curve);
194
224
        }
195
225
 
 
226
    if (shape->path_effect_href) {
 
227
        g_free(shape->path_effect_href);
 
228
    }
 
229
    shape->path_effect_ref->detach();
 
230
 
 
231
    shape->lpe_modified_connection.disconnect();
 
232
    shape->lpe_modified_connection.~connection();
 
233
    
196
234
        if (((SPObjectClass *) parent_class)->release) {
197
235
          ((SPObjectClass *) parent_class)->release (object);
198
236
        }
199
237
}
200
238
 
 
239
 
 
240
 
 
241
static void
 
242
sp_shape_set(SPObject *object, unsigned int key, gchar const *value)
 
243
{
 
244
    SPShape *shape = (SPShape *) object;
 
245
 
 
246
    switch (key) {
 
247
        case SP_ATTR_INKSCAPE_PATH_EFFECT:
 
248
            if ( value && shape->path_effect_href && ( strcmp(value, shape->path_effect_href) == 0 ) ) {
 
249
                /* No change, do nothing. */
 
250
            } else {
 
251
                if (shape->path_effect_href) {
 
252
                    g_free(shape->path_effect_href);
 
253
                    shape->path_effect_href = NULL;
 
254
                }
 
255
                if (value) {
 
256
                    shape->path_effect_href = g_strdup(value);
 
257
 
 
258
                    // Now do the attaching, which emits the changed signal.
 
259
                    try {
 
260
                        shape->path_effect_ref->attach(Inkscape::URI(value));
 
261
                    } catch (Inkscape::BadURIException &e) {
 
262
                        g_warning("%s", e.what());
 
263
                        shape->path_effect_ref->detach();
 
264
                    }
 
265
                } else {
 
266
                    // Detach, which emits the changed signal.
 
267
                    shape->path_effect_ref->detach();
 
268
                }
 
269
            }
 
270
            break;
 
271
        default:
 
272
            if (((SPObjectClass *) parent_class)->set) {
 
273
                ((SPObjectClass *) parent_class)->set(object, key, value);
 
274
            }
 
275
            break;
 
276
    }
 
277
}
 
278
 
 
279
static Inkscape::XML::Node *
 
280
sp_shape_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
 
281
{
 
282
    SPShape *shape = (SPShape *) object;
 
283
 
 
284
    if ( shape->path_effect_href ) {
 
285
        repr->setAttribute("inkscape:path-effect", shape->path_effect_href);
 
286
    } else {
 
287
        repr->setAttribute("inkscape:path-effect", NULL);
 
288
    }
 
289
 
 
290
    if (((SPObjectClass *)(parent_class))->write) {
 
291
        ((SPObjectClass *)(parent_class))->write(object, repr, flags);
 
292
    }
 
293
 
 
294
    return repr;
 
295
}
 
296
 
201
297
/** 
202
298
 * Updates the shape when its attributes have changed.  Also establishes
203
299
 * marker objects to match the style settings.  
238
334
        if (flags & (SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG)) {
239
335
                /* This is suboptimal, because changing parent style schedules recalculation */
240
336
                /* But on the other hand - how can we know that parent does not tie style and transform */
241
 
                NR::Rect const paintbox = SP_ITEM(object)->invokeBbox(NR::identity());
 
337
                NR::Maybe<NR::Rect> paintbox = SP_ITEM(object)->getBounds(NR::identity());
242
338
                for (SPItemView *v = SP_ITEM (shape)->display; v != NULL; v = v->next) {
243
339
                    NRArenaShape * const s = NR_ARENA_SHAPE(v->arenaitem);
244
340
                    if (flags & SP_OBJECT_MODIFIED_FLAG) {
245
341
                        nr_arena_shape_set_path(s, shape->curve, (flags & SP_OBJECT_USER_MODIFIED_FLAG_B));
246
342
                    }
247
 
                    s->setPaintBox(paintbox);
 
343
                    if (paintbox) {
 
344
                        s->setPaintBox(*paintbox);
 
345
                    }
248
346
                }
249
347
        }
250
348
 
616
714
 
617
715
        nr_path_matrix_bbox_union(&bp, transform, &cbbox);
618
716
 
619
 
        SPStyle* style=SP_OBJECT_STYLE (item);
620
 
        if (style->stroke.type != SP_PAINT_TYPE_NONE) {
621
 
            double const scale = expansion(transform);
622
 
            if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
623
 
                double const width = MAX(0.125, style->stroke_width.computed * scale);
624
 
                if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
625
 
                    cbbox.x0-=0.5*width;
626
 
                    cbbox.x1+=0.5*width;
627
 
                    cbbox.y0-=0.5*width;
628
 
                    cbbox.y1+=0.5*width;
 
717
        if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) {
 
718
            
 
719
            SPStyle* style=SP_OBJECT_STYLE (item);
 
720
            if (!style->stroke.isNone()) {
 
721
                double const scale = expansion(transform);
 
722
                if ( fabs(style->stroke_width.computed * scale) > 0.01 ) { // sinon c'est 0=oon veut pas de bord
 
723
                    double const width = MAX(0.125, style->stroke_width.computed * scale);
 
724
                    if ( fabs(cbbox.x1-cbbox.x0) > -0.00001 && fabs(cbbox.y1-cbbox.y0) > -0.00001 ) {
 
725
                        cbbox.x0-=0.5*width;
 
726
                        cbbox.x1+=0.5*width;
 
727
                        cbbox.y0-=0.5*width;
 
728
                        cbbox.y1+=0.5*width;
 
729
                    }
629
730
                }
630
731
            }
631
 
        }
632
 
 
633
 
        // Union with bboxes of the markers, if any
634
 
        if (sp_shape_has_markers (shape)) {
635
 
            for (NArtBpath* bp = SP_CURVE_BPATH(shape->curve); bp->code != NR_END; bp++) {
636
 
                for (int m = SP_MARKER_LOC_START; m < SP_MARKER_LOC_QTY; m++) {
637
 
                    if (sp_shape_marker_required (shape, m, bp)) {
638
 
 
639
 
                        SPMarker* marker = SP_MARKER (shape->marker[m]);
640
 
                        SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
641
 
 
642
 
                        NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
643
 
 
644
 
                        if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
645
 
                            tr = NR::scale(style->stroke_width.computed) * tr;
 
732
 
 
733
            // Union with bboxes of the markers, if any
 
734
            if (sp_shape_has_markers (shape)) {
 
735
                for (NArtBpath* bp = SP_CURVE_BPATH(shape->curve); bp->code != NR_END; bp++) {
 
736
                    for (int m = SP_MARKER_LOC_START; m < SP_MARKER_LOC_QTY; m++) {
 
737
                        if (sp_shape_marker_required (shape, m, bp)) {
 
738
 
 
739
                            SPMarker* marker = SP_MARKER (shape->marker[m]);
 
740
                            SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
 
741
 
 
742
                            NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
 
743
 
 
744
                            if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
 
745
                                tr = NR::scale(style->stroke_width.computed) * tr;
 
746
                            }
 
747
 
 
748
                            // total marker transform
 
749
                            tr = marker_item->transform * marker->c2p * tr * transform;
 
750
 
 
751
                            // get bbox of the marker with that transform
 
752
                            NRRect marker_bbox;
 
753
                            sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
 
754
                            // union it with the shape bbox
 
755
                            nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
646
756
                        }
647
 
 
648
 
                        // total marker transform
649
 
                        tr = marker_item->transform * marker->c2p * tr * transform;
650
 
 
651
 
                        // get bbox of the marker with that transform
652
 
                        NRRect marker_bbox;
653
 
                        sp_item_invoke_bbox (marker_item, &marker_bbox, tr, true);
654
 
                        // union it with the shape bbox
655
 
                        nr_rect_d_union (&cbbox, &cbbox, &marker_bbox);
656
757
                    }
657
758
                }
658
759
            }
697
798
 
698
799
        SPStyle* style = SP_OBJECT_STYLE (item);
699
800
 
700
 
        if (style->fill.type != SP_PAINT_TYPE_NONE) {
 
801
        if (!style->fill.isNone()) {
701
802
                NRBPath bp;
702
803
                bp.path = SP_CURVE_BPATH(shape->curve);
703
804
                sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox);
704
805
        }
705
806
 
706
 
        if (style->stroke.type != SP_PAINT_TYPE_NONE) {
 
807
        if (!style->stroke.isNone()) {
707
808
                NRBPath bp;
708
809
                bp.path = SP_CURVE_BPATH(shape->curve);
709
810
                sp_print_stroke (ctx, &bp, i2d, style, &pbox, &dbox, &bbox);
744
845
 * Sets style, path, and paintbox.  Updates marker views, including dimensions.
745
846
 */
746
847
static NRArenaItem *
747
 
sp_shape_show (SPItem *item, NRArena *arena, unsigned int key, unsigned int flags)
 
848
sp_shape_show (SPItem *item, NRArena *arena, unsigned int /*key*/, unsigned int /*flags*/)
748
849
{
749
850
        SPObject *object = SP_OBJECT(item);
750
851
        SPShape *shape = SP_SHAPE(item);
753
854
        NRArenaShape * const s = NR_ARENA_SHAPE(arenaitem);
754
855
        nr_arena_shape_set_style(s, object->style);
755
856
        nr_arena_shape_set_path(s, shape->curve, false);
756
 
        NR::Rect const paintbox = item->invokeBbox(NR::identity());
757
 
        s->setPaintBox(paintbox);
 
857
        NR::Maybe<NR::Rect> paintbox = item->getBounds(NR::identity());
 
858
        if (paintbox) {
 
859
            s->setPaintBox(*paintbox);
 
860
        }
758
861
 
759
862
        if (sp_shape_has_markers (shape)) {
760
863
 
878
981
 * No-op.  Exists for handling 'modified' messages
879
982
 */
880
983
static void
881
 
sp_shape_marker_modified (SPObject *marker, guint flags, SPItem *item)
 
984
sp_shape_marker_modified (SPObject */*marker*/, guint /*flags*/, SPItem */*item*/)
882
985
{
883
986
        /* I think mask does update automagically */
884
987
        /* g_warning ("Item %s mask %s modified", SP_OBJECT_ID (item), SP_OBJECT_ID (mask)); */
901
1004
        return;
902
1005
    }
903
1006
 
904
 
    SPObject *mrk = sp_uri_reference_resolve (SP_OBJECT_DOCUMENT (object), value);
 
1007
    SPObject *mrk = sp_css_uri_reference_resolve (SP_OBJECT_DOCUMENT (object), value);
905
1008
    if (mrk != shape->marker[key]) {
906
1009
        if (shape->marker[key]) {
907
1010
            SPItemView *v;
998
1101
}
999
1102
 
1000
1103
/**
1001
 
 * Sets the snappoint p to the end point of the path segment
 
1104
 * Return all nodes in a path that are to be considered for snapping
1002
1105
 */
1003
1106
static void sp_shape_snappoints(SPItem const *item, SnapPointsIter p)
1004
1107
{
1009
1112
    if (shape->curve == NULL) {
1010
1113
        return;
1011
1114
    }
1012
 
 
 
1115
    
1013
1116
    NR::Matrix const i2d (sp_item_i2d_affine (item));
1014
 
 
1015
 
    /* Use the end points of each segment of the path */
1016
 
    NArtBpath const *bp = SP_CURVE_BPATH(shape->curve);
1017
 
    while (bp->code != NR_END) {
1018
 
        *p = bp->c(3) * i2d;
1019
 
        bp++;
1020
 
    }
1021
 
}
1022
 
 
 
1117
    NArtBpath const *b = SP_CURVE_BPATH(shape->curve);    
 
1118
    
 
1119
    // Cycle through the nodes in the concatenated subpaths
 
1120
    while (b->code != NR_END) {
 
1121
        NR::Point pos = b->c(3) * i2d; // this is the current node
 
1122
        
 
1123
        // NR_MOVETO Indicates the start of a closed subpath, see nr-path-code.h
 
1124
        // If we're looking at a closed subpath, then we can skip this first 
 
1125
        // point of the subpath because it's coincident with the last point.  
 
1126
        if (b->code != NR_MOVETO) {
 
1127
            if (b->code == NR_MOVETO_OPEN || b->code == NR_LINETO || b[1].code == NR_LINETO || b[1].code == NR_END) {
 
1128
                // end points of a line segment are always considered for snapping
 
1129
                *p = pos; 
 
1130
            } else {        
 
1131
                // g_assert(b->code == NR_CURVETO);
 
1132
                NR::Point ppos, npos;
 
1133
                ppos = b->code == NR_CURVETO ? b->c(2) * i2d : pos; // backward handle 
 
1134
                npos = b[1].code == NR_CURVETO ? b[1].c(1) * i2d : pos; // forward handle            
 
1135
                // Determine whether a node is at a smooth part of the path, by 
 
1136
                // calculating a measure for the collinearity of the handles
 
1137
                bool c1 = fabs (Inkscape::Util::triangle_area (pos, ppos, npos)) < 1; // points are (almost) collinear
 
1138
                bool c2 = NR::L2(pos - ppos) < 1e-6 || NR::L2(pos - npos) < 1e-6; // endnode, or a node with a retracted handle
 
1139
                if (!(c1 & !c2)) {
 
1140
                    *p = pos; // only return non-smooth nodes ("cusps")
 
1141
                }
 
1142
            }
 
1143
        }
 
1144
        
 
1145
        b++;
 
1146
    }
 
1147
}
 
1148
 
 
1149
 
 
1150
LivePathEffectObject *
 
1151
sp_shape_get_livepatheffectobject(SPShape *shape) {
 
1152
    if (!shape) return NULL;
 
1153
 
 
1154
    if (sp_shape_has_path_effect(shape)) {
 
1155
        return shape->path_effect_ref->lpeobject;
 
1156
    } else {
 
1157
        return NULL;
 
1158
    }
 
1159
}
 
1160
 
 
1161
Inkscape::LivePathEffect::Effect *
 
1162
sp_shape_get_livepatheffect(SPShape *shape) {
 
1163
    if (!shape) return NULL;
 
1164
 
 
1165
    LivePathEffectObject * lpeobj = sp_shape_get_livepatheffectobject(shape);
 
1166
    if (lpeobj)
 
1167
        return lpeobj->lpe;
 
1168
    else
 
1169
        return NULL;
 
1170
}
 
1171
 
 
1172
/**
 
1173
 * Calls any registered handlers for the update_patheffect action
 
1174
 */
 
1175
void
 
1176
sp_shape_update_patheffect (SPShape *shape, bool write)
 
1177
{
 
1178
#ifdef SHAPE_VERBOSE
 
1179
    g_message("sp_shape_update_patheffect: %p\n", shape);
 
1180
#endif
 
1181
    g_return_if_fail (shape != NULL);
 
1182
    g_return_if_fail (SP_IS_SHAPE (shape));
 
1183
 
 
1184
    if (SP_SHAPE_CLASS (G_OBJECT_GET_CLASS (shape))->update_patheffect) {
 
1185
        SP_SHAPE_CLASS (G_OBJECT_GET_CLASS (shape))->update_patheffect (shape, write);
 
1186
    }
 
1187
}
 
1188
 
 
1189
void sp_shape_perform_path_effect(SPCurve *curve, SPShape *shape) {
 
1190
    if (!shape) return;
 
1191
    if (!curve) return;
 
1192
 
 
1193
    LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);
 
1194
    if (lpeobj && lpeobj->lpe) {
 
1195
        lpeobj->lpe->doEffect(curve);
 
1196
    }
 
1197
}
 
1198
 
 
1199
/**
 
1200
 * Gets called when (re)attached to another lpeobject.
 
1201
 */
 
1202
static void
 
1203
lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPShape *shape)
 
1204
{
 
1205
    if (old_ref) {
 
1206
        sp_signal_disconnect_by_data(old_ref, shape);
 
1207
    }
 
1208
    if ( IS_LIVEPATHEFFECT(ref) && ref != shape )
 
1209
    {
 
1210
        shape->lpe_modified_connection.disconnect();
 
1211
        shape->lpe_modified_connection = ref->connectModified(sigc::bind(sigc::ptr_fun(&lpeobject_ref_modified), shape));
 
1212
        lpeobject_ref_modified(ref, 0, shape);
 
1213
    }
 
1214
}
 
1215
 
 
1216
/**
 
1217
 * Gets called when lpeobject repr contents change: i.e. parameter change.
 
1218
 */
 
1219
static void
 
1220
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPShape *shape)
 
1221
{
 
1222
    sp_shape_update_patheffect (shape, true);
 
1223
}
 
1224
 
 
1225
void sp_shape_set_path_effect(SPShape *shape, gchar *value)
 
1226
{
 
1227
    if (!value) {
 
1228
        sp_shape_remove_path_effect(shape);
 
1229
    } else {
 
1230
        SP_OBJECT_REPR(shape)->setAttribute("inkscape:path-effect", value);
 
1231
    }
 
1232
}
 
1233
 
 
1234
void sp_shape_set_path_effect(SPShape *shape, LivePathEffectObject * new_lpeobj)
 
1235
{
 
1236
    const gchar * repr_id = SP_OBJECT_REPR(new_lpeobj)->attribute("id");
 
1237
    gchar *hrefstr = g_strdup_printf("#%s", repr_id);
 
1238
    sp_shape_set_path_effect(shape, hrefstr);
 
1239
    g_free(hrefstr);
 
1240
}
 
1241
 
 
1242
void sp_shape_remove_path_effect(SPShape *shape)
 
1243
{
 
1244
    Inkscape::XML::Node *repr = SP_OBJECT_REPR(shape);
 
1245
    repr->setAttribute("inkscape:path-effect", NULL);
 
1246
    if (SP_IS_PATH(shape)) {
 
1247
        repr->setAttribute("d", repr->attribute("inkscape:original-d"));
 
1248
        repr->setAttribute("inkscape:original-d", NULL);
 
1249
    }
 
1250
}
 
1251
 
 
1252
bool sp_shape_has_path_effect(SPShape *shape)
 
1253
{
 
1254
    return (shape->path_effect_href != NULL);
 
1255
}
 
1256
 
 
1257
void sp_shape_edit_next_param_oncanvas(SPShape *shape, SPDesktop *dt)
 
1258
{
 
1259
    LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);
 
1260
    if (lpeobj && lpeobj->lpe) {
 
1261
        lpeobj->lpe->editNextParamOncanvas(SP_ITEM(shape), dt);
 
1262
    }
 
1263
}
1023
1264
 
1024
1265
/*
1025
1266
  Local Variables: