index 8cab1690b5778ff48c3c9be53f4e29b1ebe50478..bb8e690923e66402bdabd7f5e71914e3267ff809 100644 (file)
#include "desktop.h"
#include "desktop-events.h"
#include "desktop-handles.h"
-#include "desktop-affine.h"
#include "desktop-style.h"
#include "message-context.h"
#include "preferences.h"
static gint sp_dyna_draw_context_root_handler(SPEventContext *ec, GdkEvent *event);
static void clear_current(SPDynaDrawContext *dc);
-static void set_to_accumulated(SPDynaDrawContext *dc, bool unionize);
+static void set_to_accumulated(SPDynaDrawContext *dc, bool unionize, bool subtract);
static void add_cap(SPCurve *curve, Geom::Point const &from, Geom::Point const &to, double rounding);
static bool accumulate_calligraphic(SPDynaDrawContext *dc);
// If force is below the absolute threshold DYNA_EPSILON,
// or we haven't yet reached DYNA_VEL_START (i.e. at the beginning of stroke)
// _and_ the force is below the (higher) DYNA_EPSILON_START threshold,
- // discard this move.
+ // discard this move.
// This prevents flips, blobs, and jerks caused by microscopic tremor of the tablet pen,
// especially bothersome at the start of the stroke where we don't yet have the inertia to
// smooth them out.
// get the real brush point, not the same as pointer (affected by hatch tracking and/or mass
// drag)
Geom::Point brush = sp_dyna_draw_get_vpoint(dc, dc->cur);
- Geom::Point brush_w = SP_EVENT_CONTEXT(dc)->desktop->d2w(brush);
+ Geom::Point brush_w = SP_EVENT_CONTEXT(dc)->desktop->d2w(brush);
double trace_thick = 1;
if (dc->trace_bg) {
} else {
dc->_message_context->set(Inkscape::NORMAL_MESSAGE, _("<b>Select a guide path</b> to track with <b>Ctrl</b>"));
}
- }
+ }
if ( dc->is_drawing && (event->motion.state & GDK_BUTTON1_MASK) && !event_context->space_panning) {
dc->dragging = TRUE;
if (event->motion.state & GDK_CONTROL_MASK && dc->hatch_item) { // hatching
#define HATCH_VECTOR_ELEMENTS 12
-#define INERTIA_ELEMENTS 36
+#define INERTIA_ELEMENTS 24
#define SPEED_ELEMENTS 12
#define SPEED_MIN 0.3
-#define SPEED_NORMAL 0.3
+#define SPEED_NORMAL 0.35
+#define INERTIA_FORCE 0.5
// speed is the movement of the nearest point along the guide path, divided by
// the movement of the pointer at the same period; it is averaged for the last
if (dot > 0) { // mouse is still moving in approx the same direction
Geom::Point should_have_moved =
(inertia) * (1/Geom::L2(inertia)) * Geom::L2(moved_past_escape);
- motion_dt = dc->inertia_vectors.front() + should_have_moved;
+ motion_dt = dc->inertia_vectors.front() +
+ (INERTIA_FORCE * should_have_moved + (1 - INERTIA_FORCE) * moved_past_escape);
}
}
} else {
// looks like we're starting to lose speed,
// so _gradually_ let go attraction to prevent jerks
- target = (dc->hatch_spacing * speed + hatch_dist * (SPEED_NORMAL - speed))/SPEED_NORMAL;
+ target = (dc->hatch_spacing * speed + hatch_dist * (SPEED_NORMAL - speed))/SPEED_NORMAL;
}
if (!IS_NAN(dot) && dot < -0.5) {// flip
target = -target;
}
} else {
- // this is the first motion event, set the dist
+ // this is the first motion event, set the dist
dc->hatch_spacing = hatch_dist;
}
}
// Draw the hatching circle if necessary
- if (event->motion.state & GDK_CONTROL_MASK) {
- if (dc->hatch_spacing == 0 && hatch_dist != 0) {
+ if (event->motion.state & GDK_CONTROL_MASK) {
+ if (dc->hatch_spacing == 0 && hatch_dist != 0) {
// Haven't set spacing yet: gray, center free, update radius live
Geom::Point c = desktop->w2d(motion_w);
Geom::Matrix const sm (Geom::Scale(hatch_dist, hatch_dist) * Geom::Translate(c));
/* Create object */
fit_and_split(dc, TRUE);
if (accumulate_calligraphic(dc))
- set_to_accumulated(dc, event->button.state & GDK_SHIFT_MASK); // performs document_done
+ set_to_accumulated(dc, event->button.state & GDK_SHIFT_MASK, event->button.state & GDK_MOD1_MASK); // performs document_done
else
g_warning ("Failed to create path: invalid data in dc->cal1 or dc->cal2");
dc->hatch_livarot_path = NULL;
dc->just_started_drawing = false;
- if (dc->hatch_spacing != 0 && !dc->keep_selected) {
+ if (dc->hatch_spacing != 0 && !dc->keep_selected) {
// we do not select the newly drawn path, so increase spacing by step
if (dc->hatch_spacing_step == 0) {
dc->hatch_spacing_step = dc->hatch_spacing;
}
static void
-set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
+set_to_accumulated(SPDynaDrawContext *dc, bool unionize, bool subtract)
{
SPDesktop *desktop = SP_EVENT_CONTEXT(dc)->desktop;
item->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
item->updateRepr();
}
- Geom::PathVector pathv = dc->accumulated->get_pathvector() * sp_desktop_dt2doc_affine(desktop);
+ Geom::PathVector pathv = dc->accumulated->get_pathvector() * desktop->dt2doc();
gchar *str = sp_svg_write_path(pathv);
g_assert( str != NULL );
dc->repr->setAttribute("d", str);
if (unionize) {
sp_desktop_selection(desktop)->add(dc->repr);
sp_selected_path_union_skip_undo(desktop);
+ } else if (subtract) {
+ sp_desktop_selection(desktop)->add(dc->repr);
+ sp_selected_path_diff_skip_undo(desktop);
} else {
if (dc->keep_selected) {
sp_desktop_selection(desktop)->set(dc->repr);
- }
+ }
}
} else {
dc->repr = NULL;
}
- sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC,
+ sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC,
_("Draw calligraphic stroke"));
}
static void
add_cap(SPCurve *curve,
Geom::Point const &from,
- Geom::Point const &to,
+ Geom::Point const &to,
double rounding)
{
if (Geom::L2( to - from ) > DYNA_EPSILON) {
dc->cal1->is_empty() ||
dc->cal2->is_empty() ||
(dc->cal1->get_segment_count() <= 0) ||
- dc->cal1->first_path()->closed()
+ dc->cal1->first_path()->closed()
) {
dc->cal1->reset();
dc->cal2->reset();
SPCurve *rev_cal2 = dc->cal2->create_reverse();
if (
(rev_cal2->get_segment_count() <= 0) ||
- rev_cal2->first_path()->closed()
+ rev_cal2->first_path()->closed()
) {
rev_cal2->unref();
dc->cal1->reset();
!dc_cal1_firstseg ||
!rev_cal2_firstseg ||
!dc_cal1_lastseg ||
- !rev_cal2_lastseg
+ !rev_cal2_lastseg
) {
rev_cal2->unref();
dc->cal1->reset();