Code

use <errno.h> instead of assuming extern int
[inkscape.git] / src / dyna-draw-context.cpp
index e4fac3293d38f724dca4c9bb35dc98b18ce79871..ba44df3ce784e05ebcc0a9a18a4598277cc7463c 100644 (file)
@@ -27,6 +27,7 @@
 
 #include <gtk/gtk.h>
 #include <gdk/gdkkeysyms.h>
+#include <glibmm/i18n.h>
 
 #include "svg/svg.h"
 #include "display/canvas-bpath.h"
@@ -43,7 +44,6 @@
 #include "desktop-style.h"
 #include "message-context.h"
 #include "pixmaps/cursor-calligraphy.xpm"
-#include "pixmaps/cursor-calligraphy.pixbuf"
 #include "dyna-draw-context.h"
 #include "libnr/n-art-bpath.h"
 #include "libnr/nr-path.h"
 #define SAMPLE_TIMEOUT 10
 #define TOLERANCE_LINE 1.0
 #define TOLERANCE_CALLIGRAPHIC 3.0
-#define DYNA_EPSILON 0.5e-2
+
+#define DYNA_EPSILON 0.5e-6
+#define DYNA_EPSILON_START 0.5e-2
+#define DYNA_VEL_START 1e-5
 
 #define DYNA_MIN_WIDTH 1.0e-6
 
@@ -130,11 +133,6 @@ sp_dyna_draw_context_init(SPDynaDrawContext *ddc)
     SPEventContext *event_context = SP_EVENT_CONTEXT(ddc);
 
     event_context->cursor_shape = cursor_calligraphy_xpm;
-    event_context->cursor_pixbuf = gdk_pixbuf_new_from_inline(
-            -1,
-            cursor_calligraphy_pixbuf,
-            FALSE,
-            NULL);  
     event_context->hot_x = 4;
     event_context->hot_y = 4;
 
@@ -151,6 +149,7 @@ sp_dyna_draw_context_init(SPDynaDrawContext *ddc)
     ddc->cur = NR::Point(0,0);
     ddc->last = NR::Point(0,0);
     ddc->vel = NR::Point(0,0);
+    ddc->vel_max = 0;
     ddc->acc = NR::Point(0,0);
     ddc->ang = NR::Point(0,0);
     ddc->del = NR::Point(0,0);
