line.rs - icy_draw - icy_draw is the successor to mystic draw. fork / mirror
(HTM) git clone https://git.drkhsh.at/icy_draw.git
(DIR) Log
(DIR) Files
(DIR) Refs
(DIR) README
(DIR) LICENSE
---
line.rs (4660B)
---
1 #![allow(clippy::comparison_chain)]
2 use icy_engine::Position;
3 use icy_engine_egui::BufferView;
4
5 use super::{plot_point, BrushMode, ColorMode, PointRole};
6
7 fn get_line_points(from: Position, to: Position) -> Vec<Position> {
8 let dx = (to.x - from.x).abs();
9 let sx = if from.x < to.x { 1 } else { -1 };
10 let dy = (to.y - from.y).abs();
11 let sy = if from.y < to.y { 1 } else { -1 };
12
13 let mut err = if dx > dy { dx } else { -dy } / 2;
14
15 let mut result = Vec::new();
16 let mut cur = from;
17 loop {
18 result.push(cur);
19 if cur == to {
20 break;
21 }
22
23 let e2 = err;
24 if e2 > -dx {
25 err -= dy;
26 cur.x += sx;
27 }
28 if e2 < dy {
29 err += dx;
30 cur.y += sy;
31 }
32 }
33 result
34 }
35
36 pub fn draw_line(buffer_view: &mut BufferView, from: impl Into<Position>, to: impl Into<Position>, mode: BrushMode, color_mode: ColorMode) {
37 let mut from = from.into();
38 let mut to = to.into();
39 let mut y_mul = 1;
40 if !matches!(mode, BrushMode::HalfBlock) {
41 from.y /= 2;
42 to.y /= 2;
43 y_mul = 2;
44 }
45
46 let mut v = get_line_points(from, to);
47 if v.is_empty() {
48 return;
49 }
50 if !matches!(mode, BrushMode::Outline) {
51 for point in get_line_points(from, to) {
52 plot_point(buffer_view, (point.x, point.y * y_mul), mode.clone(), color_mode, PointRole::Line);
53 }
54 return;
55 }
56 let mut n = Vec::new();
57 for pt in v {
58 let p = Position::new(pt.x, 2 * (pt.y / 2));
59 if let Some(l) = n.last() {
60 if p == *l {
61 continue;
62 }
63 }
64 n.push(p);
65 }
66 v = n;
67 let mut last = v[0];
68 let mut i = 0;
69 while i < v.len() {
70 let is_last = i + 1 >= v.len();
71 let next = if is_last {
72 Position::new(v[i].x + v[i].x - last.x, v[i].y + v[i].y + last.y)
73 } else {
74 v[i + 1]
75 };
76 let point = v[i];
77 last = point;
78 let cy2 = point.y;
79 let ny2 = next.y;
80
81 let role = if point.x > next.x {
82 // Left side
83 if ny2 < cy2 {
84 println!("plot ne corner above");
85 plot_point(buffer_view, point + Position::new(0, -1), mode.clone(), color_mode, PointRole::NECorner);
86 PointRole::SWCorner
87 } else if ny2 > cy2 {
88 println!("plot se corner below");
89 plot_point(buffer_view, point + Position::new(0, 2), mode.clone(), color_mode, PointRole::SECorner);
90 PointRole::NWCorner
91 } else {
92 PointRole::TopSide
93 }
94 } else if point.x < next.x {
95 // Right Side
96 if ny2 < cy2 {
97 println!("plot nw corner above");
98 plot_point(buffer_view, point + Position::new(0, -1), mode.clone(), color_mode, PointRole::NWCorner);
99 PointRole::SECorner
100 } else if ny2 > cy2 {
101 println!("plot sw corner below");
102 plot_point(buffer_view, point + Position::new(0, 2), mode.clone(), color_mode, PointRole::SWCorner);
103 PointRole::NECorner
104 } else {
105 // telel
106 if point.x < next.x {
107 if point.y == next.y {
108 println!("top side right 1");
109 PointRole::TopSide
110 } else {
111 println!("plot ne corner right");
112 i += 1;
113 plot_point(buffer_view, point + Position::new(1, 0), mode.clone(), color_mode, PointRole::NECorner);
114 PointRole::SWCorner
115 }
116 } else if point.x > next.x {
117 println!("plot nw corner left");
118 plot_point(buffer_view, point + Position::new(-1, 0), mode.clone(), color_mode, PointRole::NWCorner);
119 PointRole::SECorner
120 } else {
121 // case 4
122 if last.y == point.y {
123 println!("top side right 2");
124 PointRole::TopSide
125 } else {
126 println!("plot ne corner right");
127 plot_point(buffer_view, point + Position::new(1, 0), mode.clone(), color_mode, PointRole::NECorner);
128 PointRole::SWCorner
129 }
130 }
131 }
132 } else {
133 PointRole::LeftSide
134 };
135 plot_point(buffer_view, point, mode.clone(), color_mode, role);
136 i += 1;
137 }
138 }