mirror of
https://github.com/storytold/vectorcraft.git
synced 2026-10-30 04:37:29 -06:00
Merge pull request #4585 from storytold/fix/pencil-preview-lag
Fix #4565: preview Pencil and Paintbrush strokes at half a pixel at most
This commit is contained in:
@@ -27,8 +27,14 @@ use crate::{Action, Cursor, Mods, Overlay, PointerEvent, PointerKind, Tool, Tool
|
||||
/// radius while Alt switches it to the Smooth tool.
|
||||
const SMOOTH_RADIUS: f64 = 12.0;
|
||||
|
||||
/// The finest Fidelity (screen pixels) a Pencil or Paintbrush stroke is fitted at while it is drawn:
|
||||
/// a fit's cost grows as its Fidelity shrinks (at 0.01 pt a long pen stroke lagged, #4565), and
|
||||
/// a preview within half a pixel of the stroke looks the same. The release fits it at its Fidelity.
|
||||
const PREVIEW_FIDELITY_PX: f64 = 0.5;
|
||||
|
||||
pub struct GestureTool {
|
||||
/// How many points the last preview of the stroke had ([`crate::previews_at`]).
|
||||
/// How many points the last preview of the stroke had ([`crate::previews_at`]); 0 when it was
|
||||
/// fitted coarser than the stroke kept ([`PREVIEW_FIDELITY_PX`]).
|
||||
previewed: usize,
|
||||
id: &'static str,
|
||||
points: Vec<Point>,
|
||||
@@ -488,8 +494,11 @@ impl Tool for GestureTool {
|
||||
}
|
||||
// With the Pencil's Live preview off a thin line shows instead (`overlays`).
|
||||
if self.previews() && crate::previews_at(self.points.len()) {
|
||||
self.previewed = self.points.len();
|
||||
let mut v = self.freehand_params(false);
|
||||
let fidelity = self.fidelity.max(cx.tol(PREVIEW_FIDELITY_PX));
|
||||
v["fidelity"] = json!(fidelity);
|
||||
// A preview fitted coarser than the stroke kept is stale (`deactivate`).
|
||||
self.previewed = if fidelity > self.fidelity { 0 } else { self.points.len() };
|
||||
if !self.live_fit {
|
||||
// Live curve fitting off: the release fits the stroke (`finish`).
|
||||
v["fit"] = json!(false);
|
||||
|
||||
@@ -122,6 +122,40 @@ fn pencil_with_live_curve_fitting_off_previews_the_stroke_unfitted() {
|
||||
assert!(!drawn.is_empty() && drawn.iter().all(Option::is_none), "{drawn:?}");
|
||||
}
|
||||
|
||||
/// A stroke whose Fidelity is finer than half a screen pixel previews fitted at half a pixel, which
|
||||
/// looks the same at a fraction of the fit's cost (#4565); the release, and another tool chosen
|
||||
/// while it is drawn, fit it at its own Fidelity. A coarser Fidelity previews as it is kept.
|
||||
#[test]
|
||||
fn fine_fidelity_previews_at_half_a_pixel() {
|
||||
let (d, _) = doc_with_rect();
|
||||
let s = Selection::default();
|
||||
let p = paint();
|
||||
let mut cx = cx(&d, &s, &p);
|
||||
let stroke = [(0.0, 0.0), (10.0, 5.0), (20.0, 0.0), (30.0, 5.0)];
|
||||
let fidelities = |acts: &[Action]| -> Vec<f64> {
|
||||
acts.iter().filter_map(|a| if let Action::Preview(_, v) = a { v["fidelity"].as_f64() } else { None }).collect()
|
||||
};
|
||||
for id in ["pencil", "paintbrush"] {
|
||||
for (zoom, fidelity, drawn) in [(1.0, 0.01, 0.5), (4.0, 0.01, 0.125), (1.0, 1.5, 1.5)] {
|
||||
cx.zoom = zoom;
|
||||
let mut t = GestureTool::new(id);
|
||||
t.set_option("fidelity", &json!(fidelity));
|
||||
let acts = drag(&mut t, &cx, &stroke, Mods::default());
|
||||
let (release, during) = acts.split_last().unwrap();
|
||||
assert_eq!(fidelities(&during.concat()), [drawn; 3], "{id} at {zoom}x, {fidelity} pt");
|
||||
assert_eq!(fidelities(release), [fidelity], "{id} at {zoom}x, {fidelity} pt: the release");
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Down, 0.0, 0.0));
|
||||
for &(x, y) in &stroke[1..] {
|
||||
t.pointer(&cx, &PointerEvent::new(PointerKind::Drag, x, y));
|
||||
}
|
||||
let acts = t.deactivate(&cx);
|
||||
let kept = if drawn > fidelity { [fidelity].to_vec() } else { vec![] };
|
||||
assert_eq!(fidelities(&acts), kept, "{id} at {zoom}x, {fidelity} pt: another tool chosen");
|
||||
assert_eq!(acts.last(), Some(&Action::Commit));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Keep selected is on by default, and every Pencil and Paintbrush preview sends it.
|
||||
#[test]
|
||||
fn pencil_and_paintbrush_send_keep_selected() {
|
||||
|
||||
Reference in New Issue
Block a user