use egui::{Context, FontData, FontDefinitions, FontFamily};
#[derive(Debug)]
pub enum FontError {
NotFound(String),
ReadError(std::io::Error),
UnsupportedPlatform,
}
impl std::fmt::Display for FontError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
FontError::NotFound(path) => write!(f, "Font file not found: {}", path),
FontError::ReadError(err) => write!(f, "Failed to read font file: {}", err),
FontError::UnsupportedPlatform => write!(f, "Platform not supported"),
}
}
}
impl std::error::Error for FontError {}
pub fn setup_chinese_fonts(ctx: &Context) -> Result<(), FontError> {
let mut fonts = FontDefinitions::default();
let chinese_font_data = load_chinese_font()?;
fonts.font_data.insert(
"chinese".to_owned(),
chinese_font_data.into(),
);
fonts.families.entry(FontFamily::Proportional).or_default()
.insert(0, "chinese".to_owned());
fonts.families.entry(FontFamily::Monospace).or_default()
.insert(0, "chinese".to_owned());
ctx.set_fonts(fonts);
Ok(())
}
fn load_chinese_font() -> Result<FontData, FontError> {
#[cfg(target_os = "windows")]
{
load_windows_chinese_font()
}
#[cfg(target_os = "macos")]
{
load_macos_chinese_font()
}
#[cfg(target_os = "linux")]
{
load_linux_chinese_font()
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
Err(FontError::UnsupportedPlatform)
}
}
#[cfg(target_os = "windows")]
fn load_windows_chinese_font() -> Result<FontData, FontError> {
let font_paths = [
r"C:\Windows\Fonts\msyh.ttc", r"C:\Windows\Fonts\msyhbd.ttc", r"C:\Windows\Fonts\simsun.ttc", r"C:\Windows\Fonts\simhei.ttf", r"C:\Windows\Fonts\simkai.ttf", r"C:\Windows\Fonts\simfang.ttf", r"C:\Windows\Fonts\msjh.ttc", r"C:\Windows\Fonts\msjhbd.ttc", r"C:\Windows\Fonts\kaiu.ttf", r"C:\Windows\Fonts\mingliu.ttc", ];
for font_path in &font_paths {
if let Ok(font_data) = std::fs::read(font_path) {
return Ok(FontData::from_owned(font_data));
}
}
Err(FontError::NotFound("No Chinese font found on Windows".to_string()))
}
#[cfg(target_os = "macos")]
fn load_macos_chinese_font() -> Result<FontData, FontError> {
let font_paths = [
"/System/Library/Fonts/PingFang.ttc", "/System/Library/Fonts/STHeiti Light.ttc", "/System/Library/Fonts/STHeiti Medium.ttc",
"/System/Library/Fonts/Hiragino Sans GB.ttc", "/Library/Fonts/Arial Unicode.ttf", "/System/Library/Fonts/Apple LiGothic Medium.ttf", ];
for font_path in &font_paths {
if let Ok(font_data) = std::fs::read(font_path) {
return Ok(FontData::from_owned(font_data));
}
}
Err(FontError::NotFound("No Chinese font found on macOS".to_string()))
}
#[cfg(target_os = "linux")]
fn load_linux_chinese_font() -> Result<FontData, FontError> {
let font_paths = [
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf",
"/usr/share/fonts/truetype/arphic/uming.ttc",
"/usr/share/fonts/truetype/arphic/ukai.ttc",
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc",
"/usr/share/fonts/truetype/wqy/wqy-zenhei.ttc",
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc",
"/usr/share/fonts/truetype/liberation/LiberationSans-Regular.ttf",
"/usr/share/fonts/truetype/dejavu/DejaVuSans.ttf",
"/usr/share/fonts/google-droid/DroidSansFallbackFull.ttf",
"/usr/share/fonts/noto-cjk/NotoSansCJK-Regular.ttc",
];
for font_path in &font_paths {
if let Ok(font_data) = std::fs::read(font_path) {
return Ok(FontData::from_owned(font_data));
}
}
Err(FontError::NotFound("No Chinese font found on Linux".to_string()))
}
pub fn setup_custom_chinese_font(
ctx: &Context,
font_data: Vec<u8>,
font_name: Option<&str>
) {
let mut fonts = FontDefinitions::default();
let name = font_name.unwrap_or("chinese");
fonts.font_data.insert(
name.to_owned(),
FontData::from_owned(font_data).into(),
);
fonts.families.entry(FontFamily::Proportional).or_default()
.insert(0, name.to_owned());
fonts.families.entry(FontFamily::Monospace).or_default()
.insert(0, name.to_owned());
ctx.set_fonts(fonts);
}
pub fn get_chinese_font_paths() -> Vec<String> {
#[cfg(target_os = "windows")]
{
vec![
r"C:\Windows\Fonts\msyh.ttc".to_string(),
r"C:\Windows\Fonts\msyhbd.ttc".to_string(),
r"C:\Windows\Fonts\simsun.ttc".to_string(),
r"C:\Windows\Fonts\simhei.ttf".to_string(),
r"C:\Windows\Fonts\simkai.ttf".to_string(),
r"C:\Windows\Fonts\simfang.ttf".to_string(),
r"C:\Windows\Fonts\msjh.ttc".to_string(),
r"C:\Windows\Fonts\msjhbd.ttc".to_string(),
]
}
#[cfg(target_os = "macos")]
{
vec![
"/System/Library/Fonts/PingFang.ttc".to_string(),
"/System/Library/Fonts/STHeiti Light.ttc".to_string(),
"/System/Library/Fonts/STHeiti Medium.ttc".to_string(),
"/System/Library/Fonts/Hiragino Sans GB.ttc".to_string(),
"/Library/Fonts/Arial Unicode.ttf".to_string(),
]
}
#[cfg(target_os = "linux")]
{
vec![
"/usr/share/fonts/truetype/droid/DroidSansFallbackFull.ttf".to_string(),
"/usr/share/fonts/truetype/arphic/uming.ttc".to_string(),
"/usr/share/fonts/truetype/wqy/wqy-microhei.ttc".to_string(),
"/usr/share/fonts/opentype/noto/NotoSansCJK-Regular.ttc".to_string(),
]
}
#[cfg(not(any(target_os = "windows", target_os = "macos", target_os = "linux")))]
{
vec![]
}
}