egui_chinese_font/
lib.rs

1//! # egui-chinese-font
2//! 
3//! A simple crate to load Chinese fonts for egui applications.
4//! 
5//! This crate provides cross-platform support for loading system Chinese fonts
6//! and configuring them with egui applications.
7//! 
8//! ## Usage
9//! 
10//! ```rust,no_run
11//! use egui_chinese_font::setup_chinese_fonts;
12//! 
13//! let ctx = egui::Context::default();
14//! setup_chinese_fonts(&ctx);
15//! ```
16
17use egui::{Context, FontData, FontDefinitions, FontFamily};
18
19/// Error type for font loading operations
20#[derive(Debug)]
21pub enum FontError {
22    /// Font file not found
23    NotFound(String),
24    /// Failed to read font file
25    ReadError(std::io::Error),
26    /// Platform not supported
27    UnsupportedPlatform,
28}
29
30impl std::fmt::Display for FontError {
31    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
32        match self {
33            FontError::NotFound(path) => write!(f, "Font file not found: {}", path),
34            FontError::ReadError(err) => write!(f, "Failed to read font file: {}", err),
35            FontError::UnsupportedPlatform => write!(f, "Platform not supported"),
36        }
37    }
38}
39
40impl std::error::Error for FontError {}
41
42/// Setup Chinese fonts for egui context
43/// 
44/// This function will attempt to load system Chinese fonts and configure them
45/// for use with the provided egui context.
46/// 
47/// # Arguments
48/// * `ctx` - The egui context to configure
49/// 
50/// # Returns
51/// * `Ok(())` if fonts were successfully loaded
52/// * `Err(FontError)` if font loading failed
53pub fn setup_chinese_fonts(ctx: &Context) -> Result<(), FontError> {
54    let mut fonts = FontDefinitions::default();
55    
56    // Try to load Chinese fonts based on platform
57    let chinese_font_data = load_chinese_font()?;
58    
59    // Insert the Chinese font
60    fonts.font_data.insert(
61        "chinese".to_owned(),
62        chinese_font_data,
63    );
64    
65    // Configure font families
66    fonts.families.entry(FontFamily::Proportional).or_default()
67        .insert(0, "chinese".to_owned());
68    fonts.families.entry(FontFamily::Monospace).or_default()
69        .insert(0, "chinese".to_owned());
70    
71    // Apply the font configuration
72    ctx.set_fonts(fonts);
73    
74    Ok(())
75}
76
77/// Load Chinese font data from system
78fn load_chinese_font() -> Result<FontData, FontError> {
79    #[cfg(target_os = "windows")]
80    {
81        load_windows_chinese_font()
82    }
83    
84    #[cfg(target_os = "macos")]
85    {
86        load_macos_chinese_font()
87    }
88    
89    #[cfg(target_os = "linux")]
90    {
91        load_linux_chinese_font()
92    }
93    
94    #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
95    {
96        Err(FontError::UnsupportedPlatform)
97    }
98}
99
100#[cfg(target_os = "windows")]
101fn load_windows_chinese_font() -> Result<FontData, FontError> {
102    // List of common Chinese font paths on Windows
103    let font_paths = [
104        r"C:\Windows\Fonts\msyh.ttc",      // Microsoft YaHei
105        r"C:\Windows\Fonts\msyhbd.ttc",    // Microsoft YaHei Bold
106        r"C:\Windows\Fonts\simsun.ttc",    // SimSun
107        r"C:\Windows\Fonts\simhei.ttf",    // SimHei
108        r"C:\Windows\Fonts\simkai.ttf",    // KaiTi
109        r"C:\Windows\Fonts\simfang.ttf",   // FangSong
110        r"C:\Windows\Fonts\msjh.ttc",      // Microsoft JhengHei (Traditional Chinese)
111        r"C:\Windows\Fonts\msjhbd.ttc",    // Microsoft JhengHei Bold
112        r"C:\Windows\Fonts\kaiu.ttf",      // DFKai-SB (Traditional Chinese)
113        r"C:\Windows\Fonts\mingliu.ttc",   // MingLiU (Traditional Chinese)
114    ];
115    
116    for font_path in &font_paths {
117        if let Ok(font_data) = std::fs::read(font_path) {
118            return Ok(FontData::from_owned(font_data));
119        }
120    }
121    
122    Err(FontError::NotFound("No Chinese font found on Windows".to_string()))
123}
124
125#[cfg(target_os = "macos")]
126fn load_macos_chinese_font() -> Result<FontData, FontError> {
127    let font_paths = [
128        "/System/Library/Fonts/PingFang.ttc",           // PingFang SC
129        "/System/Library/Fonts/STHeiti Light.ttc",      // STHeiti
130        "/System/Library/Fonts/STHeiti Medium.ttc",
131        "/System/Library/Fonts/Hiragino Sans GB.ttc",   // Hiragino Sans GB
132        "/Library/Fonts/Arial Unicode.ttf",             // Arial Unicode MS
133        "/System/Library/Fonts/Apple LiGothic Medium.ttf", // Apple LiGothic (Traditional)
134    ];
135    
136    for font_path in &font_paths {
137        if let Ok(font_data) = std::fs::read(font_path) {
138            return Ok(FontData::from_owned(font_data));
139        }
140    }
141    
142    Err(FontError::NotFound("No Chinese font found on macOS".to_string()))
143}
144
145#[cfg(target_os = "linux")]
146fn load_linux_chinese_font() -> Result<FontData, FontError> {
147    // Common Chinese font paths on Linux distributions
148    let font_paths = [
149        "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf",
150        "/usr/share/fonts/truetype/arphic/uming.ttc",
151        "/usr/share/fonts/truetype/arphic/ukai.ttc",
152        "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
153        "/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
154        "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
155        "/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
156        // Ubuntu/Debian paths
157        "/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
158        // CentOS/RHEL paths
159        "/usr/share/fonts/google-droid/DroidSansFallbackFull.ttf",
160        // Arch Linux paths
161        "/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
162    ];
163    
164    for font_path in &font_paths {
165        if let Ok(font_data) = std::fs::read(font_path) {
166            return Ok(FontData::from_owned(font_data));
167        }
168    }
169    
170    Err(FontError::NotFound("No Chinese font found on Linux".to_string()))
171}
172
173/// Setup Chinese fonts with custom font data
174/// 
175/// This function allows you to provide your own font data instead of
176/// loading from system fonts.
177/// 
178/// # Arguments
179/// * `ctx` - The egui context to configure
180/// * `font_data` - The font data to use
181/// * `font_name` - Name for the font (optional, defaults to "chinese")
182pub fn setup_custom_chinese_font(
183    ctx: &Context, 
184    font_data: Vec<u8>, 
185    font_name: Option<&str>
186) {
187    let mut fonts = FontDefinitions::default();
188    let name = font_name.unwrap_or("chinese");
189    
190    fonts.font_data.insert(
191        name.to_owned(),
192        FontData::from_owned(font_data),
193    );
194    
195    fonts.families.entry(FontFamily::Proportional).or_default()
196        .insert(0, name.to_owned());
197    fonts.families.entry(FontFamily::Monospace).or_default()
198        .insert(0, name.to_owned());
199    
200    ctx.set_fonts(fonts);
201}
202
203/// Get available Chinese font paths on the current system
204/// 
205/// This function returns a list of paths where Chinese fonts might be located
206/// on the current platform. Useful for debugging font loading issues.
207pub fn get_chinese_font_paths() -> Vec<String> {
208    #[cfg(target_os = "windows")]
209    {
210        vec![
211            r"C:\Windows\Fonts\msyh.ttc".to_string(),
212            r"C:\Windows\Fonts\msyhbd.ttc".to_string(),
213            r"C:\Windows\Fonts\simsun.ttc".to_string(),
214            r"C:\Windows\Fonts\simhei.ttf".to_string(),
215            r"C:\Windows\Fonts\simkai.ttf".to_string(),
216            r"C:\Windows\Fonts\simfang.ttf".to_string(),
217            r"C:\Windows\Fonts\msjh.ttc".to_string(),
218            r"C:\Windows\Fonts\msjhbd.ttc".to_string(),
219        ]
220    }
221    
222    #[cfg(target_os = "macos")]
223    {
224        vec![
225            "/System/Library/Fonts/PingFang.ttc".to_string(),
226            "/System/Library/Fonts/STHeiti Light.ttc".to_string(),
227            "/System/Library/Fonts/STHeiti Medium.ttc".to_string(),
228            "/System/Library/Fonts/Hiragino Sans GB.ttc".to_string(),
229            "/Library/Fonts/Arial Unicode.ttf".to_string(),
230        ]
231    }
232    
233    #[cfg(target_os = "linux")]
234    {
235        vec![
236            "/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf".to_string(),
237            "/usr/share/fonts/truetype/arphic/uming.ttc".to_string(),
238            "/usr/share/fonts/truetype/wqy/wqy-microhei.ttc".to_string(),
239            "/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc".to_string(),
240        ]
241    }
242    
243    #[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
244    {
245        vec![]
246    }
247}