45
58
static void sp_shape_build (SPObject * object, SPDocument * document, Inkscape::XML::Node * repr);
46
59
static void sp_shape_release (SPObject *object);
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);
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);
89
107
sp_shape_class_init (SPShapeClass *klass)
91
GObjectClass *gobject_class;
109
GObjectClass *gobject_class;
92
110
SPObjectClass *sp_object_class;
93
111
SPItemClass * item_class;
94
112
SPPathClass * path_class;
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;
101
119
parent_class = (SPItemClass *)g_type_class_peek_parent (klass);
103
gobject_class->finalize = sp_shape_finalize;
121
gobject_class->finalize = sp_shape_finalize;
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;
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;
136
klass->set_shape = NULL;
137
klass->update_patheffect = NULL;
147
174
* Virtual build callback for SPMarker.
149
* This is to be invoked immediately after creation of an SPShape. This is
176
* This is to be invoked immediately after creation of an SPShape.
152
178
* \see sp_object_build()
155
181
sp_shape_build (SPObject *object, SPDocument *document, Inkscape::XML::Node *repr)
157
if (((SPObjectClass *) (parent_class))->build) {
158
(*((SPObjectClass *) (parent_class))->build) (object, document, repr);
183
SP_SHAPE(object)->path_effect_ref->changedSignal().connect(sigc::bind(sigc::ptr_fun(lpeobject_ref_changed), SP_SHAPE(object)));
185
sp_object_read_attr(object, "inkscape:path-effect");
187
if (((SPObjectClass *) (parent_class))->build) {
188
(*((SPObjectClass *) (parent_class))->build) (object, document, repr);
193
223
shape->curve = sp_curve_unref (shape->curve);
226
if (shape->path_effect_href) {
227
g_free(shape->path_effect_href);
229
shape->path_effect_ref->detach();
231
shape->lpe_modified_connection.disconnect();
232
shape->lpe_modified_connection.~connection();
196
234
if (((SPObjectClass *) parent_class)->release) {
197
235
((SPObjectClass *) parent_class)->release (object);
242
sp_shape_set(SPObject *object, unsigned int key, gchar const *value)
244
SPShape *shape = (SPShape *) object;
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. */
251
if (shape->path_effect_href) {
252
g_free(shape->path_effect_href);
253
shape->path_effect_href = NULL;
256
shape->path_effect_href = g_strdup(value);
258
// Now do the attaching, which emits the changed signal.
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();
266
// Detach, which emits the changed signal.
267
shape->path_effect_ref->detach();
272
if (((SPObjectClass *) parent_class)->set) {
273
((SPObjectClass *) parent_class)->set(object, key, value);
279
static Inkscape::XML::Node *
280
sp_shape_write(SPObject *object, Inkscape::XML::Node *repr, guint flags)
282
SPShape *shape = (SPShape *) object;
284
if ( shape->path_effect_href ) {
285
repr->setAttribute("inkscape:path-effect", shape->path_effect_href);
287
repr->setAttribute("inkscape:path-effect", NULL);
290
if (((SPObjectClass *)(parent_class))->write) {
291
((SPObjectClass *)(parent_class))->write(object, repr, flags);
202
298
* Updates the shape when its attributes have changed. Also establishes
203
299
* marker objects to match the style settings.
617
715
nr_path_matrix_bbox_union(&bp, transform, &cbbox);
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 ) {
717
if ((SPItem::BBoxType) flags != SPItem::GEOMETRIC_BBOX) {
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 ) {
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)) {
639
SPMarker* marker = SP_MARKER (shape->marker[m]);
640
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
642
NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
644
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
645
tr = NR::scale(style->stroke_width.computed) * tr;
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)) {
739
SPMarker* marker = SP_MARKER (shape->marker[m]);
740
SPItem* marker_item = sp_item_first_item_child (SP_OBJECT (shape->marker[m]));
742
NR::Matrix tr(sp_shape_marker_get_transform(shape, bp));
744
if (marker->markerUnits == SP_MARKER_UNITS_STROKEWIDTH) {
745
tr = NR::scale(style->stroke_width.computed) * tr;
748
// total marker transform
749
tr = marker_item->transform * marker->c2p * tr * transform;
751
// get bbox of the marker with that transform
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);
648
// total marker transform
649
tr = marker_item->transform * marker->c2p * tr * transform;
651
// get bbox of the marker with that transform
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);
698
799
SPStyle* style = SP_OBJECT_STYLE (item);
700
if (style->fill.type != SP_PAINT_TYPE_NONE) {
801
if (!style->fill.isNone()) {
702
803
bp.path = SP_CURVE_BPATH(shape->curve);
703
804
sp_print_fill (ctx, &bp, i2d, style, &pbox, &dbox, &bbox);
706
if (style->stroke.type != SP_PAINT_TYPE_NONE) {
807
if (!style->stroke.isNone()) {
708
809
bp.path = SP_CURVE_BPATH(shape->curve);
709
810
sp_print_stroke (ctx, &bp, i2d, style, &pbox, &dbox, &bbox);
1009
1112
if (shape->curve == NULL) {
1013
1116
NR::Matrix const i2d (sp_item_i2d_affine (item));
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;
1117
NArtBpath const *b = SP_CURVE_BPATH(shape->curve);
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
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
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
1140
*p = pos; // only return non-smooth nodes ("cusps")
1150
LivePathEffectObject *
1151
sp_shape_get_livepatheffectobject(SPShape *shape) {
1152
if (!shape) return NULL;
1154
if (sp_shape_has_path_effect(shape)) {
1155
return shape->path_effect_ref->lpeobject;
1161
Inkscape::LivePathEffect::Effect *
1162
sp_shape_get_livepatheffect(SPShape *shape) {
1163
if (!shape) return NULL;
1165
LivePathEffectObject * lpeobj = sp_shape_get_livepatheffectobject(shape);
1173
* Calls any registered handlers for the update_patheffect action
1176
sp_shape_update_patheffect (SPShape *shape, bool write)
1178
#ifdef SHAPE_VERBOSE
1179
g_message("sp_shape_update_patheffect: %p\n", shape);
1181
g_return_if_fail (shape != NULL);
1182
g_return_if_fail (SP_IS_SHAPE (shape));
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);
1189
void sp_shape_perform_path_effect(SPCurve *curve, SPShape *shape) {
1193
LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);
1194
if (lpeobj && lpeobj->lpe) {
1195
lpeobj->lpe->doEffect(curve);
1200
* Gets called when (re)attached to another lpeobject.
1203
lpeobject_ref_changed(SPObject *old_ref, SPObject *ref, SPShape *shape)
1206
sp_signal_disconnect_by_data(old_ref, shape);
1208
if ( IS_LIVEPATHEFFECT(ref) && ref != shape )
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);
1217
* Gets called when lpeobject repr contents change: i.e. parameter change.
1220
lpeobject_ref_modified(SPObject */*href*/, guint /*flags*/, SPShape *shape)
1222
sp_shape_update_patheffect (shape, true);
1225
void sp_shape_set_path_effect(SPShape *shape, gchar *value)
1228
sp_shape_remove_path_effect(shape);
1230
SP_OBJECT_REPR(shape)->setAttribute("inkscape:path-effect", value);
1234
void sp_shape_set_path_effect(SPShape *shape, LivePathEffectObject * new_lpeobj)
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);
1242
void sp_shape_remove_path_effect(SPShape *shape)
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);
1252
bool sp_shape_has_path_effect(SPShape *shape)
1254
return (shape->path_effect_href != NULL);
1257
void sp_shape_edit_next_param_oncanvas(SPShape *shape, SPDesktop *dt)
1259
LivePathEffectObject *lpeobj = sp_shape_get_livepatheffectobject(shape);
1260
if (lpeobj && lpeobj->lpe) {
1261
lpeobj->lpe->editNextParamOncanvas(SP_ITEM(shape), dt);
1025
1266
Local Variables: