plotters_unstable/style/
color.rs1use super::palette::Palette;
2use super::ShapeStyle;
3
4use plotters_backend::{BackendColor, BackendStyle};
5
6use std::marker::PhantomData;
7
8pub trait Color: BackendStyle {
10 #[inline(always)]
12 fn rgb(&self) -> (u8, u8, u8) {
13 self.color().rgb
14 }
15
16 #[inline(always)]
18 fn alpha(&self) -> f64 {
19 self.color().alpha
20 }
21
22 fn mix(&self, value: f64) -> RGBAColor {
24 let (r, g, b) = self.rgb();
25 let a = self.alpha() * value;
26 RGBAColor(r, g, b, a)
27 }
28
29 fn to_rgba(&self) -> RGBAColor {
31 let (r, g, b) = self.rgb();
32 let a = self.alpha();
33 RGBAColor(r, g, b, a)
34 }
35
36 fn filled(&self) -> ShapeStyle
38 where
39 Self: Sized,
40 {
41 Into::<ShapeStyle>::into(self).filled()
42 }
43
44 fn stroke_width(&self, width: u32) -> ShapeStyle
46 where
47 Self: Sized,
48 {
49 Into::<ShapeStyle>::into(self).stroke_width(width)
50 }
51}
52
53#[derive(Clone, PartialEq, Debug)]
56pub struct RGBAColor(pub(crate) u8, pub(crate) u8, pub(crate) u8, pub(crate) f64);
57
58impl BackendStyle for RGBAColor {
59 #[inline(always)]
60 fn color(&self) -> BackendColor {
61 BackendColor {
62 rgb: (self.0, self.1, self.2),
63 alpha: self.3,
64 }
65 }
66}
67impl Color for RGBAColor {}
68
69pub struct PaletteColor<P: Palette>(usize, PhantomData<P>);
71
72impl<P: Palette> PaletteColor<P> {
73 pub fn pick(idx: usize) -> PaletteColor<P> {
75 PaletteColor(idx % P::COLORS.len(), PhantomData)
76 }
77}
78
79impl<P: Palette> BackendStyle for PaletteColor<P> {
80 #[inline(always)]
81 fn color(&self) -> BackendColor {
82 BackendColor {
83 rgb: P::COLORS[self.0],
84 alpha: 1.0,
85 }
86 }
87}
88
89impl<P: Palette> Color for PaletteColor<P> {}
90
91#[derive(Debug)]
93pub struct RGBColor(pub u8, pub u8, pub u8);
94
95impl BackendStyle for RGBColor {
96 #[inline(always)]
97 fn color(&self) -> BackendColor {
98 BackendColor {
99 rgb: (self.0, self.1, self.2),
100 alpha: 1.0,
101 }
102 }
103}
104
105impl Color for RGBColor {}
106
107pub struct HSLColor(pub f64, pub f64, pub f64);
109
110impl BackendStyle for HSLColor {
111 #[inline(always)]
112 #[allow(clippy::many_single_char_names)]
113 fn color(&self) -> BackendColor {
114 let (h, s, l) = (
115 self.0.min(1.0).max(0.0),
116 self.1.min(1.0).max(0.0),
117 self.2.min(1.0).max(0.0),
118 );
119
120 if s == 0.0 {
121 let value = (l * 255.0).round() as u8;
122 return BackendColor {
123 rgb: (value, value, value),
124 alpha: 1.0,
125 };
126 }
127
128 let q = if l < 0.5 {
129 l * (1.0 + s)
130 } else {
131 l + s - l * s
132 };
133 let p = 2.0 * l - q;
134
135 let cvt = |mut t| {
136 if t < 0.0 {
137 t += 1.0;
138 }
139 if t > 1.0 {
140 t -= 1.0;
141 }
142 let value = if t < 1.0 / 6.0 {
143 p + (q - p) * 6.0 * t
144 } else if t < 1.0 / 2.0 {
145 q
146 } else if t < 2.0 / 3.0 {
147 p + (q - p) * (2.0 / 3.0 - t) * 6.0
148 } else {
149 p
150 };
151 (value * 255.0).round() as u8
152 };
153
154 BackendColor {
155 rgb: (cvt(h + 1.0 / 3.0), cvt(h), cvt(h - 1.0 / 3.0)),
156 alpha: 1.0,
157 }
158 }
159}
160
161impl Color for HSLColor {}