diff --git a/src/sp-pattern.cpp b/src/sp-pattern.cpp
index 96ff50cda909f02ae1cfe2592dc51de8385cf0e7..ec0d0d576c8b78cffd56631fc5850179eecfab86 100644 (file)
--- a/src/sp-pattern.cpp
+++ b/src/sp-pattern.cpp
Geom::Matrix pa2ca;
NRRectL cached_bbox;
NRPixBlock cached_tile;
Geom::Matrix pa2ca;
NRRectL cached_bbox;
NRPixBlock cached_tile;
+
+ std::map<SPObject *, sigc::connection> *_release_connections;
};
static void sp_pattern_class_init (SPPatternClass *klass);
};
static void sp_pattern_class_init (SPPatternClass *klass);
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_PATTERNTRANSFORM: {
object->requestModified(SP_OBJECT_MODIFIED_FLAG);
break;
case SP_ATTR_PATTERNTRANSFORM: {
- NR::Matrix t;
+ Geom::Matrix t;
if (value && sp_svg_transform_read (value, &t)) {
pat->patternTransform = t;
pat->patternTransform_set = TRUE;
if (value && sp_svg_transform_read (value, &t)) {
pat->patternTransform = t;
pat->patternTransform_set = TRUE;
{
if (SP_IS_OBJECT (pattern))
SP_OBJECT (pattern)->requestModified(SP_OBJECT_MODIFIED_FLAG);
{
if (SP_IS_OBJECT (pattern))
SP_OBJECT (pattern)->requestModified(SP_OBJECT_MODIFIED_FLAG);
+ /* Conditional to avoid causing infinite loop if there's a cycle in the href chain. */
}
guint
}
guint
@@ -521,7 +524,7 @@ pattern_tile (GSList *reprs, Geom::Rect bounds, SPDocument *document, Geom::Matr
dup_transform = Geom::identity();
dup_transform *= move;
dup_transform = Geom::identity();
dup_transform *= move;
- sp_item_write_transform(copy, SP_OBJECT_REPR(copy), dup_transform);
+ sp_item_write_transform(copy, SP_OBJECT_REPR(copy), dup_transform, NULL, false);
}
Inkscape::GC::release(repr);
}
Inkscape::GC::release(repr);
static void sp_pat_fill (SPPainter *painter, NRPixBlock *pb);
static void sp_pat_fill (SPPainter *painter, NRPixBlock *pb);
+// item in this pattern is about to be deleted, hide it on our arena and disconnect
+void
+sp_pattern_painter_release (SPObject *obj, SPPatPainter *painter)
+{
+ std::map<SPObject *, sigc::connection>::iterator iter = painter->_release_connections->find(obj);
+ if (iter != painter->_release_connections->end()) {
+ iter->second.disconnect();
+ painter->_release_connections->erase(obj);
+ }
+
+ sp_item_invoke_hide(SP_ITEM(obj), painter->dkey);
+}
+
/**
Creates a painter (i.e. the thing that does actual filling at the given zoom).
See (*) below for why the parent_transform may be necessary.
/**
Creates a painter (i.e. the thing that does actual filling at the given zoom).
See (*) below for why the parent_transform may be necessary.
@@ -717,13 +733,19 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G
pp->root = NRArenaGroup::create(pp->arena);
/* Show items */
pp->root = NRArenaGroup::create(pp->arena);
/* Show items */
+ pp->_release_connections = new std::map<SPObject *, sigc::connection>;
for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
if (SP_IS_ITEM (child)) {
for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
if (SP_IS_ITEM (child)) {
+ // for each item in pattern,
NRArenaItem *cai;
NRArenaItem *cai;
+ // show it on our arena,
cai = sp_item_invoke_show (SP_ITEM (child), pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS);
cai = sp_item_invoke_show (SP_ITEM (child), pp->arena, pp->dkey, SP_ITEM_REFERENCE_FLAGS);
+ // add to the group,
nr_arena_item_append_child (pp->root, cai);
nr_arena_item_append_child (pp->root, cai);
+ // and connect to the release signal in case the item gets deleted
+ pp->_release_connections->insert(std::make_pair(child, child->connectRelease(sigc::bind<1>(sigc::ptr_fun(&sp_pattern_painter_release), pp))));
}
}
break; // do not go further up the chain if children are found
}
}
break; // do not go further up the chain if children are found
@@ -787,22 +809,25 @@ sp_pattern_painter_new (SPPaintServer *ps, Geom::Matrix const &full_transform, G
return (SPPainter *) pp;
}
return (SPPainter *) pp;
}
+
static void
sp_pattern_painter_free (SPPaintServer */*ps*/, SPPainter *painter)
{
SPPatPainter *pp = (SPPatPainter *) painter;
static void
sp_pattern_painter_free (SPPaintServer */*ps*/, SPPainter *painter)
{
SPPatPainter *pp = (SPPatPainter *) painter;
- SPPattern *pat = pp->pat;
+ // free our arena
+ if (pp->arena) {
+ ((NRObject *) pp->arena)->unreference();
+ pp->arena = NULL;
+ }
- for (SPPattern *pat_i = pat; pat_i != NULL; pat_i = pat_i->ref ? pat_i->ref->getObject() : NULL) {
- if (pat_i && SP_IS_OBJECT (pat_i) && pattern_hasItemChildren(pat_i)) { // find the first one with item children
- for (SPObject *child = sp_object_first_child(SP_OBJECT(pat_i)) ; child != NULL; child = SP_OBJECT_NEXT(child) ) {
- if (SP_IS_ITEM (child)) {
- sp_item_invoke_hide (SP_ITEM (child), pp->dkey);
- }
- }
- break; // do not go further up the chain if children are found
- }
+ // disconnect all connections
+ std::map<SPObject *, sigc::connection>::iterator iter;
+ for (iter = pp->_release_connections->begin() ; iter!=pp->_release_connections->end() ; iter++) {
+ iter->second.disconnect();
}
}
+ pp->_release_connections->clear();
+ delete pp->_release_connections;
+
if ( pp->use_cached_tile ) nr_pixblock_release(&pp->cached_tile);
g_free (pp);
}
if ( pp->use_cached_tile ) nr_pixblock_release(&pp->cached_tile);
g_free (pp);
}
nr_pixblock_release (&ppb);
}
}
nr_pixblock_release (&ppb);
}
}
- }
+ }
}
}
}
}