plotters_unsable/style/font/
font_desc.rs1use super::{FontData, FontDataInternal};
2use crate::style::{Color, LayoutBox, TextStyle};
3
4use std::convert::From;
5
6pub type FontError = <FontDataInternal as FontData>::ErrorType;
8
9pub type FontResult<T> = Result<T, FontError>;
11
12#[derive(Clone)]
14pub enum FontTransform {
15 None,
16 Rotate90,
17 Rotate180,
18 Rotate270,
19}
20
21impl FontTransform {
22 pub fn offset(&self, layout: LayoutBox) -> (i32, i32) {
25 match self {
26 FontTransform::None => (0, 0),
27 FontTransform::Rotate90 => ((layout.1).1 - (layout.0).1, 0),
28 FontTransform::Rotate180 => ((layout.1).0 - (layout.0).0, (layout.1).1 - (layout.0).1),
29 FontTransform::Rotate270 => (0, (layout.1).0 - (layout.0).0),
30 }
31 }
32
33 pub fn transform(&self, x: i32, y: i32) -> (i32, i32) {
35 match self {
36 FontTransform::None => (x, y),
37 FontTransform::Rotate90 => (-y, x),
38 FontTransform::Rotate180 => (-x, -y),
39 FontTransform::Rotate270 => (y, -x),
40 }
41 }
42}
43
44pub struct FontDesc<'a> {
46 size: f64,
47 name: &'a str,
48 data: FontResult<FontDataInternal>,
49 transform: FontTransform,
50}
51
52impl<'a> From<&'a str> for FontDesc<'a> {
53 fn from(from: &'a str) -> FontDesc<'a> {
54 FontDesc::new(from, 1.0)
55 }
56}
57
58impl<'a, T: Into<f64>> From<(&'a str, T)> for FontDesc<'a> {
59 fn from((typeface, size): (&'a str, T)) -> FontDesc<'a> {
60 FontDesc::new(typeface, size.into())
61 }
62}
63
64pub trait IntoFont<'a> {
65 fn into_font(self) -> FontDesc<'a>;
66}
67
68impl<'a, T: Into<FontDesc<'a>>> IntoFont<'a> for T {
69 fn into_font(self) -> FontDesc<'a> {
70 self.into()
71 }
72}
73
74impl<'a> FontDesc<'a> {
75 pub fn new(typeface: &'a str, size: f64) -> Self {
77 Self {
78 size,
79 name: typeface,
80 data: FontDataInternal::new(typeface),
81 transform: FontTransform::None,
82 }
83 }
84
85 pub fn resize(&self, size: f64) -> FontDesc<'a> {
87 Self {
88 size,
89 name: self.name,
90 data: self.data.clone(),
91 transform: self.transform.clone(),
92 }
93 }
94
95 pub fn transform(&self, trans: FontTransform) -> Self {
97 Self {
98 size: self.size,
99 name: self.name,
100 data: self.data.clone(),
101 transform: trans,
102 }
103 }
104
105 pub fn get_transform(&self) -> FontTransform {
107 self.transform.clone()
108 }
109
110 pub fn color<C: Color>(&'a self, color: &'a C) -> TextStyle<'a> {
112 TextStyle { font: self, color }
113 }
114
115 pub fn get_name(&self) -> &'a str {
117 self.name
118 }
119
120 pub fn get_size(&self) -> f64 {
122 self.size
123 }
124
125 pub fn layout_box(&self, text: &str) -> FontResult<((i32, i32), (i32, i32))> {
127 match &self.data {
128 Ok(ref font) => font.estimate_layout(self.size, text),
129 Err(e) => Err(e.clone()),
130 }
131 }
132
133 pub fn box_size(&self, text: &str) -> FontResult<(u32, u32)> {
135 let ((min_x, min_y), (max_x, max_y)) = self.layout_box(text)?;
136 Ok(((max_x - min_x) as u32, (max_y - min_y) as u32))
137 }
138
139 pub fn draw<E, DrawFunc: FnMut(i32, i32, f32) -> Result<(), E>>(
141 &self,
142 text: &str,
143 (x, y): (i32, i32),
144 draw: DrawFunc,
145 ) -> FontResult<Result<(), E>> {
146 match &self.data {
147 Ok(ref font) => font.draw((x, y), self.size, text, self.get_transform(), draw),
148 Err(e) => Err(e.clone()),
149 }
150 }
151}