@@ -309,6 +308,7 @@ sp_dyna_draw_reset(SPDynaDrawContext *dc, NR::Point p)
 {
     dc->last = dc->cur = sp_dyna_draw_get_npoint(dc, p);
     dc->vel = NR::Point(0,0);
+    dc->vel_max = 0;
     dc->acc = NR::Point(0,0);
     dc->ang = NR::Point(0,0);
     dc->del = NR::Point(0,0);
@@ -345,7 +345,7 @@ sp_dyna_draw_apply(SPDynaDrawContext *dc, NR::Point p)
 
     /* Calculate force and acceleration */
     NR::Point force = n - dc->cur;
-    if ( NR::L2(force) < DYNA_EPSILON ) {
+    if ( NR::L2(force) < DYNA_EPSILON || (dc->vel_max < DYNA_VEL_START && NR::L2(force) < DYNA_EPSILON_START)) {
         return FALSE;
     }
 
@@ -354,6 +354,9 @@ sp_dyna_draw_apply(SPDynaDrawContext *dc, NR::Point p)
     /* Calculate new velocity */
     dc->vel += dc->acc;
 
+    if (NR::L2(dc->vel) > dc->vel_max)
+        dc->vel_max = NR::L2(dc->vel);
+
     /* Calculate angle of drawing tool */
 
     double a1;
@@ -399,9 +402,18 @@ sp_dyna_draw_apply(SPDynaDrawContext *dc, NR::Point p)
     // find the flatness-weighted bisector angle, unflip if a2 was flipped
     // FIXME: when dc->vel is oscillating around the fixed angle, the new_ang flips back and forth. How to avoid this?
     double new_ang = a1 + (1 - dc->flatness) * (a2 - a1) - (flipped? M_PI : 0);
+
+    double angle_delta = NR::L2(NR::Point (cos (new_ang), sin (new_ang)) - dc->ang);
+
+    if ( angle_delta / NR::L2(dc->vel) > 4000 ) {
+        return FALSE;
+    }
+
     // convert to point
     dc->ang = NR::Point (cos (new_ang), sin (new_ang));
 
+//    g_print ("force %g  acc %g  vel_max %g  vel %g  a1 %g  a2 %g  new_ang %g\n", NR::L2(force), NR::L2(dc->acc), dc->vel_max, NR::L2(dc->vel), a1, a2, new_ang);
+
     /* Apply drag */
     dc->vel *= 1.0 - drag;
 
@@ -475,6 +487,27 @@ sp_ddc_update_toolbox (SPDesktop *desktop, const gchar *id, double value)
     desktop->setToolboxAdjustmentValue (id, value);
 }
 
+static void
+calligraphic_cancel(SPDynaDrawContext *dc)
+{
+    SPDesktop *desktop = SP_EVENT_CONTEXT(dc)->desktop;
+    dc->dragging = FALSE;
+    dc->is_drawing = false;
+    sp_canvas_item_ungrab(SP_CANVAS_ITEM(desktop->acetate), 0);
+            /* Remove all temporary line segments */
+            while (dc->segments) {
+                gtk_object_destroy(GTK_OBJECT(dc->segments->data));
+                dc->segments = g_slist_remove(dc->segments, dc->segments->data);
+            }
+            /* reset accumulated curve */
+            sp_curve_reset(dc->accumulated);
+            clear_current(dc);
+            if (dc->repr) {
+                dc->repr = NULL;
+            }
+}
+
+
 gint
 sp_dyna_draw_context_root_handler(SPEventContext *event_context,
                                   GdkEvent *event)
@@ -623,9 +656,20 @@ sp_dyna_draw_context_root_handler(SPEventContext *event_context,
             }
             break;
         case GDK_Escape:
-            sp_desktop_selection(desktop)->clear();
+            if (dc->is_drawing) {
+                // if drawing, cancel, otherwise pass it up for deselecting
+                calligraphic_cancel (dc);
+                ret = TRUE;
+            }
+            break;
+        case GDK_z:
+        case GDK_Z:
+            if (MOD__CTRL_ONLY && dc->is_drawing) {
+                // if drawing, cancel, otherwise pass it up for undo
+                calligraphic_cancel (dc);
+                ret = TRUE;
+            }
             break;
-
         default:
             break;
         }
@@ -667,7 +711,8 @@ set_to_accumulated(SPDynaDrawContext *dc)
 
         if (!dc->repr) {
             /* Create object */
-            Inkscape::XML::Node *repr = sp_repr_new("svg:path");
+            Inkscape::XML::Document *xml_doc = sp_document_repr_doc(desktop->doc());
+            Inkscape::XML::Node *repr = xml_doc->createElement("svg:path");
 
             /* Set style */
             sp_desktop_apply_style_tool (desktop, repr, "tools.calligraphic", false);
@@ -698,7 +743,7 @@ set_to_accumulated(SPDynaDrawContext *dc)
     }
 
     sp_document_done(sp_desktop_document(desktop), SP_VERB_CONTEXT_CALLIGRAPHIC, 
-                     /* TODO: annotate */ "dyna-draw-context.cpp:689");
+                     _("Create calligraphic stroke"));
 }
 
 static void
@@ -901,14 +946,18 @@ static void
 draw_temporary_box(SPDynaDrawContext *dc)
 {
     sp_curve_reset(dc->currentcurve);
-    sp_curve_moveto(dc->currentcurve, dc->point1[0]);
-    for (gint i = 1; i < dc->npoints; i++) {
+
+    sp_curve_moveto(dc->currentcurve, dc->point1[dc->npoints-1]);
+    for (gint i = dc->npoints-2; i >= 0; i--) {
         sp_curve_lineto(dc->currentcurve, dc->point1[i]);
     }
-    for (gint i = dc->npoints-1; i >= 0; i--) {
+    for (gint i = 0; i < dc->npoints; i++) {
         sp_curve_lineto(dc->currentcurve, dc->point2[i]);
     }
-    add_cap(dc->currentcurve, dc->point2[1], dc->point2[0], dc->point1[0], dc->point1[1], dc->cap_rounding);
+    if (dc->npoints >= 2) {
+        add_cap(dc->currentcurve, dc->point2[dc->npoints-2], dc->point2[dc->npoints-1], dc->point1[dc->npoints-1], dc->point1[dc->npoints-2], dc->cap_rounding);
+    }
+
     sp_curve_closepath(dc->currentcurve);
     sp_canvas_bpath_set_bpath(SP_CANVAS_BPATH(dc->currentshape), dc->currentcurve);
 }