mirror of
https://github.com/storytold/deckcraft.git
synced 2026-10-30 21:47:00 -06:00
Merge pull request #1452
Fonts: a variable font's named instances answer to their Windows family names
This commit is contained in:
@@ -393,6 +393,22 @@ fn legacy_names(f: &skrifa::FontRef<'_>, family: &str) -> Option<(String, String
|
||||
Some((legacy, name(f, &[StringId::SUBFAMILY_NAME]).unwrap_or_else(|| "Regular".into())))
|
||||
}
|
||||
|
||||
/// The Windows family and style a variable font's named instance answers to. Windows lists each
|
||||
/// instance other than Regular, Italic, Bold and Bold Italic as a family of its own, as the
|
||||
/// family's static files name themselves: "Montserrat ExtraBold" / "Regular" for the ExtraBold
|
||||
/// instance, "Montserrat ExtraBold" / "Italic" for ExtraBold Italic.
|
||||
fn instance_legacy_names(family: &str, style: &str) -> Option<(String, String)> {
|
||||
if style.contains('{') {
|
||||
return None;
|
||||
}
|
||||
let weight: Vec<&str> = style.split_whitespace().filter(|w| !matches!(norm(w).as_str(), "italic" | "oblique")).collect();
|
||||
let weight = weight.join(" ");
|
||||
if matches!(norm(&weight).as_str(), "" | "regular" | "bold") {
|
||||
return None;
|
||||
}
|
||||
Some((format!("{family} {weight}"), if style_italic(style) { "Italic" } else { "Regular" }.into()))
|
||||
}
|
||||
|
||||
/// The tables skrifa reads glyph outlines from: `glyf` (TrueType), `CFF `, `CFF2` and `VARC`. For a
|
||||
/// face with none of them (bitmaps only, or outlines in Apple's `hvgl` table), [`FontDb::outline`]
|
||||
/// returns an empty path for every glyph.
|
||||
@@ -686,7 +702,7 @@ fn make_face(bytes: FontBytes, index: u32, family: String, style: String, coords
|
||||
.map(|v| v >= 0.5)
|
||||
.or(axis(b"slnt").map(|v| v.abs() > 0.1))
|
||||
.unwrap_or(!matches!(a.style, skrifa::attribute::Style::Normal) || style_italic(&style));
|
||||
let legacy = if coords.is_empty() { legacy_names(&f, &family) } else { None };
|
||||
let legacy = if coords.is_empty() { legacy_names(&f, &family) } else { instance_legacy_names(&family, &style) };
|
||||
Some(FontFace {
|
||||
id: NEXT_ID.fetch_add(1, Ordering::Relaxed),
|
||||
family,
|
||||
|
||||
@@ -147,6 +147,36 @@ fn windows_family_names_find_their_faces() {
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn variable_font_instances_answer_to_their_windows_names() {
|
||||
// Windows lists a variable font's named instances other than Regular, Italic, Bold and
|
||||
// Bold Italic as families of their own, and documents name them that way ("Montserrat
|
||||
// ExtraBold"). The bundled Montserrat is variable, so these names found no face and drew
|
||||
// in Inter Regular, even with the family's static files installed (their faces are
|
||||
// skipped as already present).
|
||||
let db = FontDb::with_font_dirs(Vec::new());
|
||||
db.set_system_fallback(false);
|
||||
if !db.is_loaded("Montserrat") {
|
||||
return; // built without craft-fonts
|
||||
}
|
||||
for (name, style, weight, italic) in [
|
||||
("Montserrat ExtraBold", "Regular", 800.0, false),
|
||||
("Montserrat SemiBold", "Regular", 600.0, false),
|
||||
("Montserrat Medium", "Regular", 500.0, false),
|
||||
("Montserrat Medium", "Italic", 500.0, true),
|
||||
("Montserrat Thin", "Bold", 100.0, false),
|
||||
] {
|
||||
assert!(db.has_family(name), "{name}");
|
||||
let f = db.face(name, style);
|
||||
assert_eq!((f.family.as_str(), f.weight, f.italic), ("Montserrat", weight, italic), "{name} {style}");
|
||||
assert_eq!(db.document_face(name, style).family, "Montserrat", "{name}: installed, so not Calibri");
|
||||
}
|
||||
// Regular and Bold are the family itself, not families of their own.
|
||||
assert!(!db.has_family("Montserrat Regular"));
|
||||
assert!(!db.has_family("Montserrat Bold"));
|
||||
assert_eq!(db.face("Montserrat", "Bold").weight, 700.0);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn faces_without_outlines_are_not_cataloged() {
|
||||
// Rename the Semibold's `glyf` table, as in fonts whose glyphs are bitmaps or are stored in
|
||||
|
||||
Reference in New Issue
Block a user