Files
vectorcraft/crates/engine/src/tests_fontlist.rs
T
bflatasticandClaude Opus 5.5 f12428264c Fix #36: the font menus list the installed fonts, with a search field
Type > Font, the Character, Properties and Glyphs panels and Find Font list
every installed font by default, as the reference app does, instead of the
four bundled families. The family dropdowns get a search field that filters
the list as you type (Enter picks the first match) and open on the current
font. Show System Fonts, which no longer means anything, becomes Refresh Font
List (text.rescanFonts): it picks up fonts installed since the app started and
redraws type set in them without editing the document. text.fontList lets MCP
agents list the families and a family's styles.

Root cause: the font lists came from FontDb::families(), which only held the
bundled fonts until something scanned the system fonts (fixed with #130). The
Type > Font menu, rebuilt every frame, now builds its items once per font
change, and renderers lay type out again when the fonts change.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-06 00:49:22 +07:00

47 lines
2.0 KiB
Rust

//! The fonts available (`text.fontList`), the installed ones listed without asking for them (#36),
//! and Refresh Font List (`text.rescanFonts`).
use serde_json::{Value, json};
use vectorcraft_text::{FontDb, system_font_dirs};
use super::*;
fn names(v: &Value) -> Vec<String> {
serde_json::from_value(v.clone()).unwrap()
}
#[test]
fn the_font_list_names_every_available_family_with_its_styles() {
let mut s = Session::new();
let fams = names(&s.execute("text.fontList", &json!({})).unwrap()["families"]);
assert_eq!(fams, FontDb::global().families());
for f in ["Source Sans 3", "Source Serif 4", "Inter", "JetBrains Mono"] {
assert!(fams.iter().any(|x| x == f), "{f}");
}
// Every installed family, though nothing asked for system fonts.
let installed = FontDb::with_font_dirs(system_font_dirs());
installed.load_system_fonts();
let missing: Vec<String> = installed.families().into_iter().filter(|f| !fams.contains(f)).collect();
assert!(missing.is_empty(), "{missing:?}");
let r = s.execute("text.fontList", &json!({"family": "source sans 3"})).unwrap();
assert_eq!(r["family"], "Source Sans 3");
let styles = names(&r["styles"]);
assert!(["Regular", "Semibold", "Bold", "Italic"].iter().all(|x| styles.iter().any(|s| s == x)), "{styles:?}");
assert!(s.execute("text.fontList", &json!({"family": "No Such Font"})).is_err());
}
#[test]
fn refreshing_the_font_list_redraws_type_without_editing_the_document() {
let mut s = Session::new();
s.execute("file.new", &json!({"width": 200, "height": 200})).unwrap();
s.execute("text.create", &json!({"x": 10, "y": 40, "text": "Type", "font": "No Such Font"})).unwrap();
s.doc_mut().unwrap().mark_saved();
let revision = s.doc().unwrap().revision;
let r = s.execute("text.rescanFonts", &json!({})).unwrap();
assert_eq!(r["families"], json!(FontDb::global().families().len()));
assert!(r["faces"].is_u64());
let d = s.doc().unwrap();
assert!(d.revision > revision, "the canvas redraws");
assert!(!d.is_dirty(), "nothing to save");
}