• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 use super::color::Color;
2 use super::font::{FontDesc, FontError, FontFamily, FontStyle, FontTransform};
3 use super::size::{HasDimension, SizeDesc};
4 use super::BLACK;
5 pub use plotters_backend::text_anchor;
6 use plotters_backend::{BackendColor, BackendCoord, BackendStyle, BackendTextStyle};
7 
8 /// Style of a text
9 #[derive(Clone)]
10 pub struct TextStyle<'a> {
11     /// The font description
12     pub font: FontDesc<'a>,
13     /// The text color
14     pub color: BackendColor,
15     /// The anchor point position
16     pub pos: text_anchor::Pos,
17 }
18 
19 pub trait IntoTextStyle<'a> {
into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>20     fn into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>;
21 }
22 
23 impl<'a> IntoTextStyle<'a> for FontDesc<'a> {
into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a>24     fn into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a> {
25         self.into()
26     }
27 }
28 
29 impl<'a> IntoTextStyle<'a> for TextStyle<'a> {
into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a>30     fn into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a> {
31         self
32     }
33 }
34 
35 impl<'a> IntoTextStyle<'a> for FontFamily<'a> {
into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a>36     fn into_text_style<P: HasDimension>(self, _: &P) -> TextStyle<'a> {
37         self.into()
38     }
39 }
40 
41 impl<'a, T: SizeDesc> IntoTextStyle<'a> for (&'a str, T) {
into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>42     fn into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a> {
43         (self.0, self.1.in_pixels(parent)).into()
44     }
45 }
46 
47 impl<'a, T: SizeDesc> IntoTextStyle<'a> for (FontFamily<'a>, T) {
into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>48     fn into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a> {
49         (self.0, self.1.in_pixels(parent)).into()
50     }
51 }
52 
53 impl<'a, T: SizeDesc> IntoTextStyle<'a> for (&'a str, T, FontStyle) {
into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>54     fn into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a> {
55         Into::<FontDesc>::into((self.0, self.1.in_pixels(parent), self.2)).into()
56     }
57 }
58 
59 impl<'a, T: SizeDesc> IntoTextStyle<'a> for (FontFamily<'a>, T, FontStyle) {
into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a>60     fn into_text_style<P: HasDimension>(self, parent: &P) -> TextStyle<'a> {
61         Into::<FontDesc>::into((self.0, self.1.in_pixels(parent), self.2)).into()
62     }
63 }
64 
65 impl<'a> TextStyle<'a> {
66     /// Sets the color of the style.
67     ///
68     /// - `color`: The required color
69     /// - **returns** The up-to-dated text style
70     ///
71     /// ```rust
72     /// use plotters::prelude::*;
73     ///
74     /// let style = TextStyle::from(("sans-serif", 20).into_font()).color(&RED);
75     /// ```
color<C: Color>(&self, color: &'a C) -> Self76     pub fn color<C: Color>(&self, color: &'a C) -> Self {
77         Self {
78             font: self.font.clone(),
79             color: color.color(),
80             pos: self.pos,
81         }
82     }
83 
84     /// Sets the font transformation of the style.
85     ///
86     /// - `trans`: The required transformation
87     /// - **returns** The up-to-dated text style
88     ///
89     /// ```rust
90     /// use plotters::prelude::*;
91     ///
92     /// let style = TextStyle::from(("sans-serif", 20).into_font()).transform(FontTransform::Rotate90);
93     /// ```
transform(&self, trans: FontTransform) -> Self94     pub fn transform(&self, trans: FontTransform) -> Self {
95         Self {
96             font: self.font.clone().transform(trans),
97             color: self.color,
98             pos: self.pos,
99         }
100     }
101 
102     /// Sets the anchor position.
103     ///
104     /// - `pos`: The required anchor position
105     /// - **returns** The up-to-dated text style
106     ///
107     /// ```rust
108     /// use plotters::prelude::*;
109     /// use plotters::style::text_anchor::{Pos, HPos, VPos};
110     ///
111     /// let pos = Pos::new(HPos::Left, VPos::Top);
112     /// let style = TextStyle::from(("sans-serif", 20).into_font()).pos(pos);
113     /// ```
pos(&self, pos: text_anchor::Pos) -> Self114     pub fn pos(&self, pos: text_anchor::Pos) -> Self {
115         Self {
116             font: self.font.clone(),
117             color: self.color,
118             pos,
119         }
120     }
121 }
122 
123 /// Make sure that we are able to automatically copy the `TextStyle`
124 impl<'a, 'b: 'a> Into<TextStyle<'a>> for &'b TextStyle<'a> {
into(self) -> TextStyle<'a>125     fn into(self) -> TextStyle<'a> {
126         self.clone()
127     }
128 }
129 
130 impl<'a, T: Into<FontDesc<'a>>> From<T> for TextStyle<'a> {
from(font: T) -> Self131     fn from(font: T) -> Self {
132         Self {
133             font: font.into(),
134             color: BLACK.color(),
135             pos: text_anchor::Pos::default(),
136         }
137     }
138 }
139 
140 impl<'a> BackendTextStyle for TextStyle<'a> {
141     type FontError = FontError;
color(&self) -> BackendColor142     fn color(&self) -> BackendColor {
143         self.color.color()
144     }
145 
size(&self) -> f64146     fn size(&self) -> f64 {
147         self.font.get_size()
148     }
149 
transform(&self) -> FontTransform150     fn transform(&self) -> FontTransform {
151         self.font.get_transform()
152     }
153 
style(&self) -> FontStyle154     fn style(&self) -> FontStyle {
155         self.font.get_style()
156     }
157 
158     #[allow(clippy::type_complexity)]
layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>159     fn layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError> {
160         self.font.layout_box(text)
161     }
162 
anchor(&self) -> text_anchor::Pos163     fn anchor(&self) -> text_anchor::Pos {
164         self.pos
165     }
166 
family(&self) -> FontFamily167     fn family(&self) -> FontFamily {
168         self.font.get_family()
169     }
170 
draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>( &self, text: &str, pos: BackendCoord, mut draw: DrawFunc, ) -> Result<Result<(), E>, Self::FontError>171     fn draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>(
172         &self,
173         text: &str,
174         pos: BackendCoord,
175         mut draw: DrawFunc,
176     ) -> Result<Result<(), E>, Self::FontError> {
177         let color = self.color.color();
178         self.font.draw(text, pos, move |x, y, a| {
179             let mix_color = color.mix(a as f64);
180             draw(x, y, mix_color)
181         })
182     }
183 }
184