Skip to main content

max / quasi-type

State the glyph set version in the face, not only in the packed version A cut face is a composition of a base and a glyph set, and the set moves on its own schedule. Which set a face carries had to be inferred from the build that produced it: `version` is `{set}.{base}`, so `1.2.5.0` cannot be split without already knowing Plex Mono was at 2.5.0. Identity gains set_version. The description names it beside the base, and the unique id — the record whose whole job is identifying one exact build — names both halves instead of the packed string. Quasi Mono Regular; house glyph set v1; IBM Plex Mono 2.5.0 Derived from IBM Plex Mono 2.5.0, by drawing quasi house glyph set v1 into it. The letterforms are unmodified. Both readable with plain strings(1), which is what makes "does this installed face have the octants" a question about the file.
Co-Authored-By
Claude Opus 5 (1M context) <noreply@anthropic.com>
Author: Max Johnson <me@maxj.phd> · 2026-08-17 01:12 UTC
Signed with PGP, not checked
Commit: 03829c5714bff6bd18064a6deb42fea36021e2cc
Parent: e92165e
3 files changed, +72 insertions, -4 deletions
M src/compose.rs +29 -4
@@ -27,6 +27,17 @@
27 27 pub family: &'a str,
28 28 pub style: &'a str,
29 29 pub version: &'a str,
30 + /// `[set] version` from the glyph manifest, stated in the description on
31 + /// its own rather than only folded into `version`.
32 + ///
33 + /// A cut face is a composition of a base and a glyph set, and the set
34 + /// versions independently of the base and of this pipeline. Two faces over
35 + /// the same base carrying different sets are different fonts, so "which set
36 + /// is this face carrying" has to be answerable from the file. It was not:
37 + /// `version` is `{set}.{base}`, and nothing in the face says where the
38 + /// boundary falls, so `1.2.5.0` is unreadable without knowing that Plex Mono
39 + /// happened to be at 2.5.0.
40 + pub set_version: u32,
30 41 pub base: &'a Base,
31 42 }
32 43
@@ -341,17 +352,31 @@
341 352 );
342 353 // OFL 1.1 requires the base's copyright and licence to travel with a
343 354 // modified build, and asks that the lineage be stated. It goes here rather
344 - // than in the family name, which the Reserved Font Name forbids.
355 + // than in the family name, which a Reserved Font Name would forbid.
356 + //
357 + // The glyph set version is stated alongside the base because a cut face is
358 + // a composition of the two and the set moves on its own schedule. Naming
359 + // both is what makes "does this installed face have the octants" a question
360 + // about the file rather than about which build produced it.
345 361 let description = format!(
346 - "Derived from {} {}, by drawing the quasi house glyph set into it. \
362 + "Derived from {} {}, by drawing quasi house glyph set v{} into it. \
347 363 The letterforms are unmodified.",
348 - id.base.family, id.base.version
364 + id.base.family, id.base.version, id.set_version
349 365 );
350 366 let records = vec![
351 367 record(NameId::COPYRIGHT_NOTICE, &id.base.copyright),
352 368 record(NameId::FAMILY_NAME, id.family),
353 369 record(NameId::SUBFAMILY_NAME, id.style),
354 - record(NameId::UNIQUE_ID, &format!("{full}; {}", id.version)),
370 + // Names both halves of the composition rather than the packed version,
371 + // so the record that exists to identify one exact build identifies it
372 + // without a decoder ring.
373 + record(
374 + NameId::UNIQUE_ID,
375 + &format!(
376 + "{full}; house glyph set v{}; {} {}",
377 + id.set_version, id.base.family, id.base.version
378 + ),
379 + ),
355 380 record(NameId::FULL_NAME, &full),
356 381 record(NameId::VERSION_STRING, &format!("Version {}", id.version)),
357 382 record(NameId::POSTSCRIPT_NAME, &postscript),
@@ -154,6 +154,7 @@
154 154 family: &slot.family,
155 155 style: &face.style,
156 156 version: &version,
157 + set_version: manifest.set.version,
157 158 base: base_pin,
158 159 };
159 160 let built = compose::build(&face.bytes, &selected, &id)?;
@@ -52,6 +52,7 @@
52 52 family: &slot.family,
53 53 style,
54 54 version: "1.2.5.0",
55 + set_version: 1,
55 56 base,
56 57 };
57 58 let built = compose::build(&face.bytes, &refs, &id).expect("the face cuts");
@@ -155,6 +156,47 @@
155 156 assert!(copyright.unwrap().contains("IBM"));
156 157 }
157 158
159 + #[test]
160 + fn the_face_states_which_glyph_set_it_carries() {
161 + // A cut face is a composition of a base and a glyph set, and the set
162 + // versions independently of both the base and this pipeline. So "which set
163 + // is this face carrying" has to be answerable from the file rather than
164 + // from knowing which build produced it — otherwise an installed face that
165 + // predates a set version is indistinguishable from one that does not.
166 + let Some((bytes, _)) = cut("Regular") else {
167 + return;
168 + };
169 + let font = FontRef::new(&bytes).unwrap();
170 + let name = font.name().unwrap();
171 + let mut description = None;
172 + let mut unique_id = None;
173 + for record in name.name_record() {
174 + let value = record
175 + .string(name.string_data())
176 + .map(|s| s.chars().collect::<String>())
177 + .unwrap_or_default();
178 + match record.name_id().to_u16() {
179 + 3 => unique_id = Some(value),
180 + 10 => description = Some(value),
181 + _ => {}
182 + }
183 + }
184 + let description = description.expect("a description");
185 + let unique_id = unique_id.expect("a unique id");
186 +
187 + assert!(
188 + description.contains("house glyph set v1"),
189 + "the description names the set version: {description}"
190 + );
191 + // The unique id identifies one exact build, so it names both halves rather
192 + // than the packed `{set}.{base}` version, which cannot be split without
193 + // already knowing where the base's version starts.
194 + assert!(
195 + unique_id.contains("house glyph set v1") && unique_id.contains("IBM Plex Mono 2.5.0"),
196 + "the unique id names both halves of the composition: {unique_id}"
197 + );
198 + }
199 +
158 200 #[test]
159 201 fn the_signature_over_the_old_bytes_is_dropped() {
160 202 let Some((bytes, _)) = cut("Regular") else {