From 486b8633e480fcf8db8c562bbf5ad98bd9a4b639 Mon Sep 17 00:00:00 2001 From: John Bintz Date: Sat, 23 May 2015 16:12:17 -0400 Subject: Cache SVG DOM node order for faster touch selection. (bzr r14169.1.1) --- src/document.cpp | 77 +++++++++++++++++++++++++++++++++----------------------- 1 file changed, 45 insertions(+), 32 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 741e7c812..2b76625ff 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1335,20 +1335,11 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro } /** -Returns the topmost (in z-order) item from the descendants of group (recursively) which -is at the point p, or NULL if none. Honors into_groups on whether to recurse into -non-layer groups or not. Honors take_insensitive on whether to return insensitive -items. If upto != NULL, then if item upto is encountered (at any level), stops searching -upwards in z-order and returns what it has found so far (i.e. the found item is -guaranteed to be lower than upto). - */ -static SPItem *find_item_at_point(unsigned int dkey, SPGroup *group, Geom::Point const &p, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) +Turn the SVG DOM into a flat list of nodes that can be searched from top-down. +The list can be persisted, which improves "find at multiple points" speed. +*/ +static void build_flat_item_list(std::deque *nodes, unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) { - SPItem *seen = NULL; - SPItem *newseen = NULL; - Inkscape::Preferences *prefs = Inkscape::Preferences::get(); - gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0); - for ( SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { if (!SP_IS_ITEM(o)) { continue; @@ -1359,27 +1350,43 @@ static SPItem *find_item_at_point(unsigned int dkey, SPGroup *group, Geom::Point } if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { - // if nothing found yet, recurse into the group - newseen = find_item_at_point(dkey, SP_GROUP(o), p, into_groups, take_insensitive, upto); - if (newseen) { - seen = newseen; - newseen = NULL; - } - - if (item_is_in_group(upto, SP_GROUP(o))) { - break; - } + build_flat_item_list(nodes, dkey, SP_GROUP(o), into_groups, take_insensitive, upto); } else { SPItem *child = SP_ITEM(o); - Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey); - // seen remembers the last (topmost) of items pickable at this point - if (arenaitem && arenaitem->pick(p, delta, 1) != NULL - && (take_insensitive || child->isVisibleAndUnlocked(dkey))) { - seen = child; + if (take_insensitive || child->isVisibleAndUnlocked(dkey)) { + nodes->push_front(child); } } } +} + +/** +Returns the topmost (in z-order) item from the descendants of group (recursively) which +is at the point p, or NULL if none. Honors into_groups on whether to recurse into +non-layer groups or not. Honors take_insensitive on whether to return insensitive +items. If upto != NULL, then if item upto is encountered (at any level), stops searching +upwards in z-order and returns what it has found so far (i.e. the found item is +guaranteed to be lower than upto). Requires a list of nodes built by +build_flat_item_list. + */ +static SPItem *find_item_at_point(std::deque *nodes, unsigned int dkey, Geom::Point const &p) +{ + Inkscape::Preferences *prefs = Inkscape::Preferences::get(); + gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0); + + SPItem *seen = NULL; + SPItem *child; + for (unsigned long i = 0; i < nodes->size(); ++i) { + child = nodes->at(i); + Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey); + + if (arenaitem && arenaitem->pick(p, delta, 1) != NULL) { + seen = child; + break; + } + } + return seen; } @@ -1454,9 +1461,12 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto gdouble saved_delta = prefs->getDouble("/options/cursortolerance/value", 1.0); prefs->setDouble("/options/cursortolerance/value", 0.25); + // Cache a flattened SVG DOM to speed up selection. + std::deque nodes; + build_flat_item_list(&nodes, key, SP_GROUP(this->root), true, false, NULL); + for(int i = points.size()-1;i>=0; i--) { - SPItem *item = getItemAtPoint(key, points[i], - false, NULL); + SPItem *item = find_item_at_point(&nodes, key, points[i]); if (item && items.end()==find(items.begin(),items.end(), item)) items.push_back(item); } @@ -1472,7 +1482,11 @@ SPItem *SPDocument::getItemAtPoint( unsigned const key, Geom::Point const &p, { g_return_val_if_fail(this->priv != NULL, NULL); - return find_item_at_point(key, SP_GROUP(this->root), p, into_groups, false, upto); + // Build a flattened SVG DOM for find_item_at_point. + std::deque nodes; + build_flat_item_list(&nodes, key, SP_GROUP(this->root), into_groups, false, upto); + + return find_item_at_point(&nodes, key, p); } SPItem *SPDocument::getGroupAtPoint(unsigned int key, Geom::Point const &p) const @@ -1482,7 +1496,6 @@ SPItem *SPDocument::getGroupAtPoint(unsigned int key, Geom::Point const &p) cons return find_group_at_point(key, SP_GROUP(this->root), p); } - // Resource management bool SPDocument::addResource(gchar const *key, SPObject *object) -- cgit v1.2.3 From d75d9a6b3f33a3d901b8bc0d1d37b0f6af8d2766 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Sat, 1 Aug 2015 11:14:20 +0200 Subject: fix for 1478636 (crash on import when comments in defs) Fixed bugs: - https://launchpad.net/bugs/1478636 (bzr r14270) --- src/document.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index ebf5d312f..2ea969910 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1640,7 +1640,7 @@ void SPDocument::importDefs(SPDocument *source) prevent_id_clashes(source, this); for (std::vector::iterator defs = defsNodes.begin(); defs != defsNodes.end(); ++defs) { - importDefsNode(source, const_cast(*defs), target_defs); + importDefsNode(source, const_cast(*defs), target_defs); } } @@ -1688,11 +1688,10 @@ void SPDocument::importDefsNode(SPDocument *source, Inkscape::XML::Node *defs, I /* First pass: remove duplicates in clipboard of definitions in document */ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) { - + if(def->type() != Inkscape::XML::ELEMENT_NODE)continue; /* If this clipboard has been pasted into one document, and is now being pasted into another, or pasted again into the same, it will already have been processed. If we detect that then skip the rest of this pass. */ - Glib::ustring defid = def->attribute("id"); if( defid.find( DuplicateDefString ) != Glib::ustring::npos )break; @@ -1722,6 +1721,7 @@ void SPDocument::importDefsNode(SPDocument *source, Inkscape::XML::Node *defs, I /* Second pass: remove duplicates in clipboard of earlier definitions in clipboard */ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) { + if(def->type() != Inkscape::XML::ELEMENT_NODE)continue; Glib::ustring defid = def->attribute("id"); if( defid.find( DuplicateDefString ) != Glib::ustring::npos )continue; // this one already handled SPObject *src = source->getObjectByRepr(def); @@ -1749,6 +1749,7 @@ void SPDocument::importDefsNode(SPDocument *source, Inkscape::XML::Node *defs, I /* Final pass: copy over those parts which are not duplicates */ for (Inkscape::XML::Node *def = defs->firstChild() ; def ; def = def->next()) { + if(def->type() != Inkscape::XML::ELEMENT_NODE)continue; /* Ignore duplicate defs marked in the first pass */ Glib::ustring defid = def->attribute("id"); -- cgit v1.2.3 From ce0673e204454338fd2850d9c97ff8d113da1ef7 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 15 Sep 2015 01:49:19 +0200 Subject: Fix for 1495106 (Add a check for id before sending a modified signal) Fixed bugs: - https://launchpad.net/bugs/1495106 (bzr r14367) --- src/document.cpp | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index d6a2e1b98..54e98b3e6 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1514,7 +1514,15 @@ bool SPDocument::addResource(gchar const *key, SPObject *object) g_hash_table_insert(priv->resources, (gpointer) key, rlist); GQuark q = g_quark_from_string(key); - priv->resources_changed_signals[q].emit(); + + /*do not send signal if the object has no id (yet), + it means the object is not completely built. + (happens when pasting swatches across documents, cf bug 1495106) + [this check should be more generally presend on emit() calls since + the backtrace is unusable with crashed from this cause] + */ + if(object->getId()) + priv->resources_changed_signals[q].emit(); result = true; } -- cgit v1.2.3 From 6d6a3649cacefa158228d884058347677fc6f51f Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Sun, 20 Sep 2015 20:01:28 +0200 Subject: fix regression observed on layer dialog (bzr r14379) --- src/document.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 54e98b3e6..c64bf3ed5 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1515,13 +1515,13 @@ bool SPDocument::addResource(gchar const *key, SPObject *object) GQuark q = g_quark_from_string(key); - /*do not send signal if the object has no id (yet), + /*in general, do not send signal if the object has no id (yet), it means the object is not completely built. (happens when pasting swatches across documents, cf bug 1495106) [this check should be more generally presend on emit() calls since the backtrace is unusable with crashed from this cause] */ - if(object->getId()) + if(object->getId() || dynamic_cast(object) ) priv->resources_changed_signals[q].emit(); result = true; -- cgit v1.2.3 From 6b61296109001d15cd1e2a43c38385b5fdba81c7 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sun, 4 Oct 2015 03:31:27 +0200 Subject: Add improvements to measure tool: more responsive add option to handle only active layer or all add a option to hide/show first and last segment add a option to compute only one global sice (bzr r14393.1.1) --- src/document.cpp | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index c64bf3ed5..97113cb25 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1450,7 +1450,7 @@ std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom: return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps); } -std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points) const +std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const { std::vector items; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1464,11 +1464,25 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto // Cache a flattened SVG DOM to speed up selection. std::deque nodes; build_flat_item_list(&nodes, key, SP_GROUP(this->root), true, false, NULL); - + SPObject *current_layer = SP_ACTIVE_DESKTOP->currentLayer(); + SPDesktop *desktop = SP_ACTIVE_DESKTOP; + Inkscape::LayerModel *layer_model = NULL; + if(desktop){ + layer_model = desktop->layers; + } + size_t h = 0; for(int i = points.size()-1;i>=0; i--) { SPItem *item = find_item_at_point(&nodes, key, points[i]); if (item && items.end()==find(items.begin(),items.end(), item)) - items.push_back(item); + if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){ + items.push_back(item); + h++; + //limit 0 = no limit + if(h == limit){ + prefs->setDouble("/options/cursortolerance/value", saved_delta); + return items; + } + } } // and now we restore it back -- cgit v1.2.3 From b2f49404d1fcffc1627c76a1f053a457637de7b3 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Wed, 25 Nov 2015 02:05:31 +0100 Subject: fixes infinite loop due to buggy recursion in flattening function Fixed bugs: - https://launchpad.net/bugs/1519547 (bzr r14489) --- src/document.cpp | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 0e49f23e2..23d99d78c 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1337,20 +1337,25 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro /** Turn the SVG DOM into a flat list of nodes that can be searched from top-down. The list can be persisted, which improves "find at multiple points" speed. +Returns true if upto is reached. */ -static void build_flat_item_list(std::deque *nodes, unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) +static bool build_flat_item_list(std::deque *nodes, unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) { + bool found_upto = false; for ( SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { if (!SP_IS_ITEM(o)) { continue; } if (upto && SP_ITEM(o) == upto) { + found_upto = true; break; } if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { - build_flat_item_list(nodes, dkey, SP_GROUP(o), into_groups, take_insensitive, upto); + found_upto = build_flat_item_list(nodes, dkey, SP_GROUP(o), into_groups, take_insensitive, upto); + if (found_upto) + break; } else { SPItem *child = SP_ITEM(o); @@ -1359,6 +1364,7 @@ static void build_flat_item_list(std::deque *nodes, unsigned int dkey, } } } + return found_upto; } /** -- cgit v1.2.3 From 93650897c928bfa9ca9b737cfbff55c25271d5d3 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 8 Dec 2015 00:34:32 +0100 Subject: cppification : GHashMaps replaced by stl maps. getResouceList now gives a std::set. Should give some performance improvements (quite a few linear lookups are now logarithmic) (bzr r14504.1.6) --- src/document.cpp | 74 +++++++++++++++++++++++++++----------------------------- 1 file changed, 35 insertions(+), 39 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 23d99d78c..8c160be38 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -119,11 +119,6 @@ SPDocument::SPDocument() : p->serial = next_serial++; - p->iddef = g_hash_table_new(g_direct_hash, g_direct_equal); - p->reprdef = g_hash_table_new(g_direct_hash, g_direct_equal); - - p->resources = g_hash_table_new(g_str_hash, g_str_equal); - p->sensitive = false; p->partial = NULL; p->history_size = 0; @@ -177,17 +172,10 @@ SPDocument::~SPDocument() { root = NULL; } - if (priv->iddef) g_hash_table_destroy(priv->iddef); - if (priv->reprdef) g_hash_table_destroy(priv->reprdef); - if (rdoc) Inkscape::GC::release(rdoc); /* Free resources */ - g_hash_table_foreach_remove(priv->resources, sp_document_resource_list_free, this); - g_hash_table_destroy(priv->resources); - - delete priv; - priv = NULL; + priv->resources.clear(); } cr_cascade_unref(style_cascade); @@ -1008,11 +996,15 @@ void SPDocument::bindObjectToId(gchar const *id, SPObject *object) { GQuark idq = g_quark_from_string(id); if (object) { - g_assert(g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)) == NULL); - g_hash_table_insert(priv->iddef, GINT_TO_POINTER(idq), object); + g_assert(priv->iddef.find(id)==priv->iddef.end()); + priv->iddef[id] = object; + //g_assert(g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)) == NULL); + //g_hash_table_insert(priv->iddef, GINT_TO_POINTER(idq), object); } else { - g_assert(g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)) != NULL); - g_hash_table_remove(priv->iddef, GINT_TO_POINTER(idq)); + g_assert(priv->iddef.find(id)!=priv->iddef.end()); + priv->iddef.erase(id); + //g_assert(g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)) != NULL); + //g_hash_table_remove(priv->iddef, GINT_TO_POINTER(idq)); } SPDocumentPrivate::IDChangedSignalMap::iterator pos; @@ -1047,15 +1039,16 @@ SPObject *SPDocument::getObjectById(Glib::ustring const &id) const SPObject *SPDocument::getObjectById(gchar const *id) const { g_return_val_if_fail(id != NULL, NULL); - if (!priv || !priv->iddef) { + if (!priv || priv->iddef.empty()) { return NULL; } GQuark idq = g_quark_from_string(id); - gpointer rv = g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)); - if(rv != NULL) + std::map::iterator rv = priv->iddef.find(id); + //gpointer rv = g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)); + if(rv != priv->iddef.end()) { - return static_cast(rv); + return (rv->second); } else { @@ -1072,18 +1065,22 @@ sigc::connection SPDocument::connectIdChanged(gchar const *id, void SPDocument::bindObjectToRepr(Inkscape::XML::Node *repr, SPObject *object) { if (object) { - g_assert(g_hash_table_lookup(priv->reprdef, repr) == NULL); - g_hash_table_insert(priv->reprdef, repr, object); + g_assert(priv->reprdef.find(repr)==priv->reprdef.end()); + priv->reprdef[repr] = object; } else { - g_assert(g_hash_table_lookup(priv->reprdef, repr) != NULL); - g_hash_table_remove(priv->reprdef, repr); + g_assert(priv->reprdef.find(repr)!=priv->reprdef.end()); + priv->reprdef.erase(repr); } } SPObject *SPDocument::getObjectByRepr(Inkscape::XML::Node *repr) const { g_return_val_if_fail(repr != NULL, NULL); - return static_cast(g_hash_table_lookup(priv->reprdef, repr)); + std::map::iterator rv = priv->reprdef.find(repr); + if(rv != priv->reprdef.end()) + return (rv->second); + else + return NULL; } Glib::ustring SPDocument::getLanguage() const @@ -1528,10 +1525,9 @@ bool SPDocument::addResource(gchar const *key, SPObject *object) bool result = false; if ( !object->cloned ) { - GSList *rlist = (GSList*)g_hash_table_lookup(priv->resources, key); - g_return_val_if_fail(!g_slist_find(rlist, object), false); - rlist = g_slist_prepend(rlist, object); - g_hash_table_insert(priv->resources, (gpointer) key, rlist); + std::set rlist = priv->resources[key]; + g_return_val_if_fail(rlist.find(object) == rlist.end(), false); + rlist.insert(object); GQuark q = g_quark_from_string(key); @@ -1560,11 +1556,10 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object) bool result = false; if ( !object->cloned ) { - GSList *rlist = (GSList*)g_hash_table_lookup(priv->resources, key); - g_return_val_if_fail(rlist != NULL, false); - g_return_val_if_fail(g_slist_find(rlist, object), false); - rlist = g_slist_remove(rlist, object); - g_hash_table_insert(priv->resources, (gpointer) key, rlist); + std::set rlist = priv->resources[key]; + g_return_val_if_fail(!rlist.empty(), false); + g_return_val_if_fail(rlist.find(object) != rlist.end(), false); + rlist.erase(object); GQuark q = g_quark_from_string(key); priv->resources_changed_signals[q].emit(); @@ -1575,12 +1570,13 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object) return result; } -GSList const *SPDocument::getResourceList(gchar const *key) const +std::set const SPDocument::getResourceList(gchar const *key) const { - g_return_val_if_fail(key != NULL, NULL); - g_return_val_if_fail(*key != '\0', NULL); + std::set emptyset; + g_return_val_if_fail(key != NULL, emptyset); + g_return_val_if_fail(*key != '\0', emptyset); - return (GSList*)g_hash_table_lookup(this->priv->resources, key); + return this->priv->resources[key]; } sigc::connection SPDocument::connectResourcesChanged(gchar const *key, -- cgit v1.2.3 From 5e6d4ac718a806bff5363a1b5ff06ac8160897c3 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 8 Dec 2015 01:07:44 +0100 Subject: fix crash (oops) (bzr r14504.1.8) --- src/document.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 8c160be38..fcbe5a809 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1527,7 +1527,7 @@ bool SPDocument::addResource(gchar const *key, SPObject *object) if ( !object->cloned ) { std::set rlist = priv->resources[key]; g_return_val_if_fail(rlist.find(object) == rlist.end(), false); - rlist.insert(object); + priv->resources[key].insert(object); GQuark q = g_quark_from_string(key); @@ -1559,7 +1559,7 @@ bool SPDocument::removeResource(gchar const *key, SPObject *object) std::set rlist = priv->resources[key]; g_return_val_if_fail(!rlist.empty(), false); g_return_val_if_fail(rlist.find(object) != rlist.end(), false); - rlist.erase(object); + priv->resources[key].erase(object); GQuark q = g_quark_from_string(key); priv->resources_changed_signals[q].emit(); -- cgit v1.2.3 From cfd295134c9804bf98fba835361000a891c2fa56 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 8 Dec 2015 23:18:50 +0100 Subject: cppification: GSList replaced by vectors (undo/redo) (bzr r14504.1.14) --- src/document.cpp | 25 +++++++------------------ 1 file changed, 7 insertions(+), 18 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index fcbe5a809..05e165965 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -81,7 +81,7 @@ using Inkscape::Util::unit_table; static gint sp_document_idle_handler(gpointer data); static gint sp_document_rerouting_handler(gpointer data); -gboolean sp_document_resource_list_free(gpointer key, gpointer value, gpointer data); +//gboolean sp_document_resource_list_free(gpointer key, gpointer value, gpointer data); static gint doc_count = 0; static gint doc_mem_count = 0; @@ -105,7 +105,6 @@ SPDocument::SPDocument() : rerouting_handler_id(0), profileManager(NULL), // deferred until after other initialization router(new Avoid::Router(Avoid::PolyLineRouting|Avoid::OrthogonalRouting)), - _collection_queue(NULL), oldSignalsConnected(false), current_persp3d(NULL), current_persp3d_impl(NULL), @@ -122,8 +121,6 @@ SPDocument::SPDocument() : p->sensitive = false; p->partial = NULL; p->history_size = 0; - p->undo = NULL; - p->redo = NULL; p->seeking = false; priv = p; @@ -283,19 +280,18 @@ void SPDocument::queueForOrphanCollection(SPObject *object) { g_return_if_fail(object->document == this); sp_object_ref(object, NULL); - _collection_queue = g_slist_prepend(_collection_queue, object); + _collection_queue.push_back(object); } void SPDocument::collectOrphans() { - while (_collection_queue) { - GSList *objects=_collection_queue; - _collection_queue = NULL; - for ( GSList *iter=objects ; iter ; iter = iter->next ) { - SPObject *object=reinterpret_cast(iter->data); + while (!_collection_queue.empty()) { + std::vector objects(_collection_queue); + _collection_queue.clear(); + for (std::vector::const_iterator iter = objects.begin(); iter != objects.end(); ++iter) { + SPObject *object = *iter; object->collectOrphan(); sp_object_unref(object, NULL); } - g_slist_free(objects); } } @@ -1588,13 +1584,6 @@ sigc::connection SPDocument::connectResourcesChanged(gchar const *key, /* Helpers */ -gboolean -sp_document_resource_list_free(gpointer /*key*/, gpointer value, gpointer /*data*/) -{ - g_slist_free((GSList *) value); - return TRUE; -} - static unsigned int count_objects_recursive(SPObject *obj, unsigned int count) { count++; // obj itself -- cgit v1.2.3 From 67d50bdf148df18e790341e963bafeb50767cfb4 Mon Sep 17 00:00:00 2001 From: Kris De Gussem Date: Mon, 14 Dec 2015 21:46:00 +0100 Subject: static code analysis: suppress compiler warning (bzr r14535) --- src/document.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 05e165965..b22b99e66 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1039,7 +1039,7 @@ SPObject *SPDocument::getObjectById(gchar const *id) const return NULL; } - GQuark idq = g_quark_from_string(id); + // GQuark idq = g_quark_from_string(id); std::map::iterator rv = priv->iddef.find(id); //gpointer rv = g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)); if(rv != priv->iddef.end()) -- cgit v1.2.3 From 38f4e0e9aeb0696939475ce9450a20b281144d27 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Fri, 18 Dec 2015 23:31:07 +0100 Subject: brings back CMS tab Fixed bugs: - https://launchpad.net/bugs/1504612 (bzr r14537) --- src/document.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index b22b99e66..70fb56fe8 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -992,6 +992,8 @@ void SPDocument::bindObjectToId(gchar const *id, SPObject *object) { GQuark idq = g_quark_from_string(id); if (object) { + if(object->getId()) + priv->iddef.erase(object->getId()); g_assert(priv->iddef.find(id)==priv->iddef.end()); priv->iddef[id] = object; //g_assert(g_hash_table_lookup(priv->iddef, GINT_TO_POINTER(idq)) == NULL); -- cgit v1.2.3 From 7c5342d04a8c59714becfdf0ceb8ea1de4686736 Mon Sep 17 00:00:00 2001 From: Jabier Arraiza Cenoz Date: Sun, 7 Feb 2016 01:12:34 +0100 Subject: Fix for bug 1540518. Improved performance based on previous meassure code comment Fixed bugs: - https://launchpad.net/bugs/1540518 (bzr r14635) --- src/document.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 70fb56fe8..d4bd29386 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1262,14 +1262,14 @@ static bool overlaps(Geom::Rect const &area, Geom::Rect const &box) } static std::vector &find_items_in_area(std::vector &s, SPGroup *group, unsigned int dkey, Geom::Rect const &area, - bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false) + bool (*test)(Geom::Rect const &, Geom::Rect const &), bool take_insensitive = false, bool into_groups = false) { g_return_val_if_fail(SP_IS_GROUP(group), s); for ( SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { if ( SP_IS_ITEM(o) ) { - if (SP_IS_GROUP(o) && SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER ) { - s = find_items_in_area(s, SP_GROUP(o), dkey, area, test); + if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { + s = find_items_in_area(s, SP_GROUP(o), dkey, area, test, take_insensitive, into_groups); } else { SPItem *child = SP_ITEM(o); Geom::OptRect box = child->desktopVisualBounds(); @@ -1430,11 +1430,11 @@ static SPItem *find_group_at_point(unsigned int dkey, SPGroup *group, Geom::Poin * Assumes box is normalized (and g_asserts it!) * */ -std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box) const +std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const { std::vector x; g_return_val_if_fail(this->priv != NULL, x); - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, is_within, false, into_groups); } /* @@ -1444,11 +1444,11 @@ std::vector SPDocument::getItemsInBox(unsigned int dkey, Geom::Rect con * */ -std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box) const +std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom::Rect const &box, bool into_groups) const { std::vector x; g_return_val_if_fail(this->priv != NULL, x); - return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps); + return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, false, into_groups); } std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const -- cgit v1.2.3 From f200503cc154d84f3e4aa87400c1c045bfa80937 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Tue, 16 Feb 2016 02:42:58 +0100 Subject: Performance improvements when working in large files At each mouse move, a list of all elements in the document was computed (to get the correct cursor, in text mode for instance). This list is now cached. (bzr r14655) --- src/document.cpp | 39 ++++++++++++++++++++++++--------------- 1 file changed, 24 insertions(+), 15 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index d4bd29386..621cb071e 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -108,7 +108,8 @@ SPDocument::SPDocument() : oldSignalsConnected(false), current_persp3d(NULL), current_persp3d_impl(NULL), - _parent_document(NULL) + _parent_document(NULL), + _node_cache_valid(false) { // Penalise libavoid for choosing paths with needless extra segments. // This results in much better looking orthogonal connector paths. @@ -130,6 +131,7 @@ SPDocument::SPDocument() : // XXX only for testing! priv->undoStackObservers.add(p->console_output_undo_observer); + _node_cache = std::deque(); } SPDocument::~SPDocument() { @@ -986,6 +988,7 @@ void SPDocument::_emitModified() { static guint const flags = SP_OBJECT_MODIFIED_FLAG | SP_OBJECT_CHILD_MODIFIED_FLAG | SP_OBJECT_PARENT_MODIFIED_FLAG; root->emitModified(0); priv->modified_signal.emit(flags); + _node_cache_valid=false; } void SPDocument::bindObjectToId(gchar const *id, SPObject *object) { @@ -1334,7 +1337,7 @@ Turn the SVG DOM into a flat list of nodes that can be searched from top-down. The list can be persisted, which improves "find at multiple points" speed. Returns true if upto is reached. */ -static bool build_flat_item_list(std::deque *nodes, unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive = false, SPItem *upto = NULL) +bool SPDocument::build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive, SPItem *upto) { bool found_upto = false; for ( SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { @@ -1348,14 +1351,14 @@ static bool build_flat_item_list(std::deque *nodes, unsigned int dkey, } if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { - found_upto = build_flat_item_list(nodes, dkey, SP_GROUP(o), into_groups, take_insensitive, upto); + found_upto = build_flat_item_list(dkey, SP_GROUP(o), into_groups, take_insensitive, upto); if (found_upto) break; } else { SPItem *child = SP_ITEM(o); if (take_insensitive || child->isVisibleAndUnlocked(dkey)) { - nodes->push_front(child); + _node_cache.push_front(child); } } } @@ -1378,8 +1381,8 @@ static SPItem *find_item_at_point(std::deque *nodes, unsigned int dkey, SPItem *seen = NULL; SPItem *child; - for (unsigned long i = 0; i < nodes->size(); ++i) { - child = nodes->at(i); + for (std::deque::const_iterator i = nodes->begin(); i != nodes->end(); ++i) { + child = *i; Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey); if (arenaitem && arenaitem->pick(p, delta, 1) != NULL) { @@ -1451,7 +1454,7 @@ std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom: return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, false, into_groups); } -std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const +std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) { std::vector items; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1463,8 +1466,11 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto prefs->setDouble("/options/cursortolerance/value", 0.25); // Cache a flattened SVG DOM to speed up selection. - std::deque nodes; - build_flat_item_list(&nodes, key, SP_GROUP(this->root), true, false, NULL); + if(!_node_cache_valid){ + _node_cache.clear(); + build_flat_item_list(key, SP_GROUP(this->root), true, false, NULL); + _node_cache_valid=true; + } SPObject *current_layer = SP_ACTIVE_DESKTOP->currentLayer(); SPDesktop *desktop = SP_ACTIVE_DESKTOP; Inkscape::LayerModel *layer_model = NULL; @@ -1473,7 +1479,7 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto } size_t item_counter = 0; for(int i = points.size()-1;i>=0; i--) { - SPItem *item = find_item_at_point(&nodes, key, points[i]); + SPItem *item = find_item_at_point(&_node_cache, key, points[i]); if (item && items.end()==find(items.begin(),items.end(), item)) if(all_layers || (layer_model && layer_model->layerForObject(item) == current_layer)){ items.push_back(item); @@ -1493,15 +1499,18 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto } SPItem *SPDocument::getItemAtPoint( unsigned const key, Geom::Point const &p, - bool const into_groups, SPItem *upto) const + bool const into_groups, SPItem *upto) { g_return_val_if_fail(this->priv != NULL, NULL); // Build a flattened SVG DOM for find_item_at_point. - std::deque nodes; - build_flat_item_list(&nodes, key, SP_GROUP(this->root), into_groups, false, upto); - - return find_item_at_point(&nodes, key, p); + if(!_node_cache_valid){ + _node_cache.clear(); + build_flat_item_list(key, SP_GROUP(this->root), into_groups, false, upto); + if(!upto) + _node_cache_valid = true; + } + return find_item_at_point(&_node_cache, key, p); } SPItem *SPDocument::getGroupAtPoint(unsigned int key, Geom::Point const &p) const -- cgit v1.2.3 From 109ec952f041590ee5f42ac6e7d6bd5c212c9441 Mon Sep 17 00:00:00 2001 From: Marc Jeanmougin Date: Thu, 18 Feb 2016 00:38:22 +0100 Subject: Fixes some regressions from rev14655 Fixed bugs: - https://launchpad.net/bugs/1546531 (bzr r14658) --- src/document.cpp | 48 ++++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 22 deletions(-) (limited to 'src/document.cpp') diff --git a/src/document.cpp b/src/document.cpp index 621cb071e..ae03b1ba1 100644 --- a/src/document.cpp +++ b/src/document.cpp @@ -1335,34 +1335,24 @@ SPItem *SPDocument::getItemFromListAtPointBottom(unsigned int dkey, SPGroup *gro /** Turn the SVG DOM into a flat list of nodes that can be searched from top-down. The list can be persisted, which improves "find at multiple points" speed. -Returns true if upto is reached. */ -bool SPDocument::build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups, bool take_insensitive, SPItem *upto) +void SPDocument::build_flat_item_list(unsigned int dkey, SPGroup *group, gboolean into_groups) const { - bool found_upto = false; for ( SPObject *o = group->firstChild() ; o ; o = o->getNext() ) { if (!SP_IS_ITEM(o)) { continue; } - if (upto && SP_ITEM(o) == upto) { - found_upto = true; - break; - } - if (SP_IS_GROUP(o) && (SP_GROUP(o)->effectiveLayerMode(dkey) == SPGroup::LAYER || into_groups)) { - found_upto = build_flat_item_list(dkey, SP_GROUP(o), into_groups, take_insensitive, upto); - if (found_upto) - break; + build_flat_item_list(dkey, SP_GROUP(o), into_groups); } else { SPItem *child = SP_ITEM(o); - if (take_insensitive || child->isVisibleAndUnlocked(dkey)) { + if (child->isVisibleAndUnlocked(dkey)) { _node_cache.push_front(child); } } } - return found_upto; } /** @@ -1374,15 +1364,21 @@ upwards in z-order and returns what it has found so far (i.e. the found item is guaranteed to be lower than upto). Requires a list of nodes built by build_flat_item_list. */ -static SPItem *find_item_at_point(std::deque *nodes, unsigned int dkey, Geom::Point const &p) +static SPItem *find_item_at_point(std::deque *nodes, unsigned int dkey, Geom::Point const &p, SPItem* upto=NULL) { Inkscape::Preferences *prefs = Inkscape::Preferences::get(); gdouble delta = prefs->getDouble("/options/cursortolerance/value", 1.0); SPItem *seen = NULL; SPItem *child; + bool seen_upto = (!upto); for (std::deque::const_iterator i = nodes->begin(); i != nodes->end(); ++i) { child = *i; + if (!seen_upto){ + if(child == upto) + seen_upto = true; + continue; + } Inkscape::DrawingItem *arenaitem = child->get_arenaitem(dkey); if (arenaitem && arenaitem->pick(p, delta, 1) != NULL) { @@ -1454,7 +1450,7 @@ std::vector SPDocument::getItemsPartiallyInBox(unsigned int dkey, Geom: return find_items_in_area(x, SP_GROUP(this->root), dkey, box, overlaps, false, into_groups); } -std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) +std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vector points, bool all_layers, size_t limit) const { std::vector items; Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -1468,7 +1464,7 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto // Cache a flattened SVG DOM to speed up selection. if(!_node_cache_valid){ _node_cache.clear(); - build_flat_item_list(key, SP_GROUP(this->root), true, false, NULL); + build_flat_item_list(key, SP_GROUP(this->root), true); _node_cache_valid=true; } SPObject *current_layer = SP_ACTIVE_DESKTOP->currentLayer(); @@ -1499,18 +1495,26 @@ std::vector SPDocument::getItemsAtPoints(unsigned const key, std::vecto } SPItem *SPDocument::getItemAtPoint( unsigned const key, Geom::Point const &p, - bool const into_groups, SPItem *upto) + bool const into_groups, SPItem *upto) const { g_return_val_if_fail(this->priv != NULL, NULL); // Build a flattened SVG DOM for find_item_at_point. - if(!_node_cache_valid){ + std::deque bak(_node_cache); + if(!into_groups){ _node_cache.clear(); - build_flat_item_list(key, SP_GROUP(this->root), into_groups, false, upto); - if(!upto) - _node_cache_valid = true; + build_flat_item_list(key, SP_GROUP(this->root), into_groups); } - return find_item_at_point(&_node_cache, key, p); + if(!_node_cache_valid && into_groups){ + _node_cache.clear(); + build_flat_item_list(key, SP_GROUP(this->root), true); + _node_cache_valid=true; + } + + SPItem *res = find_item_at_point(&_node_cache, key, p, upto); + if(!into_groups) + _node_cache = bak; + return res; } SPItem *SPDocument::getGroupAtPoint(unsigned int key, Geom::Point const &p) const -- cgit v1.2.3