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 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