bdf2/
glyph.rs

1use crate::{Bitmap, BoundingBox, Direction};
2use std::ops::{Deref, DerefMut};
3
4/// A font glyph.
5#[derive(Clone, Debug)]
6pub struct Glyph {
7    name: Option<String>,
8    codepoint: Option<char>,
9
10    direction: Direction,
11
12    scalable_width: Option<(u32, u32)>,
13    device_width: Option<(u32, u32)>,
14
15    alternate_scalable_width: Option<(u32, u32)>,
16    alternate_device_width: Option<(u32, u32)>,
17
18    vector: Option<(u32, u32)>,
19
20    bounds: Option<BoundingBox>,
21    map: Bitmap,
22}
23
24impl Default for Glyph {
25    #[inline]
26    fn default() -> Self {
27        Glyph {
28            name: None,
29            codepoint: None,
30
31            direction: Default::default(),
32
33            scalable_width: None,
34            device_width: None,
35
36            alternate_scalable_width: None,
37            alternate_device_width: None,
38
39            vector: None,
40
41            bounds: Default::default(),
42            map: Default::default(),
43        }
44    }
45}
46
47impl Glyph {
48    /// Creates a new glyph with the given name and codepoint.
49    #[inline]
50    pub fn new<T: Into<String>>(name: T, codepoint: char) -> Self {
51        Glyph {
52            name: Some(name.into()),
53            codepoint: Some(codepoint),
54
55            ..Default::default()
56        }
57    }
58
59    /// Validates the definition.
60    pub fn validate(&self) -> bool {
61        if self.name.is_none() {
62            return false;
63        }
64
65        if self.codepoint.is_none() {
66            return false;
67        }
68
69        if self.bounds.is_none() {
70            return false;
71        }
72
73        if self.direction == Direction::Default {
74            if self.alternate_scalable_width.is_some() {
75                return false;
76            }
77
78            if self.alternate_device_width.is_some() {
79                return false;
80            }
81        } else {
82            if self.alternate_scalable_width.is_none() {
83                return false;
84            }
85
86            if self.alternate_device_width.is_none() {
87                return false;
88            }
89        }
90
91        true
92    }
93
94    /// Gets the name.
95    #[inline]
96    pub fn name(&self) -> &str {
97        &self.name.as_ref().unwrap().as_ref()
98    }
99
100    /// Sets the name.
101    #[inline]
102    pub fn set_name<T: Into<String>>(&mut self, name: T) {
103        self.name = Some(name.into());
104    }
105
106    /// Gets the codepoint.
107    #[inline]
108    pub fn codepoint(&self) -> char {
109        self.codepoint.unwrap()
110    }
111
112    /// Sets the codepoint.
113    #[inline]
114    pub fn set_codepoint(&mut self, codepoint: char) {
115        self.codepoint = Some(codepoint);
116    }
117
118    /// Gets the direction.
119    #[inline]
120    pub fn direction(&self) -> Direction {
121        self.direction
122    }
123
124    /// Sets the direction.
125    #[inline]
126    pub fn set_direction(&mut self, direction: Direction) {
127        self.direction = direction;
128    }
129
130    /// Gets the scalable width.
131    #[inline]
132    pub fn scalable_width(&self) -> Option<&(u32, u32)> {
133        self.scalable_width.as_ref()
134    }
135
136    /// Sets the scalable width.
137    #[inline]
138    pub fn set_scalable_width(&mut self, value: Option<(u32, u32)>) {
139        self.scalable_width = value;
140    }
141
142    /// Gets the device width.
143    #[inline]
144    pub fn device_width(&self) -> Option<&(u32, u32)> {
145        self.device_width.as_ref()
146    }
147
148    /// Sets the device width.
149    #[inline]
150    pub fn set_device_width(&mut self, value: Option<(u32, u32)>) {
151        self.device_width = value;
152    }
153
154    /// Gets the alternate scalable width.
155    #[inline]
156    pub fn alternate_scalable_width(&self) -> Option<&(u32, u32)> {
157        self.alternate_scalable_width.as_ref()
158    }
159
160    /// Sets the alternate scalable width.
161    #[inline]
162    pub fn set_alternate_scalable_width(&mut self, value: Option<(u32, u32)>) {
163        self.alternate_scalable_width = value;
164    }
165
166    /// Gets the alternate device width.
167    #[inline]
168    pub fn alternate_device_width(&self) -> Option<&(u32, u32)> {
169        self.alternate_device_width.as_ref()
170    }
171
172    /// Sets the alternate device width.
173    #[inline]
174    pub fn set_alternate_device_width(&mut self, value: Option<(u32, u32)>) {
175        self.alternate_device_width = value;
176    }
177
178    /// Gets the offset vector.
179    #[inline]
180    pub fn vector(&self) -> Option<&(u32, u32)> {
181        self.vector.as_ref()
182    }
183
184    /// Sets the offset vector.
185    #[inline]
186    pub fn set_vector(&mut self, value: Option<(u32, u32)>) {
187        self.vector = value;
188    }
189
190    /// Gets the bounds.
191    #[inline]
192    pub fn bounds(&self) -> &BoundingBox {
193        self.bounds.as_ref().unwrap()
194    }
195
196    /// Sets the bounds.
197    #[inline]
198    pub fn set_bounds(&mut self, bounds: BoundingBox) {
199        self.bounds = Some(bounds);
200    }
201
202    /// Gets the bitmap.
203    #[inline]
204    pub fn map(&self) -> &Bitmap {
205        &self.map
206    }
207
208    /// Sets the bitmap.
209    #[inline]
210    pub fn set_map(&mut self, map: Bitmap) {
211        self.map = map;
212    }
213
214    /// Create an iterator over the pixels which will yield `((x, y), value)`.
215    #[inline]
216    pub fn pixels(&self) -> PixelIter {
217        PixelIter {
218            x: 0,
219            y: 0,
220
221            map: &self.map,
222        }
223    }
224}
225
226impl Deref for Glyph {
227    type Target = Bitmap;
228
229    #[inline]
230    fn deref(&self) -> &Bitmap {
231        &self.map
232    }
233}
234
235impl DerefMut for Glyph {
236    #[inline]
237    fn deref_mut(&mut self) -> &mut Bitmap {
238        &mut self.map
239    }
240}
241
242pub struct PixelIter<'a> {
243    x: u32,
244    y: u32,
245
246    map: &'a Bitmap,
247}
248
249impl<'a> Iterator for PixelIter<'a> {
250    type Item = ((u32, u32), bool);
251
252    #[inline]
253    fn next(&mut self) -> Option<<Self as Iterator>::Item> {
254        if self.x >= self.map.width() {
255            self.x = 0;
256            self.y += 1;
257        }
258
259        if self.y >= self.map.height() {
260            return None;
261        }
262
263        let x = self.x;
264        let y = self.y;
265
266        self.x += 1;
267
268        Some(((x, y), self.map.get(x, y)))
269    }
270
271    #[inline]
272    fn size_hint(&self) -> (usize, Option<usize>) {
273        let width = self.map.width();
274        let height = self.map.height();
275        let current = (self.y * height) + self.x;
276
277        (
278            current as usize,
279            Some(((width * height) - current) as usize),
280        )
281    }
282}
283
284impl<'a> ExactSizeIterator for PixelIter<'a> {}