From 597de4a7a6a70f44324f3ddf984c80210b6c268a Mon Sep 17 00:00:00 2001 From: buliabyak Date: Thu, 30 Mar 2006 14:13:46 +0000 Subject: [PATCH] added variable tremor --- src/dyna-draw-context.cpp | 36 ++++++++++++++++++++++++++++++++---- src/dyna-draw-context.h | 3 ++- src/widgets/toolbox.cpp | 21 ++++++++++++++++++++- 3 files changed, 54 insertions(+), 6 deletions(-) diff --git a/src/dyna-draw-context.cpp b/src/dyna-draw-context.cpp index 7fd7bfe72..303573c46 100644 --- a/src/dyna-draw-context.cpp +++ b/src/dyna-draw-context.cpp @@ -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); } diff --git a/src/dyna-draw-context.h b/src/dyna-draw-context.h index e2f2c1e59..614bf68c3 100644 --- a/src/dyna-draw-context.h +++ b/src/dyna-draw-context.h @@ -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; diff --git a/src/widgets/toolbox.cpp b/src/widgets/toolbox.cpp index ee9609282..6a3a33183 100644 --- a/src/widgets/toolbox.cpp +++ b/src/widgets/toolbox.cpp @@ -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"), -- 2.30.2