windows: Let the OS decide which font to use as the UI font (#10877)
On my computer, I get `Yahei UI`, which makes sense since I'm using a Chinese operating system, and `Yahei UI` includes Chinese codepoints. On an English operating system, `Segoe UI` should be used instead. Edit: I also choose to use the UI font selected by the system as the fallback font, rather than hard-coding the `Arial` font. Release Notes: - N/A
This commit is contained in:
parent
9e88155a48
commit
06d2d9da5f
1 changed files with 68 additions and 38 deletions
|
@ -16,9 +16,11 @@ use windows::{
|
||||||
Direct2D::{Common::*, *},
|
Direct2D::{Common::*, *},
|
||||||
DirectWrite::*,
|
DirectWrite::*,
|
||||||
Dxgi::Common::*,
|
Dxgi::Common::*,
|
||||||
|
Gdi::LOGFONTW,
|
||||||
Imaging::{D2D::IWICImagingFactory2, *},
|
Imaging::{D2D::IWICImagingFactory2, *},
|
||||||
},
|
},
|
||||||
System::{Com::*, SystemServices::LOCALE_NAME_MAX_LENGTH},
|
System::{Com::*, SystemServices::LOCALE_NAME_MAX_LENGTH},
|
||||||
|
UI::WindowsAndMessaging::*,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -51,6 +53,7 @@ unsafe impl Send for DirectWriteComponent {}
|
||||||
|
|
||||||
struct DirectWriteState {
|
struct DirectWriteState {
|
||||||
components: DirectWriteComponent,
|
components: DirectWriteComponent,
|
||||||
|
system_ui_font_name: SharedString,
|
||||||
system_font_collection: IDWriteFontCollection1,
|
system_font_collection: IDWriteFontCollection1,
|
||||||
custom_font_collection: IDWriteFontCollection1,
|
custom_font_collection: IDWriteFontCollection1,
|
||||||
fonts: Vec<FontInfo>,
|
fonts: Vec<FontInfo>,
|
||||||
|
@ -106,9 +109,11 @@ impl DirectWriteTextSystem {
|
||||||
.factory
|
.factory
|
||||||
.CreateFontCollectionFromFontSet(&custom_font_set)?
|
.CreateFontCollectionFromFontSet(&custom_font_set)?
|
||||||
};
|
};
|
||||||
|
let system_ui_font_name = get_system_ui_font_name();
|
||||||
|
|
||||||
Ok(Self(RwLock::new(DirectWriteState {
|
Ok(Self(RwLock::new(DirectWriteState {
|
||||||
components,
|
components,
|
||||||
|
system_ui_font_name,
|
||||||
system_font_collection,
|
system_font_collection,
|
||||||
custom_font_collection,
|
custom_font_collection,
|
||||||
fonts: Vec::new(),
|
fonts: Vec::new(),
|
||||||
|
@ -309,53 +314,55 @@ impl DirectWriteState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn select_font(&mut self, target_font: &Font) -> FontId {
|
fn select_font(&mut self, target_font: &Font) -> FontId {
|
||||||
let family_name = if target_font.family == ".SystemUIFont" {
|
|
||||||
// https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
|
|
||||||
// Segoe UI is the Windows font intended for user interface text strings.
|
|
||||||
"Segoe UI"
|
|
||||||
} else {
|
|
||||||
target_font.family.as_ref()
|
|
||||||
};
|
|
||||||
unsafe {
|
unsafe {
|
||||||
// try to find target font in custom font collection first
|
if target_font.family == ".SystemUIFont" {
|
||||||
self.get_font_id_from_font_collection(
|
let family = self.system_ui_font_name.clone();
|
||||||
family_name,
|
self.find_font_id(
|
||||||
target_font.weight,
|
family.as_ref(),
|
||||||
target_font.style,
|
|
||||||
&target_font.features,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
.or_else(|| {
|
|
||||||
self.get_font_id_from_font_collection(
|
|
||||||
family_name,
|
|
||||||
target_font.weight,
|
target_font.weight,
|
||||||
target_font.style,
|
target_font.style,
|
||||||
&target_font.features,
|
&target_font.features,
|
||||||
true,
|
|
||||||
)
|
)
|
||||||
|
.unwrap()
|
||||||
|
} else {
|
||||||
|
self.find_font_id(
|
||||||
|
target_font.family.as_ref(),
|
||||||
|
target_font.weight,
|
||||||
|
target_font.style,
|
||||||
|
&target_font.features,
|
||||||
|
)
|
||||||
|
.unwrap_or_else(|| {
|
||||||
|
let family = self.system_ui_font_name.clone();
|
||||||
|
log::error!("{} not found, use {} instead.", target_font.family, family);
|
||||||
|
self.get_font_id_from_font_collection(
|
||||||
|
family.as_ref(),
|
||||||
|
target_font.weight,
|
||||||
|
target_font.style,
|
||||||
|
&target_font.features,
|
||||||
|
true,
|
||||||
|
)
|
||||||
|
.unwrap()
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe fn find_font_id(
|
||||||
|
&mut self,
|
||||||
|
family_name: &str,
|
||||||
|
weight: FontWeight,
|
||||||
|
style: FontStyle,
|
||||||
|
features: &FontFeatures,
|
||||||
|
) -> Option<FontId> {
|
||||||
|
// try to find target font in custom font collection first
|
||||||
|
self.get_font_id_from_font_collection(family_name, weight, style, features, false)
|
||||||
|
.or_else(|| {
|
||||||
|
self.get_font_id_from_font_collection(family_name, weight, style, features, true)
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
.or_else(|| {
|
||||||
self.update_system_font_collection();
|
self.update_system_font_collection();
|
||||||
self.get_font_id_from_font_collection(
|
self.get_font_id_from_font_collection(family_name, weight, style, features, true)
|
||||||
family_name,
|
|
||||||
target_font.weight,
|
|
||||||
target_font.style,
|
|
||||||
&target_font.features,
|
|
||||||
true,
|
|
||||||
)
|
|
||||||
})
|
})
|
||||||
.or_else(|| {
|
|
||||||
log::error!("{} not found, use Arial instead.", family_name);
|
|
||||||
self.get_font_id_from_font_collection(
|
|
||||||
"Arial",
|
|
||||||
target_font.weight,
|
|
||||||
target_font.style,
|
|
||||||
&target_font.features,
|
|
||||||
false,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.unwrap()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout {
|
fn layout_line(&mut self, text: &str, font_size: Pixels, font_runs: &[FontRun]) -> LineLayout {
|
||||||
|
@ -1271,6 +1278,29 @@ fn translate_color(color: &DWRITE_COLOR_F) -> D2D1_COLOR_F {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn get_system_ui_font_name() -> SharedString {
|
||||||
|
unsafe {
|
||||||
|
let mut info: LOGFONTW = std::mem::zeroed();
|
||||||
|
let font_family = if SystemParametersInfoW(
|
||||||
|
SPI_GETICONTITLELOGFONT,
|
||||||
|
std::mem::size_of::<LOGFONTW>() as u32,
|
||||||
|
Some(&mut info as *mut _ as _),
|
||||||
|
SYSTEM_PARAMETERS_INFO_UPDATE_FLAGS(0),
|
||||||
|
)
|
||||||
|
.log_err()
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
// https://learn.microsoft.com/en-us/windows/win32/uxguide/vis-fonts
|
||||||
|
// Segoe UI is the Windows font intended for user interface text strings.
|
||||||
|
"Segoe UI".into()
|
||||||
|
} else {
|
||||||
|
String::from_utf16_lossy(&info.lfFaceName).into()
|
||||||
|
};
|
||||||
|
log::info!("Use {} as UI font.", font_family);
|
||||||
|
font_family
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US");
|
const DEFAULT_LOCALE_NAME: PCWSTR = windows::core::w!("en-US");
|
||||||
const BRUSH_COLOR: D2D1_COLOR_F = D2D1_COLOR_F {
|
const BRUSH_COLOR: D2D1_COLOR_F = D2D1_COLOR_F {
|
||||||
r: 1.0,
|
r: 1.0,
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue