use crate::{
ColorFormattable,
Color,
TextStyle,
CustomColor,
RGB,
constants::ANSI_PATTERN
};
pub fn interpolate_color(start: &RGB, end: &RGB, steps: usize) -> Vec<RGB> {
if steps < 2 {
return vec![*start];
}
let mut colors: Vec<RGB> = Vec::with_capacity(steps);
for i in 0..steps {
let ratio: f32 = i as f32 / (steps - 1) as f32;
let r: u8 = (start.r as f32 + (end.r as i16 - start.r as i16) as f32 * ratio).round() as u8;
let g: u8 = (start.g as f32 + (end.g as i16 - start.g as i16) as f32 * ratio).round() as u8;
let b: u8 = (start.b as f32 + (end.b as i16 - start.b as i16) as f32 * ratio).round() as u8;
(&mut colors).push(RGB::new(r, g, b));
}
colors
}
pub fn generate_palette(base_color: &RGB, count: usize) -> Vec<RGB> {
if count < 1 {
return vec![];
}
if count == 1 {
return vec![*base_color];
}
let lighter: RGB = RGB::new(base_color.r.saturating_add(50), base_color.g.saturating_add(50), base_color.b.saturating_add(50));
let darker: RGB = RGB::new(base_color.r.saturating_sub(50), base_color.g.saturating_sub(50), base_color.b.saturating_sub(50));
interpolate_color(&darker, &lighter, count)
}
pub fn colorize(text: &str, color: impl ColorFormattable, background: Option<impl ColorFormattable>) -> String {
let mut result: String = String::new();
if let Some(bg) = background {
(&mut result).push_str(&Color::new(bg, true).formatted());
}
(&mut result).push_str(&Color::new(color, false).formatted());
(&mut result).push_str(text);
(&mut result).push_str(&Color::new(TextStyle::Reset, false).formatted());
result
}
pub fn strip_ansi(text: &str) -> String {
ANSI_PATTERN.replace_all(text, "").to_string()
}
pub fn gradient(text: &str, start_color: &RGB, end_color: &RGB) -> String {
if text.is_empty() {
return String::new();
}
let chars: Vec<char> = text.chars().collect();
let length: usize = chars.len();
if length == 1 {
return colorize(text, CustomColor::from(*start_color), None::<TextStyle>);
}
let mut result: String = String::new();
for (i, ch) in chars.iter().enumerate() {
let ratio: f32 = i as f32 / (length - 1) as f32;
let r: u8 = (start_color.r as f32 + (end_color.r as i16 - start_color.r as i16) as f32 * ratio).round() as u8;
let g: u8 = (start_color.g as f32 + (end_color.g as i16 - start_color.g as i16) as f32 * ratio).round() as u8;
let b: u8 = (start_color.b as f32 + (end_color.b as i16 - start_color.b as i16) as f32 * ratio).round() as u8;
let color: CustomColor = CustomColor::from(RGB::new(r, g, b));
(&mut result).push_str(&colorize(&ch.to_string(), color, None::<TextStyle>));
}
result
}
pub fn percent_color<T: ColorFormattable>(percent: f32, thresholds: Option<(f32, f32)>, reverse: bool, low_color: T, mid_color: T, high_color: T) -> T {
let (low, mid): (f32, f32) = thresholds.unwrap_or((50.0, 75.0));
if reverse {
if percent < low {
high_color
} else if percent < mid {
mid_color
} else {
low_color
}
} else {
if percent < low {
low_color
} else if percent < mid {
mid_color
} else {
high_color
}
}
}