summaryrefslogtreecommitdiffstats
path: root/src/canvas/canvas_colours/drawing_utils.rs
blob: e54c99e9bb4ca31cee028ac6d03bc198701c369a (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
use crate::utils::{error, gen_util::*};
use tui::style::{Color, Style};

const GOLDEN_RATIO: f32 = 0.618_034; // Approx, good enough for use (also Clippy gets mad if it's too long)

/// Generates random colours.  Strategy found from
/// https://martin.ankerl.com/2009/12/09/how-to-create-random-colors-programmatically/
pub fn gen_n_styles(num_to_gen: i32) -> Vec<Style> {
	fn gen_hsv(h: f32) -> f32 {
		let new_val = h + GOLDEN_RATIO;
		if new_val > 1.0 {
			new_val.fract()
		} else {
			new_val
		}
	}
	/// This takes in an h, s, and v value of range [0, 1]
	/// For explanation of what this does, see
	/// https://en.wikipedia.org/wiki/HSL_and_HSV#HSV_to_RGB_alternative
	fn hsv_to_rgb(hue: f32, saturation: f32, value: f32) -> (u8, u8, u8) {
		fn hsv_helper(num: u32, hu: f32, sat: f32, val: f32) -> f32 {
			let k = (num as f32 + hu * 6.0) % 6.0;
			val - val * sat * float_max(float_min(k, float_min(4.1 - k, 1.1)), 0.0)
		}

		(
			(hsv_helper(5, hue, saturation, value) * 255.0) as u8,
			(hsv_helper(3, hue, saturation, value) * 255.0) as u8,
			(hsv_helper(1, hue, saturation, value) * 255.0) as u8,
		)
	}

	// Generate colours
	let mut colour_vec: Vec<Style> = vec![
		Style::default().fg(Color::Rgb(150, 106, 253)),
		Style::default().fg(Color::LightYellow),
		Style::default().fg(Color::LightMagenta),
		Style::default().fg(Color::LightCyan),
		Style::default().fg(Color::Green),
		Style::default().fg(Color::Red),
	];

	let mut h: f32 = 0.4; // We don't need random colours... right?
	for _i in 0..(num_to_gen - 6) {
		h = gen_hsv(h);
		let result = hsv_to_rgb(h, 0.5, 0.95);
		colour_vec.push(Style::default().fg(Color::Rgb(result.0, result.1, result.2)));
	}

	colour_vec
}

pub fn convert_hex_to_color(hex: &str) -> error::Result<Color> {
	fn convert_hex_to_rgb(hex: &str) -> error::Result<(u8, u8, u8)> {
		if hex.len() == 7 && &hex[0..1] == "#" {
			let r = u8::from_str_radix(&hex[1..3], 16)?;
			let g = u8::from_str_radix(&hex[3..5], 16)?;
			let b = u8::from_str_radix(&hex[5..7], 16)?;

			return Ok((r, g, b));
		}

		Err(error::BottomError::GenericError(format!(
				"Colour hex {} is not of valid length.  It must be a 7 character string of the form \"#112233\".",
				hex
			)))
	}

	let rgb = convert_hex_to_rgb(hex)?;
	Ok(Color::Rgb(rgb.0, rgb.1, rgb.2))
}