Code

Merge and cleanup of GSoC C++-ification project.
[inkscape.git] / src / dyna-draw-context.cpp
index 8cab1690b5778ff48c3c9be53f4e29b1ebe50478..93d4262cd172512dbfe53d9fe6befc064f398009 100644 (file)
@@ -1,5 +1,3 @@
-#define __SP_DYNA_DRAW_CONTEXT_C__
-
 /*
  * Handwriting-like drawing mode
  *
@@ -8,6 +6,7 @@
  *   Lauris Kaplinski <lauris@kaplinski.com>
  *   bulia byak <buliabyak@users.sf.net>
  *   MenTaLguY <mental@rydia.net>
+ *   Abhishek Sharma
  *
  * The original dynadraw code:
  *   Paul Haeberli <paul@sgi.com>
@@ -45,7 +44,6 @@
 #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"
@@ -66,6 +64,8 @@
 
 #include "dyna-draw-context.h"
 
+using Inkscape::DocumentUndo;
+
 #define DDC_RED_RGBA 0xff0000ff
 
 #define TOLERANCE_CALLIGRAPHIC 0.1
@@ -85,7 +85,7 @@ static void sp_dyna_draw_context_set(SPEventContext *ec, Inkscape::Preferences::
 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);
 
@@ -335,7 +335,7 @@ sp_dyna_draw_apply(SPDynaDrawContext *dc, Geom::Point p)
     // 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.
@@ -433,7 +433,7 @@ sp_dyna_draw_brush(SPDynaDrawContext *dc)
     // 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) {
@@ -600,7 +600,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                     }
 
                     // calculate pointer point in the guide item's coords
-                    motion_to_curve = sp_item_dt2i_affine(selected) * sp_item_i2doc_affine(selected);
+                    motion_to_curve = selected->dt2i_affine() * selected->i2doc_affine();
                     pointer = motion_dt * motion_to_curve;
 
                     // calculate the nearest point on the guide path
@@ -617,7 +617,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                 } 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;
@@ -625,10 +625,11 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                 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
@@ -690,7 +691,8 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                             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);
                             }
                         }
 
@@ -712,7 +714,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                             } 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;
@@ -735,7 +737,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                             }
 
                         } else {
-                            // this is the first motion event, set the dist 
+                            // this is the first motion event, set the dist
                             dc->hatch_spacing = hatch_dist;
                         }
 
@@ -773,8 +775,8 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             }
 
             // 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));
@@ -836,7 +838,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             /* 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");
 
@@ -859,7 +861,7 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             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;
@@ -994,14 +996,14 @@ clear_current(SPDynaDrawContext *dc)
 }
 
 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;
 
     if (!dc->accumulated->is_empty()) {
         if (!dc->repr) {
             /* Create object */
-            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
+            Inkscape::XML::Document *xml_doc = desktop->doc()->getReprDoc();
             Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
 
             /* Set style */
@@ -1011,10 +1013,10 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
 
             SPItem *item=SP_ITEM(desktop->currentLayer()->appendChildRepr(dc->repr));
             Inkscape::GC::release(dc->repr);
-            item->transform = sp_item_i2doc_affine(SP_ITEM(desktop->currentLayer())).inverse();
+            item->transform = SP_ITEM(desktop->currentLayer())->i2doc_affine().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);
@@ -1023,10 +1025,13 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
         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 {
@@ -1036,14 +1041,14 @@ set_to_accumulated(SPDynaDrawContext *dc, bool unionize)
         dc->repr = NULL;
     }
 
-    sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC, 
-                     _("Draw calligraphic stroke"));
+    DocumentUndo::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) {
@@ -1062,7 +1067,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
             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();
@@ -1072,7 +1077,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
         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();
@@ -1089,7 +1094,7 @@ accumulate_calligraphic(SPDynaDrawContext *dc)
             !dc_cal1_firstseg ||
             !rev_cal2_firstseg ||
             !dc_cal1_lastseg ||
-            !rev_cal2_lastseg 
+            !rev_cal2_lastseg
             ) {
             rev_cal2->unref();
             dc->cal1->reset();
@@ -1280,4 +1285,4 @@ draw_temporary_box(SPDynaDrawContext *dc)
   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 :