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