1use super::{FontData, FontDataInternal};
2use crate::style::text_anchor::Pos;
3use crate::style::{Color, TextStyle};
4
5use std::convert::From;
6
7pub use plotters_backend::{FontFamily, FontStyle, FontTransform};
8
9pub type FontError = <FontDataInternal as FontData>::ErrorType;
11
12pub type FontResult<T> = Result<T, FontError>;
14
15#[derive(Clone)]
17pub struct FontDesc<'a> {
18 size: f64,
19 family: FontFamily<'a>,
20 data: FontResult<FontDataInternal>,
21 transform: FontTransform,
22 style: FontStyle,
23}
24
25impl<'a> FontDesc<'a> {
26 pub fn new(family: FontFamily<'a>, size: f64, style: FontStyle) -> Self {
33 Self {
34 size,
35 family,
36 data: FontDataInternal::new(family, style),
37 transform: FontTransform::None,
38 style,
39 }
40 }
41
42 pub fn resize(&self, size: f64) -> Self {
47 Self {
48 size,
49 family: self.family,
50 data: self.data.clone(),
51 transform: self.transform.clone(),
52 style: self.style,
53 }
54 }
55
56 pub fn style(&self, style: FontStyle) -> Self {
61 Self {
62 size: self.size,
63 family: self.family,
64 data: self.data.clone(),
65 transform: self.transform.clone(),
66 style,
67 }
68 }
69
70 pub fn transform(&self, trans: FontTransform) -> Self {
75 Self {
76 size: self.size,
77 family: self.family,
78 data: self.data.clone(),
79 transform: trans,
80 style: self.style,
81 }
82 }
83
84 pub fn get_transform(&self) -> FontTransform {
86 self.transform.clone()
87 }
88
89 pub fn color<C: Color>(&self, color: &C) -> TextStyle<'a> {
91 TextStyle {
92 font: self.clone(),
93 color: color.to_backend_color(),
94 pos: Pos::default(),
95 }
96 }
97
98 pub fn get_family(&self) -> FontFamily {
99 self.family
100 }
101
102 pub fn get_name(&self) -> &str {
104 self.family.as_str()
105 }
106
107 pub fn get_style(&self) -> FontStyle {
109 self.style
110 }
111
112 pub fn get_size(&self) -> f64 {
114 self.size
115 }
116
117 pub fn layout_box(&self, text: &str) -> FontResult<((i32, i32), (i32, i32))> {
122 match &self.data {
123 Ok(ref font) => font.estimate_layout(self.size, text),
124 Err(e) => Err(e.clone()),
125 }
126 }
127
128 pub fn box_size(&self, text: &str) -> FontResult<(u32, u32)> {
132 let ((min_x, min_y), (max_x, max_y)) = self.layout_box(text)?;
133 let (w, h) = self.get_transform().transform(max_x - min_x, max_y - min_y);
134 Ok((w.abs() as u32, h.abs() as u32))
135 }
136
137 pub fn draw<E, DrawFunc: FnMut(i32, i32, f32) -> Result<(), E>>(
139 &self,
140 text: &str,
141 (x, y): (i32, i32),
142 draw: DrawFunc,
143 ) -> FontResult<Result<(), E>> {
144 match &self.data {
145 Ok(ref font) => font.draw((x, y), self.size, text, draw),
146 Err(e) => Err(e.clone()),
147 }
148 }
149}
150
151impl<'a> From<&'a str> for FontDesc<'a> {
152 fn from(from: &'a str) -> FontDesc<'a> {
153 FontDesc::new(from.into(), 12.0, FontStyle::Normal)
154 }
155}
156
157impl<'a> From<FontFamily<'a>> for FontDesc<'a> {
158 fn from(family: FontFamily<'a>) -> FontDesc<'a> {
159 FontDesc::new(family, 12.0, FontStyle::Normal)
160 }
161}
162
163impl<'a, T: Into<f64>> From<(FontFamily<'a>, T)> for FontDesc<'a> {
164 fn from((family, size): (FontFamily<'a>, T)) -> FontDesc<'a> {
165 FontDesc::new(family, size.into(), FontStyle::Normal)
166 }
167}
168
169impl<'a, T: Into<f64>> From<(&'a str, T)> for FontDesc<'a> {
170 fn from((typeface, size): (&'a str, T)) -> FontDesc<'a> {
171 FontDesc::new(typeface.into(), size.into(), FontStyle::Normal)
172 }
173}
174
175impl<'a, T: Into<f64>, S: Into<FontStyle>> From<(FontFamily<'a>, T, S)> for FontDesc<'a> {
176 fn from((family, size, style): (FontFamily<'a>, T, S)) -> FontDesc<'a> {
177 FontDesc::new(family, size.into(), style.into())
178 }
179}
180
181impl<'a, T: Into<f64>, S: Into<FontStyle>> From<(&'a str, T, S)> for FontDesc<'a> {
182 fn from((typeface, size, style): (&'a str, T, S)) -> FontDesc<'a> {
183 FontDesc::new(typeface.into(), size.into(), style.into())
184 }
185}
186
187pub trait IntoFont<'a> {
189 fn into_font(self) -> FontDesc<'a>;
191}
192
193impl<'a, T: Into<FontDesc<'a>>> IntoFont<'a> for T {
194 fn into_font(self) -> FontDesc<'a> {
195 self.into()
196 }
197}