Code

noop: rename function name and whitespace
[inkscape.git] / src / pencil-context.cpp
index 3d397b1800e580b5cc86f38ae2e3c4815eb53862..397a5a0ffb0d7cb52f3f6c51b58424c782c5d762 100644 (file)
@@ -41,6 +41,7 @@
 #include "document.h"
 #include "desktop-style.h"
 #include "macros.h"
+#include "display/curve.h"
 
 static void sp_pencil_context_class_init(SPPencilContextClass *klass);
 static void sp_pencil_context_init(SPPencilContext *pc);
@@ -61,6 +62,8 @@ static void fit_and_split(SPPencilContext *pc);
 
 
 static SPDrawContextClass *pencil_parent_class;
+static NR::Point pencil_drag_origin_w(0, 0);
+static bool pencil_within_tolerance = false;
 
 /**
  * Register SPPencilContext class with Gdk and return its type number.
@@ -221,6 +224,9 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
         /* Test whether we hit any anchor. */
         SPDrawAnchor *anchor = spdc_test_inside(pc, button_w);
 
+        pencil_drag_origin_w = NR::Point(bevent.x,bevent.y);
+        pencil_within_tolerance = true;
+
         switch (pc->state) {
             case SP_PENCIL_CONTEXT_ADDLINE:
                 /* Current segment will be finished with release */
@@ -247,7 +253,7 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path"));
                         SnapManager &m = desktop->namedview->snap_manager;
                         m.setup(desktop);
-                        p = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p).getPoint();
+                        m.freeSnapReturnByRef(Inkscape::Snapper::SNAPPOINT_NODE, p);
                     } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) {
                         desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path"));
                     }
@@ -296,6 +302,19 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
     /* Test whether we hit any anchor. */
     SPDrawAnchor *anchor = spdc_test_inside(pc, NR::Point(mevent.x, mevent.y));
 
+    if (pencil_within_tolerance) {
+        gint const tolerance = prefs_get_int_attribute_limited("options.dragtolerance",
+                                                               "value", 0, 0, 100);
+        if ( NR::LInfty( NR::Point(mevent.x,mevent.y) - pencil_drag_origin_w ) < tolerance ) {
+            return FALSE;   // Do not drag if we're within tolerance from origin.
+        }
+    }
+
+    // Once the user has moved farther than tolerance from the original location
+    // (indicating they intend to move the object, not click), then always process the
+    // motion notify coordinates as given (no snapping back to origin)
+    pencil_within_tolerance = false;
+
     switch (pc->state) {
         case SP_PENCIL_CONTEXT_ADDLINE:
             /* Set red endpoint */
@@ -324,8 +343,7 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev
                 } else if ((mevent.state & GDK_SHIFT_MASK) == 0) {
                     SnapManager &m = dt->namedview->snap_manager;
                     m.setup(dt, NULL);
-                    Inkscape::SnappedPoint const s = m.freeSnap(Inkscape::Snapper::SNAPPOINT_NODE, p);
-                    p = s.getPoint();
+                    m.freeSnapReturnByRef(Inkscape::Snapper::SNAPPOINT_NODE, p);
                 }
                 if ( pc->npoints != 0 ) { // buttonpress may have happened before we entered draw context!
                     spdc_add_freehand_point(pc, p, mevent.state);
@@ -445,13 +463,13 @@ pencil_cancel (SPPencilContext *const pc)
 
     pc->state = SP_PENCIL_CONTEXT_IDLE;
 
-    sp_curve_reset(pc->red_curve);
+    pc->red_curve->reset();
     sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL);
     while (pc->green_bpaths) {
         gtk_object_destroy(GTK_OBJECT(pc->green_bpaths->data));
         pc->green_bpaths = g_slist_remove(pc->green_bpaths, pc->green_bpaths->data);
     }
-    sp_curve_reset(pc->green_curve);
+    pc->green_curve->reset();
     if (pc->green_anchor) {
         pc->green_anchor = sp_draw_anchor_destroy(pc->green_anchor);
     }
@@ -543,7 +561,7 @@ spdc_set_endpoint(SPPencilContext *const pc, NR::Point const p)
     }
     g_return_if_fail( pc->npoints > 0 );
 
-    sp_curve_reset(pc->red_curve);
+    pc->red_curve->reset();
     if ( ( p == pc->p[0] )
          || !in_svg_plane(p) )
     {
@@ -552,8 +570,8 @@ spdc_set_endpoint(SPPencilContext *const pc, NR::Point const p)
         pc->p[1] = p;
         pc->npoints = 2;
 
-        sp_curve_moveto(pc->red_curve, pc->p[0]);
-        sp_curve_lineto(pc->red_curve, pc->p[1]);
+        pc->red_curve->moveto(pc->p[0]);
+        pc->red_curve->lineto(pc->p[1]);
         pc->red_curve_is_valid = true;
 
         sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), pc->red_curve);
