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]);