bdf_reader/
font.rs

1use crate::Bitmap;
2use bit_vec::BitVec;
3use std::{
4	borrow::Borrow,
5	cmp::Ordering,
6	collections::{BTreeSet, HashMap},
7	fmt::{self, Debug, Display, Formatter}
8};
9
10#[derive(Clone, Copy, Debug, Eq, PartialEq)]
11pub struct BoundingBox {
12	pub width: u32,
13	pub height: u32,
14	pub offset_x: i32,
15	pub offset_y: i32
16}
17
18#[derive(Clone, Copy, Debug, Eq, PartialEq)]
19pub struct Size {
20	pub pt: u32,
21	pub xres: u32,
22	pub yres: u32
23}
24
25#[derive(Clone)]
26pub enum Value {
27	Integer(i32),
28	String(String)
29}
30
31impl Debug for Value {
32	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
33		match self {
34			Self::Integer(i) => write!(f, "{i}"),
35			Self::String(str) => write!(f, "{str:?}")
36		}
37	}
38}
39
40impl Display for Value {
41	fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
42		match self {
43			Self::Integer(i) => write!(f, "{i}"),
44			Self::String(str) => write!(f, "{str}")
45		}
46	}
47}
48
49#[derive(Clone, Debug)]
50pub struct Glyph {
51	pub(crate) name: String,
52	pub(crate) encoding: u32,
53	pub(crate) swidth: Option<(f64, f64)>,
54	pub(crate) dwidth: Option<(f64, f64)>,
55	pub(crate) bbox: BoundingBox,
56	pub(crate) bitmap: Vec<BitVec>
57}
58
59impl Glyph {
60	/// Get the name of this glyph as specified in the font.
61	pub fn name(&self) -> &str {
62		&self.name
63	}
64
65	/// Get the encoding value of this glyph.
66	pub fn encoding(&self) -> u32 {
67		self.encoding
68	}
69
70	/// Get the space width of this glyph.
71	pub fn swidth(&self) -> Option<(f64, f64)> {
72		self.swidth
73	}
74
75	/// Get the device width of this glyph.
76	pub fn dwidth(&self) -> Option<(f64, f64)> {
77		self.dwidth
78	}
79
80	/// Get the bounding box of this glyph.
81	pub fn bounding_box(&self) -> BoundingBox {
82		self.bbox
83	}
84
85	/// Get the bitmap of this glyph.
86	pub fn bitmap(&self) -> Bitmap<'_> {
87		Bitmap {
88			data: &self.bitmap,
89			bbox: self.bbox
90		}
91	}
92}
93
94/// A glyph wrapper that can be compared by its encoding.
95pub(crate) struct GlyphWrapper(Glyph);
96
97impl From<Glyph> for GlyphWrapper {
98	fn from(glyph: Glyph) -> Self {
99		Self(glyph)
100	}
101}
102
103impl Borrow<u32> for GlyphWrapper {
104	fn borrow(&self) -> &u32 {
105		&self.0.encoding
106	}
107}
108
109impl PartialEq for GlyphWrapper {
110	fn eq(&self, other: &Self) -> bool {
111		self.0.encoding == other.0.encoding
112	}
113}
114
115impl Eq for GlyphWrapper {}
116
117impl PartialEq<u32> for GlyphWrapper {
118	fn eq(&self, other: &u32) -> bool {
119		self.0.encoding == *other
120	}
121}
122
123impl PartialOrd for GlyphWrapper {
124	fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
125		Some(self.cmp(other))
126	}
127}
128
129impl Ord for GlyphWrapper {
130	fn cmp(&self, other: &Self) -> Ordering {
131		self.0.encoding.cmp(&other.0.encoding)
132	}
133}
134
135/// A trait to help use u32 and char as glyph index.
136pub trait GlyphIdx {
137	fn encoding(self) -> u32;
138}
139
140impl GlyphIdx for u32 {
141	fn encoding(self) -> u32 {
142		self
143	}
144}
145
146impl GlyphIdx for char {
147	fn encoding(self) -> u32 {
148		self as _
149	}
150}
151
152pub struct Font {
153	pub(crate) version: Option<i32>,
154	pub(crate) name: String,
155	pub(crate) bbox: BoundingBox,
156	pub(crate) size: Size,
157	pub(crate) properties: HashMap<String, Value>,
158
159	pub(crate) glyphs: BTreeSet<GlyphWrapper>
160}
161
162impl Font {
163	/// Get the content version of the font.
164	pub fn version(&self) -> Option<i32> {
165		self.version
166	}
167
168	/// Get the name of the font.
169	pub fn name(&self) -> &str {
170		&self.name
171	}
172
173	/// Get the default bounding box for glyphs.
174	pub fn bounding_box(&self) -> BoundingBox {
175		self.bbox
176	}
177
178	/// Get the size of the font.
179	pub fn size(&self) -> Size {
180		self.size
181	}
182
183	/// Get a property of the font.
184	pub fn property(&self, key: &str) -> Option<&Value> {
185		self.properties.get(key)
186	}
187
188	/// Get an iterator over all glyphs of the font.
189	pub fn glyphs(&self) -> impl IntoIterator<Item = &Glyph> {
190		self.glyphs.iter().map(|gw| &gw.0)
191	}
192
193	/// Get the glyph for this character, if contained in the font.
194	pub fn glyph<I: GlyphIdx>(&self, ch: I) -> Option<&Glyph> {
195		self.glyphs.get(&ch.encoding()).map(|gw| &gw.0)
196	}
197}