@@ -570,11 +588,10 @@ spdc_set_endpoint(SPPencilContext *const pc, NR::Point const p)
 static void
 spdc_finish_endpoint(SPPencilContext *const pc)
 {
-    if ( ( SP_CURVE_LENGTH(pc->red_curve) != 2 )
-         || ( SP_CURVE_SEGMENT(pc->red_curve, 0)->c(3) ==
-              SP_CURVE_SEGMENT(pc->red_curve, 1)->c(3)   ) )
+    if ( ( pc->red_curve->is_empty() )
+         || ( pc->red_curve->first_point() == pc->red_curve->second_point()   ) )
     {
-        sp_curve_reset(pc->red_curve);
+        pc->red_curve->reset();
         sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL);
     } else {
         /* Write curves to object. */
@@ -609,9 +626,9 @@ fit_and_split(SPPencilContext *pc)
 {
     g_assert( pc->npoints > 1 );
 
-    double const tolerance_sq = square( NR::expansion(pc->desktop->w2d())
-                                        * prefs_get_double_attribute_limited("tools.freehand.pencil",
-                                                                             "tolerance", 10.0, 1.0, 100.0) );
+    double const tol = prefs_get_double_attribute_limited("tools.freehand.pencil",                                                                             "tolerance", 10.0, 1.0, 100.0);
+    double const tolerance_sq = 0.02 * square( NR::expansion(pc->desktop->w2d()) * tol) 
+        * exp(0.2*tol - 2);
 
     NR::Point b[4];
     g_assert(is_zero(pc->req_tangent)
@@ -623,35 +640,34 @@ fit_and_split(SPPencilContext *pc)
          && unsigned(pc->npoints) < G_N_ELEMENTS(pc->p) )
     {
         /* Fit and draw and reset state */
-        sp_curve_reset(pc->red_curve);
-        sp_curve_moveto(pc->red_curve, b[0]);
-        sp_curve_curveto(pc->red_curve, b[1], b[2], b[3]);
+        pc->red_curve->reset();
+        pc->red_curve->moveto(b[0]);
+        pc->red_curve->curveto(b[1], b[2], b[3]);
         sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), pc->red_curve);
         pc->red_curve_is_valid = true;
     } else {
         /* Fit and draw and copy last point */
 
-        g_assert(!sp_curve_empty(pc->red_curve));
+        g_assert(!pc->red_curve->is_empty());
 
         /* Set up direction of next curve. */
         {
-            NArtBpath const &last_seg = *sp_curve_last_bpath(pc->red_curve);
-            pc->p[0] = last_seg.c(3);
+            Geom::CubicBezier const * last_seg = dynamic_cast<Geom::CubicBezier const *>(pc->red_curve->last_segment());
+            g_assert( last_seg );      // Relevance: validity of (*last_seg)[2]
+            pc->p[0] = last_seg->finalPoint();
             pc->npoints = 1;
-            g_assert( last_seg.code == NR_CURVETO );
-            /* Relevance: validity of last_seg.c(2). */
-            NR::Point const req_vec( pc->p[0] - last_seg.c(2) );
+            NR::Point const req_vec( pc->p[0] - (*last_seg)[2] );
             pc->req_tangent = ( ( NR::is_zero(req_vec) || !in_svg_plane(req_vec) )
                                 ? NR::Point(0, 0)
                                 : NR::unit_vector(req_vec) );
         }
 
-        sp_curve_append_continuous(pc->green_curve, pc->red_curve, 0.0625);
-        SPCurve *curve = sp_curve_copy(pc->red_curve);
+        pc->green_curve->append_continuous(pc->red_curve, 0.0625);
+        SPCurve *curve = pc->red_curve->copy();
 
         /// \todo fixme:
         SPCanvasItem *cshape = sp_canvas_bpath_new(sp_desktop_sketch(pc->desktop), curve);
-        sp_curve_unref(curve);
+        curve->unref();
         sp_canvas_bpath_set_stroke(SP_CANVAS_BPATH(cshape), pc->green_color, 1.0, SP_STROKE_LINEJOIN_MITER, SP_STROKE_LINECAP_BUTT);
 
         pc->green_bpaths = g_slist_prepend(pc->green_bpaths, cshape);