Code

added variable tremor
authorbuliabyak <buliabyak@users.sourceforge.net>
Thu, 30 Mar 2006 14:13:46 +0000 (14:13 +0000)
committerbuliabyak <buliabyak@users.sourceforge.net>
Thu, 30 Mar 2006 14:13:46 +0000 (14:13 +0000)
src/dyna-draw-context.cpp
src/dyna-draw-context.h
src/widgets/toolbox.cpp

index 7fd7bfe7223661dfbafc157e794b6307d1df184a..303573c4680116a5824472382ead7c4535977d06 100644 (file)
@@ -226,6 +226,7 @@ sp_dyna_draw_context_setup(SPEventContext *ec)
     sp_event_context_read(ec, "angle");
     sp_event_context_read(ec, "width");
     sp_event_context_read(ec, "thinning");
+    sp_event_context_read(ec, "tremor");
     sp_event_context_read(ec, "flatness");
     sp_event_context_read(ec, "usepressure");
     sp_event_context_read(ec, "usetilt");
@@ -255,6 +256,9 @@ sp_dyna_draw_context_set(SPEventContext *ec, gchar const *key, gchar const *val)
     } else if (!strcmp(key, "thinning")) {
         double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.1 );
         ddc->vel_thin = CLAMP(dval, -1.0, 1.0);
+    } else if (!strcmp(key, "tremor")) {
+        double const dval = ( val ? g_ascii_strtod (val, NULL) : 0.0 );
+        ddc->tremor = CLAMP(dval, 0.0, 1.0);
     } else if (!strcmp(key, "flatness")) {
         double const dval = ( val ? g_ascii_strtod (val, NULL) : 1.0 );
         ddc->flatness = CLAMP(dval, 0, 1.0);
@@ -422,16 +426,40 @@ sp_dyna_draw_brush(SPDynaDrawContext *dc)
         double pressure_thick = (dc->usepressure ? dc->pressure : 1.0);
 
         double width = ( pressure_thick - vel_thin * NR::L2(dc->vel) ) * dc->width;
+
+        double tremble_left = 0, tremble_right = 0;
+        if (dc->tremor > 0) {
+            // obtain two normally distributed random variables, using polar Box-Muller transform
+            double x1, x2, w, y1, y2;
+            do {
+                 x1 = 2.0 * g_random_double_range(0,1) - 1.0;
+                 x2 = 2.0 * g_random_double_range(0,1) - 1.0;
+                 w = x1 * x1 + x2 * x2;
+            } while ( w >= 1.0 );
+            w = sqrt( (-2.0 * log( w ) ) / w );
+            y1 = x1 * w;
+            y2 = x2 * w;
+
+            // deflect both left and right edges randomly and independently, so that:
+            // (1) dc->tremor=1 corresponds to sigma=1, decreasing dc->tremor narrows the bell curve;
+            // (2) deflection depends on width, but is upped for small widths for better visual uniformity across widths;
+            // (3) deflection somewhat depends on speed, to prevent fast strokes looking
+            // comparatively smooth and slow ones excessively jittery
+            tremble_left  = (y1)*dc->tremor * (0.15 + 0.8*width) * (0.35 + 14*NR::L2(dc->vel));
+            tremble_right = (y2)*dc->tremor * (0.15 + 0.8*width) * (0.35 + 14*NR::L2(dc->vel));
+        }
+
         if ( width < 0.02 * dc->width ) {
             width = 0.02 * dc->width;
         }
 
-        NR::Point del = 0.05 * width * dc->ang;
+        NR::Point del_left = 0.05 * (width + tremble_left) * dc->ang;
+        NR::Point del_right = 0.05 * (width + tremble_right) * dc->ang;
 
-        dc->point1[dc->npoints] = sp_dyna_draw_get_vpoint(dc, dc->cur + del);
-        dc->point2[dc->npoints] = sp_dyna_draw_get_vpoint(dc, dc->cur - del);
+        dc->point1[dc->npoints] = sp_dyna_draw_get_vpoint(dc, dc->cur + del_left);
+        dc->point2[dc->npoints] = sp_dyna_draw_get_vpoint(dc, dc->cur - del_right);
 
-        dc->del = del;
+        dc->del = 0.5*(del_left + del_right);
     } else {
         dc->point1[dc->npoints] = sp_dyna_draw_get_curr_vpoint(dc);
     }
