//! Variable fonts: each named instance is a style of its own, listed, resolved, shaped, drawn and //! embedded at its axis settings (#296: Figtree listed only Light, its default instance). use kurbo::{Point, Shape}; use skrifa::MetadataProvider; use skrifa::instance::{LocationRef, Size}; use skrifa::raw::TableProvider; use vectorcraft_doc::CharStyle; use super::test_fonts::{VARIABLE_CHARS, VARIABLE_FAMILY as FAMILY, VARIABLE_WIDEN, name_table, variable_font}; use super::*; fn font() -> Vec { variable_font().expect("the test font builds") } /// A database of the bundled fonts and the test variable font. fn db() -> FontDb { let db = FontDb::with_font_dirs(vec![]); assert_eq!(db.add_font(font()), 3, "Regular, SemiBold and Bold"); db } /// The width of `c`'s outline in font units. fn ink_width(db: &FontDb, face: &FontFace, c: char) -> f64 { db.outline(face, face.glyph_for(c)).bounding_box().width() } fn text(family: &str, style: &str, s: &str) -> TextObject { TextObject::point(Point::ZERO, s, CharStyle { font_family: family.into(), font_style: style.into(), size: 100.0, ..CharStyle::default() }) } #[test] fn named_instances_are_styles_of_the_family() { let db = db(); // The default instance is the face itself; the unnamed and the twice-named ones are left out. assert_eq!(db.styles(FAMILY), ["Regular", "SemiBold", "Bold"]); let bold = db.face(FAMILY, "Bold").unwrap(); assert_eq!((bold.family.as_str(), bold.style.as_str(), bold.weight, bold.italic), (FAMILY, "Bold", 700.0, false)); assert_eq!(bold.variations(), [(*b"wght", 700.0)]); let regular = db.face(FAMILY, "Regular").unwrap(); assert!(regular.variations().is_empty() && regular.weight == 400.0); assert_eq!(db.face(FAMILY, "SemiBold").unwrap().weight, 550.0); // Fonts added again add nothing. assert_eq!(db.add_font(font()), 0); } #[test] fn an_instance_is_found_by_its_names_and_by_weight() { let db = db(); let m = |f: &str, s: &str| db.resolve(f, s).map(|(face, m)| (face.style.clone(), m)).unwrap(); assert_eq!(m(FAMILY, "Bold"), ("Bold".into(), FontMatch::Exact)); assert_eq!(m("varitest sans", "semi bold"), ("SemiBold".into(), FontMatch::Exact), "names are normalized"); // The default instance's own name names the face. assert_eq!(m(FAMILY, "Normal"), ("Regular".into(), FontMatch::Exact)); assert!(!db.styles(FAMILY).contains(&"Normal".to_string())); // A style the font hasn't: the closest weight. assert_eq!(m(FAMILY, "Black"), ("Bold".into(), FontMatch::Style)); assert_eq!(m(FAMILY, "Medium"), ("SemiBold".into(), FontMatch::Style)); // PostScript names (as PDF and .ai files name fonts): `-