From 76ddc9b3e92f760e426b3ddc3c901e0d277959bd Mon Sep 17 00:00:00 2001 From: AskaEth Date: Fri, 6 Nov 2026 22:31:11 +0800 Subject: [PATCH] =?UTF-8?q?fix(fonts):=20Termux=20=E4=B8=8A=E6=B3=A8?= =?UTF-8?q?=E5=86=8C=20Android=20=E7=B3=BB=E7=BB=9F=20CJK=20=E5=AD=97?= =?UTF-8?q?=E4=BD=93=EF=BC=8C=E6=B6=88=E9=99=A4=E4=B8=AD=E6=96=87=E6=96=B9?= =?UTF-8?q?=E6=A1=86?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glibc 构建跑在 Termux 里时 target_os 仍是 linux,fontdb 只扫 Linux 常规 字体目录,/system/fonts 不在其中,中文实例名与界面文案全渲染成方框。 在字体求值入口按运行时识别 Termux,把 NotoSansCJK 等候选注册进 cosmic-text 的字体库(OnceLock 只加载一次,找不到就静默放过)。 app-iced 直接依赖 unlucky-core 复用平台识别,不再本地复制环境判断。 --- Cargo.lock | 1 + crates/app-iced/Cargo.toml | 3 +++ crates/app-iced/src/fonts.rs | 35 +++++++++++++++++++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/Cargo.lock b/Cargo.lock index fb854ba..1395f79 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5003,6 +5003,7 @@ dependencies = [ "image", "log", "unlucky-cli", + "unlucky-core", "unlucky-design", "unlucky-i18n", "unlucky-presenter", diff --git a/crates/app-iced/Cargo.toml b/crates/app-iced/Cargo.toml index 51fb282..e4a7177 100644 --- a/crates/app-iced/Cargo.toml +++ b/crates/app-iced/Cargo.toml @@ -24,6 +24,9 @@ path = "src/lib.rs" # 令牌唯一真源(M61):颜色/排版/形状/间距/图标几何全部只从这里取。 unlucky-design = { path = "../design", version = "0.2.1" } +# 平台识别(Termux / $PREFIX 路径)唯一真源:字体注册这类平台适配不再各写一份环境判断。 +unlucky-core = { path = "../core", version = "0.2.1" } + # M85:UI 框架无关的宿主层(DTO / 状态 reducer / host)。**只登记依赖,本 mission 不接线**—— # 页面用它的时机由后续 iced 页面 mission 决定(接线流程见 crates/presenter/src/lib.rs 的 crate 文档)。 # 与 Slint 版共用同一套 host 与状态语义,这是 D26「重写只换渲染」的落点。 diff --git a/crates/app-iced/src/fonts.rs b/crates/app-iced/src/fonts.rs index 74c5b5e..8690f05 100644 --- a/crates/app-iced/src/fonts.rs +++ b/crates/app-iced/src/fonts.rs @@ -139,8 +139,43 @@ pub fn resolve() -> Resolved { resolve_with(None) } +/// Termux 上把 Android 的系统 CJK 字体注册进 cosmic-text 的字体库。 +/// +/// 这套 glibc 构建跑在 Termux 里(`target_os = "linux"`),fontdb 只扫 Linux 的常规字体目录, +/// Android 的 `/system/fonts` 不在其中——不注册的话中文实例名与界面文案全是方框。 +/// 第一次调用加载一次;找不到任何候选字体时静默放过(由既有回退链兜底)。 +fn register_termux_fonts() { + use std::sync::OnceLock; + + use unlucky_core::platform::paths::ProcessEnv; + use unlucky_core::platform::termux; + + static REGISTERED: OnceLock<()> = OnceLock::new(); + REGISTERED.get_or_init(|| { + if !termux::is_termux(&ProcessEnv) { + return; + } + const CANDIDATES: &[&str] = &[ + "/system/fonts/NotoSansCJK-Regular.ttc", + "/system/fonts/NotoSansCJKSC-Regular.otf", + "/system/fonts/DroidSansFallback.ttf", + ]; + let Ok(mut font_system) = iced::advanced::graphics::text::font_system().write() else { + return; + }; + let db = font_system.raw().db_mut(); + for path in CANDIDATES { + if db.load_font_file(path).is_ok() { + return; + } + } + }); +} + /// 同 [`resolve`],但把配置里 `ui.language` 的显式值喂给中文策略(D28 的第一级)。 pub fn resolve_with(setting: Option<&str>) -> Resolved { + register_termux_fonts(); + let platform = Platform::current(); let faces = system_faces();