X-Git-Url: https://git.tokkee.org/?a=blobdiff_plain;f=src%2Fpencil-context.cpp;h=a873eb6fcb9a84e383c68e006e1ee2040b13a7e9;hb=0dc33d4ce43e0bb49c63aa53b826ec4a1ff68e28;hp=a8c3112acd0617ce65e091d5c2d5bdf29f5bb088;hpb=f780ca188e0073ffb3ec8916c12675dd4e564f66;p=inkscape.git diff --git a/src/pencil-context.cpp b/src/pencil-context.cpp index a8c3112ac..a873eb6fc 100644 --- a/src/pencil-context.cpp +++ b/src/pencil-context.cpp @@ -41,7 +41,9 @@ #include "document.h" #include "desktop-style.h" #include "macros.h" +#include "display/sp-canvas.h" #include "display/curve.h" +#include "livarot/Path.h" static void sp_pencil_context_class_init(SPPencilContextClass *klass); static void sp_pencil_context_init(SPPencilContext *pc); @@ -234,6 +236,15 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve return TRUE; } + if (!pc->grab) { + /* Grab mouse, so release will not pass unnoticed */ + pc->grab = SP_CANVAS_ITEM(desktop->acetate); + sp_canvas_item_grab(pc->grab, ( GDK_KEY_PRESS_MASK | GDK_BUTTON_PRESS_MASK | + GDK_BUTTON_RELEASE_MASK | + GDK_POINTER_MOTION_MASK ), + NULL, bevent.time); + } + Geom::Point const button_w(bevent.x, bevent.y); /* Find desktop coordinates */ @@ -252,35 +263,35 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve break; default: /* Set first point of sequence */ - SnapManager &m = desktop->namedview->snap_manager; - m.setup(desktop); - sp_canvas_set_snap_delay_active(desktop->canvas, true); + SnapManager &m = desktop->namedview->snap_manager; if (bevent.state & GDK_CONTROL_MASK) { - if (!(bevent.state & GDK_SHIFT_MASK)) { - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); - } - spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state); - sp_canvas_set_snap_delay_active(desktop->canvas, false); - ret = true; + m.setup(desktop); + if (!(bevent.state & GDK_SHIFT_MASK)) { + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); + } + spdc_create_single_dot(event_context, p, "/tools/freehand/pencil", bevent.state); + m.unSetup(); + ret = true; break; } if (anchor) { p = anchor->dp; desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Continuing selected path")); } else { - + m.setup(desktop); if (!(bevent.state & GDK_SHIFT_MASK)) { - // This is the first click of a new curve; deselect item so that + // This is the first click of a new curve; deselect item so that // this curve is not combined with it (unless it is drawn from its // anchor, which is handled by the sibling branch above) selection->clear(); desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Creating new path")); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); } else if (selection->singleItem() && SP_IS_PATH(selection->singleItem())) { desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Appending to selected path")); - m.freeSnapReturnByRef(Inkscape::SnapPreferences::SNAPPOINT_NODE, p); + m.freeSnapReturnByRef(p, Inkscape::SNAPSOURCE_NODE_HANDLE); } + m.unSetup(); } pc->sa = anchor; spdc_set_startpoint(pc, p); @@ -296,9 +307,9 @@ pencil_handle_button_press(SPPencilContext *const pc, GdkEventButton const &beve static gint pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mevent) { - SPDesktop *const dt = pc->desktop; + SPDesktop *const dt = pc->desktop; - if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) { + if ((mevent.state & GDK_CONTROL_MASK) && (mevent.state & GDK_BUTTON1_MASK)) { // mouse was accidentally moved during Ctrl+click; // ignore the motion and create a single point pc->is_drawing = false; @@ -357,25 +368,28 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev /* We may be idle or already freehand */ if ( mevent.state & GDK_BUTTON1_MASK && pc->is_drawing ) { if (pc->state == SP_PENCIL_CONTEXT_IDLE) { - sp_canvas_set_snap_delay_active(dt->canvas, false); + sp_event_context_discard_delayed_snap_event(event_context); } - pc->state = SP_PENCIL_CONTEXT_FREEHAND; + pc->state = SP_PENCIL_CONTEXT_FREEHAND; if ( !pc->sa && !pc->green_anchor ) { /* Create green anchor */ pc->green_anchor = sp_draw_anchor_new(pc, pc->green_curve, TRUE, pc->p[0]); } - /** \todo - * fixme: I am not sure whether we want to snap to anchors - * in middle of freehand (Lauris) - */ if (anchor) { p = anchor->dp; } if ( pc->npoints != 0) { // buttonpress may have happened before we entered draw context! - spdc_add_freehand_point(pc, p, mevent.state); - ret = TRUE; + if (pc->ps.size() == 0) { + // Only in freehand mode we have to add the first point also to pc->ps (apparently) + // - We cannot add this point in spdc_set_startpoint, because we only need it for freehand + // - We cannot do this in the button press handler because at that point we don't know yet + // wheter we're going into freehand mode or not + pc->ps.push_back(pc->p[0]); + } + spdc_add_freehand_point(pc, p, mevent.state); + ret = TRUE; } if (anchor && !pc->anchor_statusbar) { @@ -397,6 +411,16 @@ pencil_handle_motion_notify(SPPencilContext *const pc, GdkEventMotion const &mev pc->anchor_statusbar = false; } } + + // Show the pre-snap indicator to communicate to the user where we would snap to if he/she were to + // a) press the mousebutton to start a freehand drawing, or + // b) release the mousebutton to finish a freehand drawing + if (!sp_event_context_knot_mouseover(pc)) { + SnapManager &m = dt->namedview->snap_manager; + m.setup(dt); + m.preSnap(Inkscape::SnapCandidatePoint(p, Inkscape::SNAPSOURCE_NODE_HANDLE)); + m.unSetup(); + } break; } return ret; @@ -427,7 +451,6 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re if (!(revent.state & GDK_CONTROL_MASK)) { // Ctrl+click creates a single point so only set context in ADDLINE mode when Ctrl isn't pressed pc->state = SP_PENCIL_CONTEXT_ADDLINE; - //sp_canvas_set_snap_delay_active(dt->canvas, true); } ret = TRUE; break; @@ -442,7 +465,7 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re spdc_set_endpoint(pc, p); spdc_finish_endpoint(pc); pc->state = SP_PENCIL_CONTEXT_IDLE; - sp_canvas_set_snap_delay_active(dt->canvas, false); + sp_event_context_discard_delayed_snap_event(event_context); ret = TRUE; break; case SP_PENCIL_CONTEXT_FREEHAND: @@ -456,13 +479,20 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re } pc->state = SP_PENCIL_CONTEXT_SKETCH; - //sp_canvas_set_snap_delay_active(dt->canvas, true); } else { /* Finish segment now */ /// \todo fixme: Clean up what follows (Lauris) if (anchor) { p = anchor->dp; + } else { + Geom::Point p_end = p; + spdc_endpoint_snap(pc, p_end, revent.state); + if (p_end != p) { + // then we must have snapped! + spdc_add_freehand_point(pc, p_end, revent.state); + } } + pc->ea = anchor; /* Write curves to object */ @@ -476,7 +506,6 @@ pencil_handle_button_release(SPPencilContext *const pc, GdkEventButton const &re pc->green_anchor = sp_draw_anchor_destroy(pc->green_anchor); } pc->state = SP_PENCIL_CONTEXT_IDLE; - // sp_canvas_set_snap_delay_active(dt->canvas, false); // reset sketch mode too pc->sketch_n = 0; } @@ -509,7 +538,7 @@ pencil_cancel (SPPencilContext *const pc) pc->is_drawing = false; pc->state = SP_PENCIL_CONTEXT_IDLE; - sp_canvas_set_snap_delay_active(pc->desktop->canvas, false); + sp_event_context_discard_delayed_snap_event(SP_EVENT_CONTEXT(pc)); pc->red_curve->reset(); sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(pc->red_bpath), NULL); @@ -600,7 +629,7 @@ pencil_handle_key_release(SPPencilContext *const pc, guint const keyval, guint c pc->green_anchor = sp_draw_anchor_destroy(pc->green_anchor); } pc->state = SP_PENCIL_CONTEXT_IDLE; - sp_canvas_set_snap_delay_active(pc->desktop->canvas, false); + sp_event_context_discard_delayed_snap_event(SP_EVENT_CONTEXT(pc)); pc->desktop->messageStack()->flash(Inkscape::NORMAL_MESSAGE, _("Finishing freehand sketch")); ret = TRUE; } @@ -710,9 +739,8 @@ square(double const x) static void interpolate(SPPencilContext *pc) { - if ( pc->ps.size() <= 1 ) { - return; + return; } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); @@ -775,7 +803,9 @@ interpolate(SPPencilContext *pc) static void sketch_interpolate(SPPencilContext *pc) { - g_assert( pc->ps.size() > 1 ); + if ( pc->ps.size() <= 1 ) { + return; + } Inkscape::Preferences *prefs = Inkscape::Preferences::get(); double const tol = prefs->getDoubleLimited("/tools/freehand/pencil/tolerance", 10.0, 1.0, 100.0) * 0.4; @@ -823,6 +853,14 @@ sketch_interpolate(SPPencilContext *pc) t = 0.5; } pc->sketch_interpolation = Geom::lerp(t, fit_pwd2, pc->sketch_interpolation); + // simplify path, to eliminate small segments + Path *path = new Path; + path->LoadPathVector(Geom::path_from_piecewise(pc->sketch_interpolation, 0.01)); + path->Simplify(0.5); + Geom::PathVector *pathv = path->MakePathVector(); + pc->sketch_interpolation = (*pathv)[0].toPwSb(); + delete path; + delete pathv; } else { pc->sketch_interpolation = fit_pwd2; } @@ -916,4 +954,4 @@ fit_and_split(SPPencilContext *pc) fill-column:99 End: */ -// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:encoding=utf-8:textwidth=99 : +// vim: filetype=cpp:expandtab:shiftwidth=4:tabstop=8:softtabstop=4:fileencoding=utf-8:textwidth=99 :