1use image::Rgba;
9
10use crate::MappingStrategy;
11use crate::Palette;
12
13pub struct LinearStrategy;
15impl MappingStrategy for LinearStrategy {
16 fn map(&self, count: u32, max_count: u32, num_colors: usize) -> usize {
17 if count == 0 || max_count == 0 {
18 return 0;
19 }
20 let ratio = count as f32 / max_count as f32;
21 ((ratio * (num_colors - 1) as f32).round() as usize).min(num_colors - 1)
22 }
23}
24
25pub struct LogarithmicStrategy;
27impl MappingStrategy for LogarithmicStrategy {
28 fn map(&self, count: u32, max_count: u32, num_colors: usize) -> usize {
29 if count == 0 {
30 return 0;
31 }
32 let log_count = (count as f32 + 1.0).ln();
33 let log_max = (max_count as f32 + 1.0).ln();
34 let ratio = log_count / log_max;
35 ((ratio * (num_colors - 1) as f32).round() as usize).min(num_colors - 1)
36 }
37}
38
39pub struct ThresholdStrategy {
41 thresholds: Vec<u32>,
42}
43impl ThresholdStrategy {
44 pub fn new(thresholds: Vec<u32>) -> Self {
45 Self { thresholds }
46 }
47}
48impl MappingStrategy for ThresholdStrategy {
49 fn map(&self, count: u32, _max_count: u32, _num_colors: usize) -> usize {
50 self.thresholds
51 .iter()
52 .position(|&t| count < t)
53 .unwrap_or(self.thresholds.len())
54 }
55}
56
57pub struct Theme;
59
60impl Theme {
61 pub fn github(strategy: impl MappingStrategy + 'static) -> Palette {
63 Palette::new(
64 vec![
65 Rgba([235, 237, 240, 255]),
66 Rgba([155, 233, 168, 255]),
67 Rgba([48, 196, 99, 255]),
68 Rgba([48, 161, 78, 255]),
69 Rgba([33, 110, 57, 255]),
70 ],
71 strategy,
72 )
73 }
74
75 pub fn github_old(strategy: impl MappingStrategy + 'static) -> Palette {
77 Palette::new(
78 vec![
79 Rgba([238, 238, 238, 255]),
80 Rgba([198, 228, 139, 255]),
81 Rgba([123, 201, 111, 255]),
82 Rgba([35, 154, 59, 255]),
83 Rgba([25, 97, 39, 255]),
84 ],
85 strategy,
86 )
87 }
88
89 pub fn blue(strategy: impl MappingStrategy + 'static) -> Palette {
91 Palette::new(
92 vec![
93 Rgba([235, 237, 240, 255]),
94 Rgba([201, 231, 245, 255]),
95 Rgba([168, 196, 238, 255]),
96 Rgba([135, 146, 232, 255]),
97 Rgba([96, 101, 181, 255]),
98 Rgba([61, 62, 125, 255]),
99 Rgba([31, 29, 66, 255]),
100 ],
101 strategy,
102 )
103 }
104
105 pub fn red(strategy: impl MappingStrategy + 'static) -> Palette {
107 Palette::new(
108 vec![
109 Rgba([235, 237, 240, 255]),
110 Rgba([255, 208, 198, 255]),
111 Rgba([255, 148, 133, 255]),
112 Rgba([234, 86, 70, 255]),
113 Rgba([181, 28, 28, 255]),
114 ],
115 strategy,
116 )
117 }
118}
119
120pub struct Strategy;
122
123impl Strategy {
124 pub fn linear() -> impl MappingStrategy + 'static {
134 LinearStrategy
135 }
136
137 pub fn logarithmic() -> impl MappingStrategy + 'static {
147 LogarithmicStrategy
148 }
149
150 pub fn threshold(thresholds: Vec<u32>) -> impl MappingStrategy + 'static {
160 ThresholdStrategy::new(thresholds)
161 }
162}