Skip to main content

font_types/
glyph_id.rs

1//! Glyph Identifiers.
2//!
3//! Although these are treated as integers in the spec, we choose to represent
4//! them as distinct types.
5
6use crate::Uint24;
7
8/// A 16-bit glyph identifier.
9#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
10#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
11#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
12#[repr(transparent)]
13pub struct GlyphId16(u16);
14
15impl GlyphId16 {
16    /// The identifier reserved for unknown glyphs
17    pub const NOTDEF: GlyphId16 = GlyphId16(0);
18
19    /// Construct a new `GlyphId16`.
20    pub const fn new(raw: u16) -> Self {
21        GlyphId16(raw)
22    }
23
24    /// The identifier as a u16.
25    pub const fn to_u16(self) -> u16 {
26        self.0
27    }
28
29    /// The identifier as a u32.
30    pub const fn to_u32(self) -> u32 {
31        self.0 as u32
32    }
33
34    pub const fn to_be_bytes(self) -> [u8; 2] {
35        self.0.to_be_bytes()
36    }
37}
38
39impl Default for GlyphId16 {
40    fn default() -> Self {
41        GlyphId16::NOTDEF
42    }
43}
44
45impl From<u16> for GlyphId16 {
46    fn from(value: u16) -> Self {
47        Self(value)
48    }
49}
50
51impl From<GlyphId16> for usize {
52    fn from(value: GlyphId16) -> Self {
53        value.0 as usize
54    }
55}
56
57impl std::fmt::Display for GlyphId16 {
58    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
59        write!(f, "GID_{}", self.0)
60    }
61}
62
63impl From<GlyphId16> for u32 {
64    fn from(value: GlyphId16) -> u32 {
65        value.to_u32()
66    }
67}
68
69crate::newtype_scalar!(GlyphId16, [u8; 2]);
70
71/// A 24-bit glyph identifier.
72#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
73#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
74#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
75#[repr(transparent)]
76pub struct GlyphId24(Uint24);
77
78impl GlyphId24 {
79    /// The identifier reserved for unknown glyphs
80    pub const NOTDEF: GlyphId24 = GlyphId24(Uint24::MIN);
81
82    /// Construct a new `GlyphId24`, saturating on overflow.
83    pub const fn new(raw: u32) -> Self {
84        GlyphId24(Uint24::new(raw))
85    }
86
87    /// Construct a new `GlyphId24`, returning `None` on overflow.
88    pub const fn checked_new(raw: u32) -> Option<Self> {
89        match Uint24::checked_new(raw) {
90            Some(raw) => Some(GlyphId24(raw)),
91            None => None,
92        }
93    }
94
95    /// The identifier as a u32.
96    pub const fn to_u32(self) -> u32 {
97        self.0.to_u32()
98    }
99
100    pub const fn to_be_bytes(self) -> [u8; 3] {
101        self.0.to_be_bytes()
102    }
103
104    pub const fn from_be_bytes(bytes: [u8; 3]) -> Self {
105        GlyphId24(Uint24::from_be_bytes(bytes))
106    }
107}
108
109impl Default for GlyphId24 {
110    fn default() -> Self {
111        GlyphId24::NOTDEF
112    }
113}
114
115impl From<GlyphId24> for usize {
116    fn from(value: GlyphId24) -> Self {
117        value.to_u32() as usize
118    }
119}
120
121impl std::fmt::Display for GlyphId24 {
122    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
123        write!(f, "GID_{}", self.to_u32())
124    }
125}
126
127impl From<GlyphId24> for u32 {
128    fn from(value: GlyphId24) -> u32 {
129        value.to_u32()
130    }
131}
132
133crate::newtype_scalar!(GlyphId24, [u8; 3]);
134
135/// A 32-bit glyph identifier.
136#[derive(Clone, Copy, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)]
137#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
138#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
139#[repr(transparent)]
140pub struct GlyphId(u32);
141
142impl GlyphId {
143    /// The identifier reserved for unknown glyphs.
144    pub const NOTDEF: GlyphId = GlyphId(0);
145
146    /// Construct a new `GlyphId`.
147    pub const fn new(raw: u32) -> Self {
148        Self(raw)
149    }
150
151    /// The identifier as a u32.
152    pub const fn to_u32(self) -> u32 {
153        self.0
154    }
155}
156
157impl Default for GlyphId {
158    fn default() -> Self {
159        GlyphId::NOTDEF
160    }
161}
162
163impl From<u16> for GlyphId {
164    fn from(value: u16) -> Self {
165        Self(value as u32)
166    }
167}
168
169impl From<u32> for GlyphId {
170    fn from(value: u32) -> Self {
171        Self(value)
172    }
173}
174
175impl std::fmt::Display for GlyphId {
176    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
177        write!(f, "GID_{}", self.0)
178    }
179}
180
181impl From<GlyphId> for u32 {
182    fn from(value: GlyphId) -> u32 {
183        value.to_u32()
184    }
185}
186
187impl From<GlyphId16> for GlyphId {
188    fn from(value: GlyphId16) -> GlyphId {
189        Self(value.to_u32())
190    }
191}
192
193impl From<GlyphId24> for GlyphId {
194    fn from(value: GlyphId24) -> GlyphId {
195        Self(value.to_u32())
196    }
197}
198
199impl PartialEq<GlyphId16> for GlyphId {
200    fn eq(&self, other: &GlyphId16) -> bool {
201        self.0 == other.0 as u32
202    }
203}
204
205impl PartialOrd<GlyphId16> for GlyphId {
206    fn partial_cmp(&self, other: &GlyphId16) -> Option<core::cmp::Ordering> {
207        Some(self.0.cmp(&(other.0 as u32)))
208    }
209}
210
211impl PartialEq<GlyphId> for GlyphId16 {
212    fn eq(&self, other: &GlyphId) -> bool {
213        self.0 as u32 == other.0
214    }
215}
216
217impl PartialOrd<GlyphId> for GlyphId16 {
218    fn partial_cmp(&self, other: &GlyphId) -> Option<core::cmp::Ordering> {
219        Some((self.0 as u32).cmp(&other.0))
220    }
221}
222
223impl TryFrom<GlyphId> for GlyphId16 {
224    type Error = TryFromGlyphIdError;
225
226    fn try_from(value: GlyphId) -> Result<Self, Self::Error> {
227        Ok(Self(
228            value
229                .0
230                .try_into()
231                .map_err(|_| TryFromGlyphIdError(value.0))?,
232        ))
233    }
234}
235
236impl TryFrom<GlyphId> for GlyphId24 {
237    type Error = TryFromGlyphIdError;
238
239    fn try_from(value: GlyphId) -> Result<Self, Self::Error> {
240        Self::checked_new(value.0).ok_or(TryFromGlyphIdError(value.0))
241    }
242}
243
244/// The error type returned when a glyph identifier conversion fails.
245#[derive(Debug)]
246pub struct TryFromGlyphIdError(u32);
247
248impl core::fmt::Display for TryFromGlyphIdError {
249    fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
250        write!(f, "glyph identifier {} too large for conversion", self.0)
251    }
252}
253
254#[cfg(feature = "std")]
255impl std::error::Error for TryFromGlyphIdError {}