use text_typeset::Typesetter;
const NOTO_SANS: &[u8] = include_bytes!("../test-fonts/NotoSans-Variable.ttf");
#[test]
fn register_font_returns_valid_id() {
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
assert_eq!(face, text_typeset::FontFaceId(0));
}
#[test]
fn register_multiple_fonts_returns_distinct_ids() {
let mut ts = Typesetter::new();
let face1 = ts.register_font(NOTO_SANS);
let face2 = ts.register_font(NOTO_SANS); assert_ne!(face1, face2);
}
#[test]
fn set_default_font_and_query() {
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 16.0);
assert_eq!(ts.font_registry().default_font(), Some(face));
assert!((ts.font_registry().default_size_px() - 16.0).abs() < f32::EPSILON);
}
#[test]
fn register_font_as_with_explicit_metadata() {
let mut ts = Typesetter::new();
let face = ts.register_font_as(NOTO_SANS, "CustomFamily", 400, false);
let found = ts.font_registry().query_font("CustomFamily", 400, false);
assert_eq!(found, Some(face));
}
#[test]
fn query_by_family_name() {
let mut ts = Typesetter::new();
let _face = ts.register_font(NOTO_SANS);
let found = ts.font_registry().query_font("Noto Sans", 400, false);
assert!(found.is_some());
}
#[test]
fn query_nonexistent_family_returns_none() {
let mut ts = Typesetter::new();
let _face = ts.register_font(NOTO_SANS);
let found = ts
.font_registry()
.query_font("Nonexistent Font", 400, false);
assert!(found.is_none());
}
#[test]
fn generic_family_mapping() {
let mut ts = Typesetter::new();
let _face = ts.register_font(NOTO_SANS);
ts.set_generic_family("sans-serif", "Noto Sans");
let found = ts.font_registry().query_font("sans-serif", 400, false);
assert!(found.is_some());
}
#[test]
fn font_entry_has_valid_data() {
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
let entry = ts.font_registry().get(face);
assert!(entry.is_some());
let entry = entry.unwrap();
assert!(!entry.data.is_empty());
let font_ref = swash::FontRef::from_index(&entry.data, entry.face_index as usize);
assert!(font_ref.is_some());
}
#[test]
fn font_resolve_with_default_fallback() {
use text_typeset::font::resolve::resolve_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 14.0);
let resolved = resolve_font(ts.font_registry(), None, None, None, None, None, 1.0);
assert!(resolved.is_some());
let resolved = resolved.unwrap();
assert_eq!(resolved.font_face_id, face);
assert!((resolved.size_px - 14.0).abs() < f32::EPSILON);
}
#[test]
fn font_resolve_with_explicit_family() {
use text_typeset::font::resolve::resolve_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 16.0);
let resolved = resolve_font(
ts.font_registry(),
Some("Noto Sans"),
None,
None,
None,
Some(24),
1.0,
);
assert!(resolved.is_some());
let resolved = resolved.unwrap();
assert!((resolved.size_px - 24.0).abs() < f32::EPSILON);
}
#[test]
fn font_resolve_bold_uses_weight_700() {
use text_typeset::font::resolve::resolve_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 16.0);
let resolved = resolve_font(
ts.font_registry(),
Some("Noto Sans"),
None,
Some(true),
None,
None,
1.0,
);
assert!(resolved.is_some());
}
#[test]
fn glyph_coverage_check() {
use text_typeset::font::resolve::font_has_glyph;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
assert!(font_has_glyph(ts.font_registry(), face, 'A'));
assert!(font_has_glyph(ts.font_registry(), face, 'z'));
}
#[test]
fn resolve_with_no_default_font_returns_none() {
use text_typeset::font::resolve::resolve_font;
let ts = Typesetter::new(); let resolved = resolve_font(ts.font_registry(), None, None, None, None, None, 1.0);
assert!(resolved.is_none());
}
#[test]
fn font_weight_takes_priority_over_font_bold() {
use text_typeset::font::resolve::resolve_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 16.0);
let resolved = resolve_font(
ts.font_registry(),
Some("Noto Sans"),
Some(300),
Some(true),
None,
None,
1.0,
);
assert!(resolved.is_some());
}
#[test]
fn register_font_as_overrides_family_name() {
let mut ts = Typesetter::new();
let _face = ts.register_font_as(NOTO_SANS, "MyCustomName", 400, false);
let original = ts.font_registry().query_font("Noto Sans", 400, false);
assert!(
original.is_none(),
"original family name should not match after override"
);
let custom = ts.font_registry().query_font("MyCustomName", 400, false);
assert!(custom.is_some());
}
#[test]
fn find_fallback_font_returns_none_with_single_font() {
use text_typeset::font::resolve::find_fallback_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
let fallback = find_fallback_font(ts.font_registry(), '?', face);
assert!(
fallback.is_none(),
"no fallback when only one font and it's excluded"
);
}
#[test]
fn find_fallback_font_finds_second_font() {
use text_typeset::font::resolve::find_fallback_font;
let mut ts = Typesetter::new();
let face1 = ts.register_font(NOTO_SANS);
let face2 = ts.register_font(NOTO_SANS);
let fallback = find_fallback_font(ts.font_registry(), 'A', face1);
assert_eq!(fallback, Some(face2));
}
#[test]
fn font_has_glyph_with_invalid_face_id() {
use text_typeset::font::resolve::font_has_glyph;
let ts = Typesetter::new();
assert!(!font_has_glyph(
ts.font_registry(),
text_typeset::FontFaceId(999),
'A'
));
}
#[test]
fn resolve_font_with_nonexistent_family_falls_back() {
use text_typeset::font::resolve::resolve_font;
let mut ts = Typesetter::new();
let face = ts.register_font(NOTO_SANS);
ts.set_default_font(face, 16.0);
let resolved = resolve_font(
ts.font_registry(),
Some("NonExistentFont"),
None,
None,
None,
Some(20),
1.0,
);
assert!(resolved.is_some());
let resolved = resolved.unwrap();
assert_eq!(
resolved.font_face_id, face,
"should fall back to default font"
);
assert!(
(resolved.size_px - 20.0).abs() < 0.01,
"should respect requested size"
);
}