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