index e2f2c1e5902016b7ff3ebc0b3783443f2633eb04..614bf68c3210d2b71e6597d40abea5e83f10e25f 100644 (file)
@@ -32,7 +32,7 @@
 class SPDynaDrawContext;
 class SPDynaDrawContextClass;
 
-#define SAMPLING_SIZE 16        /* fixme: ?? */
+#define SAMPLING_SIZE 8        /* fixme: ?? */
 
 #define DDC_MIN_PRESSURE      0.0
 #define DDC_MAX_PRESSURE      1.0
@@ -89,6 +89,7 @@ struct SPDynaDrawContext
 
     double vel_thin;
     double flatness;
+    double tremor;
 
     Inkscape::MessageContext *_message_context;
 
index ee96092824a67e2fecb17ecc6185f648e4a7acb4..6a3a331835dd314f7b7d9958001bf0ad4009fd6a 100644 (file)
@@ -756,7 +756,9 @@ sp_tb_spinbutton(
     gtk_tooltips_set_tip(tt, sb, tooltip, NULL);
     if (altx)
         gtk_object_set_data(GTK_OBJECT(sb), altx_mark, sb);
-    gtk_widget_set_size_request(sb, AUX_SPINBUTTON_WIDTH_SMALL, AUX_SPINBUTTON_HEIGHT);
+    gtk_widget_set_size_request(sb, 
+                                (upper <= 1.0 || digits == 0)? AUX_SPINBUTTON_WIDTH_SMALL - 10: AUX_SPINBUTTON_WIDTH_SMALL,
+                                AUX_SPINBUTTON_HEIGHT);
     gtk_widget_show(sb);
     gtk_signal_connect(GTK_OBJECT(sb), "focus-in-event", GTK_SIGNAL_FUNC(spinbutton_focus_in), tbl);
     gtk_signal_connect(GTK_OBJECT(sb), "key-press-event", GTK_SIGNAL_FUNC(spinbutton_keypress), tbl);
@@ -1869,6 +1871,13 @@ sp_ddc_flatness_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
     spinbutton_defocus(GTK_OBJECT(tbl));
 }
 
+static void
+sp_ddc_tremor_value_changed(GtkAdjustment *adj, GtkWidget *tbl)
+{
+    prefs_set_double_attribute("tools.calligraphic", "tremor", adj->value);
+    spinbutton_defocus(GTK_OBJECT(tbl));
+}
+
 static void
 sp_ddc_pressure_state_changed(GtkWidget *button, gpointer data)
 {
@@ -1895,6 +1904,7 @@ static void sp_ddc_defaults(GtkWidget *, GtkWidget *tbl)
         {"angle", 30.0},
         {"width", 0.15},
         {"thinning", 0.1},
+        {"tremor", 0.0},
         {"flatness", 0.9}
     };
 
@@ -1966,6 +1976,15 @@ sp_calligraphy_toolbox_new(SPDesktop *desktop)
     //  interval
     gtk_box_pack_start(GTK_BOX(tbl), gtk_hbox_new(FALSE, 0), FALSE, FALSE, AUX_BETWEEN_BUTTON_GROUPS);
 
+    /* Tremor */
+    {
+        GtkWidget *hb = sp_tb_spinbutton(_("Tremor:"), _("How uneven or trembling is the pen stroke"),
+                                         "tools.calligraphic", "tremor", 0.0,
+                                         NULL, tbl, FALSE, NULL,
+                                         0.0, 1.0, 0.01, 0.1,
+                                         sp_ddc_tremor_value_changed, 0.01, 2);
+        gtk_box_pack_start(GTK_BOX(tbl), hb, FALSE, FALSE, AUX_SPACING);
+    }
     /* Mass */
     {
         GtkWidget *hb = sp_tb_spinbutton(_("Mass:"), _("How much inertia affects the movement of the pen"),