font_types/
name_id.rs

1//! Name Identifiers
2//!
3//! Although these are treated as u16s in the spec, we choose to represent them
4//! as a distinct type.
5
6use core::fmt;
7
8/// Identifier for an informational string (or name).
9///
10/// A set of predefined identifiers exist for accessing names and other various metadata
11/// about the font and those are provided as associated constants on this type.
12///
13/// IDs 26 to 255, inclusive, are reserved for future standard names. IDs 256 to 32767,
14/// inclusive, are reserved for font-specific names such as those referenced by a font's
15/// layout features.
16///
17/// For more detail, see <https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-ids>
18#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
20#[cfg_attr(feature = "bytemuck", derive(bytemuck::AnyBitPattern))]
21#[repr(transparent)]
22pub struct NameId(u16);
23
24impl NameId {
25    /// Copyright notice.
26    pub const COPYRIGHT_NOTICE: Self = Self(0);
27
28    /// Font family name.
29    ///
30    /// The font family name is used in combination with font subfamily name (ID 2),
31    /// and should be shared among at most four fonts that differ only in weight or style (as described below).
32    pub const FAMILY_NAME: Self = Self(1);
33
34    /// Font subfamily name.
35    ///
36    /// The font subfamily name is used in combination with font family name (ID 1),
37    /// and distinguishes the fonts in a group with the same font family name. This should be used for style
38    /// and weight variants only (as described below).
39    pub const SUBFAMILY_NAME: Self = Self(2);
40
41    /// Unique font identifier.
42    pub const UNIQUE_ID: Self = Self(3);
43
44    /// Full font name that reflects all family and relevant subfamily descriptors.
45    ///
46    /// The full font name is generally a combination of IDs 1 and 2, or of IDs 16 and
47    /// 17, or a similar human-readable variant.
48    pub const FULL_NAME: Self = Self(4);
49
50    /// Version string.
51    ///
52    /// Should begin with the syntax “Version number.number” (upper case, lower case, or mixed,
53    /// with a space between “Version” and the number).
54    pub const VERSION_STRING: Self = Self(5);
55
56    /// PostScript name for the font.
57    ///
58    /// ID 6 specifies a string which is used to invoke a PostScript language font
59    /// that corresponds to this OpenType font. When translated to ASCII, the name string must be no longer than 63
60    /// characters and restricted to the printable ASCII subset, codes 33 to 126, except for the 10 characters '[', ']',
61    /// '(', ')', '{', '}', '<', '>', '/', '%'.
62    pub const POSTSCRIPT_NAME: Self = Self(6);
63
64    /// Trademark; this is used to save any trademark notice/information for this font.
65    ///
66    /// Such information should be based on legal advice. This is distinctly separate from the copyright.
67    pub const TRADEMARK: Self = Self(7);
68
69    /// Manufacturer name.
70    pub const MANUFACTURER: Self = Self(8);
71
72    /// Name of the designer of the typeface.
73    pub const DESIGNER: Self = Self(9);
74
75    /// Description of the typeface.
76    ///
77    /// Can contain revision information, usage recommendations, history, features, etc.
78    pub const DESCRIPTION: Self = Self(10);
79
80    /// URL of font vendor (with protocol, e.g., http://, ftp://).
81    ///
82    /// If a unique serial number is embedded in the URL, it can be used to register the font.
83    pub const VENDOR_URL: Self = Self(11);
84
85    /// URL of typeface designer (with protocol, e.g., http://, ftp://).
86    pub const DESIGNER_URL: Self = Self(12);
87
88    /// License description.
89    ///
90    /// A description of how the font may be legally used, or different example scenarios for licensed use.
91    /// This field should be written in plain language, not legalese.
92    pub const LICENSE_DESCRIPTION: Self = Self(13);
93
94    /// URL where additional licensing information can be found.
95    pub const LICENSE_URL: Self = Self(14);
96
97    /// Typographic family name.
98    ///
99    /// The typographic family grouping doesn't impose any constraints on the number of faces within it,
100    /// in contrast with the 4-style family grouping (ID 1), which is present both for historical reasons and to express style
101    /// linking groups.
102    pub const TYPOGRAPHIC_FAMILY_NAME: Self = Self(16);
103
104    /// Typographic subfamily name.
105    ///
106    /// This allows font designers to specify a subfamily name within the typographic family grouping.
107    /// This string must be unique within a particular typographic family.
108    pub const TYPOGRAPHIC_SUBFAMILY_NAME: Self = Self(17);
109
110    /// Compatible full (Macintosh only).
111    ///
112    /// On the Macintosh, the menu name is constructed using the FOND resource. This usually matches
113    /// the full name. If you want the name of the font to appear differently than the Full Name, you can insert the compatible full
114    /// name in ID 18.
115    pub const COMPATIBLE_FULL_NAME: Self = Self(18);
116
117    /// Sample text.
118    ///
119    /// This can be the font name, or any other text that the designer thinks is the best sample to display the font in.
120    pub const SAMPLE_TEXT: Self = Self(19);
121
122    /// PostScript CID findfont name.
123    ///
124    /// Its presence in a font means that the ID 6 holds a PostScript font name that is meant to be
125    /// used with the “composefont” invocation in order to invoke the font in a PostScript interpreter.
126    pub const POSTSCRIPT_CID_NAME: Self = Self(20);
127
128    /// WWS family name.
129    ///
130    /// Used to provide a WWS-conformant family name in case the entries for IDs 16 and 17 do not conform to the WWS model.
131    pub const WWS_FAMILY_NAME: Self = Self(21);
132
133    /// WWS subfamily name.
134    ///
135    /// Used in conjunction with ID 21, this ID provides a WWS-conformant subfamily name (reflecting only weight, width
136    /// and slope attributes) in case the entries for IDs 16 and 17 do not conform to the WWS model.
137    pub const WWS_SUBFAMILY_NAME: Self = Self(22);
138
139    /// Light background palette.
140    ///
141    /// This ID, if used in the CPAL table's Palette Labels Array, specifies that the corresponding color palette in
142    /// the CPAL table is appropriate to use with the font when displaying it on a light background such as white.
143    pub const LIGHT_BACKGROUND_PALETTE: Self = Self(23);
144
145    /// Dark background palette.
146    ///
147    /// This ID, if used in the CPAL table's Palette Labels Array, specifies that the corresponding color palette in
148    /// the CPAL table is appropriate to use with the font when displaying it on a dark background such as black.
149    pub const DARK_BACKGROUND_PALETTE: Self = Self(24);
150
151    /// Variations PostScript name prefix.
152    ///
153    /// If present in a variable font, it may be used as the family prefix in the PostScript Name Generation
154    /// for Variation Fonts algorithm.
155    pub const VARIATIONS_POSTSCRIPT_NAME_PREFIX: Self = Self(25);
156
157    /// The last value that is explicitly reserved for standard names.
158    ///
159    /// Values after this are available to be used for font-specific names.
160    ///
161    /// See <https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-ids>
162    pub const LAST_RESERVED_NAME_ID: Self = Self(255);
163
164    /// The last value that is available for font-specific names.
165    ///
166    /// See <https://learn.microsoft.com/en-us/typography/opentype/spec/name#name-ids>
167    pub const LAST_ALLOWED_NAME_ID: Self = Self(32767);
168}
169
170impl NameId {
171    /// Create a new identifier from a raw u16 value.
172    #[inline]
173    pub const fn new(raw: u16) -> Self {
174        Self(raw)
175    }
176
177    /// Returns an iterator over the set of predefined identifiers according to the
178    /// specification.
179    #[inline]
180    pub fn predefined() -> impl Iterator<Item = Self> + Clone {
181        // Poor name id 15 got lost...
182        (0..15).chain(16..=25).map(Self)
183    }
184
185    /// Return the identifier as a u16.
186    #[inline]
187    pub const fn to_u16(self) -> u16 {
188        self.0
189    }
190
191    /// Returns `true` if self is in the range `0..=255` (reserved for standard names.)
192    #[inline]
193    pub const fn is_reserved(self) -> bool {
194        self.0 <= Self::LAST_RESERVED_NAME_ID.0
195    }
196
197    /// Returns a new `NameId` by adding `rhs` to the current value.
198    ///
199    /// Returns `None` if the result would be greater than `Self::LAST_ALLOWED_NAME_ID`.
200    #[inline]
201    pub const fn checked_add(self, rhs: u16) -> Option<Self> {
202        let result = Self(self.0.saturating_add(rhs));
203        if result.0 > Self::LAST_ALLOWED_NAME_ID.0 {
204            None
205        } else {
206            Some(result)
207        }
208    }
209
210    /// Return the memory representation of this identifier as a byte array in big-endian
211    /// (network) byte order.
212    #[inline]
213    pub const fn to_be_bytes(self) -> [u8; 2] {
214        self.0.to_be_bytes()
215    }
216}
217
218impl Default for NameId {
219    fn default() -> Self {
220        Self(0xFFFF)
221    }
222}
223
224impl From<u16> for NameId {
225    fn from(value: u16) -> Self {
226        Self(value)
227    }
228}
229
230impl fmt::Debug for NameId {
231    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
232        let name = match *self {
233            Self::COPYRIGHT_NOTICE => "COPYRIGHT_NOTICE",
234            Self::FAMILY_NAME => "FAMILY_NAME",
235            Self::SUBFAMILY_NAME => "SUBFAMILY_NAME",
236            Self::UNIQUE_ID => "UNIQUE_ID",
237            Self::FULL_NAME => "FULL_NAME",
238            Self::VERSION_STRING => "VERSION_STRING",
239            Self::POSTSCRIPT_NAME => "POSTSCRIPT_NAME",
240            Self::TRADEMARK => "TRADEMARK",
241            Self::MANUFACTURER => "MANUFACTURER",
242            Self::DESIGNER => "DESIGNER",
243            Self::DESCRIPTION => "DESCRIPTION",
244            Self::VENDOR_URL => "VENDOR_URL",
245            Self::DESIGNER_URL => "DESIGNER_URL",
246            Self::LICENSE_DESCRIPTION => "LICENSE_DESCRIPTION",
247            Self::LICENSE_URL => "LICENSE_URL",
248            Self::TYPOGRAPHIC_FAMILY_NAME => "TYPOGRAPHIC_FAMILY_NAME",
249            Self::TYPOGRAPHIC_SUBFAMILY_NAME => "TYPOGRAPHIC_SUBFAMILY_NAME",
250            Self::COMPATIBLE_FULL_NAME => "COMPATIBLE_FULL_NAME",
251            Self::SAMPLE_TEXT => "SAMPLE_TEXT",
252            Self::POSTSCRIPT_CID_NAME => "POSTSCRIPT_CID_NAME",
253            Self::WWS_FAMILY_NAME => "WWS_FAMILY_NAME",
254            Self::WWS_SUBFAMILY_NAME => "WWS_SUBFAMILY_NAME",
255            Self::LIGHT_BACKGROUND_PALETTE => "LIGHT_BACKGROUND_PALETTE",
256            Self::DARK_BACKGROUND_PALETTE => "DARK_BACKGROUND_PALETTE",
257            Self::VARIATIONS_POSTSCRIPT_NAME_PREFIX => "VARIATIONS_POSTSCRIPT_NAME_PREFIX",
258            _ => return write!(f, "NameId {}", self.0),
259        };
260        f.write_str(name)
261    }
262}
263
264impl fmt::Display for NameId {
265    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
266        write!(f, "{:?}", self)
267    }
268}
269
270crate::newtype_scalar!(NameId, [u8; 2]);