1use std::cmp::{max, min};
2use std::io::{stdout, Write};
3use std::{thread, time};
4
5pub fn escape<T: std::fmt::Display>(code: T) {
6 print!("{}[{}", 27 as char, code);
7}
8
9pub fn tc_color_fg(r: u8, g: u8, b: u8) {
11 escape(format!("38;2;{};{};{}", r, g, b));
12}
13
14pub fn tc_color_bg(r: u8, g: u8, b: u8) {
16 escape(format!("48;2;{};{};{}", r, g, b));
17}
18
19pub fn color_fg(color: u8) {
21 escape(format!("38;5;{}m", color));
22}
23
24pub fn color_bg(color: u8) {
26 escape(format!("48;5;{}m", color));
27}
28
29pub fn decolor() {
31 escape("0m");
32}
33
34pub fn clear() {
36 print!("{}c", 27 as char);
37}
38
39pub fn pixel(c: char, x: u32, y: u32) {
41 escape(format!("{};{}H{}", y, x, c));
42 stdout().flush().unwrap();
43}
44
45pub fn orth_line(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
47 if x1 != x2 && y1 != y2 {
48 panic!("Cannot draw non-ortho lines with orth-line");
50 }
51
52 if x1 != x2 {
53 let mut x = min(x1, x2);
54
55 while x != max(x1, x2) + 1 {
56 pixel(c, x, y1);
57
58 x += 1;
59 }
60 } else {
61 let mut y = min(y1, y2);
62
63 while y != max(y1, y2) + 1 {
64 pixel(c, x1, y);
65
66 y += 1;
67 }
68 }
69}
70
71pub fn line(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
72 if x1 == x2 || y1 == y2 {
73 orth_line(c, x1, x2, y1, y2);
74 return;
75 }
76
77 let mut dx: i32 = (x2 - x1) as i32;
78 let mut dy: i32 = (y2 - y1) as i32;
79
80 let sx = if (x2 as i32) - (x1 as i32) > 0 { 1 } else { -1 };
81 let sy = if (y2 as i32) - (y1 as i32) > 0 { 1 } else { -1 };
82
83 let xx; let xy; let yx; let yy;
84 if dx > dy {
85 xx = sx;
86 xy = 0i32;
87 yx = 0i32;
88 yy = sy;
89 } else {
90 std::mem::swap(&mut dx, &mut dy);
91 xx = 0i32;
92 xy = sy;
93 yx = sx;
94 yy = 0i32;
95 }
96
97 let mut err = ((dy << 1) - dx) as i32;
98
99 let mut x = 0;
100 let mut y = 0;
101
102 while x <= dx {
103 pixel(c, ((x1 as i32) + x*xx + y*yx) as u32, ((y1 as i32) + x*xy + y*yy) as u32);
104
105 if err >= 0 {
106 y += 1;
107 err -= (dx as i32) << 1;
108 }
109
110 err += (dy as i32) << 1;
111 x += 1;
112 }
113}
114
115pub fn rect(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
117 orth_line(c, x1, y1, x1, y2);
118 orth_line(c, x1, y1, x2, y1);
119 orth_line(c, x2, y2, x1, y2);
120 orth_line(c, x2, y2, x2, y1);
121}
122
123pub fn rect_fill(c: char, x1: u32, y1: u32, x2: u32, y2: u32) {
125 let mut y = y1;
126 while y != y2 {
127 orth_line(c, x1, y, x2, y);
128 y += 1;
129 }
130}
131
132pub fn triangle(c: char, x1: u32, y1: u32, x2: u32, y2: u32, x3: u32, y3: u32) {
134 line(c, x1, y1, x2, y2);
135 line(c, x1, y1, x3, y3);
136 line(c, x3, y3, x2, y2);
137}
138
139pub fn triangle_fill(c: char, x1: u32, y1: u32, x2: u32, y2: u32, x3: u32, y3: u32) {
141 unimplemented!();
142}
143
144pub fn text(s: String, ox: u32, y: u32) {
146 let mut x = ox;
147
148 for c in s.chars() {
149 pixel(c, x, y);
150 x += 1;
151 }
152}
153
154pub fn goto(x: u32, y: u32) {
156 escape(format!("{};{}H", y, x));
157}
158
159pub fn home() {
161 goto(1, 1);
162}
163
164pub fn bot() {
166 goto(1, 9999);
167}
168
169pub fn sleep(seconds: f32) {
172 let secs = seconds as u64;
173 let mils = (seconds % 1.0 * 1000.0 * 1000000.0) as u32;
174 thread::sleep(time::Duration::new(secs, mils));
175}
176