modcli/output/
gradient.rs1use crossterm::style::{Color, Stylize};
2
3pub fn generate(text: &str, start: Color, end: Color) -> String {
12 let chars: Vec<char> = text.chars().collect();
13 let steps = chars.len().max(1);
14 let mut result = String::with_capacity(text.len() * 10); for (i, c) in chars.iter().enumerate() {
17 let r = interpolate(get_r(&start), get_r(&end), i, steps);
18 let g = interpolate(get_g(&start), get_g(&end), i, steps);
19 let b = interpolate(get_b(&start), get_b(&end), i, steps);
20 let color = Color::Rgb { r, g, b };
21 result.push_str(&c.to_string().with(color).to_string());
22 }
23
24 result
25}
26
27#[inline(always)]
32pub fn two_color(text: &str, start: Color, end: Color) -> String {
33 generate(text, start, end)
34}
35
36pub fn three_color(text: &str, start: Color, mid: Color, end: Color) -> String {
40 let chars: Vec<char> = text.chars().collect();
41 let total = chars.len().max(1);
42 let midpoint = total / 2;
43 let mut result = String::with_capacity(text.len() * 10);
44
45 for (i, c) in chars.iter().enumerate() {
46 let (from, to, step, steps) = if i < midpoint {
47 (start, mid, i, midpoint)
48 } else {
49 (mid, end, i - midpoint, total - midpoint)
50 };
51
52 let r = interpolate(get_r(&from), get_r(&to), step, steps);
53 let g = interpolate(get_g(&from), get_g(&to), step, steps);
54 let b = interpolate(get_b(&from), get_b(&to), step, steps);
55 let color = Color::Rgb { r, g, b };
56 result.push_str(&c.to_string().with(color).to_string());
57 }
58
59 result
60}
61
62pub fn multi_color(text: &str, colors: Vec<Color>) -> String {
66 let chars: Vec<char> = text.chars().collect();
67 let steps = chars.len().max(1);
68 let segments = colors.len().saturating_sub(1).max(1);
69 let mut result = String::with_capacity(text.len() * 10);
70
71 for (i, c) in chars.iter().enumerate() {
72 let t = i as f32 / (steps - 1).max(1) as f32;
73 let seg_float = t * segments as f32;
74 let seg = seg_float.floor() as usize;
75 let seg_t = seg_float - seg as f32;
76
77 let from = colors.get(seg).unwrap_or(&colors[0]);
78 let to = colors.get(seg + 1).unwrap_or(from);
79
80 let r = interpolate(get_r(from), get_r(to), (seg_t * 100.0) as usize, 100);
81 let g = interpolate(get_g(from), get_g(to), (seg_t * 100.0) as usize, 100);
82 let b = interpolate(get_b(from), get_b(to), (seg_t * 100.0) as usize, 100);
83
84 let color = Color::Rgb { r, g, b };
85 result.push_str(&c.to_string().with(color).to_string());
86 }
87
88 result
89}
90
91#[inline(always)]
100fn get_r(c: &Color) -> u8 {
101 match c {
102 Color::Rgb { r, .. } => *r,
103 _ => 255,
104 }
105}
106
107#[inline(always)]
110fn get_g(c: &Color) -> u8 {
111 match c {
112 Color::Rgb { g, .. } => *g,
113 _ => 255,
114 }
115}
116
117#[inline(always)]
120fn get_b(c: &Color) -> u8 {
121 match c {
122 Color::Rgb { b, .. } => *b,
123 _ => 255,
124 }
125}
126
127#[inline(always)]
133fn interpolate(start: u8, end: u8, step: usize, total: usize) -> u8 {
134 let start_f = start as f32;
135 let end_f = end as f32;
136 let ratio = step as f32 / (total - 1).max(1) as f32;
137 (start_f + (end_f - start_f) * ratio).round() as u8
138}