From 04ebc4ed4236cb19d70561d6bff86fa3f9cc8a37 Mon Sep 17 00:00:00 2001 From: Martin Ball Date: Fri, 23 Oct 2026 15:13:56 +0100 Subject: [PATCH] #3995: Thai one-face fallback tests skip unless a Thai font with Latin is installed Noto Sans Thai and its siblings have no Latin letters or digits, so on a machine whose only Thai fonts are Noto no face covers the test run and fallback_for_run rightly returns None. The guard now asks whether the Thai substitute covers the whole run, which doesn't go through fallback_for_run. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_01CX1hMKX28764Lrx5moxs1o --- crates/fonts/src/fontdb/tests.rs | 8 +++++--- crates/layout/src/tests/complex.rs | 15 +++++++++++---- 2 files changed, 16 insertions(+), 7 deletions(-) diff --git a/crates/fonts/src/fontdb/tests.rs b/crates/fonts/src/fontdb/tests.rs index 52c5b86dc..48e157393 100644 --- a/crates/fonts/src/fontdb/tests.rs +++ b/crates/fonts/src/fontdb/tests.rs @@ -98,12 +98,14 @@ const THAI_RUN: &str = "[D] น้ำ ค่ำ ปั้น ฝั่ง ปู #[test] fn a_thai_run_with_latin_falls_back_to_one_face() { let db = FontDb::global(); - if db.fallback_for('น', 0).is_none() { - eprintln!("skipped: no Thai font installed"); + let chars: Vec = THAI_RUN.chars().filter(|c| !c.is_whitespace()).collect(); + // Needs a Thai font with Latin letters and digits (Tahoma, Leelawadee UI, Thonburi, the + // TLWG fonts…): Noto Sans Thai alone has none, so no face covers the run. + if !chars.iter().all(|c| crate::word::resolve("TH Sarabun New", false, false).face.covers(*c)) { + eprintln!("skipped: no Thai font with Latin letters installed"); return; } let latin = db.face(FALLBACK_FAMILY, "Regular"); - let chars: Vec = THAI_RUN.chars().filter(|c| !c.is_whitespace()).collect(); let f = db.fallback_for_run(&chars, latin.id(), false, false).expect("one face covers the run"); assert_ne!(f.id, latin.id); for c in &chars { diff --git a/crates/layout/src/tests/complex.rs b/crates/layout/src/tests/complex.rs index 74a40ded9..793678424 100644 --- a/crates/layout/src/tests/complex.rs +++ b/crates/layout/src/tests/complex.rs @@ -118,6 +118,13 @@ fn thai_font_installed() -> bool { wordcraft_fonts::FontDb::global().fallback_for('\u{0E19}', 0).is_some() } +/// Is a Thai font with Latin letters and digits installed (Tahoma, Leelawadee UI, Thonburi, the +/// TLWG fonts…)? Noto Sans Thai alone has none, so no face covers [`THAI_RUN`]: `false` skips. +fn thai_latin_font_installed() -> bool { + let face = wordcraft_fonts::word::resolve("TH Sarabun New", false, false).face; + THAI_RUN.chars().filter(|c| !c.is_whitespace()).all(|c| face.covers(c)) +} + /// Body paragraph 0 of `text`, its run set in `font` at 16 pt (`None` keeps the document's /// default font), and the face of every cluster: (cluster start, face). fn cluster_faces(text: &str, font: Option<&str>) -> Vec<(usize, wordcraft_fonts::FaceRef)> { @@ -132,8 +139,8 @@ fn cluster_faces(text: &str, font: Option<&str>) -> Vec<(usize, wordcraft_fonts: #[test] fn a_missing_thai_font_draws_the_whole_run_in_one_thai_face() { - if !thai_font_installed() { - eprintln!("skipped: no Thai font installed"); + if !thai_latin_font_installed() { + eprintln!("skipped: no Thai font with Latin letters installed"); return; } // Word substitutes one font (Cordia New) for a missing Thai font, so the Latin letters, the @@ -154,8 +161,8 @@ fn a_missing_thai_font_draws_the_whole_run_in_one_thai_face() { #[test] fn a_thai_substitute_without_latin_hands_the_run_to_one_face_covering_it() { - if !thai_font_installed() { - eprintln!("skipped: no Thai font installed"); + if !thai_latin_font_installed() { + eprintln!("skipped: no Thai font with Latin letters installed"); return; } // When the substitute lacks the run's Thai letters (no listed Thai font is installed, so the