Skip to content

Commit 831a9f1

Browse files
committed
feat: add stroke stabilizer
1 parent ec544fe commit 831a9f1

29 files changed

Lines changed: 599 additions & 13 deletions

File tree

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -208,6 +208,7 @@ For distro-specific package details, see [Installation](#installation). For keyb
208208
- Selection: Alt-drag, <kbd>V</kbd> tool, properties panel
209209
- Duplicate (<kbd>Ctrl+D</kbd>), delete (<kbd>Delete</kbd>), undo/redo
210210
- Color picker, palettes, size via hotkeys or scroll
211+
- Opt-in stroke stabilizer for completed pen/marker paths
211212
- Render color profiles for print/projector/light-theme preview
212213
- Radial menu at cursor (<kbd>Middle-click</kbd>): quick tool/color selection + scroll size adjust
213214

config.example.toml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -813,6 +813,10 @@ default_eraser_mode = "brush"
813813
# Default marker opacity multiplier (0.05 - 0.90). Multiplies the current color alpha.
814814
marker_opacity = 0.32
815815

816+
# Stroke stabilizer strength for completed pen/marker paths (0.0 - 1.0).
817+
# 0.0 disables smoothing; live previews remain raw and the finalized stroke is smoothed on release.
818+
stroke_stabilizer_strength = 0.0
819+
816820
# Default fill state for fill-capable shapes
817821
default_fill_enabled = false
818822

configurator/src/app/search/terms.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,9 @@ pub(super) const DRAWING_DEFAULT_TERMS: &[&str] = &[
8888
"shape",
8989
"marker",
9090
"marker opacity",
91+
"stroke stabilizer",
92+
"stabilizer",
93+
"smoothing",
9194
"fill",
9295
"start shapes filled",
9396
"enable text background",

configurator/src/app/search/tests.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,13 @@ fn field_level_terms_do_not_force_whole_tab_visible() {
106106

107107
#[test]
108108
fn exact_drawing_default_labels_match_defaults_section() {
109-
for query in ["font size pt", "eraser size px", "enable text background"] {
109+
for query in [
110+
"font size pt",
111+
"eraser size px",
112+
"enable text background",
113+
"stroke stabilizer",
114+
"smoothing",
115+
] {
110116
let (mut app, _task) = ConfiguratorApp::new_app();
111117
app.search_query = SearchQuery::new(query);
112118

configurator/src/app/view/drawing/mod.rs

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,18 @@ impl ConfiguratorApp {
106106
None,
107107
validate_f64_range(&self.draft.drawing_marker_opacity, 0.05, 0.9),
108108
),
109+
labeled_input_with_feedback(
110+
"Stroke stabilizer",
111+
&self.draft.drawing_stroke_stabilizer_strength,
112+
&self.defaults.drawing_stroke_stabilizer_strength,
113+
TextField::DrawingStrokeStabilizerStrength,
114+
Some("Range: 0-1"),
115+
validate_f64_range(
116+
&self.draft.drawing_stroke_stabilizer_strength,
117+
0.0,
118+
1.0,
119+
),
120+
),
109121
labeled_input_with_feedback(
110122
"Undo stack limit",
111123
&self.draft.drawing_undo_stack_limit,

configurator/src/app/view/widgets/validation.rs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ pub(in crate::app::view) fn validate_f64_range(value: &str, min: f64, max: f64)
88

99
match trimmed.parse::<f64>() {
1010
Ok(value) => {
11-
if value < min || value > max {
11+
if !value.is_finite() {
12+
Some("Expected a finite numeric value".to_string())
13+
} else if value < min || value > max {
1214
Some(format!(
1315
"Range: {}-{}",
1416
format_float(min),
@@ -132,6 +134,10 @@ mod tests {
132134
validate_f64_range("", 0.5, 2.0),
133135
Some("Expected a numeric value".to_string())
134136
);
137+
assert_eq!(
138+
validate_f64_range("nan", 0.5, 2.0),
139+
Some("Expected a finite numeric value".to_string())
140+
);
135141
}
136142

137143
#[test]

configurator/src/models/config/draft/from_config.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ impl ConfigDraft {
3434
drawing_default_font_size: format_float(config.drawing.default_font_size),
3535
drawing_polygon_sides: config.drawing.polygon_sides.to_string(),
3636
drawing_marker_opacity: format_float(config.drawing.marker_opacity),
37+
drawing_stroke_stabilizer_strength: format_float(
38+
config.drawing.stroke_stabilizer_strength,
39+
),
3740
drawing_hit_test_tolerance: format_float(config.drawing.hit_test_tolerance),
3841
drawing_hit_test_linear_threshold: config.drawing.hit_test_linear_threshold.to_string(),
3942
drawing_undo_stack_limit: config.drawing.undo_stack_limit.to_string(),

configurator/src/models/config/draft/mod.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ pub struct ConfigDraft {
2525
pub drawing_default_font_size: String,
2626
pub drawing_polygon_sides: String,
2727
pub drawing_marker_opacity: String,
28+
pub drawing_stroke_stabilizer_strength: String,
2829
pub drawing_hit_test_tolerance: String,
2930
pub drawing_hit_test_linear_threshold: String,
3031
pub drawing_undo_stack_limit: String,

configurator/src/models/config/setters.rs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -258,6 +258,9 @@ impl ConfigDraft {
258258
TextField::DrawingFontSize => self.drawing_default_font_size = value,
259259
TextField::DrawingPolygonSides => self.drawing_polygon_sides = value,
260260
TextField::DrawingMarkerOpacity => self.drawing_marker_opacity = value,
261+
TextField::DrawingStrokeStabilizerStrength => {
262+
self.drawing_stroke_stabilizer_strength = value;
263+
}
261264
TextField::DrawingFontFamily => self.drawing_font_family = value,
262265
TextField::DrawingFontWeight => {
263266
self.drawing_font_weight = value;

configurator/src/models/config/tests.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -364,6 +364,12 @@ fn setters_update_draft_state() {
364364
assert_eq!(draft.drawing_font_weight, "weird");
365365
assert_eq!(draft.drawing_font_weight_option, FontWeightOption::Custom);
366366

367+
draft.set_text(
368+
TextField::DrawingStrokeStabilizerStrength,
369+
"0.5".to_string(),
370+
);
371+
assert_eq!(draft.drawing_stroke_stabilizer_strength, "0.5");
372+
367373
draft.set_text(TextField::DrawingColorName, "green".to_string());
368374
assert_eq!(draft.drawing_color.name, "green");
369375
assert_eq!(draft.drawing_color.selected_named, NamedColorOption::Green);

0 commit comments

Comments
 (0)