Find Font: a style that differs only in spacing isn't missing

Montilla Design's Flex Layout file names its body face "Regular " (with a
trailing space, as the designer's copy of Articulat CF did). Face lookup
already ignores spacing and case, so the text is drawn in Regular, but
font.list (Find Font) compared names exactly and reported the style
missing. It now uses the lookup's comparison (designcraft_fonts::same_style).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
moppeeer
2026-10-15 01:25:04 +02:00
co-authored by Claude Opus 5.5
parent d07cbbe94c
commit 89f6adb6fb
4 changed files with 27 additions and 2 deletions
+1
View File
@@ -132,6 +132,7 @@ list) · [roadmap.md](docs/roadmap.md) (milestones, plan) · [parity-checklist.m
Newest first.
- **2026-10-15** · Find Font no longer reports a style missing when it differs from the installed one only in spacing or case (InDesign files can name `Regular ` with a trailing space); the text was already drawn in the right face. No readiness percentage change.
- **2026-10-13** · Object › Fitting has InDesign's shortcuts: Fill Frame Proportionally ⌘⌥⇧C, Fit Content Proportionally ⌘⌥⇧E, Fit Frame to Content ⌘⌥C, Fit Content to Frame ⌘⌥E, Center Content ⌘⇧E. No readiness percentage change.
- **2026-10-13** · Gradients between process colours blend as inks, as InDesign shows them: magenta to cyan passes through C 50 M 50 (a light lilac) on screen instead of the darker RGB mix, and a midpoint between CMYK or grey stops no longer turns the PDF shading RGB. No readiness percentage change.
- **2026-10-14** · The Swatches panel has InDesign's header: a Fill/Stroke proxy, Formatting Affects Container/Text and the Tint of the colour in front (a tint alone keeps each object's own swatch). Clicking a swatch applies it to the fill or stroke in front (of the text, when formatting affects text), and the bottom row has New Color Group, New Swatch and Delete Swatch. No readiness percentage change.
+19 -1
View File
@@ -73,7 +73,7 @@ fn list(d: &Document) -> Vec<Value> {
.into_iter()
.map(|((family, style), n)| {
let missing = !db.has_family(&family);
let style_missing = !missing && !db.styles(&family).iter().any(|s| s.eq_ignore_ascii_case(&style));
let style_missing = !missing && !db.styles(&family).iter().any(|s| designcraft_fonts::same_style(s, &style));
let source = (!missing).then(|| match db.face(&family, &style).source {
FontSource::Bundled => "bundled",
FontSource::Installed(_) => "installed",
@@ -225,4 +225,22 @@ mod tests {
assert_eq!((&l[0]["family"], &l[0]["missing"]), (&json!("Nope (OTF)"), &json!(true)), "{l}");
assert!(kinds(&mut s).iter().any(|k| k == "missingFont"));
}
/// A style name that differs only in spacing (Montilla Design's file sets `Regular ` with a
/// trailing space) is the face the text is drawn in, not a missing style.
#[test]
fn a_style_with_extra_spacing_is_not_missing() {
let mut s = Session::new();
s.execute("file.new", &json!({})).unwrap();
let r = s.execute("frame.create", &json!({"rect": [72, 72, 400, 300], "content": "text", "text": "Text"})).unwrap();
let sid = s.doc().unwrap().doc.item(designcraft_doc::ItemId(r["id"].as_u64().unwrap())).unwrap().text_frame().unwrap().story;
s.execute("text.select", &json!({"story": sid.0, "anchor": 0, "focus": 4})).unwrap();
s.execute("type.char", &json!({"fontFamily": "Source Serif 4", "fontStyle": "Regular "})).unwrap();
let l = s.execute("font.list", &json!({})).unwrap();
let entry = l.as_array().unwrap().iter().find(|f| f["style"] == "Regular ").unwrap();
assert_eq!((&entry["missing"], &entry["styleMissing"]), (&json!(false), &json!(false)), "{l}");
s.execute("type.char", &json!({"fontFamily": "Source Serif 4", "fontStyle": "Nope"})).unwrap();
let l = s.execute("font.list", &json!({})).unwrap();
assert_eq!(l[0]["styleMissing"], json!(true), "{l}");
}
}
+6
View File
@@ -845,6 +845,12 @@ pub fn base_style(style: &str) -> &str {
style.split('{').next().unwrap_or(style).trim()
}
/// Do two style names name the same face? Spacing, punctuation and case don't count, as when a face
/// is looked up (InDesign documents can carry `Regular ` with a trailing space).
pub fn same_style(a: &str, b: &str) -> bool {
norm(a) == norm(b)
}
fn norm(s: &str) -> String {
s.chars().filter(|c| c.is_alphanumeric()).flat_map(|c| c.to_lowercase()).collect()
}
+1 -1
View File
@@ -16,7 +16,7 @@ mod vertical;
pub use fontdb::{
DOCUMENT_FONTS_FOLDER, DocumentFonts, FALLBACK_FAMILY, FaceRef, FontDb, FontFace, FontSource, MAX_DOCUMENT_FONT_BYTES, MAX_DOCUMENT_FONT_FILES,
MAX_DOCUMENT_FONTS_TOTAL, ScopedFonts, base_style, bundled, system_font_dirs,
MAX_DOCUMENT_FONTS_TOTAL, ScopedFonts, base_style, bundled, same_style, system_font_dirs,
};
pub use group::{FamilyInfo, FontGroup, sort_for_menu};
pub use harfrust::Feature;