Code

Fix performance regressions in the node tool and a stupid crash bug
authorKrzysztof Kosiński <tweenk.pl@gmail.com>
Sat, 6 Feb 2010 21:45:14 +0000 (22:45 +0100)
committerKrzysztof Kosiński <tweenk.pl@gmail.com>
Sat, 6 Feb 2010 21:45:14 +0000 (22:45 +0100)
when deleting more than one stretch of selected nodes

src/ui/tool/control-point-selection.cpp
src/ui/tool/control-point-selection.h
src/ui/tool/control-point.cpp
src/ui/tool/event-utils.cpp
src/ui/tool/event-utils.h
src/ui/tool/multi-path-manipulator.cpp
src/ui/tool/node.cpp
src/ui/tool/path-manipulator.cpp

index de19fef8d0268d47b37aa05f4603f8f3c6f1f260..638318dbfcacf4992edff39904bafea663679573 100644 (file)
@@ -344,7 +344,7 @@ void ControlPointSelection::_updateTransformHandles(bool preserve_center)
 bool ControlPointSelection::_keyboardMove(GdkEventKey const &event, Geom::Point const &dir)
 {
     if (held_control(event)) return false;
-    unsigned num = 1 + consume_same_key_events(shortcut_key(event), 0);
+    unsigned num = 1 + combine_key_events(shortcut_key(event), 0);
 
     Geom::Point delta = dir * num; 
     if (held_shift(event)) delta *= 10;
index 025f9bb618be83927473a0e942c4f1396969ec9d..93fba56f55be5b0b24269e1f4f04a9c4be573ef2 100644 (file)
@@ -15,8 +15,6 @@
 #include <memory>
 #include <tr1/unordered_map>
 #include <tr1/unordered_set>
-#include <boost/shared_ptr.hpp>
-#include <boost/weak_ptr.hpp>
 #include <boost/optional.hpp>
 #include <sigc++/sigc++.h>
 #include <2geom/forward.h>
@@ -43,7 +41,6 @@ class ControlPointSelection : public Manipulator {
 public:
     ControlPointSelection(SPDesktop *d, SPCanvasGroup *th_group);
     ~ControlPointSelection();
-    typedef std::list<sigc::connection> connlist_type;
     typedef std::tr1::unordered_set< SelectableControlPoint * > set_type;
     typedef set_type Set; // convenience alias
 
index 06092b7d5d806356a3ea09875bb7c89b22603f1a..90d879c66d09bfd1d586164088e2d2689d11e555 100644 (file)
@@ -337,6 +337,7 @@ bool ControlPoint::_eventHandler(GdkEvent *event)
         return false;
         
     case GDK_MOTION_NOTIFY:
+        combine_motion_events(_desktop->canvas, event->motion, 0);
         if (_event_grab && !_desktop->event_context->space_panning) {
             _desktop->snapindicator->remove_snaptarget(); 
             bool transferred = false;
index 6912897da5fac457d984fbf4ff67d4440dc52dce..91b2cdb04f1f1dc92dda7d8dfd691e5dcf06f395 100644 (file)
@@ -8,8 +8,10 @@
  * Released under GNU GPL, read the file 'COPYING' for more information
  */
 
+#include <cstring>
 #include <gdk/gdk.h>
 #include <gdk/gdkkeysyms.h>
+#include "display/sp-canvas.h"
 #include "ui/tool/event-utils.h"
 
 namespace Inkscape {
@@ -28,7 +30,7 @@ guint shortcut_key(GdkEventKey const &event)
     return shortcut_key;
 }
 
-unsigned consume_same_key_events(guint keyval, gint mask)
+unsigned combine_key_events(guint keyval, gint mask)
 {
     GdkEvent *event_next;
     gint i = 0;
@@ -37,7 +39,7 @@ unsigned consume_same_key_events(guint keyval, gint mask)
     // while the next event is also a key notify with the same keyval and mask,
     while (event_next && (event_next->type == GDK_KEY_PRESS || event_next->type == GDK_KEY_RELEASE)
            && event_next->key.keyval == keyval
-           && (!mask || (event_next->key.state & mask))) {
+           && (!mask || event_next->key.state & mask)) {
         if (event_next->type == GDK_KEY_PRESS)
             i ++;
         // kill it
@@ -51,6 +53,47 @@ unsigned consume_same_key_events(guint keyval, gint mask)
     return i;
 }
 
+unsigned combine_motion_events(SPCanvas *canvas, GdkEventMotion &event, gint mask)
+{
+    GdkEvent *event_next;
+    gint i = 0;
+    event.x -= canvas->x0;
+    event.y -= canvas->y0;
+
+    event_next = gdk_event_get();
+    // while the next event is also a motion notify
+    while (event_next && event_next->type == GDK_MOTION_NOTIFY
+            && (!mask || event_next->motion.state & mask))
+    {
+        if (event_next->motion.device == event.device) {
+            GdkEventMotion &next = event_next->motion;
+            event.send_event = next.send_event;
+            event.time = next.time;
+            event.x = next.x;
+            event.y = next.y;
+            event.state = next.state;
+            event.is_hint = next.is_hint;
+            event.x_root = next.x_root;
+            event.y_root = next.y_root;
+            if (event.axes && next.axes) {
+                memcpy(event.axes, next.axes, event.device->num_axes);
+            }
+        }
+
+        // kill it
+        gdk_event_free(event_next);
+        event_next = gdk_event_get();
+        i++;
+    }
+    // otherwise, put it back onto the queue
+    if (event_next)
+        gdk_event_put(event_next);
+    event.x += canvas->x0;
+    event.y += canvas->y0;
+
+    return i;
+}
+
 /** Returns the modifier state valid after this event. Use this when you process events
  * that change the modifier state. Currently handles only Shift, Ctrl, Alt. */
 unsigned state_after_event(GdkEvent *event)
index 74907d61c49de14bb89a8dfbda7e3c4eae9e3a89..784855f56f9d24d0482b4007a14630fc8f874ea2 100644 (file)
@@ -14,6 +14,8 @@
 #include <gdk/gdk.h>
 #include <2geom/point.h>
 
+struct SPCanvas;
+
 namespace Inkscape {
 namespace UI {
 
@@ -109,7 +111,8 @@ inline bool held_button(E const &event) {
 }
 
 guint shortcut_key(GdkEventKey const &event);
-unsigned consume_same_key_events(guint keyval, gint mask);
+unsigned combine_key_events(guint keyval, gint mask);
+unsigned combine_motion_events(SPCanvas *canvas, GdkEventMotion &event, gint mask);
 unsigned state_after_event(GdkEvent *event);
 
 } // namespace UI
index c34ef066e48d448a88ce52b642e1830e9315715e..5d7b520c8d15df2611cedd7858fc92eb20a6ae98 100644 (file)
@@ -516,12 +516,15 @@ bool MultiPathManipulator::event(GdkEvent *event)
             break;
         }
         break;
+    case GDK_MOTION_NOTIFY:
+        combine_motion_events(_desktop->canvas, event->motion, 0);
+        for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
+            if (i->second->event(event)) return true;
+        }
+        break;
     default: break;
     }
 
-    for (MapType::iterator i = _mmap.begin(); i != _mmap.end(); ++i) {
-        if (i->second->event(event)) return true;
-    }
     return false;
 }
 
index 6419acf6d32e12bc842a43a9a14584035e7f7c1b..9f1e25877254214e172202eabfa5174501dac323 100644 (file)
@@ -858,7 +858,7 @@ void Node::dragged(Geom::Point &new_pos, GdkEventMotion *event)
 
         // Build the list of unselected nodes.
         typedef ControlPointSelection::Set Set;
-        Set nodes = _selection.allPoints();
+        Set &nodes = _selection.allPoints();
         for (Set::iterator i = nodes.begin(); i != nodes.end(); ++i) {
             if (!(*i)->selected()) {
                 Node *n = static_cast<Node*>(*i);
index 43955edbfa9303fd15180d78d9e7d75a918b1f80..b1a86dd7766f12059c46c38b4de8645d59ff7ee3 100644 (file)
@@ -522,7 +522,7 @@ void PathManipulator::deleteNodes(bool keep_shape)
         sel_end = sel_beg;
         
         while (num_selected > 0) {
-            while (!sel_beg->selected()) {
+            while (sel_beg && !sel_beg->selected()) {
                 sel_beg = sel_beg.next();
             }
             sel_end = sel_beg;
@@ -532,6 +532,7 @@ void PathManipulator::deleteNodes(bool keep_shape)
             }
             
             num_selected -= _deleteStretch(sel_beg, sel_end, keep_shape);
+            sel_beg = sel_end;
         }
         ++i;
     }
@@ -1294,11 +1295,12 @@ void PathManipulator::_commit(Glib::ustring const &annotation)
 void PathManipulator::_updateDragPoint(Geom::Point const &evp)
 {
     // TODO find a way to make this faster (no transform required)
-    Geom::PathVector pv = _spcurve->get_pathvector() * (_edit_transform * _i2d_transform);
+    Geom::Matrix to_desktop = _edit_transform * _i2d_transform;
+    Geom::PathVector pv = _spcurve->get_pathvector();
     boost::optional<Geom::PathVectorPosition> pvp
-        = Geom::nearestPoint(pv, _desktop->w2d(evp));
+        = Geom::nearestPoint(pv, _desktop->w2d(evp) * to_desktop.inverse());
     if (!pvp) return;
-    Geom::Point nearest_point = _desktop->d2w(pv.at(pvp->path_nr).pointAt(pvp->t));
+    Geom::Point nearest_point = _desktop->d2w(pv.at(pvp->path_nr).pointAt(pvp->t) * to_desktop);
     
     double fracpart;
     std::list<SubpathPtr>::iterator spi = _subpaths.begin();