diff --git a/crates/ui-egui/src/theme.rs b/crates/ui-egui/src/theme.rs index 485b9a2f3..08097ba27 100644 --- a/crates/ui-egui/src/theme.rs +++ b/crates/ui-egui/src/theme.rs @@ -252,7 +252,8 @@ fn candidates(role: &str) -> Vec<(String, u32)> { let mac_sys = "/System/Library/Fonts"; let mac_sup = "/System/Library/Fonts/Supplemental"; let win = std::env::var("WINDIR").map(|w| format!("{w}\\Fonts")).unwrap_or_else(|_| "C:\\Windows\\Fonts".into()); - let lin = ["/usr/share/fonts/truetype", "/usr/share/fonts", "/usr/local/share/fonts", "/usr/share/fonts/TTF"]; + // ChromeOS's Linux container (Crostini) mounts the host's fonts under `chromeos/` (#1762). + let lin = ["/usr/share/fonts/truetype", "/usr/share/fonts", "/usr/local/share/fonts", "/usr/share/fonts/TTF", "/usr/share/fonts/chromeos"]; let mut v: Vec<(String, u32)> = Vec::new(); let mut add = |s: String, i: u32| v.push((s, i)); match role { @@ -498,10 +499,10 @@ fn fallback_faces(han: HanOrder) -> Vec<(&'static str, Vec<(String, u32)>)> { } /// Linux directories that hold CJK fonts across distributions: Debian/Ubuntu (`opentype/noto`, -/// `truetype/wqy`), Fedora (`google-noto-cjk`), Arch (`noto-cjk`, `wenquanyi`), plus local and -/// flat layouts. +/// `truetype/wqy`), Fedora (`google-noto-cjk`), Arch (`noto-cjk`, `wenquanyi`), ChromeOS's Linux +/// container (`chromeos/notocjk`, #1762), plus local and flat layouts. #[cfg(not(target_arch = "wasm32"))] -const LINUX_CJK_DIRS: [&str; 10] = [ +const LINUX_CJK_DIRS: [&str; 11] = [ "/usr/share/fonts/opentype/noto", "/usr/share/fonts/google-noto-cjk", "/usr/share/fonts/noto-cjk", @@ -512,6 +513,7 @@ const LINUX_CJK_DIRS: [&str; 10] = [ "/usr/share/fonts", "/usr/local/share/fonts", "/usr/local/share/fonts/noto-cjk", + "/usr/share/fonts/chromeos/notocjk", ]; /// Japanese Han + Kana faces (Japanese kanji glyph shapes). @@ -581,7 +583,13 @@ fn thai() -> Vec<(String, u32)> { let mac_sys = "/System/Library/Fonts"; let mac_sup = "/System/Library/Fonts/Supplemental"; let win = std::env::var("WINDIR").map(|w| format!("{w}\\Fonts")).unwrap_or_else(|_| "C:\\Windows\\Fonts".into()); - let lin = ["/usr/share/fonts/truetype/noto", "/usr/share/fonts/opentype/noto", "/usr/share/fonts/truetype", "/usr/share/fonts"]; + let lin = [ + "/usr/share/fonts/truetype/noto", + "/usr/share/fonts/opentype/noto", + "/usr/share/fonts/truetype", + "/usr/share/fonts", + "/usr/share/fonts/chromeos/noto", // ChromeOS's Linux container (#1762) + ]; let mut v: Vec<(String, u32)> = Vec::new(); v.push((format!("{win}\\LeelawUI.ttf"), 0)); // Leelawadee UI v.push((format!("{win}\\tahoma.ttf"), 0)); // Tahoma @@ -603,7 +611,13 @@ fn hebrew() -> Vec<(String, u32)> { let mac_sys = "/System/Library/Fonts"; let mac_sup = "/System/Library/Fonts/Supplemental"; let win = std::env::var("WINDIR").map(|w| format!("{w}\\Fonts")).unwrap_or_else(|_| "C:\\Windows\\Fonts".into()); - let lin = ["/usr/share/fonts/truetype/noto", "/usr/share/fonts/opentype/noto", "/usr/share/fonts/truetype", "/usr/share/fonts"]; + let lin = [ + "/usr/share/fonts/truetype/noto", + "/usr/share/fonts/opentype/noto", + "/usr/share/fonts/truetype", + "/usr/share/fonts", + "/usr/share/fonts/chromeos/noto", // ChromeOS's Linux container (#1762) + ]; let mut v: Vec<(String, u32)> = Vec::new(); v.push((format!("{win}\\david.ttf"), 0)); // David v.push((format!("{win}\\frank.ttf"), 0)); // FrankRuehl @@ -657,6 +671,7 @@ fn symbols_more() -> Vec<(String, u32)> { "/usr/share/fonts/google-noto-sans-symbols-2-fonts", "/usr/share/fonts/google-noto", "/usr/local/share/fonts/noto", + "/usr/share/fonts/chromeos/noto", ] { v.push((format!("{d}/NotoSansSymbols2-Regular.ttf"), 0)); } @@ -888,6 +903,22 @@ mod tests { } } + #[test] + fn chromeos_font_layout_is_probed() { + // #1762: Crostini mounts the host's fonts under /usr/share/fonts/chromeos, one folder per + // family set; a script whose list misses it renders as tofu with the font installed. + let probes = |cands: Vec<(String, u32)>, path: &str| cands.iter().any(|(p, _)| p == path); + let cros = "/usr/share/fonts/chromeos"; + assert!(probes(thai(), &format!("{cros}/noto/NotoSansThai-Regular.ttf"))); + assert!(probes(hebrew(), &format!("{cros}/noto/NotoSansHebrew-Regular.ttf"))); + assert!(probes(cjk_han_japanese(), &format!("{cros}/notocjk/NotoSansCJK-Regular.ttc"))); + assert!(probes(cjk_han_simplified(), &format!("{cros}/notocjk/NotoSansCJK-Regular.ttc"))); + assert!(probes(cjk_hangul(), &format!("{cros}/notocjk/NotoSansCJK-Regular.ttc"))); + assert!(probes(symbols_more(), &format!("{cros}/noto/NotoSansSymbols2-Regular.ttf"))); + assert!(probes(candidates(UI), &format!("{cros}/noto/NotoSans-Regular.ttf"))); + assert!(probes(candidates(CELL), &format!("{cros}/crosextra/Carlito-Regular.ttf"))); + } + #[test] fn unparseable_font_files_are_rejected_not_fatal() { // #226: epaint panics in `set_fonts` on a face it can't parse ("An offset was out of