mirror of
https://github.com/storytold/designcraft.git
synced 2026-10-28 04:06:54 -06:00
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:
co-authored by
Claude Opus 5.5
parent
d07cbbe94c
commit
89f6adb6fb
@@ -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.
|
||||
|
||||
@@ -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}");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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()
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user