1 use super::{BackendColor, BackendCoord}; 2 use std::error::Error; 3 4 /// Describes font family. 5 /// This can be either a specific font family name, such as "arial", 6 /// or a general font family class, such as "serif" and "sans-serif" 7 #[derive(Clone, Copy)] 8 pub enum FontFamily<'a> { 9 /// The system default serif font family 10 Serif, 11 /// The system default sans-serif font family 12 SansSerif, 13 /// The system default monospace font 14 Monospace, 15 /// A specific font family name 16 Name(&'a str), 17 } 18 19 impl<'a> FontFamily<'a> { 20 /// Make a CSS compatible string for the font family name. 21 /// This can be used as the value of `font-family` attribute in SVG. as_str(&self) -> &str22 pub fn as_str(&self) -> &str { 23 match self { 24 FontFamily::Serif => "serif", 25 FontFamily::SansSerif => "sans-serif", 26 FontFamily::Monospace => "monospace", 27 FontFamily::Name(face) => face, 28 } 29 } 30 } 31 32 impl<'a> From<&'a str> for FontFamily<'a> { from(from: &'a str) -> FontFamily<'a>33 fn from(from: &'a str) -> FontFamily<'a> { 34 match from.to_lowercase().as_str() { 35 "serif" => FontFamily::Serif, 36 "sans-serif" => FontFamily::SansSerif, 37 "monospace" => FontFamily::Monospace, 38 _ => FontFamily::Name(from), 39 } 40 } 41 } 42 43 /// Text anchor attributes are used to properly position the text. 44 /// 45 /// # Examples 46 /// 47 /// In the example below, the text anchor (X) position is `Pos::new(HPos::Right, VPos::Center)`. 48 /// ```text 49 /// ***** X 50 /// ``` 51 /// The position is always relative to the text regardless of its rotation. 52 /// In the example below, the text has style 53 /// `style.transform(FontTransform::Rotate90).pos(Pos::new(HPos::Center, VPos::Top))`. 54 /// ```text 55 /// * 56 /// * 57 /// * X 58 /// * 59 /// * 60 /// ``` 61 pub mod text_anchor { 62 /// The horizontal position of the anchor point relative to the text. 63 #[derive(Clone, Copy)] 64 pub enum HPos { 65 /// Anchor point is on the left side of the text 66 Left, 67 /// Anchor point is on the right side of the text 68 Right, 69 /// Anchor point is in the horizontal center of the text 70 Center, 71 } 72 73 /// The vertical position of the anchor point relative to the text. 74 #[derive(Clone, Copy)] 75 pub enum VPos { 76 /// Anchor point is on the top of the text 77 Top, 78 /// Anchor point is in the vertical center of the text 79 Center, 80 /// Anchor point is on the bottom of the text 81 Bottom, 82 } 83 84 /// The text anchor position. 85 #[derive(Clone, Copy)] 86 pub struct Pos { 87 /// The horizontal position of the anchor point 88 pub h_pos: HPos, 89 /// The vertical position of the anchor point 90 pub v_pos: VPos, 91 } 92 93 impl Pos { 94 /// Create a new text anchor position. 95 /// 96 /// - `h_pos`: The horizontal position of the anchor point 97 /// - `v_pos`: The vertical position of the anchor point 98 /// - **returns** The newly created text anchor position 99 /// 100 /// ```rust 101 /// use plotters_backend::text_anchor::{Pos, HPos, VPos}; 102 /// 103 /// let pos = Pos::new(HPos::Left, VPos::Top); 104 /// ``` new(h_pos: HPos, v_pos: VPos) -> Self105 pub fn new(h_pos: HPos, v_pos: VPos) -> Self { 106 Pos { h_pos, v_pos } 107 } 108 109 /// Create a default text anchor position (top left). 110 /// 111 /// - **returns** The default text anchor position 112 /// 113 /// ```rust 114 /// use plotters_backend::text_anchor::{Pos, HPos, VPos}; 115 /// 116 /// let pos = Pos::default(); 117 /// ``` default() -> Self118 pub fn default() -> Self { 119 Pos { 120 h_pos: HPos::Left, 121 v_pos: VPos::Top, 122 } 123 } 124 } 125 } 126 127 /// Specifying text transformations 128 #[derive(Clone)] 129 pub enum FontTransform { 130 /// Nothing to transform 131 None, 132 /// Rotating the text 90 degree clockwise 133 Rotate90, 134 /// Rotating the text 180 degree clockwise 135 Rotate180, 136 /// Rotating the text 270 degree clockwise 137 Rotate270, 138 } 139 140 impl FontTransform { 141 /// Transform the coordinate to perform the rotation 142 /// 143 /// - `x`: The x coordinate in pixels before transform 144 /// - `y`: The y coordinate in pixels before transform 145 /// - **returns**: The coordinate after transform transform(&self, x: i32, y: i32) -> (i32, i32)146 pub fn transform(&self, x: i32, y: i32) -> (i32, i32) { 147 match self { 148 FontTransform::None => (x, y), 149 FontTransform::Rotate90 => (-y, x), 150 FontTransform::Rotate180 => (-x, -y), 151 FontTransform::Rotate270 => (y, -x), 152 } 153 } 154 } 155 156 /// Describes the font style. Such as Italic, Oblique, etc. 157 #[derive(Clone, Copy)] 158 pub enum FontStyle { 159 /// The normal style 160 Normal, 161 /// The oblique style 162 Oblique, 163 /// The italic style 164 Italic, 165 /// The bold style 166 Bold, 167 } 168 169 impl FontStyle { 170 /// Convert the font style into a CSS compatible string which can be used in `font-style` attribute. as_str(&self) -> &str171 pub fn as_str(&self) -> &str { 172 match self { 173 FontStyle::Normal => "normal", 174 FontStyle::Italic => "italic", 175 FontStyle::Oblique => "oblique", 176 FontStyle::Bold => "bold", 177 } 178 } 179 } 180 181 impl<'a> From<&'a str> for FontStyle { from(from: &'a str) -> FontStyle182 fn from(from: &'a str) -> FontStyle { 183 match from.to_lowercase().as_str() { 184 "normal" => FontStyle::Normal, 185 "italic" => FontStyle::Italic, 186 "oblique" => FontStyle::Oblique, 187 "bold" => FontStyle::Bold, 188 _ => FontStyle::Normal, 189 } 190 } 191 } 192 193 /// The trait that abstracts a style of a text. 194 /// 195 /// This is used because the the backend crate have no knowledge about how 196 /// the text handling is implemented in plotters. 197 /// 198 /// But the backend still wants to know some information about the font, for 199 /// the backend doesn't handles text drawing, may want to call the `draw` method which 200 /// is implemented by the plotters main crate. While for the backend that handles the 201 /// text drawing, those font information provides instructions about how the text should be 202 /// rendered: color, size, slant, anchor, font, etc. 203 /// 204 /// This trait decouples the detailed implementaiton about the font and the backend code which 205 /// wants to perfome some operation on the font. 206 /// 207 pub trait BackendTextStyle { 208 /// The error type of this text style implementation 209 type FontError: Error + Sync + Send + 'static; 210 color(&self) -> BackendColor211 fn color(&self) -> BackendColor { 212 BackendColor { 213 alpha: 1.0, 214 rgb: (0, 0, 0), 215 } 216 } 217 size(&self) -> f64218 fn size(&self) -> f64 { 219 1.0 220 } 221 transform(&self) -> FontTransform222 fn transform(&self) -> FontTransform { 223 FontTransform::None 224 } 225 style(&self) -> FontStyle226 fn style(&self) -> FontStyle { 227 FontStyle::Normal 228 } 229 anchor(&self) -> text_anchor::Pos230 fn anchor(&self) -> text_anchor::Pos { 231 text_anchor::Pos::default() 232 } 233 family(&self) -> FontFamily234 fn family(&self) -> FontFamily; 235 layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>236 fn layout_box(&self, text: &str) -> Result<((i32, i32), (i32, i32)), Self::FontError>; 237 draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>( &self, text: &str, pos: BackendCoord, draw: DrawFunc, ) -> Result<Result<(), E>, Self::FontError>238 fn draw<E, DrawFunc: FnMut(i32, i32, BackendColor) -> Result<(), E>>( 239 &self, 240 text: &str, 241 pos: BackendCoord, 242 draw: DrawFunc, 243 ) -> Result<Result<(), E>, Self::FontError>; 244 } 245