bear_lib_terminal/terminal/config/
font.rs

1//! Module containing font changing tools.
2//!
3//! # Examples
4//! The following from [the official documentation](http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management):
5//!
6//! ```text
7//! font: UbuntuMono-R.ttf, size=12;
8//! 0x5E: curcumflex.png;
9//! 0xE000: tileset.png, size=16x16, spacing=2x1;
10//! ```
11//!
12//! Is equivalent to
13//!
14//! ```
15//! use bear_lib_terminal::terminal;
16//! use bear_lib_terminal::terminal::config::font;
17//! use bear_lib_terminal::geometry::Size;
18//! # assert!({let result =
19//! terminal::set(font::true_type(font::Origin::Root, "UbuntuMono-R.ttf", Size::new(0, 12)));
20//! # result}); assert!({let result =
21//! terminal::set(font::bitmap(font::Origin::Offset('^'), "circumflex.png"));
22//! # result}); assert!({let result =
23//! terminal::set(font::bitmap(font::Origin::Offset('\u{E000}'), "tileset.png").size(Size::new(16, 16)).spacing(Size::new(2, 1)));
24//! # result});
25//! ```
26
27
28use std::fmt;
29use std::path::Path;
30use std::borrow::Cow;
31use geometry::Size;
32use terminal::config::{ConfigPart, escape_config_string};
33
34
35/// Construct a bitmap font override segment repr.
36pub fn bitmap<T: AsRef<Path>>(origin: Origin, path: T) -> Bitmap {
37	Bitmap{
38		origin: origin,
39		path: path.as_ref().to_str().unwrap().to_string(),
40		size: None,
41		resize: None,
42		resize_filter: None,
43		resize_mode: None,
44		raw_size: None,
45		codepage: None,
46		align: None,
47		spacing: None,
48	}
49}
50
51/// Construct a TrueType font override segment repr.
52///
53/// If `title_size.width` is `0`, the resulting `size` prop will be `size=<title_size.width>` as opposed to `size=<title_size>`.
54pub fn true_type<T: AsRef<Path>>(origin: Origin, path: T, tile_size: Size) -> TrueType {
55	TrueType{
56		origin: origin,
57		path: path.as_ref().to_str().unwrap().to_string(),
58		size: tile_size,
59		size_reference: None,
60		mode: None,
61		codepage: None,
62		align: None,
63		spacing: None,
64	}
65}
66
67
68/// The origin for the font (the part before `:` in the config string).
69#[derive(Clone, Debug, Eq, PartialEq, Hash)]
70pub enum Origin {
71	/// `font`
72	Root,
73	/// `[name] font`
74	Named(Cow<'static, str>),
75	/// `0xNNNN`
76	Offset(char),
77}
78
79/// Rasterization mode for TrueType fonts.
80#[derive(Clone, Debug, Eq, PartialEq, Hash)]
81pub enum RasterizationMode {
82	Monochrome,
83	Normal,
84	/// Forces an opaque black background.
85	Lcd,
86}
87
88/// Resizing filter for bitmaps.
89#[derive(Clone, Debug, Eq, PartialEq, Hash)]
90pub enum ResizeFilter {
91	Nearest,
92	Bilinear,
93	Bicubic,
94}
95
96/// How to aspect-change when resizing a bitmap.
97#[derive(Clone, Debug, Eq, PartialEq, Hash)]
98pub enum ResizeMode {
99	Stretch,
100	Fit,
101	Crop,
102}
103
104/// Per-tileset tile alignment.
105#[derive(Clone, Debug, Eq, PartialEq, Hash)]
106pub enum Align {
107	Center,
108	TopLeft,
109	BottomLeft,
110	TopRight,
111	BottomRight,
112}
113
114// What's the format for this?
115// ref: http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management
116// pub enum Background {
117// 	Auto,
118// 	Color(Color),
119// }
120
121
122/// A bitmap font override segment repr, constructed with [`bitmap()`](fn.bitmap.html).
123///
124/// Refer to [the official documentation](http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management).
125#[derive(Clone, Debug, Eq, PartialEq, Hash)]
126pub struct Bitmap {
127	origin       : Origin,
128	path         : String,
129	size         : Option<Size>,
130	resize       : Option<Size>,
131	resize_filter: Option<ResizeFilter>,
132	resize_mode  : Option<ResizeMode>,
133	raw_size     : Option<Size>,
134	codepage     : Option<String>,
135	align        : Option<Align>,
136	spacing      : Option<Size>,
137//	transparent  : Option<Background>,
138}
139
140/// A TrueType font override segment repr, constructed with [`true_type()`](fn.true_type.html).
141///
142/// Refer to [the official documentation](http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management).
143#[derive(Clone, Debug, Eq, PartialEq, Hash)]
144pub struct TrueType {
145	origin        : Origin,
146	path          : String,
147	size          : Size,
148	size_reference: Option<char>,
149	mode          : Option<RasterizationMode>,
150	codepage      : Option<String>,
151	align         : Option<Align>,
152	spacing       : Option<Size>,
153}
154
155
156/// For all functions consult the corresponding attributes in
157/// [the official docs](http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management).
158impl Bitmap {
159	/// The size of a single tile in the tileset.
160	pub fn size         (mut self, size: Size)                  -> Self {self.size          = Some(size)         ; self}
161
162	/// The size to resize the image to.
163	pub fn resize       (mut self, resize: Size)                -> Self {self.resize        = Some(resize)       ; self}
164
165	/// How to resize the image.
166	///
167	/// Default: `ResizeFilter::Bilinear`.
168	pub fn resize_filter(mut self, resize_filter: ResizeFilter) -> Self {self.resize_filter = Some(resize_filter); self}
169
170	/// Resize aspect method.
171	///
172	/// Default: `ResizeMode::Stretch`.
173	pub fn resize_mode  (mut self, resize_mode: ResizeMode)     -> Self {self.resize_mode   = Some(resize_mode)  ; self}
174
175	/// Raw memory size, `size` if not specified.
176	pub fn raw_size     (mut self, raw_size: Size)              -> Self {self.raw_size      = Some(raw_size)     ; self}
177
178	/// Tileset's codepage.
179	///
180	/// Default: `"ascii"`.
181	pub fn codepage     (mut self, codepage: String)            -> Self {self.codepage      = Some(codepage)     ; self}
182
183	/// How tiles are to be aligned.
184	///
185	/// Default: `Align::Center`.
186	pub fn align        (mut self, align: Align)                -> Self {self.align         = Some(align)        ; self}
187
188	/// Tile alignment area \[cells\].
189	///
190	/// Default: `1x1`.
191	pub fn spacing      (mut self, spacing: Size)               -> Self {self.spacing       = Some(spacing)      ; self}
192}
193
194/// For all functions consult the corresponding attributes in
195/// [the official docs](http://foo.wyrd.name/en:bearlibterminal:reference:configuration#font_and_tileset_management).
196impl TrueType {
197	/// Character used for size probing.
198	///
199	/// Default: `'@'`.
200	pub fn size_reference(mut self, size_reference: char)    -> Self {self.size_reference = Some(size_reference); self}
201
202	/// Rasterization mode. Note: `RasterizationMode::Lcd` forces opaque black background.
203	///
204	/// Default: `RasterizationMode::Normal`.
205	pub fn mode          (mut self, mode: RasterizationMode) -> Self {self.mode           = Some(mode)          ; self}
206
207	/// Reverse codepage for loading symbols.
208	pub fn codepage      (mut self, codepage: String)        -> Self {self.codepage       = Some(codepage)      ; self}
209
210	/// How tiles are to be aligned.
211	///
212	/// Default: `Align::Center`.
213	pub fn align         (mut self, align: Align)            -> Self {self.align          = Some(align)         ; self}
214
215	/// Tile alignment area \[cells\].
216	///
217	/// Default: `1x1`.
218	pub fn spacing       (mut self, spacing: Size)           -> Self {self.spacing        = Some(spacing)       ; self}
219}
220
221
222impl ConfigPart for Bitmap {
223	fn to_config_str(&self) -> String {
224		format!("{}: {}{}{}{}{}{}{}{}{};", self.origin, escape_config_string(&self.path),
225			match self.size {
226				None           => "".to_string(),
227				Some(ref size) => format!(", size={}", size),
228			},
229			match self.resize {
230				None             => "".to_string(),
231				Some(ref resize) => format!(", resize={}", resize),
232			},
233			match self.resize_filter {
234				None                    => "".to_string(),
235				Some(ref resize_filter) => format!(", resize-filter={}", resize_filter),
236			},
237			match self.resize_mode {
238				None                  => "".to_string(),
239				Some(ref resize_mode) => format!(", resize-mode={}", resize_mode),
240			},
241			match self.raw_size {
242				None               => "".to_string(),
243				Some(ref raw_size) => format!(", raw-size={}", raw_size),
244			},
245			match self.codepage {
246				None               => "".to_string(),
247				Some(ref codepage) => format!(", codepage={}", escape_config_string(codepage)),
248			},
249			match self.align {
250				None            => "".to_string(),
251				Some(ref align) => format!(", align={}", align),
252			},
253			match self.spacing {
254				None              => "".to_string(),
255				Some(ref spacing) => format!(", spacing={}", spacing),
256			}
257		)
258	}
259}
260
261impl ConfigPart for TrueType {
262	fn to_config_str(&self) -> String {
263		format!("{}: {}, size={}{}{}{}{}{};", self.origin, escape_config_string(&self.path),
264			match self.size {
265				Size{width: 0, height} => format!("{}", height),
266				size                   => format!("{}", size),
267			},
268			match self.size_reference {
269				None                     => "".to_string(),
270				Some(ref size_reference) => format!(", size-reference=0x{:X}", *size_reference as i32),
271			},
272			match self.mode {
273				None           => "".to_string(),
274				Some(ref mode) => format!(", mode={}", mode),
275			},
276			match self.codepage {
277				None               => "".to_string(),
278				Some(ref codepage) => format!(", codepage={}", escape_config_string(codepage)),
279			},
280			match self.align {
281				None            => "".to_string(),
282				Some(ref align) => format!(", align={}", align),
283			},
284			match self.spacing {
285				None              => "".to_string(),
286				Some(ref spacing) => format!(", spacing={}", spacing),
287			}
288		)
289	}
290}
291
292
293impl fmt::Display for Origin {
294	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
295		match self {
296			&Origin::Root          => formatter.write_str("[font]"),
297			&Origin::Named(ref n)  => formatter.write_str(&*&format!("{} font", &n)),
298			&Origin::Offset(o)     => formatter.write_str(&*&format!("0x{:X}", o as i32)),
299		}
300	}
301}
302
303impl fmt::Display for RasterizationMode {
304	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
305		match self {
306			&RasterizationMode::Monochrome => formatter.write_str("monochrome"),
307			&RasterizationMode::Normal     => formatter.write_str("normal"),
308			&RasterizationMode::Lcd        => formatter.write_str("lcd"),
309		}
310	}
311}
312
313impl fmt::Display for ResizeFilter {
314	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
315		match self {
316			&ResizeFilter::Nearest  => formatter.write_str("nearest"),
317			&ResizeFilter::Bilinear => formatter.write_str("bilinear"),
318			&ResizeFilter::Bicubic  => formatter.write_str("bicubic"),
319		}
320	}
321}
322
323impl fmt::Display for ResizeMode {
324	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
325		match self {
326			&ResizeMode::Stretch => formatter.write_str("stretch"),
327			&ResizeMode::Fit     => formatter.write_str("fit"),
328			&ResizeMode::Crop    => formatter.write_str("crop"),
329		}
330	}
331}
332
333impl fmt::Display for Align {
334	fn fmt(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
335		match self {
336			&Align::Center      => formatter.write_str("center"),
337			&Align::TopLeft     => formatter.write_str("top-left"),
338			&Align::BottomLeft  => formatter.write_str("bottom-left"),
339			&Align::TopRight    => formatter.write_str("top-right"),
340			&Align::BottomRight => formatter.write_str("bottom-right"),
341		}
342	}
343}