1//! Insert Space's feedback, as OneNote 2010 draws it: lines across the view where the drag
2//! began and where it is, an arrow between them in the middle of the view, and a tint where
3//! what moves lands.
4
5use crate::gpu::colorref;
6use draw::Primitive;
7
8/// Appends the feedback for lines at `from` and `to` along `axis` (0 for x), with `moved` the
9/// extents of what moves, over `view`, the page's visible rectangle; `pixel` is page units
10/// per pixel.
11pub(super) fn append(
12 axis: usize,
13 [from, to]: [f32; 2],
14 moved: &[[f32; 4]],
15 view: [f32; 4],
16 pixel: f32,
17 primitives: &mut Vec<Primitive<'_>>,
18) {
19 let across = 1 - axis;
20 let rect = |along: [f32; 2], side: [f32; 2]| {
21 let [a0, a1] = [along[0].min(along[1]), along[0].max(along[1])];
22 let [s0, s1] = side;
23 if axis == 1 {
24 [s0, a0, s1, a1]
25 } else {
26 [a0, s0, a1, s1]
27 }
28 };
29 let point = |along: f32, side: f32| {
30 let mut point = [side; 2];
31 point[axis] = along;
32 point
33 };
34 let delta = to - from;
35 let mut tint = colorref(0x00f7e4cc);
36 tint[3] = 0.6;
37 for extent in moved {
38 let mut extent = *extent;
39 extent[axis] += delta;
40 extent[axis + 2] += delta;
41 primitives.push(Primitive::Rect {
42 rect: extent,
43 color: tint,
44 });
45 }
46 if delta.abs() >= pixel {
47 let (fill, edge) = (colorref(0x00fff2e5), colorref(0x00e8a460));
48 let middle = (view[across] + view[across + 2]) / 2.0;
49 let [shaft, head] = [36.5 * pixel, 73.0 * pixel];
50 let length = (31.0 * pixel).min(delta.abs());
51 let base = to - length * delta.signum();
52 primitives.push(Primitive::Rect {
53 rect: rect([from, base], [middle - shaft, middle + shaft]),
54 color: fill,
55 });
56 let rows = (length / pixel).ceil().max(1.0);
57 for row in 0..rows as u32 {
58 let row = row as f32;
59 let half = head * (1.0 - (row + 0.5) / rows);
60 let near = base + delta.signum() * row * pixel;
61 let far = base + delta.signum() * ((row + 1.0) * pixel).min(length);
62 primitives.push(Primitive::Rect {
63 rect: rect([near, far], [middle - half, middle + half]),
64 color: fill,
65 });
66 }
67 let segments = [
68 (point(from, middle - shaft), point(base, middle - shaft)),
69 (point(from, middle + shaft), point(base, middle + shaft)),
70 (point(base, middle - shaft), point(base, middle - head)),
71 (point(base, middle + shaft), point(base, middle + head)),
72 (point(base, middle - head), point(to, middle)),
73 (point(base, middle + head), point(to, middle)),
74 ];
75 for (from, to) in segments {
76 primitives.push(Primitive::Segment {
77 from,
78 to,
79 width: pixel,
80 round: false,
81 color: edge,
82 });
83 }
84 }
85 for at in [from, to] {
86 primitives.push(Primitive::Rect {
87 rect: rect(
88 [at - pixel / 2.0, at + pixel / 2.0],
89 [view[across], view[across + 2]],
90 ),
91 color: colorref(0x00df862d),
92 });
93 }
94}